From 48876998922d22a6d4684ec5ea11213f9176b5d9 Mon Sep 17 00:00:00 2001 From: ZioPao Date: Sun, 12 Nov 2023 22:20:46 +0100 Subject: [PATCH] Reworked some stuff for MP --- media/lua/client/TOC/ClientSyncCommands.lua | 15 ++-- .../client/TOC/Handlers/AmputationHandler.lua | 9 ++- .../lua/client/TOC/Handlers/ItemsHandler.lua | 2 +- .../client/TOC/Handlers/ModDataHandler.lua | 72 ++++++++++++++----- .../lua/client/TOC/Handlers/PlayerHandler.lua | 61 +++++----------- media/lua/client/TOC/Main.lua | 9 ++- media/lua/client/TOC/Tests.lua | 2 +- media/lua/client/TOC/UI/HealthPanel.lua | 43 ++++++++--- media/lua/server/TOC/ServerDataCommands.lua | 54 ++++++++++++++ media/lua/server/TOC/ServerSyncCommands.lua | 15 ++-- .../BodyLocations.lua} | 1 + media/lua/shared/TOC/CommandsData.lua | 17 +++-- media/lua/{client => shared}/TOC/Debug.lua | 0 13 files changed, 209 insertions(+), 91 deletions(-) create mode 100644 media/lua/server/TOC/ServerDataCommands.lua rename media/lua/shared/{NPCs/TOC_BodyLocations.lua => TOC/BodyLocations.lua} (97%) rename media/lua/{client => shared}/TOC/Debug.lua (100%) diff --git a/media/lua/client/TOC/ClientSyncCommands.lua b/media/lua/client/TOC/ClientSyncCommands.lua index 3420ce1..830659a 100644 --- a/media/lua/client/TOC/ClientSyncCommands.lua +++ b/media/lua/client/TOC/ClientSyncCommands.lua @@ -1,24 +1,27 @@ local CommandsData = require("TOC/CommandsData") +local ModDataHandler = require("TOC/Handlers/ModDataHandler") + local ClientSyncCommands = {} local moduleName = CommandsData.modules.TOC_SYNC ------------------------------ ---Send the toc mod data to the server to relay it to someone else ----@param args {surgeonNum : number} +---@param args sendPlayerDataParams function ClientSyncCommands.SendPlayerData(args) -- TODO get moddata and send it - sendClientCommand(moduleName, CommandsData.server.Sync.RelayPlayerData, {surgeonNum = args.surgeonNum, tocData = {}}) + + ---@type relayPlayerDataParams + local params = {surgeonNum = args.surgeonNum, tocData = {}} + sendClientCommand(moduleName, CommandsData.server.Sync.RelayPlayerData, params) end ---Receives and store the toc mod data from another player ----@param args {patientNum : number} +---@param args receivePlayerDataParams function ClientSyncCommands.ReceivePlayerData(args) local patientPl = getSpecificPlayer(args.patientNum) local patientUsername patientPl:getUsername() - - - -- TODO Save the data somewhere that makes sense. + ModDataHandler.AddExternalTocData(patientUsername, args.tocData) end ------------------------------ diff --git a/media/lua/client/TOC/Handlers/AmputationHandler.lua b/media/lua/client/TOC/Handlers/AmputationHandler.lua index 2ba7c27..6d62a30 100644 --- a/media/lua/client/TOC/Handlers/AmputationHandler.lua +++ b/media/lua/client/TOC/Handlers/AmputationHandler.lua @@ -76,7 +76,10 @@ function AmputationHandler:execute(damagePlayer) -- Set the data in modData - ModDataHandler.GetInstance():setCutLimb(self.limbName, false, false, false, surgeonFactor) + -- TODO This could be run on another player! + local modDataHandler = ModDataHandler.GetInstance() + modDataHandler:setCutLimb(self.limbName, false, false, false, surgeonFactor) + modDataHandler:apply() -- Give the player the correct amputation item ItemsHandler.DeleteOldAmputationItem(self.patient, self.limbName) @@ -86,7 +89,7 @@ function AmputationHandler:execute(damagePlayer) PlayerHandler.AddLocalAmputatedLimb(self.limbName) -- Set the highest amputation and caches them. - ISHealthPanel.GetHighestAmputation() + --ISHealthPanel.GetHighestAmputation() end ---Deletes the instance @@ -98,7 +101,7 @@ end function AmputationHandler.UpdateCicatrization() if ModDataHandler.GetInstance():getIsAnyLimbCut() == false then return end - + -- TODO Update cicatrization end return AmputationHandler \ No newline at end of file diff --git a/media/lua/client/TOC/Handlers/ItemsHandler.lua b/media/lua/client/TOC/Handlers/ItemsHandler.lua index 09bac36..6ff4a2d 100644 --- a/media/lua/client/TOC/Handlers/ItemsHandler.lua +++ b/media/lua/client/TOC/Handlers/ItemsHandler.lua @@ -109,7 +109,7 @@ function ISInventoryPane:refreshContainer() for i=1, #self.itemslist do local cItem = self.itemslist[i] if cItem and cItem.cat == "Amputation" then - TOC_DEBUG.print("current item is an amputation, removing it from the list") + TOC_DEBUG.print("Refreshing container - current item is an amputation, removing it from the list of the container") table.remove(self.itemslist, i) end end diff --git a/media/lua/client/TOC/Handlers/ModDataHandler.lua b/media/lua/client/TOC/Handlers/ModDataHandler.lua index ad5811d..00614d7 100644 --- a/media/lua/client/TOC/Handlers/ModDataHandler.lua +++ b/media/lua/client/TOC/Handlers/ModDataHandler.lua @@ -1,35 +1,67 @@ +local CommandsData = require("TOC/CommandsData") local StaticData = require("TOC/StaticData") ---------------- --- Handle all mod data related stuff ---@class ModDataHandler ----@field playerObj IsoPlayer +---@field username string ---@field tocData tocModData local ModDataHandler = {} ModDataHandler.instances = {} - -function ModDataHandler.AddExternalTocData(username, tocData) - -end - + -- Instead of requiring a player, to make it compatible in a MP env, we should require the table containing the modData for the init ---@param username string ----@param tocData tocModData +---@param isResetForced boolean? ---@return ModDataHandler -function ModDataHandler:new(username, tocData) +function ModDataHandler:new(username, isResetForced) local o = {} setmetatable(o, self) self.__index = self - -- 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.username = username + local key = CommandsData.GetKey(username) + + ModData.request(key) + o.tocData = ModData.get(key) + + if isResetForced or o.tocData == nil or o.tocData.Hand_L == nil or o.tocData.Hand_L.isCut == nil then + TOC_DEBUG.print("tocData in ModDataHandler for " .. username .. " is nil, creating it now") + self:setup(key) + end - o.tocData = tocData ModDataHandler.instances[username] = o return o end +---Setup a new toc mod data data class +---@param key string +function ModDataHandler:setup(key) + + ---@type tocModData + self.tocData = { + -- 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} + + -- Initialize limbs + for i=1, #StaticData.LIMBS_STRINGS do + local limbName = StaticData.LIMBS_STRINGS[i] + self.tocData[limbName] = {} + self:setLimbParams(StaticData.LIMBS_STRINGS[i], defaultParams, 0) + end + + -- Add it to global mod data + ModData.add(key, self.tocData) + + -- Transmit it to the server + ModData.transmit(key) +end ----------------- @@ -137,17 +169,23 @@ function ModDataHandler:setLimbParams(limbName, ampStatus, cicatrizationTime) end +--* Global Mod Data Apply *-- + +function ModDataHandler:apply() + ModData.transmit(CommandsData.GetKey(self.username)) +end + ---@param username string? ----@return ModDataHandler? +---@return ModDataHandler function ModDataHandler.GetInstance(username) + if username == nil then + username = getPlayer():getUsername() + end - if username == nil then username = getPlayer():getUsername() end - - if ModDataHandler.instances[username] ~= nil then - return ModDataHandler.instances[username] + if ModDataHandler.instances[username] == nil then + return ModDataHandler:new(username) else - return nil -- TODO This isn't exactly good - --return ModDataHandler:new(getPlayer()) + return ModDataHandler.instances[username] end end diff --git a/media/lua/client/TOC/Handlers/PlayerHandler.lua b/media/lua/client/TOC/Handlers/PlayerHandler.lua index 2d8a541..27f66b6 100644 --- a/media/lua/client/TOC/Handlers/PlayerHandler.lua +++ b/media/lua/client/TOC/Handlers/PlayerHandler.lua @@ -15,61 +15,36 @@ local StaticData = require("TOC/StaticData") ---@field playerObj IsoPlayer local PlayerHandler = {} +PlayerHandler.amputatedLimbs = {} + + ---Setup the Player Handler and modData ----@param _ nil ---@param playerObj IsoPlayer ---@param isForced boolean? -function PlayerHandler.InitializePlayer(_, playerObj, isForced) - PlayerHandler.SetupModData(playerObj, isForced) - PlayerHandler.playerObj = playerObj +function PlayerHandler.InitializePlayer(playerObj, isForced) + local username = playerObj:getUsername() + TOC_DEBUG.print("initializing " .. username) + local modDataHandler = ModDataHandler:new(username, isForced) + PlayerHandler.playerObj = playerObj -- Calculate amputated limbs at startup - PlayerHandler.amputatedLimbs = {} + PlayerHandler.amputatedLimbs[username] = {} for i=1, #StaticData.LIMBS_STRINGS do local limbName = StaticData.LIMBS_STRINGS[i] - if ModDataHandler.GetInstance():getIsCut(limbName) then - PlayerHandler.AddLocalAmputatedLimb(limbName) + if modDataHandler:getIsCut(limbName) then + PlayerHandler.AddLocalAmputatedLimb(username, limbName) end end -- Since isForced is used to reset an existing player data, we're gonna clean their ISHealthPanel table too if isForced then - ISHealthPanel.highestAmputations = {} + --ISHealthPanel.highestAmputations = {} local ItemsHandler = require("TOC/Handlers/ItemsHandler") ItemsHandler.DeleteAllOldAmputationItems(playerObj) 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) @@ -87,9 +62,9 @@ end ---Cache the currently amputated limbs ---@param limbName string -function PlayerHandler.AddLocalAmputatedLimb(limbName) - TOC_DEBUG.print("added " .. limbName .. " to known amputated limbs") - table.insert(PlayerHandler.amputatedLimbs, limbName) -- TODO This should be player specific, not generic +function PlayerHandler.AddLocalAmputatedLimb(username, limbName) + TOC_DEBUG.print("added " .. limbName .. " to known amputated limbs for " .. username) + table.insert(PlayerHandler.amputatedLimbs[username], limbName) -- TODO This should be player specific, not generic end --* Getters *-- @@ -108,16 +83,18 @@ function PlayerHandler.CheckInfection(character) -- This fucking event barely works. Bleeding seems to be the only thing that triggers it if character ~= getPlayer() then return end local bd = character:getBodyDamage() + local modDataHandler = ModDataHandler.GetInstance() + for i=1, #StaticData.LIMBS_STRINGS do local limbName = StaticData.LIMBS_STRINGS[i] local bptEnum = StaticData.BODYPARTSTYPES_ENUM[limbName] local bodyPart = bd:getBodyPart(bptEnum) if bodyPart:bitten() or bodyPart:IsInfected() then - if ModDataHandler.GetInstance():getIsCut(limbName) then + if modDataHandler:getIsCut(limbName) then bodyPart:SetBitten(false) else - ModDataHandler.GetInstance():setIsInfected(limbName, true) + modDataHandler:setIsInfected(limbName, true) end end end diff --git a/media/lua/client/TOC/Main.lua b/media/lua/client/TOC/Main.lua index b581b25..e78da25 100644 --- a/media/lua/client/TOC/Main.lua +++ b/media/lua/client/TOC/Main.lua @@ -40,10 +40,17 @@ function Main.Start() Main.SetupTraits() -- Starts initialization for local client - Events.OnCreatePlayer.Add(PlayerHandler.InitializePlayer) + Events.OnGameStart.Add(Main.Initialize) end + +function Main.Initialize() + local pl = getPlayer() + PlayerHandler.InitializePlayer(pl, false) +end + + --* Events *-- Events.OnGameBoot.Add(Main.Start) \ No newline at end of file diff --git a/media/lua/client/TOC/Tests.lua b/media/lua/client/TOC/Tests.lua index 249beeb..6f9c094 100644 --- a/media/lua/client/TOC/Tests.lua +++ b/media/lua/client/TOC/Tests.lua @@ -11,7 +11,7 @@ TestFramework.registerTestModule("Functionality", "PlayerHandler", function() local Tests = {} function Tests.InitializePlayer() local pl = getPlayer() - PlayerHandler.InitializePlayer(_, pl, true) + PlayerHandler.InitializePlayer(pl, true) end function Tests.SetMaxPerks() diff --git a/media/lua/client/TOC/UI/HealthPanel.lua b/media/lua/client/TOC/UI/HealthPanel.lua index c5a81a7..3035670 100644 --- a/media/lua/client/TOC/UI/HealthPanel.lua +++ b/media/lua/client/TOC/UI/HealthPanel.lua @@ -2,6 +2,7 @@ local PlayerHandler = require("TOC/Handlers/PlayerHandler") local StaticData = require("TOC/StaticData") local CommonMethods = require("TOC/CommonMethods") local ModDataHandler = require("TOC/Handlers/ModDataHandler") +local CommandsData = require("TOC/CommandsData") ---@diagnostic disable: duplicate-set-field local CutLimbHandler = require("TOC/UI/CutLimbInteractions") @@ -44,23 +45,35 @@ end --* Modification to handle visible amputation on the health menu *-- - - function ISHealthPanel:setHighestAmputation() + + --TOC_DEBUG.print("setHighestAmputation") + + if PlayerHandler.amputatedLimbs == nil or PlayerHandler.amputatedLimbs[self.tocUsername] then + TOC_DEBUG.print("PlayerHandler.amputatedLimbs is still nil or wasn't initialized for that player") + return + end + if self.otherPlayer ~= nil then self.tocUsername = self.otherPlayer:getUsername() else self.tocUsername = self.character:getUsername() end - ISHealthPanel.highestAmputations[self.tocUsername] = {} + self.highestAmputations[self.tocUsername] = {} + TOC_DEBUG.print("Searching highest amputations for " .. self.tocUsername) local modDataHandler = ModDataHandler.GetInstance(self.tocUsername) - if modDataHandler == nil then return end -- TODO Test this + if modDataHandler == nil then + TOC_DEBUG.print("ModDataHandler not found for " .. self.tocUsername) + return + end + for i=1, #PlayerHandler.amputatedLimbs do local limbName = PlayerHandler.amputatedLimbs[i] local index = CommonMethods.GetSide(limbName) if modDataHandler:getIsCut(limbName) and modDataHandler:getIsVisible(limbName) then - ISHealthPanel.highestAmputations[index] = limbName + TOC_DEBUG.print("found high amputation " .. limbName) + self.highestAmputations[self.tocUsername][index] = limbName end end end @@ -73,6 +86,7 @@ function ISHealthPanel:initialise() self.sexPl = "Male" end + self.highestAmputations = {} self:setHighestAmputation() og_ISHealthPanel_initialise(self) @@ -87,6 +101,12 @@ function ISHealthPanel:setOtherPlayer(playerObj) -- Since setOtherPlayer may be run after initialise (or always), we need to recheck it after. self:setHighestAmputation() + + -- TODO Request from server! + + -----@type askPlayerDataParams + --local params = {patientNum = playerObj:getOnlineID()} + --sendClientCommand(CommandsData.modules.TOC_SYNC, CommandsData.server.Sync.AskPlayerData, params) end @@ -96,20 +116,21 @@ function ISHealthPanel:render() -- TODO Handle another player health panel - if ISHealthPanel.highestAmputations[self.tocUsername] then + if self.highestAmputations ~= nil and self.highestAmputations[self.tocUsername] ~= nil then -- Left Texture - if ISHealthPanel.highestAmputations[self.tocUsername]["L"] then - local textureL = StaticData.HEALTH_PANEL_TEXTURES[self.sexPl][ISHealthPanel.highestAmputations["L"]] + if self.highestAmputations[self.tocUsername]["L"] then + local textureL = StaticData.HEALTH_PANEL_TEXTURES[self.sexPl][self.highestAmputations[self.tocUsername]["L"]] self:drawTexture(textureL, self.healthPanel.x/2 - 2, self.healthPanel.y/2, 1, 1, 0, 0) end -- Right Texture - if ISHealthPanel.highestAmputations[self.tocUsername]["R"] then - local textureR = StaticData.HEALTH_PANEL_TEXTURES[self.sexPl][ISHealthPanel.highestAmputations["R"]] + if self.highestAmputations["R"] then + local textureR = StaticData.HEALTH_PANEL_TEXTURES[self.sexPl][self.highestAmputations[self.tocUsername]["R"]] self:drawTexture(textureR, self.healthPanel.x/2 + 2, self.healthPanel.y/2, 1, 1, 0, 0) end else - ISHealthPanel.GetHighestAmputation(self.tocUsername) + self:setHighestAmputation() + --ISHealthPanel.GetHighestAmputation(self.tocUsername) end end diff --git a/media/lua/server/TOC/ServerDataCommands.lua b/media/lua/server/TOC/ServerDataCommands.lua new file mode 100644 index 0000000..d09ffe0 --- /dev/null +++ b/media/lua/server/TOC/ServerDataCommands.lua @@ -0,0 +1,54 @@ +-- TODO Switch EVERYTHING to global mod data + +local CommandsData = require("TOC/CommandsData") + +local ServerDataCommands = {} +local moduleName = "test_sync" + + +local function PrintModDataTable(key, table) + print("Received key: " .. key) +end + + +Events.OnReceiveGlobalModData.Add(PrintModDataTable) + + + +-- TODO Consider delays + + + + +-- TODO Use transmit from client +-- ---comment +-- ---@param playerObj IsoPlayer +-- ---@param args any +-- function ServerDataCommands.AddTable(playerObj, args) +-- ModData.add(GetKey(playerObj), args.tocData) +-- end + + +-- function ServerDataCommands.GetTable(playerObj, args) +-- local requestedPlayer = getSpecificPlayer(args.playerNum) +-- local data = ModData.get(CommandsData.GetKey(requestedPlayer)) + +-- -- TODO Request from that client again just to be sure that it's synced? + +-- sendServerCommand() +-- end + + + +------------------------------ + +-- local function OnClientDataCommand(module, command, playerObj, args) +-- if module == moduleName and ServerDataCommands[command] then +-- ServerDataCommands[command](playerObj, args) +-- end +-- end + +-- Events.OnClientCommand.Add(OnClientDataCommand) + + + diff --git a/media/lua/server/TOC/ServerSyncCommands.lua b/media/lua/server/TOC/ServerSyncCommands.lua index 43b8618..96892a8 100644 --- a/media/lua/server/TOC/ServerSyncCommands.lua +++ b/media/lua/server/TOC/ServerSyncCommands.lua @@ -10,20 +10,25 @@ local moduleName = CommandsData.modules.TOC_SYNC ---A client has asked the server to ask another client to send its toc mod data ---@param surgeonPl IsoPlayer ----@param args {patientNum : number} +---@param args askPlayerDataParams function ServerSyncCommands.AskPlayerData(surgeonPl, args) local patientPl = getSpecificPlayer(args.patientNum) - local surgeonNum = surgeonPl:getOnlineID() - sendServerCommand(patientPl, moduleName, CommandsData.client.Sync.SendPlayerData, {surgeonNum = surgeonNum}) + + ---@type sendPlayerDataParams + local params = {surgeonNum = surgeonPl:getOnlineID()} + sendServerCommand(patientPl, moduleName, CommandsData.client.Sync.SendPlayerData, params) end ---Relay the toc mod data from a certain player to another one ---@param patientPl IsoPlayer ----@param args {surgeonNum : number, tocData : tocModData} +---@param args relayPlayerDataParams function ServerSyncCommands.RelayPlayerData(patientPl, args) local surgeonPl = getSpecificPlayer(args.surgeonNum) local patientNum = patientPl:getOnlineID() - sendServerCommand(surgeonPl, moduleName, CommandsData.client.Sync.ReceivePlayerData, {patientNum = patientNum, tocData = args.tocData}) + + ---@type receivePlayerDataParams + local params = {patientNum = patientNum, tocData = args.tocData} + sendServerCommand(surgeonPl, moduleName, CommandsData.client.Sync.ReceivePlayerData, params) end ------------------------------ diff --git a/media/lua/shared/NPCs/TOC_BodyLocations.lua b/media/lua/shared/TOC/BodyLocations.lua similarity index 97% rename from media/lua/shared/NPCs/TOC_BodyLocations.lua rename to media/lua/shared/TOC/BodyLocations.lua index eed5c37..a2586ee 100644 --- a/media/lua/shared/NPCs/TOC_BodyLocations.lua +++ b/media/lua/shared/TOC/BodyLocations.lua @@ -1,4 +1,5 @@ -- TODO This part is still one of the weakest and we don't have a better solution yet +require("TOC/Debug") local function AddBodyLocationBefore(newLocation, moveToLocation) local group = BodyLocations.getGroup("Human") diff --git a/media/lua/shared/TOC/CommandsData.lua b/media/lua/shared/TOC/CommandsData.lua index e63d725..41458dd 100644 --- a/media/lua/shared/TOC/CommandsData.lua +++ b/media/lua/shared/TOC/CommandsData.lua @@ -1,3 +1,5 @@ +local StaticData = require("TOC/StaticData") + local CommandsData = {} @@ -8,16 +10,23 @@ CommandsData.modules = { CommandsData.client = { Sync = { - SendPlayerData = "SendPlayerData", - ReceivePlayerData = "ReceivePlayerData" + SendPlayerData = "SendPlayerData", ---@alias sendPlayerDataParams {surgeonNum : number} + ReceivePlayerData = "ReceivePlayerData" ---@alias receivePlayerDataParams {patientNum : number, tocData : tocModData} } } CommandsData.server = { Sync = { - AskPlayerData = "AskPlayerData", - RelayPlayerData = "RelayPlayerData" + AskPlayerData = "AskPlayerData", ---@alias askPlayerDataParams {patientNum : number} + RelayPlayerData = "RelayPlayerData" ---@alias relayPlayerDataParams {surgeonNum : number, tocData : tocModData} } } +---Get the correct key for that particular player to be used in the global mod data table +---@param username string +---@return string +function CommandsData.GetKey(username) + return StaticData.MOD_NAME .. "_" .. username +end + return CommandsData \ No newline at end of file diff --git a/media/lua/client/TOC/Debug.lua b/media/lua/shared/TOC/Debug.lua similarity index 100% rename from media/lua/client/TOC/Debug.lua rename to media/lua/shared/TOC/Debug.lua