Merge pull request #156 from GameServerPanel/copilot/slow-safe-upgrade-protocols
This commit is contained in:
commit
924a82bc00
5 changed files with 407 additions and 0 deletions
|
|
@ -1,6 +1,7 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
## 2026-05-18
|
## 2026-05-18
|
||||||
|
- **Protocol/image upgrade Phase 1 scaffolding (non-breaking):** Added `protocol/gsp_query.php` normalized query wrapper (LGSL default provider with future-provider placeholders), documented current protocol integration and migration plan in `protocol/PROTOCOL_UPGRADE_REVIEW.md`, and documented image module comparison/unification direction in `modules/SERVER_IMAGE_MODULE_REVIEW.md` without removing LGSL, dsi, or `lgsl_with_img_mod`.
|
||||||
- **Cron ↔ Server Content action hook integration:** Added scheduler-callable Server Content hooks in `modules/addonsmanager/server_content_actions.php`, exposed API route `server_content/run_scheduled_action`, and wired cron/user-cron action builders/parsing to support server content scheduled actions (check/install/queue/restart/validate/backup flows) without embedding game-specific install logic in the scheduler.
|
- **Cron ↔ Server Content action hook integration:** Added scheduler-callable Server Content hooks in `modules/addonsmanager/server_content_actions.php`, exposed API route `server_content/run_scheduled_action`, and wired cron/user-cron action builders/parsing to support server content scheduled actions (check/install/queue/restart/validate/backup flows) without embedding game-specific install logic in the scheduler.
|
||||||
- **Server Content Workshop Phase 1 in addonsmanager:** Added a new `Workshop Content` flow under Server Content with per-home Workshop ID storage, ID validation/deduplication, install/update/remove/update-all actions, manifest-based script handoff (`gsp_server_content/workshop_manifest.json`), safe placeholder workshop scripts for Linux/Cygwin, and schema support via `server_content_workshop` plus `addons.addon_type VARCHAR(32)`.
|
- **Server Content Workshop Phase 1 in addonsmanager:** Added a new `Workshop Content` flow under Server Content with per-home Workshop ID storage, ID validation/deduplication, install/update/remove/update-all actions, manifest-based script handoff (`gsp_server_content/workshop_manifest.json`), safe placeholder workshop scripts for Linux/Cygwin, and schema support via `server_content_workshop` plus `addons.addon_type VARCHAR(32)`.
|
||||||
- **Updater layout hardening + pre-update patch framework:** Reworked `modules/administration/panel_update.php` to resolve explicit GSP root/Panel/Website paths, run mandatory preflight checks, self-update updater files before main sync when drift is detected, and apply ordered required patches from `modules/update/patches/` with DB/local state tracking. Backup/rollback now includes both Panel + Website archives and root `version.json`, logs moved to root `logs/update_trace.log`, and the admin Update UI now exposes preflight, patch apply, Apache path scan/fix, backup, update, and rollback actions.
|
- **Updater layout hardening + pre-update patch framework:** Reworked `modules/administration/panel_update.php` to resolve explicit GSP root/Panel/Website paths, run mandatory preflight checks, self-update updater files before main sync when drift is detected, and apply ordered required patches from `modules/update/patches/` with DB/local state tracking. Backup/rollback now includes both Panel + Website archives and root `version.json`, logs moved to root `logs/update_trace.log`, and the admin Update UI now exposes preflight, patch apply, Apache path scan/fix, backup, update, and rollback actions.
|
||||||
|
|
|
||||||
|
|
@ -19,3 +19,4 @@
|
||||||
- Add an admin preview/diff panel for Apache path repairs so staff can review exact vhost line changes before confirming `Fix Apache Paths`.
|
- Add an admin preview/diff panel for Apache path repairs so staff can review exact vhost line changes before confirming `Fix Apache Paths`.
|
||||||
- Add Phase 2 Workshop Content UX in `addonsmanager`: browse/search/select Workshop items with metadata while reusing the Phase 1 per-home saved-ID action pipeline.
|
- Add Phase 2 Workshop Content UX in `addonsmanager`: browse/search/select Workshop items with metadata while reusing the Phase 1 per-home saved-ID action pipeline.
|
||||||
- Add localized language strings/tooltips for the new cron scheduler `server_content_*` action labels across all supported panel locales.
|
- Add localized language strings/tooltips for the new cron scheduler `server_content_*` action labels across all supported panel locales.
|
||||||
|
- Add a Game Manager "Live Server Status" panel that consumes `Panel/protocol/gsp_query.php` and shows banner preview plus copyable embed code.
|
||||||
|
|
|
||||||
80
Panel/modules/SERVER_IMAGE_MODULE_REVIEW.md
Normal file
80
Panel/modules/SERVER_IMAGE_MODULE_REVIEW.md
Normal file
|
|
@ -0,0 +1,80 @@
|
||||||
|
# Server Image Module Review (Phase 1)
|
||||||
|
|
||||||
|
## Scope reviewed
|
||||||
|
- `Panel/modules/lgsl_with_img_mod/`
|
||||||
|
- `Panel/modules/dsi/`
|
||||||
|
- Integration touchpoints in `Panel/modules/gamemanager/`
|
||||||
|
|
||||||
|
## Entry points
|
||||||
|
|
||||||
|
### lgsl_with_img_mod
|
||||||
|
- Module metadata: `Panel/modules/lgsl_with_img_mod/module.php`
|
||||||
|
- User/admin pages:
|
||||||
|
- `lgsl.php`
|
||||||
|
- `lgsl_admin.php`
|
||||||
|
- Image endpoint:
|
||||||
|
- `image.php` (reads by `s` argument, supports `img_type`)
|
||||||
|
- Core query/cache/image logic:
|
||||||
|
- `lgsl_files/lgsl_class.php`
|
||||||
|
|
||||||
|
### dsi
|
||||||
|
- Module metadata: `Panel/modules/dsi/module.php`
|
||||||
|
- User/admin/list pages:
|
||||||
|
- `dsi_user.php`
|
||||||
|
- `dsi_admin.php`
|
||||||
|
- `dsi_list.php`
|
||||||
|
- Image endpoint:
|
||||||
|
- `image.php` (`modules/dsi/s-IP_PORT-type.png` style)
|
||||||
|
- Helpers:
|
||||||
|
- `includes/functions.php`
|
||||||
|
- `includes/functions_ui.php`
|
||||||
|
|
||||||
|
## Comparison
|
||||||
|
|
||||||
|
### Which module generates images?
|
||||||
|
- **Both** generate PNG status banners.
|
||||||
|
- `lgsl_with_img_mod` is LGSL-centric and built around the `OGP_DB_PREFIXlgsl` cache model.
|
||||||
|
- `dsi` supports LGSL/GameQ/TS3 monitor includes and can render banner/code snippets directly for panel users.
|
||||||
|
|
||||||
|
### Which has better cache support?
|
||||||
|
- **lgsl_with_img_mod** has deeper cache integration:
|
||||||
|
- DB-backed query cache (`OGP_DB_PREFIXlgsl.cache`, `cache_time`)
|
||||||
|
- image file cache handling
|
||||||
|
- pending/retry semantics in `lgsl_query_cached(...)`
|
||||||
|
- `dsi` has simple file cache (60s TTL) per generated image and relies on protocol monitor include side effects for query state.
|
||||||
|
|
||||||
|
### Which integrates with server monitor better?
|
||||||
|
- **dsi** is currently more user-facing for “banner + embed code” workflows:
|
||||||
|
- `dsi_render_table(...)` outputs HTML/BBCode snippets.
|
||||||
|
- Integrates query handlers by protocol in `dsi/image.php`.
|
||||||
|
- `lgsl_with_img_mod` is more standalone/legacy LGSL module flow.
|
||||||
|
|
||||||
|
### Which supports player info better?
|
||||||
|
- Both are focused on banner status fields (name/map/players/status).
|
||||||
|
- Neither is currently a full player-list UI provider for Game Manager.
|
||||||
|
- Query-level player data comes from monitor protocol paths, not these image modules as a first-class shared API.
|
||||||
|
|
||||||
|
### Which is easier to modernize?
|
||||||
|
- **dsi** is the better base for a future unified GSP banner module:
|
||||||
|
- simpler structure
|
||||||
|
- clear image endpoint + code generation UI
|
||||||
|
- already aware of LGSL/GameQ/TS3 protocol branching
|
||||||
|
- `lgsl_with_img_mod` contains useful mature cache ideas and map/image utilities worth reusing.
|
||||||
|
|
||||||
|
## Recommended future GSP banner direction
|
||||||
|
Future module target: `Panel/modules/server_status_banner/`
|
||||||
|
|
||||||
|
### Plan
|
||||||
|
1. Keep both current modules in place during migration.
|
||||||
|
2. Use `dsi` UX flow and embed-code patterns as baseline.
|
||||||
|
3. Reuse selective `lgsl_with_img_mod` cache + map/image helper ideas.
|
||||||
|
4. Drive data from normalized query cache (planned `server_query_cache`) and wrapper output.
|
||||||
|
5. Generate GSP-owned PNG banners (small / wide / large styles).
|
||||||
|
6. Avoid external GameTracker asset dependency.
|
||||||
|
7. Provide HTML / BBCode / direct image URL output.
|
||||||
|
8. Surface banner preview and code tool in Game Manager.
|
||||||
|
|
||||||
|
## No-removal statement (Phase 1 safety)
|
||||||
|
- `lgsl_with_img_mod` was **not removed**.
|
||||||
|
- `dsi` was **not removed**.
|
||||||
|
- This phase is documentation and direction-setting only.
|
||||||
168
Panel/protocol/PROTOCOL_UPGRADE_REVIEW.md
Normal file
168
Panel/protocol/PROTOCOL_UPGRADE_REVIEW.md
Normal file
|
|
@ -0,0 +1,168 @@
|
||||||
|
# Protocol Upgrade Review (Phase 1, safe path)
|
||||||
|
|
||||||
|
## Scope reviewed
|
||||||
|
- `Panel/protocol/lgsl/`
|
||||||
|
- `Panel/protocol/GameQ/`
|
||||||
|
- `Panel/modules/gamemanager/server_monitor.php`
|
||||||
|
- `Panel/modules/gamemanager/ref_servermonitor.php`
|
||||||
|
- `Panel/modules/gamemanager/start_server.php`
|
||||||
|
- `Panel/modules/gamemanager/restart_server.php`
|
||||||
|
- `Panel/modules/gamemanager/mini_start.php`
|
||||||
|
- `Panel/modules/dashboard/query_ref.php`
|
||||||
|
- `Panel/modules/config_games/server_configs/*.xml`
|
||||||
|
|
||||||
|
## Current protocol folders
|
||||||
|
- `Panel/protocol/lgsl/`
|
||||||
|
- Legacy LGSL implementation and protocol map (`lgsl_protocol.php`).
|
||||||
|
- Monitor helper (`LGSLMonitor.php`).
|
||||||
|
- Player list rendering helper (`functions.php`).
|
||||||
|
- `Panel/protocol/GameQ/`
|
||||||
|
- Modern namespaced GameQ implementation with PSR-4 autoloader.
|
||||||
|
- Monitor helper (`GameQMonitor.php`) + player list rendering helper (`functions.php`).
|
||||||
|
- Very large protocol coverage in `Protocols/`.
|
||||||
|
- Also contains legacy-looking `gameq/` subtree alongside modern files (technical debt signal).
|
||||||
|
|
||||||
|
## How LGSL is currently called
|
||||||
|
- Monitor refresh path:
|
||||||
|
- `gamemanager/ref_servermonitor.php` loads `protocol/lgsl/LGSLMonitor.php` when XML protocol is `lgsl`.
|
||||||
|
- `LGSLMonitor.php` calls `lgsl_query_live(...)`, handles panel query cache (`getServerStatusCache`/`saveServerStatusCache`), and sets `$status/$map/$players/$player_list`.
|
||||||
|
- Start/restart detection path:
|
||||||
|
- `gamemanager/start_server.php` and `restart_server.php` call `lgsl_query_live(..., "sa")` after process launch to decide if server is considered running.
|
||||||
|
- Quick checks:
|
||||||
|
- `gamemanager/mini_start.php` and other helpers call `lgsl_port_conversion(...)` and `lgsl_query_live(...)`.
|
||||||
|
- Connection links:
|
||||||
|
- `server_monitor.php` and dsi/lgsl image flows use `lgsl_port_conversion(...)` and `lgsl_software_link(...)`.
|
||||||
|
|
||||||
|
## GameQ status (usable vs incomplete)
|
||||||
|
- Present and actively used in monitor/start/restart flows (`GameQMonitor.php`, `start_server.php`, `restart_server.php`, `dashboard/query_ref.php`).
|
||||||
|
- Usable for configured XML entries (`protocol=gameq` + `gameq_query_name`).
|
||||||
|
- Inconsistencies/risks:
|
||||||
|
- Mixed API usage exists in module code (`process()` and `requestData()` patterns).
|
||||||
|
- Legacy and modern GameQ structures coexist under `Panel/protocol/GameQ/`.
|
||||||
|
- GameQ is integrated, but implementation consistency is incomplete and should be normalized before broad protocol migration.
|
||||||
|
|
||||||
|
## Files that map game configs to protocol names
|
||||||
|
- Primary source of protocol selection:
|
||||||
|
- `Panel/modules/config_games/server_configs/*.xml` fields:
|
||||||
|
- `<protocol>`
|
||||||
|
- `<lgsl_query_name>`
|
||||||
|
- `<gameq_query_name>`
|
||||||
|
- Supporting editor/schema surfaces:
|
||||||
|
- `Panel/modules/config_games/config_servers.php` (schema order includes protocol tags).
|
||||||
|
- `Panel/modules/config_games/xml_tag_descriptions.php` (documents protocol fields).
|
||||||
|
- `Panel/modules/config_games/xml_config_creator.php` (protocol selector and query-name population).
|
||||||
|
|
||||||
|
## Where player list parsing happens
|
||||||
|
- LGSL:
|
||||||
|
- Query payload from `lgsl_query_live(...)` in `lgsl_protocol.php`.
|
||||||
|
- Player table rendering in `protocol/lgsl/functions.php::print_player_list(...)`.
|
||||||
|
- GameQ:
|
||||||
|
- Query payload from `GameQMonitor.php`.
|
||||||
|
- Player table rendering and field normalization in `protocol/GameQ/functions.php::print_player_list_gameq(...)`.
|
||||||
|
|
||||||
|
## Where map/player/server status data is returned
|
||||||
|
- LGSL live payload shape: `b/s/e/p/t` arrays from `lgsl_query_live(...)`:
|
||||||
|
- status: `b.status`
|
||||||
|
- map/name/player counts/password: `s.*`
|
||||||
|
- player list: `p`
|
||||||
|
- extras (including some bot fields): `e`
|
||||||
|
- GameQ normalized payload (after `normalise` filter):
|
||||||
|
- status: `server.gq_online`
|
||||||
|
- map: `server.gq_mapname`
|
||||||
|
- player counts: `server.gq_numplayers`, `server.gq_maxplayers`
|
||||||
|
- player list: `server.players`
|
||||||
|
|
||||||
|
## Known problems (Phase 1 findings)
|
||||||
|
- Query invocation is duplicated in multiple modules (monitor/start/restart/dashboard/image modules), increasing drift risk.
|
||||||
|
- Start detection currently combines process + query checks but does not explicitly represent a `starting` state in monitor output.
|
||||||
|
- LGSL uses hard exits for invalid parameters (`lgsl_query_live`), which is risky for direct callers without guard logic.
|
||||||
|
- GameQ integration style is not fully standardized across all call sites.
|
||||||
|
- Existing cache model is spread across current status cache and module-specific image caches, without one normalized query cache contract.
|
||||||
|
|
||||||
|
## New wrapper prepared in this phase
|
||||||
|
- Added `Panel/protocol/gsp_query.php`.
|
||||||
|
- Introduces `gsp_query_server($server_info, $options = [])` normalized result contract.
|
||||||
|
- Keeps default provider on LGSL (`lgsl_legacy`) for safety.
|
||||||
|
- Adds provider concept placeholders (no broad provider switch in this phase):
|
||||||
|
- `lgsl_legacy`
|
||||||
|
- `gameq`
|
||||||
|
- `xpaw_source_query`
|
||||||
|
- `minecraft_query`
|
||||||
|
- `custom_script`
|
||||||
|
|
||||||
|
## Proposed query cache table (planning only, no migration applied)
|
||||||
|
```sql
|
||||||
|
CREATE TABLE IF NOT EXISTS OGP_DB_PREFIXserver_query_cache (
|
||||||
|
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
home_id INT NOT NULL,
|
||||||
|
ip VARCHAR(64) NOT NULL,
|
||||||
|
port INT NOT NULL,
|
||||||
|
query_port INT NULL,
|
||||||
|
protocol VARCHAR(64) NULL,
|
||||||
|
provider VARCHAR(64) NULL,
|
||||||
|
online TINYINT(1) NOT NULL DEFAULT 0,
|
||||||
|
server_name VARCHAR(255) NULL,
|
||||||
|
map_name VARCHAR(128) NULL,
|
||||||
|
players INT NULL,
|
||||||
|
max_players INT NULL,
|
||||||
|
bots INT NULL,
|
||||||
|
passworded TINYINT(1) NULL,
|
||||||
|
latency_ms INT NULL,
|
||||||
|
player_list_json MEDIUMTEXT NULL,
|
||||||
|
raw_json MEDIUMTEXT NULL,
|
||||||
|
last_query_at DATETIME NULL,
|
||||||
|
last_success_at DATETIME NULL,
|
||||||
|
last_error TEXT NULL,
|
||||||
|
UNIQUE KEY uniq_home_query (home_id),
|
||||||
|
KEY idx_last_query_at (last_query_at),
|
||||||
|
KEY idx_online (online)
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
Cache TTL target: **60 seconds** default.
|
||||||
|
|
||||||
|
## Server start detection improvement plan (no behavior change yet)
|
||||||
|
- After start command, mark status as **starting**.
|
||||||
|
- Poll on a short interval until timeout:
|
||||||
|
1. Check agent process state.
|
||||||
|
2. Check network port open.
|
||||||
|
3. Check query response (if protocol supported).
|
||||||
|
- Final states:
|
||||||
|
- Process + query OK: **Online**
|
||||||
|
- Process OK but query unavailable: **Running, query unavailable**
|
||||||
|
- Process missing at timeout: **Failed to start**
|
||||||
|
|
||||||
|
## Game Manager integration plan (`server_monitor.php`)
|
||||||
|
Future `Live Server Status` panel should include:
|
||||||
|
- State: Online / Offline / Starting / Running query unavailable
|
||||||
|
- Server name
|
||||||
|
- Current map
|
||||||
|
- Players / max players
|
||||||
|
- Player list
|
||||||
|
- Query latency
|
||||||
|
- Last query time
|
||||||
|
- Banner preview
|
||||||
|
- “Get banner code” action
|
||||||
|
|
||||||
|
## Admin query debug/test page plan
|
||||||
|
Future page: `Panel/protocol/query_test.php` (admin-only)
|
||||||
|
- Inputs: IP, port, query port, protocol, provider, timeout
|
||||||
|
- Outputs: normalized result, raw result, errors
|
||||||
|
- Security:
|
||||||
|
- admin-only access gate
|
||||||
|
- CSRF for submit actions
|
||||||
|
- request limits / timeout caps
|
||||||
|
- no anonymous/public proxy behavior
|
||||||
|
|
||||||
|
## Recommended next phase
|
||||||
|
1. Switch one low-risk monitor path to read `gsp_query_server()` output in parallel with existing behavior (feature-flag style).
|
||||||
|
2. Standardize GameQ call style (single API usage pattern) and document supported protocol mappings.
|
||||||
|
3. Add normalized cache write/read adapter (without removing existing caches yet).
|
||||||
|
4. Add explicit start-state model and timeout policy constants.
|
||||||
|
5. Begin unified banner module implementation against normalized cache payloads.
|
||||||
|
|
||||||
|
## Safety statement
|
||||||
|
- No protocol engines were removed.
|
||||||
|
- LGSL remains in place.
|
||||||
|
- GameQ remains in place.
|
||||||
|
- Existing server monitor behavior remains intact in this phase.
|
||||||
157
Panel/protocol/gsp_query.php
Normal file
157
Panel/protocol/gsp_query.php
Normal file
|
|
@ -0,0 +1,157 @@
|
||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* GSP query wrapper (Phase 1 scaffolding)
|
||||||
|
*
|
||||||
|
* Normalizes server query results while keeping LGSL as the default provider.
|
||||||
|
* This file intentionally avoids changing existing monitor paths in this phase.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!function_exists('gsp_query_provider_names')) {
|
||||||
|
function gsp_query_provider_names()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
// LGSL remains default for legacy/older game coverage.
|
||||||
|
'lgsl_legacy',
|
||||||
|
// TODO: Use for games where current GameQ support is proven reliable.
|
||||||
|
'gameq',
|
||||||
|
// TODO: Prefer for modern Source/Steam query games in a later phase.
|
||||||
|
'xpaw_source_query',
|
||||||
|
// TODO: Prefer dedicated Minecraft query handling in a later phase.
|
||||||
|
'minecraft_query',
|
||||||
|
// TODO: Allow custom scripts for unusual game protocols.
|
||||||
|
'custom_script',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!function_exists('gsp_query_default_result')) {
|
||||||
|
function gsp_query_default_result()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
'success' => false,
|
||||||
|
'online' => false,
|
||||||
|
'provider' => 'lgsl_legacy',
|
||||||
|
'protocol' => '',
|
||||||
|
'game' => '',
|
||||||
|
'server_name' => '',
|
||||||
|
'map' => '',
|
||||||
|
'players' => 0,
|
||||||
|
'max_players' => 0,
|
||||||
|
'bots' => 0,
|
||||||
|
'passworded' => false,
|
||||||
|
'latency_ms' => null,
|
||||||
|
'address' => '',
|
||||||
|
'port' => 0,
|
||||||
|
'query_port' => 0,
|
||||||
|
'player_list' => array(),
|
||||||
|
'raw' => array(),
|
||||||
|
'error' => '',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!function_exists('gsp_query_normalize_player_list')) {
|
||||||
|
function gsp_query_normalize_player_list($players)
|
||||||
|
{
|
||||||
|
$normalized = array();
|
||||||
|
foreach ((array)$players as $player) {
|
||||||
|
$normalized[] = array(
|
||||||
|
'name' => isset($player['name']) ? (string)$player['name'] : '',
|
||||||
|
'score' => isset($player['score']) ? (int)$player['score'] : 0,
|
||||||
|
'time' => isset($player['time']) ? $player['time'] : '',
|
||||||
|
'ping' => isset($player['ping']) ? (int)$player['ping'] : 0,
|
||||||
|
'raw' => (array)$player,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return $normalized;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!function_exists('gsp_query_server')) {
|
||||||
|
function gsp_query_server($server_info, $options = array())
|
||||||
|
{
|
||||||
|
$result = gsp_query_default_result();
|
||||||
|
$server = (array)$server_info;
|
||||||
|
$options = (array)$options;
|
||||||
|
|
||||||
|
$provider = isset($options['provider']) ? (string)$options['provider'] : (isset($server['query_provider']) ? (string)$server['query_provider'] : 'lgsl_legacy');
|
||||||
|
$result['provider'] = $provider;
|
||||||
|
|
||||||
|
$ip = isset($server['ip']) ? trim((string)$server['ip']) : '';
|
||||||
|
$port = isset($server['port']) ? (int)$server['port'] : 0;
|
||||||
|
$query_ip = $ip;
|
||||||
|
if (!empty($server['use_nat']) && !empty($server['agent_ip'])) {
|
||||||
|
$query_ip = trim((string)$server['agent_ip']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$result['address'] = ($ip !== '' && $port > 0) ? $ip . ':' . $port : '';
|
||||||
|
$result['port'] = $port;
|
||||||
|
|
||||||
|
if ($provider !== 'lgsl_legacy') {
|
||||||
|
$result['error'] = "Query provider not implemented yet: {$provider}";
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
$query_name = '';
|
||||||
|
if (isset($server['lgsl_query_name'])) {
|
||||||
|
$query_name = (string)$server['lgsl_query_name'];
|
||||||
|
} elseif (isset($server['query_name'])) {
|
||||||
|
$query_name = (string)$server['query_name'];
|
||||||
|
}
|
||||||
|
$query_name = trim($query_name);
|
||||||
|
$result['protocol'] = $query_name;
|
||||||
|
|
||||||
|
if ($query_name === '') {
|
||||||
|
$result['error'] = 'Missing LGSL query name.';
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($query_ip === '' || preg_match("/[^0-9a-z\\.\\-\\[\\]\\:]/i", $query_ip)) {
|
||||||
|
$result['error'] = 'Invalid query IP/hostname.';
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($port <= 0) {
|
||||||
|
$result['error'] = 'Invalid server port.';
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
require_once __DIR__ . '/lgsl/lgsl_protocol.php';
|
||||||
|
$protocols = lgsl_protocol_list();
|
||||||
|
if (!isset($protocols[$query_name])) {
|
||||||
|
$result['error'] = "Unsupported LGSL protocol type: {$query_name}";
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
list($c_port, $default_q_port, $s_port) = lgsl_port_conversion($query_name, $port, "", "");
|
||||||
|
$q_port = isset($server['query_port']) && (int)$server['query_port'] > 0 ? (int)$server['query_port'] : (int)$default_q_port;
|
||||||
|
$result['query_port'] = $q_port;
|
||||||
|
|
||||||
|
if ($q_port <= 0) {
|
||||||
|
$result['error'] = 'Invalid query port for LGSL query.';
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
$raw = lgsl_query_live($query_name, $query_ip, $c_port, $q_port, $s_port, "sep");
|
||||||
|
if (!is_array($raw) || !isset($raw['b']) || !isset($raw['b']['status'])) {
|
||||||
|
$result['error'] = 'LGSL query returned an invalid payload.';
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
$result['raw'] = $raw;
|
||||||
|
$result['success'] = true;
|
||||||
|
$result['online'] = ((string)$raw['b']['status'] === '1' || (int)$raw['b']['status'] === 1);
|
||||||
|
$result['game'] = isset($raw['s']['game']) ? (string)$raw['s']['game'] : '';
|
||||||
|
$result['server_name'] = isset($raw['s']['name']) ? (string)$raw['s']['name'] : '';
|
||||||
|
$result['map'] = isset($raw['s']['map']) ? (string)$raw['s']['map'] : '';
|
||||||
|
$result['players'] = isset($raw['s']['players']) ? (int)$raw['s']['players'] : 0;
|
||||||
|
$result['max_players'] = isset($raw['s']['playersmax']) ? (int)$raw['s']['playersmax'] : 0;
|
||||||
|
$result['bots'] = isset($raw['e']['bots']) ? (int)$raw['e']['bots'] : 0;
|
||||||
|
$result['passworded'] = !empty($raw['s']['password']);
|
||||||
|
$result['latency_ms'] = isset($raw['t']['ping']) ? (int)$raw['t']['ping'] : null;
|
||||||
|
$result['player_list'] = isset($raw['p']) ? gsp_query_normalize_player_list($raw['p']) : array();
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
Loading…
Add table
Add a link
Reference in a new issue