diff --git a/SpigotCore_10/build.gradle b/SpigotCore_10/build.gradle index 5ce5602..bd21efa 100644 --- a/SpigotCore_10/build.gradle +++ b/SpigotCore_10/build.gradle @@ -43,8 +43,7 @@ sourceSets { } dependencies { - implementation project(":SpigotCore_9") - implementation project(":SpigotCore_API") + implementation project(":SpigotCore_Main") compileOnly 'org.projectlombok:lombok:1.18.6' testCompileOnly 'org.projectlombok:lombok:1.18.6' @@ -52,5 +51,4 @@ dependencies { testAnnotationProcessor 'org.projectlombok:lombok:1.18.6' compileOnly files("${project.rootDir}/lib/Spigot-1.10.jar") - compileOnly files("${project.rootDir}/lib/WorldEdit-1.12.jar") } diff --git a/SpigotCore_10/src/de/steamwar/chunk/Chunk_10.java b/SpigotCore_10/src/de/steamwar/core/CraftbukkitWrapper10.java similarity index 74% rename from SpigotCore_10/src/de/steamwar/chunk/Chunk_10.java rename to SpigotCore_10/src/de/steamwar/core/CraftbukkitWrapper10.java index 4f59621..8916735 100644 --- a/SpigotCore_10/src/de/steamwar/chunk/Chunk_10.java +++ b/SpigotCore_10/src/de/steamwar/core/CraftbukkitWrapper10.java @@ -1,6 +1,6 @@ -/* +/* This file is a part of the SteamWar software. - + Copyright (C) 2020 SteamWar.de-Serverteam This program is free software: you can redistribute it and/or modify @@ -17,17 +17,24 @@ along with this program. If not, see . */ -package de.steamwar.chunk; +package de.steamwar.core; +import net.minecraft.server.v1_10_R1.MinecraftServer; import net.minecraft.server.v1_10_R1.PacketPlayOutMapChunk; import org.bukkit.craftbukkit.v1_10_R1.CraftChunk; import org.bukkit.craftbukkit.v1_10_R1.entity.CraftPlayer; import org.bukkit.entity.Player; -public class Chunk_10 { - private Chunk_10(){} +public class CraftbukkitWrapper10 implements CraftbukkitWrapper.ICraftbukkitWrapper { - public static void sendChunk(Player p, int chunkX, int chunkZ){ + @Override + public void sendChunk(Player p, int chunkX, int chunkZ) { ((CraftPlayer)p).getHandle().playerConnection.sendPacket(new PacketPlayOutMapChunk(((CraftChunk)p.getWorld().getChunkAt(chunkX, chunkZ)).getHandle(), 65535)); } + + @SuppressWarnings("deprecation") + @Override + public double[] getSpigotTPS() { + return MinecraftServer.getServer().recentTps; + } } diff --git a/SpigotCore_10/src/de/steamwar/core/SpigotTPS_10.java b/SpigotCore_10/src/de/steamwar/core/SpigotTPS_10.java deleted file mode 100644 index 2cc2d26..0000000 --- a/SpigotCore_10/src/de/steamwar/core/SpigotTPS_10.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - This file is a part of the SteamWar software. - - Copyright (C) 2020 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.core; - -import net.minecraft.server.v1_10_R1.MinecraftServer; - -public class SpigotTPS_10 { - - private SpigotTPS_10(){} - - static double[] getTps(){ - return MinecraftServer.getServer().recentTps; - } - -} diff --git a/SpigotCore_12/build.gradle b/SpigotCore_12/build.gradle index a455a07..48c917b 100644 --- a/SpigotCore_12/build.gradle +++ b/SpigotCore_12/build.gradle @@ -43,8 +43,7 @@ sourceSets { } dependencies { - implementation project(":SpigotCore_8") - implementation project(":SpigotCore_API") + implementation project(":SpigotCore_Main") compileOnly 'org.projectlombok:lombok:1.18.6' testCompileOnly 'org.projectlombok:lombok:1.18.6' @@ -52,5 +51,4 @@ dependencies { testAnnotationProcessor 'org.projectlombok:lombok:1.18.6' compileOnly files("${project.rootDir}/lib/Spigot-1.12.jar") - compileOnly files("${project.rootDir}/lib/WorldEdit-1.12.jar") } diff --git a/SpigotCore_12/src/de/steamwar/chunk/Chunk_12.java b/SpigotCore_12/src/de/steamwar/core/CraftbukkitWrapper12.java similarity index 74% rename from SpigotCore_12/src/de/steamwar/chunk/Chunk_12.java rename to SpigotCore_12/src/de/steamwar/core/CraftbukkitWrapper12.java index 8944a1f..3d084b3 100644 --- a/SpigotCore_12/src/de/steamwar/chunk/Chunk_12.java +++ b/SpigotCore_12/src/de/steamwar/core/CraftbukkitWrapper12.java @@ -1,6 +1,6 @@ -/* +/* This file is a part of the SteamWar software. - + Copyright (C) 2020 SteamWar.de-Serverteam This program is free software: you can redistribute it and/or modify @@ -17,17 +17,24 @@ along with this program. If not, see . */ -package de.steamwar.chunk; +package de.steamwar.core; +import net.minecraft.server.v1_12_R1.MinecraftServer; import net.minecraft.server.v1_12_R1.PacketPlayOutMapChunk; import org.bukkit.craftbukkit.v1_12_R1.CraftChunk; import org.bukkit.craftbukkit.v1_12_R1.entity.CraftPlayer; import org.bukkit.entity.Player; -public class Chunk_12 { - private Chunk_12(){} +public class CraftbukkitWrapper12 implements CraftbukkitWrapper.ICraftbukkitWrapper { - public static void sendChunk(Player p, int chunkX, int chunkZ){ + @Override + public void sendChunk(Player p, int chunkX, int chunkZ) { ((CraftPlayer)p).getHandle().playerConnection.sendPacket(new PacketPlayOutMapChunk(((CraftChunk)p.getWorld().getChunkAt(chunkX, chunkZ)).getHandle(), 65535)); } + + @SuppressWarnings("deprecation") + @Override + public double[] getSpigotTPS() { + return MinecraftServer.getServer().recentTps; + } } diff --git a/SpigotCore_12/src/de/steamwar/core/SpigotTPS_12.java b/SpigotCore_12/src/de/steamwar/core/SpigotTPS_12.java deleted file mode 100644 index 17541c7..0000000 --- a/SpigotCore_12/src/de/steamwar/core/SpigotTPS_12.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - This file is a part of the SteamWar software. - - Copyright (C) 2020 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.core; - -import net.minecraft.server.v1_12_R1.MinecraftServer; - -public class SpigotTPS_12 { - - private SpigotTPS_12(){} - - static double[] getTps(){ - return MinecraftServer.getServer().recentTps; - } - -} diff --git a/SpigotCore_12/src/de/steamwar/message/Message_12.java b/SpigotCore_12/src/de/steamwar/core/WorldOfColorWrapper12.java similarity index 84% rename from SpigotCore_12/src/de/steamwar/message/Message_12.java rename to SpigotCore_12/src/de/steamwar/core/WorldOfColorWrapper12.java index a228394..f6c5050 100644 --- a/SpigotCore_12/src/de/steamwar/message/Message_12.java +++ b/SpigotCore_12/src/de/steamwar/core/WorldOfColorWrapper12.java @@ -17,16 +17,16 @@ along with this program. If not, see . */ -package de.steamwar.message; +package de.steamwar.core; import org.bukkit.entity.Player; import java.util.Locale; -class Message_12 { - private Message_12(){} +public class WorldOfColorWrapper12 implements WorldOfColorWrapper.IWorldOfColorWrapper { - static Locale getLocale(Player player){ + @Override + public Locale getLocale(Player player){ return Locale.forLanguageTag(player.getLocale()); } } diff --git a/SpigotCore_14/build.gradle b/SpigotCore_14/build.gradle index 522e351..5ed491e 100644 --- a/SpigotCore_14/build.gradle +++ b/SpigotCore_14/build.gradle @@ -43,7 +43,7 @@ sourceSets { } dependencies { - implementation project(":SpigotCore_API") + implementation project(":SpigotCore_Main") compileOnly 'org.projectlombok:lombok:1.18.6' testCompileOnly 'org.projectlombok:lombok:1.18.6' diff --git a/SpigotCore_14/src/de/steamwar/chunk/Chunk_14.java b/SpigotCore_14/src/de/steamwar/core/CraftbukkitWrapper14.java similarity index 74% rename from SpigotCore_14/src/de/steamwar/chunk/Chunk_14.java rename to SpigotCore_14/src/de/steamwar/core/CraftbukkitWrapper14.java index fa5a2ca..bc27af3 100644 --- a/SpigotCore_14/src/de/steamwar/chunk/Chunk_14.java +++ b/SpigotCore_14/src/de/steamwar/core/CraftbukkitWrapper14.java @@ -1,6 +1,6 @@ -/* +/* This file is a part of the SteamWar software. - + Copyright (C) 2020 SteamWar.de-Serverteam This program is free software: you can redistribute it and/or modify @@ -17,17 +17,24 @@ along with this program. If not, see . */ -package de.steamwar.chunk; +package de.steamwar.core; +import net.minecraft.server.v1_14_R1.MinecraftServer; import net.minecraft.server.v1_14_R1.PacketPlayOutMapChunk; import org.bukkit.craftbukkit.v1_14_R1.CraftChunk; import org.bukkit.craftbukkit.v1_14_R1.entity.CraftPlayer; import org.bukkit.entity.Player; -public class Chunk_14 { - private Chunk_14(){} +public class CraftbukkitWrapper14 implements CraftbukkitWrapper.ICraftbukkitWrapper { - public static void sendChunk(Player p, int chunkX, int chunkZ){ + @Override + public void sendChunk(Player p, int chunkX, int chunkZ) { ((CraftPlayer)p).getHandle().playerConnection.sendPacket(new PacketPlayOutMapChunk(((CraftChunk)p.getWorld().getChunkAt(chunkX, chunkZ)).getHandle(), 65535)); } + + @SuppressWarnings("deprecation") + @Override + public double[] getSpigotTPS() { + return MinecraftServer.getServer().recentTps; + } } diff --git a/SpigotCore_14/src/de/steamwar/sql/Schematic_14.java b/SpigotCore_14/src/de/steamwar/core/FlatteningWrapper14.java similarity index 63% rename from SpigotCore_14/src/de/steamwar/sql/Schematic_14.java rename to SpigotCore_14/src/de/steamwar/core/FlatteningWrapper14.java index 255530f..b5da68a 100644 --- a/SpigotCore_14/src/de/steamwar/sql/Schematic_14.java +++ b/SpigotCore_14/src/de/steamwar/core/FlatteningWrapper14.java @@ -1,6 +1,6 @@ -/* +/* This file is a part of the SteamWar software. - + Copyright (C) 2020 SteamWar.de-Serverteam This program is free software: you can redistribute it and/or modify @@ -17,8 +17,9 @@ along with this program. If not, see . */ -package de.steamwar.sql; +package de.steamwar.core; +import com.comphenix.tinyprotocol.Reflection; import com.google.common.collect.ImmutableList; import com.google.common.collect.Maps; import com.sk89q.jnbt.*; @@ -46,8 +47,13 @@ import com.sk89q.worldedit.world.DataFixer; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockTypes; import com.sk89q.worldedit.world.registry.LegacyMapper; +import de.steamwar.scoreboard.SWScoreboard; +import de.steamwar.sql.NoClipboardException; import org.bukkit.Bukkit; +import org.bukkit.Material; import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.SkullMeta; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -57,13 +63,272 @@ import java.util.stream.Collectors; import static com.google.common.base.Preconditions.checkNotNull; -class Schematic_14 { - private Schematic_14(){} +public class FlatteningWrapper14 implements FlatteningWrapper.IFlatteningWrapper { + + private static final Map renamedLegacy = new HashMap<>(); + + static{ + renamedLegacy.put("WOOD", Material.OAK_WOOD); + renamedLegacy.put("SAPLING", Material.OAK_SAPLING); + renamedLegacy.put("STATIONARY_WATER", Material.WATER); + renamedLegacy.put("STATIONARY_LAVA", Material.LAVA); + renamedLegacy.put("LOG", Material.OAK_LOG); + renamedLegacy.put("LEAVES", Material.OAK_LEAVES); + renamedLegacy.put("BED_BLOCK", Material.RED_BED); + renamedLegacy.put("BED", Material.RED_BED); + renamedLegacy.put("PISTON_STICKY_BASE", Material.STICKY_PISTON); + renamedLegacy.put("WEB", Material.COBWEB); + renamedLegacy.put("LONG_GRASS", Material.TALL_GRASS); + renamedLegacy.put("PISTON_BASE", Material.PISTON); + renamedLegacy.put("PISTON_EXTENSION", Material.PISTON_HEAD); + renamedLegacy.put("WOOL", Material.WHITE_WOOL); + renamedLegacy.put("PISTON_MOVING_PIECE", Material.MOVING_PISTON); + renamedLegacy.put("YELLOW_FLOWER", Material.DANDELION); + renamedLegacy.put("RED_ROSE", Material.POPPY); + renamedLegacy.put("DOUBLE_STEP", Material.SMOOTH_STONE); + renamedLegacy.put("STEP", Material.SMOOTH_STONE_SLAB); + renamedLegacy.put("MOB_SPAWNER", Material.SPAWNER); + renamedLegacy.put("WOOD_STAIRS", Material.OAK_STAIRS); + renamedLegacy.put("WORKBENCH", Material.CRAFTING_TABLE); + renamedLegacy.put("CROPS", Material.WHEAT_SEEDS); + renamedLegacy.put("SEEDS", Material.WHEAT_SEEDS); + renamedLegacy.put("SOIL", Material.FARMLAND); + renamedLegacy.put("BURNING_FURNACE", Material.FURNACE); + renamedLegacy.put("SIGN_POST", Material.OAK_SIGN); + renamedLegacy.put("SIGN", Material.OAK_SIGN); + renamedLegacy.put("WOODEN_DOOR", Material.OAK_DOOR); + renamedLegacy.put("WOOD_DOOR", Material.OAK_DOOR); + renamedLegacy.put("RAILS", Material.RAIL); + renamedLegacy.put("WALL_SIGN", Material.OAK_WALL_SIGN); + renamedLegacy.put("STONE_PLATE", Material.STONE_PRESSURE_PLATE); + renamedLegacy.put("WOOD_PLATE", Material.OAK_PRESSURE_PLATE); + renamedLegacy.put("GLOWING_REDSTONE_ORE", Material.REDSTONE_ORE); + renamedLegacy.put("REDSTONE_TORCH_OFF", Material.REDSTONE_TORCH); + renamedLegacy.put("REDSTONE_TORCH_ON", Material.REDSTONE_TORCH); + renamedLegacy.put("IRON_DOOR_BLOCK", Material.IRON_DOOR); + renamedLegacy.put("SUGAR_CANE_BLOCK", Material.SUGAR_CANE); + renamedLegacy.put("CAKE_BLOCK", Material.CAKE); + renamedLegacy.put("MELON_BLOCK", Material.MELON); + renamedLegacy.put("BEETROOT_BLOCK", Material.BEETROOT); + renamedLegacy.put("FENCE", Material.OAK_FENCE); + renamedLegacy.put("PORTAL", Material.NETHER_PORTAL); + renamedLegacy.put("DIODE_BLOCK_OFF", Material.REPEATER); + renamedLegacy.put("DIODE_BLOCK_ON", Material.REPEATER); + renamedLegacy.put("DIODE", Material.REPEATER); + renamedLegacy.put("STAINED_GLASS", Material.WHITE_STAINED_GLASS); + renamedLegacy.put("TRAP_DOOR", Material.OAK_TRAPDOOR); + renamedLegacy.put("MONSTER_EGGS", Material.SKELETON_SPAWN_EGG); + renamedLegacy.put("MONSTER_EGG", Material.SKELETON_SPAWN_EGG); + renamedLegacy.put("SMOOTH_BRICK", Material.STONE_BRICKS); + renamedLegacy.put("HUGE_MUSHROOM_1", Material.MUSHROOM_STEM); + renamedLegacy.put("HUGE_MUSHROOM_2", Material.RED_MUSHROOM); + renamedLegacy.put("IRON_FENCE", Material.IRON_BARS); + renamedLegacy.put("THIN_GLASS", Material.GLASS_PANE); + renamedLegacy.put("FENCE_GATE", Material.OAK_FENCE_GATE); + renamedLegacy.put("SMOOTH_STAIRS", Material.STONE_BRICK_STAIRS); + renamedLegacy.put("MYCEL", Material.MYCELIUM); + renamedLegacy.put("WATER_LILY", Material.LILY_PAD); + renamedLegacy.put("NETHER_FENCE", Material.NETHER_BRICK_FENCE); + renamedLegacy.put("NETHER_WARTS", Material.NETHER_WART); + renamedLegacy.put("NETHER_STALK", Material.NETHER_WART); + renamedLegacy.put("ENCHANTMENT_TABLE", Material.ENCHANTING_TABLE); + renamedLegacy.put("ENDER_PORTAL", Material.END_PORTAL); + renamedLegacy.put("ENDER_PORTAL_FRAME", Material.END_PORTAL_FRAME); + renamedLegacy.put("ENDER_STONE", Material.END_STONE); + renamedLegacy.put("REDSTONE_LAMP_OFF", Material.REDSTONE_LAMP); + renamedLegacy.put("REDSTONE_LAMP_ON", Material.REDSTONE_LAMP); + renamedLegacy.put("WOOD_DOUBLE_STEP", Material.OAK_SLAB); + renamedLegacy.put("WOOD_STEP", Material.OAK_SLAB); + renamedLegacy.put("SPRUCE_WOOD_STAIRS", Material.SPRUCE_STAIRS); + renamedLegacy.put("BIRCH_WOOD_STAIRS", Material.BIRCH_STAIRS); + renamedLegacy.put("JUNGLE_WOOD_STAIRS", Material.JUNGLE_STAIRS); + renamedLegacy.put("COMMAND", Material.COMMAND_BLOCK); + renamedLegacy.put("COBBLE_WALL", Material.COBBLESTONE_WALL); + renamedLegacy.put("WOOD_BUTTON", Material.OAK_BUTTON); + renamedLegacy.put("SKULL", Material.SKELETON_SKULL); + renamedLegacy.put("SKULL_ITEM", Material.SKELETON_SKULL); + renamedLegacy.put("GOLD_PLATE", Material.LIGHT_WEIGHTED_PRESSURE_PLATE); + renamedLegacy.put("IRON_PLATE", Material.HEAVY_WEIGHTED_PRESSURE_PLATE); + renamedLegacy.put("REDSTONE_COMPARATOR_OFF", Material.COMPARATOR); + renamedLegacy.put("REDSTONE_COMPARATOR_ON", Material.COMPARATOR); + renamedLegacy.put("REDSTONE_COMPARATOR", Material.COMPARATOR); + renamedLegacy.put("QUARTZ_ORE", Material.QUARTZ); + renamedLegacy.put("STAINED_CLAY", Material.WHITE_TERRACOTTA); + renamedLegacy.put("STAINED_GLASS_PANE", Material.WHITE_STAINED_GLASS_PANE); + renamedLegacy.put("LEAVES_2", Material.ACACIA_LEAVES); + renamedLegacy.put("LOG_2", Material.ACACIA_LOG); + renamedLegacy.put("CARPET", Material.WHITE_CARPET); + renamedLegacy.put("HARD_CLAY", Material.TERRACOTTA); + renamedLegacy.put("DOUBLE_PLANT", Material.SUNFLOWER); + renamedLegacy.put("STANDING_BANNER", Material.WHITE_BANNER); + renamedLegacy.put("BANNER", Material.WHITE_BANNER); + renamedLegacy.put("WALL_BANNER", Material.WHITE_WALL_BANNER); + renamedLegacy.put("DAYLIGHT_DETECTOR_INVERTED", Material.DAYLIGHT_DETECTOR); + renamedLegacy.put("DOUBLE_STONE_SLAB2", Material.RED_SANDSTONE_SLAB); + renamedLegacy.put("STONE_SLAB2", Material.RED_SANDSTONE_SLAB); + renamedLegacy.put("PURPUR_DOUBLE_SLAB", Material.PURPUR_SLAB); + renamedLegacy.put("END_BRICKS", Material.END_STONE_BRICKS); + renamedLegacy.put("COMMAND_REPEATING", Material.REPEATING_COMMAND_BLOCK); + renamedLegacy.put("COMMAND_CHAIN", Material.CHAIN_COMMAND_BLOCK); + renamedLegacy.put("MAGMA", Material.MAGMA_BLOCK); + renamedLegacy.put("RED_NETHER_BRICK", Material.RED_NETHER_BRICKS); + renamedLegacy.put("SILVER_SHULKER_BOX", Material.LIGHT_GRAY_SHULKER_BOX); + renamedLegacy.put("SILVER_GLAZED_TERRACOTTA", Material.LIGHT_GRAY_TERRACOTTA); + renamedLegacy.put("CONCRETE", Material.WHITE_CONCRETE); + renamedLegacy.put("CONCRETE_POWDER", Material.WHITE_CONCRETE_POWDER); + renamedLegacy.put("IRON_SPADE", Material.IRON_SHOVEL); + renamedLegacy.put("WOOD_SWORD", Material.WOODEN_SWORD); + renamedLegacy.put("WOOD_SPADE", Material.WOODEN_SHOVEL); + renamedLegacy.put("WOOD_PICKAXE", Material.WOODEN_PICKAXE); + renamedLegacy.put("WOOD_AXE", Material.WOODEN_AXE); + renamedLegacy.put("STONE_SPADE", Material.STONE_SHOVEL); + renamedLegacy.put("DIAMOND_SPADE", Material.DIAMOND_SHOVEL); + renamedLegacy.put("MUSHROOM_SOUP", Material.MUSHROOM_STEW); + renamedLegacy.put("GOLD_SWORD", Material.GOLDEN_SWORD); + renamedLegacy.put("GOLD_SPADE", Material.GOLDEN_SHOVEL); + renamedLegacy.put("GOLD_PICKAXE", Material.GOLDEN_PICKAXE); + renamedLegacy.put("GOLD_AXE", Material.GOLDEN_AXE); + renamedLegacy.put("SULPHUR", Material.GUNPOWDER); + renamedLegacy.put("WOOD_HOE", Material.WOODEN_HOE); + renamedLegacy.put("GOLD_HOE", Material.GOLDEN_HOE); + renamedLegacy.put("GOLD_HELMET", Material.GOLDEN_HELMET); + renamedLegacy.put("GOLD_CHESTPLATE", Material.GOLDEN_CHESTPLATE); + renamedLegacy.put("GOLD_LEGGINGS", Material.GOLDEN_LEGGINGS); + renamedLegacy.put("GOLD_BOOTS", Material.GOLDEN_BOOTS); + renamedLegacy.put("PORK", Material.PORKCHOP); + renamedLegacy.put("GRILLED_PORK", Material.COOKED_PORKCHOP); + renamedLegacy.put("SNOW_BALL", Material.SNOWBALL); + renamedLegacy.put("BOAT", Material.OAK_BOAT); + renamedLegacy.put("CLAY_BRICK", Material.BRICKS); + renamedLegacy.put("STORAGE_MINECART", Material.CHEST_MINECART); + renamedLegacy.put("POWERED_MINECART", Material.FURNACE_MINECART); + renamedLegacy.put("WATCH", Material.CLOCK); + renamedLegacy.put("RAW_FISH", Material.SALMON); + renamedLegacy.put("COOKED_FISH", Material.COOKED_SALMON); + renamedLegacy.put("INK_SACK", Material.INK_SAC); + renamedLegacy.put("RAW_BEEF", Material.BEEF); + renamedLegacy.put("RAW_CHICKEN", Material.CHICKEN); + renamedLegacy.put("EYE_OF_ENDER", Material.ENDER_EYE); + renamedLegacy.put("SPECKLED_MELON", Material.GLISTERING_MELON_SLICE); + renamedLegacy.put("EXP_BOTTLE", Material.EXPERIENCE_BOTTLE); + renamedLegacy.put("FIREBALL", Material.FIRE_CHARGE); + renamedLegacy.put("BOOK_AND_QUILL", Material.WRITABLE_BOOK); + renamedLegacy.put("FLOWER_POT_ITEM", Material.FLOWER_POT); + renamedLegacy.put("EMPTY_MAP", Material.MAP); + renamedLegacy.put("BREWING_STAND_ITEM", Material.BREWING_STAND); + renamedLegacy.put("CAULDRON_ITEM", Material.CAULDRON); + renamedLegacy.put("CARROT_ITEM", Material.CARROT); + renamedLegacy.put("POTATO_ITEM", Material.POTATO); + renamedLegacy.put("SPRUCE_DOOR_ITEM", Material.SPRUCE_DOOR); + renamedLegacy.put("BIRCH_DOOR_ITEM", Material.BIRCH_DOOR); + renamedLegacy.put("JUNGLE_DOOR_ITEM", Material.JUNGLE_DOOR); + renamedLegacy.put("ACACIA_DOOR_ITEM", Material.ACACIA_DOOR); + renamedLegacy.put("DARK_OAK_DOOR_ITEM", Material.DARK_OAK_DOOR); + renamedLegacy.put("CARROT_STICK", Material.CARROT_ON_A_STICK); + renamedLegacy.put("FIREWORK", Material.FIREWORK_ROCKET); + renamedLegacy.put("FIREWORK_CHARGE", Material.FIREWORK_STAR); + renamedLegacy.put("NETHER_BRICK_ITEM", Material.NETHER_BRICKS); + renamedLegacy.put("EXPLOSIVE_MINECART", Material.TNT_MINECART); + renamedLegacy.put("IRON_BARDING", Material.IRON_HORSE_ARMOR); + renamedLegacy.put("GOLD_BARDING", Material.GOLDEN_HORSE_ARMOR); + renamedLegacy.put("DIAMOND_BARDING", Material.DIAMOND_HORSE_ARMOR); + renamedLegacy.put("LEASH", Material.LEAD); + renamedLegacy.put("COMMAND_MINECART", Material.COMMAND_BLOCK_MINECART); + renamedLegacy.put("CHORUS_FRUIT_POPPED", Material.POPPED_CHORUS_FRUIT); + renamedLegacy.put("DRAGONS_BREATH", Material.DRAGON_BREATH); + renamedLegacy.put("BOAT_SPRUCE", Material.SPRUCE_BOAT); + renamedLegacy.put("BOAT_BIRCH", Material.BIRCH_BOAT); + renamedLegacy.put("BOAT_JUNGLE", Material.JUNGLE_BOAT); + renamedLegacy.put("BOAT_ACACIA", Material.ACACIA_BOAT); + renamedLegacy.put("BOAT_DARK_OAK", Material.DARK_OAK_BOAT); + renamedLegacy.put("TOTEM", Material.TOTEM_OF_UNDYING); + renamedLegacy.put("GOLD_RECORD", Material.MUSIC_DISC_13); + renamedLegacy.put("GREEN_RECORD", Material.MUSIC_DISC_CAT); + renamedLegacy.put("RECORD_3", Material.MUSIC_DISC_BLOCKS); + renamedLegacy.put("RECORD_4", Material.MUSIC_DISC_CHIRP); + renamedLegacy.put("RECORD_5", Material.MUSIC_DISC_FAR); + renamedLegacy.put("RECORD_6", Material.MUSIC_DISC_MALL); + renamedLegacy.put("RECORD_7", Material.MUSIC_DISC_MELLOHI); + renamedLegacy.put("RECORD_8", Material.MUSIC_DISC_STAL); + renamedLegacy.put("RECORD_9", Material.MUSIC_DISC_STRAD); + renamedLegacy.put("RECORD_10", Material.MUSIC_DISC_WARD); + renamedLegacy.put("RECORD_11", Material.MUSIC_DISC_11); + renamedLegacy.put("RECORD_12", Material.MUSIC_DISC_WAIT); + } + + private static final Class chatComponent = Reflection.getClass("{nms}.ChatComponentText"); + private static final Reflection.FieldAccessor scoreboardName = Reflection.getField(SWScoreboard.scoreboardObjective, chatComponent, 0); + private static final Reflection.ConstructorInvoker chatComponentConstructor = Reflection.getConstructor(chatComponent, String.class); + + @Override + public void setScoreboardTitle(Object packet, String title) { + scoreboardName.set(packet, chatComponentConstructor.invoke(title)); + } + + @Override + public Material getMaterial(String material) { + try{ + return Material.valueOf(material); + }catch(IllegalArgumentException e){ + return renamedLegacy.get(material); + } + } + + @Override + public Material getDye(int colorCode) { + switch(colorCode){ + case 1: + return Material.RED_DYE; + case 2: + return Material.GREEN_DYE; + case 3: + return Material.BROWN_DYE; + case 4: + return Material.LAPIS_LAZULI; + case 5: + return Material.PURPLE_DYE; + case 6: + return Material.CYAN_DYE; + case 7: + return Material.LIGHT_GRAY_DYE; + case 8: + return Material.GRAY_DYE; + case 9: + return Material.PINK_DYE; + case 10: + return Material.LIME_DYE; + case 11: + return Material.YELLOW_DYE; + case 12: + return Material.LIGHT_BLUE_DYE; + case 13: + return Material.MAGENTA_DYE; + case 14: + return Material.ORANGE_DYE; + case 15: + return Material.WHITE_DYE; + default: + return Material.BLACK_DYE; + } + } + + @SuppressWarnings("deprecation") + @Override + public ItemStack setSkullOwner(String player) { + ItemStack head = new ItemStack(Material.PLAYER_HEAD, 1); + SkullMeta headmeta = (SkullMeta) head.getItemMeta(); + assert headmeta != null; + headmeta.setOwningPlayer(Bukkit.getOfflinePlayer(player)); + headmeta.setDisplayName(player); + head.setItemMeta(headmeta); + return head; + } private static final ClipboardFormat SCHEMATIC = BuiltInClipboardFormat.MCEDIT_SCHEMATIC; private static final ClipboardFormat SCHEM = BuiltInClipboardFormat.SPONGE_SCHEMATIC; - static byte[] getPlayerClipboard(Player player, boolean schemFormat) { + @Override + public byte[] getPlayerClipboard(Player player, boolean schemFormat) { ClipboardHolder clipboardHolder; try { clipboardHolder = getWorldEditPlugin().getSession(player).getClipboard(); @@ -92,7 +357,8 @@ class Schematic_14 { return outputStream.toByteArray(); } - static void setPlayerClipboard(Player player, InputStream is, boolean schemFormat) { + @Override + public void setPlayerClipboard(Player player, InputStream is, boolean schemFormat) { Clipboard clipboard = null; try { clipboard = getClipboard(is, schemFormat); @@ -107,7 +373,8 @@ class Schematic_14 { getWorldEditPlugin().getWorldEdit().getSessionManager().get(actor).setClipboard(new ClipboardHolder(clipboard)); } - static Clipboard getClipboard(InputStream is, boolean schemFormat) throws IOException { + @Override + public Clipboard getClipboard(InputStream is, boolean schemFormat) throws IOException { try { if(schemFormat){ return new SpongeSchematicReader(new NBTInputStream(is)).read(); @@ -419,7 +686,7 @@ class Schematic_14 { return readVersion1(schematicTag); } else if (schematicVersion == 2) { dataVersion = requireTag(schematic, "DataVersion", IntTag.class).getValue(); - if (dataVersion < liveDataVersion) { + if (dataVersion < liveDataVersion) { fixer = platform.getDataFixer(); } diff --git a/SpigotCore_14/src/de/steamwar/core/SpigotTPS_14.java b/SpigotCore_14/src/de/steamwar/core/SpigotTPS_14.java deleted file mode 100644 index d00aba8..0000000 --- a/SpigotCore_14/src/de/steamwar/core/SpigotTPS_14.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - This file is a part of the SteamWar software. - - Copyright (C) 2020 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.core; - -import net.minecraft.server.v1_14_R1.MinecraftServer; - -public class SpigotTPS_14 { - - private SpigotTPS_14(){} - - static double[] getTps(){ - return MinecraftServer.getServer().recentTps; - } - -} diff --git a/SpigotCore_14/src/de/steamwar/inventory/SWItem_14.java b/SpigotCore_14/src/de/steamwar/inventory/SWItem_14.java deleted file mode 100644 index 623dd20..0000000 --- a/SpigotCore_14/src/de/steamwar/inventory/SWItem_14.java +++ /dev/null @@ -1,278 +0,0 @@ -/* - This file is a part of the SteamWar software. - - Copyright (C) 2020 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.inventory; - -import org.bukkit.Bukkit; -import org.bukkit.Material; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.SkullMeta; - -import java.util.HashMap; -import java.util.Map; - -class SWItem_14 { - private SWItem_14(){} - - private static final Map renamedLegacy = new HashMap<>(); - - static{ - renamedLegacy.put("WOOD", Material.OAK_WOOD); - renamedLegacy.put("SAPLING", Material.OAK_SAPLING); - renamedLegacy.put("STATIONARY_WATER", Material.WATER); - renamedLegacy.put("STATIONARY_LAVA", Material.LAVA); - renamedLegacy.put("LOG", Material.OAK_LOG); - renamedLegacy.put("LEAVES", Material.OAK_LEAVES); - renamedLegacy.put("BED_BLOCK", Material.RED_BED); - renamedLegacy.put("BED", Material.RED_BED); - renamedLegacy.put("PISTON_STICKY_BASE", Material.STICKY_PISTON); - renamedLegacy.put("WEB", Material.COBWEB); - renamedLegacy.put("LONG_GRASS", Material.TALL_GRASS); - renamedLegacy.put("PISTON_BASE", Material.PISTON); - renamedLegacy.put("PISTON_EXTENSION", Material.PISTON_HEAD); - renamedLegacy.put("WOOL", Material.WHITE_WOOL); - renamedLegacy.put("PISTON_MOVING_PIECE", Material.MOVING_PISTON); - renamedLegacy.put("YELLOW_FLOWER", Material.DANDELION); - renamedLegacy.put("RED_ROSE", Material.POPPY); - renamedLegacy.put("DOUBLE_STEP", Material.SMOOTH_STONE); - renamedLegacy.put("STEP", Material.SMOOTH_STONE_SLAB); - renamedLegacy.put("MOB_SPAWNER", Material.SPAWNER); - renamedLegacy.put("WOOD_STAIRS", Material.OAK_STAIRS); - renamedLegacy.put("WORKBENCH", Material.CRAFTING_TABLE); - renamedLegacy.put("CROPS", Material.WHEAT_SEEDS); - renamedLegacy.put("SEEDS", Material.WHEAT_SEEDS); - renamedLegacy.put("SOIL", Material.FARMLAND); - renamedLegacy.put("BURNING_FURNACE", Material.FURNACE); - renamedLegacy.put("SIGN_POST", Material.OAK_SIGN); - renamedLegacy.put("SIGN", Material.OAK_SIGN); - renamedLegacy.put("WOODEN_DOOR", Material.OAK_DOOR); - renamedLegacy.put("WOOD_DOOR", Material.OAK_DOOR); - renamedLegacy.put("RAILS", Material.RAIL); - renamedLegacy.put("WALL_SIGN", Material.OAK_WALL_SIGN); - renamedLegacy.put("STONE_PLATE", Material.STONE_PRESSURE_PLATE); - renamedLegacy.put("WOOD_PLATE", Material.OAK_PRESSURE_PLATE); - renamedLegacy.put("GLOWING_REDSTONE_ORE", Material.REDSTONE_ORE); - renamedLegacy.put("REDSTONE_TORCH_OFF", Material.REDSTONE_TORCH); - renamedLegacy.put("REDSTONE_TORCH_ON", Material.REDSTONE_TORCH); - renamedLegacy.put("IRON_DOOR_BLOCK", Material.IRON_DOOR); - renamedLegacy.put("SUGAR_CANE_BLOCK", Material.SUGAR_CANE); - renamedLegacy.put("CAKE_BLOCK", Material.CAKE); - renamedLegacy.put("MELON_BLOCK", Material.MELON); - renamedLegacy.put("BEETROOT_BLOCK", Material.BEETROOT); - renamedLegacy.put("FENCE", Material.OAK_FENCE); - renamedLegacy.put("PORTAL", Material.NETHER_PORTAL); - renamedLegacy.put("DIODE_BLOCK_OFF", Material.REPEATER); - renamedLegacy.put("DIODE_BLOCK_ON", Material.REPEATER); - renamedLegacy.put("DIODE", Material.REPEATER); - renamedLegacy.put("STAINED_GLASS", Material.WHITE_STAINED_GLASS); - renamedLegacy.put("TRAP_DOOR", Material.OAK_TRAPDOOR); - renamedLegacy.put("MONSTER_EGGS", Material.SKELETON_SPAWN_EGG); - renamedLegacy.put("MONSTER_EGG", Material.SKELETON_SPAWN_EGG); - renamedLegacy.put("SMOOTH_BRICK", Material.STONE_BRICKS); - renamedLegacy.put("HUGE_MUSHROOM_1", Material.MUSHROOM_STEM); - renamedLegacy.put("HUGE_MUSHROOM_2", Material.RED_MUSHROOM); - renamedLegacy.put("IRON_FENCE", Material.IRON_BARS); - renamedLegacy.put("THIN_GLASS", Material.GLASS_PANE); - renamedLegacy.put("FENCE_GATE", Material.OAK_FENCE_GATE); - renamedLegacy.put("SMOOTH_STAIRS", Material.STONE_BRICK_STAIRS); - renamedLegacy.put("MYCEL", Material.MYCELIUM); - renamedLegacy.put("WATER_LILY", Material.LILY_PAD); - renamedLegacy.put("NETHER_FENCE", Material.NETHER_BRICK_FENCE); - renamedLegacy.put("NETHER_WARTS", Material.NETHER_WART); - renamedLegacy.put("NETHER_STALK", Material.NETHER_WART); - renamedLegacy.put("ENCHANTMENT_TABLE", Material.ENCHANTING_TABLE); - renamedLegacy.put("ENDER_PORTAL", Material.END_PORTAL); - renamedLegacy.put("ENDER_PORTAL_FRAME", Material.END_PORTAL_FRAME); - renamedLegacy.put("ENDER_STONE", Material.END_STONE); - renamedLegacy.put("REDSTONE_LAMP_OFF", Material.REDSTONE_LAMP); - renamedLegacy.put("REDSTONE_LAMP_ON", Material.REDSTONE_LAMP); - renamedLegacy.put("WOOD_DOUBLE_STEP", Material.OAK_SLAB); - renamedLegacy.put("WOOD_STEP", Material.OAK_SLAB); - renamedLegacy.put("SPRUCE_WOOD_STAIRS", Material.SPRUCE_STAIRS); - renamedLegacy.put("BIRCH_WOOD_STAIRS", Material.BIRCH_STAIRS); - renamedLegacy.put("JUNGLE_WOOD_STAIRS", Material.JUNGLE_STAIRS); - renamedLegacy.put("COMMAND", Material.COMMAND_BLOCK); - renamedLegacy.put("COBBLE_WALL", Material.COBBLESTONE_WALL); - renamedLegacy.put("WOOD_BUTTON", Material.OAK_BUTTON); - renamedLegacy.put("SKULL", Material.SKELETON_SKULL); - renamedLegacy.put("SKULL_ITEM", Material.SKELETON_SKULL); - renamedLegacy.put("GOLD_PLATE", Material.LIGHT_WEIGHTED_PRESSURE_PLATE); - renamedLegacy.put("IRON_PLATE", Material.HEAVY_WEIGHTED_PRESSURE_PLATE); - renamedLegacy.put("REDSTONE_COMPARATOR_OFF", Material.COMPARATOR); - renamedLegacy.put("REDSTONE_COMPARATOR_ON", Material.COMPARATOR); - renamedLegacy.put("REDSTONE_COMPARATOR", Material.COMPARATOR); - renamedLegacy.put("QUARTZ_ORE", Material.QUARTZ); - renamedLegacy.put("STAINED_CLAY", Material.WHITE_TERRACOTTA); - renamedLegacy.put("STAINED_GLASS_PANE", Material.WHITE_STAINED_GLASS_PANE); - renamedLegacy.put("LEAVES_2", Material.ACACIA_LEAVES); - renamedLegacy.put("LOG_2", Material.ACACIA_LOG); - renamedLegacy.put("CARPET", Material.WHITE_CARPET); - renamedLegacy.put("HARD_CLAY", Material.TERRACOTTA); - renamedLegacy.put("DOUBLE_PLANT", Material.SUNFLOWER); - renamedLegacy.put("STANDING_BANNER", Material.WHITE_BANNER); - renamedLegacy.put("BANNER", Material.WHITE_BANNER); - renamedLegacy.put("WALL_BANNER", Material.WHITE_WALL_BANNER); - renamedLegacy.put("DAYLIGHT_DETECTOR_INVERTED", Material.DAYLIGHT_DETECTOR); - renamedLegacy.put("DOUBLE_STONE_SLAB2", Material.RED_SANDSTONE_SLAB); - renamedLegacy.put("STONE_SLAB2", Material.RED_SANDSTONE_SLAB); - renamedLegacy.put("PURPUR_DOUBLE_SLAB", Material.PURPUR_SLAB); - renamedLegacy.put("END_BRICKS", Material.END_STONE_BRICKS); - renamedLegacy.put("COMMAND_REPEATING", Material.REPEATING_COMMAND_BLOCK); - renamedLegacy.put("COMMAND_CHAIN", Material.CHAIN_COMMAND_BLOCK); - renamedLegacy.put("MAGMA", Material.MAGMA_BLOCK); - renamedLegacy.put("RED_NETHER_BRICK", Material.RED_NETHER_BRICKS); - renamedLegacy.put("SILVER_SHULKER_BOX", Material.LIGHT_GRAY_SHULKER_BOX); - renamedLegacy.put("SILVER_GLAZED_TERRACOTTA", Material.LIGHT_GRAY_TERRACOTTA); - renamedLegacy.put("CONCRETE", Material.WHITE_CONCRETE); - renamedLegacy.put("CONCRETE_POWDER", Material.WHITE_CONCRETE_POWDER); - renamedLegacy.put("IRON_SPADE", Material.IRON_SHOVEL); - renamedLegacy.put("WOOD_SWORD", Material.WOODEN_SWORD); - renamedLegacy.put("WOOD_SPADE", Material.WOODEN_SHOVEL); - renamedLegacy.put("WOOD_PICKAXE", Material.WOODEN_PICKAXE); - renamedLegacy.put("WOOD_AXE", Material.WOODEN_AXE); - renamedLegacy.put("STONE_SPADE", Material.STONE_SHOVEL); - renamedLegacy.put("DIAMOND_SPADE", Material.DIAMOND_SHOVEL); - renamedLegacy.put("MUSHROOM_SOUP", Material.MUSHROOM_STEW); - renamedLegacy.put("GOLD_SWORD", Material.GOLDEN_SWORD); - renamedLegacy.put("GOLD_SPADE", Material.GOLDEN_SHOVEL); - renamedLegacy.put("GOLD_PICKAXE", Material.GOLDEN_PICKAXE); - renamedLegacy.put("GOLD_AXE", Material.GOLDEN_AXE); - renamedLegacy.put("SULPHUR", Material.GUNPOWDER); - renamedLegacy.put("WOOD_HOE", Material.WOODEN_HOE); - renamedLegacy.put("GOLD_HOE", Material.GOLDEN_HOE); - renamedLegacy.put("GOLD_HELMET", Material.GOLDEN_HELMET); - renamedLegacy.put("GOLD_CHESTPLATE", Material.GOLDEN_CHESTPLATE); - renamedLegacy.put("GOLD_LEGGINGS", Material.GOLDEN_LEGGINGS); - renamedLegacy.put("GOLD_BOOTS", Material.GOLDEN_BOOTS); - renamedLegacy.put("PORK", Material.PORKCHOP); - renamedLegacy.put("GRILLED_PORK", Material.COOKED_PORKCHOP); - renamedLegacy.put("SNOW_BALL", Material.SNOWBALL); - renamedLegacy.put("BOAT", Material.OAK_BOAT); - renamedLegacy.put("CLAY_BRICK", Material.BRICKS); - renamedLegacy.put("STORAGE_MINECART", Material.CHEST_MINECART); - renamedLegacy.put("POWERED_MINECART", Material.FURNACE_MINECART); - renamedLegacy.put("WATCH", Material.CLOCK); - renamedLegacy.put("RAW_FISH", Material.SALMON); - renamedLegacy.put("COOKED_FISH", Material.COOKED_SALMON); - renamedLegacy.put("INK_SACK", Material.INK_SAC); - renamedLegacy.put("RAW_BEEF", Material.BEEF); - renamedLegacy.put("RAW_CHICKEN", Material.CHICKEN); - renamedLegacy.put("EYE_OF_ENDER", Material.ENDER_EYE); - renamedLegacy.put("SPECKLED_MELON", Material.GLISTERING_MELON_SLICE); - renamedLegacy.put("EXP_BOTTLE", Material.EXPERIENCE_BOTTLE); - renamedLegacy.put("FIREBALL", Material.FIRE_CHARGE); - renamedLegacy.put("BOOK_AND_QUILL", Material.WRITABLE_BOOK); - renamedLegacy.put("FLOWER_POT_ITEM", Material.FLOWER_POT); - renamedLegacy.put("EMPTY_MAP", Material.MAP); - renamedLegacy.put("BREWING_STAND_ITEM", Material.BREWING_STAND); - renamedLegacy.put("CAULDRON_ITEM", Material.CAULDRON); - renamedLegacy.put("CARROT_ITEM", Material.CARROT); - renamedLegacy.put("POTATO_ITEM", Material.POTATO); - renamedLegacy.put("SPRUCE_DOOR_ITEM", Material.SPRUCE_DOOR); - renamedLegacy.put("BIRCH_DOOR_ITEM", Material.BIRCH_DOOR); - renamedLegacy.put("JUNGLE_DOOR_ITEM", Material.JUNGLE_DOOR); - renamedLegacy.put("ACACIA_DOOR_ITEM", Material.ACACIA_DOOR); - renamedLegacy.put("DARK_OAK_DOOR_ITEM", Material.DARK_OAK_DOOR); - renamedLegacy.put("CARROT_STICK", Material.CARROT_ON_A_STICK); - renamedLegacy.put("FIREWORK", Material.FIREWORK_ROCKET); - renamedLegacy.put("FIREWORK_CHARGE", Material.FIREWORK_STAR); - renamedLegacy.put("NETHER_BRICK_ITEM", Material.NETHER_BRICKS); - renamedLegacy.put("EXPLOSIVE_MINECART", Material.TNT_MINECART); - renamedLegacy.put("IRON_BARDING", Material.IRON_HORSE_ARMOR); - renamedLegacy.put("GOLD_BARDING", Material.GOLDEN_HORSE_ARMOR); - renamedLegacy.put("DIAMOND_BARDING", Material.DIAMOND_HORSE_ARMOR); - renamedLegacy.put("LEASH", Material.LEAD); - renamedLegacy.put("COMMAND_MINECART", Material.COMMAND_BLOCK_MINECART); - renamedLegacy.put("CHORUS_FRUIT_POPPED", Material.POPPED_CHORUS_FRUIT); - renamedLegacy.put("DRAGONS_BREATH", Material.DRAGON_BREATH); - renamedLegacy.put("BOAT_SPRUCE", Material.SPRUCE_BOAT); - renamedLegacy.put("BOAT_BIRCH", Material.BIRCH_BOAT); - renamedLegacy.put("BOAT_JUNGLE", Material.JUNGLE_BOAT); - renamedLegacy.put("BOAT_ACACIA", Material.ACACIA_BOAT); - renamedLegacy.put("BOAT_DARK_OAK", Material.DARK_OAK_BOAT); - renamedLegacy.put("TOTEM", Material.TOTEM_OF_UNDYING); - renamedLegacy.put("GOLD_RECORD", Material.MUSIC_DISC_13); - renamedLegacy.put("GREEN_RECORD", Material.MUSIC_DISC_CAT); - renamedLegacy.put("RECORD_3", Material.MUSIC_DISC_BLOCKS); - renamedLegacy.put("RECORD_4", Material.MUSIC_DISC_CHIRP); - renamedLegacy.put("RECORD_5", Material.MUSIC_DISC_FAR); - renamedLegacy.put("RECORD_6", Material.MUSIC_DISC_MALL); - renamedLegacy.put("RECORD_7", Material.MUSIC_DISC_MELLOHI); - renamedLegacy.put("RECORD_8", Material.MUSIC_DISC_STAL); - renamedLegacy.put("RECORD_9", Material.MUSIC_DISC_STRAD); - renamedLegacy.put("RECORD_10", Material.MUSIC_DISC_WARD); - renamedLegacy.put("RECORD_11", Material.MUSIC_DISC_11); - renamedLegacy.put("RECORD_12", Material.MUSIC_DISC_WAIT); - } - - static Material getMaterial(String material) { - try{ - return Material.valueOf(material); - }catch(IllegalArgumentException e){ - return renamedLegacy.get(material); - } - } - - static Material getDye(int colorCode){ - switch(colorCode){ - case 1: - return Material.RED_DYE; - case 2: - return Material.GREEN_DYE; - case 3: - return Material.BROWN_DYE; - case 4: - return Material.LAPIS_LAZULI; - case 5: - return Material.PURPLE_DYE; - case 6: - return Material.CYAN_DYE; - case 7: - return Material.LIGHT_GRAY_DYE; - case 8: - return Material.GRAY_DYE; - case 9: - return Material.PINK_DYE; - case 10: - return Material.LIME_DYE; - case 11: - return Material.YELLOW_DYE; - case 12: - return Material.LIGHT_BLUE_DYE; - case 13: - return Material.MAGENTA_DYE; - case 14: - return Material.ORANGE_DYE; - case 15: - return Material.WHITE_DYE; - default: - return Material.BLACK_DYE; - } - } - - static ItemStack setSkullOwner(String player){ - ItemStack head = new ItemStack(Material.PLAYER_HEAD, 1); - SkullMeta headmeta = (SkullMeta) head.getItemMeta(); - assert headmeta != null; - headmeta.setOwningPlayer(Bukkit.getOfflinePlayer(player)); - headmeta.setDisplayName(player); - head.setItemMeta(headmeta); - return head; - } -} diff --git a/SpigotCore_15/build.gradle b/SpigotCore_15/build.gradle index 7cf4806..31149fe 100644 --- a/SpigotCore_15/build.gradle +++ b/SpigotCore_15/build.gradle @@ -43,8 +43,7 @@ sourceSets { } dependencies { - implementation project(":SpigotCore_14") - implementation project(":SpigotCore_API") + implementation project(":SpigotCore_Main") compileOnly 'org.projectlombok:lombok:1.18.6' testCompileOnly 'org.projectlombok:lombok:1.18.6' @@ -52,5 +51,4 @@ dependencies { testAnnotationProcessor 'org.projectlombok:lombok:1.18.6' compileOnly files("${project.rootDir}/lib/Spigot-1.15.jar") - compileOnly files("${project.rootDir}/lib/WorldEdit-1.15.jar") } diff --git a/SpigotCore_15/src/de/steamwar/chunk/Chunk_15.java b/SpigotCore_15/src/de/steamwar/core/CraftbukkitWrapper15.java similarity index 74% rename from SpigotCore_15/src/de/steamwar/chunk/Chunk_15.java rename to SpigotCore_15/src/de/steamwar/core/CraftbukkitWrapper15.java index 8a8b636..d5b908f 100644 --- a/SpigotCore_15/src/de/steamwar/chunk/Chunk_15.java +++ b/SpigotCore_15/src/de/steamwar/core/CraftbukkitWrapper15.java @@ -1,6 +1,6 @@ -/* +/* This file is a part of the SteamWar software. - + Copyright (C) 2020 SteamWar.de-Serverteam This program is free software: you can redistribute it and/or modify @@ -17,17 +17,24 @@ along with this program. If not, see . */ -package de.steamwar.chunk; +package de.steamwar.core; +import net.minecraft.server.v1_15_R1.MinecraftServer; import net.minecraft.server.v1_15_R1.PacketPlayOutMapChunk; import org.bukkit.craftbukkit.v1_15_R1.CraftChunk; import org.bukkit.craftbukkit.v1_15_R1.entity.CraftPlayer; import org.bukkit.entity.Player; -public class Chunk_15 { - private Chunk_15(){} +public class CraftbukkitWrapper15 implements CraftbukkitWrapper.ICraftbukkitWrapper { - public static void sendChunk(Player p, int chunkX, int chunkZ){ + @Override + public void sendChunk(Player p, int chunkX, int chunkZ) { ((CraftPlayer)p).getHandle().playerConnection.sendPacket(new PacketPlayOutMapChunk(((CraftChunk)p.getWorld().getChunkAt(chunkX, chunkZ)).getHandle(), 65535)); } + + @SuppressWarnings("deprecation") + @Override + public double[] getSpigotTPS() { + return MinecraftServer.getServer().recentTps; + } } diff --git a/SpigotCore_15/src/de/steamwar/core/SpigotTPS_15.java b/SpigotCore_15/src/de/steamwar/core/SpigotTPS_15.java deleted file mode 100644 index 46c1186..0000000 --- a/SpigotCore_15/src/de/steamwar/core/SpigotTPS_15.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - This file is a part of the SteamWar software. - - Copyright (C) 2020 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.core; - -import net.minecraft.server.v1_15_R1.MinecraftServer; - -public class SpigotTPS_15 { - - private SpigotTPS_15(){} - - static double[] getTps(){ - return MinecraftServer.getServer().recentTps; - } - -} diff --git a/SpigotCore_8/build.gradle b/SpigotCore_8/build.gradle index cb5ff47..f5207ab 100644 --- a/SpigotCore_8/build.gradle +++ b/SpigotCore_8/build.gradle @@ -43,7 +43,7 @@ sourceSets { } dependencies { - implementation project(":SpigotCore_API") + implementation project(":SpigotCore_Main") compileOnly 'org.projectlombok:lombok:1.18.6' testCompileOnly 'org.projectlombok:lombok:1.18.6' diff --git a/SpigotCore_8/src/de/steamwar/comms/BungeeReceiver_8.java b/SpigotCore_8/src/de/steamwar/core/BountifulWrapper8.java similarity index 85% rename from SpigotCore_8/src/de/steamwar/comms/BungeeReceiver_8.java rename to SpigotCore_8/src/de/steamwar/core/BountifulWrapper8.java index 2b2ce08..2337739 100644 --- a/SpigotCore_8/src/de/steamwar/comms/BungeeReceiver_8.java +++ b/SpigotCore_8/src/de/steamwar/core/BountifulWrapper8.java @@ -17,14 +17,15 @@ along with this program. If not, see . */ -package de.steamwar.comms; +package de.steamwar.core; import org.bukkit.Sound; import org.bukkit.entity.Player; -public class BungeeReceiver_8 { +public class BountifulWrapper8 implements BountifulWrapper.IBountifulWrapper { - public static void playPling(Player player) { + @Override + public void playPling(Player player) { player.playSound(player.getLocation(), Sound.ORB_PICKUP, 1, 1); } } diff --git a/SpigotCore_8/src/de/steamwar/chunk/Chunk_8.java b/SpigotCore_8/src/de/steamwar/core/CraftbukkitWrapper8.java similarity index 76% rename from SpigotCore_8/src/de/steamwar/chunk/Chunk_8.java rename to SpigotCore_8/src/de/steamwar/core/CraftbukkitWrapper8.java index 404c158..149664c 100644 --- a/SpigotCore_8/src/de/steamwar/chunk/Chunk_8.java +++ b/SpigotCore_8/src/de/steamwar/core/CraftbukkitWrapper8.java @@ -1,6 +1,6 @@ -/* +/* This file is a part of the SteamWar software. - + Copyright (C) 2020 SteamWar.de-Serverteam This program is free software: you can redistribute it and/or modify @@ -17,17 +17,23 @@ along with this program. If not, see . */ -package de.steamwar.chunk; +package de.steamwar.core; +import net.minecraft.server.v1_8_R3.MinecraftServer; import net.minecraft.server.v1_8_R3.PacketPlayOutMapChunk; import org.bukkit.craftbukkit.v1_8_R3.CraftChunk; import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer; import org.bukkit.entity.Player; -public class Chunk_8 { - private Chunk_8(){} +public class CraftbukkitWrapper8 implements CraftbukkitWrapper.ICraftbukkitWrapper { - public static void sendChunk(Player p, int chunkX, int chunkZ){ + @Override + public void sendChunk(Player p, int chunkX, int chunkZ) { ((CraftPlayer)p).getHandle().playerConnection.sendPacket(new PacketPlayOutMapChunk(((CraftChunk)p.getWorld().getChunkAt(chunkX, chunkZ)).getHandle(), true, 65535)); } + + @Override + public double[] getSpigotTPS() { + return MinecraftServer.getServer().recentTps; + } } diff --git a/SpigotCore_8/src/de/steamwar/sql/Schematic_8.java b/SpigotCore_8/src/de/steamwar/core/FlatteningWrapper8.java similarity index 87% rename from SpigotCore_8/src/de/steamwar/sql/Schematic_8.java rename to SpigotCore_8/src/de/steamwar/core/FlatteningWrapper8.java index 29974ab..6aaa7ab 100644 --- a/SpigotCore_8/src/de/steamwar/sql/Schematic_8.java +++ b/SpigotCore_8/src/de/steamwar/core/FlatteningWrapper8.java @@ -1,6 +1,6 @@ -/* +/* This file is a part of the SteamWar software. - + Copyright (C) 2020 SteamWar.de-Serverteam This program is free software: you can redistribute it and/or modify @@ -17,8 +17,9 @@ along with this program. If not, see . */ -package de.steamwar.sql; +package de.steamwar.core; +import com.comphenix.tinyprotocol.Reflection; import com.google.common.base.Preconditions; import com.google.common.collect.Maps; import com.sk89q.jnbt.*; @@ -36,8 +37,13 @@ import com.sk89q.worldedit.extent.clipboard.io.SchematicReader; import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.session.ClipboardHolder; import com.sk89q.worldedit.world.registry.WorldData; +import de.steamwar.scoreboard.SWScoreboard; +import de.steamwar.sql.NoClipboardException; import org.bukkit.Bukkit; +import org.bukkit.Material; import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.SkullMeta; import javax.annotation.Nullable; import java.io.ByteArrayOutputStream; @@ -49,10 +55,41 @@ import java.util.List; import java.util.Map; import java.util.stream.Collectors; -class Schematic_8 { - private Schematic_8(){} +public class FlatteningWrapper8 implements FlatteningWrapper.IFlatteningWrapper { - static byte[] getPlayerClipboard(Player player) { + private static final Reflection.FieldAccessor scoreboardName = Reflection.getField(SWScoreboard.scoreboardObjective, String.class, 1); + + @Override + public void setScoreboardTitle(Object packet, String title) { + scoreboardName.set(packet, title); + } + + @Override + public Material getMaterial(String material) { + try{ + return Material.valueOf(material); + }catch(IllegalArgumentException e){ + return Material.STONE; + } + } + + @Override + public Material getDye(int colorCode) { + return Material.INK_SACK; + } + + @Override + public ItemStack setSkullOwner(String player) { + ItemStack head = new ItemStack(Material.SKULL_ITEM, 1, (short) 3); + SkullMeta headmeta = (SkullMeta) head.getItemMeta(); + headmeta.setOwner(player); + headmeta.setDisplayName(player); + head.setItemMeta(headmeta); + return head; + } + + @Override + public byte[] getPlayerClipboard(Player player, boolean schemFormat) { ClipboardHolder clipboardHolder; try { clipboardHolder = getWorldEditPlugin().getSession(player).getClipboard(); @@ -73,7 +110,8 @@ class Schematic_8 { return outputStream.toByteArray(); } - static void setPlayerClipboard(Player player, InputStream is, boolean schemFormat) { + @Override + public void setPlayerClipboard(Player player, InputStream is, boolean schemFormat) { WorldData world = new BukkitWorld(player.getWorld()).getWorldData(); Clipboard clipboard; try { @@ -86,7 +124,8 @@ class Schematic_8 { getWorldEditPlugin().getWorldEdit().getSessionManager().get(actor).setClipboard(new ClipboardHolder(clipboard, world)); } - static Clipboard getClipboard(InputStream is, boolean schemFormat) throws IOException { + @Override + public Clipboard getClipboard(InputStream is, boolean schemFormat) throws IOException { if(schemFormat) return new SpongeSchematicReader(new NBTInputStream(is)).read(WorldEdit.getInstance().getServer().getWorlds().get(0).getWorldData()); else @@ -97,7 +136,7 @@ class Schematic_8 { return (WorldEditPlugin) Bukkit.getPluginManager().getPlugin("WorldEdit"); } - public static class SpongeSchematicReader implements ClipboardReader { + private static class SpongeSchematicReader implements ClipboardReader { private final NBTInputStream inputStream; private int schematicVersion = -1; @@ -132,7 +171,7 @@ class Schematic_8 { } private BlockArrayClipboard readSchematic(CompoundTag schematicTag) throws IOException { - final Map ids = IDConverter.getMap(); + final Map ids = IDConverter8.getMap(); Map schematic = schematicTag.getValue(); int width = (requireTag(schematic, "Width", ShortTag.class)).getValue(); @@ -181,7 +220,7 @@ class Schematic_8 { String palettePart = iterator.next(); id = requireTag(paletteObject, palettePart, IntTag.class).getValue(); - IDConverter.BlockTypeID blockID = ids.get(palettePart); + IDConverter8.BlockTypeID blockID = ids.get(palettePart); if(blockID == null){ blockID = ids.get(palettePart.split("\\[")[0]); } diff --git a/SpigotCore_8/src/de/steamwar/sql/IDConverter.java b/SpigotCore_8/src/de/steamwar/core/IDConverter8.java similarity index 90% rename from SpigotCore_8/src/de/steamwar/sql/IDConverter.java rename to SpigotCore_8/src/de/steamwar/core/IDConverter8.java index b503bde..fdbf70b 100644 --- a/SpigotCore_8/src/de/steamwar/sql/IDConverter.java +++ b/SpigotCore_8/src/de/steamwar/core/IDConverter8.java @@ -17,7 +17,7 @@ along with this program. If not, see . */ -package de.steamwar.sql; +package de.steamwar.core; import org.bukkit.configuration.file.YamlConfiguration; @@ -26,12 +26,12 @@ import java.util.HashMap; import java.util.Map; import java.util.Objects; -class IDConverter { - private IDConverter(){} +class IDConverter8 { + private IDConverter8(){} static Map getMap(){ Map ids = new HashMap<>(); - YamlConfiguration legacy = YamlConfiguration.loadConfiguration(new InputStreamReader(Objects.requireNonNull(IDConverter.class.getClassLoader().getResourceAsStream("legacy.yml")))); + YamlConfiguration legacy = YamlConfiguration.loadConfiguration(new InputStreamReader(Objects.requireNonNull(IDConverter8.class.getClassLoader().getResourceAsStream("legacy.yml")))); for(String blockString : legacy.getKeys(false)){ String blockNum = legacy.getString(blockString); String[] block = blockNum.split(":"); diff --git a/SpigotCore_8/src/de/steamwar/core/SpigotTPS_8.java b/SpigotCore_8/src/de/steamwar/core/SpigotTPS_8.java deleted file mode 100644 index aeb94d1..0000000 --- a/SpigotCore_8/src/de/steamwar/core/SpigotTPS_8.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - This file is a part of the SteamWar software. - - Copyright (C) 2020 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.core; - -import net.minecraft.server.v1_8_R3.MinecraftServer; - -public class SpigotTPS_8 { - - private SpigotTPS_8(){} - - static double[] getTps(){ - return MinecraftServer.getServer().recentTps; - } - -} diff --git a/SpigotCore_8/src/de/steamwar/message/Message_8.java b/SpigotCore_8/src/de/steamwar/core/WorldOfColorWrapper8.java similarity index 84% rename from SpigotCore_8/src/de/steamwar/message/Message_8.java rename to SpigotCore_8/src/de/steamwar/core/WorldOfColorWrapper8.java index 61b897b..73cf7fd 100644 --- a/SpigotCore_8/src/de/steamwar/message/Message_8.java +++ b/SpigotCore_8/src/de/steamwar/core/WorldOfColorWrapper8.java @@ -17,16 +17,16 @@ along with this program. If not, see . */ -package de.steamwar.message; +package de.steamwar.core; import org.bukkit.entity.Player; import java.util.Locale; -class Message_8 { - private Message_8(){} +public class WorldOfColorWrapper8 implements WorldOfColorWrapper.IWorldOfColorWrapper { - static Locale getLocale(Player player){ + @Override + public Locale getLocale(Player player){ return Locale.forLanguageTag(player.spigot().getLocale()); } } diff --git a/SpigotCore_9/build.gradle b/SpigotCore_9/build.gradle index a6ea4c5..e0e40ad 100644 --- a/SpigotCore_9/build.gradle +++ b/SpigotCore_9/build.gradle @@ -43,8 +43,7 @@ sourceSets { } dependencies { - implementation project(":SpigotCore_8") - implementation project(":SpigotCore_API") + implementation project(":SpigotCore_Main") compileOnly 'org.projectlombok:lombok:1.18.6' testCompileOnly 'org.projectlombok:lombok:1.18.6' @@ -52,5 +51,4 @@ dependencies { testAnnotationProcessor 'org.projectlombok:lombok:1.18.6' compileOnly files("${project.rootDir}/lib/Spigot-1.9.jar") - compileOnly files("${project.rootDir}/lib/WorldEdit-1.12.jar") } diff --git a/SpigotCore_9/src/de/steamwar/comms/BungeeReceiver_9.java b/SpigotCore_9/src/de/steamwar/core/BountifulWrapper9.java similarity index 85% rename from SpigotCore_9/src/de/steamwar/comms/BungeeReceiver_9.java rename to SpigotCore_9/src/de/steamwar/core/BountifulWrapper9.java index 685b65a..632606c 100644 --- a/SpigotCore_9/src/de/steamwar/comms/BungeeReceiver_9.java +++ b/SpigotCore_9/src/de/steamwar/core/BountifulWrapper9.java @@ -17,14 +17,15 @@ along with this program. If not, see . */ -package de.steamwar.comms; +package de.steamwar.core; import org.bukkit.Sound; import org.bukkit.entity.Player; -public class BungeeReceiver_9 { +public class BountifulWrapper9 implements BountifulWrapper.IBountifulWrapper { - public static void playpling(Player player) { + @Override + public void playPling(Player player) { player.playSound(player.getLocation(), Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 1, 1); } } diff --git a/SpigotCore_9/src/de/steamwar/chunk/Chunk_9.java b/SpigotCore_9/src/de/steamwar/core/CraftbukkitWrapper9.java similarity index 74% rename from SpigotCore_9/src/de/steamwar/chunk/Chunk_9.java rename to SpigotCore_9/src/de/steamwar/core/CraftbukkitWrapper9.java index b4792fa..6cce09e 100644 --- a/SpigotCore_9/src/de/steamwar/chunk/Chunk_9.java +++ b/SpigotCore_9/src/de/steamwar/core/CraftbukkitWrapper9.java @@ -1,6 +1,6 @@ -/* +/* This file is a part of the SteamWar software. - + Copyright (C) 2020 SteamWar.de-Serverteam This program is free software: you can redistribute it and/or modify @@ -17,17 +17,24 @@ along with this program. If not, see . */ -package de.steamwar.chunk; +package de.steamwar.core; +import net.minecraft.server.v1_9_R2.MinecraftServer; import net.minecraft.server.v1_9_R2.PacketPlayOutMapChunk; import org.bukkit.craftbukkit.v1_9_R2.CraftChunk; import org.bukkit.craftbukkit.v1_9_R2.entity.CraftPlayer; import org.bukkit.entity.Player; -public class Chunk_9 { - private Chunk_9(){} +public class CraftbukkitWrapper9 implements CraftbukkitWrapper.ICraftbukkitWrapper { - public static void sendChunk(Player p, int chunkX, int chunkZ){ + @Override + public void sendChunk(Player p, int chunkX, int chunkZ) { ((CraftPlayer)p).getHandle().playerConnection.sendPacket(new PacketPlayOutMapChunk(((CraftChunk)p.getWorld().getChunkAt(chunkX, chunkZ)).getHandle(), 65535)); } + + @SuppressWarnings("deprecation") + @Override + public double[] getSpigotTPS() { + return MinecraftServer.getServer().recentTps; + } } diff --git a/SpigotCore_9/src/de/steamwar/core/SpigotTPS_9.java b/SpigotCore_9/src/de/steamwar/core/SpigotTPS_9.java deleted file mode 100644 index 6a0ba28..0000000 --- a/SpigotCore_9/src/de/steamwar/core/SpigotTPS_9.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - This file is a part of the SteamWar software. - - Copyright (C) 2020 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.core; - -import net.minecraft.server.v1_9_R2.MinecraftServer; - -public class SpigotTPS_9 { - - private SpigotTPS_9(){} - - static double[] getTps(){ - return MinecraftServer.getServer().recentTps; - } - -} diff --git a/SpigotCore_API/build.gradle b/SpigotCore_API/build.gradle deleted file mode 100644 index f2bf8a1..0000000 --- a/SpigotCore_API/build.gradle +++ /dev/null @@ -1,52 +0,0 @@ -/* - * This file is a part of the SteamWar software. - * - * Copyright (C) 2020 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 . - */ - -plugins { - id 'base' - id 'java' -} - -group 'steamwar' -version '1.0' - -compileJava.options.encoding = 'UTF-8' - -sourceCompatibility = 1.8 -targetCompatibility = 1.8 - -sourceSets { - main { - java { - srcDirs = ['src/'] - } - resources { - srcDirs = ['src/'] - exclude '**/*.java', '**/*.kt' - } - } -} - -dependencies { - compileOnly 'org.projectlombok:lombok:1.18.6' - testCompileOnly 'org.projectlombok:lombok:1.18.6' - annotationProcessor 'org.projectlombok:lombok:1.18.6' - testAnnotationProcessor 'org.projectlombok:lombok:1.18.6' - - compileOnly files("${project.rootDir}/lib/Spigot-1.15.jar") -} \ No newline at end of file diff --git a/SpigotCore_API/settings.gradle b/SpigotCore_API/settings.gradle deleted file mode 100644 index ada3e44..0000000 --- a/SpigotCore_API/settings.gradle +++ /dev/null @@ -1,20 +0,0 @@ -/* - * This file is a part of the SteamWar software. - * - * Copyright (C) 2020 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 . - */ - -rootProject.name = 'SpigotCore_API' \ No newline at end of file diff --git a/SpigotCore_Main/build.gradle b/SpigotCore_Main/build.gradle index 78a10e1..06f85b7 100644 --- a/SpigotCore_Main/build.gradle +++ b/SpigotCore_Main/build.gradle @@ -43,14 +43,6 @@ sourceSets { } dependencies { - implementation project(":SpigotCore_8") - implementation project(":SpigotCore_9") - implementation project(":SpigotCore_10") - implementation project(":SpigotCore_12") - implementation project(":SpigotCore_14") - implementation project(":SpigotCore_15") - implementation project(":SpigotCore_API") - compileOnly 'org.projectlombok:lombok:1.18.6' testCompileOnly 'org.projectlombok:lombok:1.18.6' annotationProcessor 'org.projectlombok:lombok:1.18.6' @@ -58,7 +50,6 @@ dependencies { compileOnly files("${project.rootDir}/lib/Spigot-1.15.jar") compileOnly files("${project.rootDir}/lib/WorldEdit-1.12.jar") - compileOnly files("${project.rootDir}/lib/ProtocolLib.jar") compileOnly 'net.wesjd:anvilgui:1.4.0-SNAPSHOT' } diff --git a/SpigotCore_Main/src/com/comphenix/tinyprotocol/Reflection.java b/SpigotCore_Main/src/com/comphenix/tinyprotocol/Reflection.java new file mode 100644 index 0000000..1e18232 --- /dev/null +++ b/SpigotCore_Main/src/com/comphenix/tinyprotocol/Reflection.java @@ -0,0 +1,411 @@ +package com.comphenix.tinyprotocol; + +import org.bukkit.Bukkit; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * An utility class that simplifies reflection in Bukkit plugins. + * + * @author Kristian + */ +public final class Reflection { + /** + * An interface for invoking a specific constructor. + */ + public interface ConstructorInvoker { + /** + * Invoke a constructor for a specific class. + * + * @param arguments - the arguments to pass to the constructor. + * @return The constructed object. + */ + public Object invoke(Object... arguments); + } + + /** + * An interface for invoking a specific method. + */ + public interface MethodInvoker { + /** + * Invoke a method on a specific target object. + * + * @param target - the target object, or NULL for a static method. + * @param arguments - the arguments to pass to the method. + * @return The return value, or NULL if is void. + */ + public Object invoke(Object target, Object... arguments); + } + + /** + * An interface for retrieving the field content. + * + * @param - field type. + */ + public interface FieldAccessor { + /** + * Retrieve the content of a field. + * + * @param target - the target object, or NULL for a static field. + * @return The value of the field. + */ + public T get(Object target); + + /** + * Set the content of a field. + * + * @param target - the target object, or NULL for a static field. + * @param value - the new value of the field. + */ + public void set(Object target, Object value); + + /** + * Determine if the given object has this field. + * + * @param target - the object to test. + * @return TRUE if it does, FALSE otherwise. + */ + public boolean hasField(Object target); + } + + // Deduce the net.minecraft.server.v* package + private static String OBC_PREFIX = Bukkit.getServer().getClass().getPackage().getName(); + private static String NMS_PREFIX = OBC_PREFIX.replace("org.bukkit.craftbukkit", "net.minecraft.server"); + private static String VERSION = OBC_PREFIX.replace("org.bukkit.craftbukkit", "").replace(".", ""); + + // Variable replacement + private static Pattern MATCH_VARIABLE = Pattern.compile("\\{([^\\}]+)\\}"); + + private Reflection() { + // Seal class + } + + /** + * Retrieve a field accessor for a specific field type and name. + * + * @param target - the target type. + * @param name - the name of the field, or NULL to ignore. + * @param fieldType - a compatible field type. + * @return The field accessor. + */ + public static FieldAccessor getField(Class target, String name, Class fieldType) { + return getField(target, name, fieldType, 0); + } + + /** + * Retrieve a field accessor for a specific field type and name. + * + * @param className - lookup name of the class, see {@link #getClass(String)}. + * @param name - the name of the field, or NULL to ignore. + * @param fieldType - a compatible field type. + * @return The field accessor. + */ + public static FieldAccessor getField(String className, String name, Class fieldType) { + return getField(getClass(className), name, fieldType, 0); + } + + /** + * Retrieve a field accessor for a specific field type and name. + * + * @param target - the target type. + * @param fieldType - a compatible field type. + * @param index - the number of compatible fields to skip. + * @return The field accessor. + */ + public static FieldAccessor getField(Class target, Class fieldType, int index) { + return getField(target, null, fieldType, index); + } + + /** + * Retrieve a field accessor for a specific field type and name. + * + * @param className - lookup name of the class, see {@link #getClass(String)}. + * @param fieldType - a compatible field type. + * @param index - the number of compatible fields to skip. + * @return The field accessor. + */ + public static FieldAccessor getField(String className, Class fieldType, int index) { + return getField(getClass(className), fieldType, index); + } + + // Common method + private static FieldAccessor getField(Class target, String name, Class fieldType, int index) { + for (final Field field : target.getDeclaredFields()) { + if ((name == null || field.getName().equals(name)) && fieldType.isAssignableFrom(field.getType()) && index-- <= 0) { + field.setAccessible(true); + + // A function for retrieving a specific field value + return new FieldAccessor() { + + @Override + @SuppressWarnings("unchecked") + public T get(Object target) { + try { + return (T) field.get(target); + } catch (IllegalAccessException e) { + throw new RuntimeException("Cannot access reflection.", e); + } + } + + @Override + public void set(Object target, Object value) { + try { + field.set(target, value); + } catch (IllegalAccessException e) { + throw new RuntimeException("Cannot access reflection.", e); + } + } + + @Override + public boolean hasField(Object target) { + // target instanceof DeclaringClass + return field.getDeclaringClass().isAssignableFrom(target.getClass()); + } + }; + } + } + + // Search in parent classes + if (target.getSuperclass() != null) + return getField(target.getSuperclass(), name, fieldType, index); + + throw new IllegalArgumentException("Cannot find field with type " + fieldType); + } + + /** + * Search for the first publicly and privately defined method of the given name and parameter count. + * + * @param className - lookup name of the class, see {@link #getClass(String)}. + * @param methodName - the method name, or NULL to skip. + * @param params - the expected parameters. + * @return An object that invokes this specific method. + * @throws IllegalStateException If we cannot find this method. + */ + public static MethodInvoker getMethod(String className, String methodName, Class... params) { + return getTypedMethod(getClass(className), methodName, null, params); + } + + /** + * Search for the first publicly and privately defined method of the given name and parameter count. + * + * @param clazz - a class to start with. + * @param methodName - the method name, or NULL to skip. + * @param params - the expected parameters. + * @return An object that invokes this specific method. + * @throws IllegalStateException If we cannot find this method. + */ + public static MethodInvoker getMethod(Class clazz, String methodName, Class... params) { + return getTypedMethod(clazz, methodName, null, params); + } + + /** + * Search for the first publicly and privately defined method of the given name and parameter count. + * + * @param clazz - a class to start with. + * @param methodName - the method name, or NULL to skip. + * @param returnType - the expected return type, or NULL to ignore. + * @param params - the expected parameters. + * @return An object that invokes this specific method. + * @throws IllegalStateException If we cannot find this method. + */ + public static MethodInvoker getTypedMethod(Class clazz, String methodName, Class returnType, Class... params) { + for (final Method method : clazz.getDeclaredMethods()) { + if ((methodName == null || method.getName().equals(methodName)) + && (returnType == null || method.getReturnType().equals(returnType)) + && Arrays.equals(method.getParameterTypes(), params)) { + method.setAccessible(true); + + return new MethodInvoker() { + + @Override + public Object invoke(Object target, Object... arguments) { + try { + return method.invoke(target, arguments); + } catch (Exception e) { + throw new RuntimeException("Cannot invoke method " + method, e); + } + } + + }; + } + } + + // Search in every superclass + if (clazz.getSuperclass() != null) + return getMethod(clazz.getSuperclass(), methodName, params); + + throw new IllegalStateException(String.format("Unable to find method %s (%s).", methodName, Arrays.asList(params))); + } + + /** + * Search for the first publically and privately defined constructor of the given name and parameter count. + * + * @param className - lookup name of the class, see {@link #getClass(String)}. + * @param params - the expected parameters. + * @return An object that invokes this constructor. + * @throws IllegalStateException If we cannot find this method. + */ + public static ConstructorInvoker getConstructor(String className, Class... params) { + return getConstructor(getClass(className), params); + } + + /** + * Search for the first publically and privately defined constructor of the given name and parameter count. + * + * @param clazz - a class to start with. + * @param params - the expected parameters. + * @return An object that invokes this constructor. + * @throws IllegalStateException If we cannot find this method. + */ + public static ConstructorInvoker getConstructor(Class clazz, Class... params) { + for (final Constructor constructor : clazz.getDeclaredConstructors()) { + if (Arrays.equals(constructor.getParameterTypes(), params)) { + constructor.setAccessible(true); + + return new ConstructorInvoker() { + + @Override + public Object invoke(Object... arguments) { + try { + return constructor.newInstance(arguments); + } catch (Exception e) { + throw new RuntimeException("Cannot invoke constructor " + constructor, e); + } + } + + }; + } + } + + throw new IllegalStateException(String.format("Unable to find constructor for %s (%s).", clazz, Arrays.asList(params))); + } + + /** + * Retrieve a class from its full name, without knowing its type on compile time. + *

+ * This is useful when looking up fields by a NMS or OBC type. + *

+ * + * @see {@link #getClass()} for more information. + * @param lookupName - the class name with variables. + * @return The class. + */ + public static Class getUntypedClass(String lookupName) { + @SuppressWarnings({ "rawtypes", "unchecked" }) + Class clazz = (Class) getClass(lookupName); + return clazz; + } + + /** + * Retrieve a class from its full name. + *

+ * Strings enclosed with curly brackets - such as {TEXT} - will be replaced according to the following table: + *

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
VariableContent
{nms}Actual package name of net.minecraft.server.VERSION
{obc}Actual pacakge name of org.bukkit.craftbukkit.VERSION
{version}The current Minecraft package VERSION, if any.
+ * + * @param lookupName - the class name with variables. + * @return The looked up class. + * @throws IllegalArgumentException If a variable or class could not be found. + */ + public static Class getClass(String lookupName) { + return getCanonicalClass(expandVariables(lookupName)); + } + + /** + * Retrieve a class in the net.minecraft.server.VERSION.* package. + * + * @param name - the name of the class, excluding the package. + * @throws IllegalArgumentException If the class doesn't exist. + */ + public static Class getMinecraftClass(String name) { + return getCanonicalClass(NMS_PREFIX + "." + name); + } + + /** + * Retrieve a class in the org.bukkit.craftbukkit.VERSION.* package. + * + * @param name - the name of the class, excluding the package. + * @throws IllegalArgumentException If the class doesn't exist. + */ + public static Class getCraftBukkitClass(String name) { + return getCanonicalClass(OBC_PREFIX + "." + name); + } + + /** + * Retrieve a class by its canonical name. + * + * @param canonicalName - the canonical name. + * @return The class. + */ + private static Class getCanonicalClass(String canonicalName) { + try { + return Class.forName(canonicalName); + } catch (ClassNotFoundException e) { + throw new IllegalArgumentException("Cannot find " + canonicalName, e); + } + } + + /** + * Expand variables such as "{nms}" and "{obc}" to their corresponding packages. + * + * @param name - the full name of the class. + * @return The expanded string. + */ + private static String expandVariables(String name) { + StringBuffer output = new StringBuffer(); + Matcher matcher = MATCH_VARIABLE.matcher(name); + + while (matcher.find()) { + String variable = matcher.group(1); + String replacement = ""; + + // Expand all detected variables + if ("nms".equalsIgnoreCase(variable)) + replacement = NMS_PREFIX; + else if ("obc".equalsIgnoreCase(variable)) + replacement = OBC_PREFIX; + else if ("version".equalsIgnoreCase(variable)) + replacement = VERSION; + else + throw new IllegalArgumentException("Unknown variable: " + variable); + + // Assume the expanded variables are all packages, and append a dot + if (replacement.length() > 0 && matcher.end() < name.length() && name.charAt(matcher.end()) != '.') + replacement += "."; + matcher.appendReplacement(output, Matcher.quoteReplacement(replacement)); + } + + matcher.appendTail(output); + return output.toString(); + } + + public static Object newInstance(Class clazz) { + try { + return clazz.newInstance(); + } catch (InstantiationException | IllegalAccessException e) { + throw new SecurityException("Could not create object", e); + } + } +} diff --git a/SpigotCore_Main/src/com/comphenix/tinyprotocol/TinyProtocol.java b/SpigotCore_Main/src/com/comphenix/tinyprotocol/TinyProtocol.java new file mode 100644 index 0000000..3f754f3 --- /dev/null +++ b/SpigotCore_Main/src/com/comphenix/tinyprotocol/TinyProtocol.java @@ -0,0 +1,509 @@ +package com.comphenix.tinyprotocol; + +import com.comphenix.tinyprotocol.Reflection.FieldAccessor; +import com.comphenix.tinyprotocol.Reflection.MethodInvoker; +import com.google.common.collect.Lists; +import com.google.common.collect.MapMaker; +import com.mojang.authlib.GameProfile; +import io.netty.channel.*; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.HandlerList; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerLoginEvent; +import org.bukkit.event.server.PluginDisableEvent; +import org.bukkit.plugin.Plugin; +import org.bukkit.scheduler.BukkitRunnable; + +import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.logging.Level; + +/** + * Represents a very tiny alternative to ProtocolLib. + *

+ * It now supports intercepting packets during login and status ping (such as OUT_SERVER_PING)! + * + * @author Kristian + */ +public abstract class TinyProtocol { + private static final AtomicInteger ID = new AtomicInteger(0); + + // Used in order to lookup a channel + private static final MethodInvoker getPlayerHandle = Reflection.getMethod("{obc}.entity.CraftPlayer", "getHandle"); + private static final FieldAccessor getConnection = Reflection.getField("{nms}.EntityPlayer", "playerConnection", Object.class); + private static final FieldAccessor getManager = Reflection.getField("{nms}.PlayerConnection", "networkManager", Object.class); + private static final FieldAccessor getChannel = Reflection.getField("{nms}.NetworkManager", Channel.class, 0); + + // Looking up ServerConnection + private static final Class minecraftServerClass = Reflection.getUntypedClass("{nms}.MinecraftServer"); + private static final Class serverConnectionClass = Reflection.getUntypedClass("{nms}.ServerConnection"); + private static final FieldAccessor getMinecraftServer = Reflection.getField("{obc}.CraftServer", minecraftServerClass, 0); + private static final FieldAccessor getServerConnection = Reflection.getField(minecraftServerClass, serverConnectionClass, 0); + private static final MethodInvoker getNetworkMarkers = Reflection.getTypedMethod(serverConnectionClass, null, List.class, serverConnectionClass); + + // Packets we have to intercept + private static final Class PACKET_LOGIN_IN_START = Reflection.getMinecraftClass("PacketLoginInStart"); + private static final FieldAccessor getGameProfile = Reflection.getField(PACKET_LOGIN_IN_START, GameProfile.class, 0); + + // Speedup channel lookup + private Map channelLookup = new MapMaker().weakValues().makeMap(); + private Listener listener; + + // Channels that have already been removed + private Set uninjectedChannels = Collections.newSetFromMap(new MapMaker().weakKeys().makeMap()); + + // List of network markers + private List networkManagers; + + // Injected channel handlers + private List serverChannels = Lists.newArrayList(); + private ChannelInboundHandlerAdapter serverChannelHandler; + private ChannelInitializer beginInitProtocol; + private ChannelInitializer endInitProtocol; + + // Current handler name + private String handlerName; + + protected volatile boolean closed; + protected Plugin plugin; + + /** + * Construct a new instance of TinyProtocol, and start intercepting packets for all connected clients and future clients. + *

+ * You can construct multiple instances per plugin. + * + * @param plugin - the plugin. + */ + public TinyProtocol(final Plugin plugin) { + this.plugin = plugin; + + // Compute handler name + this.handlerName = getHandlerName(); + + // Prepare existing players + registerBukkitEvents(); + + try { + registerChannelHandler(); + registerPlayers(plugin); + } catch (IllegalArgumentException ex) { + // Damn you, late bind + plugin.getLogger().info("[TinyProtocol] Delaying server channel injection due to late bind."); + + new BukkitRunnable() { + @Override + public void run() { + registerChannelHandler(); + registerPlayers(plugin); + plugin.getLogger().info("[TinyProtocol] Late bind injection successful."); + } + }.runTask(plugin); + } + } + + private void createServerChannelHandler() { + // Handle connected channels + endInitProtocol = new ChannelInitializer() { + + @Override + protected void initChannel(Channel channel) throws Exception { + try { + // This can take a while, so we need to stop the main thread from interfering + synchronized (networkManagers) { + // Stop injecting channels + if (!closed) { + channel.eventLoop().submit(() -> injectChannelInternal(channel)); + } + } + } catch (Exception e) { + plugin.getLogger().log(Level.SEVERE, "Cannot inject incomming channel " + channel, e); + } + } + + }; + + // This is executed before Minecraft's channel handler + beginInitProtocol = new ChannelInitializer() { + + @Override + protected void initChannel(Channel channel) throws Exception { + channel.pipeline().addLast(endInitProtocol); + } + + }; + + serverChannelHandler = new ChannelInboundHandlerAdapter() { + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + Channel channel = (Channel) msg; + + // Prepare to initialize ths channel + channel.pipeline().addFirst(beginInitProtocol); + ctx.fireChannelRead(msg); + } + + }; + } + + /** + * Register bukkit events. + */ + private void registerBukkitEvents() { + listener = new Listener() { + + @EventHandler(priority = EventPriority.LOWEST) + public final void onPlayerLogin(PlayerLoginEvent e) { + if (closed) + return; + + Channel channel = getChannel(e.getPlayer()); + + // Don't inject players that have been explicitly uninjected + if (!uninjectedChannels.contains(channel)) { + injectPlayer(e.getPlayer()); + } + } + + @EventHandler + public final void onPluginDisable(PluginDisableEvent e) { + if (e.getPlugin().equals(plugin)) { + close(); + } + } + + }; + + plugin.getServer().getPluginManager().registerEvents(listener, plugin); + } + + @SuppressWarnings("unchecked") + private void registerChannelHandler() { + Object mcServer = getMinecraftServer.get(Bukkit.getServer()); + Object serverConnection = getServerConnection.get(mcServer); + boolean looking = true; + + // We need to synchronize against this list + networkManagers = (List) getNetworkMarkers.invoke(null, serverConnection); + createServerChannelHandler(); + + // Find the correct list, or implicitly throw an exception + for (int i = 0; looking; i++) { + List list = Reflection.getField(serverConnection.getClass(), List.class, i).get(serverConnection); + + for (Object item : list) { + if (!ChannelFuture.class.isInstance(item)) + break; + + // Channel future that contains the server connection + Channel serverChannel = ((ChannelFuture) item).channel(); + + serverChannels.add(serverChannel); + serverChannel.pipeline().addFirst(serverChannelHandler); + looking = false; + } + } + } + + private void unregisterChannelHandler() { + if (serverChannelHandler == null) + return; + + for (Channel serverChannel : serverChannels) { + final ChannelPipeline pipeline = serverChannel.pipeline(); + + // Remove channel handler + serverChannel.eventLoop().execute(new Runnable() { + + @Override + public void run() { + try { + pipeline.remove(serverChannelHandler); + } catch (NoSuchElementException e) { + // That's fine + } + } + + }); + } + } + + private void registerPlayers(Plugin plugin) { + for (Player player : plugin.getServer().getOnlinePlayers()) { + injectPlayer(player); + } + } + + /** + * Invoked when the server is starting to send a packet to a player. + *

+ * Note that this is not executed on the main thread. + * + * @param receiver - the receiving player, NULL for early login/status packets. + * @param channel - the channel that received the packet. Never NULL. + * @param packet - the packet being sent. + * @return The packet to send instead, or NULL to cancel the transmission. + */ + public Object onPacketOutAsync(Player receiver, Channel channel, Object packet) { + return packet; + } + + /** + * Invoked when the server has received a packet from a given player. + *

+ * Use {@link Channel#remoteAddress()} to get the remote address of the client. + * + * @param sender - the player that sent the packet, NULL for early login/status packets. + * @param channel - channel that received the packet. Never NULL. + * @param packet - the packet being received. + * @return The packet to recieve instead, or NULL to cancel. + */ + public Object onPacketInAsync(Player sender, Channel channel, Object packet) { + return packet; + } + + /** + * Send a packet to a particular player. + *

+ * Note that {@link #onPacketOutAsync(Player, Channel, Object)} will be invoked with this packet. + * + * @param player - the destination player. + * @param packet - the packet to send. + */ + public void sendPacket(Player player, Object packet) { + sendPacket(getChannel(player), packet); + } + + /** + * Send a packet to a particular client. + *

+ * Note that {@link #onPacketOutAsync(Player, Channel, Object)} will be invoked with this packet. + * + * @param channel - client identified by a channel. + * @param packet - the packet to send. + */ + public void sendPacket(Channel channel, Object packet) { + channel.pipeline().writeAndFlush(packet); + } + + /** + * Pretend that a given packet has been received from a player. + *

+ * Note that {@link #onPacketInAsync(Player, Channel, Object)} will be invoked with this packet. + * + * @param player - the player that sent the packet. + * @param packet - the packet that will be received by the server. + */ + public void receivePacket(Player player, Object packet) { + receivePacket(getChannel(player), packet); + } + + /** + * Pretend that a given packet has been received from a given client. + *

+ * Note that {@link #onPacketInAsync(Player, Channel, Object)} will be invoked with this packet. + * + * @param channel - client identified by a channel. + * @param packet - the packet that will be received by the server. + */ + public void receivePacket(Channel channel, Object packet) { + channel.pipeline().context("encoder").fireChannelRead(packet); + } + + /** + * Retrieve the name of the channel injector, default implementation is "tiny-" + plugin name + "-" + a unique ID. + *

+ * Note that this method will only be invoked once. It is no longer necessary to override this to support multiple instances. + * + * @return A unique channel handler name. + */ + protected String getHandlerName() { + return "tiny-" + plugin.getName() + "-" + ID.incrementAndGet(); + } + + /** + * Add a custom channel handler to the given player's channel pipeline, allowing us to intercept sent and received packets. + *

+ * This will automatically be called when a player has logged in. + * + * @param player - the player to inject. + */ + public void injectPlayer(Player player) { + injectChannelInternal(getChannel(player)).player = player; + } + + /** + * Add a custom channel handler to the given channel. + * + * @param channel - the channel to inject. + * @return The intercepted channel, or NULL if it has already been injected. + */ + public void injectChannel(Channel channel) { + injectChannelInternal(channel); + } + + /** + * Add a custom channel handler to the given channel. + * + * @param channel - the channel to inject. + * @return The packet interceptor. + */ + private PacketInterceptor injectChannelInternal(Channel channel) { + try { + PacketInterceptor interceptor = (PacketInterceptor) channel.pipeline().get(handlerName); + + // Inject our packet interceptor + if (interceptor == null) { + interceptor = new PacketInterceptor(); + channel.pipeline().addBefore("packet_handler", handlerName, interceptor); + uninjectedChannels.remove(channel); + } + + return interceptor; + } catch (IllegalArgumentException e) { + // Try again + return (PacketInterceptor) channel.pipeline().get(handlerName); + } + } + + /** + * Retrieve the Netty channel associated with a player. This is cached. + * + * @param player - the player. + * @return The Netty channel. + */ + public Channel getChannel(Player player) { + Channel channel = channelLookup.get(player.getName()); + + // Lookup channel again + if (channel == null) { + Object connection = getConnection.get(getPlayerHandle.invoke(player)); + Object manager = getManager.get(connection); + + channelLookup.put(player.getName(), channel = getChannel.get(manager)); + } + + return channel; + } + + /** + * Uninject a specific player. + * + * @param player - the injected player. + */ + public void uninjectPlayer(Player player) { + uninjectChannel(getChannel(player)); + } + + /** + * Uninject a specific channel. + *

+ * This will also disable the automatic channel injection that occurs when a player has properly logged in. + * + * @param channel - the injected channel. + */ + public void uninjectChannel(final Channel channel) { + // No need to guard against this if we're closing + if (!closed) { + uninjectedChannels.add(channel); + } + + // See ChannelInjector in ProtocolLib, line 590 + channel.eventLoop().execute(new Runnable() { + + @Override + public void run() { + channel.pipeline().remove(handlerName); + } + + }); + } + + /** + * Determine if the given player has been injected by TinyProtocol. + * + * @param player - the player. + * @return TRUE if it is, FALSE otherwise. + */ + public boolean hasInjected(Player player) { + return hasInjected(getChannel(player)); + } + + /** + * Determine if the given channel has been injected by TinyProtocol. + * + * @param channel - the channel. + * @return TRUE if it is, FALSE otherwise. + */ + public boolean hasInjected(Channel channel) { + return channel.pipeline().get(handlerName) != null; + } + + /** + * Cease listening for packets. This is called automatically when your plugin is disabled. + */ + public final void close() { + if (!closed) { + closed = true; + + // Remove our handlers + for (Player player : plugin.getServer().getOnlinePlayers()) { + uninjectPlayer(player); + } + + // Clean up Bukkit + HandlerList.unregisterAll(listener); + unregisterChannelHandler(); + } + } + + /** + * Channel handler that is inserted into the player's channel pipeline, allowing us to intercept sent and received packets. + * + * @author Kristian + */ + private final class PacketInterceptor extends ChannelDuplexHandler { + // Updated by the login event + public volatile Player player; + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + // Intercept channel + final Channel channel = ctx.channel(); + handleLoginStart(channel, msg); + + try { + msg = onPacketInAsync(player, channel, msg); + } catch (Exception e) { + plugin.getLogger().log(Level.SEVERE, "Error in onPacketInAsync().", e); + } + + if (msg != null) { + super.channelRead(ctx, msg); + } + } + + @Override + public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { + try { + msg = onPacketOutAsync(player, ctx.channel(), msg); + } catch (Exception e) { + plugin.getLogger().log(Level.SEVERE, "Error in onPacketOutAsync().", e); + } + + if (msg != null) { + super.write(ctx, msg, promise); + } + } + + private void handleLoginStart(Channel channel, Object packet) { + if (PACKET_LOGIN_IN_START.isInstance(packet)) { + GameProfile profile = getGameProfile.get(packet); + channelLookup.put(profile.getName(), channel); + } + } + } +} diff --git a/SpigotCore_15/src/de/steamwar/authlib/AuthlibInjector_15.java b/SpigotCore_Main/src/de/steamwar/authlib/AuthlibInjector_15.java similarity index 100% rename from SpigotCore_15/src/de/steamwar/authlib/AuthlibInjector_15.java rename to SpigotCore_Main/src/de/steamwar/authlib/AuthlibInjector_15.java diff --git a/SpigotCore_Main/src/de/steamwar/comms/BungeeReceiver.java b/SpigotCore_Main/src/de/steamwar/comms/BungeeReceiver.java index 594e82b..021414e 100644 --- a/SpigotCore_Main/src/de/steamwar/comms/BungeeReceiver.java +++ b/SpigotCore_Main/src/de/steamwar/comms/BungeeReceiver.java @@ -23,8 +23,9 @@ import com.google.common.io.ByteArrayDataInput; import com.google.common.io.ByteStreams; import de.steamwar.comms.handlers.BungeeHandler; import de.steamwar.comms.handlers.InventoryHandler; -import de.steamwar.core.VersionedRunnable; -import de.steamwar.sql.*; +import de.steamwar.core.BountifulWrapper; +import de.steamwar.sql.BauweltMember; +import de.steamwar.sql.SteamwarUser; import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.plugin.messaging.PluginMessageListener; @@ -46,8 +47,7 @@ public class BungeeReceiver implements PluginMessageListener { UUID uuid = SteamwarUser.get(byteArrayDataInput.readInt()).getUUID(); if(Bukkit.getPlayer(uuid).isOnline()) { Player player = Bukkit.getPlayer(uuid); - VersionedRunnable.call(new VersionedRunnable(() -> BungeeReceiver_8.playPling(player), 8), - new VersionedRunnable(() -> BungeeReceiver_9.playpling(player), 9)); + BountifulWrapper.impl.playPling(player); } }); diff --git a/SpigotCore_Main/src/de/steamwar/core/BountifulWrapper.java b/SpigotCore_Main/src/de/steamwar/core/BountifulWrapper.java new file mode 100644 index 0000000..26069de --- /dev/null +++ b/SpigotCore_Main/src/de/steamwar/core/BountifulWrapper.java @@ -0,0 +1,32 @@ +/* + This file is a part of the SteamWar software. + + Copyright (C) 2020 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.core; + +import org.bukkit.entity.Player; + +public class BountifulWrapper { + private BountifulWrapper() {} + + public static final IBountifulWrapper impl = VersionDependent.getVersionImpl(Core.getInstance()); + + public interface IBountifulWrapper { + void playPling(Player player); + } +} diff --git a/SpigotCore_Main/src/de/steamwar/core/CraftbukkitWrapper.java b/SpigotCore_Main/src/de/steamwar/core/CraftbukkitWrapper.java new file mode 100644 index 0000000..f3ad54e --- /dev/null +++ b/SpigotCore_Main/src/de/steamwar/core/CraftbukkitWrapper.java @@ -0,0 +1,33 @@ +/* + This file is a part of the SteamWar software. + + Copyright (C) 2021 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.core; + +import org.bukkit.entity.Player; + +public class CraftbukkitWrapper { + private CraftbukkitWrapper() {} + + public static final ICraftbukkitWrapper impl = VersionDependent.getVersionImpl(Core.getInstance()); + + public interface ICraftbukkitWrapper { + void sendChunk(Player p, int chunkX, int chunkZ); + double[] getSpigotTPS(); + } +} diff --git a/SpigotCore_8/src/de/steamwar/inventory/SWItem_8.java b/SpigotCore_Main/src/de/steamwar/core/FlatteningWrapper.java similarity index 50% rename from SpigotCore_8/src/de/steamwar/inventory/SWItem_8.java rename to SpigotCore_Main/src/de/steamwar/core/FlatteningWrapper.java index 746134f..17179b8 100644 --- a/SpigotCore_8/src/de/steamwar/inventory/SWItem_8.java +++ b/SpigotCore_Main/src/de/steamwar/core/FlatteningWrapper.java @@ -1,6 +1,6 @@ -/* +/* This file is a part of the SteamWar software. - + Copyright (C) 2020 SteamWar.de-Serverteam This program is free software: you can redistribute it and/or modify @@ -17,33 +17,31 @@ along with this program. If not, see . */ -package de.steamwar.inventory; +package de.steamwar.core; +import com.sk89q.worldedit.extent.clipboard.Clipboard; import org.bukkit.Material; +import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.SkullMeta; -class SWItem_8 { - private SWItem_8(){} +import java.io.IOException; +import java.io.InputStream; - static Material getMaterial(String material){ - try{ - return Material.valueOf(material); - }catch(IllegalArgumentException e){ - return Material.STONE; - } - } +public class FlatteningWrapper { + private FlatteningWrapper() {} - static Material getDye(){ - return Material.INK_SACK; - } + public static final IFlatteningWrapper impl = VersionDependent.getVersionImpl(Core.getInstance()); + + public interface IFlatteningWrapper { + void setScoreboardTitle(Object packet, String title); + + Material getMaterial(String material); + Material getDye(int colorCode); + ItemStack setSkullOwner(String player); + + byte[] getPlayerClipboard(Player player, boolean schemFormat); + void setPlayerClipboard(Player player, InputStream is, boolean schemFormat); + Clipboard getClipboard(InputStream is, boolean schemFormat) throws IOException; - static ItemStack setSkullOwner(String player){ - ItemStack head = new ItemStack(Material.SKULL_ITEM, 1, (short) 3); - SkullMeta headmeta = (SkullMeta) head.getItemMeta(); - headmeta.setOwner(player); - headmeta.setDisplayName(player); - head.setItemMeta(headmeta); - return head; } } diff --git a/SpigotCore_Main/src/de/steamwar/core/TPSWatcher.java b/SpigotCore_Main/src/de/steamwar/core/TPSWatcher.java index cb92fcf..826213c 100644 --- a/SpigotCore_Main/src/de/steamwar/core/TPSWatcher.java +++ b/SpigotCore_Main/src/de/steamwar/core/TPSWatcher.java @@ -79,12 +79,7 @@ public class TPSWatcher { } private static double[] getSpigotTPS() { - return VersionedCallable.call(new VersionedCallable<>(SpigotTPS_8::getTps, 8), - new VersionedCallable<>(SpigotTPS_9::getTps, 9), - new VersionedCallable<>(SpigotTPS_10::getTps, 10), - new VersionedCallable<>(SpigotTPS_12::getTps, 12), - new VersionedCallable<>(SpigotTPS_14::getTps, 14), - new VersionedCallable<>(SpigotTPS_15::getTps, 15)); + return CraftbukkitWrapper.impl.getSpigotTPS(); } private static double round(double d) { diff --git a/SpigotCore_Main/src/de/steamwar/core/VersionDependent.java b/SpigotCore_Main/src/de/steamwar/core/VersionDependent.java new file mode 100644 index 0000000..5e8ec24 --- /dev/null +++ b/SpigotCore_Main/src/de/steamwar/core/VersionDependent.java @@ -0,0 +1,46 @@ +/* + This file is a part of the SteamWar software. + + Copyright (C) 2021 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.core; + +import org.bukkit.plugin.Plugin; + +import java.lang.reflect.InvocationTargetException; + +public class VersionDependent { + private VersionDependent() {} + + public static T getVersionImpl(Plugin plugin) { + return getVersionImpl(plugin, (new Exception()).getStackTrace()[1].getClassName()); + } + + public static T getVersionImpl(Plugin plugin, String className){ + ClassLoader loader = plugin.getClass().getClassLoader(); + for(int version = Core.getVersion(); version >= 8; version--) { + try { + return ((Class) Class.forName(className + version, true, loader)).getDeclaredConstructor().newInstance(); + } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { + throw new SecurityException("Could not load version dependent class", e); + } catch (ClassNotFoundException e) { + // try next version + } + } + throw new SecurityException("Unable to find version dependent implementation for " + className); + } +} diff --git a/SpigotCore_Main/src/de/steamwar/core/VersionedCallable.java b/SpigotCore_Main/src/de/steamwar/core/VersionedCallable.java index 2846fb1..0da1b6f 100644 --- a/SpigotCore_Main/src/de/steamwar/core/VersionedCallable.java +++ b/SpigotCore_Main/src/de/steamwar/core/VersionedCallable.java @@ -33,6 +33,7 @@ public class VersionedCallable { this.minVersion = minVersion; } + @Deprecated public static T call(VersionedCallable... versionedCallables) { for (int i = versionedCallables.length - 1; i >= 0; i--) { VersionedCallable versionedCallable = versionedCallables[i]; diff --git a/SpigotCore_Main/src/de/steamwar/core/VersionedRunnable.java b/SpigotCore_Main/src/de/steamwar/core/VersionedRunnable.java index fc65517..604169a 100644 --- a/SpigotCore_Main/src/de/steamwar/core/VersionedRunnable.java +++ b/SpigotCore_Main/src/de/steamwar/core/VersionedRunnable.java @@ -31,6 +31,7 @@ public class VersionedRunnable { this.minVersion = minVersion; } + @Deprecated public static void call(VersionedRunnable... versionedRunnables) { for (int i = versionedRunnables.length - 1; i >= 0; i--) { VersionedRunnable versionedRunnable = versionedRunnables[i]; diff --git a/SpigotCore_Main/src/de/steamwar/core/WorldOfColorWrapper.java b/SpigotCore_Main/src/de/steamwar/core/WorldOfColorWrapper.java new file mode 100644 index 0000000..70f7269 --- /dev/null +++ b/SpigotCore_Main/src/de/steamwar/core/WorldOfColorWrapper.java @@ -0,0 +1,34 @@ +/* + This file is a part of the SteamWar software. + + Copyright (C) 2020 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.core; + +import org.bukkit.entity.Player; + +import java.util.Locale; + +public class WorldOfColorWrapper { + private WorldOfColorWrapper() {} + + public static final IWorldOfColorWrapper impl = VersionDependent.getVersionImpl(Core.getInstance()); + + public interface IWorldOfColorWrapper { + Locale getLocale(Player player); + } +} diff --git a/SpigotCore_Main/src/de/steamwar/core/events/ChunkListener.java b/SpigotCore_Main/src/de/steamwar/core/events/ChunkListener.java index d6bf688..f61068c 100644 --- a/SpigotCore_Main/src/de/steamwar/core/events/ChunkListener.java +++ b/SpigotCore_Main/src/de/steamwar/core/events/ChunkListener.java @@ -19,64 +19,45 @@ package de.steamwar.core.events; -import com.comphenix.protocol.PacketType; -import com.comphenix.protocol.ProtocolLibrary; -import com.comphenix.protocol.events.PacketAdapter; -import com.comphenix.protocol.events.PacketContainer; -import com.comphenix.protocol.events.PacketEvent; -import com.comphenix.protocol.injector.server.TemporaryPlayer; -import com.comphenix.protocol.reflect.StructureModifier; -import de.steamwar.chunk.*; +import com.comphenix.tinyprotocol.Reflection; +import com.comphenix.tinyprotocol.TinyProtocol; import de.steamwar.core.Core; -import de.steamwar.core.VersionedRunnable; +import de.steamwar.core.CraftbukkitWrapper; import de.steamwar.sql.SteamwarUser; -import org.bukkit.Bukkit; +import io.netty.channel.Channel; import org.bukkit.entity.Player; -import java.util.logging.Level; - public class ChunkListener { private ChunkListener(){} + private static final Class mapChunkPacket = Reflection.getClass("{nms}.PacketPlayOutMapChunk"); + private static final Reflection.FieldAccessor fullChunk = Reflection.getField(mapChunkPacket, boolean.class, 0); + private static final Reflection.FieldAccessor chunkX = Reflection.getField(mapChunkPacket, int.class, 0); + private static final Reflection.FieldAccessor chunkZ = Reflection.getField(mapChunkPacket, int.class, 1); + + public static final TinyProtocol protocol = new TinyProtocol(Core.getInstance()){ + @Override + public Object onPacketOutAsync(Player receiver, Channel channel, Object packet) { + if ( + !mapChunkPacket.isInstance(packet) || + !SteamwarUser.get(receiver.getUniqueId()).isBedrock() || + fullChunk.get(packet) + ) + return packet; + + //TODO: Test ViaVersion prior or post + //TODO: Test if this can be done async? + //TODO: Nicer way: generate new and send new + CraftbukkitWrapper.impl.sendChunk(receiver, chunkX.get(packet), chunkZ.get(packet)); + return null; + } + }; + public static void init(){ - ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(Core.getInstance(), PacketType.Play.Server.MAP_CHUNK) { - @Override - public void onPacketSending(PacketEvent e) { - Player p = e.getPlayer(); - if(p instanceof TemporaryPlayer) - return; - - try{ - SteamwarUser user = SteamwarUser.get(p.getUniqueId()); - if(!user.isBedrock()) - return; - }catch(UnsupportedOperationException ex){ - Bukkit.getLogger().log(Level.SEVERE, "Could not get uuid", ex); - return; - } - - PacketContainer packet = e.getPacket(); - StructureModifier fullChunk = packet.getBooleans(); - if(fullChunk.read(0)) - return; - - e.setCancelled(true); - - StructureModifier ints = packet.getIntegers(); - int chunkX = ints.read(0); - int chunkZ = ints.read(1); - - sendChunk(p, chunkX, chunkZ); - } - }); + //triggering } - public static void sendChunk(Player p, int chunkX, int chunkZ){ - VersionedRunnable.call(new VersionedRunnable(() -> Chunk_8.sendChunk(p, chunkX, chunkZ), 8), - new VersionedRunnable(() -> Chunk_9.sendChunk(p, chunkX, chunkZ), 9), - new VersionedRunnable(() -> Chunk_10.sendChunk(p, chunkX, chunkZ), 10), - new VersionedRunnable(() -> Chunk_12.sendChunk(p, chunkX, chunkZ), 12), - new VersionedRunnable(() -> Chunk_14.sendChunk(p, chunkX, chunkZ), 14), - new VersionedRunnable(() -> Chunk_15.sendChunk(p, chunkX, chunkZ), 15)); + public static void sendChunk(Player p, int chunkX, int chunkZ) { + CraftbukkitWrapper.impl.sendChunk(p, chunkX, chunkZ); } } diff --git a/SpigotCore_Main/src/de/steamwar/inventory/SWItem.java b/SpigotCore_Main/src/de/steamwar/inventory/SWItem.java index d82a9af..02e89b2 100644 --- a/SpigotCore_Main/src/de/steamwar/inventory/SWItem.java +++ b/SpigotCore_Main/src/de/steamwar/inventory/SWItem.java @@ -21,7 +21,7 @@ package de.steamwar.inventory; import com.google.gson.JsonArray; import com.google.gson.JsonObject; -import de.steamwar.core.VersionedCallable; +import de.steamwar.core.FlatteningWrapper; import org.bukkit.Material; import org.bukkit.OfflinePlayer; import org.bukkit.enchantments.Enchantment; @@ -44,24 +44,21 @@ public class SWItem { public static SWItem getPlayerSkull(String playerName){ SWItem p = new SWItem(); - ItemStack head = VersionedCallable.call(new VersionedCallable<>(() -> SWItem_8.setSkullOwner(playerName), 8), - new VersionedCallable<>(() -> SWItem_14.setSkullOwner(playerName), 14)); + ItemStack head = FlatteningWrapper.impl.setSkullOwner(playerName); p.setItemStack(head); return p; } public static Material getMaterial(String material){ try{ - return VersionedCallable.call(new VersionedCallable<>(() -> SWItem_8.getMaterial(material), 8), - new VersionedCallable<>(() -> SWItem_14.getMaterial(material), 14)); + return FlatteningWrapper.impl.getMaterial(material); }catch(IllegalArgumentException e){ return Material.STONE; } } public static Material getDye(int colorCode){ - return VersionedCallable.call(new VersionedCallable<>(SWItem_8::getDye, 8), - new VersionedCallable<>(() -> SWItem_14.getDye(colorCode), 14)); + return FlatteningWrapper.impl.getDye(colorCode); } public SWItem() { diff --git a/SpigotCore_Main/src/de/steamwar/message/Message.java b/SpigotCore_Main/src/de/steamwar/message/Message.java index 7ae38e0..e277ee1 100644 --- a/SpigotCore_Main/src/de/steamwar/message/Message.java +++ b/SpigotCore_Main/src/de/steamwar/message/Message.java @@ -19,7 +19,7 @@ package de.steamwar.message; -import de.steamwar.core.VersionedCallable; +import de.steamwar.core.WorldOfColorWrapper; import net.md_5.bungee.api.ChatMessageType; import net.md_5.bungee.api.chat.ClickEvent; import net.md_5.bungee.api.chat.HoverEvent; @@ -73,8 +73,7 @@ public class Message { } private Locale getLocale(Player player){ - return VersionedCallable.call(new VersionedCallable<>(() -> Message_8.getLocale(player), 8), - new VersionedCallable<>(() -> Message_12.getLocale(player), 12)); + return WorldOfColorWrapper.impl.getLocale(player); } /* Send a message to one player */ diff --git a/SpigotCore_Main/src/de/steamwar/scoreboard/SWScoreboard.java b/SpigotCore_Main/src/de/steamwar/scoreboard/SWScoreboard.java index 809fc30..c01b56b 100644 --- a/SpigotCore_Main/src/de/steamwar/scoreboard/SWScoreboard.java +++ b/SpigotCore_Main/src/de/steamwar/scoreboard/SWScoreboard.java @@ -19,57 +19,72 @@ package de.steamwar.scoreboard; -import com.comphenix.protocol.PacketType; -import com.comphenix.protocol.ProtocolLibrary; -import com.comphenix.protocol.ProtocolManager; -import com.comphenix.protocol.events.PacketContainer; -import com.comphenix.protocol.wrappers.WrappedChatComponent; +import com.comphenix.tinyprotocol.Reflection; import de.steamwar.core.Core; -import de.steamwar.core.VersionedRunnable; +import de.steamwar.core.FlatteningWrapper; +import de.steamwar.core.events.ChunkListener; import org.bukkit.Bukkit; import org.bukkit.entity.Player; -import java.lang.reflect.InvocationTargetException; import java.util.HashMap; import java.util.Map; public class SWScoreboard { private SWScoreboard() {} - private static final ProtocolManager manager = ProtocolLibrary.getProtocolManager(); + public static final Class scoreboardObjective = Reflection.getClass("{nms}.PacketPlayOutScoreboardObjective"); + private static final Reflection.FieldAccessor scoreboardName = Reflection.getField(scoreboardObjective, String.class, 0); + private static final Reflection.FieldAccessor scoreboardAction = Reflection.getField(scoreboardObjective, int.class, 0); + private static final Class scoreboardDisplayEnum = Reflection.getClass("{nms}.IScoreboardCriteria$EnumScoreboardHealthDisplay"); + private static final Reflection.FieldAccessor scoreboardDisplayType = Reflection.getField(scoreboardObjective, scoreboardDisplayEnum, 0); + private static final Object displayTypeIntegers = scoreboardDisplayEnum.getEnumConstants()[0]; + + private static final Class scoreboardScore = Reflection.getClass("{nms}.PacketPlayOutScoreboardScore"); + private static final Reflection.FieldAccessor scoreName = Reflection.getField(scoreboardScore, String.class, 0); + private static final Reflection.FieldAccessor scoreScoreboardName = Reflection.getField(scoreboardScore, String.class, 1); + private static final Reflection.FieldAccessor scoreValue = Reflection.getField(scoreboardScore, int.class, 0); + private static final Class scoreActionEnum = Reflection.getClass("{nms}.ScoreboardServer$Action"); + private static final Reflection.FieldAccessor scoreAction = Reflection.getField(scoreboardScore, scoreActionEnum, 0); + private static final Object scoreActionChange = scoreActionEnum.getEnumConstants()[0]; + private static final HashMap playerBoards = new HashMap<>(); //Object -> Scoreboard | Alle Versionen in der Map! private static int toggle = 0; // Scoreboard 0 updates while scoreboard 1 is presenting. toggle marks the current active scoreboard private static final String SIDEBAR = "Sidebar"; - private static final PacketContainer[] DELETE_SCOREBOARD = new PacketContainer[2]; - private static final PacketContainer[] DISPLAY_SIDEBAR = new PacketContainer[2]; + private static final Object[] DELETE_SCOREBOARD = new Object[2]; + private static final Object[] DISPLAY_SIDEBAR = new Object[2]; static { - setScoreboardConstants(0); - setScoreboardConstants(1); + Class scoreboardDisplayObjective = Reflection.getClass("{nms}.PacketPlayOutScoreboardDisplayObjective"); + Reflection.FieldAccessor scoreboardDisplayName = Reflection.getField(scoreboardDisplayObjective, String.class, 0); + Reflection.FieldAccessor scoreboardDisplaySlot = Reflection.getField(scoreboardDisplayObjective, int.class, 0); + for(int id = 0; id < 2; id++) { + DELETE_SCOREBOARD[id] = Reflection.newInstance(scoreboardObjective); + scoreboardName.set(DELETE_SCOREBOARD[id], SIDEBAR + id); + scoreboardAction.set(DELETE_SCOREBOARD[id], 1); //1 to remove + + DISPLAY_SIDEBAR[id] = Reflection.newInstance(scoreboardDisplayObjective); + scoreboardDisplayName.set(DISPLAY_SIDEBAR[id], SIDEBAR + id); + scoreboardDisplaySlot.set(DISPLAY_SIDEBAR[id], 1); // 1 = Sidebar + } + Bukkit.getScheduler().runTaskTimer(Core.getInstance(), () -> { toggle ^= 1; // Toggle between 0 and 1 for(Map.Entry scoreboard : playerBoards.entrySet()) { Player player = scoreboard.getKey(); ScoreboardCallback callback = scoreboard.getValue(); - try { - manager.sendServerPacket(player, DELETE_SCOREBOARD[toggle]); - manager.sendServerPacket(player, createSidebarPacket(callback.getTitle())); - for(Map.Entry score : callback.getData().entrySet()){ - manager.sendServerPacket(player, createScorePacket(score.getKey(), score.getValue())); - } - } catch (InvocationTargetException e) { - throw new SecurityException("Could not send scoreboard packets", e); + + ChunkListener.protocol.sendPacket(player, DELETE_SCOREBOARD[toggle]); + ChunkListener.protocol.sendPacket(player, createSidebarPacket(callback.getTitle())); + for(Map.Entry score : callback.getData().entrySet()){ + ChunkListener.protocol.sendPacket(player, createScorePacket(score.getKey(), score.getValue())); } + Bukkit.getScheduler().runTaskLater(Core.getInstance(), () -> { if(!player.isOnline()) return; - try { - ProtocolLibrary.getProtocolManager().sendServerPacket(player, DISPLAY_SIDEBAR[toggle]); - } catch (InvocationTargetException e) { - throw new SecurityException("Could not send DISPLAY_SIDEBAR", e); - } + ChunkListener.protocol.sendPacket(player, DISPLAY_SIDEBAR[toggle]); }, 2); } }, 10, 5); @@ -81,52 +96,27 @@ public class SWScoreboard { } public static void removeScoreboard(Player player) { - if(playerBoards.remove(player) == null) + if(playerBoards.remove(player) == null || !player.isOnline()) return; - try { - ProtocolLibrary.getProtocolManager().sendServerPacket(player, DELETE_SCOREBOARD[toggle]); - } catch (InvocationTargetException e) { - throw new SecurityException("Could not send DELETE_PACKET", e); - } + ChunkListener.protocol.sendPacket(player, DELETE_SCOREBOARD[toggle]); } - private static PacketContainer createSidebarPacket(String name){ - PacketContainer packet = manager.createPacket(PacketType.Play.Server.SCOREBOARD_OBJECTIVE); - packet.getStrings().write(0, SIDEBAR + toggle); - packet.getIntegers().write(0, 0); //0 to create - VersionedRunnable.call(new VersionedRunnable(() -> packet.getStrings().write(1, name), 8), - new VersionedRunnable(() -> packet.getChatComponents().write(0, WrappedChatComponent.fromText(name)), 14)); - packet.getEnumModifier(RenderType.class, 2).write(0, RenderType.INTEGER); + private static Object createSidebarPacket(String name){ + Object packet = Reflection.newInstance(scoreboardObjective); + scoreboardName.set(packet, SIDEBAR + toggle); + scoreboardAction.set(packet, 0); //0 to create + FlatteningWrapper.impl.setScoreboardTitle(packet, name); + scoreboardDisplayType.set(packet, displayTypeIntegers); return packet; } - private static PacketContainer createScorePacket(String name, int value){ - PacketContainer packet = manager.createPacket(PacketType.Play.Server.SCOREBOARD_SCORE); - packet.getStrings().write(0, name); - packet.getIntegers().write(0, value); - packet.getStrings().write(1, SIDEBAR + toggle); - packet.getEnumModifier(Action.class, 3).write(0, Action.CHANGE); + private static Object createScorePacket(String name, int value){ + Object packet = Reflection.newInstance(scoreboardScore); + scoreName.set(packet, name); + scoreScoreboardName.set(packet, SIDEBAR + toggle); + scoreValue.set(packet, value); + scoreAction.set(packet, scoreActionChange); return packet; } - - private enum Action{ - CHANGE, - REMOVE - } - - private enum RenderType{ - INTEGER, - HEART - } - - private static void setScoreboardConstants(int id){ - DELETE_SCOREBOARD[id] = manager.createPacket(PacketType.Play.Server.SCOREBOARD_OBJECTIVE); - DELETE_SCOREBOARD[id].getStrings().write(0, SIDEBAR + id); - DELETE_SCOREBOARD[id].getIntegers().write(0, 1); //1 to remove - - DISPLAY_SIDEBAR[id] = manager.createPacket(PacketType.Play.Server.SCOREBOARD_DISPLAY_OBJECTIVE); - DISPLAY_SIDEBAR[id].getStrings().write(0, SIDEBAR + id); - DISPLAY_SIDEBAR[id].getIntegers().write(0, 1); // 1 = Sidebar - } } diff --git a/SpigotCore_API/src/de/steamwar/scoreboard/ScoreboardCallback.java b/SpigotCore_Main/src/de/steamwar/scoreboard/ScoreboardCallback.java similarity index 100% rename from SpigotCore_API/src/de/steamwar/scoreboard/ScoreboardCallback.java rename to SpigotCore_Main/src/de/steamwar/scoreboard/ScoreboardCallback.java diff --git a/SpigotCore_API/src/de/steamwar/sql/NoClipboardException.java b/SpigotCore_Main/src/de/steamwar/sql/NoClipboardException.java similarity index 100% rename from SpigotCore_API/src/de/steamwar/sql/NoClipboardException.java rename to SpigotCore_Main/src/de/steamwar/sql/NoClipboardException.java diff --git a/SpigotCore_Main/src/de/steamwar/sql/Schematic.java b/SpigotCore_Main/src/de/steamwar/sql/Schematic.java index a7d8c45..b12a375 100644 --- a/SpigotCore_Main/src/de/steamwar/sql/Schematic.java +++ b/SpigotCore_Main/src/de/steamwar/sql/Schematic.java @@ -20,8 +20,7 @@ package de.steamwar.sql; import com.sk89q.worldedit.extent.clipboard.Clipboard; -import de.steamwar.core.VersionedCallable; -import de.steamwar.core.VersionedRunnable; +import de.steamwar.core.FlatteningWrapper; import org.bukkit.entity.Player; import java.io.IOException; @@ -197,8 +196,11 @@ public class Schematic { } public static Clipboard clipboardFromStream(InputStream is, boolean schemFormat) { - return VersionedCallable.call(new VersionedCallable<>(() -> Schematic_8.getClipboard(is, schemFormat), 8), - new VersionedCallable<>(() -> Schematic_14.getClipboard(is, schemFormat), 14)); + try { + return FlatteningWrapper.impl.getClipboard(is, schemFormat); + } catch (IOException e) { + throw new SecurityException("Could not read schem", e); + } } public Clipboard load() throws IOException, NoClipboardException { @@ -207,8 +209,7 @@ public class Schematic { public void loadToPlayer(Player player) throws IOException, NoClipboardException { InputStream is = schemData(); - VersionedRunnable.call(new VersionedRunnable(() -> Schematic_8.setPlayerClipboard(player, is, schemFormat), 8), - new VersionedRunnable(() -> Schematic_14.setPlayerClipboard(player, is, schemFormat), 14)); + FlatteningWrapper.impl.setPlayerClipboard(player, is, schemFormat); } public void saveOldFormatFromPlayer(Player player) throws IOException, NoClipboardException { @@ -231,21 +232,11 @@ public class Schematic { private void saveFromPlayer(Player player, boolean newFormat) throws IOException, NoClipboardException { Blob blob = SQL.blob(); - VersionedRunnable.call(new VersionedRunnable(() -> { - try { - blob.setBytes(1, Schematic_8.getPlayerClipboard(player)); - } catch (SQLException e) { - throw new RuntimeException(e.getMessage(), e); - } - updateDatabase(blob, false); - }, 8), new VersionedRunnable(() -> { - try { - blob.setBytes(1, Schematic_14.getPlayerClipboard(player, newFormat)); - } catch (SQLException exception) { - throw new RuntimeException(exception.getMessage(), exception); - } - updateDatabase(blob, newFormat); - }, 14)); + try { + blob.setBytes(1, FlatteningWrapper.impl.getPlayerClipboard(player, newFormat)); + } catch (SQLException e) { + throw new SecurityException(e.getMessage(), e); + } } private void updateDatabase(Blob blob, boolean newFormat) { diff --git a/SpigotCore_Main/src/plugin.yml b/SpigotCore_Main/src/plugin.yml index 370fc34..8eee87b 100644 --- a/SpigotCore_Main/src/plugin.yml +++ b/SpigotCore_Main/src/plugin.yml @@ -5,8 +5,6 @@ api-version: "1.13" load: STARTUP softdepend: - WorldEdit -depend: - - ProtocolLib main: de.steamwar.core.Core commands: \ No newline at end of file diff --git a/build.gradle b/build.gradle index a310072..87b87f4 100644 --- a/build.gradle +++ b/build.gradle @@ -79,6 +79,12 @@ allprojects { dependencies { implementation project(":SpigotCore_Main") + implementation project(":SpigotCore_8") + implementation project(":SpigotCore_9") + implementation project(":SpigotCore_10") + implementation project(":SpigotCore_12") + implementation project(":SpigotCore_14") + implementation project(":SpigotCore_15") } task buildProject {