Import T5-AIO and T6 into combined repo
This commit is contained in:
@@ -0,0 +1,163 @@
|
||||
/* tws_t6_telemetry.gsc - direct HTTP round telemetry via t6-gsc-utils. */
|
||||
|
||||
#include maps\mp\_utility;
|
||||
#include common_scripts\utility;
|
||||
|
||||
// Plutonium probes both entry points; runtime setup belongs in init.
|
||||
main()
|
||||
{
|
||||
println("[tws_t6_telemetry] main reached (HTTP API target: t6-gsc-utils v3.1.1)");
|
||||
}
|
||||
|
||||
init()
|
||||
{
|
||||
println("[tws_t6_telemetry] init reached");
|
||||
// Loaded only from scripts/zm; no shared HUD configuration is needed.
|
||||
// Enabled when unset; explicitly set 0 to opt out.
|
||||
if (GetDvar("tws_telemetry_enabled") == "0")
|
||||
{
|
||||
println("[tws_t6_telemetry] disabled");
|
||||
return;
|
||||
}
|
||||
|
||||
// Repeated init in the same VM must not create competing senders.
|
||||
if (isDefined(level.telemetry_initialized))
|
||||
return;
|
||||
|
||||
level.telemetry_url = GetDvar("tws_telemetry_url");
|
||||
if (level.telemetry_url == "")
|
||||
level.telemetry_url = "http://192.168.1.199:3000/api/telemetry";
|
||||
|
||||
level.telemetry_server = GetDvar("tws_server_id");
|
||||
if (level.telemetry_server == "" || level.telemetry_server.size > 255)
|
||||
{
|
||||
println("[tws_t6_telemetry] Set tws_server_id to the exact registered server name (1-255 characters)");
|
||||
return;
|
||||
}
|
||||
|
||||
level.telemetry_initialized = true;
|
||||
level.telemetry_pending = undefined;
|
||||
println("[tws_t6_telemetry] watching for an occupied positive round");
|
||||
level thread telemetry_delivery_worker();
|
||||
level thread telemetry_round_watcher();
|
||||
}
|
||||
|
||||
// Independent of HUD installation. Report the first occupied positive round,
|
||||
// including round 1 when the map pre-seeds it, then each observed transition.
|
||||
telemetry_round_watcher()
|
||||
{
|
||||
level endon("end_game");
|
||||
level endon("game_ended");
|
||||
level endon("intermission");
|
||||
|
||||
last_round = -1;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (isDefined(level.round_number) && level.round_number >= 1 &&
|
||||
level.round_number != last_round)
|
||||
{
|
||||
players = getPlayers();
|
||||
if (players.size > 0)
|
||||
{
|
||||
last_round = level.round_number;
|
||||
|
||||
// Snapshot values before handing off to the HTTP thread.
|
||||
data = [];
|
||||
data["event"] = "round_change";
|
||||
data["round"] = int(last_round);
|
||||
data["server"] = level.telemetry_server;
|
||||
data["players"] = players.size;
|
||||
|
||||
// No runId field (including null/empty), boot, session or
|
||||
// feature events in Fleet-only mode. Keep just the newest
|
||||
// pending observation so an outage cannot build a backlog.
|
||||
pending = spawnStruct();
|
||||
println("[tws_t6_telemetry] serializing round " + last_round);
|
||||
pending.body = jsonSerialize(data);
|
||||
pending.observed_at = getTime();
|
||||
level.telemetry_pending = pending;
|
||||
}
|
||||
}
|
||||
|
||||
wait (0.5);
|
||||
}
|
||||
}
|
||||
|
||||
telemetry_delivery_worker()
|
||||
{
|
||||
level endon("end_game");
|
||||
level endon("game_ended");
|
||||
level endon("intermission");
|
||||
|
||||
backoff = [];
|
||||
backoff[0] = 1;
|
||||
backoff[1] = 2;
|
||||
backoff[2] = 5;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (!isDefined(level.telemetry_pending))
|
||||
{
|
||||
wait (0.5);
|
||||
continue;
|
||||
}
|
||||
|
||||
pending = level.telemetry_pending;
|
||||
level.telemetry_pending = undefined;
|
||||
|
||||
// One in-flight request plus one replaceable pending observation.
|
||||
// A newer observation always retires retries of an older round.
|
||||
for (attempt = 0; attempt < 4; attempt++)
|
||||
{
|
||||
if (isDefined(level.telemetry_pending) ||
|
||||
getTime() - pending.observed_at > 15000)
|
||||
break;
|
||||
|
||||
if (telemetry_send(pending.body))
|
||||
break;
|
||||
|
||||
if (attempt < 3)
|
||||
wait (backoff[attempt]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Returns transport completion only, NEVER beta/API acceptance. The released
|
||||
// plugin exposes body/success/error but no HTTP status or cancellation. Do not
|
||||
// start a replacement request on a script timeout: the old one could still
|
||||
// commit later and overwrite Fleet with a stale round. Gameplay never waits
|
||||
// on this worker. Malformed/HTML bodies are not passed to throwing jsonParse.
|
||||
telemetry_send(body)
|
||||
{
|
||||
headers = [];
|
||||
headers["Content-Type"] = "application/json";
|
||||
|
||||
options = [];
|
||||
options["method"] = "POST";
|
||||
options["headers"] = headers;
|
||||
options["body"] = body;
|
||||
|
||||
// v3.1.1 global alias: options array, NOT positional body/headers.
|
||||
// Avoid the raw loader treating the http namespace as http.gsc.
|
||||
println("[tws_t6_telemetry] calling httpPost");
|
||||
request = httpPost(level.telemetry_url, options);
|
||||
println("[tws_t6_telemetry] HTTP handle returned; waiting for completion");
|
||||
request waittill("done", response, success, error);
|
||||
println("[tws_t6_telemetry] HTTP completion received");
|
||||
|
||||
// The plugin's success flag reports transport completion, not HTTP status.
|
||||
// Unscoped round reports replace Fleet state; retrying the same snapshot
|
||||
// cannot duplicate beta evidence. HTTP errors cannot be classified here,
|
||||
// so only reported transport failures receive bounded retries.
|
||||
if (!isDefined(success) || !success)
|
||||
{
|
||||
if (!isDefined(error))
|
||||
error = "unknown transport error";
|
||||
print("^1[tws_t6_telemetry] Round telemetry failed: " + error);
|
||||
return false;
|
||||
}
|
||||
|
||||
println("[tws_t6_telemetry] Transport completed; API acceptance is not verified by this plugin");
|
||||
return true;
|
||||
}
|
||||
Reference in New Issue
Block a user