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
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:
1 parent
d72d7c2e80
commit
7809d47d39
32 files changed
+518
-325
No files matched your search
@@ -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()
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
|
||||
@@ -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>) {
|
||||
|
||||
Reference in new issue
Block a user