This commit is contained in:
guava
2016-12-15 13:40:07 +01:00
commit ee4dd89693
95 changed files with 7368 additions and 0 deletions

View File

@@ -0,0 +1,11 @@
client_scripts {
'client/initial.lua',
'client/leavehandler.lua',
'client/activationhandler.lua',
'client/hostservice.lua',
'client/sessionstarter.lua'
}
server_script 'server/host_lock.lua'
export 'serviceHostStuff'

View File

@@ -0,0 +1,27 @@
-- triggers an event when the local network player becomes active
AddEventHandler('sessionInitialized', function()
local playerId = GetPlayerId()
-- create a looping thread
CreateThread(function()
-- wait until the player becomes active
while not IsNetworkPlayerActive(playerId) do
Wait(0)
end
-- set some defaults
AllowGameToPauseForStreaming(true)
SetMaxWantedLevel(6)
SetWantedMultiplier(0.9999999)
SetCreateRandomCops(true)
SetDitchPoliceModels(false)
DisplayPlayerNames(true)
NetworkSetHealthReticuleOption(true)
-- trigger an event on both the local client and the server
TriggerEvent('playerActivated')
TriggerServerEvent('playerActivated')
end)
end)

View File

@@ -0,0 +1,55 @@
-- serving the duties of the office of the host
-- two functions from GTA script; they do 'something lock-ish'
local function acquireHostLock()
if IsThisMachineTheServer() then
SetThisMachineRunningServerScript(true)
return true
end
return false
end
local function releaseHostLock()
SetThisMachineRunningServerScript(false)
end
-- handle msgGetReadyToStartPlaying sending
function serviceHostStuff()
-- acquire the host lock
if acquireHostLock() then
-- check if players want to join
for i = 0, 31 do
-- does this index?
if PlayerWantsToJoinNetworkGame(i) then
-- well, get ready to start playing!
TellNetPlayerToStartPlaying(i, 0)
TriggerServerEvent('playerJoining', i)
end
end
-- release the host lock
releaseHostLock()
end
end
-- host service loop
CreateThread(function()
NetworkSetScriptLobbyState(false)
SwitchArrowAboveBlippedPickups(true)
UsePlayerColourInsteadOfTeamColour(true)
LoadAllPathNodes(true)
SetSyncWeatherAndGameTime(true)
while true do
Wait(0)
serviceHostStuff()
-- launch the local player, for the initial host scenario
if LocalPlayerIsReadyToStartPlaying() then
LaunchLocalPlayerInNetworkGame()
end
end
end)

View File

