Skip to content

Commit a73bbaf

Browse files
committed
Moved the client-side specialization logic to a class and registry based
system much like the backend to make specialization logic more encapsulated and easier to produce
1 parent 710f0a2 commit a73bbaf

File tree

4 files changed

+55
-38
lines changed

4 files changed

+55
-38
lines changed

src/configuration.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use serde_json::Value;
1717
/// * `registry` - The specialization registry to check allowed types.
1818
pub fn validate_specializations_in_config(config_json: &Value, registry: &SpecializationRegistry) {
1919
let allowed: Vec<String> = registry
20-
.allowed_names()
20+
.existing_names()
2121
.into_iter()
2222
.map(|name| format!("\"{}\"", name))
2323
.collect();

src/html_src/index.js

Lines changed: 52 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ function addServerDropdown(serverName, inactive) {
209209
if (inactive == true) {
210210
dropdown.toggleClass("inactiveServer");
211211
}
212-
updateServerInfoMCSpecialization();
212+
updateServerInfoSpecializations();
213213
}
214214

215215
function addDropdownNoDupe(name, inactive) {
@@ -233,35 +233,59 @@ function checkAllServers() {
233233
var servers = $(".CentralMenuDropdown").toArray();
234234
//finish this, make sure serverInfo
235235
}
236-
function updateServerInfoMCSpecialization() {
236+
/**
237+
* Specialization base class.
238+
* Extend this for each server specialization.
239+
*/
240+
class ServerSpecialization {
241+
updateUI(dropdownElement, server) {
242+
// Default: do nothing
243+
}
244+
}
245+
246+
/**
247+
* Minecraft specialization class.
248+
*/
249+
class MinecraftSpecialization extends ServerSpecialization {
250+
updateUI(dropdownElement, server) {
251+
const serverNameElem = dropdownElement.querySelector(".serverName");
252+
if (serverNameElem) {
253+
if (server.active) {
254+
let playerCount = server.specialized_info?.player_count ?? 0;
255+
let maxPlayers = server.specialized_info?.max_players ?? 0;
256+
let isReady = server.specialized_info?.ready ?? false;
257+
let statusText = isReady ? "ready to join" : "starting";
258+
serverNameElem.textContent = `${server.name} (${playerCount} / ${maxPlayers}) Status: ${statusText}`;
259+
} else {
260+
serverNameElem.textContent = `${server.name} (inactive)`;
261+
}
262+
}
263+
}
264+
}
265+
266+
/**
267+
* Specialization registry.
268+
* Maps config string to specialization class instance.
269+
*/
270+
const specializationRegistry = {
271+
Minecraft: new MinecraftSpecialization(),
272+
// Add more: Rust: new RustSpecialization(), etc.
273+
};
274+
275+
/**
276+
* Generic update function for all specializations.
277+
* Calls the appropriate specialization's updateUI for each server.
278+
*/
279+
function updateServerInfoSpecializations() {
237280
try {
238281
const serverInfo = window.serverInfoObj;
282+
if (!serverInfo || !serverInfo.servers) return;
239283
serverInfo.servers.forEach((server) => {
240-
if (server.specialization === "Minecraft") {
241-
// Check if the specialization is Minecraft
242-
const serverElement = $(`.${server.name}dropdown`).find(
243-
".serverName",
244-
)[0];
245-
if (serverElement) {
246-
if (server.active) {
247-
// Expect specialized_info to be an object with player_count, max_players, ready
248-
let playerCount = 0;
249-
let maxPlayers = 0;
250-
let isReady = false;
251-
if (
252-
server.specialized_info &&
253-
typeof server.specialized_info === "object"
254-
) {
255-
playerCount = server.specialized_info.player_count ?? 0;
256-
maxPlayers = server.specialized_info.max_players ?? 0;
257-
isReady = server.specialized_info.ready ?? false;
258-
}
259-
let statusText = isReady ? "ready to join" : "starting";
260-
serverElement.textContent = `${server.name} (${playerCount} / ${maxPlayers}) Status: ${statusText}`;
261-
} else {
262-
serverElement.textContent = `${server.name} (inactive)`;
263-
}
264-
}
284+
const dropdownElement = document.querySelector(`.${server.name}dropdown`);
285+
if (!dropdownElement) return;
286+
const specialization = specializationRegistry[server.specialization];
287+
if (specialization) {
288+
specialization.updateUI(dropdownElement, server);
265289
}
266290
});
267291
} catch (e) {}
@@ -296,7 +320,7 @@ $(document).ready(function () {
296320
hotReloadWhenReady();
297321
};
298322
// Set interval to update server info every quarter second
299-
setInterval(updateServerInfoMCSpecialization, 250);
323+
setInterval(updateServerInfoSpecializations, 250);
300324

301325
socket.onclose = function () {
302326
hotReloadWhenReady();

src/specializations/minecraft.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,6 @@ pub fn factory() -> Box<dyn ServerSpecialization> {
216216
Box::new(MinecraftSpecialization::default())
217217
}
218218

219-
/// Colorizes a single Minecraft log line using bracket counting.
220219
/// Colorizes a single Minecraft log line using bracket counting and HTML spans.
221220
///
222221
/// Applies faded color to the timestamp, semantic color to the log level,
@@ -272,7 +271,7 @@ fn colorize_minecraft_log_line(line: &str) -> String {
272271

273272
// Theme variable mapping
274273
fn type_to_var(typ: &str) -> &'static str {
275-
if typ.contains("ERROR") {
274+
if typ.contains("ERROR") || typ.contains("FATAL") {
276275
"var(--danger)"
277276
} else if typ.contains("WARN") {
278277
"var(--warning)"

src/specializations/mod.rs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -50,19 +50,17 @@ pub trait ServerSpecialization: Send + Sync {
5050
fn get_status(&self) -> serde_json::Value;
5151
}
5252

53-
/// Factory type for creating new specialization instances.
5453
/// Factory type for creating new specialization instances.
5554
pub type SpecializationFactory = fn() -> Box<dyn ServerSpecialization>;
5655

57-
/// Thread-safe registry for all available specializations.
5856
/// Thread-safe registry for all available specializations.
5957
pub struct SpecializationRegistry {
6058
map: DashMap<String, SpecializationFactory>,
6159
}
6260

6361
impl SpecializationRegistry {
6462
/// Returns a Vec of allowed specialization names.
65-
pub fn allowed_names(&self) -> Vec<String> {
63+
pub fn existing_names(&self) -> Vec<String> {
6664
self.map
6765
.iter()
6866
.map(|entry| entry.key().to_string())
@@ -73,9 +71,6 @@ impl SpecializationRegistry {
7371
pub fn contains_key(&self, key: &str) -> bool {
7472
self.map.contains_key(key)
7573
}
76-
}
77-
78-
impl SpecializationRegistry {
7974
/// Create a new, empty registry.
8075
pub fn new() -> Self {
8176
Self {
@@ -104,7 +99,6 @@ impl SpecializationRegistry {
10499
}
105100
}
106101

107-
/// Helper to initialize the registry with built-in specializations.
108102
/// Helper to initialize the registry with built-in specializations.
109103
///
110104
/// Registers "Minecraft" and "Terraria" specializations by default.

0 commit comments

Comments
 (0)