From 6ec43b72cee6c64e6893ec4ff0e4bf413a824a21 Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Thu, 16 Feb 2023 18:22:06 +0100 Subject: [PATCH 01/17] #AICSAR * Added PlayerName to `OnAfterPilotRescued(From,Event,To,PilotName)` if available --- Moose Development/Moose/Functional/AICSAR.lua | 35 ++++++++++++++++--- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/Moose Development/Moose/Functional/AICSAR.lua b/Moose Development/Moose/Functional/AICSAR.lua index b1ee470ca..0780b6814 100644 --- a/Moose Development/Moose/Functional/AICSAR.lua +++ b/Moose Development/Moose/Functional/AICSAR.lua @@ -52,6 +52,7 @@ -- @field Core.Set#SET_CLIENT playerset Track if alive heli pilots are available. -- @field #boolean limithelos limit available number of helos going on mission (defaults to true) -- @field #number helonumber number of helos available (default: 3) +-- @field Utilities.FiFo#FIFO PilotStore -- @extends Core.Fsm#FSM @@ -186,7 +187,7 @@ -- @field #AICSAR AICSAR = { ClassName = "AICSAR", - version = "0.1.9", + version = "0.1.10", lid = "", coalition = coalition.side.BLUE, template = "", @@ -226,6 +227,7 @@ AICSAR = { SRSPilotVoice = false, SRSOperator = nil, SRSOperatorVoice = false, + PilotStore = nil, } -- TODO Messages @@ -369,6 +371,9 @@ function AICSAR:New(Alias,Coalition,Pilottemplate,Helotemplate,FARP,MASHZone) -- Set some string id for output to DCS.log file. self.lid=string.format("%s (%s) | ", self.alias, self.coalition and UTILS.GetCoalitionName(self.coalition) or "unknown") + --Pilot Store + self.PilotStore = FIFO:New() + -- Start State. self:SetStartState("Stopped") @@ -385,6 +390,7 @@ function AICSAR:New(Alias,Coalition,Pilottemplate,Helotemplate,FARP,MASHZone) self:AddTransition("*", "Stop", "Stopped") -- Stop FSM. self:HandleEvent(EVENTS.LandingAfterEjection) + self:HandleEvent(EVENTS.Ejection) self:__Start(math.random(2,5)) @@ -438,7 +444,8 @@ function AICSAR:New(Alias,Coalition,Pilottemplate,Helotemplate,FARP,MASHZone) -- @param #AICSAR self -- @param #string From From state. -- @param #string Event Event. - -- @param #string To To state. + -- @param #string To To state. + -- @param #string PilotName --- On after "PilotUnloaded" event. -- @function [parent=#AICSAR] OnAfterPilotUnloaded @@ -648,6 +655,19 @@ function AICSAR:DCSRadioBroadcast(Soundfile,Duration,Subtitle) return self end +--- [Internal] Catch the ejection and save the pilot name +-- @param #AICSAR self +-- @param Core.Event#EVENTDATA EventData +-- @return #AICSAR self +function AICSAR:OnEventEjection(EventData) + local _event = EventData -- Core.Event#EVENTDATA + if _event.IniPlayerName then + self.PilotStore:Push(_event.IniPlayerName) + self:T(self.lid.."Pilot Ejected: ".._event.IniPlayerName) + end + return self +end + --- [Internal] Catch the landing after ejection and spawn a pilot in situ. -- @param #AICSAR self -- @param Core.Event#EVENTDATA EventData @@ -667,7 +687,7 @@ function AICSAR:OnEventLandingAfterEjection(EventData) local _LandingPos = COORDINATE:NewFromVec3(_event.initiator:getPosition().p) local _country = _event.initiator:getCountry() local _coalition = coalition.getCountryCoalition( _country ) - + -- DONE: add distance check local distancetofarp = _LandingPos:Get2DDistance(self.farp:GetCoordinate()) @@ -858,6 +878,7 @@ function AICSAR:_CheckQueue(OpsGroup) for _index, _pilot in pairs(self.pilotqueue) do local classname = _pilot.ClassName and _pilot.ClassName or "NONE" local name = _pilot.GroupName and _pilot.GroupName or "NONE" + local playername = "John Doe" local helocount = self:_CountHelos() --self:T("Looking at " .. classname .. " " .. name) -- find one w/o mission @@ -873,7 +894,10 @@ function AICSAR:_CheckQueue(OpsGroup) end self.pilotqueue[_index] = nil self.rescued[_index] = true - self:__PilotRescued(2) + if self.PilotStore:Count() > 0 then + playername = self.PilotStore:Pull() + end + self:__PilotRescued(2,playername) if flightgroup then flightgroup.AICSARReserved = false end @@ -1095,8 +1119,9 @@ end -- @param #string From -- @param #string Event -- @param #string To +-- @param #string PilotName -- @return #AICSAR self -function AICSAR:onafterPilotRescued(From, Event, To) +function AICSAR:onafterPilotRescued(From, Event, To, PilotName) self:T({From, Event, To}) local text,Soundfile,Soundlength,Subtitle = self.gettext:GetEntry("PILOTRESCUED",self.locale) if self.verbose then From 2ebbc8f466b2629c4d5033e50cb4ef8b0e08756c Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Fri, 17 Feb 2023 08:54:15 +0100 Subject: [PATCH 02/17] #NET - added docu --- Moose Development/Moose/Wrapper/Net.lua | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Moose Development/Moose/Wrapper/Net.lua b/Moose Development/Moose/Wrapper/Net.lua index d2ac28285..34c7bdbdf 100644 --- a/Moose Development/Moose/Wrapper/Net.lua +++ b/Moose Development/Moose/Wrapper/Net.lua @@ -91,7 +91,7 @@ function NET:New() -- @param #string From State. -- @param #string Event Trigger. -- @param #string To State. - -- @param Wrapper.Unit#UNIT Client Unit Object. + -- @param Wrapper.Unit#UNIT Client Unit Object, might be nil. -- @param #string Name Name of leaving Pilot. -- @return #NET self @@ -101,7 +101,7 @@ function NET:New() -- @param #string From State. -- @param #string Event Trigger. -- @param #string To State. - -- @param Wrapper.Unit#UNIT Client Unit Object. + -- @param Wrapper.Unit#UNIT Client Unit Object, might be nil. -- @param #string Name Name of leaving Pilot. -- @return #NET self @@ -111,7 +111,7 @@ function NET:New() -- @param #string From State. -- @param #string Event Trigger. -- @param #string To State. - -- @param Wrapper.Unit#UNIT Client Unit Object. + -- @param Wrapper.Unit#UNIT Client Unit Object, might be nil. -- @param #string Name Name of dead Pilot. -- @return #NET self @@ -121,7 +121,7 @@ function NET:New() -- @param #string From State. -- @param #string Event Trigger. -- @param #string To State. - -- @param Wrapper.Client#CLIENT Client Client Object. + -- @param Wrapper.Client#CLIENT Client Client Object, might be nil. -- @param #string Name Name of blocked Pilot. -- @param #number Seconds Blocked for this number of seconds -- @return #NET self @@ -132,7 +132,7 @@ function NET:New() -- @param #string From State. -- @param #string Event Trigger. -- @param #string To State. - -- @param Wrapper.Client#CLIENT Client Client Object. + -- @param Wrapper.Client#CLIENT Client Client Object, might be nil. -- @param #string Name Name of unblocked Pilot. -- @return #NET self From a7e45338e39a6f183d8f4d0846393dbc17253a96 Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Fri, 17 Feb 2023 08:54:54 +0100 Subject: [PATCH 03/17] #AICSAR - Added alt/speed options --- Moose Development/Moose/Functional/AICSAR.lua | 33 +++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/Moose Development/Moose/Functional/AICSAR.lua b/Moose Development/Moose/Functional/AICSAR.lua index 0780b6814..45b6f9a4e 100644 --- a/Moose Development/Moose/Functional/AICSAR.lua +++ b/Moose Development/Moose/Functional/AICSAR.lua @@ -53,6 +53,8 @@ -- @field #boolean limithelos limit available number of helos going on mission (defaults to true) -- @field #number helonumber number of helos available (default: 3) -- @field Utilities.FiFo#FIFO PilotStore +-- @field #number Altitude Default altitude setting for the helicopter FLIGHTGROUP 1500ft. +-- @field #number Speed Default speed setting for the helicopter FLIGHTGROUP is 100kn. -- @extends Core.Fsm#FSM @@ -78,7 +80,7 @@ -- -- @param #string Alias Name of this instance. -- -- @param #number Coalition Coalition as in coalition.side.BLUE, can also be passed as "blue", "red" or "neutral" -- -- @param #string Pilottemplate Pilot template name. --- -- @param #string Helotemplate Helicopter template name. +-- -- @param #string Helotemplate Helicopter template name. Set the template to "cold start". Hueys work best. -- -- @param Wrapper.Airbase#AIRBASE FARP FARP object or Airbase from where to start. -- -- @param Core.Zone#ZONE MASHZone Zone where to drop pilots after rescue. -- local my_aicsar=AICSAR:New("Luftrettung",coalition.side.BLUE,"Downed Pilot","Rescue Helo",AIRBASE:FindByName("Test FARP"),ZONE:New("MASH")) @@ -187,7 +189,7 @@ -- @field #AICSAR AICSAR = { ClassName = "AICSAR", - version = "0.1.10", + version = "0.1.11", lid = "", coalition = coalition.side.BLUE, template = "", @@ -228,6 +230,8 @@ AICSAR = { SRSOperator = nil, SRSOperatorVoice = false, PilotStore = nil, + Speed = 100, + Altitude = 1500, } -- TODO Messages @@ -785,10 +789,15 @@ function AICSAR:_InitMission(Pilot,Index) -- Cargo transport assignment. local opstransport=OPSTRANSPORT:New(Pilot, pickupzone, self.farpzone) + local helo = self:_GetFlight() -- inject reservation helo.AICSARReserved = true + helo:SetDefaultAltitude(self.Altitude or 1500) + + helo:SetDefaultSpeed(self.Speed or 100) + -- Cargo transport assignment to first Huey group. helo:AddOpsTransport(opstransport) @@ -835,6 +844,26 @@ function AICSAR:_CheckInMashZone(Pilot) end end +--- [User] Set default helo speed. Note - AI might have other ideas. Defaults to 100kn. +-- @param #AICSAR self +-- @param #number Knots Speed in knots. +-- @return #AICSAR self +function AICSAR:SetDefaultSpeed(Knots) + self:T(self.lid .. "SetDefaultSpeed") + self.Speed = Knots or 100 + return self +end + +--- [User] Set default helo altitudeAGL. Note - AI might have other ideas. Defaults to 1500ft. +-- @param #AICSAR self +-- @param #number Feet AGL set in feet. +-- @return #AICSAR self +function AICSAR:SetDefaultAltitude(Feet) + self:T(self.lid .. "SetDefaultAltitude") + self.Altitude = Feet or 1500 + return self +end + --- [Internal] Check helo queue -- @param #AICSAR self -- @return #AICSAR self From 50f73f1be275bfef4ad6970e1723bb80ebbbdf05 Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Fri, 17 Feb 2023 13:22:10 +0100 Subject: [PATCH 04/17] #NET extended block to UCID --- Moose Development/Moose/Wrapper/Net.lua | 47 +++++++++++++++++++++---- 1 file changed, 41 insertions(+), 6 deletions(-) diff --git a/Moose Development/Moose/Wrapper/Net.lua b/Moose Development/Moose/Wrapper/Net.lua index 34c7bdbdf..1e3845979 100644 --- a/Moose Development/Moose/Wrapper/Net.lua +++ b/Moose Development/Moose/Wrapper/Net.lua @@ -1,6 +1,6 @@ --- **Wrapper** - DCS net functions. -- --- Encapsules **multiplayer** environment scripting functions from [net](https://wiki.hoggitworld.com/view/DCS_singleton_net) +-- Encapsules **multiplayer server** environment scripting functions from [net](https://wiki.hoggitworld.com/view/DCS_singleton_net) -- -- === -- @@ -22,6 +22,7 @@ do -- @field #table KnownPilots -- @field #string BlockMessage -- @field #string UnblockMessage +-- @field #table BlockedUCIDs -- @extends Core.Fsm#FSM --- Encapsules multiplayer environment scripting functions from [net](https://wiki.hoggitworld.com/view/DCS_singleton_net) @@ -30,9 +31,10 @@ do -- @field #NET NET = { ClassName = "NET", - Version = "0.0.3", + Version = "0.0.4", BlockTime = 600, BlockedPilots = {}, + BlockedUCIDs = {}, KnownPilots = {}, BlockMessage = nil, UnblockMessage = nil, @@ -150,17 +152,22 @@ function NET:_EventHandler(EventData) if data.id and data.IniUnit and (data.IniPlayerName or data.IniUnit:GetPlayerName()) then -- Get PlayerName local name = data.IniPlayerName and data.IniPlayerName or data.IniUnit:GetPlayerName() - self:T(self.lid.."Event for: "..name) + local ucid = self:GetPlayerUCID(nil,name) + self:T(self.lid.."Event for: "..name.." | UCID: "..ucid) -- Joining if data.id == EVENTS.PlayerEnterUnit or data.id == EVENTS.PlayerEnterAircraft then -- Check for known pilots local TNow = timer.getTime() if self.BlockedPilots[name] and TNow < self.BlockedPilots[name] then - -- block pilot + -- block pilot by name + self:ReturnToSpectators(data.IniUnit) + elseif self.BlockedUCIDs[ucid] and TNow < self.BlockedUCIDs[ucid] then + -- block pilot by ucid self:ReturnToSpectators(data.IniUnit) else self.KnownPilots[name] = true self.BlockedPilots[name] = nil + self.BlockedUCIDs[ucid] = nil self:__PlayerJoined(1,data.IniUnit,name) return self end @@ -204,8 +211,10 @@ function NET:BlockPlayer(Client,PlayerName,Seconds,Message) self:F(self.lid.."Block: No PlayerName given or not found!") return self end + local ucid = self:GetPlayerUCID(Client,name) local addon = Seconds or self.BlockTime self.BlockedPilots[name] = timer.getTime()+addon + self.BlockedUCIDs[ucid] = timer.getTime()+addon local message = Message or self.BlockMessage if Client then self:SendChatToPlayer(message,Client) @@ -233,7 +242,9 @@ function NET:UnblockPlayer(Client,PlayerName,Message) self:F(self.lid.."Unblock: No PlayerName given or not found!") return self end + local ucid = self:GetPlayerUCID(Client,name) self.BlockedPilots[name] = nil + self.BlockedUCIDs[ucid] = nil local message = Message or self.UnblockMessage if Client then self:SendChatToPlayer(message,Client) @@ -244,16 +255,28 @@ function NET:UnblockPlayer(Client,PlayerName,Message) return self end +--- Set block chat message. +-- @param #NET self +-- @param #string Text The message +-- @return #NET self function NET:SetBlockMessage(Text) self.BlockMessage = Text or "You are blocked from joining. Wait time is: "..self.BlockTime.." seconds!" return self end +--- Set block time in seconds. +-- @param #NET self +-- @param #number Seconds Numnber of seconds this block will last. Defaults to 600. +-- @return #NET self function NET:SetBlockTime(Seconds) self.BlockTime = Seconds or 600 return self end +--- Set unblock chat message. +-- @param #NET self +-- @param #string Text The message +-- @return #NET self function NET:SetUnblockMessage(Text) self.UnblockMessage = Text or "You are unblocked now and can join again." return self @@ -275,7 +298,7 @@ end -- @param #NET self -- @param #string Name The player name whose ID to find -- @return #number PlayerID or nil -function NET:GetPlayerIdByName(Name) +function NET:GetPlayerIDByName(Name) local playerList = self:GetPlayerList() for i=1,#playerList do local playerName = net.get_name(i) @@ -292,7 +315,7 @@ end -- @return #number PlayerID or nil function NET:GetPlayerIDFromClient(Client) local name = Client:GetPlayerName() - local id = self:GetPlayerIdByName(name) + local id = self:GetPlayerIDByName(name) return id end @@ -384,6 +407,18 @@ function NET:GetPlayerInfo(Client,Attribute) end end + +--- Get player UCID from player CLIENT object or player name. Provide either one. +-- @param #NET self +-- @param Wrapper.Client#CLIENT Client The client object to be used. +-- @param #string Name Player name to be used. +-- @return #boolean success +function NET:GetPlayerUCID(Client,Name) + local PlayerID = self:GetPlayerIDByName(Name) or self:GetPlayerIDFromClient(Client) + local ucid = net.get_player_info(tonumber(PlayerID), 'ucid') + return ucid +end + --- Kicks a player from the server. Can display a message to the user. -- @param #NET self -- @param Wrapper.Client#CLIENT Client The client From 4797abc2875fdbdf4addc54b7f6cb3f19ec2e5da Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Fri, 17 Feb 2023 14:32:48 +0100 Subject: [PATCH 05/17] #NET Bugfix --- Moose Development/Moose/Wrapper/Net.lua | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/Moose Development/Moose/Wrapper/Net.lua b/Moose Development/Moose/Wrapper/Net.lua index 1e3845979..eafa6a640 100644 --- a/Moose Development/Moose/Wrapper/Net.lua +++ b/Moose Development/Moose/Wrapper/Net.lua @@ -208,7 +208,7 @@ function NET:BlockPlayer(Client,PlayerName,Seconds,Message) elseif PlayerName then name = PlayerName else - self:F(self.lid.."Block: No PlayerName given or not found!") + self:F(self.lid.."Block: No Client or PlayerName given or nothing found!") return self end local ucid = self:GetPlayerUCID(Client,name) @@ -414,7 +414,14 @@ end -- @param #string Name Player name to be used. -- @return #boolean success function NET:GetPlayerUCID(Client,Name) - local PlayerID = self:GetPlayerIDByName(Name) or self:GetPlayerIDFromClient(Client) + local PlayerID = nil + if Client then + PlayerID = self:GetPlayerIDFromClient(Client) + elseif Name then + PlayerID = self:GetPlayerIDByName(Name) + else + self:E(self.lid.."Neither client nor name provided!") + end local ucid = net.get_player_info(tonumber(PlayerID), 'ucid') return ucid end From 9e23cda02a292bfcab0ebf9bf309bf06797070cb Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Fri, 17 Feb 2023 15:01:49 +0100 Subject: [PATCH 06/17] #NET Fixes --- Moose Development/Moose/Wrapper/Net.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Moose Development/Moose/Wrapper/Net.lua b/Moose Development/Moose/Wrapper/Net.lua index eafa6a640..b7c61ed86 100644 --- a/Moose Development/Moose/Wrapper/Net.lua +++ b/Moose Development/Moose/Wrapper/Net.lua @@ -204,7 +204,7 @@ end function NET:BlockPlayer(Client,PlayerName,Seconds,Message) local name if Client then - name = CLIENT:GetPlayerName() + name = Client:GetPlayerName() elseif PlayerName then name = PlayerName else @@ -235,7 +235,7 @@ end function NET:UnblockPlayer(Client,PlayerName,Message) local name if Client then - name = CLIENT:GetPlayerName() + name = Client:GetPlayerName() elseif PlayerName then name = PlayerName else From 83866c3dd3080a45c84ac9824f3e9d11d6e05811 Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Fri, 17 Feb 2023 15:02:11 +0100 Subject: [PATCH 07/17] #NET Fixes --- Moose Development/Moose/Wrapper/Net.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Moose Development/Moose/Wrapper/Net.lua b/Moose Development/Moose/Wrapper/Net.lua index eafa6a640..b7c61ed86 100644 --- a/Moose Development/Moose/Wrapper/Net.lua +++ b/Moose Development/Moose/Wrapper/Net.lua @@ -204,7 +204,7 @@ end function NET:BlockPlayer(Client,PlayerName,Seconds,Message) local name if Client then - name = CLIENT:GetPlayerName() + name = Client:GetPlayerName() elseif PlayerName then name = PlayerName else @@ -235,7 +235,7 @@ end function NET:UnblockPlayer(Client,PlayerName,Message) local name if Client then - name = CLIENT:GetPlayerName() + name = Client:GetPlayerName() elseif PlayerName then name = PlayerName else From a4dcb643bd0a9c4b1e07275434b3034c83d6a07b Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Fri, 17 Feb 2023 15:41:33 +0100 Subject: [PATCH 08/17] #NET Fixes --- Moose Development/Moose/Wrapper/Net.lua | 39 +++++++++++++++++++------ 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/Moose Development/Moose/Wrapper/Net.lua b/Moose Development/Moose/Wrapper/Net.lua index b7c61ed86..87840fd78 100644 --- a/Moose Development/Moose/Wrapper/Net.lua +++ b/Moose Development/Moose/Wrapper/Net.lua @@ -216,8 +216,8 @@ function NET:BlockPlayer(Client,PlayerName,Seconds,Message) self.BlockedPilots[name] = timer.getTime()+addon self.BlockedUCIDs[ucid] = timer.getTime()+addon local message = Message or self.BlockMessage - if Client then - self:SendChatToPlayer(message,Client) + if name then + self:SendChatToPlayer(message,name) else self:SendChat(name..": "..message) end @@ -246,8 +246,8 @@ function NET:UnblockPlayer(Client,PlayerName,Message) self.BlockedPilots[name] = nil self.BlockedUCIDs[ucid] = nil local message = Message or self.UnblockMessage - if Client then - self:SendChatToPlayer(message,Client) + if name then + self:SendChatToPlayer(message,name) else self:SendChat(name..": "..message) end @@ -314,18 +314,22 @@ end -- @param Wrapper.Client#CLIENT Client The client -- @return #number PlayerID or nil function NET:GetPlayerIDFromClient(Client) - local name = Client:GetPlayerName() - local id = self:GetPlayerIDByName(name) - return id + if Client then + local name = Client:GetPlayerName() + local id = self:GetPlayerIDByName(name) + return id + else + return nil + end end ---- Send chat message to a specific player. +--- Send chat message to a specific player using the CLIENT object. -- @param #NET self -- @param #string Message The text message -- @param Wrapper.Client#CLIENT ToClient Client receiving the message -- @param Wrapper.Client#CLIENT FromClient (Optional) Client sending the message -- @return #NET self -function NET:SendChatToPlayer(Message, ToClient, FromClient) +function NET:SendChatToClient(Message, ToClient, FromClient) local PlayerId = self:GetPlayerIDFromClient(ToClient) local FromId = self:GetPlayerIDFromClient(FromClient) if Message and PlayerId and FromId then @@ -336,6 +340,23 @@ function NET:SendChatToPlayer(Message, ToClient, FromClient) return self end +--- Send chat message to a specific player using the player name +-- @param #NET self +-- @param #string Message The text message +-- @param #string ToPlayer Player receiving the message +-- @param #string FromPlayer(Optional) Player sending the message +-- @return #NET self +function NET:SendChatToPlayer(Message, ToPlayer, FromPlayer) + local PlayerId = self:GetPlayerIDByName(ToPlayer) + local FromId = self:GetPlayerIDByName(FromPlayer) + if Message and PlayerId and FromId then + net.send_chat_to(Message, tonumber(PlayerId) , tonumber(FromId)) + elseif Message and PlayerId then + net.send_chat_to(Message, tonumber(PlayerId)) + end + return self +end + --- Load a specific mission. -- @param #NET self -- @param #string Path and Mission From 973127aa8cb46ca4b03d13ff227cadc5c1601f51 Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Fri, 17 Feb 2023 15:42:06 +0100 Subject: [PATCH 09/17] #NET Fixes --- Moose Development/Moose/Wrapper/Net.lua | 39 +++++++++++++++++++------ 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/Moose Development/Moose/Wrapper/Net.lua b/Moose Development/Moose/Wrapper/Net.lua index b7c61ed86..87840fd78 100644 --- a/Moose Development/Moose/Wrapper/Net.lua +++ b/Moose Development/Moose/Wrapper/Net.lua @@ -216,8 +216,8 @@ function NET:BlockPlayer(Client,PlayerName,Seconds,Message) self.BlockedPilots[name] = timer.getTime()+addon self.BlockedUCIDs[ucid] = timer.getTime()+addon local message = Message or self.BlockMessage - if Client then - self:SendChatToPlayer(message,Client) + if name then + self:SendChatToPlayer(message,name) else self:SendChat(name..": "..message) end @@ -246,8 +246,8 @@ function NET:UnblockPlayer(Client,PlayerName,Message) self.BlockedPilots[name] = nil self.BlockedUCIDs[ucid] = nil local message = Message or self.UnblockMessage - if Client then - self:SendChatToPlayer(message,Client) + if name then + self:SendChatToPlayer(message,name) else self:SendChat(name..": "..message) end @@ -314,18 +314,22 @@ end -- @param Wrapper.Client#CLIENT Client The client -- @return #number PlayerID or nil function NET:GetPlayerIDFromClient(Client) - local name = Client:GetPlayerName() - local id = self:GetPlayerIDByName(name) - return id + if Client then + local name = Client:GetPlayerName() + local id = self:GetPlayerIDByName(name) + return id + else + return nil + end end ---- Send chat message to a specific player. +--- Send chat message to a specific player using the CLIENT object. -- @param #NET self -- @param #string Message The text message -- @param Wrapper.Client#CLIENT ToClient Client receiving the message -- @param Wrapper.Client#CLIENT FromClient (Optional) Client sending the message -- @return #NET self -function NET:SendChatToPlayer(Message, ToClient, FromClient) +function NET:SendChatToClient(Message, ToClient, FromClient) local PlayerId = self:GetPlayerIDFromClient(ToClient) local FromId = self:GetPlayerIDFromClient(FromClient) if Message and PlayerId and FromId then @@ -336,6 +340,23 @@ function NET:SendChatToPlayer(Message, ToClient, FromClient) return self end +--- Send chat message to a specific player using the player name +-- @param #NET self +-- @param #string Message The text message +-- @param #string ToPlayer Player receiving the message +-- @param #string FromPlayer(Optional) Player sending the message +-- @return #NET self +function NET:SendChatToPlayer(Message, ToPlayer, FromPlayer) + local PlayerId = self:GetPlayerIDByName(ToPlayer) + local FromId = self:GetPlayerIDByName(FromPlayer) + if Message and PlayerId and FromId then + net.send_chat_to(Message, tonumber(PlayerId) , tonumber(FromId)) + elseif Message and PlayerId then + net.send_chat_to(Message, tonumber(PlayerId)) + end + return self +end + --- Load a specific mission. -- @param #NET self -- @param #string Path and Mission From 66494b7b5ac2a98eddb1d623698bd7916f123757 Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Fri, 17 Feb 2023 16:23:02 +0100 Subject: [PATCH 10/17] NET --- Moose Development/Moose/Wrapper/Net.lua | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/Moose Development/Moose/Wrapper/Net.lua b/Moose Development/Moose/Wrapper/Net.lua index 87840fd78..f98f1f93f 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.4", + Version = "0.0.5", BlockTime = 600, BlockedPilots = {}, BlockedUCIDs = {}, @@ -202,7 +202,7 @@ end -- @param #string Message (optional) Message to be sent via chat. -- @return #NET self function NET:BlockPlayer(Client,PlayerName,Seconds,Message) - local name + local name = PlayerName if Client then name = Client:GetPlayerName() elseif PlayerName then @@ -222,7 +222,10 @@ function NET:BlockPlayer(Client,PlayerName,Seconds,Message) self:SendChat(name..": "..message) end self:__PlayerBlocked(1,Client,name,Seconds) - self:ReturnToSpectators(Client) + local PlayerID = self:GetPlayerIDByName(name) + if PlayerID and tonumber(PlayerID) ~= 1 then + local outcome = net.force_player_slot(tonumber(PlayerID), 0, '' ) + end return self end @@ -233,7 +236,7 @@ end -- @param #string Message (optional) Message to be sent via chat. -- @return #NET self function NET:UnblockPlayer(Client,PlayerName,Message) - local name + local name = PlayerName if Client then name = Client:GetPlayerName() elseif PlayerName then @@ -299,6 +302,7 @@ end -- @param #string Name The player name whose ID to find -- @return #number PlayerID or nil function NET:GetPlayerIDByName(Name) + if not Name then return nil end local playerList = self:GetPlayerList() for i=1,#playerList do local playerName = net.get_name(i) @@ -526,8 +530,8 @@ end -- @return #boolean Success function NET:ForceSlot(Client,SideID,SlotID) local PlayerID = self:GetPlayerIDFromClient(Client) - if PlayerID then - return net.force_player_slot(tonumber(PlayerID), SideID, SlotID ) + if PlayerID and tonumber(PlayerID) ~= 1 then + return net.force_player_slot(tonumber(PlayerID), SideID, SlotID or '' ) else return false end From ff86bfb91dafb5748857d2dcc41e71abe03b85e7 Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Fri, 17 Feb 2023 16:41:38 +0100 Subject: [PATCH 11/17] #NET Event blocker fix --- Moose Development/Moose/Wrapper/Net.lua | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Moose Development/Moose/Wrapper/Net.lua b/Moose Development/Moose/Wrapper/Net.lua index f98f1f93f..a12d580ca 100644 --- a/Moose Development/Moose/Wrapper/Net.lua +++ b/Moose Development/Moose/Wrapper/Net.lua @@ -160,10 +160,16 @@ function NET:_EventHandler(EventData) local TNow = timer.getTime() if self.BlockedPilots[name] and TNow < self.BlockedPilots[name] then -- block pilot by name - self:ReturnToSpectators(data.IniUnit) + local PlayerID = self:GetPlayerIDByName(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 - self:ReturnToSpectators(data.IniUnit) + 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 From 1fd8f4d8373401efad40ef0d7d3ef96de4451f2e Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Sat, 18 Feb 2023 11:04:49 +0100 Subject: [PATCH 12/17] #AICSAR * Named functions for the events --- Moose Development/Moose/Functional/AICSAR.lua | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Moose Development/Moose/Functional/AICSAR.lua b/Moose Development/Moose/Functional/AICSAR.lua index 45b6f9a4e..a09d0e1bd 100644 --- a/Moose Development/Moose/Functional/AICSAR.lua +++ b/Moose Development/Moose/Functional/AICSAR.lua @@ -189,7 +189,7 @@ -- @field #AICSAR AICSAR = { ClassName = "AICSAR", - version = "0.1.11", + version = "0.1.12", lid = "", coalition = coalition.side.BLUE, template = "", @@ -393,8 +393,8 @@ function AICSAR:New(Alias,Coalition,Pilottemplate,Helotemplate,FARP,MASHZone) self:AddTransition("*", "HeloDown", "*") -- Helo dead self:AddTransition("*", "Stop", "Stopped") -- Stop FSM. - self:HandleEvent(EVENTS.LandingAfterEjection) - self:HandleEvent(EVENTS.Ejection) + self:HandleEvent(EVENTS.LandingAfterEjection,self._EventHandler) + self:HandleEvent(EVENTS.Ejection,self._EventHandlerEject) self:__Start(math.random(2,5)) @@ -663,7 +663,7 @@ end -- @param #AICSAR self -- @param Core.Event#EVENTDATA EventData -- @return #AICSAR self -function AICSAR:OnEventEjection(EventData) +function AICSAR:_EventHandlerEject(EventData) local _event = EventData -- Core.Event#EVENTDATA if _event.IniPlayerName then self.PilotStore:Push(_event.IniPlayerName) @@ -676,7 +676,7 @@ end -- @param #AICSAR self -- @param Core.Event#EVENTDATA EventData -- @return #AICSAR self -function AICSAR:OnEventLandingAfterEjection(EventData) +function AICSAR:_EventHandler(EventData) self:T(self.lid .. "OnEventLandingAfterEjection ID=" .. EventData.id) -- autorescue on off? From 3e8413c6b7e0286c7ce68a5740557f699ba7b691 Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Sat, 18 Feb 2023 15:03:53 +0100 Subject: [PATCH 13/17] #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 bef8e53347353e0788c9f2bc29b8a69102c89dd2 Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Sun, 19 Feb 2023 12:30:00 +0100 Subject: [PATCH 14/17] #AICSAR - added option to use eject event --- Moose Development/Moose/Functional/AICSAR.lua | 95 ++++++++++++++++++- 1 file changed, 91 insertions(+), 4 deletions(-) diff --git a/Moose Development/Moose/Functional/AICSAR.lua b/Moose Development/Moose/Functional/AICSAR.lua index a09d0e1bd..c9ec13298 100644 --- a/Moose Development/Moose/Functional/AICSAR.lua +++ b/Moose Development/Moose/Functional/AICSAR.lua @@ -55,6 +55,8 @@ -- @field Utilities.FiFo#FIFO PilotStore -- @field #number Altitude Default altitude setting for the helicopter FLIGHTGROUP 1500ft. -- @field #number Speed Default speed setting for the helicopter FLIGHTGROUP is 100kn. +-- @field #boolean UseEventEject In case Event LandingAfterEjection isn't working, use set this to true. +-- @field #number Delay In case of UseEventEject wait this long until we spawn a landed pilot. -- @extends Core.Fsm#FSM @@ -189,7 +191,7 @@ -- @field #AICSAR AICSAR = { ClassName = "AICSAR", - version = "0.1.12", + version = "0.1.14", lid = "", coalition = coalition.side.BLUE, template = "", @@ -232,6 +234,8 @@ AICSAR = { PilotStore = nil, Speed = 100, Altitude = 1500, + UseEventEject = false, + Delay = 100, } -- TODO Messages @@ -343,6 +347,8 @@ function AICSAR:New(Alias,Coalition,Pilottemplate,Helotemplate,FARP,MASHZone) self.farp = FARP self.farpzone = MASHZone self.playerset = SET_CLIENT:New():FilterActive(true):FilterCategories("helicopter"):FilterStart() + self.UseEventEject = false + self.Delay = 300 -- Radio self.SRS = nil @@ -394,7 +400,7 @@ function AICSAR:New(Alias,Coalition,Pilottemplate,Helotemplate,FARP,MASHZone) self:AddTransition("*", "Stop", "Stopped") -- Stop FSM. self:HandleEvent(EVENTS.LandingAfterEjection,self._EventHandler) - self:HandleEvent(EVENTS.Ejection,self._EventHandlerEject) + self:HandleEvent(EVENTS.Ejection,self._EjectEventHandler) self:__Start(math.random(2,5)) @@ -663,20 +669,99 @@ end -- @param #AICSAR self -- @param Core.Event#EVENTDATA EventData -- @return #AICSAR self -function AICSAR:_EventHandlerEject(EventData) +function AICSAR:_EjectEventHandler(EventData) local _event = EventData -- Core.Event#EVENTDATA if _event.IniPlayerName then self.PilotStore:Push(_event.IniPlayerName) self:T(self.lid.."Pilot Ejected: ".._event.IniPlayerName) + if self.UseEventEject then + -- get position and spawn in a template pilot + local _LandingPos = COORDINATE:NewFromVec3(_event.initiator:getPosition().p) + local _country = _event.initiator:getCountry() + local _coalition = coalition.getCountryCoalition( _country ) + local data = UTILS.DeepCopy(EventData) + Unit.destroy(_event.initiator) -- shagrat remove static Pilot model + self:ScheduleOnce(self.Delay,self._DelayedSpawnPilot,self,_LandingPos,_coalition) + end end return self end +--- [Internal] Spawn a pilot +-- @param #AICSAR self +-- @param Core.Point#COORDINATE _LandingPos Landing Postion +-- @param #number _coalition Coalition side +-- @return #AICSAR self +function AICSAR:_DelayedSpawnPilot(_LandingPos,_coalition) + + local distancetofarp = _LandingPos:Get2DDistance(self.farp:GetCoordinate()) + -- Mayday Message + local Text,Soundfile,Soundlength,Subtitle = self.gettext:GetEntry("PILOTDOWN",self.locale) + local text = "" + local setting = {} + setting.MGRS_Accuracy = self.MGRS_Accuracy + local location = _LandingPos:ToStringMGRS(setting) + local msgtxt = Text..location.."!" + location = string.gsub(location,"MGRS ","") + location = string.gsub(location,"%s+","") + location = string.gsub(location,"([%a%d])","%1;") -- "0 5 1 " + location = string.gsub(location,"0","zero") + location = string.gsub(location,"9","niner") + location = "MGRS;"..location + if self.SRSGoogle then + location = string.format("%s",location) + end + text = Text .. location .. "!" + local ttstext = Text .. location .. "! Repeat! "..location + if _coalition == self.coalition then + if self.verbose then + MESSAGE:New(msgtxt,15,"AICSAR"):ToCoalition(self.coalition) + -- MESSAGE:New(msgtxt,15,"AICSAR"):ToLog() + end + if self.SRSRadio then + local sound = SOUNDFILE:New(Soundfile,self.SRSSoundPath,Soundlength) + sound:SetPlayWithSRS(true) + self.SRS:PlaySoundFile(sound,2) + elseif self.DCSRadio then + self:DCSRadioBroadcast(Soundfile,Soundlength,text) + elseif self.SRSTTSRadio then + if self.SRSPilotVoice then + self.SRSQ:NewTransmission(ttstext,nil,self.SRSPilot,nil,1) + else + self.SRSQ:NewTransmission(ttstext,nil,self.SRS,nil,1) + end + end + end + + -- further processing + if _coalition == self.coalition and distancetofarp <= self.maxdistance then + -- in reach + self:T(self.lid .. "Spawning new Pilot") + self.pilotindex = self.pilotindex + 1 + local newpilot = SPAWN:NewWithAlias(self.template,string.format("%s-AICSAR-%d",self.template, self.pilotindex)) + newpilot:InitDelayOff() + newpilot:OnSpawnGroup( + function (grp) + self.pilotqueue[self.pilotindex] = grp + end + ) + newpilot:SpawnFromCoordinate(_LandingPos) + + self:__PilotDown(2,_LandingPos,true) + elseif _coalition == self.coalition and distancetofarp > self.maxdistance then + -- out of reach, apologies, too far off + self:T(self.lid .. "Pilot out of reach") + self:__PilotDown(2,_LandingPos,false) + end + return self +end + --- [Internal] Catch the landing after ejection and spawn a pilot in situ. -- @param #AICSAR self -- @param Core.Event#EVENTDATA EventData +-- @param #boolean FromEject -- @return #AICSAR self -function AICSAR:_EventHandler(EventData) +function AICSAR:_EventHandler(EventData, FromEject) self:T(self.lid .. "OnEventLandingAfterEjection ID=" .. EventData.id) -- autorescue on off? @@ -686,6 +771,8 @@ function AICSAR:_EventHandler(EventData) end end + if self.UseEventEject and (not FromEject) then return self end + local _event = EventData -- Core.Event#EVENTDATA -- get position and spawn in a template pilot local _LandingPos = COORDINATE:NewFromVec3(_event.initiator:getPosition().p) From 7dc239f506bb010bd363bc86201b88f2a858db8a Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Sun, 19 Feb 2023 12:31:08 +0100 Subject: [PATCH 15/17] 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 16/17] #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 ------------------------------------------------------------------------------- From 9cfed56847ffaea249b325d81d709ba5773a32b9 Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Tue, 21 Feb 2023 11:38:40 +0100 Subject: [PATCH 17/17] #CTLD logic correction for loading --- Moose Development/Moose/Ops/CTLD.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Moose Development/Moose/Ops/CTLD.lua b/Moose Development/Moose/Ops/CTLD.lua index db2afa9c0..9524e67b0 100644 --- a/Moose Development/Moose/Ops/CTLD.lua +++ b/Moose Development/Moose/Ops/CTLD.lua @@ -22,7 +22,7 @@ -- @module Ops.CTLD -- @image OPS_CTLD.jpg --- Last Update Jan 2023 +-- Last Update Feb 2023 do @@ -1196,7 +1196,7 @@ CTLD.UnitTypes = { --- CTLD class version. -- @field #string version -CTLD.version="1.0.30" +CTLD.version="1.0.31" --- Instantiate a new CTLD. -- @param #CTLD self @@ -2609,7 +2609,7 @@ function CTLD:_LoadCratesNearby(Group, Unit) crateind = _crate:GetID() end else - if not _crate:HasMoved() and _crate:WasDropped() and _crate:GetID() > crateind then + if not _crate:HasMoved() and not _crate:WasDropped() and _crate:GetID() > crateind then crateind = _crate:GetID() end end