PHP-DTS Game State Transitions: Complete Guide to the 7-State Game Loop

The PHP-DTS game engine manages battle royale matches through a strict 7-state machine defined by the $gamestate variable, with transitions triggered by time checks, player counts, and zone expansions in common.inc.php and system.func.php.

The amarillonmc/phpdts repository implements a real-time battle royale system where game state transitions control everything from lobby countdowns to final duels. Understanding how the $gamestate variable evolves from 0 (not started) through 50 (duel mode) reveals the core timing logic that drives the entire match lifecycle.

Core Game State Architecture

The game loop relies on a single integer variable $gamestate that persists across requests. Each numeric value represents a distinct phase with specific entry conditions and exit triggers. The state machine enforces sequential progression with one exception: the Duel state (50) can interrupt any active combat phase.

State Value Description
Not started 0 Server idle or post-game reset
Preparation 10 Lobby open, countdown active
Game start 20 Combat enabled, safe zone expanding
Activation stop 30 Registration closed, zone limits reached
Combo 40 Continuous battle mode, no safe zone resets
Duel 50 Special key-item triggered duel mode
Game over 0 Final results recorded, server reset

State Transition Triggers in Detail

Not Started (0) → Preparation (10)

The transition from idle to lobby mode occurs when the current server time enters the pre-game countdown window. In include/common.inc.php lines 165–170, the system checks if the $starttime is within $startmin minutes of opening:

if($now > $starttime - $startmin*60 && $gamestate == 0) {
    $gamestate = 10;
    // Lobby initialization logic
}

This trigger fires once per round when the server clock crosses the preparation threshold.

Preparation (10) → Game Start (20)

At the exact scheduled start time, the game state transition moves from lobby to active combat. The condition in common.inc.php lines 181–186 verifies the clock has reached $starttime:

if($gamestate == 10 && $now >= $starttime) {
    $gamestate = 20;
    // Battle initialization begins
}

This transition is strictly time-gated and irreversible without manual intervention.

Game Start (20) → Activation Stop (30)

The Activation Stop phase triggers when either the participant cap is reached or the safe zone expansion hits its limit. According to common.inc.php lines 220–227, the system monitors two variables during the $gamestate == 20 block:

  • Participant threshold: $validnum >= $validlimit
  • Zone expansion: $areanum >= $arealimit * $areaadd
if($validnum >= $validlimit || $areanum >= $arealimit * $areaadd) {
    $gamestate = 30;
    // Close registration, lock zone settings
}

Either condition immediately seals the match roster.

Activation Stop (30) → Combo (40)

The Combo state enables continuous combat without safe zone resets. This game state transition fires when survival pressure intensifies, detected in common.inc.php lines 230–244 through two alternative triggers:

  1. Low population: $alivenum <= $combolimit
  2. Death threshold: $deathnum >= $real_combonum (calculated from $validnum and $deathdeno)
if($alivenum <= $combolimit) {
    $gamestate = 40;
} elseif($deathnum >= $real_combonum) {
    $gamestate = 40;
}

Once entered, the game remains in Combo mode until conclusion or a Duel interrupt.

Combo Phase and Anti-AFK (≥40)

While in Combo state, the loop runs periodic anti-AFK checks. In common.inc.php lines 248–254, the system monitors the $afktime timestamp against $antiAFKertime:

if($now > $afktime + $antiAFKertime*60) {
    antiAFK();
    $afktime = $now;
}

This does not change the $gamestate value but maintains state integrity by removing inactive players during the high-intensity phase.

Duel Mode (50)

The Duel state represents an exception to the linear progression. Triggered by player action via include/system.func.php lines 11–13, any player holding a duel key can force the entire server into duel mode:

function duel() {
    global $gamestate;
    $gamestate = 50;
    // Save state and broadcast duel start
}

This overrides the current state regardless of whether the match is in standard combat (20), activation stop (30), or combo (40).

Game Over (Reset to 0)

The final game state transition occurs when survival conditions terminate the match. Inside the $gamestate >= 40 block, when player counts drop to one or zero, system.func.php lines 31–34 invoke the reset sequence:

function gameover() {
    // Record winners and statistics
    rs_sttime();
    $gamestate = 0;
}

The rs_sttime() function recalculates the next round's schedule before clearing the state variable in common.inc.php lines 332–334.

The Game Loop Execution Flow

Understanding the game state transitions requires following the execution order in the main loop:

  1. Lock acquisition: The script obtains process.lock to prevent concurrent state modifications
  2. State persistence: Game info loads from storage into the $gamestate variable
  3. Transition evaluation: Conditions check for numeric state changes based on time, counts, or zone data
  4. Action execution: State-specific logic runs (lobby management, combat resolution, or duel handling)
  5. State persistence: Updated $gamestate values save back to storage before lock release

This cycle repeats every server tick, ensuring game state transitions occur at precise thresholds defined in the configuration variables ($starttime, $validlimit, $combolimit, etc.).

Summary

  • PHP-DTS uses a numeric $gamestate variable with 7 distinct values (0, 10, 20, 30, 40, 50) to control match phases
  • Preparation (10) triggers when $now enters the $startmin window before $starttime
  • Game Start (20) fires exactly at $starttime, moving from lobby to combat
  • Activation Stop (30) occurs when $validnum meets $validlimit or zone expansion completes
  • Combo (40) activates from low survivor counts ($alivenum <= $combolimit) or death thresholds
  • Duel (50) interrupts any state via the duel() function in system.func.php
  • Game Over resets to 0 through rs_sttime() after gameover() detects final elimination

Frequently Asked Questions

What triggers the transition from Preparation to Game Start?

The transition from state 10 to 20 triggers when the server timestamp $now becomes greater than or equal to the configured $starttime. This check runs in include/common.inc.php lines 181–186 and represents the exact moment the battle royale match begins.

How does the game enter the Combo state?

The Combo state (40) activates through two alternative conditions in common.inc.php lines 230–244: either the number of alive players drops below $combolimit, or the death count exceeds the calculated $real_combonum threshold derived from total participants and the $deathdeno divisor.

Can players trigger game state transitions manually?

Yes. The Duel state (50) can be triggered by any player possessing a duel key, which calls duel() in include/system.func.php lines 11–13. This forces the server into duel mode regardless of the current state, pausing normal zone expansion and combo calculations.

What happens when the game ends?

When the alive player count reaches one or zero while $gamestate >= 40, the gameover() function executes in include/system.func.php lines 31–34. It records final statistics, calls rs_sttime() to schedule the next round, and resets $gamestate to 0 in common.inc.php lines 332–334.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →