Merge branch 'fixes' into main/gingo-test
[ryzomcore.git] / ryzom / common / data_common / r2 / r2_version.lua
blob17e709df8b6d40263b631d968459a14a3b873343
2 r2.Version = {}
4 local version = r2.Version
7 function r2.Version.checkVersion(scenarioVersionList, currentVersionList)
8 local undef = {}
9 local older = {}
10 local newer = {}
11 local ok = true
13 local k,v = next(scenarioVersionList, nil)
14 while k do
15 if (v ~= currentVersionList[k]) then
16 ok = false
17 if currentVersionList[k] == nil then
18 table.insert(undef, k)
19 elseif v < currentVersionList[k] then
20 table.insert(older, k)
21 else
22 table.insert(newer, k)
23 end
24 end
25 k,v = next(scenarioVersionList, k)
26 end
27 return ok, undef, older, newer
29 end
31 function r2.Version.getUndefComponent(scenarioVersionList, currentVersionList)
32 local undef = {}
33 local k,v = next(scenarioVersionList, nil)
34 while k do
35 if (v ~= currentVersionList[k] and currentVersionList[k] == nil ) then
36 table.insert(undef, k)
37 end
38 k,v = next(scenarioVersionList, k)
39 end
40 return true
42 end
44 local levelToString =
46 [0] = "20",
47 [1] = "50",
48 [2] = "100",
49 [3] = "150",
50 [4] = "200",
51 [5] = "250"
54 function r2.Version.save(filename)
56 local scenario = r2.Scenario
58 if scenario then
59 local scenarioList = r2.Version.getCurrentVersionList()
60 local update = false
62 local k,v = next(scenarioList, nil)
63 while k do
64 if (r2.Scenario.Versions[k] ~= v) then update = true end
65 k,v = next(scenarioList, k)
66 end
68 k,v = next(r2.Scenario.Versions, nil)
69 while k do
70 if (scenarioList[k] ~= v) then update = true end
71 k,v = next(r2.Scenario.Versions, k)
72 end
74 if update then
75 r2.requestSetGhostNode(scenario.InstanceId, "Versions", scenarioList)
76 end
77 local accessList = {}
80 local ok, level, err = r2.RingAccess.verifyScenario()
81 if not r2.RingAccess.LoadAnimation and not r2.getIsAnimationSession() then
82 r2.updateScenarioAck(ok, level, err.What)
83 end
84 accessList = r2.RingAccess.getAccessListAsString(level)
87 local values = {}
91 local date = os.date()
93 local firstLocationName = ""
94 local shortDescription = ""
95 local title = ""
96 local name = ""
97 local userName = r2:getUserEntityName()
98 local modifierMD5 = r2.getCharIdMd5()
99 local creatorName = ""
100 local rules = ""
101 local level = ""
102 local language = ""
103 local type = ""
104 local creatorMD5 =""
105 local createUserName = userName
106 local createDate = date
107 local otherCharAccess = "Full"
108 local nevraxScenario = "0"
109 local trialAllowed = "0"
110 local scenarioTag = ""
113 if r2.Scenario and r2.Scenario.Locations
114 and table.getn(r2.Scenario.Locations) > 0 and r2.Scenario.Locations[0].IslandName then
115 firstLocationName = r2.Scenario.Locations[0].IslandName
118 if r2.Scenario and r2.Scenario.Description then
119 --shortDescription =string.gsub(r2.Scenario.Description.ShortDescription, "\n", "\\n")
120 shortDescription = r2.Scenario.Description.ShortDescription
121 level = string.gsub(r2.Scenario.Description.LevelId, "\n", "\\n")
122 level = levelToString[tonumber(level)]
123 rules = string.gsub(r2.Scenario.AccessRules, "\n", "\\n")
124 if rules=="liberal" then
125 rules=i18n.get("uiR2EDliberal"):toUtf8()
126 elseif rules == "strict" then
127 rules=i18n.get("uiR2EDstrict"):toUtf8()
129 title = string.gsub(r2.Scenario.Description.Title, "\n", "\\n")
130 language = r2.Scenario.Language
131 type = r2.Scenario.Type
132 name = r2.Scenario.Name
133 if r2.Scenario.Ghost_Name then
134 name = r2.Scenario.Ghost_Name
136 if r2.Scenario.Description.Creator then
137 createUserName = r2.Scenario.Description.Creator
139 if r2.Scenario.Description.CreatorMD5 then
140 creatorMD5 = r2.Scenario.Description.CreatorMD5
142 if r2.Scenario.Description.CreationDate then
143 createDate = r2.Scenario.Description.CreationDate
144 end
145 if table.getn(r2.Scenario.Locations) > 0 then
146 initialIslandLocation = r2.Scenario.Locations[0].IslandName
147 initialEntryPoint = r2.Scenario.Locations[0].EntryPoint
148 initialSeason = r2.Scenario.Locations[0].Season
151 if r2.Scenario.Description.OtherCharAccess then
152 otherCharAccess = r2.Scenario.Description.OtherCharAccess
153 if otherCharAccess == "RoSOnly" then
154 if config.R2EDExtendedDebug ~= 1 then
155 if filename == "data/r2_buffer.dat" then
156 return false
157 else
158 r2.onSystemMessageReceived("BC_ML", "", "uiR2EDErrorRefuseToSaveRoS")
159 r2.requestNewAction(i18n.get("uiR2EDUpdatingScenarioToDefaultAccess"))
160 r2.requestSetNode(r2.Scenario.Description.InstanceId, "OtherCharAccess", "Full")
161 r2.requestEndAction()
162 return false
164 else
165 r2.onSystemMessageReceived("BC_ML", "", "Updating the system of Trial limitation")
166 r2.requestNewAction(i18n.get("uiR2EDUpdatingScenarioAccess"))
167 r2.requestSetNode(r2.Scenario.Description.InstanceId, "OtherCharAccess", "Full")
168 r2.requestSetNode(r2.Scenario.Description.InstanceId, "NevraxScenario", "1")
169 r2.requestSetNode(r2.Scenario.Description.InstanceId, "TrialAllowed", "1")
170 r2.requestSetNode(r2.Scenario.Description.InstanceId, "ScenarioTag", "")
171 r2.requestEndAction()
172 return false
179 if r2.Scenario.Description.NevraxScenario == tostring(1) then
180 nevraxScenario = r2.Scenario.Description.NevraxScenario
181 trialAllowed = r2.Scenario.Description.TrialAllowed
182 scenarioTag = r2.Scenario.Description.ScenarioTag
183 userName = "Ring(Nevrax)"
184 createUserName = userName
186 if config.R2EDExtendedDebug ~= 1 then
188 if filename == "data/r2_buffer.dat" then
189 return false
190 else
191 r2.onSystemMessageReceived("BC_ML", "", "uiR2EDErrorRefuseToSaveRoS")
192 r2.requestNewAction(i18n.get("uiR2EDUpdatingScenarioAccess"))
193 r2.requestSetNode(r2.Scenario.Description.InstanceId, "NevraxScenario", "0")
194 r2.requestSetNode(r2.Scenario.Description.InstanceId, "TrialAllowed", "0")
195 r2.requestSetNode(r2.Scenario.Description.InstanceId, "ScenarioTag", "")
196 r2.requestEndAction()
198 return false
207 table.insert(values, {Title = title})
208 table.insert(values, {Name = name})
209 table.insert(values, {ShortDescription = shortDescription})
210 table.insert(values, {FirstLocation = firstLocationName})
211 table.insert(values, {RingPointLevel = accessList})
212 table.insert(values, {CreateBy = createUserName})
213 table.insert(values, {CreatorMD5 = creatorMD5})
214 table.insert(values, {CreationDate = createDate})
215 table.insert(values, {ModifiedBy = userName})
216 table.insert(values, {ModifierMD5 = modifierMD5})
217 table.insert(values, {OtherCharAccess = otherCharAccess})
219 table.insert(values, {ModificationDate = date})
220 table.insert(values, {Rules = rules})
221 table.insert(values, {Level = level})
222 table.insert(values, {Type = type})
223 table.insert(values, {Language = language})
224 table.insert(values, {InitialIsland = initialIslandLocation})
225 table.insert(values, {InitialEntryPoint = initialEntryPoint})
226 table.insert(values, {InitialSeason = initialSeason})
227 if nevraxScenario == tostring(1) then
228 table.insert(values, {NevraxScenario = nevraxScenario})
229 table.insert(values, {TrialAllowed = trialAllowed})
230 table.insert(values, {ScenarioTag = scenarioTag})
234 r2.save(filename, values)
236 return true
240 local function updateVersionImpl(nodeList, scenarioVersionList, currentVersionFullList)
241 assert(nodeList)
242 assert(scenarioVersionList)
243 assert(currentVersionFullList)
245 local k,v = next(nodeList, nil)
246 while k do
249 -- go up in the class hierarchy, calling each redefinition of 'onUpdate' function
250 -- when a version change is detected
251 local currClassName = v.Class
253 -- look at a update function for this component or one of it's ancester
254 while currClassName ~= "" and currClassName ~= nil do
255 local currClass = r2.Classes[currClassName]
256 if not currClass then
257 debugInfo(colorTag(255, 0, 0) .. "Error can not update your scenario: the component"..currClassName.." seems to be obsolete")
258 return false
260 local scenarioVersionNode = defaulting(scenarioVersionList[currClassName], 0)
261 local currentVersionNode = defaulting(currentVersionFullList[currClassName], 0)
262 if currentVersionNode ~= scenarioVersionNode then
264 if scenarioVersionNode == nil then
265 debugInfo(colorTag(0, 255 ,255) .. "The component (".. v.Class .. ") does not exist anymore")
266 return false
267 elseif currentVersionNode == nil then
268 debugInfo(colorTag(0, 255 ,255) .. "The component (".. v.Class .. ") does not exist anymore")
269 return false
270 else
271 debugInfo(colorTag(0, 255 ,255) .. "Updating the component " .. v.InstanceId .. "(".. v.Class .. "/"..currClassName..") from ".. scenarioVersionNode .. " to " .. currentVersionNode ..".")
273 local updateFunc = currClass.updateVersion
274 if not updateFunc then
275 debugInfo( "Your scenario can not be updated. Because the component " .. v.Class .. " can not be updated (no update Function?).\n")
276 return false
278 local ok1, ok2 = pcall(updateFunc, v, scenarioVersionNode, currentVersionNode)
279 if not ok1 or not ok2 then
280 debugInfo( "Your scenario can not be updated. Because the component " .. v.Class .. " can not be updated.\n")
281 if not ok1 then
282 debugInfo(ok2)
284 return false
289 currClassName = currClass.BaseClass
292 k,v = next(nodeList, k)
294 return true
298 function r2.Version.updateVersion()
299 if r2.Translator == nil then
300 debugInfo("Syntax error")
301 return false
303 local scenarioInstance = r2.Scenario
305 if not scenarioInstance then return true end
307 local currentVersionFullList = r2.Version.getCurrentVersionFullList()
308 local scenarioVersionList = r2.Version.getScenarioVersionList()
310 local versionOk, undef, older, newer = r2.Version.checkVersion(scenarioVersionList, currentVersionFullList)
312 local modified = false
313 if not versionOk then
315 debugInfo(colorTag(0,255,25).."Begin Update")
317 local scenarioVersionName = scenarioInstance.VersionName
318 local currentVersionName = r2.Classes["Scenario"].VersionName
320 if scenarioVersionName == nil then scenarioVersionName = "0.0.0" end
321 if currentVersionName == nil then currentVersionName = "0.0.0" end
323 local str = "Updating the scenario from '"..scenarioVersionName.."' to '".. currentVersionName .."'.\nThe obsolete scenario will be saved in 'old_scenario.r2'"
324 printMsg(str)
325 local nodeList = r2.Version.getScenarioNodes(scenarioInstance)
326 assert(nodeList)
329 local k,v = next(undef, nil)
330 while k do
331 debugInfo(colorTag(0, 255 ,255) .. "The component ".. v .. " used in this scenario does not exist.")
332 k,v = next(undef, k)
337 local k,v = next(older, nil)
338 while k do
339 debugInfo(colorTag(0, 255 ,255) .. "The component ".. v .. " is too old (we will try to update it)")
340 k,v = next(older, k)
345 local k,v = next(newer, nil)
346 while k do
347 debugInfo(colorTag(0, 255 ,255) .. "The component ".. v .. " is too new (maybe wrong version?)")
348 k,v = next(newer, k)
351 if table.getn(undef) > 0 then
352 debugInfo(colorTag(255, 0, 0) .. "Error can not update your scenario: the scenario containse components that are not defined")
353 return true
355 local oldState = scenarioInstance.Ghost
356 scenarioInstance.Ghost = false
357 r2.save("old_scenario.r2")
358 scenarioInstance = r2.Scenario
360 scenarioInstance.Ghost = true
362 local syntaxOk, ok = pcall(updateVersionImpl, nodeList, scenarioVersionList, currentVersionFullList)
363 if not syntaxOk then
364 r2.print(ok)
365 ok = false
367 if ok then
368 -- ok
369 debugInfo(colorTag(0,255,25).."Update succced")
370 local currentVersionList = r2.Version.getCurrentVersionList()
371 r2.requestSetNode(scenarioInstance.InstanceId, "VersionName", currentVersionName)
372 r2.requestSetNode(scenarioInstance.InstanceId, "Versions", currentVersionList)
373 scenarioInstance.Ghost = oldState
374 r2.requestUploadCurrentScenario()
375 r2.clearActionHistoric() -- undo invalidated after a version update !!
376 modified = true
377 else
378 debugInfo(colorTag(255, 0, 0) .. "Errors occurs while updateing your scenario")
381 scenarioInstance.Ghost = oldState
382 debugInfo(colorTag(0,255,25).."End Update")
384 end
385 return not modified;
391 -- return Scenario Nodes - leaf first
392 function r2.Version.getScenarioNodes(node, nodeListParam)
393 assert(node)
394 if nodeListParam then nodeList = nodeListParam else nodeList = {} end
396 if not r2.isTable(node) then return nodeList end
397 local k,v = next(node, nil)
398 while k do
399 r2.Version.getScenarioNodes(v, nodeList)
400 k,v = next(node, k)
402 if node.InstanceId then
403 table.insert(nodeList, node)
404 if not node.Class then assert(nil) end
406 return nodeList
410 -- get the Current Version of sceanrio
411 function r2.Version.getCurrentVersionList()
412 local scenarionInstance = r2.Scenario
413 local versionList = {}
414 r2.Version._getCurrentVersionListImpl(scenarionInstance, versionList)
415 return versionList;
418 function r2.Version.getCurrentVersionFullList()
419 local versionList = {}
420 local classes = r2.Classes
421 local k, v = next(classes, nil)
422 while k do
423 if v.Version then
424 versionList[k] = v.Version
425 else
426 versionList[k] = 0
428 k, v = next(classes, k)
430 return versionList
433 function r2.Version._getCurrentVersionListImpl(node, versionList)
434 if ( type (node) == "string" or type(node) == "number") then return end
435 local k,v = next(node, nil)
436 if node.Class and not versionList[node.Class] then
437 if r2.Classes[node.Class] and r2.Classes[node.Class].Version then
438 versionList[node.Class] = r2.Classes[node.Class].Version
439 else
440 versionList[node.Class] = 0
443 while k do
444 r2.Version._getCurrentVersionListImpl(v, versionList);
445 k,v = next(node, k)
450 function r2.Version.getScenarioVersionList(scenarioNode)
451 local scenario = scenarioNode
452 if not scenario then scenario = r2.Scenario end
453 assert(scenario)
454 local versions = scenario.Versions
455 local versionList = {}
456 if versions == nil then
457 return r2.Version._getScenarioVersionListImpl(scenario, versionList)
458 else
459 local k,v = next(versions, nil)
460 while k do
461 versionList[k] = v
462 k,v = next(versions, k)
465 return versionList
469 function r2.Version._getScenarioVersionListImpl(node, versionList)
470 if ( type (node) == "string" or type(node) == "number") then return end
471 local k,v = next(node, nil)
472 if node.Class and not versionList[node.Class] then
473 versionList[node.Class] = 0
474 end
475 while k do
476 r2.Version._getScenarioVersionListImpl(v, versionList);
477 k,v = next(node, k)
479 return versionList
482 -- Version 0.0.0 -> prior to 7 dec 2005
484 -- version 0.0.1 prior to 7 dec 2005
485 -- Act.Version = 1
486 -- Act.ManualWeather
487 -- Act.WeatherValue
489 -- version 0.0.2 19 dec 2005
490 -- Act.Version = 2
491 -- Act.Behavior (Because Act changes type from BaseType to LogicAction
493 -- version 0.0.3 1 janv 2006
494 -- ActivityStep.Version=1
495 -- "Inactive" -> "Stand Still"