mirror of
https://github.com/horizon-rust/horizon.git
synced 2026-11-07 11:06:11 -10:00
Merge pull request #6518 from xFedeT/feat/native-server-announce
🤖 Agent: queued at b7e01926a.
This commit is contained in:
5 files changed
+44
-3
No files matched your search
@@ -390,6 +390,18 @@ impl Game<'_> {
|
||||
host.hub.send_to(g.conn, &packet);
|
||||
}
|
||||
}
|
||||
/// Posts a line to the dedicated server's event stream (`GET /api/v1/events`)
|
||||
/// as an `announce` event, which horizon-server's Discord bridge relays when
|
||||
/// `[discord] events` lists `announce`: `name` and `uuid` say who it is
|
||||
/// about (empty and 0 for no one), `message` is the line (`§` codes colour it).
|
||||
/// Only on a dedicated server; false elsewhere and for an empty message.
|
||||
pub(super) fn native_server_event(&self, name: &str, uuid: u128, message: &str) -> bool {
|
||||
if self.options.dedicated.is_none() || message.trim().is_empty() {
|
||||
return false;
|
||||
}
|
||||
super::dedicated::events::record("announce", name, uuid, json!({ "message": message }));
|
||||
true
|
||||
}
|
||||
/// A line of the command's answer, inside `native_perform_command`:
|
||||
/// sent to the player whose command it is after the call, as vanilla
|
||||
/// commands' feedback is.
|
||||
|
||||
@@ -20,7 +20,7 @@ const BATCH: Duration = Duration::from_secs(2);
|
||||
const GAP: Duration = Duration::from_secs(2);
|
||||
/// Lines in one picture; more in a burst are counted and skipped.
|
||||
const MAX_LINES: usize = 20;
|
||||
const EVENTS: [&str; 5] = ["chat", "join", "leave", "death", "kick"];
|
||||
const EVENTS: [&str; 6] = ["chat", "join", "leave", "death", "kick", "announce"];
|
||||
/// Zero-width joiner: after an `@` or a `<`, Discord no longer reads a mention.
|
||||
const ZWJ: char = '\u{200D}';
|
||||
|
||||
@@ -159,6 +159,7 @@ struct Run {
|
||||
const WHITE: u32 = 0xFFFFFF;
|
||||
const YELLOW: u32 = 0xFFFF55;
|
||||
const GRAY: u32 = 0xAAAAAA;
|
||||
const GOLD: u32 = 0xFFAA00;
|
||||
/// ChatFormatting's colours, by their code `0`-`f`.
|
||||
const PALETTE: [u32; 16] = [
|
||||
0x000000, 0x0000AA, 0x00AA00, 0x00AAAA, 0xAA0000, 0xAA00AA, 0xFFAA00, 0xAAAAAA, 0x555555,
|
||||
@@ -176,6 +177,8 @@ impl Line {
|
||||
"join" => vec![Run::plain(&format!("{name} joined the game"), YELLOW)],
|
||||
"leave" => vec![Run::plain(&format!("{name} left the game"), YELLOW)],
|
||||
"kick" => vec![Run::plain(&format!("{name} was kicked"), YELLOW)],
|
||||
// A line a native server mod posts (`native_server_event`), drawn like a broadcast.
|
||||
"announce" => legacy(text("message"), GOLD),
|
||||
// The game writes this message itself: should a nickname stand for the player there, the real name
|
||||
// follows it. Lines say who someone is only by `name` (their account), never by a nickname.
|
||||
"death" if !text("message").contains(name.as_str()) => {
|
||||
@@ -539,6 +542,25 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn an_announcement_is_its_message_in_gold_and_cannot_ping() {
|
||||
let line = Line::from_event(
|
||||
&json!({"type": "announce", "name": "", "message": "Jackpot! @everyone"}),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(line.plain(), "Jackpot! @everyone");
|
||||
assert!(line.runs.iter().all(|r| r.color == GOLD));
|
||||
assert!(!defuse(&line.plain(), false).contains("@everyone"));
|
||||
assert!(
|
||||
Settings {
|
||||
events: vec!["announce".into()],
|
||||
..Settings::default()
|
||||
}
|
||||
.check()
|
||||
.is_ok()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn section_codes_colour_the_runs() {
|
||||
let runs = legacy("a§cred§lbold§rplain§9blue§zx", WHITE);
|
||||
|
||||
+1
-1
@@ -385,7 +385,7 @@ Integrations → Webhooks → New Webhook → Copy Webhook URL, then:
|
||||
```toml
|
||||
[discord]
|
||||
webhook = "https://discord.com/api/webhooks/..." # a secret: whoever has it can post in the channel
|
||||
events = ["chat", "join", "leave", "death"] # and "kick"
|
||||
events = ["chat", "join", "leave", "death"] # and "kick", "announce" (lines native mods post)
|
||||
enabled = true # false pauses it and keeps the webhook
|
||||
```
|
||||
|
||||
|
||||
+2
-1
@@ -1287,7 +1287,8 @@ For mods that run where the world is simulated: a dedicated server, a LAN host,
|
||||
- Helpers: `native_server_players()` (uuid, name, level, dimension, position and game mode of each player on);
|
||||
`native_tell(uuid, text)`, a system line to one player, also the acting player inside their hook;
|
||||
`native_broadcast(text)`, to every player and the server's
|
||||
log; `native_feedback(text)`, the command's answer to the player whose command it is; `native_world_dir()`, the
|
||||
log; `native_server_event(name, uuid, message)`, an `announce` event on a dedicated server's event stream, which the Discord
|
||||
bridge relays when `[discord] events` lists `announce`; `native_feedback(text)`, the command's answer to the player whose command it is; `native_world_dir()`, the
|
||||
open world's folder, where a server mod keeps its data in a folder of its own so the world's backups carry it.
|
||||
- **`native_item_damaged(player, name, item, amount, cancel)`**: an item of a player is about to lose durability, on a
|
||||
server (`ItemStack.hurtAndBreak`: tools, armour, shield, rod, elytra), after Unbreaking has had its say. Change
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"hooks": [],
|
||||
"rust_summary": "a server mod's line for the event stream and the Discord bridge (`native_server_event`).",
|
||||
"doc_summary": "`native_server_event(name, uuid, message)` posts an `announce` event to a dedicated server's event stream (`GET /api/v1/events`); horizon-server's Discord bridge relays it, in gold, when `[discord] events` lists `announce` (off by default). False elsewhere and for an empty message. Bundles that use it need \"hooks\": @API:server_event@.",
|
||||
"comments": ["crates/horizon-client/src/game/native_server.rs"]
|
||||
}
|
||||
Reference in new issue
Block a user