r2.Version = {} local version = r2.Version function r2.Version.checkVersion(scenarioVersionList, currentVersionList) local undef = {} local older = {} local newer = {} local ok = true local k,v = next(scenarioVersionList, nil) while k do if (v ~= currentVersionList[k]) then ok = false if currentVersionList[k] == nil then table.insert(undef, k) elseif v < currentVersionList[k] then table.insert(older, k) else table.insert(newer, k) end end k,v = next(scenarioVersionList, k) end return ok, undef, older, newer end function r2.Version.getUndefComponent(scenarioVersionList, currentVersionList) local undef = {} local k,v = next(scenarioVersionList, nil) while k do if (v ~= currentVersionList[k] and currentVersionList[k] == nil ) then table.insert(undef, k) end k,v = next(scenarioVersionList, k) end return true end local levelToString = { [0] = "20", [1] = "50", [2] = "100", [3] = "150", [4] = "200", [5] = "250" } function r2.Version.save(filename) local scenario = r2.Scenario if scenario then local scenarioList = r2.Version.getCurrentVersionList() local update = false local k,v = next(scenarioList, nil) while k do if (r2.Scenario.Versions[k] ~= v) then update = true end k,v = next(scenarioList, k) end k,v = next(r2.Scenario.Versions, nil) while k do if (scenarioList[k] ~= v) then update = true end k,v = next(r2.Scenario.Versions, k) end if update then r2.requestSetGhostNode(scenario.InstanceId, "Versions", scenarioList) end local accessList = {} local ok, level, err = r2.RingAccess.verifyScenario() if not r2.RingAccess.LoadAnimation and not r2.getIsAnimationSession() then r2.updateScenarioAck(ok, level, err.What) end accessList = r2.RingAccess.getAccessListAsString(level) local values = {} local date = os.date() local firstLocationName = "" local shortDescription = "" local title = "" local name = "" local userName = r2:getUserEntityName() local modifierMD5 = r2.getCharIdMd5() local creatorName = "" local rules = "" local level = "" local language = "" local type = "" local creatorMD5 ="" local createUserName = userName local createDate = date local otherCharAccess = "Full" local nevraxScenario = "0" local trialAllowed = "0" local scenarioTag = "" if r2.Scenario and r2.Scenario.Locations and table.getn(r2.Scenario.Locations) > 0 and r2.Scenario.Locations[0].IslandName then firstLocationName = r2.Scenario.Locations[0].IslandName end if r2.Scenario and r2.Scenario.Description then --shortDescription =string.gsub(r2.Scenario.Description.ShortDescription, "\n", "\\n") shortDescription = r2.Scenario.Description.ShortDescription level = string.gsub(r2.Scenario.Description.LevelId, "\n", "\\n") level = levelToString[tonumber(level)] rules = string.gsub(r2.Scenario.AccessRules, "\n", "\\n") if rules=="liberal" then rules=i18n.get("uiR2EDliberal"):toUtf8() elseif rules == "strict" then rules=i18n.get("uiR2EDstrict"):toUtf8() end title = string.gsub(r2.Scenario.Description.Title, "\n", "\\n") language = r2.Scenario.Language type = r2.Scenario.Type name = r2.Scenario.Name if r2.Scenario.Ghost_Name then name = r2.Scenario.Ghost_Name end if r2.Scenario.Description.Creator then createUserName = r2.Scenario.Description.Creator end if r2.Scenario.Description.CreatorMD5 then creatorMD5 = r2.Scenario.Description.CreatorMD5 end if r2.Scenario.Description.CreationDate then createDate = r2.Scenario.Description.CreationDate end if table.getn(r2.Scenario.Locations) > 0 then initialIslandLocation = r2.Scenario.Locations[0].IslandName initialEntryPoint = r2.Scenario.Locations[0].EntryPoint initialSeason = r2.Scenario.Locations[0].Season end if r2.Scenario.Description.OtherCharAccess then otherCharAccess = r2.Scenario.Description.OtherCharAccess if otherCharAccess == "RoSOnly" then if config.R2EDExtendedDebug ~= 1 then if filename == "data/r2_buffer.dat" then return false else r2.onSystemMessageReceived("BC_ML", "", "uiR2EDErrorRefuseToSaveRoS") r2.requestNewAction(i18n.get("uiR2EDUpdatingScenarioToDefaultAccess")) r2.requestSetNode(r2.Scenario.Description.InstanceId, "OtherCharAccess", "Full") r2.requestEndAction() return false end else r2.onSystemMessageReceived("BC_ML", "", "Updating the system of Trial limitation") r2.requestNewAction(i18n.get("uiR2EDUpdatingScenarioAccess")) r2.requestSetNode(r2.Scenario.Description.InstanceId, "OtherCharAccess", "Full") r2.requestSetNode(r2.Scenario.Description.InstanceId, "NevraxScenario", "1") r2.requestSetNode(r2.Scenario.Description.InstanceId, "TrialAllowed", "1") r2.requestSetNode(r2.Scenario.Description.InstanceId, "ScenarioTag", "") r2.requestEndAction() return false end end end if r2.Scenario.Description.NevraxScenario == tostring(1) then nevraxScenario = r2.Scenario.Description.NevraxScenario trialAllowed = r2.Scenario.Description.TrialAllowed scenarioTag = r2.Scenario.Description.ScenarioTag userName = "Ring(Nevrax)" createUserName = userName if config.R2EDExtendedDebug ~= 1 then if filename == "data/r2_buffer.dat" then return false else r2.onSystemMessageReceived("BC_ML", "", "uiR2EDErrorRefuseToSaveRoS") r2.requestNewAction(i18n.get("uiR2EDUpdatingScenarioAccess")) r2.requestSetNode(r2.Scenario.Description.InstanceId, "NevraxScenario", "0") r2.requestSetNode(r2.Scenario.Description.InstanceId, "TrialAllowed", "0") r2.requestSetNode(r2.Scenario.Description.InstanceId, "ScenarioTag", "") r2.requestEndAction() return false end end end end table.insert(values, {Title = title}) table.insert(values, {Name = name}) table.insert(values, {ShortDescription = shortDescription}) table.insert(values, {FirstLocation = firstLocationName}) table.insert(values, {RingPointLevel = accessList}) table.insert(values, {CreateBy = createUserName}) table.insert(values, {CreatorMD5 = creatorMD5}) table.insert(values, {CreationDate = createDate}) table.insert(values, {ModifiedBy = userName}) table.insert(values, {ModifierMD5 = modifierMD5}) table.insert(values, {OtherCharAccess = otherCharAccess}) table.insert(values, {ModificationDate = date}) table.insert(values, {Rules = rules}) table.insert(values, {Level = level}) table.insert(values, {Type = type}) table.insert(values, {Language = language}) table.insert(values, {InitialIsland = initialIslandLocation}) table.insert(values, {InitialEntryPoint = initialEntryPoint}) table.insert(values, {InitialSeason = initialSeason}) if nevraxScenario == tostring(1) then table.insert(values, {NevraxScenario = nevraxScenario}) table.insert(values, {TrialAllowed = trialAllowed}) table.insert(values, {ScenarioTag = scenarioTag}) end r2.save(filename, values) end return true end local function updateVersionImpl(nodeList, scenarioVersionList, currentVersionFullList) assert(nodeList) assert(scenarioVersionList) assert(currentVersionFullList) local k,v = next(nodeList, nil) while k do -- go up in the class hierarchy, calling each redefinition of 'onUpdate' function -- when a version change is detected local currClassName = v.Class -- look at a update function for this component or one of it's ancester while currClassName ~= "" and currClassName ~= nil do local currClass = r2.Classes[currClassName] if not currClass then debugInfo(colorTag(255, 0, 0) .. "Error can not update your scenario: the component"..currClassName.." seems to be obsolete") return false end local scenarioVersionNode = defaulting(scenarioVersionList[currClassName], 0) local currentVersionNode = defaulting(currentVersionFullList[currClassName], 0) if currentVersionNode ~= scenarioVersionNode then -- if scenarioVersionNode == nil then debugInfo(colorTag(0, 255 ,255) .. "The component (".. v.Class .. ") does not exist anymore") return false elseif currentVersionNode == nil then debugInfo(colorTag(0, 255 ,255) .. "The component (".. v.Class .. ") does not exist anymore") return false else debugInfo(colorTag(0, 255 ,255) .. "Updating the component " .. v.InstanceId .. "(".. v.Class .. "/"..currClassName..") from ".. scenarioVersionNode .. " to " .. currentVersionNode ..".") local updateFunc = currClass.updateVersion if not updateFunc then debugInfo( "Your scenario can not be updated. Because the component " .. v.Class .. " can not be updated (no update Function?).\n") return false end local ok1, ok2 = pcall(updateFunc, v, scenarioVersionNode, currentVersionNode) if not ok1 or not ok2 then debugInfo( "Your scenario can not be updated. Because the component " .. v.Class .. " can not be updated.\n") if not ok1 then debugInfo(ok2) end return false end end end currClassName = currClass.BaseClass end k,v = next(nodeList, k) end return true end function r2.Version.updateVersion() if r2.Translator == nil then debugInfo("Syntax error") return false end local scenarioInstance = r2.Scenario if not scenarioInstance then return true end local currentVersionFullList = r2.Version.getCurrentVersionFullList() local scenarioVersionList = r2.Version.getScenarioVersionList() local versionOk, undef, older, newer = r2.Version.checkVersion(scenarioVersionList, currentVersionFullList) local modified = false if not versionOk then debugInfo(colorTag(0,255,25).."Begin Update") local scenarioVersionName = scenarioInstance.VersionName local currentVersionName = r2.Classes["Scenario"].VersionName if scenarioVersionName == nil then scenarioVersionName = "0.0.0" end if currentVersionName == nil then currentVersionName = "0.0.0" end local str = "Updating the scenario from '"..scenarioVersionName.."' to '".. currentVersionName .."'.\nThe obsolete scenario will be saved in 'old_scenario.r2'" printMsg(str) local nodeList = r2.Version.getScenarioNodes(scenarioInstance) assert(nodeList) do local k,v = next(undef, nil) while k do debugInfo(colorTag(0, 255 ,255) .. "The component ".. v .. " used in this scenario does not exist.") k,v = next(undef, k) end end do local k,v = next(older, nil) while k do debugInfo(colorTag(0, 255 ,255) .. "The component ".. v .. " is too old (we will try to update it)") k,v = next(older, k) end end do local k,v = next(newer, nil) while k do debugInfo(colorTag(0, 255 ,255) .. "The component ".. v .. " is too new (maybe wrong version?)") k,v = next(newer, k) end end if table.getn(undef) > 0 then debugInfo(colorTag(255, 0, 0) .. "Error can not update your scenario: the scenario containse components that are not defined") return true end local oldState = scenarioInstance.Ghost scenarioInstance.Ghost = false r2.save("old_scenario.r2") scenarioInstance = r2.Scenario scenarioInstance.Ghost = true local syntaxOk, ok = pcall(updateVersionImpl, nodeList, scenarioVersionList, currentVersionFullList) if not syntaxOk then r2.print(ok) ok = false end if ok then -- ok debugInfo(colorTag(0,255,25).."Update succced") local currentVersionList = r2.Version.getCurrentVersionList() r2.requestSetNode(scenarioInstance.InstanceId, "VersionName", currentVersionName) r2.requestSetNode(scenarioInstance.InstanceId, "Versions", currentVersionList) scenarioInstance.Ghost = oldState r2.requestUploadCurrentScenario() r2.clearActionHistoric() -- undo invalidated after a version update !! modified = true else debugInfo(colorTag(255, 0, 0) .. "Errors occurs while updateing your scenario") end scenarioInstance.Ghost = oldState debugInfo(colorTag(0,255,25).."End Update") end return not modified; end -- return Scenario Nodes - leaf first function r2.Version.getScenarioNodes(node, nodeListParam) assert(node) if nodeListParam then nodeList = nodeListParam else nodeList = {} end if not r2.isTable(node) then return nodeList end local k,v = next(node, nil) while k do r2.Version.getScenarioNodes(v, nodeList) k,v = next(node, k) end if node.InstanceId then table.insert(nodeList, node) if not node.Class then assert(nil) end end return nodeList end -- get the Current Version of sceanrio function r2.Version.getCurrentVersionList() local scenarionInstance = r2.Scenario local versionList = {} r2.Version._getCurrentVersionListImpl(scenarionInstance, versionList) return versionList; end function r2.Version.getCurrentVersionFullList() local versionList = {} local classes = r2.Classes local k, v = next(classes, nil) while k do if v.Version then versionList[k] = v.Version else versionList[k] = 0 end k, v = next(classes, k) end return versionList end function r2.Version._getCurrentVersionListImpl(node, versionList) if ( type (node) == "string" or type(node) == "number") then return end local k,v = next(node, nil) if node.Class and not versionList[node.Class] then if r2.Classes[node.Class] and r2.Classes[node.Class].Version then versionList[node.Class] = r2.Classes[node.Class].Version else versionList[node.Class] = 0 end end while k do r2.Version._getCurrentVersionListImpl(v, versionList); k,v = next(node, k) end end function r2.Version.getScenarioVersionList(scenarioNode) local scenario = scenarioNode if not scenario then scenario = r2.Scenario end assert(scenario) local versions = scenario.Versions local versionList = {} if versions == nil then return r2.Version._getScenarioVersionListImpl(scenario, versionList) else local k,v = next(versions, nil) while k do versionList[k] = v k,v = next(versions, k) end end return versionList end function r2.Version._getScenarioVersionListImpl(node, versionList) if ( type (node) == "string" or type(node) == "number") then return end local k,v = next(node, nil) if node.Class and not versionList[node.Class] then versionList[node.Class] = 0 end while k do r2.Version._getScenarioVersionListImpl(v, versionList); k,v = next(node, k) end return versionList end -- Version 0.0.0 -> prior to 7 dec 2005 -- version 0.0.1 prior to 7 dec 2005 -- Act.Version = 1 -- Act.ManualWeather -- Act.WeatherValue -- version 0.0.2 19 dec 2005 -- Act.Version = 2 -- Act.Behavior (Because Act changes type from BaseType to LogicAction -- -- version 0.0.3 1 janv 2006 -- ActivityStep.Version=1 -- "Inactive" -> "Stand Still"