Skip to content

Commit

Permalink
Merge pull request #152 from Itokoyamato/improv-ws
Browse files Browse the repository at this point in the history
  • Loading branch information
Dylan Thuillier authored Jul 29, 2020
2 parents 305b515 + 14411c5 commit eeef1fd
Show file tree
Hide file tree
Showing 15 changed files with 169 additions and 135 deletions.
2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,7 @@ It can be run as a standalone NodeJS application, on the same machine as your fi
* Download [Node.js](https://nodejs.org/en/)
* Open [config.js](https://github.com/Itokoyamato/TokoVOIP_TS3/blob/master/ws_server/config.js)
* Change "`TSServer`" to your Teamspeak server `IPv4`
* Change "`FivemServerPort`" to your FiveM server `port`
* If the ws-server is hosted on a separate machine:
Change "`FivemServerIP`" to your FiveM server `IPv4`
* Open ws-server folder in cmd / terminal
* Execute `npm i`
* After its done run `node index.js`
Expand Down
17 changes: 17 additions & 0 deletions fivem_script/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,3 +146,20 @@ If the channel name contains 'Call' it will be displayed as a call on the ingame
<td>If set to true, the data will be synced to all players, otherwise only to the client who requested it</td>
</tr>
</table>

- ### setRadioVolume(volume)

Changes the volume of voices over radio

<table>
<tr>
<th>Params</th>
<th>type</th>
<th>Details</th>
</tr>
<tr>
<td>volume</td>
<td>number</td>
<td>Changes the radio volume</td>
</tr>
</table>
5 changes: 3 additions & 2 deletions fivem_script/tokovoip_script/fxmanifest.lua
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
fx_version 'bodacious'
games { 'gta5' }
games { 'gta5', 'rdr3' }
rdr3_warning 'I acknowledge that this is a prerelease build of RedM, and I am aware my resources *will* become incompatible once RedM ships.'

client_script "src/c_utils.lua"
client_script "c_config.lua"
Expand All @@ -15,4 +16,4 @@ ui_page "nui/index.html"
files({
"nui/index.html",
"nui/script.js",
})
})
4 changes: 2 additions & 2 deletions fivem_script/tokovoip_script/nui/script.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,11 @@ function disconnect (src) {
}
}

