From 72f893167ca62ac9a675fb15a1f3c7e171534d8c Mon Sep 17 00:00:00 2001
From: dg <dg@51575b47-30f0-44d4-a5cc-537603b46e54>
Date: Wed, 31 Mar 2010 08:54:52 +0000
Subject: [PATCH] levels are now persisted by zones. this makes intra-zone
 level switch ultra-fast but intra-zone switch slower (and main save slower)

git-svn-id: http://svn.net-core.org/repos/t-engine4@475 51575b47-30f0-44d4-a5cc-537603b46e54
---
 game/engine/Savefile.lua                      | 38 +++++++++
 game/engine/Zone.lua                          | 79 +++++++++++++------
 game/modules/tome/class/Game.lua              |  1 +
 .../tome/data/zones/illusory-castle/zone.lua  |  2 +-
 game/modules/tome/data/zones/maze/zone.lua    |  2 +-
 .../tome/data/zones/old-forest/zone.lua       |  2 +-
 .../tome/data/zones/sandworm-lair/zone.lua    |  2 +-
 .../tome/data/zones/tol-falas/zone.lua        |  2 +-
 .../tome/data/zones/tower-amon-sul/zone.lua   |  2 +-
 .../tome/data/zones/trollshaws/zone.lua       |  2 +-
 10 files changed, 103 insertions(+), 29 deletions(-)

diff --git a/game/engine/Savefile.lua b/game/engine/Savefile.lua
index a6adb5b4e4..ad1a0e1743 100644
--- a/game/engine/Savefile.lua
+++ b/game/engine/Savefile.lua
@@ -99,6 +99,20 @@ function _M:saveGame(game)
 	game:unregisterDialog(popup)
 end
 
+--- Save a zone
+function _M:saveZone(zone)
+	fs.mkdir(self.save_dir)
+
+	local popup = Dialog:simplePopup("Saving zone", "Please wait while saving the zone...")
+	core.display.forceRedraw()
+
+	local zip = fs.zipOpen(self.save_dir..("zone-%s.teaz"):format(zone.short_name))
+	self:saveObject(zone, zip)
+	zip:close()
+
+	game:unregisterDialog(popup)
+end
+
 --- Save a level
 function _M:saveLevel(level)
 	fs.mkdir(self.save_dir)
@@ -172,6 +186,30 @@ function _M:loadGame()
 	return loadedGame
 end
 
+--- Loads a zone
+function _M:loadZone(zone)
+	local path = fs.getRealPath(self.save_dir..("zone-%s.teaz"):format(zone))
+	if not path or path == "" then return false end
+
+	fs.mount(path, self.load_dir)
+
+	local popup = Dialog:simplePopup("Loading zone", "Please wait while loading the zone...")
+	core.display.forceRedraw()
+
+	local loadedZone = self:loadReal("main")
+
+	-- Delay loaded must run
+	for i, o in ipairs(self.delayLoad) do
+--		print("loader executed for class", o, o.__CLASSNAME)
+		o:loaded()
+	end
+
+	game:unregisterDialog(popup)
+
+	fs.umount(path)
+	return loadedZone
+end
+
 --- Loads a level
 function _M:loadLevel(zone, level)
 	local path = fs.getRealPath(self.save_dir..("level-%s-%d.teal"):format(zone, level))
diff --git a/game/engine/Zone.lua b/game/engine/Zone.lua
index b5d8a9bbfc..f9de14c15f 100644
--- a/game/engine/Zone.lua
+++ b/game/engine/Zone.lua
@@ -25,24 +25,37 @@ end
 -- @param short_name the short name of the zone to load, if should correspond to a directory in your module data/zones/short_name/ with a zone.lua, npcs.lua, grids.lua and objects.lua files inside
 function _M:init(short_name)
 	self.short_name = short_name
