metatables & Savegames

» Siedler Map Source Forum » Siedler DEdK Script Forum » metatables & Savegames

Seiten: 1

mcb
#1
03.10.2014 12:30
Beiträge: 1335

metatables & Savegames

Ich hab mal einen kleinen Comfort geschrieben, um metatables beim Laden wiederherzustellen, ohne den Speicher mit nicht mehr verwendeten metatables zuzumüllen.

--- mcb
-- metatable-savegame-fix     v 1.2
-- 
-- metatable.set(table, metatable) anstatt setmetatable verwenden.
-- Automatische Speicherung und Wiederherstellung nach dem Laden.
-- metatable == nil löscht aus der Wiederherstellung und entfernt metatable.
-- Ist ein table nur noch im Speicher für die Wiederherstellung, wird es trotzdem vom gc gelöscht (weak table).
-- Achtung, im Gegensatz zu setmetatable, wird das metatable kopiert, nicht referenziert!
-- 
metatable = {weak = {}, metas = {}, key = 0}
function metatable.set(tab, meta)
	assert(type(tab)=="table", "metatables koennen nur fuer tables gesetzt werden! "..tostring(tab))
	assert(type(meta)=="table" or meta==nil, "metatable muss table oder nil sein! "..tostring(meta))
	if not metatable.Mission_OnSaveGameLoaded then -- erster Aufruf: init Loaded-Callback & weak table
		metatable.Mission_OnSaveGameLoaded = Mission_OnSaveGameLoaded
		Mission_OnSaveGameLoaded = function()
			metatable.Mission_OnSaveGameLoaded()
			metatable.recreate()
		end
		metatable.recreate()
	end
	local oldmeta = meta -- nötig für keySave bei verschiedenen tables mit demselben metatable
	meta = {}
	for k,v in pairs(oldmeta) do
		meta[k] = v
	end
	oldmeta = getmetatable(tab)
	setmetatable(tab, meta) -- setze metatable
	--metatable.weak[tab] = CopyTable(meta)   fehler!!! key = table => absturz!!!
	local k = 0
	if oldmeta and oldmeta.keySave and tab == metatable.weak[oldmeta.keySave] then -- hatte vorher schon metatable => alter key
		k = oldmeta.keySave
		if meta == nil then -- löschen!
			metatable.weak[k] = nil
			metatable.metas[k] = nil
			return
		end
	else -- neuer key
		k = metatable.key + 1
		metatable.key = k
	end
	metatable.weak[k] = tab
	metatable.metas[k] = meta
	meta.keySave = k
end
metatable.recreate = function()
	for k, tab in pairs(metatable.weak) do
		setmetatable(tab, metatable.metas[k])
	end
	setmetatable(metatable.weak, {__mode = "v"}) -- weak table => wird gelöscht, wenn value nur noch dort referenziert ist
	setmetatable(metatable.metas, {__mode = "v"})
end

Dieser Beitrag wurde von mcb am 18.11.2016 um 16:12 editiert.

mcb
#2
18.11.2016 16:13
Beiträge: 1335

Version 1.2:
2 bugs gefixt, die unter bestimmten Umständen das laden der metatables verhindeten.

Seiten: 1

SiteEngine v1.5.0 by nevermind, ©2005-2007
Design by SpiderFive (www.siedler-games.de) - English translation by juja

Impressum