diff --git a/game/engines/default/engine/CharacterBallSave.lua b/game/engines/default/engine/CharacterBallSave.lua new file mode 100644 index 0000000000000000000000000000000000000000..634c397e77fa45182965e5e320d96e7d09043425 --- /dev/null +++ b/game/engines/default/engine/CharacterBallSave.lua @@ -0,0 +1,49 @@ +-- TE4 - T-Engine 4 +-- Copyright (C) 2009, 2010, 2011 Nicolas Casalini +-- +-- This program is free software: you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation, either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see <http://www.gnu.org/licenses/>. +-- +-- Nicolas Casalini "DarkGod" +-- darkgod@te4.org + +require "engine.class" +local Savefile = require "engine.Savefile" + +--- Handles a local characters vault saves +module(..., package.seeall, class.inherit(Savefile)) + +function _M:init(savefile, coroutine) + Savefile.init(self, savefile, coroutine) + + fs.mkdir("/charballs") + self.short_name = savefile:gsub("[^a-zA-Z0-9_-.]", "_") + self.save_dir = "/charballs/" + self.quickbirth_file = "/charballs/useless.quickbirth" + self.load_dir = "/tmp/loadsave/" +end + +--- Get a savename for an entity +function _M:nameSaveEntity(e) + e.__version = game.__mod_info.version + return ("%s-%d.%d.%d.charball"):format(e.__te4_uuid, game.__mod_info.version[1], game.__mod_info.version[2], game.__mod_info.version[3]) +end +--- Get a savename for an entity +function _M:nameLoadEntity(name) + return name..".charball" +end + +--- Save an entity +function _M:saveEntity(e, no_dialog) + Savefile.saveEntity(self, e, no_dialog) +end diff --git a/game/engines/default/engine/PlayerProfile.lua b/game/engines/default/engine/PlayerProfile.lua index 1fa909129b764c0accaaed1bf6e153fb10753a96..c61a46c6d916979335953aeea0f367405924f9df 100644 --- a/game/engines/default/engine/PlayerProfile.lua +++ b/game/engines/default/engine/PlayerProfile.lua @@ -627,6 +627,16 @@ function _M:registerNewCharacter(module) return uuid end +function _M:registerSaveCharball(module, uuid, data) + if not self.auth or not self.hash_valid then return end + core.profile.pushOrder(table.serialize{o="SaveCharball", + module=module, + uuid=uuid, + data=data, + }) + print("[ONLINE PROFILE] saved character charball", uuid) +end + function _M:registerSaveChardump(module, uuid, title, tags, data) if not self.auth or not self.hash_valid then return end core.profile.pushOrder(table.serialize{o="SaveChardump", diff --git a/game/engines/default/engine/SavefilePipe.lua b/game/engines/default/engine/SavefilePipe.lua index 56fe8c88ac7bca0c14f0b62a89a1c728b9e14368..fc7f2437b7dd359815b2a4ec19301e5abd950961 100644 --- a/game/engines/default/engine/SavefilePipe.lua +++ b/game/engines/default/engine/SavefilePipe.lua @@ -49,7 +49,8 @@ end -- @param type the Savefile method to use. I.e: "game", "level", "zone". This will cann the Savefile:saveGame, Savefile:saveLevel, Savefile:saveZone methods -- @param object the object to save -- @param class a class name, if different from the default one -function _M:push(savename, type, object, class) +-- @param on_end a function to call when this object is saved; this can be nil +function _M:push(savename, type, object, class, on_end) if game.onSavefilePush then game:onSavefilePush(savename, type, object, class) end local screenshot = nil @@ -64,7 +65,7 @@ function _M:push(savename, type, object, class) if #self.pipe == 0 then savefile_pipe.current_nb = 0 end local clone, nb = object:cloneFull() - self.pipe[#self.pipe+1] = {id=id, savename = savename, type=type, object=clone, nb_objects=nb, baseobject=object, class=class, saveversion=game:saveVersion("new"), screenshot=screenshot} + self.pipe[#self.pipe+1] = {id=id, savename = savename, type=type, object=clone, nb_objects=nb, baseobject=object, class=class, saveversion=game:saveVersion("new"), screenshot=screenshot, on_end=on_end} local total_nb = 0 for i, p in ipairs(self.pipe) do total_nb = total_nb + p.nb_objects end self.total_nb = total_nb @@ -105,6 +106,10 @@ function _M:doThread() if p.screenshot then save:saveScreenshot(p.screenshot) end save:close() + if p.on_end then + p.on_end(save) + end + table.remove(self.pipe, 1) end if game.log then game.log("Saving done.") end diff --git a/game/engines/default/engine/interface/PlayerDumpJSON.lua b/game/engines/default/engine/interface/PlayerDumpJSON.lua index e32ac9ce9c7fa181b6d1a3afc229f2a0aa47e18c..d23b2e2c1d196edcb2245fd1b0c38208b7e6500f 100644 --- a/game/engines/default/engine/interface/PlayerDumpJSON.lua +++ b/game/engines/default/engine/interface/PlayerDumpJSON.lua @@ -35,7 +35,7 @@ function _M:getUUID() end --- Call this when a character is saved to upload data to te4.org -function _M:saveUUID() +function _M:saveUUID(do_charball) if not self.__te4_uuid then -- Try to grab an UUID even after char reg if self.allow_late_uuid and not game:isTainted() then self:getUUID() end @@ -58,6 +58,22 @@ function _M:saveUUID() if not data or not title then return end profile:registerSaveChardump(game.__mod_info.short_name, self.__te4_uuid, title, tags, core.zlib.compress(data)) + if do_charball then + savefile_pipe:push(do_charball.name, "entity", do_charball, "engine.CharacterBallSave", function(save) + f = fs.open("/charballs/"..save:nameSaveEntity(do_charball), "r") + if f then + local data = {} + while true do + local l = f:read() + if not l then break end + data[#data+1] = l + end + f:close() + + profile:registerSaveCharball(game.__mod_info.short_name, self.__te4_uuid, table.concat(data)) + end + end) + end end --- Override this method to define dump sections diff --git a/game/modules/tome/class/Game.lua b/game/modules/tome/class/Game.lua index 78e409122d8d6977417bee66fc2661ed11c4e870..aa5ab4da246187058a31ab36bb6d5c634fff0a52 100644 --- a/game/modules/tome/class/Game.lua +++ b/game/modules/tome/class/Game.lua @@ -126,7 +126,12 @@ function _M:run() self.uiset.npcs_display.actor = self.player -- Run the current music if any - self:onTickEnd(function() self:playMusic() end) + self:onTickEnd(function() + self:playMusic() + if self.level then + self.level.map:moveViewSurround(self.player.x, self.player.y, config.settings.tome.scroll_dist, config.settings.tome.scroll_dist) + end + end) -- Create the map scroll text overlay local lfont = core.display.newFont("/data/font/Vera.ttf", 30) @@ -162,7 +167,7 @@ function _M:setPlayerName(name) end function _M:newGame() - self.party = Party.new() + self.party = Party.new{} local player = Player.new{name=self.player_name, game_ender=true} self.party:addMember(player, { control="full", @@ -1584,7 +1589,12 @@ function _M:saveGame() if not self.creating_player then local oldplayer = self.player self.party:setPlayer(self:getPlayer(true), true) - self.player:saveUUID() + + local party = self.party:cloneFull() + party.__te4_uuid = self:getPlayer(true).__te4_uuid + for m, _ in pairs(party.members) do m.fov = {actors={}, actors_dist={}} end + self.player:saveUUID(party) + self.party:setPlayer(oldplayer, true) end self.log("Saving game...") diff --git a/game/modules/tome/class/Party.lua b/game/modules/tome/class/Party.lua index 27f4091f724734a2e2210292ce20c3916d3af328..c5b47d3042eb9193a8b784c101f3eb220a3d6413 100644 --- a/game/modules/tome/class/Party.lua +++ b/game/modules/tome/class/Party.lua @@ -29,6 +29,7 @@ module(..., package.seeall, class.inherit( )) function _M:init(t, no_default) + t.name = t.name or "party" engine.Entity.init(self, t, no_default) self.members = {} diff --git a/game/modules/tome/class/interface/PlayerDumpJSON.lua b/game/modules/tome/class/interface/PlayerDumpJSON.lua index 2259ce5e722b6bdb6edd9a445a081d50a9603388..bcfbe526acfef9833e866f7e27171cb932de5b66 100644 --- a/game/modules/tome/class/interface/PlayerDumpJSON.lua +++ b/game/modules/tome/class/interface/PlayerDumpJSON.lua @@ -296,7 +296,7 @@ function _M:dumpToJSON(js) -- Log ------------------------------------------------------------------- local log = js:newSection("last messages", "log", "text", nil) - log[#log+1] = { val=table.concat(game.logdisplay:getLines(30), "#LAST#\n"), bg="000000" } + log[#log+1] = { val=table.concat(game.uiset.logdisplay:getLines(30), "#LAST#\n"), bg="000000" } -- Cleanup numbers for _, sec in ipairs(js.sections) do diff --git a/game/modules/tome/data/general/objects/boss-artifacts.lua b/game/modules/tome/data/general/objects/boss-artifacts.lua index 4cdf4a9764595495f0fcc6c2e4ce31017f1d65f8..159483ce986b20bf2fec6ff3e50424b7a8be8a50 100644 --- a/game/modules/tome/data/general/objects/boss-artifacts.lua +++ b/game/modules/tome/data/general/objects/boss-artifacts.lua @@ -1228,7 +1228,7 @@ It has been kept somewhat intact with layers of salt and clay, but in spite of t for x, yy in pairs(grids) do for y, _ in pairs(yy) do local trap = game.level.map(x, y, Map.TRAP) - if trap and not (trap:knownBy(self) or trap:knownBy(who)) then + if trap and not (trap:knownBy(self) or trap:knownBy(actor)) then is_trap = true -- Set the artifact as knowing the trap, not the wearer trap:setKnown(self, true) diff --git a/game/profile-thread/Client.lua b/game/profile-thread/Client.lua index a3f14c7194b30dc5eb3f01c480b3ca3b3e38f261..f1d9517369daa3b8a51d348a567d6ff8bfff9644 100644 --- a/game/profile-thread/Client.lua +++ b/game/profile-thread/Client.lua @@ -345,6 +345,13 @@ function _M:orderSaveChardump(o) cprofile.pushEvent("e='SaveChardump' ok=true") end +function _M:orderSaveCharball(o) + self:command("CHAR", "CHARBALL", o.data:len(), o.uuid, o.module) + if not self:read("200") then return end + self.sock:send(o.data) + cprofile.pushEvent("e='SaveCharball' ok=true") +end + function _M:orderCurrentCharacter(o) self:command("CHAR", "CUR", table.serialize(o)) self.cur_char = o