diff --git a/src/de/steamwar/bungeecore/listeners/PluginMessage.java b/src/de/steamwar/bungeecore/listeners/PluginMessage.java index 34a1c2fb..e04723d4 100644 --- a/src/de/steamwar/bungeecore/listeners/PluginMessage.java +++ b/src/de/steamwar/bungeecore/listeners/PluginMessage.java @@ -41,6 +41,9 @@ import net.md_5.bungee.connection.InitialHandler; import net.md_5.bungee.event.EventHandler; import net.md_5.bungee.protocol.DefinedPacket; +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.IOException; import java.util.*; import java.util.function.Consumer; import java.util.logging.Level; @@ -57,6 +60,32 @@ public class PluginMessage extends BasicListener { player.sendData(channel, data); } + public static byte[] genBufPacket(Consumer generator) { + ByteBuf buf = Unpooled.buffer(); + generator.accept(buf); + + byte[] packet = new byte[buf.readableBytes()]; + buf.readBytes(packet); + return packet; + } + + public static byte[] genStreamPacket(StreamConsumer generator) { + ByteArrayOutputStream stream = new ByteArrayOutputStream(); + DataOutputStream out = new DataOutputStream(stream); + + try { + generator.accept(out); + } catch (IOException e) { + throw new SecurityException("Could not create PluginMessage packet", e); + } + + return stream.toByteArray(); + } + + public interface StreamConsumer { + void accept(DataOutputStream out) throws IOException; + } + private static final Parser UNKNOWN = event -> BungeeCore.get().getLogger().log(Level.WARNING, () -> "Undefined PluginMessage on channel " + event.getTag() + " from " + event.getSender() + " received.\n" + new String(event.getData()) + "\n" + Arrays.toString(event.getData())); private static final Parser PASS_THROUGH = event -> event.setCancelled(false); private static final Parser DROP = event -> {}; @@ -68,12 +97,11 @@ public class PluginMessage extends BasicListener { private final Map handlers = new HashMap<>(); public PluginMessage() { + //TODO interface generalisation LabyMod labyMod = new LabyMod(); - FML fml = new FML(); - FabricModSender fabricModSender = new FabricModSender(); WorldDownloader wdl = new WorldDownloader(); - knownBrands.addAll(Arrays.asList("vanilla", "fabric", "quilt", "forge", "optifine", "Geyser", "labymod")); + knownBrands.addAll(Arrays.asList("vanilla", "fabric", "quilt", "forge", "optifine", "Geyser", "labymod", "Feather Fabric")); for(String channel : Arrays.asList( "fabric:container/open", "fabric:registry/sync/direct", "fabric:registry/sync", @@ -99,6 +127,14 @@ public class PluginMessage extends BasicListener { "libgui:screen_message_s2c", //https://github.com/CottonMC/LibGui "minecraft:intave", //https://intave.ac seems to be a client side integration of intave with labymod 4 "midnightcontrols:feature", "midnightcontrols:controls_mode", //https://modrinth.com/mod/midnightcontrols + "controlify:vibrate_from_origin", "controlify:vibration", "controlify:vibrate_from_entity", + "carpet:structures", //https://modrinth.com/mod/carpet + "appleskin:exhaustion_sync", "appleskin:saturation_sync", //https://modrinth.com/mod/appleskin + "puzzleslib:1/1", //https://modrinth.com/mod/puzzles-lib + "pickupnotifier:1/1", //https://modrinth.com/mod/pick-up-notifier + "plasmo:voice/v2/installed", "plasmo:voice/v2", //https://modrinth.com/plugin/plasmo-voice + "whereisit:s2c_founditem", //https://modrinth.com/mod/where-is-it (needs server side component to work) + "inventorysorter:sync_blacklist_packet", //https://github.com/cpw/inventorysorter (needs server side component to work) //https://github.com/bernie-g/geckolib "geckolib:block_entity_anim_trigger_sync", "geckolib:entity_anim_trigger_sync", @@ -107,15 +143,18 @@ public class PluginMessage extends BasicListener { //https://github.com/Noxcrew/noxesium "noxesium-v1:reset", "noxesium-v1:change_server_rules", "noxesium-v1:server_info", - "noxesium-v1:mcc_server", "noxesium-v1:mcc_game_state", "noxesium-v1:reset_server_rules" + "noxesium-v1:mcc_server", "noxesium-v1:mcc_game_state", "noxesium-v1:reset_server_rules", + "noxesium-v1:stop_sound", "noxesium-v1:start_sound", "noxesium-v1:modify_sound" )) channelRegisterHandlers.put(channel, player -> {}); channelRegisterHandlers.put(ApolloManager.PLUGIN_MESSAGE_CHANNEL, lunar::sendRestrictions); + channelRegisterHandlers.put(Feather.CHANNEL, new Feather()::sendRestrictions); channelRegisterHandlers.put("xaerominimap:main", player -> player.sendMessage(ChatMessageType.SYSTEM, new TextComponent("§n§o§m§i§n§i§m§a§p"))); //https://www.curseforge.com/minecraft/mc-mods/xaeros-minimap channelRegisterHandlers.put("litemoretica:init_easy_place", player -> player.disconnect(ChatSender.of(player).parseToComponent(false, new Message("MOD_YELLOW_SING", "litematica")))); //https://github.com/Earthcomputer/litemoretica/tree/master channelRegisterHandlers.put("voxelmap:settings", player -> player.disconnect(ChatSender.of(player).parseToComponent(false, new Message("MOD_YELLOW_SING", "voxelmap")))); //https://modrinth.com/mod/voxelmap-updated undocumented channelRegisterHandlers.put("worldinfo:world_id", player -> player.disconnect(ChatSender.of(player).parseToComponent(false, new Message("MOD_YELLOW_SING", "minimap")))); // JourneyMap and VoxelMap + channelRegisterHandlers.put(Controlify.CHANNEL, new Controlify()::onRegister); registerBiDirPassthrough("worldedit:cui"); @@ -133,10 +172,21 @@ public class PluginMessage extends BasicListener { "axiom:manipulate_entity", "axiom:delete_entity", "axiom:marker_nbt_request", "axiom:set_buffer" ); + for(String channel : Arrays.asList( + "UNREGISTER", "minecraft:unregister", // used by carpet and servux + "WDL|REQUEST", "wdl:request", + "minecraft:intave", //undocumented, byte stringlength, clientconfig, byte length, json {"legacySneakHeight":false,"legacyOldRange":false,"legacyOldSlowdown":false} + "waila:entity", "waila:block", + "lambdacontrols:hello", + "midnightcontrols:controls_mode", + "inventorysorter:sync_settings_packet", + "voicechat:request_secret", "voicechat:update_state", //https://modrinth.com/plugin/simple-voice-chat + "shulkerboxtooltip:c2s_handshake" + )) + register(channel, false, directional(UNKNOWN, DROP)); + register("REGISTER", false, directional(this::serverRegistersChannel, this::clientRegistersChannel)); register("minecraft:register", false, directional(this::serverRegistersChannel, this::clientRegistersChannel)); - register("UNREGISTER", false, DROP); - register("minecraft:unregister", false, DROP); // used by carpet and servux register("BungeeCord", false, onlySWSource(PASS_THROUGH)); register("bungeecord:main", false, onlySWSource(PASS_THROUGH)); @@ -146,28 +196,20 @@ public class PluginMessage extends BasicListener { //Needs to be registered cause paper refuses to send PluginMessages on unregistered channels... register("sw:bridge", true, directional(onlySWSource(async(event -> NetworkPacket.handle(new ServerMetaInfo(((Server) event.getSender()).getInfo()), event.getData()))), UNKNOWN)); register("sw:hotkeys", false, directional(UNKNOWN, PASS_THROUGH)); - register("fabricmodsender:mods", true, directional(UNKNOWN, async(fabricModSender::handlePluginMessage))); + register("fabricmodsender:mods", true, directional(UNKNOWN, async(new FabricModSender()::handlePluginMessage))); - register("WDL|REQUEST", false, DROP); - register("wdl:request", false, DROP); register("WDL|INIT", true, directional(UNKNOWN, wdl::handlePluginMessage)); register("wdl:init", true, directional(UNKNOWN, wdl::handlePluginMessage)); - register("minecraft:intave", false, directional(UNKNOWN, DROP)); //undocumented, byte stringlength, clientconfig, byte length, json {"legacySneakHeight":false,"legacyOldRange":false,"legacyOldSlowdown":false} - register("waila:block", false, directional(UNKNOWN, DROP)); - register("waila:entity", false, directional(UNKNOWN, DROP)); - register("lambdacontrols:hello", false, directional(UNKNOWN, DROP)); - register("midnightcontrols:controls_mode", false, directional(UNKNOWN, DROP)); register(ApolloManager.PLUGIN_MESSAGE_CHANNEL, true, async(lunar::handlePluginMessage)); register("LMC", true, directional(UNKNOWN, async(labyMod::handlePluginMessage))); register("labymod3:main", true, directional(UNKNOWN, async(labyMod::handlePluginMessage))); register("labymod:neo", false, directional(UNKNOWN, DROP)); //undocumented, JSON format "0" byte, packetlängen byte, {"version":"4.1.25"} - register(FML.CHANNEL, true, directional(UNKNOWN, async(fml::handlePluginMessage))); + register(FML.CHANNEL, true, directional(UNKNOWN, async(new FML()::handlePluginMessage))); //vanilla does not register any channels (sends only one minecraft:brand vanilla, nothing else (potential spoofed client detection)) //Forge interestingly registers all channels the server registers //meteor https://github.com/MeteorDevelopment/meteor-client/blob/master/src/main/java/meteordevelopment/meteorclient/systems/modules/misc/ServerSpoof.java https://github.com/MeteorDevelopment/meteor-client/blob/master/src/main/java/meteordevelopment/meteorclient/systems/modules/misc/DiscordPresence.java - //feather:client https://github.com/Koupah/Feather-Client-API/blob/main/src/club/koupah/feather/handler/FeatherHandler.java //litematica/malilib https://github.com/maruohon/litematica/issues/75 https://github.com/maruohon/malilib/blob/liteloader_1.12.2/src/main/java/malilib/network/message/ConfigLockPacketHandler.java#L65 // Hackclientlike modsuppressor for labymod: https://github.com/Neocraftr/LabyMod-NeoEssentials (Potentially recognizable from NO Addons/NO Mods?) https://github.com/Neocraftr/LabyMod-NeoEssentials/blob/master/src/main/java/de/neocraftr/neoessentials/utils/BytecodeMethods.java } diff --git a/src/de/steamwar/bungeecore/mods/Controlify.java b/src/de/steamwar/bungeecore/mods/Controlify.java new file mode 100644 index 00000000..2c240172 --- /dev/null +++ b/src/de/steamwar/bungeecore/mods/Controlify.java @@ -0,0 +1,52 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2024 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bungeecore.mods; + +import de.steamwar.bungeecore.listeners.PluginMessage; +import net.md_5.bungee.api.connection.ProxiedPlayer; +import net.md_5.bungee.protocol.DefinedPacket; + +public class Controlify { + //https://modrinth.com/mod/controlify + //https://github.com/isXander/Controlify/blob/1.20.x/dev/src/main/java/dev/isxander/controlify/server/ServerPolicyPacket.java + //https://github.com/isXander/Controlify/blob/1.20.x/dev/src/main/java/dev/isxander/controlify/server/ServerPolicies.java + + public static final String CHANNEL = "controlify:server_policy"; + + private final byte[][] packets; + public Controlify() { + packets = new byte[][] { + restrict("reachAround"), + restrict("disableFlyDrifting") + }; + } + + private byte[] restrict(String name) { + return PluginMessage.genBufPacket(buf -> { + DefinedPacket.writeString(name, buf); + buf.writeBoolean(false); + }); + } + + public void onRegister(ProxiedPlayer player) { + for(byte[] packet : packets) + player.sendData(CHANNEL, packet); + } +} diff --git a/src/de/steamwar/bungeecore/mods/FML2.java b/src/de/steamwar/bungeecore/mods/FML2.java index f815869d..68699ad4 100644 --- a/src/de/steamwar/bungeecore/mods/FML2.java +++ b/src/de/steamwar/bungeecore/mods/FML2.java @@ -22,6 +22,7 @@ package de.steamwar.bungeecore.mods; import de.steamwar.bungeecore.BungeeCore; import de.steamwar.bungeecore.listeners.BasicListener; import de.steamwar.bungeecore.listeners.IPSanitizer; +import de.steamwar.bungeecore.listeners.PluginMessage; import de.steamwar.sql.Mod; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; @@ -55,19 +56,17 @@ public class FML2 extends BasicListener { public FML2() { fml2ModListPacket = generateModListPacket(false); fml3ModListPacket = generateModListPacket(true); + forgeModListPacket = PluginMessage.genBufPacket(buf -> { + buf.writeByte(0); // Login wrapper packet + DefinedPacket.writeString("forge:handshake", buf); - ByteBuf packet = Unpooled.buffer(); - packet.writeByte(1); // Mod list packet - DefinedPacket.writeVarInt(0, packet); // Mod amount + ByteBuf packet = Unpooled.buffer(); + packet.writeByte(1); // Mod list packet + DefinedPacket.writeVarInt(0, packet); // Mod amount - ByteBuf wrapper = Unpooled.buffer(); - wrapper.writeByte(0); // Login wrapper packet - DefinedPacket.writeString("forge:handshake", wrapper); - DefinedPacket.writeVarInt(packet.readableBytes(), wrapper); - wrapper.writeBytes(packet); - - forgeModListPacket = new byte[wrapper.readableBytes()]; - wrapper.readBytes(forgeModListPacket); + DefinedPacket.writeVarInt(packet.readableBytes(), buf); + buf.writeBytes(packet); + }); } @EventHandler @@ -90,30 +89,28 @@ public class FML2 extends BasicListener { } private byte[] generateModListPacket(boolean fml3) { - ByteBuf packet = Unpooled.buffer(); - packet.writeByte(1); // Mod list packet - DefinedPacket.writeVarInt(0, packet); // Mod amount + return PluginMessage.genBufPacket(buf -> { + DefinedPacket.writeString("fml:handshake", buf); - if(fml3) { - DefinedPacket.writeVarInt(1, packet); // Channel amount - DefinedPacket.writeString("forge:tier_sorting", packet); - DefinedPacket.writeString("1.0", packet); - } else { - DefinedPacket.writeVarInt(0, packet); // Channel amount - } + ByteBuf packet = Unpooled.buffer(); + packet.writeByte(1); // Mod list packet + DefinedPacket.writeVarInt(0, packet); // Mod amount - DefinedPacket.writeVarInt(0, packet); // Registries amount - if(fml3) - DefinedPacket.writeVarInt(0, packet); // DataPacks amount + if(fml3) { + DefinedPacket.writeVarInt(1, packet); // Channel amount + DefinedPacket.writeString("forge:tier_sorting", packet); + DefinedPacket.writeString("1.0", packet); + } else { + DefinedPacket.writeVarInt(0, packet); // Channel amount + } - ByteBuf wrapper = Unpooled.buffer(); - DefinedPacket.writeString("fml:handshake", wrapper); - DefinedPacket.writeVarInt(packet.readableBytes(), wrapper); - wrapper.writeBytes(packet); + DefinedPacket.writeVarInt(0, packet); // Registries amount + if(fml3) + DefinedPacket.writeVarInt(0, packet); // DataPacks amount - byte[] data = new byte[wrapper.readableBytes()]; - wrapper.readBytes(data); - return data; + DefinedPacket.writeVarInt(packet.readableBytes(), buf); + buf.writeBytes(packet); + }); } private static class FML2LoginHandler extends PacketHandler { diff --git a/src/de/steamwar/bungeecore/mods/Feather.java b/src/de/steamwar/bungeecore/mods/Feather.java new file mode 100644 index 00000000..c7d2b652 --- /dev/null +++ b/src/de/steamwar/bungeecore/mods/Feather.java @@ -0,0 +1,56 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2024 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bungeecore.mods; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import net.md_5.bungee.api.connection.ProxiedPlayer; + +public class Feather { + //https://github.com/Koupah/Feather-Client-API/blob/main/src/club/koupah/feather/packets/FeatherMod.java + //https://archive.org/details/feather-server-api + public static final String CHANNEL = "feather:client"; + + private final byte[] packet; + public Feather() { + JsonArray array = new JsonArray(); + array.add("clearWater"); + array.add("coordinates"); + array.add("coordinates"); + array.add("hitbox"); + array.add("hypixel"); + array.add("reachDisplay"); + array.add("snaplook"); + array.add("toggleSprint"); + + JsonObject mods = new JsonObject(); + mods.add("mods", array); + + JsonObject obj = new JsonObject(); + obj.addProperty("packetType", "DISABLE_MODS"); + obj.add("payload", mods); + + packet = obj.toString().getBytes(); + } + + public void sendRestrictions(ProxiedPlayer player) { + player.sendData(CHANNEL, packet); + } +} diff --git a/src/de/steamwar/bungeecore/mods/Hostname.java b/src/de/steamwar/bungeecore/mods/Hostname.java index 26390942..79b8ebe2 100644 --- a/src/de/steamwar/bungeecore/mods/Hostname.java +++ b/src/de/steamwar/bungeecore/mods/Hostname.java @@ -44,6 +44,7 @@ public class Hostname extends BasicListener { knownHostnames.add("@mat:matdoes.dev "); //https://github.com/mat-1/matscan knownHostnames.add("wtf.mynx.lol"); //https://discord.com/invite/serverseeker knownHostnames.add("masscan"); + knownHostnames.add("aaa"); knownExtraData.add(""); knownExtraData.add("\0FML\0"); diff --git a/src/de/steamwar/bungeecore/mods/LabyMod.java b/src/de/steamwar/bungeecore/mods/LabyMod.java index 1114adc6..cc299954 100644 --- a/src/de/steamwar/bungeecore/mods/LabyMod.java +++ b/src/de/steamwar/bungeecore/mods/LabyMod.java @@ -23,6 +23,7 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import de.steamwar.bungeecore.BungeeCore; +import de.steamwar.bungeecore.listeners.PluginMessage; import de.steamwar.sql.Mod; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; @@ -41,18 +42,16 @@ public class LabyMod { private final byte[] gameInfoPacket; public LabyMod() { - ByteBuf buf = Unpooled.buffer(); - DefinedPacket.writeString("discord_rpc", buf); + gameInfoPacket = PluginMessage.genBufPacket(buf -> { + DefinedPacket.writeString("discord_rpc", buf); - JsonObject json = new JsonObject(); - json.addProperty("hasGame", true); - json.addProperty("game_mode", "steamwar.de"); - json.addProperty("game_startTime", 0); - json.addProperty("game_endTime", 0); - DefinedPacket.writeString(json.toString(), buf); - - gameInfoPacket = new byte[buf.readableBytes()]; - buf.readBytes(gameInfoPacket); + JsonObject json = new JsonObject(); + json.addProperty("hasGame", true); + json.addProperty("game_mode", "steamwar.de"); + json.addProperty("game_startTime", 0); + json.addProperty("game_endTime", 0); + DefinedPacket.writeString(json.toString(), buf); + }); } public void handlePluginMessage(PluginMessageEvent event) { @@ -67,9 +66,11 @@ public class LabyMod { JsonObject message = JsonParser.parseString(DefinedPacket.readString(buf)).getAsJsonObject(); List mods = new LinkedList<>(); - for(JsonElement element : message.getAsJsonArray("addons")) { - JsonObject addon = element.getAsJsonObject(); - mods.add(Mod.getOrCreate(addon.get("name").getAsString(), Mod.Platform.LABYMOD)); + if(message.has("addons")) { + for(JsonElement element : message.getAsJsonArray("addons")) { + JsonObject addon = element.getAsJsonObject(); + mods.add(Mod.getOrCreate(addon.get("name").getAsString(), Mod.Platform.LABYMOD)); + } } if(message.has("mods")) { diff --git a/src/de/steamwar/bungeecore/mods/Lunar.java b/src/de/steamwar/bungeecore/mods/Lunar.java index 904d7bf9..e2c3f9a5 100644 --- a/src/de/steamwar/bungeecore/mods/Lunar.java +++ b/src/de/steamwar/bungeecore/mods/Lunar.java @@ -50,7 +50,7 @@ public class Lunar { private final ApolloModuleManager manager = new ApolloModuleManagerImpl().addModule(ModSettingModule.class); - public Lunar() { + public Lunar() { //TODO seems defunct Options modSettings = manager.getModule(ModSettingModule.class).getOptions(); modSettings.set(ModReplaymod.ENABLED, false); // TODO check if restrictions working modSettings.set(ModFreelook.ENABLED, false); diff --git a/src/de/steamwar/bungeecore/mods/ReplayMod.java b/src/de/steamwar/bungeecore/mods/ReplayMod.java index 2130ebc0..d92a451e 100644 --- a/src/de/steamwar/bungeecore/mods/ReplayMod.java +++ b/src/de/steamwar/bungeecore/mods/ReplayMod.java @@ -31,8 +31,6 @@ import net.md_5.bungee.api.connection.ProxiedPlayer; import net.md_5.bungee.api.event.ServerSwitchEvent; import net.md_5.bungee.event.EventHandler; -import java.io.ByteArrayOutputStream; -import java.io.IOException; import java.util.Arrays; public class ReplayMod extends BasicListener { @@ -43,18 +41,14 @@ public class ReplayMod extends BasicListener { private final byte[] restrict; public ReplayMod() { - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - try { + restrict = PluginMessage.genStreamPacket(out -> { for(String restriction : Arrays.asList("no_xray", "no_noclip", "only_first_person", "only_recording_player")) { byte[] bytes = restriction.getBytes(); - stream.write(bytes.length); - stream.write(bytes); - stream.write(1); // restrict + out.writeByte(bytes.length); + out.write(bytes); + out.writeBoolean(true); // restrict } - } catch (IOException e) { - throw new SecurityException(e); - } - restrict = stream.toByteArray(); + }); } @EventHandler diff --git a/src/de/steamwar/bungeecore/mods/WorldDownloader.java b/src/de/steamwar/bungeecore/mods/WorldDownloader.java index e7f06d07..d18be4c8 100644 --- a/src/de/steamwar/bungeecore/mods/WorldDownloader.java +++ b/src/de/steamwar/bungeecore/mods/WorldDownloader.java @@ -23,10 +23,6 @@ import de.steamwar.bungeecore.listeners.PluginMessage; import net.md_5.bungee.api.connection.ProxiedPlayer; import net.md_5.bungee.api.event.PluginMessageEvent; -import java.io.ByteArrayOutputStream; -import java.io.DataOutputStream; -import java.io.IOException; - public class WorldDownloader { // https://wiki.vg/Plugin_channels/World_downloader // https://github.com/Pokechu22/WorldDownloader-Serverside-Companion @@ -35,10 +31,7 @@ public class WorldDownloader { private final byte[] controlPacket; public WorldDownloader() { - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - DataOutputStream out = new DataOutputStream(stream); - - try { + controlPacket = PluginMessage.genStreamPacket(out -> { out.writeInt(1); // basic data packet out.writeBoolean(false); // General download enabled out.writeInt(-1); // Save radius @@ -46,11 +39,7 @@ public class WorldDownloader { out.writeBoolean(false); // Entity saving enabled out.writeBoolean(false); // Tile entity saving disabled out.writeBoolean(false); // Container saving disabled - } catch (IOException e) { - throw new SecurityException("Could not create AntiWDL packet", e); - } - - controlPacket = stream.toByteArray(); + }); } public void handlePluginMessage(PluginMessageEvent event) {