@@ -0,0 +1,124 @@
-- state variable for session host lock
local sessionHostPending = false
local sessionHostResult
AddEventHandler('sessionHostResult', function(result)
if not sessionHostPending then
return
end
sessionHostResult = result
sessionHostPending = false
end)
local attempts = 0
-- allow early script to create the player
AddEventHandler('playerInfoCreated', function()
CreateThread(function()
-- so that the game won't trigger the citizen disconnect handler
SafeguardDisconnect(true)
-- loop for 3 times
while attempts < 3 do
-- 'find' games (this will store the host session in memory, or if no host exists, tell us later)
NetworkFindGame(16, false, 0, 0)
-- we don't have to wait for the finding to complete; TestSessionFind.cpp in hooks_ny will instantly return
local gamesFound = NetworkGetNumberOfGames(_r)
-- if we found at least one game (if the game isn't hooked, this can be any amount; but
-- we can't trust the implementation in that case anyway)
local needsToHost = true -- whether we need to host after completing a possible join
if gamesFound > 0 then
-- join the game
NetworkJoinGame(0)
SetLoadingText('Entering session') -- status text
-- wait for the join to complete
while NetworkJoinGamePending() do
Wait(0)
end
-- if we succeeded, we're now a session member, and will not need to host
if NetworkJoinGameSucceeded() then
needsToHost = false
break
end
end
-- if we didn't find any games, or a join timed out, we'll *consider* hosting
if needsToHost then
-- make sure we don't have an actual other host waiting for us
sessionHostPending = true -- to trigger a wait loop below
TriggerServerEvent('hostingSession')
SetLoadingText('Initializing session') -- some vague status text
-- wait for the server to respond to our request
while sessionHostPending do
Wait(0)
end
if sessionHostResult == 'wait' then
-- TODO: not implemented yet: wait for a message from the server, then attempt finding a game/joining a game again
sessionHostPending = true
while sessionHostPending do
Wait(0)
end
if sessionHostResult == 'free' then
goto endLoop
end
end
if sessionHostResult == 'conflict' and gamesFound > 0 then
-- there's already a host which is working perfectly fine; show a message to the player
--error('session creation conflict: could not connect to original host')
echo("session creation conflict\n")
goto endLoop
end
-- we got a green light to host; start hosting
if not NetworkHostGameE1(16, false, 32, false, 0, 0) then
echo("session creation failure from NetworkHostGameE1\n")
error('failed to initialize session')
end
-- wait for internal processing to complete
while NetworkHostGamePending() do
Wait(0)
end
-- another failure check
if not NetworkHostGameSucceeded() then
echo("session creation failure from NetworkHostGameSucceeded\n")
error('failed to initialize session')
end
TriggerServerEvent('hostedSession')
break
end
::endLoop::
attempts = attempts + 1
end
SafeguardDisconnect(false)
if attempts >= 3 then
error("Could not connect to session provider.")
end
SetLoadingText('Look at that!')
-- signal local game-specific resources to start
TriggerEvent('sessionInitialized')
TriggerServerEvent('sessionInitialized')
end)
end)

View File

@@ -0,0 +1,31 @@
-- handles the script end of the flag the 'leave game' option in the pause menu sets
CreateThread(function()
while true do
Wait(0)
-- if the flag is set
if DoesGameCodeWantToLeaveNetworkSession() then
-- if we're part of a started session; end it first (FIXME: will this break others when we're host?)
if NetworkIsSessionStarted() then
NetworkEndSession()
-- wait for the session to be ended
while NetworkEndSessionPending() do
Wait(0)
end
end
-- attempt to leave the game
NetworkLeaveGame()
-- while we're waiting to leave...
while NetworkLeaveGamePending() do
Wait(0)
end
-- reinitialize the game as a network game (TODO: call into citigame for UI/NetLibrary leaving)
--ShutdownAndLaunchNetworkGame(0) -- episode id is arg
ShutdownNetworkCit('Left');
end
end
end)

View File

@@ -0,0 +1,26 @@
-- more rline stuff, this does some late-term session management (which I think has some race condition with launching the network player?)
AddEventHandler('sessionInitialized', function()
if IsThisMachineTheServer() then
-- unknown stuff, seems needed though
NetworkChangeExtendedGameConfigCit()
CreateThread(function()
Wait(1500)
if not NetworkIsSessionStarted() then
NetworkStartSession()
while NetworkStartSessionPending() do
Wait(0)
end
if not NetworkStartSessionSucceeded() then
ForceLoadingScreen(0)
SetMsgForLoadingScreen("MO_SNI")
return
end
end
end)
end
end)

View File

@@ -0,0 +1,67 @@
-- whitelist c2s events
RegisterServerEvent('hostingSession')
RegisterServerEvent('hostedSession')
-- event handler for pre-session 'acquire'
local currentHosting
local hostReleaseCallbacks = {}
-- TODO: add a timeout for the hosting lock to be held
-- TODO: add checks for 'fraudulent' conflict cases of hosting attempts (typically whenever the host can not be reached)
AddEventHandler('hostingSession', function()
-- if the lock is currently held, tell the client to await further instruction
if currentHosting then
TriggerClientEvent('sessionHostResult', source, 'wait')
-- register a callback for when the lock is freed
table.insert(hostReleaseCallbacks, function()
TriggerClientEvent('sessionHostResult', source, 'free')
end)
return
end
-- if the current host was last contacted less than a second ago
if GetHostId() >= 1 then
if GetPlayerLastMsg(GetHostId()) < 1000 then
TriggerClientEvent('sessionHostResult', source, 'conflict')
return
end
end
hostReleaseCallbacks = {}
currentHosting = source
TriggerClientEvent('sessionHostResult', source, 'go')
-- set a timeout of 5 seconds
SetTimeout(5000, function()
if not currentHosting then
return
end
currentHosting = nil
for _, cb in ipairs(hostReleaseCallbacks) do
cb()
end
end)
end)
AddEventHandler('hostedSession', function()
-- check if the client is the original locker
if currentHosting ~= source then
-- TODO: drop client as they're clearly lying
print(currentHosting, '~=', source)
return
end
-- free the host lock (call callbacks and remove the lock value)
for _, cb in ipairs(hostReleaseCallbacks) do
cb()
end
currentHosting = nil
end)