yog_core/server.rs
1//! The handle Rust mods use to act on the running server — the Rust → Minecraft
2//! path.
3
4use crate::BlockPos;
5
6/// Low-level capabilities the Yog runtime exposes to mods (the engine contract).
7///
8/// The runtime provides the concrete implementation, backed by JNI calls into
9/// the Java host; this crate stays JVM-free. Higher-level, ergonomic wrappers
10/// live in the domain crates (e.g. `yog-world`'s `World`).
11///
12/// Dimensions are identified by their registry id string, e.g.
13/// `"minecraft:overworld"`.
14pub trait Server {
15 /// Broadcast a chat message to all players on the server.
16 fn broadcast(&self, message: &str);
17
18 /// Registry id of the block at `pos` in `dimension`
19 /// (e.g. `"minecraft:stone"`), or `None` if the dimension/position is
20 /// unavailable. Call from the server thread (e.g. an event handler).
21 fn get_block(&self, dimension: &str, pos: BlockPos) -> Option<String>;
22
23 /// Set the block at `pos` in `dimension` to `block_id`. Returns whether the
24 /// change was applied. Call from the server thread.
25 fn set_block(&self, dimension: &str, pos: BlockPos, block_id: &str) -> bool;
26
27 /// Give `count` of `item_id` to the named player. Returns whether it worked
28 /// (player online, item valid). Call from the server thread.
29 fn give_item(&self, player: &str, item_id: &str, count: u32) -> bool;
30
31 /// Teleport the named player to `(x, y, z)` in their current world. Returns
32 /// whether it worked. Call from the server thread.
33 fn teleport(&self, player: &str, x: f64, y: f64, z: f64) -> bool;
34
35 /// Send a raw-byte packet to the named player on `channel` (server → client).
36 /// Returns whether the player was online. Payload is opaque bytes — no NBT.
37 fn send_to_player(&self, player: &str, channel: &str, payload: &[u8]) -> bool;
38
39 /// Send a raw-byte packet to the server on `channel` (client → server).
40 /// Only works in a client context; returns whether it was sent.
41 fn send_to_server(&self, channel: &str, payload: &[u8]) -> bool;
42
43 // ── entity (universal, by UUID) ─────────────────────────────────────────
44
45 /// Teleport any entity (by UUID) within its current world.
46 fn entity_teleport(&self, uuid: &str, x: f64, y: f64, z: f64) -> bool;
47
48 /// Position of an entity, or `None` if not loaded.
49 fn entity_position(&self, uuid: &str) -> Option<(f64, f64, f64)>;
50
51 /// Health of a living entity, or `None`.
52 fn entity_health(&self, uuid: &str) -> Option<f32>;
53
54 /// Set a living entity's health; returns whether it applied.
55 fn entity_set_health(&self, uuid: &str, health: f32) -> bool;
56
57 /// Remove/kill an entity.
58 fn entity_kill(&self, uuid: &str) -> bool;
59
60 /// Spawn an entity of `entity_type` (e.g. `minecraft:pig`) at a position;
61 /// returns its UUID, or `None` on failure.
62 fn spawn_entity(
63 &self,
64 entity_type: &str,
65 dimension: &str,
66 x: f64,
67 y: f64,
68 z: f64,
69 ) -> Option<String>;
70
71 // ── status effects ──────────────────────────────────────────────────────
72
73 /// Apply a status effect to a living entity. `effect_id` is a registry id
74 /// such as `"minecraft:speed"` or `"minecraft:regeneration"`. `amplifier` is
75 /// 0-based (0 = level I). Returns `false` if the entity or effect is unknown.
76 fn entity_add_effect(
77 &self,
78 uuid: &str,
79 effect_id: &str,
80 duration_ticks: i32,
81 amplifier: u8,
82 show_particles: bool,
83 ) -> bool;
84
85 /// Remove a single status effect from a living entity.
86 fn entity_remove_effect(&self, uuid: &str, effect_id: &str) -> bool;
87
88 /// Clear all active status effects from a living entity.
89 fn entity_clear_effects(&self, uuid: &str) -> bool;
90
91 // ── loot tables ─────────────────────────────────────────────────────────
92
93 /// Roll a loot table and spawn the resulting item entities in the world.
94 /// `table_id` is the namespaced id, e.g. `"minecraft:entities/zombie"`.
95 fn drop_loot(&self, table_id: &str, dimension: &str, x: f64, y: f64, z: f64) -> bool;
96
97 // ── tag queries ─────────────────────────────────────────────────────────
98
99 /// Returns whether `item_id` (e.g. `"minecraft:stone"`) belongs to `tag_id`
100 /// (e.g. `"minecraft:planks"`).
101 fn has_item_tag(&self, item_id: &str, tag_id: &str) -> bool;
102
103 /// Returns whether `block_id` belongs to `tag_id`.
104 fn has_block_tag(&self, block_id: &str, tag_id: &str) -> bool;
105
106 // ── world state ─────────────────────────────────────────────────────────
107
108 /// Game time in ticks since world creation (never wraps, keeps counting).
109 fn world_time(&self, dimension: &str) -> Option<i64>;
110
111 /// Set the time-of-day (0 = dawn, 6000 = noon, 12000 = dusk, 18000 = midnight).
112 /// Only changes the visual time, not the absolute world age.
113 fn world_set_time(&self, dimension: &str, time: i64) -> bool;
114
115 /// Whether it is currently raining in the given dimension.
116 fn world_is_raining(&self, dimension: &str) -> bool;
117
118 /// Start or stop rain. `duration_ticks` controls how long the weather lasts
119 /// (use 0 for a server-chosen default duration).
120 fn world_set_weather(&self, dimension: &str, raining: bool, duration_ticks: i32) -> bool;
121
122 // ── entity velocity ─────────────────────────────────────────────────────
123
124 /// Current velocity `(vx, vy, vz)` of any entity, or `None` if not loaded.
125 fn entity_velocity(&self, uuid: &str) -> Option<(f64, f64, f64)>;
126
127 /// Set the velocity of any entity. Returns `false` if not loaded.
128 fn entity_set_velocity(&self, uuid: &str, vx: f64, vy: f64, vz: f64) -> bool;
129
130 /// Add a velocity impulse (cumulative with existing velocity).
131 fn entity_add_velocity(&self, uuid: &str, vx: f64, vy: f64, vz: f64) -> bool;
132
133 // ── scoreboard ──────────────────────────────────────────────────────────
134
135 /// Score of `player` on `objective`, or `None` if the objective doesn't exist.
136 fn scoreboard_get(&self, objective: &str, player: &str) -> Option<i32>;
137
138 /// Set the score; returns `false` if the objective doesn't exist.
139 fn scoreboard_set(&self, objective: &str, player: &str, score: i32) -> bool;
140
141 /// Add `delta` to the score (negative = subtract). Returns the new score,
142 /// or `None` if the objective doesn't exist.
143 fn scoreboard_add(&self, objective: &str, player: &str, delta: i32) -> Option<i32>;
144
145 // ── sound ───────────────────────────────────────────────────────────────
146
147 /// Play a sound at `(x, y, z)` in `dimension`. `sound_id` is a registry id
148 /// (e.g. `"minecraft:entity.player.levelup"`). All players within range hear
149 /// it. Returns `false` if the dimension is unknown.
150 fn play_sound(
151 &self,
152 dimension: &str,
153 x: f64,
154 y: f64,
155 z: f64,
156 sound_id: &str,
157 volume: f32,
158 pitch: f32,
159 ) -> bool;
160
161 /// Play a sound at the named player's current position. All players nearby
162 /// (including the target) hear it. Returns `false` if the player is offline.
163 fn play_sound_to_player(
164 &self,
165 player: &str,
166 sound_id: &str,
167 volume: f32,
168 pitch: f32,
169 ) -> bool;
170
171 // ── title / actionbar ───────────────────────────────────────────────────
172
173 /// Send a title+subtitle screen to a player. Pass empty strings to omit
174 /// either line. Timings are in ticks (20 ticks = 1 second).
175 fn send_title(
176 &self,
177 player: &str,
178 title: &str,
179 subtitle: &str,
180 fadein: i32,
181 stay: i32,
182 fadeout: i32,
183 ) -> bool;
184
185 /// Send a short message to the action-bar (the line just above the hotbar).
186 fn send_actionbar(&self, player: &str, message: &str) -> bool;
187
188 // ── player management ───────────────────────────────────────────────────
189
190 /// Disconnect `player` with the given `reason` message.
191 fn kick_player(&self, player: &str, reason: &str) -> bool;
192
193 /// Change a player's game mode. `gamemode` is one of `"survival"`,
194 /// `"creative"`, `"adventure"`, `"spectator"` (or the abbreviations
195 /// `"s"`, `"c"`, `"a"`, `"sp"`). Returns `false` if the player is offline
196 /// or `gamemode` is unrecognised.
197 fn set_gamemode(&self, player: &str, gamemode: &str) -> bool;
198
199 // ── boss bar ────────────────────────────────────────────────────────────
200
201 /// Create a new boss bar identified by `id` (a namespaced id such as
202 /// `"mymod:progress"`). `color`: `"pink"` / `"blue"` / `"red"` / `"green"` /
203 /// `"yellow"` / `"purple"` / `"white"`. `style`: `"progress"` /
204 /// `"notched_6"` / `"notched_10"` / `"notched_12"` / `"notched_20"`.
205 /// Returns `false` if a bar with that id already exists.
206 fn bossbar_create(&self, id: &str, title: &str, color: &str, style: &str) -> bool;
207
208 /// Remove a boss bar (also removes it from all players). Returns `false` if
209 /// the bar doesn't exist.
210 fn bossbar_remove(&self, id: &str) -> bool;
211
212 /// Update the displayed title of a boss bar.
213 fn bossbar_set_title(&self, id: &str, title: &str) -> bool;
214
215 /// Set the fill level of a boss bar (0.0 = empty, 1.0 = full).
216 fn bossbar_set_progress(&self, id: &str, progress: f32) -> bool;
217
218 /// Change the color of a boss bar (same color names as [`bossbar_create`]).
219 fn bossbar_set_color(&self, id: &str, color: &str) -> bool;
220
221 /// Add an online player to the boss bar's audience.
222 fn bossbar_add_player(&self, id: &str, player: &str) -> bool;
223
224 /// Remove a player from the boss bar's audience.
225 fn bossbar_remove_player(&self, id: &str, player: &str) -> bool;
226
227 /// Show or hide a boss bar for all its current audience members.
228 fn bossbar_set_visible(&self, id: &str, visible: bool) -> bool;
229
230 // ── misc ────────────────────────────────────────────────────────────────
231
232 /// Absolute path of the game / server root directory.
233 fn game_dir(&self) -> String;
234
235 /// Names of all currently connected players.
236 fn online_players(&self) -> Vec<String>;
237
238 // ── block entity ─────────────────────────────────────────────────────────
239
240 /// SNBT string of the block entity at `pos` (e.g. chest contents, furnace
241 /// state, sign text). Returns `None` if there is no block entity there.
242 fn get_block_nbt(&self, dimension: &str, pos: BlockPos) -> Option<String>;
243
244 /// Write `snbt` data into the block entity at `pos` and mark it dirty.
245 /// Returns `false` if there is no block entity at that position.
246 fn set_block_nbt(&self, dimension: &str, pos: BlockPos, snbt: &str) -> bool;
247
248 // ── inventory ────────────────────────────────────────────────────────────
249
250 /// All occupied inventory slots of an online player.
251 /// Returns one entry per occupied slot: `(slot_index, item_id, count)`.
252 fn player_inventory(&self, player: &str) -> Vec<(u32, String, u32)>;
253
254 /// Set (or clear when `count == 0`) one inventory slot of an online player.
255 fn player_set_slot(&self, player: &str, slot: u32, item_id: &str, count: u32) -> bool;
256
257 // ── cross-dimension teleport ─────────────────────────────────────────────
258
259 /// Teleport a player to `(x, y, z)` in a different (or same) dimension.
260 fn teleport_to_dim(&self, player: &str, dimension: &str, x: f64, y: f64, z: f64) -> bool;
261
262 /// Teleport any entity (by UUID) to `(x, y, z)` in `dimension`.
263 fn entity_teleport_to_dim(&self, uuid: &str, dimension: &str, x: f64, y: f64, z: f64) -> bool;
264
265 // ── entity query ─────────────────────────────────────────────────────────
266
267 /// Number of loaded entities of `entity_type` (e.g. `"minecraft:zombie"`)
268 /// in `dimension`. Returns `-1` if the dimension or entity type is unknown.
269 fn world_entity_count(&self, dimension: &str, entity_type: &str) -> i32;
270
271 // ── entity NBT ───────────────────────────────────────────────────────────
272
273 /// SNBT string of the entity's persistent NBT, or `None` if not found.
274 fn entity_get_nbt(&self, uuid: &str) -> Option<String>;
275
276 /// Merge SNBT data into the entity's persistent NBT. Returns `false` if not found.
277 fn entity_set_nbt(&self, uuid: &str, snbt: &str) -> bool;
278
279 // ── particles ────────────────────────────────────────────────────────────
280
281 /// Spawn `count` particles at `(x, y, z)` in `dimension`.
282 /// `dx/dy/dz` control the spatial spread; `speed` controls particle velocity.
283 fn spawn_particles(
284 &self,
285 dimension: &str,
286 x: f64, y: f64, z: f64,
287 particle_type: &str,
288 count: i32,
289 dx: f64, dy: f64, dz: f64,
290 speed: f64,
291 ) -> bool;
292
293 // ── attributes ───────────────────────────────────────────────────────────
294
295 /// Get the base value of an attribute on a living entity.
296 /// `attribute_id` e.g. `"minecraft:generic.max_health"`.
297 /// Returns `None` if the entity or attribute is not found.
298 fn entity_attribute_get(&self, uuid: &str, attribute_id: &str) -> Option<f64>;
299
300 /// Set the base value of an attribute. Returns false if not found.
301 fn entity_attribute_set(&self, uuid: &str, attribute_id: &str, value: f64) -> bool;
302
303 // ── held item NBT (ABI minor 11) ─────────────────────────────────────────
304
305 /// SNBT string of the item currently held in the player's main hand.
306 /// Returns `None` if the player is offline or holding air.
307 fn get_held_item_nbt(&self, player: &str) -> Option<String>;
308
309 /// Merge `snbt` data into the NBT of the item in the player's main hand.
310 /// Returns `false` if the player is offline or holding air.
311 fn set_held_item_nbt(&self, player: &str, snbt: &str) -> bool;
312
313 // ── item stack query (ABI minor 12) ──────────────────────────────────────
314
315 /// SNBT of the item in the player's off hand.
316 /// Returns `None` if offline or holding air.
317 fn get_offhand_item_nbt(&self, player: &str) -> Option<String>;
318
319 /// Merge `snbt` into the NBT of the player's off-hand item.
320 /// Returns `false` if offline or holding air.
321 fn set_offhand_item_nbt(&self, player: &str, snbt: &str) -> bool;
322
323 /// Full item stack at inventory `slot`: `(item_id, count, nbt_snbt)`.
324 /// `nbt_snbt` is `"{}"` when the item has no NBT.
325 /// Returns `None` if the player is offline or the slot is empty.
326 fn get_slot_item(&self, player: &str, slot: u32) -> Option<(String, u32, String)>;
327
328 /// Replace inventory `slot`. Pass `count == 0` to clear the slot.
329 /// `snbt` is merged into the new item's NBT (pass `""` for no NBT).
330 fn set_slot_item(&self, player: &str, slot: u32, item_id: &str, count: u32, snbt: &str) -> bool;
331}