Fix Rust formatting
Server integrations / Paper and protocol tests (push) Failing after 20s
Server integrations / fabric / 1.20.1 (push) Failing after 11s
Server integrations / fabric / 1.21.1 (push) Failing after 14s
Server integrations / fabric / 26.1.2 (push) Failing after 17s
Server integrations / fabric / 26.2 (push) Failing after 12s
Server integrations / fabric / 26.3 (push) Failing after 6s
Server integrations / forge / 1.20.1 (push) Failing after 6s
Server integrations / forge / 1.21.1 (push) Failing after 8s
Server integrations / forge / 26.1.2 (push) Failing after 8s
Server integrations / forge / 26.2 (push) Failing after 8s
Server integrations / forge / 26.3 (push) Failing after 7s
CI / Web UIs (type-check + build) (panel/web) (push) Canceled after 0s
CI / Launcher (Windows build check) (push) Canceled after 2m53s
CI / Real installs (Mojang, Fabric, Quilt, Forge, NeoForge) (push) Canceled after 0s
CI / Docker image builds (push) Canceled after 0s
CI / Rust (fmt, clippy, tests) (push) Canceled after 1m22s
CI / Web UIs (type-check + build) (launcher) (push) Canceled after 1m27s

This commit is contained in:
SCOPEDD committed 2026-09-30 22:56:38 -04:00
1 parent ce49447b6e
commit 60edc99780
58 files changed
+3533 -1375

No files matched your search

