Server screen manager
ServerScreenManager is the server-side entry point for in-world interactive screens. You hand it a placement (centre, normal, width, height) and a ScreenContent tree, and it pushes the right network payload to either one player or every player in a dimension. Screen ids are stable per purpose — calling showWithId with the same id replaces the previous screen rather than stacking.
When to use it
Section titled “When to use it”- You want a clickable settings panel mounted on a wall.
- You’re showing a per-player results screen at the end of a round.
- You’re putting a world-wide informational sign in front of a hub pad.
package me.zlex.conduit.screen;
public final class ServerScreenManager {
// Per-player, auto-assigned id (starts at 1000): public static int show(ServerPlayer player, Vec3 center, Vec3 normal, float width, float height, ScreenContent content); public static int show(ServerPlayer player, ScreenPlacement place, float width, float height, ScreenContent content);
// Per-player, stable id (replaces any prior screen with the same id): public static void showWithId(ServerPlayer player, int id, Vec3 center, Vec3 normal, float width, float height, ScreenContent content);
// World-wide — sent to every player in the dimension + re-sent on join: public static int worldShow(MinecraftServer server, ResourceKey<Level> dim, Vec3 center, Vec3 normal, float width, float height, ScreenContent content); public static void worldHide(MinecraftServer server, int id);
public static void hide(ServerPlayer player, int id);
// Click + text-input routing — one handler per screen id: public static void onButton(int screenId, BiConsumer<ServerPlayer, String> handler); public static void onTextInput(int screenId, TextInputHandler handler);
public static void init(); // call once from your ModInitializer}Example
Section titled “Example”import me.zlex.conduit.screen.ScreenContent;import me.zlex.conduit.screen.ServerScreenManager;import me.zlex.conduit.screen.placement.Placements;import me.zlex.conduit.lobby.screen.builtin.LobbyScreen;import net.minecraft.server.level.ServerPlayer;
public final class MyLobbyUi {
private static final int SCREEN_ID = 7100; // pick outside the 1000+ auto range
public static void showLobbyTo(ServerPlayer host, List<String> roster) { ScreenContent content = LobbyScreen.build(MyMod.GAME, roster, List.of()); var place = Placements.inFrontOf(host, 2.5f); ServerScreenManager.showWithId(host, SCREEN_ID, place.center(), place.normal(), 4.5f, 4.0f, content);
ServerScreenManager.onButton(SCREEN_ID, (clicker, buttonId) -> { if (LobbyScreen.BTN_START.equals(buttonId)) MyRound.start(clicker); if (LobbyScreen.BTN_LEAVE.equals(buttonId)) MyLobby.leave(clicker); }); }}- Vanilla clients silently ignore screen payloads. Pair every panel with a chat-text fallback if you care about non-engine clients.
- Auto-assigned ids start at 1000. If you want a stable id (so the same panel can be re-pushed without stacking), pick one outside
1000..— engine code does this with constants like7100. - World-wide screens persist in a server-side registry until you call
worldHide— they survive/reloadand are re-pushed to joining players.