772 lines
		
	
	
	
		
			25 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
			
		
		
	
	
			772 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
 |