mirror of
https://github.com/horizon-rust/horizon-mods.git
synced 2026-11-07 11:05:58 -10:00
SMP: the /vanish reminder sits on the action bar, not mid-screen (#298)
rdbt (operator, #mod-chat 11-05): the centred 'Vanished: only operators see you' line covers the view. It is now an action bar line refreshed once a second; unvanishing sends an empty action bar instead of clearing titles. proof.py checks the action bar and that nothing shows mid-screen. Co-authored-by: Horizon agent <[email protected]> Co-authored-by: Claude Opus 5.5 <[email protected]>
This commit is contained in:
3 files changed
+21
-22
No files matched your search
@@ -117,8 +117,8 @@ the other operators on. Needs horizon#6106 (`native_inventory`, `native_move_sta
|
|||||||
|
|
||||||
**Vanish.** `/vanish` takes an operator of level 3 out of the Tab list and the world of every player below level 3,
|
**Vanish.** `/vanish` takes an operator of level 3 out of the Tab list and the world of every player below level 3,
|
||||||
whatever the game mode (survival and creative too), and those players don't read them joining or leaving; operators of
|
whatever the game mode (survival and creative too), and those players don't read them joining or leaving; operators of
|
||||||
level 3 or more still see them, and are told who vanished. A vanished operator reads a subtitle the whole time
|
level 3 or more still see them, and are told who vanished. A vanished operator reads a line above the hotbar the
|
||||||
(*Vanished: only operators see you*), isn't counted online (the sidebar, the Tab list's footer), doesn't hold the night up, isn't
|
whole time (*Vanished: only operators see you*), isn't counted online (the sidebar, the Tab list's footer), doesn't hold the night up, isn't
|
||||||
announced as AFK or on a first join, and can't be reached by name by those who don't see them (`/tpa`, `/trade`,
|
announced as AFK or on a first join, and can't be reached by name by those who don't see them (`/tpa`, `/trade`,
|
||||||
`/coinflip`, `/playtime`). It lasts over a relog and a restart (`vanish.json`) until `/vanish` again. Needs
|
`/coinflip`, `/playtime`). It lasts over a relog and a restart (`vanish.json`) until `/vanish` again. Needs
|
||||||
horizon#7003 (`native_hide_player`).
|
horizon#7003 (`native_hide_player`).
|
||||||
|
|||||||
@@ -2682,22 +2682,18 @@ pub(in crate::game) fn tick(game: &mut Game<'_>) {
|
|||||||
game.native_sleep_ignored(uuid, ignored);
|
game.native_sleep_ignored(uuid, ignored);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// A vanished player doesn't hold the night up; the subtitle lasts a
|
// A vanished player doesn't hold the night up. The reminder is on the
|
||||||
// little past the next second's (1.5 s), so it never blinks.
|
// action bar, above the hotbar, not in the middle of the screen: sent once
|
||||||
|
// a second, it stays up (an action bar line lasts about 3 s), so it never blinks.
|
||||||
for (uuid, name) in subtitles {
|
for (uuid, name) in subtitles {
|
||||||
game.native_sleep_ignored(uuid, true);
|
game.native_sleep_ignored(uuid, true);
|
||||||
let subtitle = serde_json::json!({"text": smp_vanish::SUBTITLE, "color": "aqua"});
|
let line = serde_json::json!({"text": smp_vanish::SUBTITLE, "color": "aqua"});
|
||||||
for line in [
|
game.native_run_command(&format!("title {name} actionbar {line}"));
|
||||||
format!("title {name} times 0 30 5"),
|
|
||||||
format!("title {name} subtitle {subtitle}"),
|
|
||||||
format!("title {name} title \"\""),
|
|
||||||
] {
|
|
||||||
game.native_run_command(&line);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
for (uuid, name) in unvanished {
|
for (uuid, name) in unvanished {
|
||||||
game.native_sleep_ignored(uuid, false);
|
game.native_sleep_ignored(uuid, false);
|
||||||
game.native_run_command(&format!("title {name} clear"));
|
// An empty line takes the reminder down at once, and leaves any title alone.
|
||||||
|
game.native_run_command(&format!("title {name} actionbar \"\""));
|
||||||
}
|
}
|
||||||
for line in particles.into_iter().chain(casino) {
|
for line in particles.into_iter().chain(casino) {
|
||||||
game.native_run_command(&line);
|
game.native_run_command(&line);
|
||||||
|
|||||||
+12
-9
@@ -1068,27 +1068,30 @@ def trades(server, alex, steve, port, ctl, resources, root):
|
|||||||
|
|
||||||
|
|
||||||
def vanish(server, alex, steve, out):
|
def vanish(server, alex, steve, out):
|
||||||
"""/vanish: Alex (an operator) leaves Steve's world and Tab list, and reads a subtitle the whole time; Steve can't
|
"""/vanish: Alex (an operator) leaves Steve's world and Tab list, and reads a line above the hotbar the whole time; Steve can't
|
||||||
reach her by name; /vanish again brings her back. Steve can't vanish."""
|
reach her by name; /vanish again brings her back. Steve can't vanish."""
|
||||||
r = {}
|
r = {}
|
||||||
players = lambda c: [e for e in c.run("entities", 64, "player")["entities"]]
|
players = lambda c: [e for e in c.run("entities", 64, "player")["entities"]]
|
||||||
subtitle = lambda c: c.run("messages", 1).get("subtitle") or ""
|
actionbar = lambda c: c.run("messages", 1).get("actionbar") or ""
|
||||||
|
centre = lambda c: (c.run("messages", 1).get("subtitle") or "") + (c.run("messages", 1).get("title") or "")
|
||||||
r["seen_before"] = len(players(steve))
|
r["seen_before"] = len(players(steve))
|
||||||
r["refused"] = steve.say("/vanish")
|
r["refused"] = steve.say("/vanish")
|
||||||
assert any("Unknown" in l or "Only operators" in l or "permission" in l for l in r["refused"]), r
|
assert any("Unknown" in l or "Only operators" in l or "permission" in l for l in r["refused"]), r
|
||||||
r["vanish"] = alex.say("/vanish")
|
r["vanish"] = alex.say("/vanish")
|
||||||
assert any("You vanished" in l for l in r["vanish"]), r
|
assert any("You vanished" in l for l in r["vanish"]), r
|
||||||
time.sleep(2.5)
|
time.sleep(2.5)
|
||||||
# Over a few seconds, not just once: the subtitle never lapses.
|
# Over a few seconds, not just once: the line never lapses.
|
||||||
r["subtitles"] = []
|
r["actionbar"] = []
|
||||||
for _ in range(4):
|
for _ in range(4):
|
||||||
r["subtitles"].append(subtitle(alex))
|
r["actionbar"].append(actionbar(alex))
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
assert all(s == "Vanished: only operators see you" for s in r["subtitles"]), r
|
assert all(s == "Vanished: only operators see you" for s in r["actionbar"]), r
|
||||||
assert "Vanished" not in subtitle(steve), r
|
# On the action bar only: nothing in the middle of the screen.
|
||||||
|
assert "Vanished" not in centre(alex), r
|
||||||
|
assert "Vanished" not in actionbar(steve), r
|
||||||
if r["seen_before"]:
|
if r["seen_before"]:
|
||||||
assert not players(steve), "Steve no longer sees Alex"
|
assert not players(steve), "Steve no longer sees Alex"
|
||||||
alex.run("screenshot", str(Path(out).resolve() / "vanish-subtitle.png"))
|
alex.run("screenshot", str(Path(out).resolve() / "vanish-actionbar.png"))
|
||||||
steve.run("key", "tab", "down")
|
steve.run("key", "tab", "down")
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
steve.run("screenshot", str(Path(out).resolve() / "vanish-tab.png"))
|
steve.run("screenshot", str(Path(out).resolve() / "vanish-tab.png"))
|
||||||
@@ -1100,7 +1103,7 @@ def vanish(server, alex, steve, out):
|
|||||||
r["back"] = alex.say("/vanish")
|
r["back"] = alex.say("/vanish")
|
||||||
assert any("You are visible again." in l for l in r["back"]), r
|
assert any("You are visible again." in l for l in r["back"]), r
|
||||||
time.sleep(3)
|
time.sleep(3)
|
||||||
assert "Vanished" not in subtitle(alex), r
|
assert "Vanished" not in actionbar(alex), r
|
||||||
if r["seen_before"]:
|
if r["seen_before"]:
|
||||||
assert players(steve), "Steve sees Alex again"
|
assert players(steve), "Steve sees Alex again"
|
||||||
time.sleep(6) # the spam guard's window, for the steps after
|
time.sleep(6) # the spam guard's window, for the steps after
|
||||||
|
|||||||
Reference in new issue
Block a user