-	self:load()
-	self.level_range = self.level_range or {1,1}
-	if type(self.level_range) == "number" then self.level_range = {self.level_range, self.level_range} end
-	self.level_scheme = self.level_scheme or "fixed"
-	assert(self.max_level, "no zone max level")
-	self.levels = self.levels or {}
-	self.npc_list = self.npc_class:loadList("/data/zones/"..self.short_name.."/npcs.lua")
-	self.grid_list = self.grid_class:loadList("/data/zones/"..self.short_name.."/grids.lua")
-	self.object_list = self.object_class:loadList("/data/zones/"..self.short_name.."/objects.lua")
-	self.trap_list = self.trap_class:loadList("/data/zones/"..self.short_name.."/traps.lua")
-
-	-- Determine a zone base level
-	self.base_level = self.level_range[1]
-	if self.level_scheme == "player" then
-		local plev = game:getPlayer().level
-		self.base_level = util.bound(plev, self.level_range[1], self.level_range[2])
+	if not self:load() then
+		self.level_range = self.level_range or {1,1}
+		if type(self.level_range) == "number" then self.level_range = {self.level_range, self.level_range} end
+		self.level_scheme = self.level_scheme or "fixed"
+		assert(self.max_level, "no zone max level")
+		self.levels = self.levels or {}
+		self.npc_list = self.npc_class:loadList("/data/zones/"..self.short_name.."/npcs.lua")
+		self.grid_list = self.grid_class:loadList("/data/zones/"..self.short_name.."/grids.lua")
+		self.object_list = self.object_class:loadList("/data/zones/"..self.short_name.."/objects.lua")
+		self.trap_list = self.trap_class:loadList("/data/zones/"..self.short_name.."/traps.lua")
+
+		-- Determine a zone base level
+		self.base_level = self.level_range[1]
+		if self.level_scheme == "player" then
+			local plev = game:getPlayer().level
+			self.base_level = util.bound(plev, self.level_range[1], self.level_range[2])
+		end
+		print("Initiated zone", self.name, "with base_level", self.base_level)
+	else
+		print("Loaded zone", self.name, "with base_level", self.base_level)
+	end
+end
+
+--- Leaves a zone
+-- Saves the zone to a .teaz file if requested with persistant="zone" flag
+function _M:leave()
+	if type(self.persistant) == "string" and self.persistant == "zone" then
+		local save = Savefile.new(game.save_name)
+		save:saveZone(self)
+		save:close()
 	end
-	print("Initiated zone", self.name, "with base_level", self.base_level)
 end
 
 --- Parses the npc/objects list and compute rarities for random generation
@@ -246,9 +259,16 @@ function _M:addEntity(level, e, typ, x, y)
 end
 
 function _M:load()
-	local f, err = loadfile("/data/zones/"..self.short_name.."/zone.lua")
-	if err then error(err) end
-	local data = f()
+	-- Try to load from a savefile
+	local save = Savefile.new(game.save_name)
+	local data = save:loadZone(self.short_name)
+	save:close()
+
+	if not data then
+		local f, err = loadfile("/data/zones/"..self.short_name.."/zone.lua")
+		if err then error(err) end
+		data = f()
+	end
 	for k, e in pairs(data) do self[k] = e end
 end
 
@@ -273,7 +293,11 @@ function _M:leaveLevel(no_close, lev, old_lev)
 	if not no_close and game.level and game.level.map then
 		game:leaveLevel(game.level, lev, old_lev)
 
-		if type(game.level.data.persistant) == "string" and game.level.data.persistant == "memory" then
+		if type(game.level.data.persistant) == "string" and game.level.data.persistant == "zone" then
+			print("[LEVEL] persisting to zone memory", game.level.id)
+			self.memory_levels = self.memory_levels or {}
+			self.memory_levels[game.level.level] = game.level
+		elseif type(game.level.data.persistant) == "string" and game.level.data.persistant == "memory" then
 			print("[LEVEL] persisting to memory", game.level.id)
 			game.memory_levels = game.memory_levels or {}
 			game.memory_levels[game.level.id] = game.level
@@ -300,7 +324,18 @@ function _M:getLevel(game, lev, old_lev, no_close)
 
 	local level
 	-- Load persistant level?
-	if type(level_data.persistant) == "string" and level_data.persistant == "memory" then
+	if type(level_data.persistant) == "string" and level_data.persistant == "zone" then
+		self.memory_levels = self.memory_levels or {}
+		level = self.memory_levels[lev]
+
+		if level then
+			-- Setup the level in the game
+			game:setLevel(level)
+			-- Recreate the map because it could have been saved with a different tileset or whatever
+			-- This is not needed in case of a direct to file persistance becuase the map IS recreated each time anyway
+			level.map:recreate()
+		end
+	elseif type(level_data.persistant) == "string" and level_data.persistant == "memory" then
 		game.memory_levels = game.memory_levels or {}
 		level = game.memory_levels[self.short_name.."-"..lev]
 
diff --git a/game/modules/tome/class/Game.lua b/game/modules/tome/class/Game.lua
index 80944b636a..c51778d22f 100644
--- a/game/modules/tome/class/Game.lua
+++ b/game/modules/tome/class/Game.lua
@@ -195,6 +195,7 @@ function _M:changeLevel(lev, zone)
 	if zone then
 		if self.zone then
 			self.zone:leaveLevel(false, lev, old_lev)
