Game State Management in PHPDTS: How State Transitions Work
The PHPDTS engine uses a global $gamestate variable evaluated on every request to cycle through six distinct phases, from idle preparation to final combo showdown, triggered by time-based checkpoints, player counts, and arena capacity limits.
The amarillonmc/phpdts repository implements a deterministic state machine that drives the battle royale lifecycle. At the heart of this game state management system lies the global $gamestate variable declared in include/common.inc.php, which is checked and updated inside the main request loop to ensure continuous match progression across stateless HTTP requests.
The Global State Variable and Core Architecture
All state persistence relies on the $gamestate global variable. The engine initializes this value at the start of each request via load_gameinfo() in include/init.func.php (line 165), which deserializes the stored value from gamedata/gameinfo.php. When a match ends, gameover() in include/system.func.php (line 260) resets this variable to 0.
The state machine executes inside a guarded block that excludes chat scripts to prevent high-frequency polling from triggering spurious transitions:
if(CURSCRIPT !== 'chat') {
// State transition logic runs here (lines 64-260)
}
State Values and Their Meanings
The engine defines six discrete integer states that represent distinct match phases, each set at specific lines within include/common.inc.php:
- 0 – Idle/Game Over: No active match. Initialized by
load_gameinfo()at line 165 and reset bygameover()at line 260. - 10 – Preparation: Countdown window before the match starts. Set at lines 68–70 when
$now > $starttime - $startmin*60. - 20 – Active Battle: Normal gameplay phase. Set at lines 82–84 once
$now >= $starttime. - 30 – Stop Activation: Entry is closed and the arena stops expanding. Set at lines 102–104 when capacity or player limits are reached.
- 40 – Combo Mode: Accelerated "continuous battle" phase. Set at lines 124–131 or 133–140 based on survivor counts or death thresholds.
- 50 – End of Combo: Terminal state assigned in
gameover()at line 260 immediately before resetting to 0.
State Transition Logic in the Main Loop
The transition logic resides in include/common.inc.php and evaluates conditions sequentially on every non-chat request.
Transition 0 → 10: Entering Preparation
When the system is idle, it checks against the pre-game timer:
if(!$gamestate){
if(($starttime) && ($now > $starttime - $startmin*60)){
$gamestate = 10; // preparation phase (lines 68-70)
}
}
Transition 10 → 20: Match Start
Once the preparation countdown completes, the battle phase begins:
if($gamestate == 10 && $now >= $starttime){
$gamestate = 20; // active battle (lines 82-84)
}
Transition 20 → 30: Stop Activation
During active battle, the engine monitors arena capacity ($areanum) and valid participant counts ($validnum):
if($gamestate == 20){
if(($validnum <= 0) && $areanum >= $arealimit*$areaadd){
gameover(...); // not enough players → end
} elseif(($areanum >= $arealimit*$areaadd) || ($validnum >= $validlimit)){
$gamestate = 30; // stop new entrants (lines 102-104)
}
}
If valid participants drop to zero while the arena is full, gameover() terminates the match immediately rather than transitioning to state 30.
Transition 30 → 40: Entering Combo Mode
Combo mode activates via two alternative survival checks at lines 124–140:
// Check 1: Few survivors remaining
if($gamestate < 40 && $gamestate > 20 && $alivenum <= $combolimit){
$gamestate = 40; // combo because few survivors
}
// Check 2: Death count exceeds threshold
if($gamestate < 40 && $gamestate >= 20 && $combonum && $deathnum >= $combonum){
$gamestate = 40; // combo because deaths exceed threshold
}
Transition 40 → 0: Game Conclusion
While in combo mode (state 40) or end-of-combo (state 50), the engine checks for a single survivor:
if($gamestate >= 40){
$result = $db->query("SELECT pid FROM {$tablepre}players WHERE hp>0 AND type=0");
$alivenum = $db->num_rows($result);
if($alivenum <= 1){
gameover(); // line 260: resets $gamestate to 0
}
}
Anti-AFK Protection Within Combo State
State 40 includes automated AFK detection that runs continuously to prevent idle stalling:
if($gamestate >= 40 && $now > $afktime + $antiAFKertime*60){
antiAFK(); // resets AFK timer
}
The antiAFK() function in include/system.func.php refreshes timestamps to keep the final showdown moving.
Supporting Functions and Persistence Layer
State persistence and helper logic are modularized across specific files:
load_gameinfo()ininclude/init.func.php(line 165) deserializes$gamestatefromgamedata/gameinfo.phpat request start.gameover()ininclude/system.func.php(line 260) resets$gamestateto 0, records the winner, and clears temporary data.antiAFK()ininclude/system.func.phpmanages idle protection during state 40.init_ruleset_override()andload_ruleset_override_functions()ininclude/ruleset_override.func.phpenable custom rule sets to modify transition thresholds.
Configuration and Custom Rule Sets
Default thresholds governing game state transitions are defined in gamedata/system.php:
$startmin– Minutes beforestarttimeto enter preparation (state 10).$arealimitand$areaadd– Arena expansion limits triggering state 30.$validlimit– Minimum valid participants required for stop activation.$combolimit– Alive player threshold entering combo mode.$antiAFKertime– Minutes allowed before AFK protection fires.
The include/ruleset_override.func.php file allows server administrators to inject custom logic, overriding variables like $combolimit or $validlimit without altering the core state machine in include/common.inc.php.
Summary
- The PHPDTS game state management system relies on a global
$gamestatevariable persisted ingamedata/gameinfo.phpand evaluated on every non-chat request. - Six discrete integer states (0, 10, 20, 30, 40, 50) represent the complete match lifecycle from idle preparation through combo finale.
- Transitions trigger based on time-based checkpoints (start timers), player-count thresholds (valid participants and survivors), and arena capacity limits (arealimit calculations).
- The
gameover()andantiAFK()functions ininclude/system.func.phphandle terminal state cleanup and idle protection. - Custom rule sets via
include/ruleset_override.func.phpallow modification of transition logic without core code changes.
Frequently Asked Questions
How does PHPDTS persist game state between HTTP requests?
The engine saves the $gamestate variable to gamedata/gameinfo.php at the end of each request cycle. At the start of every subsequent request, load_gameinfo() in include/init.func.php (line 165) deserializes this file back into the global scope, ensuring continuity across the stateless HTTP protocol.
What happens if the player count drops to zero during active battle?
If $validnum reaches zero while the arena has expanded beyond its limit ($areanum >= $arealimit*$areaadd), the transition logic in include/common.inc.php (lines 102–104) immediately invokes gameover(). This resets $gamestate to 0 and terminates the match early due to insufficient participants.
Can server administrators modify the state transition thresholds?
Yes. While default values reside in gamedata/system.php, administrators can implement custom logic through include/ruleset_override.func.php. The init_ruleset_override() and load_ruleset_override_functions() hooks allow modification of variables like $combolimit and $validlimit without altering the core state machine in include/common.inc.php.
Why does the state machine exclude the chat script?
The guard clause if(CURSCRIPT !== 'chat') prevents the state transition logic from executing during chat polling requests. This optimization reduces database load and prevents premature state advances caused by high-frequency AJAX chat updates that do not represent actual game actions.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →