Skip to content

Commit

Permalink
Actually working server-side state machine
Browse files Browse the repository at this point in the history
  • Loading branch information
thers committed Aug 29, 2017
1 parent cfc1fca commit b8e4809
Show file tree
Hide file tree
Showing 7 changed files with 241 additions and 250 deletions.
1 change: 0 additions & 1 deletion __resource.lua
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
resource_manifest_version '44febabe-d386-4d18-afbe-5e627f4af937'

client_script 'dist/aslt.js'
client_script 'client.lua'
server_script 'server.lua'
118 changes: 85 additions & 33 deletions server.lua
Original file line number Diff line number Diff line change
@@ -1,23 +1,11 @@
local maxTargets = 2

local timeForStart = 10000
local timeForTarget = 10000
local timeForIntermission = 10000

function onNet(name, cb)
RegisterServerEvent(name)
AddEventHandler(name, cb)
end

function emitSync(to, transition)
TriggerClientEvent('aslt:sync', to, round, transition)
end

function endOfRound()
return round.target >= maxTargets
end
local timeForStart = 5000
local timeForTarget = 5000
local timeForIntermission = 5000

local transition = {
Initial = 1337,
None = 0,
IdleToStarting = 1,
StartingToRunning = 2,
Expand All @@ -31,12 +19,29 @@ local round = {
state = 'idle', -- idle, starting, running, intermission
score = {}, -- key is a target index, value is an array where index is a team and value is a score at target
target = 1,
playersTeams = {},
playersAtTarget = {},
timerOfStart = timeForStart,
timerOfTarget = timeForTarget,
timerOfIntermission = timeForIntermission
}

-- Map of players randoms so we can assign them to teams
local booking = {}

function onNet(name, cb)
RegisterServerEvent(name)
AddEventHandler(name, cb)
end

function emitSync(to, transition)
TriggerClientEvent('aslt:sync', -1, round, transition)
end

function endOfRound()
return round.target >= maxTargets
end

onNet('aslt:start', function(seed)
round = {
seed = seed,
Expand All @@ -50,11 +55,18 @@ onNet('aslt:start', function(seed)
timerOfIntermission = timeForIntermission
}

emitSync(-1, transition.None)
emitSync(-1, transition.IdleToStarting)

Citizen.Trace('aslt:start')
end)

onNet('aslt:book', function(rnd)
booking[source] = rnd
end)

-- Request for initial sync
onNet('aslt:sync', function()
emitSync(source, transition.None)
emitSync(source, transition.Initial)
end)

-- Low overhead separate events for potentially spammy things
Expand All @@ -69,56 +81,81 @@ onNet('aslt:off-target', function()
TriggerClientEvent('aslt:off-target', -1, source)
end)

local syncThreshold = 500

local lastTime = 0
local sinceLastSync = 9000
Citizen.CreateThread(function()
while true do
Citizen.Wait(0)

local currentTime = GetGameTimer()
local dt = currentTime - lastTime
local currentTransition = transitionNone
local currentTransition = transition.None
local newTarget = false

sinceLastSync = sinceLastSync + dt

if round.state == 'starting' then
round.timerOfStart = round.timerOfStart - dt

if round.timerOfStart <= 0 then
newTarget = true
round.state = 'running'
currentTransition = transition.StartingToRunning

round.state = 'running'
round.timerOfStart = timeForStart

-- assign to teams
local sortedPlayers = {}

for playerId, playerRnd in pairs(booking) do
table.insert(sortedPlayers, playerId)
end

table.sort(sortedPlayers, function(a, b) return booking[a] < booking[b] end)

for index, playerId in ipairs(sortedPlayers) do
round.playersTeams[playerId] = index % 2
end
end

elseif round.state == 'running' then
local teamsMembersOnTarget = {}
local playersOnTarget = 0

local leadingTeam = 0
local leadingTeam = -1
local leadingTeamMembersOnTarget = 0
local secondTeamMembersOnTarget = 0

for playerId, onTarget in ipairs(round.playersAtTarget) do
for playerId, onTarget in pairs(round.playersAtTarget) do
local playerTeam = round.playersTeams[playerId]

if onTarget then
playersOnTarget = playersOnTarget + 1
local teamMembersOnTarget = teamsMembersOnTarget[playerTeam]

if teamsMembersOnTarget[playerTeam] then
teamsMembersOnTarget[playerTeam] = teamsMembersOnTarget[playerTeam] + 1
if teamMembersOnTarget then
teamsMembersOnTarget[playerTeam] = teamMembersOnTarget + 1
else
teamsMembersOnTarget[playerTeam] = 1
end

if teamsMembersOnTarget[playerTeam] > leadingTeamMembersOnTarget then
if leadingTeam ~= playerTeam then
leadingTeam = playerTeam
secondTeamMembersOnTarget = leadingTeamMembersOnTarget
end

leadingTeam = playerTeam
leadingTeamMembersOnTarget = teamsMembersOnTarget[playerTeam]
end
end
end

local contesting = secondTeamMembersOnTarget == leadingTeamMembersOnTarget
local contesting = true
local meanNumberOfPlayersOnTarget = playersOnTarget / 2

for team, membersOnTarget in pairs(teamsMembersOnTarget) do
if meanNumberOfPlayersOnTarget ~= membersOnTarget then
contesting = false
break
end
end

if playersOnTarget > 0 and not contesting then
round.timerOfTarget = round.timerOfTarget - dt
Expand All @@ -133,18 +170,30 @@ Citizen.CreateThread(function()
currentTransition = transition.RunningToIntermission
end

if not round.score[round.target] then
round.score[round.target] = {
[leadingTeam] = 0
}
end

local leadingTeamScore = round.score[round.target][leadingTeam]
round.score[round.target][leadingTeam] = leadingTeamScore + 1
round.timerOfTarget = timeForTarget
end
end

elseif round.state == 'intermission' then
round.timerOfIntermission = round.timerOfIntermission - dt

if round.timerOfIntermission <= 0 then
newTarget = true
round.state = 'running'
currentTransition = transition.IntermissionToRunning

round.state = 'running'
round.target = round.target + 1
round.timerOfTarget = timeForTarget
round.playersAtTarget = {}
round.timerOfIntermission = timeForIntermission
end
end

Expand All @@ -153,8 +202,11 @@ Citizen.CreateThread(function()
round.playersAtTarget = {}
end

if currentTransition ~= transition.None then
local needsRoutineSync = sinceLastSync > syncThreshold and round.state ~= 'idle'

if currentTransition ~= transition.None or needsRoutineSync then
emitSync(-1, currentTransition)
sinceLastSync = 0
end

lastTime = currentTime
Expand Down
19 changes: 3 additions & 16 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,7 @@ enum DecorationType {

let round = new Round();

Game.onMount(() => {
// Setup decorators
DecorRegister('aslt_random', <number>DecorationType.Float);
DecorRegister('aslt_team', <number>DecorationType.Int);

// Register event listeners
onNet('aslt:start', seed => {
console.log('round starting');

setSeed(seed);
round.start();
});
});
Game.onUnmount(() => round.stop());
Game.onMount(() => {});

let lastTime = 0;

Expand All @@ -39,11 +26,11 @@ setTick(async () => {
const dt = time - lastTime;

if (Game.controls.isJustPressed(Control.PhoneRight)) {
emitNet('aslt:round:start', Math.random() * 0xffffffff |0);
emitNet('aslt:start', Math.random() * 0xffffffff |0);
}

if (Game.controls.isJustPressed(Control.PhoneDown)) {
console.log(GetGameTimer());
emitNet('plr');
}

round.update(dt, time);
Expand Down
6 changes: 6 additions & 0 deletions src/proceduralRandom.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
import * as hashInt from 'hash-int'

let originalSeed = 0;
let seed = 0;

export function setSeed(val: number) {
seed = val;
originalSeed = val;
}

export function advanceSeed(amount: number) {
seed = hashInt(originalSeed) + amount |0;
}

export function nextInt(): number {
Expand Down
Loading

0 comments on commit b8e4809

Please sign in to comment.