diff --git a/client/src/BattleRoom.lua b/client/src/BattleRoom.lua index 9eb433cb..95b2a7f8 100644 --- a/client/src/BattleRoom.lua +++ b/client/src/BattleRoom.lua @@ -565,7 +565,7 @@ end function BattleRoom:onMatchEnded(match) self.matchesPlayed = self.matchesPlayed + 1 - if not match.aborted then + if not match.engine.aborted then local winners = match:getWinners() -- apply wins and possibly statistical data up for collection if #winners == 1 then diff --git a/client/src/ChallengeMode.lua b/client/src/ChallengeMode.lua index cf4a5a30..831e8885 100644 --- a/client/src/ChallengeMode.lua +++ b/client/src/ChallengeMode.lua @@ -204,7 +204,7 @@ function ChallengeMode:onMatchEnded(match) GAME.netClient:reportLocalGameResult(winners) end - if match.aborted then + if match.engine.aborted then -- in challenge mode, an abort is always a manual pause and leave by the local player -- match:deinit is the responsibility of the one switching out of the game scene GAME.navigationStack:pop(nil, function() match:deinit() end) diff --git a/client/src/ClientMatch.lua b/client/src/ClientMatch.lua index 8fb72fa9..67ae7794 100644 --- a/client/src/ClientMatch.lua +++ b/client/src/ClientMatch.lua @@ -334,7 +334,6 @@ function ClientMatch:setStage(stageId) end function ClientMatch:abort() - self.aborted = true self.engine:abort() self:handleMatchEnd() end diff --git a/client/src/MatchParticipant.lua b/client/src/MatchParticipant.lua index fed4ef12..a52d39ba 100644 --- a/client/src/MatchParticipant.lua +++ b/client/src/MatchParticipant.lua @@ -192,7 +192,8 @@ function MatchParticipant:setAttackEngineSettings(attackEngineSettings) end -- a callback that runs whenever a match ended -function MatchParticipant:onMatchEnded() +---@param match ClientMatch +function MatchParticipant:onMatchEnded(match) -- to prevent the game from instantly restarting, unready all players if self.human then self:setWantsReady(false) diff --git a/client/src/scenes/EndlessGame.lua b/client/src/scenes/EndlessGame.lua index 655bf50d..6f8b0ea9 100644 --- a/client/src/scenes/EndlessGame.lua +++ b/client/src/scenes/EndlessGame.lua @@ -15,6 +15,7 @@ function EndlessGame:customLoad() self.match:connectSignal("matchEnded", self, self.onMatchEnded) end +---@param match ClientMatch function EndlessGame:onMatchEnded(match) if match.players[1].settings.style == GameModes.Styles.CLASSIC then GAME.scores:saveEndlessScoreForLevel(match.players[1].stack.engine.score, match.players[1].stack.difficulty) diff --git a/client/src/scenes/Game1pChallenge.lua b/client/src/scenes/Game1pChallenge.lua index 39fb0656..7c4cdb32 100644 --- a/client/src/scenes/Game1pChallenge.lua +++ b/client/src/scenes/Game1pChallenge.lua @@ -32,6 +32,7 @@ function Game1pChallenge:startNextScene() end end +---@param match ClientMatch function Game1pChallenge:pauseChanged(match) if match.isPaused then self.timeSplitElement.isVisible = false diff --git a/client/src/scenes/GameBase.lua b/client/src/scenes/GameBase.lua index fec65d22..8c860557 100644 --- a/client/src/scenes/GameBase.lua +++ b/client/src/scenes/GameBase.lua @@ -482,6 +482,7 @@ function GameBase:drawEndGameText() end end +---@param match ClientMatch function GameBase:genericOnMatchEnded(match) self:setupGameOver() -- matches always sort players to have locals in front so if 1 isn't local, none is diff --git a/client/src/scenes/PuzzleGame.lua b/client/src/scenes/PuzzleGame.lua index 32587271..02339b18 100644 --- a/client/src/scenes/PuzzleGame.lua +++ b/client/src/scenes/PuzzleGame.lua @@ -372,7 +372,7 @@ function PuzzleGame:customGameOverSetup() end else -- puzzle failed or manually reset self.text = loc("pl_you_lose") - if (self.match.aborted == nil or self.match.aborted == false) then + if (self.match.engine.aborted == false) then self:savePuzzleRecordResult(false) end end diff --git a/client/src/scenes/ReplayGame.lua b/client/src/scenes/ReplayGame.lua index 363fae7b..f2e306a7 100644 --- a/client/src/scenes/ReplayGame.lua +++ b/client/src/scenes/ReplayGame.lua @@ -149,12 +149,13 @@ function ReplayGame:drawHUD() end end +---@param match ClientMatch function ReplayGame:genericOnMatchEnded(match) -- Call parent implementation first GameBase.genericOnMatchEnded(self, match) -- Add win count increment logic like BattleRoom does - if not match.aborted then + if not match.engine.aborted then local winners = match:getWinners() if #winners == 1 then winners[1].stack.character:playWinSfx() diff --git a/client/src/scenes/TimeAttackGame.lua b/client/src/scenes/TimeAttackGame.lua index 504f7776..b604eb27 100644 --- a/client/src/scenes/TimeAttackGame.lua +++ b/client/src/scenes/TimeAttackGame.lua @@ -15,6 +15,7 @@ function TimeAttackGame:customLoad() self.match:connectSignal("matchEnded", self, self.onMatchEnded) end +---@param match ClientMatch function TimeAttackGame:onMatchEnded(match) if match.players[1].settings.style == GameModes.Styles.CLASSIC then GAME.scores:saveTimeAttack1PScoreForLevel(match.players[1].stack.engine.score, match.players[1].stack.difficulty) diff --git a/client/src/scenes/VsSelfGame.lua b/client/src/scenes/VsSelfGame.lua index b638a734..b3f7063b 100644 --- a/client/src/scenes/VsSelfGame.lua +++ b/client/src/scenes/VsSelfGame.lua @@ -14,6 +14,7 @@ function VsSelfGame:customLoad() self.match:connectSignal("matchEnded", self, self.onMatchEnded) end +---@param match ClientMatch function VsSelfGame:onMatchEnded(match) local P1 = match.players[1].stack GAME.scores:saveVsSelfScoreForLevel(P1.analytic.data.sent_garbage_lines, P1.level) diff --git a/common/engine/Match.lua b/common/engine/Match.lua index a86a8306..18172e4c 100644 --- a/common/engine/Match.lua +++ b/common/engine/Match.lua @@ -30,6 +30,8 @@ local MatchRules = require("common.data.MatchRules") ---@field clock integer ---@field ended boolean ---@field gameOverClock integer? +---@field aborted boolean the game stopped in the middle because of crash, desync, game leave, online player left, etc. +---@field desyncError boolean? the match stopped because the other stack became too out of sync -- A match is a particular instance of the game, for example 1 time attack round, or 1 vs match ---@class Match @@ -61,6 +63,7 @@ function(self, panelSource, matchRules) self.startTimestamp = os.time(os.date("*t")) self.clock = 0 self.ended = false + self.aborted = false end ) diff --git a/common/lib/signal.lua b/common/lib/signal.lua index 9f35627b..5bd60d37 100644 --- a/common/lib/signal.lua +++ b/common/lib/signal.lua @@ -39,6 +39,10 @@ function Signal.createSignal(t, signalName) t.signalSubscriptions[signalName] = util.getWeaklyKeyedTable() end +-- emits a signal, calling all connected callbacks with the subscriber and any additional arguments +---@param emitter Signal the emitter that is emitting the signal +---@param signalName string the name of the signal to emit +---@param ... any additional arguments to pass to the callbacks function Signal.emitSignal(emitter, signalName, ...) if not emitter.signalSubscriptions[signalName] then error("Trying to emit unknown signal " .. signalName) diff --git a/main.lua b/main.lua index 3bfb5928..952272a3 100644 --- a/main.lua +++ b/main.lua @@ -255,7 +255,7 @@ function love.errorhandler(msg) if GAME.battleRoom and GAME.battleRoom.match then pcall(function() local match = GAME.battleRoom.match - match.aborted = true + match.engine.aborted = true ReplayV3.finalizeReplay(match.engine, match.replay) logger.info("Replay of match during crash:\n" .. json.encode(match.replay)) end)