Migrate CI to Gitea and improve live map diagnostics
CI / Real Minecraft installs (manual) (push) Skipped
CI / Rust, web and container (push) Canceled after 0s
CI / Windows launcher (push) Canceled after 0s
Server integrations / paper (push) Canceled after 0s
Server integrations / Fabric and Forge / 1.20.1 (push) Canceled after 0s
Server integrations / Fabric and Forge / 1.21.1 (push) Canceled after 0s
Server integrations / Fabric and Forge / 26.1.2 (push) Canceled after 0s
Server integrations / Fabric and Forge / 26.2 (push) Canceled after 0s
Server integrations / Fabric and Forge / 26.3 (push) Canceled after 0s

This commit is contained in:
SCOPEDD committed 2026-10-01 00:07:35 -04:00
1 parent d72d7c2e80
commit 7809d47d39
32 files changed
+518 -325

No files matched your search

+1
View File
@@ -259,6 +259,7 @@ pub fn api(state: &AppState) -> Router<AppState> {
.route("/map/tiles", post(worldmap::game_tiles))
.route("/map/players", post(worldmap::game_players))
.route("/map/overlay", post(worldmap::game_overlay))
.route("/map/diagnostics", post(worldmap::game_diagnostics))
.layer(DefaultBodyLimit::max(10 * 1024 * 1024));
Router::new()
+14
View File
@@ -89,6 +89,19 @@ pub async fn game_overlay(
Ok(Json(json!({ "ok": true })))
}
pub async fn game_diagnostics(
GameServer(server): GameServer,
State(state): State<AppState>,
Json(value): Json<Value>,
) -> AppResult<Json<Value>> {
require_enabled(server.map_enabled)?;
if !value.is_object() || value.to_string().len() > 4096 {
return Err(AppError::bad_request("invalid map diagnostics"));
}
state.worldmap.set_diagnostics(server.id, value);
Ok(Json(json!({ "ok": true })))
}
// ---------------------------------------------------------------------------
// Launcher and admin viewers
// ---------------------------------------------------------------------------
@@ -143,6 +156,7 @@ pub async fn admin_status(_: AdminUser, State(state): State<AppState>, Path(id):
v["stats"] = serde_json::to_value(state.worldmap.stats(id))?;
v["epoch"] = json!(state.worldmap.epoch(id));
v["roster"] = serde_json::to_value(state.worldmap.live_players(id))?;
v["diagnostics"] = state.worldmap.diagnostics(id);
Ok(Json(v))
}
+21
View File
@@ -56,6 +56,7 @@ pub struct WorldMap {
tokens: Mutex<HashMap<String, (i64, Instant)>>,
overlays: Mutex<HashMap<i64, Value>>,
stats: Mutex<HashMap<i64, Stats>>,
diagnostics: Mutex<HashMap<i64, (Instant, Value)>>,
}
/// A dimension id ("minecraft:the_nether") as a safe folder name ("the_nether"). Other namespaces keep theirs ("mod__space").
@@ -133,6 +134,7 @@ impl WorldMap {
tokens: Default::default(),
overlays: Default::default(),
stats: Default::default(),
diagnostics: Default::default(),
}
}
@@ -217,6 +219,7 @@ impl WorldMap {
std::fs::write(dir.join("epoch"), epoch.to_string())?;
self.overlays.lock().unwrap().remove(&id);
*self.stats.lock().unwrap().entry(id).or_default() = Stats::default();
self.diagnostics.lock().unwrap().remove(&id);
Ok(())
}
@@ -231,12 +234,30 @@ impl WorldMap {
self.players.lock().unwrap().remove(&id);
self.overlays.lock().unwrap().remove(&id);
self.stats.lock().unwrap().remove(&id);
self.diagnostics.lock().unwrap().remove(&id);
}
pub fn stats(&self, id: i64) -> Stats {
self.stats.lock().unwrap().get(&id).cloned().unwrap_or_default()
}
pub fn set_diagnostics(&self, id: i64, value: Value) {
self.diagnostics.lock().unwrap().insert(id, (Instant::now(), value));
}
pub fn diagnostics(&self, id: i64) -> Value {
self.diagnostics
.lock()
.unwrap()
.get(&id)
.map(|(at, value)| {
let mut value = value.clone();
value["age_seconds"] = json!(at.elapsed().as_secs());
value
})
.unwrap_or(Value::Null)
}
// ---- players -------------------------------------------------------------------------
pub fn set_players(&self, id: i64, mut players: Vec<LivePlayer>) {