|
| 1 | +# Leave World Message Patch Documentation |
| 2 | + |
| 3 | +## The Problem |
| 4 | + |
| 5 | +By default, the Hytale server prints a message when a player leaves a world: |
| 6 | + |
| 7 | +``` |
| 8 | +{username} has left {world} |
| 9 | +``` |
| 10 | + |
| 11 | +This message originates from the server's language files located at: |
| 12 | + |
| 13 | +``` |
| 14 | +Assets/Server/Languages/{language}/server.lang |
| 15 | +``` |
| 16 | + |
| 17 | +Specifically, this line: |
| 18 | + |
| 19 | +```properties |
| 20 | +general.playerLeftWorld = {username} has left {world} |
| 21 | +``` |
| 22 | + |
| 23 | +## Source Code Analysis |
| 24 | + |
| 25 | +The broadcast is triggered in the file: |
| 26 | + |
| 27 | +``` |
| 28 | +com/hypixel/hytale/server/core/modules/entity/player/PlayerSystems.java |
| 29 | +``` |
| 30 | + |
| 31 | +Inside the `PlayerRemovedSystem` class, the `onEntityRemoved` method executes when a player leaves a world. The problematic broadcast happens on the last line: |
| 32 | + |
| 33 | +```java |
| 34 | +@Override |
| 35 | +public void onEntityRemoved(@Nonnull Holder<EntityStore> holder, @Nonnull RemoveReason reason, @Nonnull Store<EntityStore> store) { |
| 36 | + World world = store.getExternalData().getWorld(); |
| 37 | + PlayerRef playerRefComponent = holder.getComponent(PlayerRef.getComponentType()); |
| 38 | + // ... (component initialization code) |
| 39 | + |
| 40 | + LOGGER.at(Level.INFO).log("Removing player '%s%s' from world '%s' (%s)", |
| 41 | + playerRefComponent.getUsername(), |
| 42 | + displayName != null ? " (" + displayName.getAnsiMessage() + ")" : "", |
| 43 | + world.getName(), |
| 44 | + playerRefComponent.getUuid()); |
| 45 | + |
| 46 | + // ... (player data saving code) |
| 47 | + |
| 48 | + // ⚠️ THIS IS THE LINE WE WANT TO DISABLE: |
| 49 | + PlayerUtil.broadcastMessageToPlayers( |
| 50 | + playerRefComponent.getUuid(), |
| 51 | + Message.translation("server.general.playerLeftWorld") |
| 52 | + .param("username", playerRefComponent.getUsername()) |
| 53 | + .param("world", worldConfig.getDisplayName() != null |
| 54 | + ? worldConfig.getDisplayName() |
| 55 | + : WorldConfig.formatDisplayName(world.getName())), |
| 56 | + store |
| 57 | + ); |
| 58 | +} |
| 59 | +``` |
| 60 | + |
| 61 | +## Why Can't We Just Disable It Like Join Messages? |
| 62 | + |
| 63 | +Unlike leave messages, Hytale **does provide a native way** to disable join messages through the plugin API: |
| 64 | + |
| 65 | +```java |
| 66 | +private void onPlayerJoinWorld(AddPlayerToWorldEvent event) { |
| 67 | + event.setBroadcastJoinMessage(false); |
| 68 | +} |
| 69 | +``` |
| 70 | + |
| 71 | +Unfortunately, there is **no equivalent method** for leave messages. The events don't expose a method to suppress the default broadcast. |
| 72 | + |
| 73 | +## The Solution: Early Plugins |
| 74 | + |
| 75 | +Until Hytale implements a native way to disable leave messages, the only solution is to use Hytale's **earlyplugins** system. |
| 76 | + |
| 77 | +### What are Early Plugins? |
| 78 | + |
| 79 | +Early plugins are loaded **before the server starts**, allowing them to modify server behavior at the bytecode level using class transformers. This is an **official feature** provided by Hytale for advanced server modifications. |
| 80 | + |
| 81 | +### How Our Patch Works |
| 82 | + |
| 83 | +Our transformer surgically removes the `PlayerUtil.broadcastMessageToPlayers` call from the `onEntityRemoved` method without affecting any other functionality: |
| 84 | + |
| 85 | +```java |
| 86 | +// Original bytecode: |
| 87 | +aload_1 // Load UUID onto stack |
| 88 | +aload_2 // Load Message onto stack |
| 89 | +aload_3 // Load Store onto stack |
| 90 | +invokestatic // Call PlayerUtil.broadcastMessageToPlayers(...) |
| 91 | + |
| 92 | +// After transformation: |
| 93 | +pop // Remove Store from stack |
| 94 | +pop // Remove Message from stack |
| 95 | +pop // Remove UUID from stack |
| 96 | +// (method call removed) |
| 97 | +``` |
| 98 | + |
| 99 | +**Important:** The transformer only modifies this specific broadcast call. All other server functionality, including the logger message on line 218, remains completely untouched. |
| 100 | + |
| 101 | +## Installation |
| 102 | + |
| 103 | +### Option 1: Automatic Installation (Recommended) |
| 104 | + |
| 105 | +1. Install the WelcomeTale plugin on your server |
| 106 | +2. Run the command in-game: |
| 107 | + ``` |
| 108 | + /welcometalepatch |
| 109 | + ``` |
| 110 | +3. Read the warning message carefully |
| 111 | +4. Run the command again within 10 minutes to confirm |
| 112 | +5. The patch will be automatically installed to `earlyplugins/LeaveMessageTransformer.jar` |
| 113 | +6. Restart your server |
| 114 | + |
| 115 | +### Option 2: Manual Installation |
| 116 | + |
| 117 | +1. Extract the `LeaveMessageTransformer.jar` from inside the WelcomeTale plugin |
| 118 | +2. Create an `earlyplugins/` directory in your server root (if it doesn't exist) |
| 119 | +3. Copy `LeaveMessageTransformer.jar` to `earlyplugins/` |
| 120 | +4. Restart your server |
| 121 | + |
| 122 | +## What to Expect After Installation |
| 123 | + |
| 124 | +### On Server Startup |
| 125 | + |
| 126 | +When you restart your server, you'll see this message in the terminal: |
| 127 | + |
| 128 | +``` |
| 129 | +[EarlyPlugin] Found: LeaveMessageTransformer.jar |
| 130 | +[EarlyPlugin] Loading transformer: com.rmaafs.welcometale.transformers.LeaveMessageTransformer (priority=1000) |
| 131 | +=============================================================================================== |
| 132 | + Loaded 1 class transformer(s)!! |
| 133 | +=============================================================================================== |
| 134 | + This is unsupported and may cause stability issues. |
| 135 | + Use at your own risk!! |
| 136 | +=============================================================================================== |
| 137 | +Press ENTER to accept and continue... |
| 138 | +``` |
| 139 | + |
| 140 | +This is Hytale's standard warning for early plugins. If you agree to use the patch, **press ENTER** to start the server normally. |
| 141 | + |
| 142 | +### Suppressing the Confirmation Prompt |
| 143 | + |
| 144 | +If you want to avoid pressing ENTER every time you start the server, add the `--accept-early-plugins` flag: |
| 145 | + |
| 146 | +```bash |
| 147 | +java -jar HytaleServer.jar --accept-early-plugins --assets Assets.zip |
| 148 | +``` |
| 149 | + |
| 150 | +### During Runtime |
| 151 | + |
| 152 | +Once the server starts, you'll see this confirmation message: |
| 153 | + |
| 154 | +``` |
| 155 | +[WelcomeTale] Transforming com/hypixel/hytale/server/core/modules/entity/player/PlayerSystems$PlayerRemovedSystem |
| 156 | +[WelcomeTale] Successfully transformed PlayerRemovedSystem |
| 157 | +``` |
| 158 | + |
| 159 | +From this point forward, the default leave messages will no longer appear. Players leaving worlds will only trigger your custom leave messages configured in WelcomeTale. |
| 160 | + |
| 161 | +## Safety and Transparency |
| 162 | + |
| 163 | +### What This Patch Does |
| 164 | + |
| 165 | +✅ **Only disables** the default "player left world" broadcast |
| 166 | +✅ **Does not affect** any other server functionality |
| 167 | +✅ **Does not modify** player data, world state, or logging |
| 168 | +✅ **Uses official** Hytale early plugin system |
| 169 | +✅ **Fully documented** and open source |
| 170 | + |
| 171 | +### What This Patch Does NOT Do |
| 172 | + |
| 173 | +❌ Does not modify player data or world files |
| 174 | +❌ Does not affect join messages or other broadcasts |
| 175 | +❌ Does not introduce new features or commands |
| 176 | +❌ Does not collect any data |
| 177 | +❌ Does not communicate with external servers |
| 178 | + |
| 179 | +### Technical Guarantees |
| 180 | + |
| 181 | +The transformer is **surgically precise**: |
| 182 | + |
| 183 | +- **Target class:** `PlayerSystems$PlayerRemovedSystem` (no other classes) |
| 184 | +- **Target method:** `onEntityRemoved` (no other methods) |
| 185 | +- **Target call:** `PlayerUtil.broadcastMessageToPlayers` (no other calls) |
| 186 | + |
| 187 | +The complete source code with detailed documentation is available in the [LeaveMessageTransformer.java](src/main/java/com/rmaafs/welcometale/transformers/LeaveMessageTransformer.java) file. |
| 188 | + |
| 189 | +## Uninstalling the Patch |
| 190 | + |
| 191 | +To remove the patch: |
| 192 | + |
| 193 | +1. Stop your server |
| 194 | +2. Delete `earlyplugins/LeaveMessageTransformer.jar` |
| 195 | +3. Start your server normally |
| 196 | + |
| 197 | +The default leave messages will be restored immediately. |
| 198 | + |
| 199 | +## Disclaimer |
| 200 | + |
| 201 | +This patch uses Hytale's official early plugin system, which is provided for advanced server modifications. However, class transformation is inherently sensitive. While this patch is designed to be safe and minimal: |
| 202 | + |
| 203 | +- ⚠️ Use at your own risk |
| 204 | +- ⚠️ Test in a development environment first |
| 205 | +- ⚠️ Keep backups of your server |
| 206 | +- ⚠️ This is a temporary solution until Hytale adds native support |
| 207 | + |
| 208 | +**Note:** This patch will become obsolete if Hytale adds a native method to disable leave messages (similar to `setBroadcastJoinMessage`). We will update WelcomeTale accordingly when that happens. |
0 commit comments