From 5c160212e190f74461d65fac1668cda07a2d0b11 Mon Sep 17 00:00:00 2001 From: srslyyyy <51768772+srslyyyy@users.noreply.github.com> Date: Sun, 21 Jul 2024 19:17:43 +0200 Subject: [PATCH] internetradio: error fix & admin commands (#524) --- .../internetradio/config/CRadioConfig.lua | 2 +- .../internetradio/config/SRadioConfig.lua | 6 +- .../handle_radio/CHandleRadio.lua | 23 ++- .../handle_radio/SHandleRadio.lua | 157 ++++++++++++++---- .../handle_radio/ShHandleRadio.lua | 29 ++++ 5 files changed, 176 insertions(+), 41 deletions(-) diff --git a/[gameplay]/internetradio/config/CRadioConfig.lua b/[gameplay]/internetradio/config/CRadioConfig.lua index 2da6babb3..46979f991 100644 --- a/[gameplay]/internetradio/config/CRadioConfig.lua +++ b/[gameplay]/internetradio/config/CRadioConfig.lua @@ -21,4 +21,4 @@ RADIO_SETTINGS_TEMPLATE = { ["boolean"] = true, }, }, -} +} \ No newline at end of file diff --git a/[gameplay]/internetradio/config/SRadioConfig.lua b/[gameplay]/internetradio/config/SRadioConfig.lua index 02648c32f..f03ab37ec 100644 --- a/[gameplay]/internetradio/config/SRadioConfig.lua +++ b/[gameplay]/internetradio/config/SRadioConfig.lua @@ -6,4 +6,8 @@ RADIO_BOX_MODEL = 2229 RADIO_DESTROY_ON_VEHICLE_EXPLODE = false -RADIO_DESTROY_ON_VEHICLE_DESTROY = false \ No newline at end of file +RADIO_DESTROY_ON_VEHICLE_DESTROY = false +RADIO_DESTROY_SPEAKER_COMMAND = "destroyspeaker" +RADIO_DESTROY_SPEAKER_ACCESS_RIGHT = "function.kickPlayer" +RADIO_DESTROY_SPEAKERS_IN_RANGE_COMMAND = "destroyspeakers" +RADIO_DESTROY_SPEAKERS_IN_RANGE_ACCESS_RIGHT = "function.kickPlayer" \ No newline at end of file diff --git a/[gameplay]/internetradio/handle_radio/CHandleRadio.lua b/[gameplay]/internetradio/handle_radio/CHandleRadio.lua index c2856137f..edfdf8193 100644 --- a/[gameplay]/internetradio/handle_radio/CHandleRadio.lua +++ b/[gameplay]/internetradio/handle_radio/CHandleRadio.lua @@ -267,15 +267,24 @@ function clearPlayerSpeaker(playerOrSpeaker) end function isObjectSpeaker(objectElement) + local validElement = isElement(objectElement) + + if (not validElement) then + return false + end + for playerElement, speakerData in pairs(playerSpeakers) do - local speakerBox = speakerData.speakerBox - local matchingElement = (speakerBox == objectElement) - if (matchingElement) then - local speakerSound = speakerSounds[playerElement] - local speakerDummy = speakerData.speakerDummy + if (speakerData) then + local speakerBox = speakerData.speakerBox + local matchingElement = (speakerBox == objectElement) - return true, speakerSound, speakerDummy + if (matchingElement) then + local speakerSound = speakerSounds[playerElement] + local speakerDummy = speakerData.speakerDummy + + return true, speakerSound, speakerDummy + end end end @@ -328,4 +337,4 @@ function clearSpeakersOnDestroyQuit() clearPlayerSpeaker(source) end addEventHandler("onClientPlayerQuit", root, clearSpeakersOnDestroyQuit) -addEventHandler("onClientElementDestroy", resourceRoot, clearSpeakersOnDestroyQuit) +addEventHandler("onClientElementDestroy", resourceRoot, clearSpeakersOnDestroyQuit) \ No newline at end of file diff --git a/[gameplay]/internetradio/handle_radio/SHandleRadio.lua b/[gameplay]/internetradio/handle_radio/SHandleRadio.lua index 700e406d4..76ec70cd3 100644 --- a/[gameplay]/internetradio/handle_radio/SHandleRadio.lua +++ b/[gameplay]/internetradio/handle_radio/SHandleRadio.lua @@ -31,16 +31,19 @@ function getPlayerSpeakerData(playerElement) return playerSpeakerData end -function clearPlayerSpeaker(playerOrSpeaker) +function clearPlayerSpeaker(playerOrSpeaker, forceDestroy) for playerElement, speakerData in pairs(playerSpeakers) do local speakerBox = speakerData.speakerBox local matchingElement = (playerElement == playerOrSpeaker) or (speakerBox == playerOrSpeaker) if (matchingElement) then - local boxElement = isElement(speakerBox) - if (boxElement) then - destroyElement(speakerBox) + if (forceDestroy) then + local boxElement = isElement(speakerBox) + + if (boxElement) then + destroyElement(speakerBox) + end end playerSpeakers[playerElement] = nil @@ -52,6 +55,25 @@ function clearPlayerSpeaker(playerOrSpeaker) return false end +function isObjectSpeaker(objectElement) + local validElement = isElement(objectElement) + + if (not validElement) then + return false + end + + for playerElement, speakerData in pairs(playerSpeakers) do + local speakerBox = speakerData.speakerBox + local matchingElement = (speakerBox == objectElement) + + if (matchingElement) then + return true + end + end + + return false +end + function onServerCreateSpeaker(streamURL) if (not client) then return false @@ -69,16 +91,7 @@ function onServerCreateSpeaker(streamURL) return false end - local playerSpeakerData = getPlayerSpeakerData(client) - - if (playerSpeakerData) then - local speakerBox = playerSpeakerData.speakerBox - local speakerElement = isElement(speakerBox) - - if (speakerElement) then - destroyElement(speakerBox) - end - end + clearPlayerSpeaker(client, true) local playerPosX, playerPosY, playerPosZ = getElementPosition(client) local playerInterior = getElementInterior(client) @@ -148,18 +161,7 @@ function onServerDestroySpeaker() return false end - local playerSpeakerData = getPlayerSpeakerData(client) - - if (not playerSpeakerData) then - return false - end - - local speakerBox = playerSpeakerData.speakerBox - local speakerElement = isElement(speakerBox) - - if (speakerElement) then - destroyElement(speakerBox) - end + clearPlayerSpeaker(client, true) end addEvent("onServerDestroySpeaker", true) addEventHandler("onServerDestroySpeaker", root, onServerDestroySpeaker) @@ -175,11 +177,102 @@ function syncSpeakers(startedResource) end addEventHandler("onPlayerResourceStart", root, syncSpeakers) -function clearSpeakersOnDestroyQuit() - clearPlayerSpeaker(source) +function clearSpeakerOnPlayerQuit() + clearPlayerSpeaker(source, true) +end +addEventHandler("onPlayerQuit", root, clearSpeakerOnPlayerQuit) + +function clearSpeakerOnElementDestroy() + clearPlayerSpeaker(source, false) +end +addEventHandler("onElementDestroy", resourceRoot, clearSpeakerOnElementDestroy) + +function destroySpeakerAdminCommand(playerElement, _, targetPlayer) + local hasPlayerRightToDestroySpeaker = hasObjectPermissionTo(playerElement, RADIO_DESTROY_SPEAKER_ACCESS_RIGHT, false) + + if (not hasPlayerRightToDestroySpeaker) then + outputChatBox("#ff8800[Speakers]: #ffffffYou have no access to #ff8800/"..RADIO_DESTROY_SPEAKER_COMMAND, playerElement, 255, 255, 255, true) + + return false + end + + if (not targetPlayer) then + outputChatBox("#ff8800[Speakers]: #ffffffSyntax: #ff8800/"..RADIO_DESTROY_SPEAKER_COMMAND.." ", playerElement, 255, 255, 255, true) + + return false + end + + local playerFromName = getPlayerFromPartialName(targetPlayer) + + if (not playerFromName) then + outputChatBox("#ff8800[Speakers]: #ffffffPlayer #ff8800"..targetPlayer.." #ffffffnot found.", playerElement, 255, 255, 255, true) + + return false + end + + local speakerFound = clearPlayerSpeaker(playerFromName, true) + local speakerDestroyed = (speakerFound and "Successfully destroyed #ff8800"..targetPlayer.."#ffffff speaker." or "Player #ff8800"..targetPlayer.."#ffffff has no speaker.") + local speakerDestroyedMessage = "#ff8800[Speakers]: #ffffff"..speakerDestroyed + + outputChatBox(speakerDestroyedMessage, playerElement, 255, 255, 255, true) +end +addCommandHandler(RADIO_DESTROY_SPEAKER_COMMAND, destroySpeakerAdminCommand) + +function destroySpeakersInRangeAdminCommand(playerElement, _, searchRange) + local hasPlayerRightToDestroySpeaker = hasObjectPermissionTo(playerElement, RADIO_DESTROY_SPEAKERS_IN_RANGE_ACCESS_RIGHT, false) + + if (not hasPlayerRightToDestroySpeaker) then + outputChatBox("#ff8800[Speakers]: #ffffffYou have no access to #ff8800/"..RADIO_DESTROY_SPEAKERS_IN_RANGE_COMMAND, playerElement, 255, 255, 255, true) + + return false + end + + local speakerSearchRange = tonumber(searchRange) + local validSearchRange = (speakerSearchRange and speakerSearchRange > 0) + + if (not speakerSearchRange or not validSearchRange) then + outputChatBox("#ff8800[Speakers]: #ffffffSyntax: #ff8800/"..RADIO_DESTROY_SPEAKERS_IN_RANGE_COMMAND.." ", playerElement, 255, 255, 255, true) + + return false + end + + local objectsTable = getElementsByType("object", resourceRoot) + local playerInterior = getElementInterior(playerElement) + local playerDimension = getElementDimension(playerElement) + local playerX, playerY, playerZ = getElementPosition(playerElement) + local totalDestroyedSpeakers = 0 + + for objectID = 1, #objectsTable do + local objectElement = objectsTable[objectID] + local objectSpeaker = isObjectSpeaker(objectElement) + + if (objectSpeaker) then + local speakerInterior = getElementInterior(objectElement) + local speakerDimension = getElementDimension(objectElement) + local matchingInterior = (speakerInterior == playerInterior) + local matchingDimension = (speakerDimension == playerDimension) + + if (matchingInterior and matchingDimension) then + local speakerX, speakerY, speakerZ = getElementPosition(objectElement) + local distanceToSpeaker = getDistanceBetweenPoints3D(playerX, playerY, playerZ, speakerX, speakerY, speakerZ) + local speakerInDistance = (distanceToSpeaker <= speakerSearchRange) + + if (speakerInDistance) then + local speakerDestroyed = clearPlayerSpeaker(objectElement, true) + + if (speakerDestroyed) then + local newCountOfDestroyedSpeakers = (totalDestroyedSpeakers + 1) + + totalDestroyedSpeakers = newCountOfDestroyedSpeakers + end + end + end + end + end + + outputChatBox("#ff8800[Speakers]: #ffffffDestroyed #ff8800"..totalDestroyedSpeakers.."#ffffff total speakers in range of #ff8800"..speakerSearchRange, playerElement, 255, 255, 255, true) end -addEventHandler("onPlayerQuit", root, clearSpeakersOnDestroyQuit) -addEventHandler("onElementDestroy", resourceRoot, clearSpeakersOnDestroyQuit) +addCommandHandler(RADIO_DESTROY_SPEAKERS_IN_RANGE_COMMAND, destroySpeakersInRangeAdminCommand) function destroyAttachedRadioOnVehicleExplodeOrDestroy() local validElement = isElement(source) @@ -203,9 +296,9 @@ function destroyAttachedRadioOnVehicleExplodeOrDestroy() local attachedElementObject = (attachedElementType == "object") if (attachedElementObject) then - local boxFound = clearPlayerSpeaker(attachedElement) + local speakerFound = clearPlayerSpeaker(attachedElement, true) - if (boxFound) then + if (speakerFound) then break end end diff --git a/[gameplay]/internetradio/handle_radio/ShHandleRadio.lua b/[gameplay]/internetradio/handle_radio/ShHandleRadio.lua index 4bfbba092..cb9e72c5b 100644 --- a/[gameplay]/internetradio/handle_radio/ShHandleRadio.lua +++ b/[gameplay]/internetradio/handle_radio/ShHandleRadio.lua @@ -50,6 +50,35 @@ function verifyRadioStreamURL(streamURL) return true end +function getPlayerFromPartialName(partialName) + if (not partialName) then + return false + end + + local playerFromName = getPlayerFromName(partialName) + + if (playerFromName) then + return playerFromName + end + + local playersTable = getElementsByType("player") + local partialNameLower = string.lower(partialName) + + for playerID = 1, #playersTable do + local playerElement = playersTable[playerID] + local playerName = getPlayerName(playerElement) + local playerNameLower = string.lower(playerName) + local playerNameWithoutColor = string.gsub(playerNameLower, "#%x%x%x%x%x%x", "") + local playerFound = string.find(playerNameWithoutColor, partialNameLower, 1, true) + + if (playerFound) then + return playerElement + end + end + + return false +end + function getOrSetPlayerDelay(playerElement, delayID, delayTime) local validElement = isElement(playerElement)