diff --git a/game/engine/Game.lua b/game/engine/Game.lua index 9ee202e6da308c5590e8b51a332ba541c002bc66..85a9ae52fda13e0d8b842afee499fc705392cde3 100644 --- a/game/engine/Game.lua +++ b/game/engine/Game.lua @@ -42,6 +42,8 @@ function _M:init(keyhandler) self.mouse:setCurrent() self.uniques = {} + + self.__threads = {} end function _M:loaded() @@ -208,3 +210,27 @@ end --- Requests the game to save function _M:saveGame() end + +--- Save a thread into the thread pool +-- Threads will be auto join'ed when the module exits or when it can<br/> +-- ALL THREADS registered *MUST* return true when they exit +function _M:registerThread(th, linda) + print("[THREAD] registering", th, linda, #self.__threads+1) + self.__threads[#self.__threads+1] = {th=th, linda=linda} + return #self.__threads +end + +--- Try to join all registered threads +-- @param timeout the time in seconds to wait for each thread +function _M:joinThreads(timeout) + for i = #self.__threads, 1, -1 do + local th = self.__threads[i].th + print("[THREAD] Thread join", i, th) + local v, err = th:join(timeout) + if err then print("[THREAD] error", th) error(err) end + if v then + print("[THREAD] Thread result", i, th, "=>", v) + table.remove(self.__threads, i) + end + end +end diff --git a/game/engine/GameTurnBased.lua b/game/engine/GameTurnBased.lua index ffe5200e0b0f671418e8d4f63680531f0a5a0480..27c30e187e5404e49a974d709eb191aa99bd3afd 100644 --- a/game/engine/GameTurnBased.lua +++ b/game/engine/GameTurnBased.lua @@ -45,6 +45,11 @@ function _M:tick() engine.GameEnergyBased.tick(self) self.turn = self.turn + 1 self:onTurn() + + -- Try to join threads if any, every hundred turns + if self.turn % 100 == 0 then + self:joinThreads(0) + end end end diff --git a/game/engine/Module.lua b/game/engine/Module.lua index 29d0fae576e1a1f3015bc38585db61c2257299a7..d14100cf08df305506144cddde5d8eb4672b846e 100644 --- a/game/engine/Module.lua +++ b/game/engine/Module.lua @@ -95,6 +95,8 @@ function _M:loadDefinition(dir, team) end profile:loadModuleProfile(mod.short_name) local m = require(mod.starter) + m[1].__session_time_played_start = os.time() + m[1].__mod_info = mod print("[MODULE LOADER] loading module", mod.long_name, "["..mod.starter.."]", "::", m[1] and m[1].__CLASSNAME, m[2] and m[2].__CLASSNAME) return m[1], m[2] end diff --git a/game/engine/PlayerProfile.lua b/game/engine/PlayerProfile.lua index 35091d88f740a4062560591753052faef459deb6..c3a250425ae3eb8186224ae5c8075941ae0bde8f 100644 --- a/game/engine/PlayerProfile.lua +++ b/game/engine/PlayerProfile.lua @@ -21,6 +21,7 @@ require "engine.class" local http = require "socket.http" local url = require "socket.url" local ltn12 = require "ltn12" +local lanes = require "lanes" require "Json2" ------------------------------------------------------------ @@ -187,10 +188,33 @@ end ----------------------------------------------------------------------- function _M:rpc(data) - print("[ONLINE PROFILE] rpc called", "http://te4.org/lua/profilesrpc.ws/"..data.action) - local body, status = http.request("http://te4.org/lua/profilesrpc.ws/"..data.action, "json="..url.escape(json.encode(data))) - if not body then return end - return json.decode(body) + -- We can work in asynchronous mode, to not delay the main game execution + if data.async and game and type(game) == "table" and not game.refuse_threads then + data.async = nil + local l = lanes.linda() + + function handler(data) + local http = require "socket.http" + local url = require "socket.url" + require "Json2" + + print("[ONLINE PROFILE] async rpc called", "http://te4.org/lua/profilesrpc.ws/"..data.action) + local body, status = http.request("http://te4.org/lua/profilesrpc.ws/"..data.action, "json="..url.escape(json.encode(data))) + if not body then l:send("final", nil) + else l:send("final", json.decode(body)) + end + return true + end + + local th = lanes.gen("*", handler)(data) + -- Tell the game to monitor this thread and end it when it's done + game:registerThread(th, l) + else + print("[ONLINE PROFILE] rpc called", "http://te4.org/lua/profilesrpc.ws/"..data.action) + local body, status = http.request("http://te4.org/lua/profilesrpc.ws/"..data.action, "json="..url.escape(json.encode(data))) + if not body then return end + return json.decode(body) + end end function _M:tryAuth() @@ -229,7 +253,7 @@ function _M:setConfigs(module, name, val) if type(val) ~= "string" then val = serialize(val) end - local data = self:rpc{action="SetConfigs", login=self.login, hash=self.auth.hash, module=module, data={[name] = val}} + local data = self:rpc{async=true, action="SetConfigs", login=self.login, hash=self.auth.hash, module=module, data={[name] = val}} if not data then return end print("[ONLINE PROFILE] saved ", module, name, val) end @@ -243,7 +267,7 @@ function _M:syncOnline(module) local data = {} for k, v in pairs(sync) do if k ~= "online" then data[k] = serialize(v) end end - local data = self:rpc{action="SetConfigs", login=self.login, hash=self.auth.hash, module=module, data=data} + local data = self:rpc{async=true, action="SetConfigs", login=self.login, hash=self.auth.hash, module=module, data=data} if not data then return end print("[ONLINE PROFILE] saved ", module) end diff --git a/game/engine/utils.lua b/game/engine/utils.lua index 4535aa63626789ba00914dfb634e36ab5fe7620f..69bc2f099b492a1d179c78d193cfceca90020064 100644 --- a/game/engine/utils.lua +++ b/game/engine/utils.lua @@ -489,6 +489,15 @@ function util.findFreeGrid(sx, sy, radius, block, what) end function util.showMainMenu(no_reboot) + if game and type(game) == "table" and game.__session_time_played_start then + profile.generic.modules_played = profile.generic.modules_played or {} + profile.generic.modules_played[game.__mod_info.short_name] = (profile.generic.modules_played[game.__mod_info.short_name] or 0) + (os.time() - game.__session_time_played_start) + profile:saveGenericProfile("modules_played", profile.generic.modules_played) + end + + -- Join threads + if game and type(game) == "table" then game:joinThreads(30) end + if no_reboot then local Menu = require("special.mainmenu.class.Game") game = Menu.new() diff --git a/game/special/mainmenu/class/Game.lua b/game/special/mainmenu/class/Game.lua index 261c88bce136a722009e7ccf16de3f8a623da4d8..2e669a19261f88773187844814dd05d9965d96a8 100644 --- a/game/special/mainmenu/class/Game.lua +++ b/game/special/mainmenu/class/Game.lua @@ -35,6 +35,7 @@ function _M:init() engine.Game.init(self, engine.KeyBind.new()) self.background = core.display.loadImage("/data/gfx/mainmenu/background.png") + self.refuse_threads = true end function _M:run()