+			self.zone:leave()
 		end
 		self.zone = Zone.new(zone)
 	end
diff --git a/game/modules/tome/data/zones/illusory-castle/zone.lua b/game/modules/tome/data/zones/illusory-castle/zone.lua
index 4f1e51161d..9c7cd7011b 100644
--- a/game/modules/tome/data/zones/illusory-castle/zone.lua
+++ b/game/modules/tome/data/zones/illusory-castle/zone.lua
@@ -7,7 +7,7 @@ return {
 	width = 50, height = 50,
 	all_remembered = true,
 	all_lited = true,
---	persistant = true,
+--	persistant = "zone",
 	generator =  {
 		map = {
 --			class = "engine.generator.map.Rooms",
diff --git a/game/modules/tome/data/zones/maze/zone.lua b/game/modules/tome/data/zones/maze/zone.lua
index a2dd3b01ae..96ab6478b4 100644
--- a/game/modules/tome/data/zones/maze/zone.lua
+++ b/game/modules/tome/data/zones/maze/zone.lua
@@ -7,7 +7,7 @@ return {
 	width = 40, height = 40,
 --	all_remembered = true,
 --	all_lited = true,
-	persistant = true,
+	persistant = "zone",
 	generator =  {
 		map = {
 			class = "engine.generator.map.Maze",
diff --git a/game/modules/tome/data/zones/old-forest/zone.lua b/game/modules/tome/data/zones/old-forest/zone.lua
index f5649345d6..05663c6d6f 100644
--- a/game/modules/tome/data/zones/old-forest/zone.lua
+++ b/game/modules/tome/data/zones/old-forest/zone.lua
@@ -7,7 +7,7 @@ return {
 	width = 50, height = 50,
 --	all_remembered = true,
 	all_lited = true,
-	persistant = true,
+	persistant = "zone",
 	generator =  {
 		map = {
 			class = "engine.generator.map.Roomer",
diff --git a/game/modules/tome/data/zones/sandworm-lair/zone.lua b/game/modules/tome/data/zones/sandworm-lair/zone.lua
index 7d653b216d..2dbd19335f 100644
--- a/game/modules/tome/data/zones/sandworm-lair/zone.lua
+++ b/game/modules/tome/data/zones/sandworm-lair/zone.lua
@@ -7,7 +7,7 @@ return {
 	width = 50, height = 50,
 --	all_remembered = true,
 --	all_lited = true,
-	persistant = true,
+	persistant = "zone",
 	generator =  {
 		map = {
 			class = "engine.generator.map.Roomer",
diff --git a/game/modules/tome/data/zones/tol-falas/zone.lua b/game/modules/tome/data/zones/tol-falas/zone.lua
index ac60d8e621..4c89a140e2 100644
--- a/game/modules/tome/data/zones/tol-falas/zone.lua
+++ b/game/modules/tome/data/zones/tol-falas/zone.lua
@@ -7,7 +7,7 @@ return {
 	width = 50, height = 50,
 --	all_remembered = true,
 --	all_lited = true,
-	persistant = true,
+	persistant = "zone",
 	generator =  {
 		map = {
 			class = "engine.generator.map.Roomer",
diff --git a/game/modules/tome/data/zones/tower-amon-sul/zone.lua b/game/modules/tome/data/zones/tower-amon-sul/zone.lua
index b608735ed4..2507490c3e 100644
--- a/game/modules/tome/data/zones/tower-amon-sul/zone.lua
+++ b/game/modules/tome/data/zones/tower-amon-sul/zone.lua
@@ -7,7 +7,7 @@ return {
 	width = 50, height = 50,
 --	all_remembered = true,
 --	all_lited = true,
-	persistant = true,
+	persistant = "zone",
 --	ambiant_music = "10_23.ogg",
 	generator =  {
 		map = {
diff --git a/game/modules/tome/data/zones/trollshaws/zone.lua b/game/modules/tome/data/zones/trollshaws/zone.lua
index c0fa8ac05b..ccceb72085 100644
--- a/game/modules/tome/data/zones/trollshaws/zone.lua
+++ b/game/modules/tome/data/zones/trollshaws/zone.lua
@@ -7,7 +7,7 @@ return {
 	width = 50, height = 50,
 --	all_remembered = true,
 	all_lited = true,
-	persistant = true,
+	persistant = "zone",
 	generator =  {
 		map = {
 			class = "engine.generator.map.Roomer",
-- 
GitLab