From 3443198edb19772873b1430c7203540485e23965 Mon Sep 17 00:00:00 2001 From: ZioPao Date: Sun, 12 Nov 2023 05:35:54 +0100 Subject: [PATCH] Trying to make stuff work in MP --- .../client/TOC/Handlers/ModDataHandler.lua | 75 +++++++------------ .../lua/client/TOC/Handlers/PlayerHandler.lua | 47 +++++++++--- media/lua/client/TOC/Tests.lua | 13 ++-- media/lua/client/TOC/UI/HealthPanel.lua | 38 ++++++++-- media/lua/server/TOC/ServerSyncCommands.lua | 4 + 5 files changed, 104 insertions(+), 73 deletions(-) diff --git a/media/lua/client/TOC/Handlers/ModDataHandler.lua b/media/lua/client/TOC/Handlers/ModDataHandler.lua index 9fb0133..ad5811d 100644 --- a/media/lua/client/TOC/Handlers/ModDataHandler.lua +++ b/media/lua/client/TOC/Handlers/ModDataHandler.lua @@ -1,64 +1,36 @@ local StaticData = require("TOC/StaticData") ---------------- ---This class should handle all the stuff related to the mod data +--- Handle all mod data related stuff ---@class ModDataHandler ---@field playerObj IsoPlayer ---@field tocData tocModData local ModDataHandler = {} +ModDataHandler.instances = {} ----@param playerObj IsoPlayer + +function ModDataHandler.AddExternalTocData(username, tocData) + +end + + +---@param username string +---@param tocData tocModData ---@return ModDataHandler -function ModDataHandler:new(playerObj) +function ModDataHandler:new(username, tocData) local o = {} setmetatable(o, self) self.__index = self - -- TODO Instead of requiring a player, to make it compatible in a MP env, we should require the table containing the modData for the init + -- Instead of requiring a player, to make it compatible in a MP env, we should require the table containing the modData for the init - o.playerObj = playerObj - o.tocData = playerObj:getModData()[StaticData.MOD_NAME] - - ModDataHandler.instance = o + o.tocData = tocData + ModDataHandler.instances[username] = o return o end ----Setup a newly instanced ModDataHandler ----@param force boolean? -function ModDataHandler:setup(force) - local tocData = self.playerObj:getModData()[StaticData.MOD_NAME] - if force or tocData == nil or tocData.Hand_L == nil or tocData.Hand_L.isCut == nil then - self:createData() - end - -- TODO Check compatibility or do we just skip it at this point? -end -function ModDataHandler:createData() - print("TOC: createData") - - local modData = self.playerObj:getModData() - modData[StaticData.MOD_NAME] = { - - -- Generic stuff that does not belong anywhere else - isIgnoredPartInfected = false, - isAnyLimbCut = false - } - - -- Set a reference to TOC data in ModData - self.tocData = self.playerObj:getModData()[StaticData.MOD_NAME] - - ---@type partData - local defaultParams = {isCut = false, isInfected = false, isOperated = false, isCicatrized = false, isCauterized = false, isVisible = false} - - - -- Initialize limbs - for i=1, #StaticData.LIMBS_STRINGS do - local limbName = StaticData.LIMBS_STRINGS[i] - modData[StaticData.MOD_NAME][limbName] = {} - self:setLimbParams(StaticData.LIMBS_STRINGS[i], defaultParams, 0) - end -end ----------------- --* Setters *-- @@ -148,11 +120,10 @@ function ModDataHandler:setCutLimb(limbName, isOperated, isCicatrized, isCauteri end ----Internal use only, set a limb data +---Set a limb data ---@param limbName string ---@param ampStatus partData {isCut, isInfected, isOperated, isCicatrized, isCauterized, isVisible} ---@param cicatrizationTime integer? ----@private function ModDataHandler:setLimbParams(limbName, ampStatus, cicatrizationTime) local limbData = self.tocData[limbName] if ampStatus.isCut ~= nil then limbData.isCut = ampStatus.isCut end @@ -165,12 +136,18 @@ function ModDataHandler:setLimbParams(limbName, ampStatus, cicatrizationTime) if cicatrizationTime ~= nil then limbData.cicatrizationTime = cicatrizationTime end end ----@return ModDataHandler -function ModDataHandler.GetInstance() - if ModDataHandler.instance ~= nil then - return ModDataHandler.instance + +---@param username string? +---@return ModDataHandler? +function ModDataHandler.GetInstance(username) + + if username == nil then username = getPlayer():getUsername() end + + if ModDataHandler.instances[username] ~= nil then + return ModDataHandler.instances[username] else - return ModDataHandler:new(getPlayer()) + return nil -- TODO This isn't exactly good + --return ModDataHandler:new(getPlayer()) end end diff --git a/media/lua/client/TOC/Handlers/PlayerHandler.lua b/media/lua/client/TOC/Handlers/PlayerHandler.lua index f75bc44..a734cf4 100644 --- a/media/lua/client/TOC/Handlers/PlayerHandler.lua +++ b/media/lua/client/TOC/Handlers/PlayerHandler.lua @@ -15,13 +15,12 @@ local StaticData = require("TOC/StaticData") ---@field playerObj IsoPlayer local PlayerHandler = {} ----Setup player modData +---Setup the Player Handler and modData ---@param _ nil ---@param playerObj IsoPlayer ---@param isForced boolean? function PlayerHandler.InitializePlayer(_, playerObj, isForced) - PlayerHandler.modDataHandler = ModDataHandler:new(playerObj) -- TODO This isn't gonna work for MP purposes - PlayerHandler.modDataHandler:setup(isForced) + PlayerHandler.SetupModData(playerObj, isForced) PlayerHandler.playerObj = playerObj -- Calculate amputated limbs at startup @@ -29,7 +28,7 @@ function PlayerHandler.InitializePlayer(_, playerObj, isForced) for i=1, #StaticData.LIMBS_STRINGS do local limbName = StaticData.LIMBS_STRINGS[i] - if PlayerHandler.modDataHandler:getIsCut(limbName) then + if ModDataHandler.GetInstance():getIsCut(limbName) then PlayerHandler.AddLocalAmputatedLimb(limbName) end end @@ -42,6 +41,35 @@ function PlayerHandler.InitializePlayer(_, playerObj, isForced) end end +---Setup TOC mod data to a local client +---@param playerObj IsoPlayer +---@param isForced boolean? +function PlayerHandler.SetupModData(playerObj, isForced) + local tocData = playerObj:getModData()[StaticData.MOD_NAME] + if isForced or tocData == nil or tocData.Hand_L == nil or tocData.Hand_L.isCut == nil then + local modData = playerObj:getModData() + modData[StaticData.MOD_NAME] = { + -- Generic stuff that does not belong anywhere else + isIgnoredPartInfected = false, + isAnyLimbCut = false + } + + ---@type partData + local defaultParams = {isCut = false, isInfected = false, isOperated = false, isCicatrized = false, isCauterized = false, isVisible = false} + + -- We're gonna make a instance of ModDataHandler to setup this player + local plUsername = playerObj:getUsername() + local dataHandler = ModDataHandler:new(plUsername, modData[StaticData.MOD_NAME]) + + -- Initialize limbs + for i=1, #StaticData.LIMBS_STRINGS do + local limbName = StaticData.LIMBS_STRINGS[i] + modData[StaticData.MOD_NAME][limbName] = {} + dataHandler:setLimbParams(StaticData.LIMBS_STRINGS[i], defaultParams, 0) + end + end +end + ---Handles the traits ---@param playerObj IsoPlayer function PlayerHandler.ManageTraits(playerObj) @@ -57,7 +85,6 @@ function PlayerHandler.ManageTraits(playerObj) end end - ---Cache the currently amputated limbs ---@param limbName string function PlayerHandler.AddLocalAmputatedLimb(limbName) @@ -87,23 +114,23 @@ function PlayerHandler.CheckInfection(character) local bodyPart = bd:getBodyPart(bptEnum) if bodyPart:bitten() or bodyPart:IsInfected() then - if PlayerHandler.modDataHandler:getIsCut(limbName) then + if ModDataHandler.GetInstance():getIsCut(limbName) then bodyPart:SetBitten(false) else - PlayerHandler.modDataHandler:setIsInfected(limbName, true) + ModDataHandler.GetInstance():setIsInfected(limbName, true) end end end -- Check other body parts that are not included in the mod, if there's a bite there then the player is fucked -- We can skip this loop if the player has been infected. The one before we kinda need it to handle correctly the bites in case the player wanna cut stuff off anyway - if PlayerHandler.modDataHandler:getIsIgnoredPartInfected() then return end + if ModDataHandler.GetInstance():getIsIgnoredPartInfected() then return end for i=1, #StaticData.IGNORED_PARTS_STRINGS do local bodyPartType = BodyPartType[StaticData.IGNORED_PARTS_STRINGS[i]] local bodyPart = bd:getBodyPart(bodyPartType) if bodyPart and (bodyPart:bitten() or bodyPart:IsInfected()) then - PlayerHandler.modDataHandler:setIsIgnoredPartInfected(true) + ModDataHandler.GetInstance():setIsIgnoredPartInfected(true) end end end @@ -140,7 +167,7 @@ local og_ISBaseTimedAction_perform = ISBaseTimedAction.perform function ISBaseTimedAction:perform() og_ISBaseTimedAction_perform(self) - if PlayerHandler.modDataHandler:getIsAnyLimbCut() then + if ModDataHandler.GetInstance():getIsAnyLimbCut() then for side, _ in pairs(StaticData.SIDES_STRINGS) do local limbName = "Hand_" .. side if ModDataHandler.GetInstance():getIsCut(limbName) then diff --git a/media/lua/client/TOC/Tests.lua b/media/lua/client/TOC/Tests.lua index 0762127..249beeb 100644 --- a/media/lua/client/TOC/Tests.lua +++ b/media/lua/client/TOC/Tests.lua @@ -4,6 +4,7 @@ local TestUtils = require("TestFramework/TestUtils") local PlayerHandler = require("TOC/Handlers/PlayerHandler") local AmputationHandler = require("TOC/Handlers/AmputationHandler") +local ModDataHandler = require("TOC/Handlers/ModDataHandler") TestFramework.registerTestModule("Functionality", "PlayerHandler", function() @@ -46,37 +47,37 @@ TestFramework.registerTestModule("Functionality", "Amputation", function() function Tests.CutLeftHand() local handler = AmputationHandler:new("Hand_L") handler:execute() - TestUtils.assert(PlayerHandler.modDataHandler:getIsCut("Hand_L")) + TestUtils.assert(ModDataHandler.GetInstance():getIsCut("Hand_L")) end function Tests.CutLeftForearm() local handler = AmputationHandler:new("ForeArm_L") handler:execute() - TestUtils.assert(PlayerHandler.modDataHandler:getIsCut("ForeArm_L") and PlayerHandler.modDataHandler:getIsCut("Hand_L")) + TestUtils.assert(ModDataHandler.GetInstance():getIsCut("ForeArm_L") and ModDataHandler.GetInstance():getIsCut("Hand_L")) end function Tests.CutLeftUpperarm() local handler = AmputationHandler:new("UpperArm_L") handler:execute() - TestUtils.assert(PlayerHandler.modDataHandler:getIsCut("UpperArm_L") and PlayerHandler.modDataHandler:getIsCut("ForeArm_L") and PlayerHandler.modDataHandler:getIsCut("Hand_L")) + TestUtils.assert(ModDataHandler.GetInstance():getIsCut("UpperArm_L") and ModDataHandler.GetInstance():getIsCut("ForeArm_L") and ModDataHandler.GetInstance():getIsCut("Hand_L")) end function Tests.CutRightHand() local handler = AmputationHandler:new("Hand_R") handler:execute() - TestUtils.assert(PlayerHandler.modDataHandler:getIsCut("Hand_R")) + TestUtils.assert(ModDataHandler.GetInstance():getIsCut("Hand_R")) end function Tests.CutRightForearm() local handler = AmputationHandler:new("ForeArm_R") handler:execute() - TestUtils.assert(PlayerHandler.modDataHandler:getIsCut("ForeArm_R") and PlayerHandler.modDataHandler:getIsCut("Hand_R")) + TestUtils.assert(ModDataHandler.GetInstance():getIsCut("ForeArm_R") and ModDataHandler.GetInstance():getIsCut("Hand_R")) end function Tests.CutRightUpperarm() local handler = AmputationHandler:new("UpperArm_R") handler:execute() - TestUtils.assert(PlayerHandler.modDataHandler:getIsCut("UpperArm_R") and PlayerHandler.modDataHandler:getIsCut("ForeArm_R") and PlayerHandler.modDataHandler:getIsCut("Hand_R")) + TestUtils.assert(ModDataHandler.GetInstance():getIsCut("UpperArm_R") and ModDataHandler.GetInstance():getIsCut("ForeArm_R") and ModDataHandler.GetInstance():getIsCut("Hand_R")) end return Tests diff --git a/media/lua/client/TOC/UI/HealthPanel.lua b/media/lua/client/TOC/UI/HealthPanel.lua index c770ecc..81e7c37 100644 --- a/media/lua/client/TOC/UI/HealthPanel.lua +++ b/media/lua/client/TOC/UI/HealthPanel.lua @@ -1,6 +1,7 @@ local PlayerHandler = require("TOC/Handlers/PlayerHandler") local StaticData = require("TOC/StaticData") local CommonMethods = require("TOC/CommonMethods") +local ModDataHandler = require("TOC/Handlers/ModDataHandler") ---@diagnostic disable: duplicate-set-field local CutLimbHandler = require("TOC/UI/CutLimbInteractions") @@ -43,18 +44,27 @@ end --* Modification to handle visible amputation on the health menu *-- -function ISHealthPanel.GetHighestAmputation() - ISHealthPanel.highestAmputations = {} + + +function ISHealthPanel:setHighestAmputation() + if self.otherPlayer ~= nil then + self.tocUsername = self.otherPlayer:getUsername() + else + self.tocUsername = self.character:getUsername() + end + + ISHealthPanel.highestAmputations[self.tocUsername] = {} + local modDataHandler = ModDataHandler.GetInstance(self.tocUsername) + if modDataHandler == nil then return end -- TODO Test this for i=1, #PlayerHandler.amputatedLimbs do local limbName = PlayerHandler.amputatedLimbs[i] local index = CommonMethods.GetSide(limbName) - if PlayerHandler.modDataHandler:getIsCut(limbName) and PlayerHandler.modDataHandler:getIsVisible(limbName) then + if modDataHandler:getIsCut(limbName) and modDataHandler:getIsVisible(limbName) then ISHealthPanel.highestAmputations[index] = limbName end end end - local og_ISHealthPanel_initialise = ISHealthPanel.initialise function ISHealthPanel:initialise() if self.character:isFemale() then @@ -62,29 +72,41 @@ function ISHealthPanel:initialise() else self.sexPl = "Male" end + + self:setHighestAmputation() + og_ISHealthPanel_initialise(self) end +local og_ISHealthPanel_setOtherPlayer = ISHealthPanel.setOtherPlayer +---comment +---@param playerObj IsoPlayer +function ISHealthPanel:setOtherPlayer(playerObj) + og_ISHealthPanel_setOtherPlayer(self, playerObj) + self:setHighestAmputation() +end + + local og_ISHealthPanel_render = ISHealthPanel.render function ISHealthPanel:render() og_ISHealthPanel_render(self) -- TODO Handle another player health panel - if ISHealthPanel.highestAmputations then + if ISHealthPanel.highestAmputations[self.tocUsername] then -- Left Texture - if ISHealthPanel.highestAmputations["L"] then + if ISHealthPanel.highestAmputations[self.tocUsername]["L"] then local textureL = StaticData.HEALTH_PANEL_TEXTURES[self.sexPl][ISHealthPanel.highestAmputations["L"]] self:drawTexture(textureL, self.healthPanel.x/2 - 2, self.healthPanel.y/2, 1, 1, 0, 0) end -- Right Texture - if ISHealthPanel.highestAmputations["R"] then + if ISHealthPanel.highestAmputations[self.tocUsername]["R"] then local textureR = StaticData.HEALTH_PANEL_TEXTURES[self.sexPl][ISHealthPanel.highestAmputations["R"]] self:drawTexture(textureR, self.healthPanel.x/2 + 2, self.healthPanel.y/2, 1, 1, 0, 0) end else - ISHealthPanel.GetHighestAmputation() + ISHealthPanel.GetHighestAmputation(self.tocUsername) end end diff --git a/media/lua/server/TOC/ServerSyncCommands.lua b/media/lua/server/TOC/ServerSyncCommands.lua index f8fb2da..43b8618 100644 --- a/media/lua/server/TOC/ServerSyncCommands.lua +++ b/media/lua/server/TOC/ServerSyncCommands.lua @@ -4,6 +4,10 @@ local moduleName = CommandsData.modules.TOC_SYNC ------------------------------ + +-- TODO This is gonna be impossible to manage. We need Global Mod Data to keep track of this kind of stuff at this point + + ---A client has asked the server to ask another client to send its toc mod data ---@param surgeonPl IsoPlayer ---@param args {patientNum : number}