function init (address) {
function init (address, serverId) {
if (!address) return;
endpoint = address;
console.log('TokoVOIP: attempt new connection');
websocket = new WebSocket(`ws://${endpoint}/socket.io/?EIO=3&transport=websocket&from=fivem`);
websocket = new WebSocket(`ws://${endpoint}/socket.io/?EIO=3&transport=websocket&from=fivem&serverId=${serverId}`);

websocket.onopen = () => {
updateWsState('FiveM', OK)
Expand Down
154 changes: 95 additions & 59 deletions fivem_script/tokovoip_script/src/c_main.lua
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@
local targetPed;
local useLocalPed = true;
local isRunning = false;
local scriptVersion = "1.5.3";
local scriptVersion = "1.5.4";
local animStates = {}
local displayingPluginScreen = false;
local HeadBone = 0x796e;
local radioVolume = 0;

--------------------------------------------------------------------------------
-- Plugin functions
Expand All @@ -37,14 +38,22 @@ local function setPlayerTalkingState(player, playerServerId)
animStates[playerServerId] = talking;
end

local function PlayRedMFacialAnimation(player, animDict, animName)
RequestAnimDict(animDict)
while not HasAnimDictLoaded(animDict) do
Wait(100)
end
SetFacialIdleAnimOverride(player, animName, animDict)
end

RegisterNUICallback("updatePluginData", function(data, cb)
local payload = data.payload;
if (voip[payload.key] == payload.data) then return end
voip[payload.key] = payload.data;
setPlayerData(voip.serverId, "voip:" .. payload.key, voip[payload.key], true);
voip:updateConfig();
voip:updateTokoVoipInfo(true);
cb('ok')
cb('ok');
end);

-- Receives data from the TS plugin on microphone toggle
Expand All @@ -53,19 +62,27 @@ RegisterNUICallback("setPlayerTalking", function(data, cb)

if (voip.talking == 1) then
setPlayerData(voip.serverId, "voip:talking", 1, true);
PlayFacialAnim(GetPlayerPed(PlayerId()), "mic_chatter", "mp_facial");
if (GetConvar("gametype") == "gta5") then
PlayFacialAnim(GetPlayerPed(PlayerId()), "mic_chatter", "mp_facial");
elseif (GetConvar("gametype") == "rdr3") then
PlayRedMFacialAnimation(GetPlayerPed(PlayerId()), "face_human@gen_male@base", "mood_talking_normal");
end
else
setPlayerData(voip.serverId, "voip:talking", 0, true);
PlayFacialAnim(PlayerPedId(), "mood_normal_1", "facials@gen_male@base");
if (GetConvar("gametype") == "gta5") then
PlayFacialAnim(PlayerPedId(), "mood_normal_1", "facials@gen_male@base");
elseif (GetConvar("gametype") == "rdr3") then
PlayRedMFacialAnimation(PlayerPedId(), "face_human@gen_male@base", "mood_normal");
end
end
cb('ok')
cb('ok');
end)

local function clientProcessing()
local playerList = voip.playerList;
local usersdata = {};
local localHeading;
local ped = PlayerPedId()
local ped = PlayerPedId();

if (voip.headingType == 1) then
localHeading = math.rad(GetEntityHeading(ped));
Expand All @@ -83,10 +100,17 @@ local function clientProcessing()
for i=1, #playerList do
local player = playerList[i];
local playerServerId = GetPlayerServerId(player);
if (GetPlayerPed(player) and voip.serverId ~= playerServerId) then
local playerPos = GetPedBoneCoords(GetPlayerPed(player), HeadBone);
local playerPed = GetPlayerPed(player);

local playerTalking = getPlayerData(playerServerId, "voip:talking");

if (voip.serverId == playerServerId or not playerPed or not playerTalking or playerTalking == 0) then goto continue end

do
local playerPos = GetPedBoneCoords(playerPed, HeadBone);
local dist = #(localPos - playerPos);
if(dist > 40) then goto continue end
if (dist > voip.distance[3]) then goto continue end


if (not getPlayerData(playerServerId, "voip:mode")) then
setPlayerData(playerServerId, "voip:mode", 1);
Expand All @@ -102,10 +126,10 @@ local function clientProcessing()
--
local angleToTarget = localHeading - math.atan(playerPos.y - localPos.y, playerPos.x - localPos.x);

-- Set player's default data
local tbl = {
-- Set player's position
local userData = {
uuid = getPlayerData(playerServerId, "voip:pluginUUID"),
volume = -30,
volume = volume,
muted = 1,
radioEffect = false,
posX = voip.plugin_data.enableStereoAudio and math.cos(angleToTarget) * dist or 0,
Expand All @@ -115,69 +139,58 @@ local function clientProcessing()
--

-- Process proximity
tbl.forceUnmuted = 0
if (dist >= voip.distance[mode]) then
tbl.muted = 1;
userData.muted = 1;
else
tbl.volume = volume;
tbl.muted = 0;
tbl.forceUnmuted = 1
userData.volume = volume;
userData.muted = 0;
end

usersdata[#usersdata + 1] = tbl
setPlayerTalkingState(player, playerServerId);
::continue::
if (GetConvar("gametype") == "gta5") then
setPlayerTalkingState(player, playerServerId);
end
usersdata[#usersdata + 1] = userData;
end

::continue::
end

-- Process channels
for _, channel in pairs(voip.myChannels) do
for _, subscriber in pairs(channel.subscribers) do
if (subscriber == voip.serverId) then goto continue end
if (subscriber == voip.serverId) then goto channelContinue end

local remotePlayerUsingRadio = getPlayerData(subscriber, "radio:talking");
local remotePlayerChannel = getPlayerData(subscriber, "radio:channel");
local remotePlayerUuid = getPlayerData(subscriber, "voip:pluginUUID");

local founduserData = nil
for k, v in pairs(usersdata) do
if(v.uuid == remotePlayerUuid) then
founduserData = v
end
end

if not founduserData then
founduserData = {
uuid = remotePlayerUuid,
radioEffect = false,
resave = true,
volume = 0,
muted = 1
}
end
if (not remotePlayerUsingRadio or remotePlayerChannel ~= channel.id) then goto channelContinue end

local remotePlayerUuid = getPlayerData(subscriber, "voip:pluginUUID");

if (remotePlayerUsingRadio and remotePlayerChannel == channel.id) then
if (type(remotePlayerChannel) == "number" and remotePlayerChannel <= voip.config.radioClickMaxChannel) then
founduserData.radioEffect = true;
end
local userData = {
uuid = remotePlayerUuid,
radioEffect = false,
muted = false,
volume = radioVolume,
posX = 0,
posY = 0,
posZ = voip.plugin_data.enableStereoAudio and localPos.z or 0
};

founduserData.muted = false
founduserData.volume = 0;
founduserData.posX = 0;
founduserData.posY = 0;
founduserData.posZ = voip.plugin_data.enableStereoAudio and localPos.z or 0;
if ((type(remotePlayerChannel) == "number" and remotePlayerChannel <= voip.config.radioClickMaxChannel) or channel.radio) then
userData.radioEffect = true;
end

if founduserData.forceUnmuted then
founduserData.muted = false;
for k, v in pairs(usersdata) do
if (v.uuid == remotePlayerUuid) then
usersdata[k] = userData;
goto channelContinue;
end
end

if(founduserData.resave) then
usersdata[#usersdata + 1] = founduserData
end
usersdata[#usersdata + 1] = userData;

::continue::
::channelContinue::
end
end

Expand Down Expand Up @@ -221,15 +234,31 @@ AddEventHandler("initializeVoip", function()
-- Set targetped (used for spectator mod for admins)
targetPed = GetPlayerPed(-1);

voip.processFunction = clientProcessing; -- Link the processing function that will be looped
voip:initialize(); -- Initialize the websocket and controls
voip:loop(); -- Start TokoVoip's loop
-- Request this stuff here only one time
if (GetConvar("gametype") == "gta5") then
RequestAnimDict("mp_facial");
RequestAnimDict("facials@gen_male@base");
elseif (GetConvar("gametype") == "rdr3") then
RequestAnimDict("face_human@gen_male@base");
end

Citizen.Trace("TokoVoip: Initialized script (" .. scriptVersion .. ")\n");

-- Request this stuff here only one time
RequestAnimDict("mp_facial");
RequestAnimDict("facials@gen_male@base");
local response;
Citizen.CreateThread(function()
local function handler(serverId) response = serverId or "N/A"; end
RegisterNetEvent("TokoVoip:onClientGetServerId");
AddEventHandler("TokoVoip:onClientGetServerId", handler);
TriggerServerEvent("TokoVoip:getServerId");
while (not response) do Wait(5) end

voip.fivemServerId = response;
print("TokoVoip: FiveM Server ID is " .. voip.fivemServerId);

voip.processFunction = clientProcessing; -- Link the processing function that will be looped
voip:initialize(); -- Initialize the websocket and controls
voip:loop(); -- Start TokoVoip's loop
end);

-- Debug data stuff
if (voip.config.enableDebug) then
Expand Down Expand Up @@ -343,6 +372,12 @@ function isPlayerInChannel(channel)
end
end

function setRadioVolume(volume)
radioVolume = volume;
end
RegisterNetEvent('TokoVoip:setRadioVolume');
AddEventHandler('TokoVoip:setRadioVolume', setRadioVolume);

--------------------------------------------------------------------------------
-- Specific utils
--------------------------------------------------------------------------------
Expand Down Expand Up @@ -371,3 +406,4 @@ end)
exports("addPlayerToRadio", addPlayerToRadio);
exports("removePlayerFromRadio", removePlayerFromRadio);
exports("isPlayerInChannel", isPlayerInChannel);
exports("setRadioVolume", setRadioVolume);
13 changes: 13 additions & 0 deletions fivem_script/tokovoip_script/src/s_main.lua
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
--------------------------------------------------------------------------------

local channels = TokoVoipConfig.channels;
local serverId;

SetConvarReplicated("gametype", GetConvar("GameName"));

function addPlayerToRadio(channelId, playerServerId, radio)
if (not channels[channelId]) then
Expand Down Expand Up @@ -96,3 +99,13 @@ AddEventHandler('rconCommand', function(commandName, args)
CancelEvent();
end
end)

function getServerId() TriggerClientEvent("TokoVoip:onClientGetServerId", source, serverId); end
RegisterServerEvent("TokoVoip:getServerId");
AddEventHandler("TokoVoip:getServerId", getServerId);

AddEventHandler("onResourceStart", function(resource)
if (resource ~= GetCurrentResourceName()) then return end;
serverId = randomString(32);
print("TokoVOIP FiveM Server ID: " .. serverId);
end);
12 changes: 12 additions & 0 deletions fivem_script/tokovoip_script/src/s_utils.lua
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,15 @@ function tablelength(T)
for _ in pairs(T) do count = count + 1 end
return count
end

local charset = {} do -- [0-9a-zA-Z]
for c = 48, 57 do table.insert(charset, string.char(c)) end
for c = 65, 90 do table.insert(charset, string.char(c)) end
for c = 97, 122 do table.insert(charset, string.char(c)) end
end

function randomString(length)
if not length or length <= 0 then return '' end
math.randomseed(os.clock()^5)
return randomString(length - 1) .. charset[math.random(1, #charset)]
end
2 changes: 1 addition & 1 deletion ts3_package/package.ini
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Name = TokoVOIP
Type = Plugin
Author = Itokoyamato, Thorsten Weinz (RadioFX)
Version = 1.5.2
Version = 1.5.4
Platforms = win32, win64
Description = "This plugin is used to add a custom proximity chat and radio system to fiveM as well as radio effects thanks to the integration of the radioFX plugin."
2 changes: 1 addition & 1 deletion ts3_plugin/deps/teamspeak-plugin-radiofx
2 changes: 1 addition & 1 deletion ts3_plugin/src/tokovoip.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -599,7 +599,7 @@ string verifyTSServer() {
return "";
}

httplib::Client cli("master.tokovoip.itokoyamato.net", 3000);
httplib::Client cli("master.tokovoip.itokoyamato.net");
string path = "/verify?address=" + string(serverIP);
cli.set_follow_location(true);
outputLog("Getting " + path);
Expand Down
2 changes: 1 addition & 1 deletion ws_server/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ COPY . .

RUN npm install --production

EXPOSE 3000
EXPOSE 33250

CMD ["npm", "start"]
Loading

0 comments on commit eeef1fd

Please sign in to comment.