From 3e8413c6b7e0286c7ce68a5740557f699ba7b691 Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Sat, 18 Feb 2023 15:03:53 +0100 Subject: [PATCH 1/3] #NET - further ado --- Moose Development/Moose/Wrapper/Net.lua | 32 ++++++++++++++++++------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/Moose Development/Moose/Wrapper/Net.lua b/Moose Development/Moose/Wrapper/Net.lua index a12d580ca..300775eb9 100644 --- a/Moose Development/Moose/Wrapper/Net.lua +++ b/Moose Development/Moose/Wrapper/Net.lua @@ -31,7 +31,7 @@ do -- @field #NET NET = { ClassName = "NET", - Version = "0.0.5", + Version = "0.0.6", BlockTime = 600, BlockedPilots = {}, BlockedUCIDs = {}, @@ -153,45 +153,56 @@ function NET:_EventHandler(EventData) -- Get PlayerName local name = data.IniPlayerName and data.IniPlayerName or data.IniUnit:GetPlayerName() local ucid = self:GetPlayerUCID(nil,name) - self:T(self.lid.."Event for: "..name.." | UCID: "..ucid) + local PlayerID = self:GetPlayerIDByName(name) or "none" + local TNow = timer.getTime() + self:I(self.lid.."Event for: "..name.." | UCID: "..ucid) + if self.BlockedPilots[name] then + self:I(self.lid.."Pilot "..name.." ID "..PlayerID.." Blocked for another "..self.BlockedPilots[name]-timer.getTime().." seconds!") + end + if self.BlockedUCIDs[ucid] then + self:I(self.lid.."Pilot "..name.." ID "..PlayerID.." Blocked for another "..self.BlockedUCIDs[ucid]-timer.getTime().." seconds!") + end -- Joining if data.id == EVENTS.PlayerEnterUnit or data.id == EVENTS.PlayerEnterAircraft then + self:I(self.lid.."Pilot Joining: "..name.." | UCID: "..ucid) -- Check for known pilots - local TNow = timer.getTime() if self.BlockedPilots[name] and TNow < self.BlockedPilots[name] then - -- block pilot by name - local PlayerID = self:GetPlayerIDByName(name) + -- block pilot by name if PlayerID and tonumber(PlayerID) ~= 1 then local outcome = net.force_player_slot(tonumber(PlayerID), 0, '' ) end elseif self.BlockedUCIDs[ucid] and TNow < self.BlockedUCIDs[ucid] then -- block pilot by ucid - local PlayerID = self:GetPlayerIDByName(name) if PlayerID and tonumber(PlayerID) ~= 1 then local outcome = net.force_player_slot(tonumber(PlayerID), 0, '' ) end else self.KnownPilots[name] = true - self.BlockedPilots[name] = nil - self.BlockedUCIDs[ucid] = nil + if (self.BlockedUCIDs[ucid] and TNow >= self.BlockedUCIDs[ucid]) or (self.BlockedPilots[name] and TNow >= self.BlockedPilots[name]) then + self.BlockedPilots[name] = nil + self.BlockedUCIDs[ucid] = nil + end self:__PlayerJoined(1,data.IniUnit,name) return self end end -- Leaving if data.id == EVENTS.PlayerLeaveUnit and self.KnownPilots[name] then + self:I(self.lid.."Pilot Leaving: "..name.." | UCID: "..ucid) self:__PlayerLeft(1,data.IniUnit,name) self.KnownPilots[name] = false return self end -- Ejected if data.id == EVENTS.Ejection and self.KnownPilots[name] then + self:I(self.lid.."Pilot Ejecting: "..name.." | UCID: "..ucid) self:__PlayerEjected(1,data.IniUnit,name) self.KnownPilots[name] = false return self end -- Dead, Crash, Suicide if (data.id == EVENTS.PilotDead or data.id == EVENTS.SelfKillPilot or data.id == EVENTS.Crash) and self.KnownPilots[name] then + self:I(self.lid.."Pilot Dead: "..name.." | UCID: "..ucid) self:__PlayerDied(1,data.IniUnit,name) self.KnownPilots[name] = false return self @@ -208,8 +219,9 @@ end -- @param #string Message (optional) Message to be sent via chat. -- @return #NET self function NET:BlockPlayer(Client,PlayerName,Seconds,Message) + self:I({PlayerName,Seconds,Message}) local name = PlayerName - if Client then + if Client and (not PlayerName) then name = Client:GetPlayerName() elseif PlayerName then name = PlayerName @@ -310,8 +322,10 @@ end function NET:GetPlayerIDByName(Name) if not Name then return nil end local playerList = self:GetPlayerList() + self:I({playerList}) for i=1,#playerList do local playerName = net.get_name(i) + self:I({playerName}) if playerName == Name then return playerList[i] end From 7dc239f506bb010bd363bc86201b88f2a858db8a Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Sun, 19 Feb 2023 12:31:08 +0100 Subject: [PATCH 2/3] Added CLIENT:FindByPlayerName(Name) NET - slot blocker comments in log removed --- Moose Development/Moose/Wrapper/Client.lua | 302 +++++++++++---------- Moose Development/Moose/Wrapper/Net.lua | 31 ++- 2 files changed, 178 insertions(+), 155 deletions(-) diff --git a/Moose Development/Moose/Wrapper/Client.lua b/Moose Development/Moose/Wrapper/Client.lua index 12f2baa13..01dce4828 100644 --- a/Moose Development/Moose/Wrapper/Client.lua +++ b/Moose Development/Moose/Wrapper/Client.lua @@ -62,15 +62,15 @@ -- -- @field #CLIENT CLIENT = { - ClassName = "CLIENT", - ClientName = nil, - ClientAlive = false, - ClientTransport = false, - ClientBriefingShown = false, - _Menus = {}, - _Tasks = {}, - Messages = {}, - Players = {}, + ClassName = "CLIENT", + ClientName = nil, + ClientAlive = false, + ClientTransport = false, + ClientBriefingShown = false, + _Menus = {}, + _Tasks = {}, + Messages = {}, + Players = {}, } @@ -95,6 +95,22 @@ function CLIENT:Find(DCSUnit, Error) end end +--- Finds a CLIENT from the _DATABASE using the relevant player name. +-- @param #CLIENT self +-- @param #string Name Name of the player +-- @return #CLIENT or nil if not found +function CLIENT:FindByPlayerName(Name) + + local foundclient = nil + _DATABASE:ForEachClient( + function(client) + if client:GetPlayerName() == Name then + foundclient = client + end + end + ) + return foundclient +end --- Finds a CLIENT from the _DATABASE using the relevant Client Unit Name. -- As an optional parameter, a briefing text can be given also. @@ -105,13 +121,13 @@ end -- @return #CLIENT -- @usage -- -- Create new Clients. --- local Mission = MISSIONSCHEDULER.AddMission( 'Russia Transport Troops SA-6', 'Operational', 'Transport troops from the control center to one of the SA-6 SAM sites to activate their operation.', 'Russia' ) --- Mission:AddGoal( DeploySA6TroopsGoal ) +-- local Mission = MISSIONSCHEDULER.AddMission( 'Russia Transport Troops SA-6', 'Operational', 'Transport troops from the control center to one of the SA-6 SAM sites to activate their operation.', 'Russia' ) +-- Mission:AddGoal( DeploySA6TroopsGoal ) -- --- Mission:AddClient( CLIENT:FindByName( 'RU MI-8MTV2*HOT-Deploy Troops 1' ):Transport() ) --- Mission:AddClient( CLIENT:FindByName( 'RU MI-8MTV2*RAMP-Deploy Troops 3' ):Transport() ) --- Mission:AddClient( CLIENT:FindByName( 'RU MI-8MTV2*HOT-Deploy Troops 2' ):Transport() ) --- Mission:AddClient( CLIENT:FindByName( 'RU MI-8MTV2*RAMP-Deploy Troops 4' ):Transport() ) +-- Mission:AddClient( CLIENT:FindByName( 'RU MI-8MTV2*HOT-Deploy Troops 1' ):Transport() ) +-- Mission:AddClient( CLIENT:FindByName( 'RU MI-8MTV2*RAMP-Deploy Troops 3' ):Transport() ) +-- Mission:AddClient( CLIENT:FindByName( 'RU MI-8MTV2*HOT-Deploy Troops 2' ):Transport() ) +-- Mission:AddClient( CLIENT:FindByName( 'RU MI-8MTV2*RAMP-Deploy Troops 4' ):Transport() ) function CLIENT:FindByName( ClientName, ClientBriefing, Error ) -- Client @@ -124,7 +140,7 @@ function CLIENT:FindByName( ClientName, ClientBriefing, Error ) ClientFound.MessageSwitch = true - return ClientFound + return ClientFound end if not Error then @@ -262,8 +278,8 @@ end -- @param #CLIENT self -- @param #string ClientName Name of the Group as defined within the Mission Editor. The Group must have a Unit with the type Client. function CLIENT:Reset( ClientName ) - self:F() - self._Menus = {} + self:F() + self._Menus = {} end -- Is Functions @@ -347,85 +363,85 @@ function CLIENT:GetDCSGroup() self:F3() -- local ClientData = Group.getByName( self.ClientName ) --- if ClientData and ClientData:isExist() then --- self:T( self.ClientName .. " : group found!" ) --- return ClientData --- else --- return nil --- end +-- if ClientData and ClientData:isExist() then +-- self:T( self.ClientName .. " : group found!" ) +-- return ClientData +-- else +-- return nil +-- end local ClientUnit = Unit.getByName( self.ClientName ) - local CoalitionsData = { AlivePlayersRed = coalition.getPlayers( coalition.side.RED ), AlivePlayersBlue = coalition.getPlayers( coalition.side.BLUE ) } - - for CoalitionId, CoalitionData in pairs( CoalitionsData ) do - self:T3( { "CoalitionData:", CoalitionData } ) - for UnitId, UnitData in pairs( CoalitionData ) do - self:T3( { "UnitData:", UnitData } ) - if UnitData and UnitData:isExist() then + local CoalitionsData = { AlivePlayersRed = coalition.getPlayers( coalition.side.RED ), AlivePlayersBlue = coalition.getPlayers( coalition.side.BLUE ) } + + for CoalitionId, CoalitionData in pairs( CoalitionsData ) do + self:T3( { "CoalitionData:", CoalitionData } ) + for UnitId, UnitData in pairs( CoalitionData ) do + self:T3( { "UnitData:", UnitData } ) + if UnitData and UnitData:isExist() then --self:F(self.ClientName) if ClientUnit then - local ClientGroup = ClientUnit:getGroup() - - if ClientGroup then - self:T3( "ClientGroup = " .. self.ClientName ) - - if ClientGroup:isExist() and UnitData:getGroup():isExist() then - - if ClientGroup:getID() == UnitData:getGroup():getID() then - self:T3( "Normal logic" ) - self:T3( self.ClientName .. " : group found!" ) + local ClientGroup = ClientUnit:getGroup() + + if ClientGroup then + self:T3( "ClientGroup = " .. self.ClientName ) + + if ClientGroup:isExist() and UnitData:getGroup():isExist() then + + if ClientGroup:getID() == UnitData:getGroup():getID() then + self:T3( "Normal logic" ) + self:T3( self.ClientName .. " : group found!" ) self.ClientGroupID = ClientGroup:getID() - self.ClientGroupName = ClientGroup:getName() - return ClientGroup - end - - else - - -- Now we need to resolve the bugs in DCS 1.5 ... - -- Consult the database for the units of the Client Group. (ClientGroup:getUnits() returns nil) - self:T3( "Bug 1.5 logic" ) - - local ClientGroupTemplate = _DATABASE.Templates.Units[self.ClientName].GroupTemplate - - self.ClientGroupID = ClientGroupTemplate.groupId - - self.ClientGroupName = _DATABASE.Templates.Units[self.ClientName].GroupName - - self:T3( self.ClientName .. " : group found in bug 1.5 resolvement logic!" ) - return ClientGroup - - end - -- else - -- error( "Client " .. self.ClientName .. " not found!" ) - end - else - --self:F( { "Client not found!", self.ClientName } ) - end - end - end - end - - -- For non player clients - if ClientUnit then - local ClientGroup = ClientUnit:getGroup() - if ClientGroup then - self:T3( "ClientGroup = " .. self.ClientName ) - if ClientGroup:isExist() then - self:T3( "Normal logic" ) - self:T3( self.ClientName .. " : group found!" ) - return ClientGroup - end - end + self.ClientGroupName = ClientGroup:getName() + return ClientGroup + end + + else + + -- Now we need to resolve the bugs in DCS 1.5 ... + -- Consult the database for the units of the Client Group. (ClientGroup:getUnits() returns nil) + self:T3( "Bug 1.5 logic" ) + + local ClientGroupTemplate = _DATABASE.Templates.Units[self.ClientName].GroupTemplate + + self.ClientGroupID = ClientGroupTemplate.groupId + + self.ClientGroupName = _DATABASE.Templates.Units[self.ClientName].GroupName + + self:T3( self.ClientName .. " : group found in bug 1.5 resolvement logic!" ) + return ClientGroup + + end + -- else + -- error( "Client " .. self.ClientName .. " not found!" ) + end + else + --self:F( { "Client not found!", self.ClientName } ) + end + end + end end - - -- Nothing could be found :( - self.ClientGroupID = nil - self.ClientGroupName = nil - - return nil + + -- For non player clients + if ClientUnit then + local ClientGroup = ClientUnit:getGroup() + if ClientGroup then + self:T3( "ClientGroup = " .. self.ClientName ) + if ClientGroup:isExist() then + self:T3( "Normal logic" ) + self:T3( self.ClientName .. " : group found!" ) + return ClientGroup + end + end + end + + -- Nothing could be found :( + self.ClientGroupID = nil + self.ClientGroupName = nil + + return nil end @@ -437,7 +453,7 @@ function CLIENT:GetClientGroupID() -- This updates the ID. self:GetDCSGroup() - return self.ClientGroupID + return self.ClientGroupID end @@ -449,7 +465,7 @@ function CLIENT:GetClientGroupName() -- This updates the group name. self:GetDCSGroup() - return self.ClientGroupName + return self.ClientGroupName end --- Returns the UNIT of the CLIENT. @@ -458,23 +474,23 @@ end function CLIENT:GetClientGroupUnit() self:F2() - local ClientDCSUnit = Unit.getByName( self.ClientName ) + local ClientDCSUnit = Unit.getByName( self.ClientName ) self:T( self.ClientDCSUnit ) - if ClientDCSUnit and ClientDCSUnit:isExist() then - local ClientUnit=_DATABASE:FindUnit( self.ClientName ) - return ClientUnit - end - - return nil + if ClientDCSUnit and ClientDCSUnit:isExist() then + local ClientUnit=_DATABASE:FindUnit( self.ClientName ) + return ClientUnit + end + + return nil end --- Returns the DCSUnit of the CLIENT. -- @param #CLIENT self -- @return DCS#Unit function CLIENT:GetClientGroupDCSUnit() - self:F2() + self:F2() local ClientDCSUnit = Unit.getByName( self.ClientName ) @@ -489,29 +505,29 @@ end -- @param #CLIENT self -- @return #boolean true is a transport. function CLIENT:IsTransport() - self:F() - return self.ClientTransport + self:F() + return self.ClientTransport end --- Shows the @{AI.AI_Cargo#CARGO} contained within the CLIENT to the player as a message. -- The @{AI.AI_Cargo#CARGO} is shown using the @{Core.Message#MESSAGE} distribution system. -- @param #CLIENT self function CLIENT:ShowCargo() - self:F() + self:F() - local CargoMsg = "" + local CargoMsg = "" - for CargoName, Cargo in pairs( CARGOS ) do - if self == Cargo:IsLoadedInClient() then - CargoMsg = CargoMsg .. Cargo.CargoName .. " Type:" .. Cargo.CargoType .. " Weight: " .. Cargo.CargoWeight .. "\n" - end - end + for CargoName, Cargo in pairs( CARGOS ) do + if self == Cargo:IsLoadedInClient() then + CargoMsg = CargoMsg .. Cargo.CargoName .. " Type:" .. Cargo.CargoType .. " Weight: " .. Cargo.CargoWeight .. "\n" + end + end - if CargoMsg == "" then - CargoMsg = "empty" - end + if CargoMsg == "" then + CargoMsg = "empty" + end - self:Message( CargoMsg, 15, "Co-Pilot: Cargo Status", 30 ) + self:Message( CargoMsg, 15, "Co-Pilot: Cargo Status", 30 ) end @@ -526,39 +542,39 @@ end -- @param #number MessageInterval is the interval in seconds between the display of the @{Core.Message#MESSAGE} when the CLIENT is in the air. -- @param #string MessageID is the identifier of the message when displayed with intervals. function CLIENT:Message( Message, MessageDuration, MessageCategory, MessageInterval, MessageID ) - self:F( { Message, MessageDuration, MessageCategory, MessageInterval } ) + self:F( { Message, MessageDuration, MessageCategory, MessageInterval } ) - if self.MessageSwitch == true then - if MessageCategory == nil then - MessageCategory = "Messages" - end - if MessageID ~= nil then - if self.Messages[MessageID] == nil then - self.Messages[MessageID] = {} - self.Messages[MessageID].MessageId = MessageID - self.Messages[MessageID].MessageTime = timer.getTime() - self.Messages[MessageID].MessageDuration = MessageDuration - if MessageInterval == nil then - self.Messages[MessageID].MessageInterval = 600 - else - self.Messages[MessageID].MessageInterval = MessageInterval - end - MESSAGE:New( Message, MessageDuration, MessageCategory ):ToClient( self ) - else - if self:GetClientGroupDCSUnit() and not self:GetClientGroupDCSUnit():inAir() then - if timer.getTime() - self.Messages[MessageID].MessageTime >= self.Messages[MessageID].MessageDuration + 10 then - MESSAGE:New( Message, MessageDuration , MessageCategory):ToClient( self ) - self.Messages[MessageID].MessageTime = timer.getTime() - end - else - if timer.getTime() - self.Messages[MessageID].MessageTime >= self.Messages[MessageID].MessageDuration + self.Messages[MessageID].MessageInterval then - MESSAGE:New( Message, MessageDuration, MessageCategory ):ToClient( self ) - self.Messages[MessageID].MessageTime = timer.getTime() - end - end - end - else + if self.MessageSwitch == true then + if MessageCategory == nil then + MessageCategory = "Messages" + end + if MessageID ~= nil then + if self.Messages[MessageID] == nil then + self.Messages[MessageID] = {} + self.Messages[MessageID].MessageId = MessageID + self.Messages[MessageID].MessageTime = timer.getTime() + self.Messages[MessageID].MessageDuration = MessageDuration + if MessageInterval == nil then + self.Messages[MessageID].MessageInterval = 600 + else + self.Messages[MessageID].MessageInterval = MessageInterval + end + MESSAGE:New( Message, MessageDuration, MessageCategory ):ToClient( self ) + else + if self:GetClientGroupDCSUnit() and not self:GetClientGroupDCSUnit():inAir() then + if timer.getTime() - self.Messages[MessageID].MessageTime >= self.Messages[MessageID].MessageDuration + 10 then + MESSAGE:New( Message, MessageDuration , MessageCategory):ToClient( self ) + self.Messages[MessageID].MessageTime = timer.getTime() + end + else + if timer.getTime() - self.Messages[MessageID].MessageTime >= self.Messages[MessageID].MessageDuration + self.Messages[MessageID].MessageInterval then + MESSAGE:New( Message, MessageDuration, MessageCategory ):ToClient( self ) + self.Messages[MessageID].MessageTime = timer.getTime() + end + end + end + else MESSAGE:New( Message, MessageDuration, MessageCategory ):ToClient( self ) end - end + end end diff --git a/Moose Development/Moose/Wrapper/Net.lua b/Moose Development/Moose/Wrapper/Net.lua index 300775eb9..4f28e8a6d 100644 --- a/Moose Development/Moose/Wrapper/Net.lua +++ b/Moose Development/Moose/Wrapper/Net.lua @@ -31,7 +31,7 @@ do -- @field #NET NET = { ClassName = "NET", - Version = "0.0.6", + Version = "0.0.7", BlockTime = 600, BlockedPilots = {}, BlockedUCIDs = {}, @@ -154,17 +154,18 @@ function NET:_EventHandler(EventData) local name = data.IniPlayerName and data.IniPlayerName or data.IniUnit:GetPlayerName() local ucid = self:GetPlayerUCID(nil,name) local PlayerID = self:GetPlayerIDByName(name) or "none" + local PlayerSide, PlayerSlot = self:GetSlot(data.IniUnit) local TNow = timer.getTime() - self:I(self.lid.."Event for: "..name.." | UCID: "..ucid) + self:T(self.lid.."Event for: "..name.." | UCID: "..ucid) if self.BlockedPilots[name] then - self:I(self.lid.."Pilot "..name.." ID "..PlayerID.." Blocked for another "..self.BlockedPilots[name]-timer.getTime().." seconds!") + self:T(self.lid.."Pilot "..name.." ID "..PlayerID.." Blocked for another "..self.BlockedPilots[name]-timer.getTime().." seconds!") end if self.BlockedUCIDs[ucid] then - self:I(self.lid.."Pilot "..name.." ID "..PlayerID.." Blocked for another "..self.BlockedUCIDs[ucid]-timer.getTime().." seconds!") + self:T(self.lid.."Pilot "..name.." ID "..PlayerID.." Blocked for another "..self.BlockedUCIDs[ucid]-timer.getTime().." seconds!") end -- Joining if data.id == EVENTS.PlayerEnterUnit or data.id == EVENTS.PlayerEnterAircraft then - self:I(self.lid.."Pilot Joining: "..name.." | UCID: "..ucid) + self:T(self.lid.."Pilot Joining: "..name.." | UCID: "..ucid) -- Check for known pilots if self.BlockedPilots[name] and TNow < self.BlockedPilots[name] then -- block pilot by name @@ -177,7 +178,13 @@ function NET:_EventHandler(EventData) local outcome = net.force_player_slot(tonumber(PlayerID), 0, '' ) end else - self.KnownPilots[name] = true + self.KnownPilots[name] = { + name = name, + ucid = ucid, + id = PlayerID, + side = PlayerSide, + slot = PlayerSlot, + } if (self.BlockedUCIDs[ucid] and TNow >= self.BlockedUCIDs[ucid]) or (self.BlockedPilots[name] and TNow >= self.BlockedPilots[name]) then self.BlockedPilots[name] = nil self.BlockedUCIDs[ucid] = nil @@ -188,21 +195,21 @@ function NET:_EventHandler(EventData) end -- Leaving if data.id == EVENTS.PlayerLeaveUnit and self.KnownPilots[name] then - self:I(self.lid.."Pilot Leaving: "..name.." | UCID: "..ucid) + self:T(self.lid.."Pilot Leaving: "..name.." | UCID: "..ucid) self:__PlayerLeft(1,data.IniUnit,name) self.KnownPilots[name] = false return self end -- Ejected if data.id == EVENTS.Ejection and self.KnownPilots[name] then - self:I(self.lid.."Pilot Ejecting: "..name.." | UCID: "..ucid) + self:T(self.lid.."Pilot Ejecting: "..name.." | UCID: "..ucid) self:__PlayerEjected(1,data.IniUnit,name) self.KnownPilots[name] = false return self end -- Dead, Crash, Suicide if (data.id == EVENTS.PilotDead or data.id == EVENTS.SelfKillPilot or data.id == EVENTS.Crash) and self.KnownPilots[name] then - self:I(self.lid.."Pilot Dead: "..name.." | UCID: "..ucid) + self:T(self.lid.."Pilot Dead: "..name.." | UCID: "..ucid) self:__PlayerDied(1,data.IniUnit,name) self.KnownPilots[name] = false return self @@ -219,7 +226,7 @@ end -- @param #string Message (optional) Message to be sent via chat. -- @return #NET self function NET:BlockPlayer(Client,PlayerName,Seconds,Message) - self:I({PlayerName,Seconds,Message}) + self:T({PlayerName,Seconds,Message}) local name = PlayerName if Client and (not PlayerName) then name = Client:GetPlayerName() @@ -322,10 +329,10 @@ end function NET:GetPlayerIDByName(Name) if not Name then return nil end local playerList = self:GetPlayerList() - self:I({playerList}) + self:T({playerList}) for i=1,#playerList do local playerName = net.get_name(i) - self:I({playerName}) + self:T({playerName}) if playerName == Name then return playerList[i] end From 6c1abddb1e14b121ef21e014405d4845915bdbec Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Sun, 19 Feb 2023 17:16:00 +0100 Subject: [PATCH 3/3] #NET added a couple of functions --- Moose Development/Moose/Wrapper/Net.lua | 287 +++++++++++++++++++++--- 1 file changed, 252 insertions(+), 35 deletions(-) diff --git a/Moose Development/Moose/Wrapper/Net.lua b/Moose Development/Moose/Wrapper/Net.lua index 4f28e8a6d..8f394eee7 100644 --- a/Moose Development/Moose/Wrapper/Net.lua +++ b/Moose Development/Moose/Wrapper/Net.lua @@ -5,7 +5,8 @@ -- === -- -- ### Author: **applevangelist** --- +-- # Last Update Feb 2023 +-- -- === -- -- @module Wrapper.Net @@ -23,18 +24,30 @@ do -- @field #string BlockMessage -- @field #string UnblockMessage -- @field #table BlockedUCIDs +-- @field #table BlockedSlots +-- @field #table BlockedSides -- @extends Core.Fsm#FSM +--- +-- @type NET.PlayerData +-- @field #string name +-- @field #string ucid +-- @field #number id +-- @field #number side +-- @field #number slot + --- Encapsules multiplayer environment scripting functions from [net](https://wiki.hoggitworld.com/view/DCS_singleton_net) -- with some added FSM functions and options to block/unblock players in MP environments. -- -- @field #NET NET = { ClassName = "NET", - Version = "0.0.7", + Version = "0.1.0", BlockTime = 600, BlockedPilots = {}, BlockedUCIDs = {}, + BlockedSides = {}, + BlockedSlots = {}, KnownPilots = {}, BlockMessage = nil, UnblockMessage = nil, @@ -54,26 +67,20 @@ function NET:New() self:SetBlockMessage() self:SetUnblockMessage() - self:HandleEvent(EVENTS.PlayerEnterUnit,self._EventHandler) - self:HandleEvent(EVENTS.PlayerEnterAircraft,self._EventHandler) - self:HandleEvent(EVENTS.PlayerLeaveUnit,self._EventHandler) - self:HandleEvent(EVENTS.PilotDead,self._EventHandler) - self:HandleEvent(EVENTS.Ejection,self._EventHandler) - self:HandleEvent(EVENTS.Crash,self._EventHandler) - self:HandleEvent(EVENTS.SelfKillPilot,self._EventHandler) - -- Start State. - self:SetStartState("Running") + self:SetStartState("Stopped") -- Add FSM transitions. -- From State --> Event --> To State - self:AddTransition("*", "Run", "Running") -- Start FSM. + self:AddTransition("Stopped", "Run", "Running") -- Start FSM. self:AddTransition("*", "PlayerJoined", "*") self:AddTransition("*", "PlayerLeft", "*") self:AddTransition("*", "PlayerDied", "*") self:AddTransition("*", "PlayerEjected", "*") self:AddTransition("*", "PlayerBlocked", "*") self:AddTransition("*", "PlayerUnblocked", "*") + self:AddTransition("*", "Status", "*") + self:AddTransition("*", "Stop", "Stopped") self.lid = string.format("NET %s | ",self.Version) @@ -138,9 +145,45 @@ function NET:New() -- @param #string Name Name of unblocked Pilot. -- @return #NET self + self:Run() + return self end +--- [Internal] Check any blockers +-- @param #NET self +-- @param #string UCID +-- @param #string Name +-- @param #number PlayerID +-- @param #number PlayerSide +-- @param #string PlayerSlot +-- @return #boolean IsBlocked +function NET:IsAnyBlocked(UCID,Name,PlayerID,PlayerSide,PlayerSlot) + local blocked = false + local TNow = timer.getTime() + -- UCID + if UCID and self.BlockedUCIDs[UCID] and TNow < self.BlockedUCIDs[UCID] then + return true + end + -- ID/Name + if PlayerID and not Name then + Name = self:GetPlayerIDByName(Name) + end + -- Name + if Name and self.BlockedPilots[Name] and TNow < self.BlockedPilots[Name] then + return true + end + -- Side + if PlayerSide and self.BlockedSides[PlayerSide] and TNow < self.BlockedSides[PlayerSide] then + return true + end + -- Slot + if PlayerSlot and self.BlockedSlots[PlayerSlot] and TNow < self.BlockedSlots[PlayerSlot] then + return true + end + return blocked +end + --- [Internal] Event Handler -- @param #NET self -- @param Core.Event#EVENTDATA EventData @@ -150,33 +193,25 @@ function NET:_EventHandler(EventData) self:T2({Event = EventData.id}) local data = EventData -- Core.Event#EVENTDATA EventData if data.id and data.IniUnit and (data.IniPlayerName or data.IniUnit:GetPlayerName()) then - -- Get PlayerName + + -- Get Player Data local name = data.IniPlayerName and data.IniPlayerName or data.IniUnit:GetPlayerName() local ucid = self:GetPlayerUCID(nil,name) local PlayerID = self:GetPlayerIDByName(name) or "none" local PlayerSide, PlayerSlot = self:GetSlot(data.IniUnit) local TNow = timer.getTime() + self:T(self.lid.."Event for: "..name.." | UCID: "..ucid) - if self.BlockedPilots[name] then - self:T(self.lid.."Pilot "..name.." ID "..PlayerID.." Blocked for another "..self.BlockedPilots[name]-timer.getTime().." seconds!") - end - if self.BlockedUCIDs[ucid] then - self:T(self.lid.."Pilot "..name.." ID "..PlayerID.." Blocked for another "..self.BlockedUCIDs[ucid]-timer.getTime().." seconds!") - end + -- Joining if data.id == EVENTS.PlayerEnterUnit or data.id == EVENTS.PlayerEnterAircraft then self:T(self.lid.."Pilot Joining: "..name.." | UCID: "..ucid) - -- Check for known pilots - if self.BlockedPilots[name] and TNow < self.BlockedPilots[name] then - -- block pilot by name - if PlayerID and tonumber(PlayerID) ~= 1 then - local outcome = net.force_player_slot(tonumber(PlayerID), 0, '' ) - end - elseif self.BlockedUCIDs[ucid] and TNow < self.BlockedUCIDs[ucid] then - -- block pilot by ucid - if PlayerID and tonumber(PlayerID) ~= 1 then - local outcome = net.force_player_slot(tonumber(PlayerID), 0, '' ) - end + -- Check for blockages + local blocked = self:IsAnyBlocked(ucid,name,PlayerID,PlayerSide,PlayerSlot) + + if blocked and PlayerID and tonumber(PlayerID) ~= 1 then + -- block pilot + local outcome = net.force_player_slot(tonumber(PlayerID), 0, '' ) else self.KnownPilots[name] = { name = name, @@ -185,14 +220,11 @@ function NET:_EventHandler(EventData) side = PlayerSide, slot = PlayerSlot, } - if (self.BlockedUCIDs[ucid] and TNow >= self.BlockedUCIDs[ucid]) or (self.BlockedPilots[name] and TNow >= self.BlockedPilots[name]) then - self.BlockedPilots[name] = nil - self.BlockedUCIDs[ucid] = nil - end self:__PlayerJoined(1,data.IniUnit,name) return self end end + -- Leaving if data.id == EVENTS.PlayerLeaveUnit and self.KnownPilots[name] then self:T(self.lid.."Pilot Leaving: "..name.." | UCID: "..ucid) @@ -200,6 +232,7 @@ function NET:_EventHandler(EventData) self.KnownPilots[name] = false return self end + -- Ejected if data.id == EVENTS.Ejection and self.KnownPilots[name] then self:T(self.lid.."Pilot Ejecting: "..name.." | UCID: "..ucid) @@ -207,6 +240,7 @@ function NET:_EventHandler(EventData) self.KnownPilots[name] = false return self end + -- Dead, Crash, Suicide if (data.id == EVENTS.PilotDead or data.id == EVENTS.SelfKillPilot or data.id == EVENTS.Crash) and self.KnownPilots[name] then self:T(self.lid.."Pilot Dead: "..name.." | UCID: "..ucid) @@ -215,6 +249,7 @@ function NET:_EventHandler(EventData) return self end end + return self end @@ -254,6 +289,108 @@ function NET:BlockPlayer(Client,PlayerName,Seconds,Message) return self end +--- Block a SET_CLIENT of players +-- @param #NET self +-- @param Core.Set#SET_CLIENT PlayerSet The SET to block. +-- @param #number Seconds Seconds (optional) Number of seconds the player has to wait before rejoining. +-- @param #string Message (optional) Message to be sent via chat. +-- @return #NET self +function NET:BlockPlayerSet(PlayerSet,Seconds,Message) + self:T({PlayerSet.Set,Seconds,Message}) + local addon = Seconds or self.BlockTime + local message = Message or self.BlockMessage + for _,_client in pairs(PlayerSet.Set) do + local name = _client:GetPlayerName() + self:BlockPlayer(_client,name,addon,message) + end + return self +end + +--- Unblock a SET_CLIENT of players +-- @param #NET self +-- @param Core.Set#SET_CLIENT PlayerSet The SET to unblock. +-- @param #string Message (optional) Message to be sent via chat. +-- @return #NET self +function NET:UnblockPlayerSet(PlayerSet,Message) + self:T({PlayerSet.Set,Seconds,Message}) + local message = Message or self.UnblockMessage + for _,_client in pairs(PlayerSet.Set) do + local name = _client:GetPlayerName() + self:UnblockPlayer(_client,name,message) + end + return self +end + +--- Block a specific UCID of a player, does NOT automatically kick the player with the UCID if already joined. +-- @param #NET self +-- @param #string ucid +-- @param #number Seconds Seconds (optional) Number of seconds the player has to wait before rejoining. +-- @return #NET self +function NET:BlockUCID(ucid,Seconds) + self:T({ucid,Seconds}) + local addon = Seconds or self.BlockTime + self.BlockedUCIDs[ucid] = timer.getTime()+addon + return self +end + +--- Unblock a specific UCID of a player +-- @param #NET self +-- @param #string ucid +-- @return #NET self +function NET:UnblockUCID(ucid) + self:T({ucid}) + self.BlockedUCIDs[ucid] = nil + return self +end + +--- Block a specific coalition side, does NOT automatically kick all players of that side or kick out joined players +-- @param #NET self +-- @param #number side The side to block - 1 : Red, 2 : Blue +-- @param #number Seconds Seconds (optional) Number of seconds the player has to wait before rejoining. +-- @return #NET self +function NET:BlockSide(Side,Seconds) + self:T({Side,Seconds}) + local addon = Seconds or self.BlockTime + if Side == 1 or Side == 2 then + self.BlockedSides[Side] = timer.getTime()+addon + end + return self +end + +--- Unblock a specific coalition side. Does NOT unblock specifically blocked playernames or UCIDs. +-- @param #number side The side to block - 1 : Red, 2 : Blue +-- @param #number Seconds Seconds (optional) Number of seconds the player has to wait before rejoining. +-- @return #NET self +function NET:UnblockSide(Side,Seconds) + self:T({Side,Seconds}) + local addon = Seconds or self.BlockTime + if Side == 1 or Side == 2 then + self.BlockedSides[Side] = nil + end + return self +end + +--- Block a specific player slot, does NOT automatically kick a player in that slot or kick out joined players +-- @param #NET self +-- @param #string slot The slot to block +-- @param #number Seconds Seconds (optional) Number of seconds the player has to wait before rejoining. +-- @return #NET self +function NET:BlockSlot(Slot,Seconds) + self:T({Slot,Seconds}) + local addon = Seconds or self.BlockTime + self.BlockedSlots[Slot] = timer.getTime()+addon + return self +end + +--- Unblock a specific slot. +-- @param #string slot The slot to block +-- @return #NET self +function NET:UnblockSlot(Slot) + self:T({Slot}) + self.BlockedSlots[Slot] = nil + return self +end + --- Unblock a player. -- @param #NET self -- @param Wrapper.Client#CLIENT Client CLIENT object @@ -521,7 +658,7 @@ function NET:GetPlayerStatistic(Client,StatisticID) end end ---- Return the name of a given client. Same a CLIENT:GetPlayerName(). +--- Return the name of a given client. Effectively the same as CLIENT:GetPlayerName(). -- @param #NET self -- @param Wrapper.Client#CLIENT Client The client -- @return #string Name or nil if not obtainable @@ -610,6 +747,86 @@ function NET:Log(Message) return self end +--- Get some data of pilots who have currently joined +-- @param #NET self +-- @param Wrapper.Client#CLIENT Client Provide either the client object whose data to find **or** +-- @param #string Name The player name whose data to find +-- @return #table Table of #NET.PlayerData or nil if not found +function NET:GetKnownPilotData(Client,Name) + local name = Name + if Client and not Name then + name = Client:GetPlayerName() + end + if name then + return self.KnownPilots[name] + else + return nil + end +end + +--- Status - housekeeping +-- @param #NET self +-- @param #string From +-- @param #string Event +-- @param #string To +-- @return #NET self +function NET:onafterStatus(From,Event,To) + self:T({From,Event,To}) + + local function HouseHold(tavolo) + local TNow = timer.getTime() + for _,entry in pairs (tavolo) do + if entry >= TNow then entry = nil end + end + end + + HouseHold(self.BlockedPilots) + HouseHold(self.BlockedSides) + HouseHold(self.BlockedSlots) + HouseHold(self.BlockedUCIDs) + + if self:Is("Running") then + self:__Status(-60) + end + + return self +end + +--- Stop the event functions +-- @param #NET self +-- @param #string From +-- @param #string Event +-- @param #string To +-- @return #NET self +function NET:onafterRun(From,Event,To) + self:T({From,Event,To}) + self:HandleEvent(EVENTS.PlayerEnterUnit,self._EventHandler) + self:HandleEvent(EVENTS.PlayerEnterAircraft,self._EventHandler) + self:HandleEvent(EVENTS.PlayerLeaveUnit,self._EventHandler) + self:HandleEvent(EVENTS.PilotDead,self._EventHandler) + self:HandleEvent(EVENTS.Ejection,self._EventHandler) + self:HandleEvent(EVENTS.Crash,self._EventHandler) + self:HandleEvent(EVENTS.SelfKillPilot,self._EventHandler) + self:__Status(-30) +end + +--- Stop the event functions +-- @param #NET self +-- @param #string From +-- @param #string Event +-- @param #string To +-- @return #NET self +function NET:onafterStop(From,Event,To) + self:T({From,Event,To}) + self:UnHandleEvent(EVENTS.PlayerEnterUnit) + self:UnHandleEvent(EVENTS.PlayerEnterAircraft) + self:UnHandleEvent(EVENTS.PlayerLeaveUnit) + self:UnHandleEvent(EVENTS.PilotDead) + self:UnHandleEvent(EVENTS.Ejection) + self:UnHandleEvent(EVENTS.Crash) + self:UnHandleEvent(EVENTS.SelfKillPilot) + return self +end ------------------------------------------------------------------------------- -- End of NET -------------------------------------------------------------------------------