+65 -15
View File
@@ -24,7 +24,14 @@ impl Env {
(self.t.login(name, "password123").await, self.t.uuid(name).await)
}
async fn report(&self, name: &str, data: Value) -> (StatusCode, Value) {
self.t.call("POST", "/api/server/v1/integrations/report", Some(&self.server), Some(json!({"name": name, "version": "5.4.1", "data": data}))).await
self.t
.call(
"POST",
"/api/server/v1/integrations/report",
Some(&self.server),
Some(json!({"name": name, "version": "5.4.1", "data": data})),
)
.await
}
async fn sync(&self, online: &[(&str, &str)]) -> Value {
let online: Vec<Value> = online.iter().map(|(u, n)| json!({"uuid": u, "name": n})).collect();
@@ -48,19 +55,31 @@ async fn luckperms_ranks_mapping_and_sync_modes() {
}
let (_, groups) = e.t.call("GET", "/api/admin/groups", Some(&e.admin), None).await;
let id = |n: &str| groups.as_array().unwrap().iter().find(|g| g["name"] == n).unwrap()["id"].as_i64().unwrap();
let (s, _) = e.t.call("PUT", &format!("/api/admin/groups/{}/luckperms", id("VIP")), Some(&e.admin), Some(json!({"luckperms_group": "vip"}))).await;
let (s, _) =
e.t.call("PUT", &format!("/api/admin/groups/{}/luckperms", id("VIP")), Some(&e.admin), Some(json!({"luckperms_group": "vip"})))
.await;
assert_eq!(s, StatusCode::OK);
let (s, _) = e.t.call("PUT", &format!("/api/admin/groups/{}/luckperms", id("Staff")), Some(&e.admin), Some(json!({"luckperms_group": "bad group!"}))).await;
let (s, _) =
e.t.call(
"PUT",
&format!("/api/admin/groups/{}/luckperms", id("Staff")),
Some(&e.admin),
Some(json!({"luckperms_group": "bad group!"})),
)
.await;
assert_eq!(s, StatusCode::BAD_REQUEST);
e.t.call("PUT", &format!("/api/admin/groups/{}/luckperms", id("Staff")), Some(&e.admin), Some(json!({"luckperms_group": "Moderator"}))).await;
e.t.call("PUT", &format!("/api/admin/groups/{}/luckperms", id("Staff")), Some(&e.admin), Some(json!({"luckperms_group": "Moderator"})))
.await;
let lp = |steve_groups: Value| json!({
let lp = |steve_groups: Value| {
json!({
"groups": [{"name": "vip", "weight": 10}, {"name": "moderator", "weight": 50}],
"players": [
{"uuid": steve, "primary": "VIP", "display": "VIP", "prefix": "§6[VIP] ", "weight": 10, "groups": steve_groups, "permissions": ["scopenet.command.*", "essentials.fly"]},
{"uuid": alex, "primary": "default", "groups": ["default"]},
{"uuid": "not-a-uuid", "primary": "x"}
]});
]})
};
// Default mode is display-only: ranks are stored, no group changes.
let (s, r) = e.report("luckperms", lp(json!(["default", "vip"]))).await;
@@ -77,7 +96,8 @@ async fn luckperms_ranks_mapping_and_sync_modes() {
assert_eq!(view["integrations"][0]["data"]["groups"][1]["name"], "moderator");
// game_to_panel: mapped groups follow LuckPerms, including removal.
let (s, _) = e.t.call("PUT", "/api/admin/integrations/settings", Some(&e.admin), Some(json!({"luckperms_sync": "game_to_panel"}))).await;
let (s, _) =
e.t.call("PUT", "/api/admin/integrations/settings", Some(&e.admin), Some(json!({"luckperms_sync": "game_to_panel"}))).await;
assert_eq!(s, StatusCode::OK);
e.report("luckperms", lp(json!(["default", "vip", "moderator"]))).await;
assert_eq!(e.groups_of("Steve").await, ["Staff", "VIP"]);
@@ -86,7 +106,11 @@ async fn luckperms_ranks_mapping_and_sync_modes() {
assert!(r["config"]["assign"].as_array().unwrap().is_empty());
// panel_to_game: the panel's groups are pushed to the game as assignments.
sqlx::query("INSERT INTO user_groups (user_id, group_id) SELECT u.id, ? FROM users u WHERE u.username = 'Alex'").bind(id("VIP")).execute(&e.t.db).await.unwrap();
sqlx::query("INSERT INTO user_groups (user_id, group_id) SELECT u.id, ? FROM users u WHERE u.username = 'Alex'")
.bind(id("VIP"))
.execute(&e.t.db)
.await
.unwrap();
e.t.call("PUT", "/api/admin/integrations/settings", Some(&e.admin), Some(json!({"luckperms_sync": "panel_to_game"}))).await;
let (_, r) = e.report("luckperms", lp(json!(["default", "moderator"]))).await;
let assign = r["config"]["assign"].as_array().unwrap();
@@ -107,7 +131,11 @@ async fn luckperms_ranks_mapping_and_sync_modes() {
async fn other_integrations_are_stored_per_server() {
let e = env().await;
e.report("spark", json!({"tps": {"m1": 19.98}, "mspt": {"mean": 12.5, "p95": 31.0}})).await;
e.report("worldguard", json!({"regions": [{"world": "world", "id": "spawn", "min": [-50, 0, -50], "max": [50, 255, 50], "owners": ["admin"]}]})).await;
e.report(
"worldguard",
json!({"regions": [{"world": "world", "id": "spawn", "min": [-50, 0, -50], "max": [50, 255, 50], "owners": ["admin"]}]}),
)
.await;
e.report("spark", json!({"tps": {"m1": 20.0}})).await;
let (_, view) = e.t.call("GET", &format!("/api/admin/servers/{}/integrations", e.sid), Some(&e.admin), None).await;
let names: Vec<&str> = view["integrations"].as_array().unwrap().iter().map(|i| i["name"].as_str().unwrap()).collect();
@@ -127,7 +155,11 @@ async fn game_servers_receive_events_with_their_sync() {
// Level-ups: global and per-server.
let adjust = |scope: &str, mode: &str, amount: i64| {
let (t, admin, uuid, sid) = (&e.t, e.admin.clone(), steve.clone(), e.sid);
let body = if scope == "global" { json!({"scope": "global", "mode": mode, "amount": amount}) } else { json!({"scope": "server", "server_id": sid, "mode": mode, "amount": amount}) };
let body = if scope == "global" {
json!({"scope": "global", "mode": mode, "amount": amount})
} else {
json!({"scope": "server", "server_id": sid, "mode": mode, "amount": amount})
};
async move { t.call("POST", &format!("/api/admin/progression/players/{uuid}/adjust"), Some(&admin), Some(body)).await }
};
adjust("global", "set_xp", 10).await;
@@ -135,7 +167,8 @@ async fn game_servers_receive_events_with_their_sync() {
adjust("server", "set_xp", 10).await;
adjust("server", "set_xp", 300).await; // level 1 -> 2
let n = e.sync(&[(&steve, "Steve")]).await["notifications"].clone();
let kinds: Vec<(&str, &str)> = n.as_array().unwrap().iter().map(|x| (x["kind"].as_str().unwrap(), x["data"]["scope"].as_str().unwrap_or(""))).collect();
let kinds: Vec<(&str, &str)> =
n.as_array().unwrap().iter().map(|x| (x["kind"].as_str().unwrap(), x["data"]["scope"].as_str().unwrap_or(""))).collect();
assert_eq!(kinds, [("level_up", "global"), ("level_up", "server")], "{n}");
assert_eq!((n[0]["data"]["previous"].as_i64(), n[0]["data"]["level"].as_i64()), (Some(1), Some(5)));
assert_eq!(n[0]["uuid"], steve);
@@ -147,10 +180,27 @@ async fn game_servers_receive_events_with_their_sync() {
// Achievements and guild changes.
let ach: String = sqlx::query_scalar("SELECT id FROM achievements LIMIT 1").fetch_one(&e.t.db).await.unwrap();
sqlx::query("INSERT INTO user_achievements (user_uuid, achievement_id, unlocked_at) VALUES (?, ?, 'now')").bind(&steve).bind(&ach).execute(&e.t.db).await.unwrap();
sqlx::query("INSERT INTO guilds (id, instance_id, name, tag, leader_uuid, created_at) VALUES ('g1', 'smp', 'Iron', 'IRON', ?, 'now')").bind(&alex).execute(&e.t.db).await.unwrap();
sqlx::query("INSERT INTO guild_members (guild_id, uuid, name, role, joined_at) VALUES ('g1', ?, 'Steve', 'member', 'now')").bind(&steve).execute(&e.t.db).await.unwrap();
sqlx::query("INSERT INTO guild_members (guild_id, uuid, name, role, joined_at) VALUES ('g1', ?, 'Alex', 'leader', 'now')").bind(&alex).execute(&e.t.db).await.unwrap();
sqlx::query("INSERT INTO user_achievements (user_uuid, achievement_id, unlocked_at) VALUES (?, ?, 'now')")
.bind(&steve)
.bind(&ach)
.execute(&e.t.db)
.await
.unwrap();
sqlx::query("INSERT INTO guilds (id, instance_id, name, tag, leader_uuid, created_at) VALUES ('g1', 'smp', 'Iron', 'IRON', ?, 'now')")
.bind(&alex)
.execute(&e.t.db)
.await
.unwrap();
sqlx::query("INSERT INTO guild_members (guild_id, uuid, name, role, joined_at) VALUES ('g1', ?, 'Steve', 'member', 'now')")
.bind(&steve)
.execute(&e.t.db)
.await
.unwrap();
sqlx::query("INSERT INTO guild_members (guild_id, uuid, name, role, joined_at) VALUES ('g1', ?, 'Alex', 'leader', 'now')")
.bind(&alex)
.execute(&e.t.db)
.await
.unwrap();
sqlx::query("DELETE FROM guild_members WHERE uuid = ?").bind(&steve).execute(&e.t.db).await.unwrap();
let n = e.sync(&[(&steve, "Steve")]).await["notifications"].clone();
let kinds: Vec<&str> = n.as_array().unwrap().iter().map(|x| x["kind"].as_str().unwrap()).collect();