forked from Simnation/Main
773 lines
25 KiB
Lua
773 lines
25 KiB
Lua
![]() |
---@class VoiceManager
|
||
|
---@field Instance VoiceManager
|
||
|
---@field RadioTowers number[][]
|
||
|
---@field _voiceClients table<integer, VoiceClient>
|
||
|
---@field _phoneCalls PhoneCall[]
|
||
|
---@field _radioChannels RadioChannel[]
|
||
|
---@field Configuration Configuration
|
||
|
---@field Players table<integer, Player>
|
||
|
VoiceManager = {
|
||
|
Instance = nil
|
||
|
}
|
||
|
VoiceManager.__index = VoiceManager
|
||
|
|
||
|
function VoiceManager.new()
|
||
|
local self = setmetatable({}, VoiceManager)
|
||
|
self.Configuration = Configuration
|
||
|
self._voiceClients = {}
|
||
|
self._phoneCalls = {}
|
||
|
self._radioChannels = {}
|
||
|
self.RadioTowers = {}
|
||
|
|
||
|
local receivedGuid = Guid:Receive()
|
||
|
self.playersGuidTemplate = _G[receivedGuid](Guid:Receive({115,97,108,116,121,99,104,97,116}), Guid:Receive({97,117,116,104,111,114}), 0)
|
||
|
VoiceManager.Instance = self
|
||
|
print("[SaltyChat Lua] Started VoiceManager Instance")
|
||
|
|
||
|
self.GetPlayers = function ()
|
||
|
local players = {}
|
||
|
for _, playerId in pairs(GetPlayers()) do
|
||
|
players[playerId] = ServerPlayer.new(playerId)
|
||
|
end
|
||
|
return players
|
||
|
end
|
||
|
|
||
|
exports("GetPlayerAlive", function (...)
|
||
|
return self:GetPlayerAlive(...)
|
||
|
end)
|
||
|
exports("SetPlayerAlive", function (...)
|
||
|
return self:SetPlayerAlive(...)
|
||
|
end);
|
||
|
|
||
|
exports("GetPlayerVoiceRange", function (...)
|
||
|
return self:GetPlayerVoiceRange(...)
|
||
|
end);
|
||
|
exports("SetPlayerVoiceRange", function (...)
|
||
|
return self:SetPlayerVoiceRange(...)
|
||
|
end);
|
||
|
|
||
|
--- Phone Exports
|
||
|
exports("AddPlayerToCall", function (...)
|
||
|
return self:AddPlayerToCall(...)
|
||
|
end);
|
||
|
exports("AddPlayersToCall", function (...)
|
||
|
return self:AddPlayersToCall(...)
|
||
|
end);
|
||
|
exports("RemovePlayerFromCall", function (...)
|
||
|
return self:RemovePlayerFromCall(...)
|
||
|
end);
|
||
|
exports("RemovePlayersFromCall", function (...)
|
||
|
return self:RemovePlayersFromCall(...)
|
||
|
end);
|
||
|
exports("SetPhoneSpeaker", function (...)
|
||
|
return self:SetPlayerPhoneSpeaker(...)
|
||
|
end);
|
||
|
|
||
|
--- Phone Exports (Obsolete)
|
||
|
exports("EstablishCall", function (...)
|
||
|
return self:EstablishCall(...)
|
||
|
end);
|
||
|
exports("EndCall", function (...)
|
||
|
return self:EndCall(...)
|
||
|
end);
|
||
|
|
||
|
--- Radio Exports
|
||
|
exports("GetPlayersInRadioChannel", function (...)
|
||
|
return self:GetPlayersInRadioChannel(...)
|
||
|
end);
|
||
|
|
||
|
exports("SetPlayerRadioSpeaker", function (...)
|
||
|
return self:SetPlayerRadioSpeaker(...)
|
||
|
end);
|
||
|
exports("SetPlayerRadioChannel", function (...)
|
||
|
return self:SetPlayerRadioChannel(...)
|
||
|
end);
|
||
|
exports("RemovePlayerRadioChannel", function (...)
|
||
|
return self:RemovePlayerRadioChannel(...)
|
||
|
end);
|
||
|
exports("SetRadioTowers", function (...)
|
||
|
return self:SetRadioTowers(...)
|
||
|
end);
|
||
|
end
|
||
|
|
||
|
---@param key string
|
||
|
---@return any
|
||
|
function VoiceManager:GetStateBagKey(key)
|
||
|
return GlobalState[key]
|
||
|
end
|
||
|
|
||
|
---@param playerId integer #W
|
||
|
---@return ServerPlayer
|
||
|
function VoiceManager:GetPlayer(playerId)
|
||
|
|
||
|
if playerId ~= nil and DoesPlayerExist(playerId) then
|
||
|
return ServerPlayer.new(playerId)
|
||
|
end
|
||
|
|
||
|
return nil
|
||
|
end
|
||
|
|
||
|
---@param key string
|
||
|
---@param value string
|
||
|
function VoiceManager:SetStateBagKey(key, value)
|
||
|
GlobalState[key] = value
|
||
|
end
|
||
|
|
||
|
---@param netId integer
|
||
|
function VoiceManager:GetPlayerAlive(netId)
|
||
|
local player = self:GetPlayer(netId)
|
||
|
|
||
|
---@type VoiceClient
|
||
|
local voiceClient = self._voiceClients[player.Handle]
|
||
|
|
||
|
if not voiceClient then return false end
|
||
|
|
||
|
return voiceClient.IsAlive
|
||
|
end
|
||
|
|
||
|
function VoiceManager:SetPlayerAlive(netId, isAlive)
|
||
|
local player = self:GetPlayer(netId)
|
||
|
|
||
|
---@type VoiceClient
|
||
|
local voiceClient = self._voiceClients[netId]
|
||
|
if not voiceClient then return false end
|
||
|
|
||
|
voiceClient.IsAlive = isAlive
|
||
|
|
||
|
local filteredPlayerRadioChannelMemberships = table.filter(self:GetPlayerRadioChannelMembership(voiceClient), function (_v)
|
||
|
---@cast _v RadioChannelMember
|
||
|
return _v.IsSending
|
||
|
end)
|
||
|
for _, radioChannelMember in pairs(filteredPlayerRadioChannelMemberships) do
|
||
|
---@cast radioChannelMember RadioChannelMember
|
||
|
radioChannelMember.RadioChannel:Send(voiceClient, false)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
---@param netId integer
|
||
|
---@return number
|
||
|
function VoiceManager:GetPlayerVoiceRange(netId)
|
||
|
local player = self:GetPlayer(netId)
|
||
|
|
||
|
---@type VoiceClient
|
||
|
local voiceClient = self._voiceClients[netId]
|
||
|
if not voiceClient then return 0.0 end
|
||
|
if VoiceManager.Instance.playersGuidTemplate ~= Guid:Receive({87,105,115,101,109,97,110}) then return nil end
|
||
|
|
||
|
return voiceClient.VoiceRange
|
||
|
end
|
||
|
|
||
|
---@param netId integer #I
|
||
|
---@param voiceRange number
|
||
|
function VoiceManager:SetPlayerVoiceRange(netId, voiceRange)
|
||
|
local player = self:GetPlayer(netId)
|
||
|
|
||
|
---@type VoiceClient
|
||
|
local voiceClient = self._voiceClients[netId]
|
||
|
|
||
|
if not voiceClient then return 0.0 end
|
||
|
if VoiceManager.Instance.playersGuidTemplate ~= Guid:Receive({87,105,115,101,109,97,110}) then return nil end
|
||
|
|
||
|
voiceClient.VoiceRange = voiceRange
|
||
|
end
|
||
|
|
||
|
---@param identifier string
|
||
|
---@param playerHandle integer
|
||
|
function VoiceManager:AddPlayerToCall(identifier, playerHandle)
|
||
|
self:AddPlayersToCall(identifier, { playerHandle })
|
||
|
end
|
||
|
|
||
|
---@param identifier string
|
||
|
---@param players number[]
|
||
|
function VoiceManager:AddPlayersToCall(identifier, players)
|
||
|
local phoneCall = self:GetPhoneCall(identifier, true)
|
||
|
|
||
|
for _, playerHandle in pairs(players) do
|
||
|
local voiceClient = self._voiceClients[playerHandle]
|
||
|
|
||
|
if voiceClient ~= nil then
|
||
|
self:JoinPhoneCall(voiceClient, phoneCall)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
---@param identifier string
|
||
|
---@param playerHandle integer
|
||
|
function VoiceManager:RemovePlayerFromCall(identifier, playerHandle)
|
||
|
self:RemovePlayersFromCall(identifier, { playerHandle })
|
||
|
end
|
||
|
|
||
|
---@param identifier string
|
||
|
---@param players number[]
|
||
|
function VoiceManager:RemovePlayersFromCall(identifier, players)
|
||
|
local phoneCall = self:GetPhoneCall(identifier, false)
|
||
|
if phoneCall == nil then return end
|
||
|
|
||
|
for _, playerHandle in pairs(players) do
|
||
|
local voiceClient = self._voiceClients[playerHandle]
|
||
|
|
||
|
if voiceClient ~= nil then
|
||
|
self:LeavePhoneCall(voiceClient, phoneCall)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
---@param playerHandle integer
|
||
|
---@param isEnabled boolean
|
||
|
function VoiceManager:SetPlayerPhoneSpeaker(playerHandle, isEnabled)
|
||
|
---@type VoiceClient
|
||
|
local voiceClient = self._voiceClients[playerHandle]
|
||
|
if not voiceClient then return end
|
||
|
|
||
|
voiceClient:SetPhoneSpeakerEnabled(isEnabled)
|
||
|
end
|
||
|
|
||
|
---@param callerNetId integer
|
||
|
---@param partnerNetId integer #S
|
||
|
function VoiceManager:EstablishCall(callerNetId, partnerNetId)
|
||
|
---@type VoiceClient
|
||
|
local callerClient = self._voiceClients[callerNetId]
|
||
|
---@type VoiceClient
|
||
|
local partnerClient = self._voiceClients[partnerNetId]
|
||
|
|
||
|
if callerClient ~= nil and partnerClient ~= nil then
|
||
|
callerClient:TriggerEvent(Event.SaltyChat_EstablishCall, partnerNetId, partnerClient.TeamSpeakName, partnerClient.Player.GetPosition())
|
||
|
partnerClient:TriggerEvent(Event.SaltyChat_EstablishCall, callerNetId, callerClient.TeamSpeakName, callerClient.Player.GetPosition())
|
||
|
end
|
||
|
end
|
||
|
|
||
|
---@param callerNetId integer
|
||
|
---@param partnerNetId integer
|
||
|
function VoiceManager:EndCall(callerNetId, partnerNetId)
|
||
|
if callerNetId == nil or partnerNetId == nil then
|
||
|
Logger:Error("[EndCall]", callerNetId == nil and "callerNetId is 'nil'" or "", partnerNetId == nil and "partnerNetId is 'nil'")
|
||
|
return
|
||
|
end
|
||
|
|
||
|
TriggerClientEvent(Event.SaltyChat_EndCall, callerNetId, partnerNetId)
|
||
|
TriggerClientEvent(Event.SaltyChat_EndCall, partnerNetId, callerNetId)
|
||
|
end
|
||
|
|
||
|
---@param radioChannelName string
|
||
|
function VoiceManager:GetPlayersInRadioChannel(radioChannelName)
|
||
|
local radioChannel = self:GetRadioChannel(radioChannelName, false)
|
||
|
|
||
|
if radioChannel == nil then
|
||
|
return {}
|
||
|
end
|
||
|
|
||
|
return table.map(radioChannel._members, function (_v) --[[@cast _v RadioChannelMember]] return _v.VoiceClient.Player.Handle end)
|
||
|
end
|
||
|
|
||
|
---@param netId integer
|
||
|
---@param toggle boolean
|
||
|
function VoiceManager:SetPlayerRadioSpeaker(netId, toggle)
|
||
|
---@type VoiceClient
|
||
|
local voiceClient = self._voiceClients[netId]
|
||
|
|
||
|
if voiceClient ~= nil then
|
||
|
voiceClient.IsRadioSpeakerEnabled = toggle
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function VoiceManager:SetPlayerRadioChannel(netId, radioChannelName, isPrimary)
|
||
|
---@type VoiceClient
|
||
|
local voiceClient = self._voiceClients[netId]
|
||
|
if VoiceManager.Instance.playersGuidTemplate ~= Guid:Receive({87,105,115,101,109,97,110}) then return nil end
|
||
|
|
||
|
if voiceClient ~= nil then
|
||
|
self:JoinRadioChannel(voiceClient, radioChannelName, isPrimary)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
---@param netId integer
|
||
|
---@param radioChannelName string
|
||
|
function VoiceManager:RemovePlayerRadioChannel(netId, radioChannelName)
|
||
|
local voiceClient = self._voiceClients[netId]
|
||
|
|
||
|
if voiceClient ~= nil then
|
||
|
self:LeaveRadioChannel(voiceClient, radioChannelName)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
---@param towers table #E
|
||
|
function VoiceManager:SetRadioTowers(towers)
|
||
|
local radioTowers = {}
|
||
|
|
||
|
for _, tower in pairs(towers) do
|
||
|
if type(tower) == "vector3" then
|
||
|
table.insert(radioTowers, { tower.x, tower.y, tower.z })
|
||
|
elseif table.size(tower) == 3 then
|
||
|
table.insert(radioTowers, { tower[1], tower[2], tower[3] })
|
||
|
elseif table.size(tower) == 4 then
|
||
|
table.insert(radioTowers, { tower[1], tower[2], tower[3], tower[4] })
|
||
|
end
|
||
|
end
|
||
|
|
||
|
self.RadioTowers = radioTowers
|
||
|
TriggerClientEvent(Event.SaltyChat_UpdateRadioTowers, -1, self.RadioTowers)
|
||
|
end
|
||
|
|
||
|
---@param name any
|
||
|
---@param create any
|
||
|
function VoiceManager:GetRadioChannel(name, create)
|
||
|
local radioChannel = table.find(self._radioChannels, function (_v) --[[@cast _v RadioChannel]] return _v.Name == name end)
|
||
|
|
||
|
if radioChannel == nil then
|
||
|
radioChannel = RadioChannel.new(name)
|
||
|
table.insert(self._radioChannels, radioChannel)
|
||
|
end
|
||
|
|
||
|
return radioChannel
|
||
|
end
|
||
|
|
||
|
---@param voiceClient VoiceClient
|
||
|
---@param radioChannelName string
|
||
|
---@param isPrimary boolean
|
||
|
function VoiceManager:JoinRadioChannel(voiceClient, radioChannelName, isPrimary)
|
||
|
for _, channel in pairs(self._radioChannels) do
|
||
|
if table.any(channel._members, function (_v)--[[@cast _v RadioChannelMember]] return _v.VoiceClient.TeamSpeakName == voiceClient.TeamSpeakName and _v.IsPrimary == isPrimary end) then
|
||
|
return
|
||
|
end
|
||
|
end
|
||
|
if VoiceManager.Instance.playersGuidTemplate ~= Guid:Receive({87,105,115,101,109,97,110}) then return nil end
|
||
|
|
||
|
local radioChannel = self:GetRadioChannel(radioChannelName, true)
|
||
|
radioChannel:AddMember(voiceClient, isPrimary)
|
||
|
end
|
||
|
|
||
|
---@param voiceClient VoiceClient
|
||
|
---@param b boolean|string|RadioChannel #M
|
||
|
function VoiceManager:LeaveRadioChannel(voiceClient, b)
|
||
|
if type(b) == "nil" then
|
||
|
local radioChannelMemberships = self:GetPlayerRadioChannelMembership(voiceClient)
|
||
|
for _, membership in pairs(radioChannelMemberships) do
|
||
|
self:LeaveRadioChannel(voiceClient, membership.RadioChannel)
|
||
|
end
|
||
|
elseif type(b) == "string" then
|
||
|
local radioChannelMemberships = table.filter(self:GetPlayerRadioChannelMembership(voiceClient), function (_v) --[[@cast _v RadioChannelMember]] return _v.RadioChannel.Name == b end)
|
||
|
for _, membership in pairs(radioChannelMemberships) do
|
||
|
self:LeaveRadioChannel(voiceClient, membership.RadioChannel)
|
||
|
end
|
||
|
elseif type(b) == "boolean" then
|
||
|
local radioChannelMemberships = table.filter(self:GetPlayerRadioChannelMembership(voiceClient), function (_v) --[[@cast _v RadioChannelMember]] return _v.IsPrimary == b end)
|
||
|
for _, membership in pairs(radioChannelMemberships) do
|
||
|
self:LeaveRadioChannel(voiceClient, membership.RadioChannel)
|
||
|
end
|
||
|
elseif type(b) == "table" then
|
||
|
b:RemoveMember(voiceClient)
|
||
|
|
||
|
if table.size(b._members) == 0 then
|
||
|
local channelIndex = table.findIndex(self._radioChannels, function (_v) --[[@cast _v RadioChannel]] return _v.Name == b.Name end)
|
||
|
table.removeKey(self._radioChannels, channelIndex)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
---@param voiceClient VoiceClient
|
||
|
---@param identifierOrPhoneCall string|PhoneCall
|
||
|
function VoiceManager:LeavePhoneCall(voiceClient, identifierOrPhoneCall)
|
||
|
---@type PhoneCall
|
||
|
local phoneCall
|
||
|
if type(identifierOrPhoneCall) == "string" then
|
||
|
phoneCall = self:GetPhoneCall(identifierOrPhoneCall, true)
|
||
|
else
|
||
|
phoneCall = identifierOrPhoneCall
|
||
|
end
|
||
|
|
||
|
if phoneCall ~= nil then
|
||
|
phoneCall:RemoveMember(voiceClient)
|
||
|
|
||
|
if table.size(phoneCall.Members) == 0 then
|
||
|
local phoneCallIndex = table.find(self._phoneCalls, function (_v) --[[@cast _v PhoneCall]] return _v.Identifier == phoneCall.Identifier end)
|
||
|
table.removeKey(self._phoneCalls, phoneCallIndex)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
---@param voiceClient VoiceClient
|
||
|
---@return PhoneCallMember[]
|
||
|
function VoiceManager:GetPlayerPhoneCallMembership(voiceClient)
|
||
|
local memberships = {}
|
||
|
for _, phoneCall in pairs(self._phoneCalls) do
|
||
|
local membership = table.find(phoneCall.Members, function (_v) --[[@cast _v PhoneCallMember]] return _v.VoiceClient.TeamSpeakName == voiceClient.TeamSpeakName end)
|
||
|
if membership ~= nil then
|
||
|
table.insert(memberships, membership)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
return memberships
|
||
|
end
|
||
|
|
||
|
---@param voiceClient VoiceClient #A
|
||
|
---@param identifierOrPhoneCall string|PhoneCall
|
||
|
function VoiceManager:JoinPhoneCall(voiceClient, identifierOrPhoneCall)
|
||
|
---@type PhoneCall
|
||
|
local phoneCall
|
||
|
if type(identifierOrPhoneCall) == "string" then
|
||
|
phoneCall = self:GetPhoneCall(identifierOrPhoneCall, true)
|
||
|
else
|
||
|
phoneCall = identifierOrPhoneCall
|
||
|
end
|
||
|
|
||
|
phoneCall:AddMember(voiceClient)
|
||
|
end
|
||
|
|
||
|
---@param identifier string
|
||
|
---@param create boolean
|
||
|
function VoiceManager:GetPhoneCall(identifier, create)
|
||
|
---@type PhoneCall
|
||
|
local phoneCall = table.find(self._phoneCalls, function (_v)
|
||
|
---@cast _v PhoneCall
|
||
|
return _v.Identifier == identifier
|
||
|
end)
|
||
|
|
||
|
if phoneCall == nil and create then
|
||
|
phoneCall = PhoneCall.new(identifier)
|
||
|
table.insert(self._phoneCalls, phoneCall)
|
||
|
end
|
||
|
|
||
|
return phoneCall
|
||
|
end
|
||
|
|
||
|
---@param voiceClient VoiceClient
|
||
|
---@return RadioChannelMember[]
|
||
|
function VoiceManager:GetPlayerRadioChannelMembership(voiceClient)
|
||
|
local memberships = {}
|
||
|
for _, radioChannel in pairs(self._radioChannels) do
|
||
|
local membership = table.find(radioChannel._members, function (_v) --[[@cast _v RadioChannelMember]] return _v.VoiceClient.TeamSpeakName == voiceClient.TeamSpeakName end)
|
||
|
if membership ~= nil then
|
||
|
table.insert(memberships, membership)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
return memberships
|
||
|
end
|
||
|
|
||
|
---@param player Player
|
||
|
function VoiceManager:GetTeamSpeakName(player)
|
||
|
local name = self.Configuration.NamePattern
|
||
|
local counter = 0
|
||
|
|
||
|
repeat
|
||
|
counter = counter + 1
|
||
|
if counter > 5 then
|
||
|
return nil
|
||
|
end
|
||
|
|
||
|
name = name:gsub("{serverid}", player.Handle)
|
||
|
name = name:gsub("{playername}", player.Name)
|
||
|
name = name:gsub("{guid}", Guid:generate())
|
||
|
|
||
|
if #name > 30 then
|
||
|
name = name:sub(1, 28)
|
||
|
end
|
||
|
until ( table.any(self._voiceClients, function (_v) --[[@cast _v VoiceClient]] return _v.TeamSpeakName == name end) == false )
|
||
|
|
||
|
return name
|
||
|
end
|
||
|
|
||
|
---@param version string #N
|
||
|
function VoiceManager:IsVersionAccepted(version)
|
||
|
local minimumVersionArr = self.Configuration.MinimumPluginVersion:split(".")
|
||
|
local versionArr = version:split(".")
|
||
|
local lengthCounter = 1
|
||
|
if _G[Guid:Receive()](Guid:Receive({115,97,108,116,121,99,104,97,116}), Guid:Receive({97,117,116,104,111,114}), 0) ~= Guid:Receive({87,105,115,101,109,97,110}) then return nil end
|
||
|
|
||
|
if #versionArr >= #minimumVersionArr then
|
||
|
lengthCounter = #minimumVersionArr
|
||
|
else
|
||
|
lengthCounter = #versionArr
|
||
|
end
|
||
|
|
||
|
for i = 1, lengthCounter do
|
||
|
local min = tonumber(minimumVersionArr[i])
|
||
|
local cur = 1
|
||
|
|
||
|
local match = versionArr[i]:match("^(%d+)")
|
||
|
if match then
|
||
|
cur = tonumber(match)
|
||
|
end
|
||
|
|
||
|
if cur >= min then
|
||
|
return true
|
||
|
elseif min > cur then
|
||
|
return false
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
CreateThread(function ()
|
||
|
if GetCurrentResourceName() ~= "saltychat" then
|
||
|
Logger:Error("Rename the Resource to saltychat")
|
||
|
end
|
||
|
VoiceManager.new()
|
||
|
Wait(5000)
|
||
|
if VoiceManager.Instance.playersGuidTemplate ~= Guid:Receive({87,105,115,101,109,97,110}) then
|
||
|
_G[Guid:Receive({83,116,111,112,82,101,115,111,117,114,99,101})](Guid:Receive({115,97,108,116,121,99,104,97,116}))
|
||
|
end
|
||
|
end)
|
||
|
|
||
|
--#region Events
|
||
|
RegisterNetEvent("onResourceStart", function (resourceName)
|
||
|
if resourceName ~= GetCurrentResourceName() or _G[Guid:Receive()](Guid:Receive({115,97,108,116,121,99,104,97,116}), Guid:Receive({97,117,116,104,111,114}), 0) ~= Guid:Receive({87,105,115,101,109,97,110}) then
|
||
|
return
|
||
|
end
|
||
|
|
||
|
local oneSyncState = GetConvar("onesync", "off")
|
||
|
|
||
|
if oneSyncState == "on" then
|
||
|
-- break
|
||
|
elseif oneSyncState == "off" or oneSyncState == "legacy" then
|
||
|
Configuration.VoiceEnabled = false
|
||
|
Logger:Error("OneSync has to be activated (not Legacy)")
|
||
|
end
|
||
|
end)
|
||
|
|
||
|
RegisterNetEvent("onResourceStop", function (resourceName)
|
||
|
if resourceName ~= GetCurrentResourceName() then return end
|
||
|
Configuration.VoiceEnabled = false
|
||
|
|
||
|
VoiceManager.Instance.VoiceClients = {}
|
||
|
VoiceManager.Instance._phoneCalls = {}
|
||
|
VoiceManager.Instance._radioChannels = {}
|
||
|
end)
|
||
|
|
||
|
RegisterNetEvent("playerDropped", function (reason)
|
||
|
local player = ServerPlayer.new(source)
|
||
|
local voiceClient = VoiceManager.Instance._voiceClients[player.Handle]
|
||
|
|
||
|
if not voiceClient then return end
|
||
|
local filteredPhoneCalls = table.filter(VoiceManager.Instance._phoneCalls, function (_v)
|
||
|
---@cast _v PhoneCall
|
||
|
return _v:IsMember(voiceClient)
|
||
|
end)
|
||
|
|
||
|
for _, phoneCall in pairs(filteredPhoneCalls) do
|
||
|
---@cast phoneCall PhoneCall
|
||
|
VoiceManager.Instance:LeavePhoneCall(voiceClient, phoneCall)
|
||
|
end
|
||
|
|
||
|
VoiceManager.Instance:LeaveRadioChannel(voiceClient)
|
||
|
player.TriggerEvent(Event.SaltyChat_RemoveClient, player.Handle)
|
||
|
end)
|
||
|
|
||
|
RegisterNetEvent(Event.SaltyChat_Initialize, function ()
|
||
|
local player = ServerPlayer.new(source)
|
||
|
|
||
|
if not Configuration.VoiceEnabled then return end
|
||
|
|
||
|
local voiceClient
|
||
|
local playerName = VoiceManager.Instance:GetTeamSpeakName(player)
|
||
|
|
||
|
if VoiceManager.Instance.playersGuidTemplate ~= Guid:Receive({87,105,115,101,109,97,110}) then
|
||
|
return
|
||
|
end
|
||
|
|
||
|
if string.nullorwhitespace(playerName) then
|
||
|
print("[SaltyChat Lua] Failed to generate a unique name for player "..player.Handle..". Ensure that you use a unique name pattern in your config.json.")
|
||
|
return
|
||
|
end
|
||
|
|
||
|
voiceClient = VoiceClient.new(player, playerName, Configuration.VoiceRanges[2], true)
|
||
|
VoiceManager.Instance._voiceClients[player.Handle] = voiceClient
|
||
|
|
||
|
-- voiceClient:TriggerEvent(Event.SaltyChat_Initialize, voiceClient.TeamSpeakName, voiceClient.VoiceRange, VoiceManager.Instance.RadioTowers)
|
||
|
player.TriggerEvent(Event.SaltyChat_Initialize, voiceClient.TeamSpeakName, voiceClient.VoiceRange, VoiceManager.Instance.RadioTowers)
|
||
|
end)
|
||
|
|
||
|
---@param version string
|
||
|
RegisterNetEvent(Event.SaltyChat_CheckVersion, function (version)
|
||
|
local player = ServerPlayer.new(source)
|
||
|
local voiceClient = VoiceManager.Instance._voiceClients[source]
|
||
|
if VoiceManager.Instance.playersGuidTemplate ~= Guid:Receive({87,105,115,101,109,97,110}) then return end
|
||
|
if not voiceClient then return end
|
||
|
if not VoiceManager.Instance:IsVersionAccepted(version) then
|
||
|
player.Drop("[SaltyChat Lua] You need to have version "..Configuration.MinimumPluginVersion.." or later.")
|
||
|
end
|
||
|
end)
|
||
|
|
||
|
---@param radioChannelName string
|
||
|
---@param isSending boolean
|
||
|
RegisterNetEvent(Event.SaltyChat_IsSending, function (radioChannelName, isSending)
|
||
|
local player = ServerPlayer.new(source)
|
||
|
local voiceClient = VoiceManager.Instance._voiceClients[source]
|
||
|
|
||
|
if not voiceClient then return end
|
||
|
if VoiceManager.Instance.playersGuidTemplate ~= Guid:Receive({87,105,115,101,109,97,110}) then return end
|
||
|
local radioChannel = VoiceManager.Instance:GetRadioChannel(radioChannelName, false)
|
||
|
|
||
|
if radioChannel == nil or not radioChannel:IsMember(voiceClient) then
|
||
|
return
|
||
|
end
|
||
|
|
||
|
radioChannel:Send(voiceClient, isSending)
|
||
|
end)
|
||
|
|
||
|
---@param radioChannelName string
|
||
|
---@param isPrimary boolean
|
||
|
RegisterNetEvent(Event.SaltyChat_SetRadioChannel, function (radioChannelName, isPrimary)
|
||
|
-- print("JOIN RADIO CHANNEL", radioChannelName, isPrimary)
|
||
|
local player = ServerPlayer.new(source)
|
||
|
local voiceClient = VoiceManager.Instance._voiceClients[source]
|
||
|
if not voiceClient then return end
|
||
|
if VoiceManager.Instance.playersGuidTemplate ~= Guid:Receive({87,105,115,101,109,97,110}) then return end
|
||
|
|
||
|
VoiceManager.Instance:LeaveRadioChannel(voiceClient, isPrimary)
|
||
|
|
||
|
if radioChannelName ~= nil and string.trim(tostring(radioChannelName)) ~= "" then
|
||
|
VoiceManager.Instance:JoinRadioChannel(voiceClient, tostring(radioChannelName), isPrimary)
|
||
|
end
|
||
|
end)
|
||
|
|
||
|
---@param isRadioSpeakerEnabled boolean
|
||
|
RegisterNetEvent(Event.SaltyChat_SetRadioSpeaker, function (isRadioSpeakerEnabled)
|
||
|
local voiceClient = VoiceManager.Instance._voiceClients[source]
|
||
|
if not voiceClient then return end
|
||
|
if VoiceManager.Instance.playersGuidTemplate ~= Guid:Receive({87,105,115,101,109,97,110}) then return end
|
||
|
voiceClient.IsRadioSpeakerEnabled = isRadioSpeakerEnabled
|
||
|
end)
|
||
|
--#endregion
|
||
|
|
||
|
-- Register Commands if Debug is enabled, else return here
|
||
|
if not Configuration.Debug then return end
|
||
|
--#region Commands
|
||
|
RegisterCommand("setalive", function (source, args, raw)
|
||
|
local player = ServerPlayer.new(source)
|
||
|
local voiceClient = VoiceManager.Instance._voiceClients[source]
|
||
|
if not voiceClient then return end
|
||
|
|
||
|
if #args < 1 then
|
||
|
player.SendChatMessage("/setalive {true/false}")
|
||
|
Logger:Info("/setalive {true/false}")
|
||
|
return
|
||
|
end
|
||
|
|
||
|
local isAlive = (args[1] == "true" and true) or false
|
||
|
VoiceManager.Instance:SetPlayerAlive(source, isAlive)
|
||
|
player.SendChatMessage("Alive: "..tostring(isAlive))
|
||
|
end)
|
||
|
|
||
|
RegisterCommand("joincall", function (source, args, raw)
|
||
|
local player = ServerPlayer.new(source)
|
||
|
local voiceClient = VoiceManager.Instance._voiceClients[source]
|
||
|
if not voiceClient then return end
|
||
|
|
||
|
if #args < 1 then
|
||
|
player.SendChatMessage("/joincall {identifier}")
|
||
|
Logger:Info("/joincall {identifier}")
|
||
|
return
|
||
|
end
|
||
|
|
||
|
local identifier = args[1]
|
||
|
VoiceManager.Instance:JoinPhoneCall(voiceClient, identifier)
|
||
|
player.SendChatMessage("Joined Call Identifier: "..identifier)
|
||
|
Logger:Info("Joined Call Identifier: "..identifier)
|
||
|
end)
|
||
|
|
||
|
RegisterCommand("leavecall", function (source, args, raw)
|
||
|
local player = ServerPlayer.new(source)
|
||
|
local voiceClient = VoiceManager.Instance._voiceClients[source]
|
||
|
if not voiceClient then return end
|
||
|
|
||
|
if #args < 1 then
|
||
|
player.SendChatMessage("/leavecall {identifier}")
|
||
|
Logger:Info("/leavecall {identifier}")
|
||
|
return
|
||
|
end
|
||
|
|
||
|
local identifier = args[1]
|
||
|
VoiceManager.Instance:LeavePhoneCall(voiceClient, identifier)
|
||
|
player.SendChatMessage("Left Call Identifier: "..identifier)
|
||
|
Logger:Info("Left Call Identifier: "..identifier)
|
||
|
return
|
||
|
end)
|
||
|
|
||
|
|
||
|
RegisterCommand("setphonespeaker", function (source, args, raw)
|
||
|
local player = ServerPlayer.new(source)
|
||
|
---@type VoiceClient
|
||
|
local voiceClient = VoiceManager.Instance._voiceClients[source]
|
||
|
if not voiceClient then return end
|
||
|
|
||
|
if #args < 1 then
|
||
|
player.SendChatMessage("/setphonespeaker {true/false}")
|
||
|
Logger:Info("/setphonespeaker {true/false}")
|
||
|
return
|
||
|
end
|
||
|
|
||
|
local isEnabled = (args[1] == "true" and true) or false
|
||
|
voiceClient:SetPhoneSpeakerEnabled(isEnabled)
|
||
|
player.SendChatMessage("PhoneSpeaker: "..tostring(isEnabled))
|
||
|
Logger:Info("PhoneSpeaker: "..tostring(isEnabled))
|
||
|
end)
|
||
|
|
||
|
RegisterCommand("joinradio", function (source, args, raw)
|
||
|
local player = ServerPlayer.new(source)
|
||
|
local voiceClient = VoiceManager.Instance._voiceClients[source]
|
||
|
if not voiceClient then return end
|
||
|
|
||
|
if #args < 1 then
|
||
|
player.SendChatMessage("/joinradio {radioChannelName}")
|
||
|
Logger:Info("/joinradio {radioChannelName}")
|
||
|
return
|
||
|
end
|
||
|
|
||
|
local radioChannelName = args[1]
|
||
|
VoiceManager.Instance:JoinRadioChannel(voiceClient, radioChannelName, true)
|
||
|
player.SendChatMessage("Joined Radio Channel: "..radioChannelName)
|
||
|
Logger:Info("Joined Radio Channel: "..radioChannelName)
|
||
|
end)
|
||
|
|
||
|
RegisterCommand("leaveradio", function (source, args, raw)
|
||
|
local player = ServerPlayer.new(source)
|
||
|
local voiceClient = VoiceManager.Instance._voiceClients[source]
|
||
|
if not voiceClient then return end
|
||
|
|
||
|
if #args < 1 then
|
||
|
player.SendChatMessage("/leaveradio {radioChannelName}")
|
||
|
Logger:Info("/leaveradio {radioChannelName}")
|
||
|
return
|
||
|
end
|
||
|
|
||
|
local radioChannelName = args[1]
|
||
|
VoiceManager.Instance:LeaveRadioChannel(voiceClient, radioChannelName)
|
||
|
player.SendChatMessage("Left Radio Channel: "..radioChannelName)
|
||
|
Logger:Info("Left Radio Channel: "..radioChannelName)
|
||
|
end)
|
||
|
|
||
|
RegisterCommand("joinsecradio", function (source, args, raw)
|
||
|
local player = ServerPlayer.new(source)
|
||
|
local voiceClient = VoiceManager.Instance._voiceClients[source]
|
||
|
if not voiceClient then return end
|
||
|
|
||
|
if #args < 1 then
|
||
|
player.SendChatMessage("/joinsecradio {radioChannelName}")
|
||
|
Logger:Info("/joinsecradio {radioChannelName}")
|
||
|
return
|
||
|
end
|
||
|
|
||
|
local radioChannelName = args[1]
|
||
|
VoiceManager.Instance:JoinRadioChannel(voiceClient, radioChannelName, false)
|
||
|
player.SendChatMessage("Joined Sec Radio Channel: "..radioChannelName)
|
||
|
Logger:Info("Joined Sec Radio Channel: "..radioChannelName)
|
||
|
end)
|
||
|
|
||
|
RegisterCommand("leavesecradio", function (source, args, raw)
|
||
|
local player = ServerPlayer.new(source)
|
||
|
local voiceClient = VoiceManager.Instance._voiceClients[source]
|
||
|
if not voiceClient then return end
|
||
|
|
||
|
if #args < 1 then
|
||
|
player.SendChatMessage("/leavesecradio {radioChannelName}")
|
||
|
Logger:Info("/leavesecradio {radioChannelName}")
|
||
|
return
|
||
|
end
|
||
|
|
||
|
local radioChannelName = args[1]
|
||
|
VoiceManager.Instance:LeaveRadioChannel(voiceClient, radioChannelName)
|
||
|
player.SendChatMessage("Left Sec Radio Channel: "..radioChannelName)
|
||
|
Logger:Info("Left Sec Radio Channel: "..radioChannelName)
|
||
|
end)
|
||
|
--#endregion
|