LUA game Scripting hot update mechanism?
Design essentials?
Ability to update program logic code during server run to fix bugs and modify game data. Hot update of Game framework code is not considered. For example:
A business processing function logic has a bug, during the server operation found that in the non-stop situation in time to update the code repair.
Skill Value table planning to fill in the wrong hand, causing the player to fight abnormally, in the case of non-stop in time to update the memory of the table of values.
To protect non-code data when updating code, try not to reload the disk data. For example:
Login user list is saved in memory, the user login module bug needs to be with the new code, after this code update, the user list is still valid, online users are not affected.
Common scenarios?
The module mechanism of LUA?
Require will prevent you from reloading the same module. When you need to update the system, uninstall the module you wrote. The method is: Set the name of the corresponding module in the package.loaded to nil (this will ensure the next require reload) and the global table in the corresponding module table nil.
At the same time, record the data under a dedicated global table and use local to refer to it. When initializing this data, you should first check if they are initialized. This ensures that the data is not reset by the update process.
The local Shortfunc = Modulea.longfunc in Module b is not updated after updating Modulea, and must be preceded by the local Shortfunc = nil. More Trouble
This method uses the module, which has deprecated the module mechanism in Lua5.2, and Lua advises users to implement a simpler method themselves.
LoadFile mechanism?
Using LoadFile to simulate the module mechanism, you can flexibly add more hot update requirements to your business needs.
LoadFile use of the foundation?
-------------------------
--Code Dynamic loading module v0.1
--
--LoadFile based on the LUA version 5.2
------------------------
----Module Management table, similar to package.loaded
Local Modules = {}
--load new code into Newmodule via LoadFile
function Load (pathname, modulename)
Local newmodule = {}
--_env is set to an empty table, the access space for loading the file is limited to the inside of the module
Local func, err = loadfile (pathname, "BT", Newmodule)
If not Func then
Print ("ERROR:"). Err
Else
Func ()
Modules[modulename] = Newmodule
End
End
Test Module Game.lua
---------------------------------
----Simulate a game timed activity gameplay logic
----
----Event winners recorded, after the event awards
----
----This code has a logic error
-----------------------------------
--award-winning user list in the event
Rewardeduser = {}
--Activity Start end time setting
Local StartTime = {hour = ten, min = 0, sec = 0}
Local Endtime = {hour = a, Min = 0, sec = 0}
--Record the winning users in the event
function Recordreward (Charid)
Rewardeduser[char] = true--error, char = nil
--The correct code after the update
--Rewardeduser[charid] = True
End
Test Drive Module Main.lua
Require ("Modules.lua")
GAME = Load ("Game.lua")
GAME. Recordreward (1001)--Error
--Reload after update error
GAME = Load ("Game.lua")
GAME. Recordreward (1001)--rewardeduser = {[1001] = True}
Local Data =game.rewardeduser
Local func = GAME. Recordreward
--local causes the current Game.recordreward, game.rewardeduser references to be treated as upvalue bindings in closure
GAME = Load ("Game.lua")
--Game.rewardeduser = {} Replaced by the reload code, {[1001] = true} data is lost, the user cannot receive the prize, and the business logic is abnormal.
GAME. Recordreward (1002)--Rewardeduser = {[1002] = true}
--data refers to an old reference saved in Upvalue, with a value of {[1001] = True}, which is out of sync with the current Game.recordreward, and a logical exception occurs
Func ()
--still error, because it refers to the old reference saved in Upvalue, not the updated Game.recordreward
LoadFile the use of advanced?
Through the above code experiment, we found the following problems
The Game.lua above cannot access _g space
Content that needs to be persisted is not saved
Upvalue causes thermal update failure
We can also see that the code loaded by LoadFile is referenced in table Form, which opens the way for us to solve the above problems.
-------------------------
--Code Dynamic loading module v0.1
--
--LoadFile based on the LUA version 5.2
------------------------
--module management table, similar to package.loaded
Local Modules = {}
--Parameters:
--String Pathname load module file name, with path
--String Name Module name, general and pathname always can
--Boolean reload whether to force update overloads
--Return:
--Table module module, if load fails to return nil
--String Err if module is nil, return error message
function Load (pathname, modulename, Reload)
ModuleName = ModuleName or pathname
Local oldmodule = Modules[modulename]
If not Oldmodule then--load module for the first time, new load
Local newmodule = {}
--Allows the module environment access through the metatable mechanism _g
Setmetatable (newmodule, {__index = _g})
Local func, err = loadfile (pathname, "BT", Newmodule)
If not Func then
Print ("ERROR:"). Err
return nil, err
End
Func ()
Modules[modulename] = Newmodule
Return Newmodule
Else--repeat load, no need to return cache directly when updating
If not reload then
Return Oldmodule
Else
--cache table data in the pre-update module first
Local Oldcache = {}
For K, V in pairs (oldmodule) do
If Type (v) = = "Table" Then
Oldcache[k] = V
End
OLDMODULE[K] = Nil
End
--The original module is used directly as a new environment
Local Newmodule = Oldmodule
--The original module is fully updated
Local func, err = loadfile (pathname, "BT", Newmodule)
If not Func then
Print ("ERROR:"). Err
return nil, err
End
Func ()
--Restore table data, preserving both existing data and existing references to other modules
--because this reference mechanism can only be used for table, the function upvalue is still not updated
For K, V in pairs (oldcache) do
--replace metatable with new to implement function segment update
Local MT = getmetatable (Newmodule[k])
If Mt then setmetatable (V, MT) end
--For existing table, the data segment remains unchanged
Newmodule[k] = V
End
Return Newmodule
End
End
End
Summary:
This method implements data retention for non-local table within the module and external hold of its references. The business module does not require special handling of this
The local table data in the module is not maintained and is recommended for storing fixed data such as numeric tables, activity times, etc.
The other modules are via local func = module. The form of Func refers to a module function that cannot be updated and is not recommended for this form. or add local func = nil before each reference, forcing the script to update the reference each time it executes.
The initialization and unload methods of the module can be expanded on the basis of this method to realize the special logic requirement.