diff --git a/.gitignore b/.gitignore index 377ce8c..36e1257 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,15 @@ +# Package Files +*.jar + +# Gradle +.gradle +**/build/ +!gradle/wrapper/gradle-wrapper.jar +steamwar.properties + +# IntelliJ IDEA .idea -target -lib -dependency-reduced-pom.xml -*.iml \ No newline at end of file +*.iml + +# Other +lib \ No newline at end of file diff --git a/SpigotCore_10/build.gradle b/SpigotCore_10/build.gradle new file mode 100644 index 0000000..34ef6f9 --- /dev/null +++ b/SpigotCore_10/build.gradle @@ -0,0 +1,49 @@ +/* + * 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 . + */ + +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 { + implementation project(":SpigotCore_Main") + + compileOnly files("${project.rootDir}/lib/Spigot-1.10.jar") +} diff --git a/SpigotCore_10/pom.xml b/SpigotCore_10/pom.xml deleted file mode 100644 index a04f9d3..0000000 --- a/SpigotCore_10/pom.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - 4.0.0 - - - steamwar - SpigotCore - 2.0 - - - - ${project.basedir}/.. - - - SpigotCore_10 - 2.0 - - - src - - - src - - **/*.java - **/*.kt - - - - - - - - steamwar - Spigot - 1.10 - system - ${main.basedir}/lib/Spigot-1.10.jar - - - steamwar - WorldEdit - 1.12 - system - ${main.basedir}/lib/WorldEdit-1.12.jar - - - steamwar - SpigotCore_API - 2.0 - - - steamwar - SpigotCore_9 - 2.0 - - - diff --git a/SpigotCore_10/settings.gradle b/SpigotCore_10/settings.gradle new file mode 100644 index 0000000..13f4f4a --- /dev/null +++ b/SpigotCore_10/settings.gradle @@ -0,0 +1,20 @@ +/* + * 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_10' \ No newline at end of file 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 new file mode 100644 index 0000000..5ee8ca9 --- /dev/null +++ b/SpigotCore_12/build.gradle @@ -0,0 +1,49 @@ +/* + * 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 . + */ + +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 { + implementation project(":SpigotCore_Main") + + compileOnly files("${project.rootDir}/lib/Spigot-1.12.jar") +} diff --git a/SpigotCore_12/pom.xml b/SpigotCore_12/pom.xml deleted file mode 100644 index c91c885..0000000 --- a/SpigotCore_12/pom.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - 4.0.0 - - - steamwar - SpigotCore - 2.0 - - - - ${project.basedir}/.. - - - SpigotCore_12 - 2.0 - - - src - - - src - - **/*.java - **/*.kt - - - - - - - - steamwar - Spigot - 1.12 - system - ${main.basedir}/lib/Spigot-1.12.jar - - - steamwar - WorldEdit - 1.12 - system - ${main.basedir}/lib/WorldEdit-1.12.jar - - - steamwar - SpigotCore_API - 2.0 - - - steamwar - SpigotCore_8 - 2.0 - - - \ No newline at end of file diff --git a/SpigotCore_12/settings.gradle b/SpigotCore_12/settings.gradle new file mode 100644 index 0000000..079bf5a --- /dev/null +++ b/SpigotCore_12/settings.gradle @@ -0,0 +1,20 @@ +/* + * 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_12' \ No newline at end of file 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 new file mode 100644 index 0000000..688968a --- /dev/null +++ b/SpigotCore_14/build.gradle @@ -0,0 +1,50 @@ +/* + * 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 . + */ + +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 { + implementation project(":SpigotCore_Main") + + compileOnly files("${project.rootDir}/lib/Spigot-1.14.jar") + compileOnly files("${project.rootDir}/lib/WorldEdit-1.15.jar") +} diff --git a/SpigotCore_14/pom.xml b/SpigotCore_14/pom.xml deleted file mode 100644 index 724d006..0000000 --- a/SpigotCore_14/pom.xml +++ /dev/null @@ -1,55 +0,0 @@ - - - 4.0.0 - - - steamwar - SpigotCore - 2.0 - - - - ${project.basedir}/.. - - - SpigotCore_14 - 2.0 - - - src - - - src - - **/*.java - **/*.kt - - - - - - - - steamwar - Spigot - 1.14 - system - ${main.basedir}/lib/Spigot-1.14.jar - - - steamwar - WorldEdit - 1.15 - system - ${main.basedir}/lib/WorldEdit-1.15.jar - - - steamwar - SpigotCore_API - 2.0 - compile - - - \ No newline at end of file diff --git a/SpigotCore_14/settings.gradle b/SpigotCore_14/settings.gradle new file mode 100644 index 0000000..4a8abac --- /dev/null +++ b/SpigotCore_14/settings.gradle @@ -0,0 +1,20 @@ +/* + * 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_14' \ No newline at end of file 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/inventory/SWItem_14.java b/SpigotCore_14/src/de/steamwar/core/FlatteningWrapper14.java similarity index 91% rename from SpigotCore_14/src/de/steamwar/inventory/SWItem_14.java rename to SpigotCore_14/src/de/steamwar/core/FlatteningWrapper14.java index 623dd20..3a28106 100644 --- a/SpigotCore_14/src/de/steamwar/inventory/SWItem_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,10 @@ along with this program. If not, see . */ -package de.steamwar.inventory; +package de.steamwar.core; +import com.comphenix.tinyprotocol.Reflection; +import de.steamwar.scoreboard.SWScoreboard; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.inventory.ItemStack; @@ -27,8 +29,7 @@ import org.bukkit.inventory.meta.SkullMeta; import java.util.HashMap; import java.util.Map; -class SWItem_14 { - private SWItem_14(){} +public class FlatteningWrapper14 implements FlatteningWrapper.IFlatteningWrapper { private static final Map renamedLegacy = new HashMap<>(); @@ -221,7 +222,25 @@ class SWItem_14 { renamedLegacy.put("RECORD_12", Material.MUSIC_DISC_WAIT); } - static Material getMaterial(String material) { + private static final Reflection.FieldAccessor scoreboardName = Reflection.getField(SWScoreboard.scoreboardObjective, Reflection.getClass("{nms}.IChatBaseComponent"), 0); + private static final Reflection.ConstructorInvoker chatComponentConstructor = Reflection.getConstructor(Reflection.getClass("{nms}.ChatComponentText"), String.class); + + @Override + public void setScoreboardTitle(Object packet, String title) { + scoreboardName.set(packet, chatComponentConstructor.invoke(title)); + } + + private static final Class scoreActionEnum = Reflection.getClass("{nms}.ScoreboardServer$Action"); + private static final Reflection.FieldAccessor scoreAction = Reflection.getField(SWScoreboard.scoreboardScore, scoreActionEnum, 0); + private static final Object scoreActionChange = scoreActionEnum.getEnumConstants()[0]; + + @Override + public void setScoreAction(Object packet) { + scoreAction.set(packet, scoreActionChange); + } + + @Override + public Material getMaterial(String material) { try{ return Material.valueOf(material); }catch(IllegalArgumentException e){ @@ -229,7 +248,8 @@ class SWItem_14 { } } - static Material getDye(int colorCode){ + @Override + public Material getDye(int colorCode) { switch(colorCode){ case 1: return Material.RED_DYE; @@ -266,7 +286,9 @@ class SWItem_14 { } } - static ItemStack setSkullOwner(String player){ + @SuppressWarnings("deprecation") + @Override + public ItemStack setSkullOwner(String player) { ItemStack head = new ItemStack(Material.PLAYER_HEAD, 1); SkullMeta headmeta = (SkullMeta) head.getItemMeta(); assert headmeta != null; 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/sql/Schematic_14.java b/SpigotCore_14/src/de/steamwar/core/WorldEditWrapper14.java similarity index 94% rename from SpigotCore_14/src/de/steamwar/sql/Schematic_14.java rename to SpigotCore_14/src/de/steamwar/core/WorldEditWrapper14.java index 255530f..96b135b 100644 --- a/SpigotCore_14/src/de/steamwar/sql/Schematic_14.java +++ b/SpigotCore_14/src/de/steamwar/core/WorldEditWrapper14.java @@ -1,23 +1,4 @@ -/* - 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.sql; +package de.steamwar.core; import com.google.common.collect.ImmutableList; import com.google.common.collect.Maps; @@ -25,7 +6,6 @@ import com.sk89q.jnbt.*; import com.sk89q.worldedit.EmptyClipboardException; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; -import com.sk89q.worldedit.bukkit.WorldEditPlugin; import com.sk89q.worldedit.extension.input.InputParseException; import com.sk89q.worldedit.extension.input.ParserContext; import com.sk89q.worldedit.extension.platform.Actor; @@ -46,7 +26,7 @@ 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 org.bukkit.Bukkit; +import de.steamwar.sql.NoClipboardException; import org.bukkit.entity.Player; import java.io.ByteArrayOutputStream; @@ -57,16 +37,16 @@ import java.util.stream.Collectors; import static com.google.common.base.Preconditions.checkNotNull; -class Schematic_14 { - private Schematic_14(){} +public class WorldEditWrapper14 implements WorldEditWrapper.IWorldEditWrapper { 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(); + clipboardHolder = WorldEditWrapper.getWorldEditPlugin().getSession(player).getClipboard(); } catch (EmptyClipboardException e) { throw new NoClipboardException(); } @@ -92,7 +72,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); @@ -103,11 +84,12 @@ class Schematic_14 { if (clipboard == null) throw new NoClipboardException(); - Actor actor = getWorldEditPlugin().wrapCommandSender(player); - getWorldEditPlugin().getWorldEdit().getSessionManager().get(actor).setClipboard(new ClipboardHolder(clipboard)); + Actor actor = WorldEditWrapper.getWorldEditPlugin().wrapCommandSender(player); + WorldEditWrapper.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(); @@ -119,10 +101,6 @@ class Schematic_14 { } } - private static WorldEditPlugin getWorldEditPlugin() { - return (WorldEditPlugin) Bukkit.getPluginManager().getPlugin("WorldEdit"); - } - private static class MCEditSchematicReader extends NBTSchematicReader { private final NBTInputStream inputStream; @@ -419,7 +397,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_15/build.gradle b/SpigotCore_15/build.gradle new file mode 100644 index 0000000..76dc3ee --- /dev/null +++ b/SpigotCore_15/build.gradle @@ -0,0 +1,49 @@ +/* + * 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 . + */ + +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 { + implementation project(":SpigotCore_Main") + + compileOnly files("${project.rootDir}/lib/Spigot-1.15.jar") +} diff --git a/SpigotCore_15/pom.xml b/SpigotCore_15/pom.xml deleted file mode 100644 index a7ecfbd..0000000 --- a/SpigotCore_15/pom.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - 4.0.0 - - - steamwar - SpigotCore - 2.0 - - - - ${project.basedir}/.. - - - SpigotCore_15 - 2.0 - - - src - - - src - - **/*.java - **/*.kt - - - - - - - - steamwar - Spigot - 1.15 - system - ${main.basedir}/lib/Spigot-1.15.jar - - - steamwar - WorldEdit - 1.15 - system - ${main.basedir}/lib/WorldEdit-1.15.jar - - - steamwar - SpigotCore_API - 2.0 - - - steamwar - SpigotCore_14 - 2.0 - - - \ No newline at end of file diff --git a/SpigotCore_15/settings.gradle b/SpigotCore_15/settings.gradle new file mode 100644 index 0000000..a861db0 --- /dev/null +++ b/SpigotCore_15/settings.gradle @@ -0,0 +1,20 @@ +/* + * 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_15' \ No newline at end of file diff --git a/SpigotCore_15/src/de/steamwar/authlib/AuthlibInjector_15.java b/SpigotCore_15/src/de/steamwar/authlib/AuthlibInjector_15.java deleted file mode 100644 index 9864a31..0000000 --- a/SpigotCore_15/src/de/steamwar/authlib/AuthlibInjector_15.java +++ /dev/null @@ -1,33 +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.authlib; - -import net.minecraft.server.v1_15_R1.MinecraftServer; - -public class AuthlibInjector_15 { - - static Class getMinecraftClass() { - return MinecraftServer.class; - } - - static Object getMinecraftServerInstance() { - return MinecraftServer.getServer(); - } -} 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_8/build.gradle b/SpigotCore_8/build.gradle new file mode 100644 index 0000000..8007cef --- /dev/null +++ b/SpigotCore_8/build.gradle @@ -0,0 +1,50 @@ +/* + * 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 . + */ + +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 { + implementation project(":SpigotCore_Main") + + compileOnly files("${project.rootDir}/lib/Spigot-1.8.jar") + compileOnly files("${project.rootDir}/lib/WorldEdit-1.12.jar") +} diff --git a/SpigotCore_8/pom.xml b/SpigotCore_8/pom.xml deleted file mode 100644 index 0e05af5..0000000 --- a/SpigotCore_8/pom.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - 4.0.0 - - - steamwar - SpigotCore - 2.0 - - - - ${project.basedir}/.. - - - SpigotCore_8 - 2.0 - - - src - - - src - - **/*.java - **/*.kt - - - - - - - - steamwar - Spigot - 1.8 - system - ${main.basedir}/lib/Spigot-1.8.jar - - - steamwar - WorldEdit - 1.12 - system - ${main.basedir}/lib/WorldEdit-1.12.jar - - - steamwar - SpigotCore_API - 2.0 - - - \ No newline at end of file diff --git a/SpigotCore_8/settings.gradle b/SpigotCore_8/settings.gradle new file mode 100644 index 0000000..e4a8e0a --- /dev/null +++ b/SpigotCore_8/settings.gradle @@ -0,0 +1,20 @@ +/* + * 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_8' \ No newline at end of file diff --git a/SpigotCore_8/src/de/steamwar/core/BountifulWrapper8.java b/SpigotCore_8/src/de/steamwar/core/BountifulWrapper8.java new file mode 100644 index 0000000..8c08082 --- /dev/null +++ b/SpigotCore_8/src/de/steamwar/core/BountifulWrapper8.java @@ -0,0 +1,41 @@ +/* + 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.md_5.bungee.api.ChatMessageType; +import net.md_5.bungee.api.chat.BaseComponent; +import net.minecraft.server.v1_8_R3.ChatComponentText; +import net.minecraft.server.v1_8_R3.PacketPlayOutChat; +import org.bukkit.Sound; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer; +import org.bukkit.entity.Player; + +public class BountifulWrapper8 implements BountifulWrapper.IBountifulWrapper { + + @Override + public void playPling(Player player) { + player.playSound(player.getLocation(), Sound.ORB_PICKUP, 1, 1); + } + + @Override + public void sendMessage(Player player, ChatMessageType type, BaseComponent... msg) { + ((CraftPlayer) player).getHandle().playerConnection.sendPacket(new PacketPlayOutChat(new ChatComponentText(BaseComponent.toLegacyText(msg)), (byte)type.ordinal())); + } +} 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/inventory/SWItem_8.java b/SpigotCore_8/src/de/steamwar/core/FlatteningWrapper8.java similarity index 54% rename from SpigotCore_8/src/de/steamwar/inventory/SWItem_8.java rename to SpigotCore_8/src/de/steamwar/core/FlatteningWrapper8.java index 746134f..371c799 100644 --- a/SpigotCore_8/src/de/steamwar/inventory/SWItem_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,16 +17,33 @@ along with this program. If not, see . */ -package de.steamwar.inventory; +package de.steamwar.core; +import com.comphenix.tinyprotocol.Reflection; +import de.steamwar.scoreboard.SWScoreboard; import org.bukkit.Material; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.SkullMeta; -class SWItem_8 { - private SWItem_8(){} +public class FlatteningWrapper8 implements FlatteningWrapper.IFlatteningWrapper { - static Material getMaterial(String material){ + private static final Reflection.FieldAccessor scoreboardName = Reflection.getField(SWScoreboard.scoreboardObjective, String.class, 1); + private static final Class scoreActionEnum = Reflection.getClass("{nms}.PacketPlayOutScoreboardScore$EnumScoreboardAction"); + private static final Reflection.FieldAccessor scoreAction = Reflection.getField(SWScoreboard.scoreboardScore, scoreActionEnum, 0); + private static final Object scoreActionChange = scoreActionEnum.getEnumConstants()[0]; + + @Override + public void setScoreboardTitle(Object packet, String title) { + scoreboardName.set(packet, title); + } + + @Override + public void setScoreAction(Object packet) { + scoreAction.set(packet, scoreActionChange); + } + + @Override + public Material getMaterial(String material) { try{ return Material.valueOf(material); }catch(IllegalArgumentException e){ @@ -34,11 +51,13 @@ class SWItem_8 { } } - static Material getDye(){ + @Override + public Material getDye(int colorCode) { return Material.INK_SACK; } - static ItemStack setSkullOwner(String player){ + @Override + public ItemStack setSkullOwner(String player) { ItemStack head = new ItemStack(Material.SKULL_ITEM, 1, (short) 3); SkullMeta headmeta = (SkullMeta) head.getItemMeta(); headmeta.setOwner(player); 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/sql/Schematic_8.java b/SpigotCore_8/src/de/steamwar/core/WorldEditWrapper8.java similarity index 85% rename from SpigotCore_8/src/de/steamwar/sql/Schematic_8.java rename to SpigotCore_8/src/de/steamwar/core/WorldEditWrapper8.java index 29974ab..3e243bd 100644 --- a/SpigotCore_8/src/de/steamwar/sql/Schematic_8.java +++ b/SpigotCore_8/src/de/steamwar/core/WorldEditWrapper8.java @@ -1,23 +1,4 @@ -/* - 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.sql; +package de.steamwar.core; import com.google.common.base.Preconditions; import com.google.common.collect.Maps; @@ -25,7 +6,6 @@ import com.sk89q.jnbt.*; import com.sk89q.worldedit.*; import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.bukkit.BukkitWorld; -import com.sk89q.worldedit.bukkit.WorldEditPlugin; import com.sk89q.worldedit.extension.input.ParserContext; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard; @@ -36,10 +16,9 @@ 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 org.bukkit.Bukkit; +import de.steamwar.sql.NoClipboardException; import org.bukkit.entity.Player; -import javax.annotation.Nullable; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; @@ -49,13 +28,13 @@ import java.util.List; import java.util.Map; import java.util.stream.Collectors; -class Schematic_8 { - private Schematic_8(){} +public class WorldEditWrapper8 implements WorldEditWrapper.IWorldEditWrapper { - static byte[] getPlayerClipboard(Player player) { + @Override + public byte[] getPlayerClipboard(Player player, boolean schemFormat) { ClipboardHolder clipboardHolder; try { - clipboardHolder = getWorldEditPlugin().getSession(player).getClipboard(); + clipboardHolder = WorldEditWrapper.getWorldEditPlugin().getSession(player).getClipboard(); } catch (EmptyClipboardException e) { throw new NoClipboardException(); } @@ -73,7 +52,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 { @@ -82,22 +62,19 @@ class Schematic_8 { throw new RuntimeException(e); } - Actor actor = getWorldEditPlugin().wrapCommandSender(player); - getWorldEditPlugin().getWorldEdit().getSessionManager().get(actor).setClipboard(new ClipboardHolder(clipboard, world)); + Actor actor = WorldEditWrapper.getWorldEditPlugin().wrapCommandSender(player); + WorldEditWrapper.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 return new SchematicReader(new NBTInputStream(is)).read(WorldEdit.getInstance().getServer().getWorlds().get(0).getWorldData()); } - private static WorldEditPlugin getWorldEditPlugin() { - 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 +109,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 +158,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]); } @@ -277,7 +254,6 @@ class Schematic_8 { } } - @Nullable private static T getTag(Map items, String key, Class expected) { if (!items.containsKey(key)) { return null; 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 new file mode 100644 index 0000000..064f759 --- /dev/null +++ b/SpigotCore_9/build.gradle @@ -0,0 +1,49 @@ +/* + * 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 . + */ + +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 { + implementation project(":SpigotCore_Main") + + compileOnly files("${project.rootDir}/lib/Spigot-1.9.jar") +} diff --git a/SpigotCore_9/pom.xml b/SpigotCore_9/pom.xml deleted file mode 100644 index 2b9cb04..0000000 --- a/SpigotCore_9/pom.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - 4.0.0 - - - steamwar - SpigotCore - 2.0 - - - - ${project.basedir}/.. - - - SpigotCore_9 - 2.0 - - - src - - - src - - **/*.java - **/*.kt - - - - - - - - steamwar - Spigot - 1.9 - system - ${main.basedir}/lib/Spigot-1.9.jar - - - steamwar - WorldEdit - 1.12 - system - ${main.basedir}/lib/WorldEdit-1.12.jar - - - steamwar - SpigotCore_API - 2.0 - - - steamwar - SpigotCore_8 - 2.0 - - - \ No newline at end of file diff --git a/SpigotCore_9/settings.gradle b/SpigotCore_9/settings.gradle new file mode 100644 index 0000000..c55656e --- /dev/null +++ b/SpigotCore_9/settings.gradle @@ -0,0 +1,20 @@ +/* + * 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_9' \ No newline at end of file diff --git a/SpigotCore_9/src/de/steamwar/comms/BungeeReceiver_9.java b/SpigotCore_9/src/de/steamwar/core/BountifulWrapper9.java similarity index 69% rename from SpigotCore_9/src/de/steamwar/comms/BungeeReceiver_9.java rename to SpigotCore_9/src/de/steamwar/core/BountifulWrapper9.java index 685b65a..d12a37d 100644 --- a/SpigotCore_9/src/de/steamwar/comms/BungeeReceiver_9.java +++ b/SpigotCore_9/src/de/steamwar/core/BountifulWrapper9.java @@ -17,14 +17,22 @@ along with this program. If not, see . */ -package de.steamwar.comms; +package de.steamwar.core; +import net.md_5.bungee.api.ChatMessageType; +import net.md_5.bungee.api.chat.BaseComponent; 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); } + + @Override + public void sendMessage(Player player, ChatMessageType type, BaseComponent... msg) { + player.spigot().sendMessage(type, msg); + } } 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/pom.xml b/SpigotCore_API/pom.xml deleted file mode 100644 index 3d316be..0000000 --- a/SpigotCore_API/pom.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - 4.0.0 - - - steamwar - SpigotCore - 2.0 - - - - ${project.basedir}/.. - - - SpigotCore_API - 2.0 - - - src - - - src - - **/*.java - **/*.kt - - - - - \ No newline at end of file diff --git a/SpigotCore_Main/build.gradle b/SpigotCore_Main/build.gradle new file mode 100644 index 0000000..59c9f89 --- /dev/null +++ b/SpigotCore_Main/build.gradle @@ -0,0 +1,55 @@ +/* + * 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 . + */ + +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 files("${project.rootDir}/lib/Spigot-1.15.jar") + compileOnly files("${project.rootDir}/lib/WorldEdit-1.12.jar") + implementation 'net.wesjd:anvilgui:1.4.0-SNAPSHOT' +} + +processResources { + from("build/classes/java/main/META-INF/annotations/") { + into("de.steamwar.bausystem") + } +} diff --git a/SpigotCore_Main/pom.xml b/SpigotCore_Main/pom.xml deleted file mode 100644 index 0d23f6f..0000000 --- a/SpigotCore_Main/pom.xml +++ /dev/null @@ -1,128 +0,0 @@ - - - 4.0.0 - - - steamwar - SpigotCore - 2.0 - - - - ${project.basedir}/.. - - - - - codemc-snapshots - https://repo.codemc.io/repository/maven-snapshots/ - - - - SpigotCore_Main - 2.0 - jar - - - src - - - src - - **/*.java - **/*.kt - - - - - - org.apache.maven.plugins - maven-shade-plugin - 3.2.1 - - - package - - shade - - - - - - spigotcore - - - - - steamwar - Spigot - 1.15 - system - ${main.basedir}/lib/Spigot-1.15.jar - - - steamwar - WorldEdit - 1.12 - system - ${main.basedir}/lib/WorldEdit-1.12.jar - - - steamwar - ProtocolLib - 1.0 - system - ${main.basedir}/lib/ProtocolLib.jar - - - net.wesjd - anvilgui - 1.4.0-SNAPSHOT - compile - - - steamwar - SpigotCore_API - 2.0 - compile - - - steamwar - SpigotCore_8 - 2.0 - compile - - - steamwar - SpigotCore_9 - 2.0 - compile - - - steamwar - SpigotCore_10 - 2.0 - compile - - - steamwar - SpigotCore_12 - 2.0 - compile - - - steamwar - SpigotCore_14 - 2.0 - compile - - - steamwar - SpigotCore_15 - 2.0 - compile - - - \ No newline at end of file diff --git a/SpigotCore_Main/settings.gradle b/SpigotCore_Main/settings.gradle new file mode 100644 index 0000000..2d1bf48 --- /dev/null +++ b/SpigotCore_Main/settings.gradle @@ -0,0 +1,20 @@ +/* + * 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_Main' \ No newline at end of file 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..3d2e41a --- /dev/null +++ b/SpigotCore_Main/src/com/comphenix/tinyprotocol/TinyProtocol.java @@ -0,0 +1,518 @@ +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; + static { + MethodInvoker networkMarkers; + try { + networkMarkers = Reflection.getTypedMethod(serverConnectionClass, null, List.class, serverConnectionClass); + } catch (IllegalStateException e) { // Paper, wtf why. + networkMarkers = Reflection.getTypedMethod(serverConnectionClass, null, Queue.class, serverConnectionClass); + } + getNetworkMarkers = networkMarkers; + } + + // 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 Collection 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 = (Collection) 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_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..8b22c31 --- /dev/null +++ b/SpigotCore_Main/src/de/steamwar/core/BountifulWrapper.java @@ -0,0 +1,36 @@ +/* + 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.md_5.bungee.api.ChatMessageType; +import net.md_5.bungee.api.chat.BaseComponent; +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); + + void sendMessage(Player player, ChatMessageType type, BaseComponent... msg); + } +} diff --git a/SpigotCore_Main/src/de/steamwar/core/Core.java b/SpigotCore_Main/src/de/steamwar/core/Core.java index 62f8849..319d199 100644 --- a/SpigotCore_Main/src/de/steamwar/core/Core.java +++ b/SpigotCore_Main/src/de/steamwar/core/Core.java @@ -19,8 +19,8 @@ package de.steamwar.core; -import de.steamwar.authlib.AuthlibInjector; import de.steamwar.comms.BungeeReceiver; +import de.steamwar.core.authlib.AuthlibInjector; import de.steamwar.core.events.ChattingEvent; import de.steamwar.core.events.ChunkListener; import de.steamwar.core.events.PlayerJoinedEvent; @@ -31,6 +31,7 @@ import org.bukkit.plugin.java.JavaPlugin; public class Core extends JavaPlugin{ + private static Core instance; private static final int version; @@ -57,20 +58,20 @@ public class Core extends JavaPlugin{ @Override public void onEnable() { + new ErrorHandler(); + Bukkit.getPluginManager().registerEvents(new PlayerJoinedEvent(), this); Bukkit.getPluginManager().registerEvents(new ChattingEvent(), this); Bukkit.getPluginManager().registerEvents(new WorldLoadEvent(), this); - ChunkListener.init(); - if(version >= 12) - ErrorLogger.init(); getServer().getMessenger().registerIncomingPluginChannel(this, "sw:bridge", new BungeeReceiver()); getServer().getMessenger().registerOutgoingPluginChannel(this, "sw:bridge"); + ChunkListener.init(); AuthlibInjector.inject(); } @Override public void onDisable(){ - SQL.closeConnection(); + SQL.close(); } public static Core getInstance() { 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_Main/src/de/steamwar/core/ErrorHandler.java b/SpigotCore_Main/src/de/steamwar/core/ErrorHandler.java new file mode 100644 index 0000000..0bc0815 --- /dev/null +++ b/SpigotCore_Main/src/de/steamwar/core/ErrorHandler.java @@ -0,0 +1,141 @@ +/* + 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 de.steamwar.sql.SWException; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.logging.Handler; +import java.util.logging.Level; +import java.util.logging.LogRecord; +import java.util.logging.Logger; + +public class ErrorHandler extends Handler { + + private boolean logDisabled = false; + + public ErrorHandler(){ + Logger.getLogger("").addHandler(this); + } + + @Override + public void publish(LogRecord logRecord) { + if(logRecord.getLevel().intValue() < Level.WARNING.intValue()) + return; + + if(logDisabled) + return; + + String message = logRecord.getMessage(); + for(String reason : ignoreStartsWith) + if(message.startsWith(reason)) + return; + for(String reason : ignoreContains) + if(message.contains(reason)) + return; + + switch (message) { + case "The server has stopped responding!": + logDisabled = true; + return; + case "------------------------------": + message = "Server stopped responding"; + logDisabled = true; + break; + case "Exception stopping the server": + logDisabled = true; + break; + default: + } + + ByteArrayOutputStream stacktraceOutput = new ByteArrayOutputStream(); + if(logRecord.getThrown() != null) + logRecord.getThrown().printStackTrace(new PrintStream(stacktraceOutput)); + String stacktrace = stacktraceOutput.toString(); + if(stacktrace.contains("POI data mismatch")) + return; + + SWException.log(message, stacktrace); + } + + @Override + public void flush() { + //This is task of the database + } + + @Override + public void close() throws SecurityException { + //Done in the database + } + + private static final List ignoreStartsWith; + private static final List ignoreContains; + + static { + List startsWith = new ArrayList<>(); + startsWith.add("Could not save the list after adding a user."); + startsWith.add("Could not save spigot.yml"); + startsWith.add("Failed to save operators list:"); + startsWith.add("Block at"); + startsWith.add("POI data mismatch"); + startsWith.add("handleDisconnection() called twice"); + startsWith.add("**** SERVER IS RUNNING IN OFFLINE/INSECURE MODE!"); + startsWith.add("The server will make no attempt to authenticate usernames. Beware."); + startsWith.add("Whilst this makes it possible to use BungeeCord,"); + startsWith.add("Please see http://www.spigotmc.org/wiki/firewall-guide/ for further information."); + startsWith.add("To change this, set \"online-mode\" to \"true\" in the server.properties file."); + startsWith.add("This crash report has been saved to:"); + startsWith.add("Could not pass event PlayerQuitEvent to WorldEditSUI"); + startsWith.add("[ViaVersion] "); + startsWith.add("[ViaBackwards] "); + startsWith.add("Something went wrong upgrading!"); + startsWith.add("Tried to load unrecognized recipe"); + startsWith.add("Invalid BlockState in palette:"); + startsWith.add("Could not register alias"); + startsWith.add("Can't keep up! Is the server overloaded?"); + startsWith.add("\tat "); + startsWith.add("java.lang.Exception"); + startsWith.add("An exceptionCaught()"); + startsWith.add("Exception verifying"); + startsWith.add("[WorldEditSUI]"); + startsWith.add("Unsupported key:"); + startsWith.add("ThrownPotion entity"); + startsWith.add("Couldn't load custom particle"); + startsWith.add("Chunk file at ["); + startsWith.add("Ignoring unknown attribute"); + startsWith.add("Skipping player strafe phase because no player was found"); + startsWith.add("Couldn't save chunk; already in use by another instance of Minecraft?"); + startsWith.add("Failed to save player data for "); + startsWith.add("Failed to check session lock for world located at"); + startsWith.add("Saving oversized chunk "); + ignoreStartsWith = Collections.unmodifiableList(startsWith); + + List contains = new ArrayList<>(); + contains.add("moved too quickly!"); + contains.add("moved wrongly!"); + contains.add("was kicked for floating too long!"); + contains.add("just tried to change non-editable sign"); + ignoreContains = Collections.unmodifiableList(contains); + } +} diff --git a/SpigotCore_Main/src/de/steamwar/core/ErrorLogger.java b/SpigotCore_Main/src/de/steamwar/core/ErrorLogger.java deleted file mode 100644 index b4ba2f1..0000000 --- a/SpigotCore_Main/src/de/steamwar/core/ErrorLogger.java +++ /dev/null @@ -1,63 +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 de.steamwar.sql.SWException; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.core.Appender; -import org.apache.logging.log4j.core.Core; -import org.apache.logging.log4j.core.LogEvent; -import org.apache.logging.log4j.core.LoggerContext; -import org.apache.logging.log4j.core.appender.AbstractAppender; -import org.apache.logging.log4j.core.config.plugins.Plugin; -import org.apache.logging.log4j.core.config.plugins.PluginAttribute; -import org.apache.logging.log4j.core.config.plugins.PluginFactory; -import org.apache.logging.log4j.spi.StandardLevel; - -@Plugin(name = "ErrorLogger", category = Core.CATEGORY_NAME, elementType = Appender.ELEMENT_TYPE) -public class ErrorLogger extends AbstractAppender { - - public static void init(){ - final LoggerContext lc = (LoggerContext) LogManager.getContext(false); - ErrorLogger el = ErrorLogger.createAppender("SWErrorLogger"); - el.start(); - lc.getConfiguration().addAppender(el); - lc.getRootLogger().addAppender(lc.getConfiguration().getAppender(el.getName())); - lc.updateLoggers(); - } - - private ErrorLogger(String name) { - super(name, null, null); - } - - @PluginFactory - public static ErrorLogger createAppender( - @PluginAttribute("name") String name) { - return new ErrorLogger(name); - } - - @Override - public void append(LogEvent logEvent) { - if(logEvent.getLevel().intLevel() > StandardLevel.WARN.intLevel()) - return; - - SWException.log(logEvent); - } -} diff --git a/SpigotCore_15/src/de/steamwar/core/SpigotTPS_15.java b/SpigotCore_Main/src/de/steamwar/core/FlatteningWrapper.java similarity index 61% rename from SpigotCore_15/src/de/steamwar/core/SpigotTPS_15.java rename to SpigotCore_Main/src/de/steamwar/core/FlatteningWrapper.java index 46c1186..ca673c0 100644 --- a/SpigotCore_15/src/de/steamwar/core/SpigotTPS_15.java +++ b/SpigotCore_Main/src/de/steamwar/core/FlatteningWrapper.java @@ -19,14 +19,20 @@ package de.steamwar.core; -import net.minecraft.server.v1_15_R1.MinecraftServer; +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; -public class SpigotTPS_15 { +public class FlatteningWrapper { + private FlatteningWrapper() {} - private SpigotTPS_15(){} + public static final IFlatteningWrapper impl = VersionDependent.getVersionImpl(Core.getInstance()); - static double[] getTps(){ - return MinecraftServer.getServer().recentTps; + public interface IFlatteningWrapper { + void setScoreboardTitle(Object packet, String title); + void setScoreAction(Object packet); + + Material getMaterial(String material); + Material getDye(int colorCode); + ItemStack setSkullOwner(String player); } - } 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/WorldEditWrapper.java b/SpigotCore_Main/src/de/steamwar/core/WorldEditWrapper.java new file mode 100644 index 0000000..920bc9f --- /dev/null +++ b/SpigotCore_Main/src/de/steamwar/core/WorldEditWrapper.java @@ -0,0 +1,26 @@ +package de.steamwar.core; + +import com.sk89q.worldedit.bukkit.WorldEditPlugin; +import com.sk89q.worldedit.extent.clipboard.Clipboard; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +import java.io.IOException; +import java.io.InputStream; + +public class WorldEditWrapper { + private WorldEditWrapper() {} + + public static final IWorldEditWrapper impl = VersionDependent.getVersionImpl(Core.getInstance()); + + public interface IWorldEditWrapper { + byte[] getPlayerClipboard(Player player, boolean schemFormat); + void setPlayerClipboard(Player player, InputStream is, boolean schemFormat); + Clipboard getClipboard(InputStream is, boolean schemFormat) throws IOException; + + } + + static WorldEditPlugin getWorldEditPlugin() { + return (WorldEditPlugin) Bukkit.getPluginManager().getPlugin("WorldEdit"); + } +} diff --git a/SpigotCore_8/src/de/steamwar/comms/BungeeReceiver_8.java b/SpigotCore_Main/src/de/steamwar/core/WorldOfColorWrapper.java similarity index 72% rename from SpigotCore_8/src/de/steamwar/comms/BungeeReceiver_8.java rename to SpigotCore_Main/src/de/steamwar/core/WorldOfColorWrapper.java index 2b2ce08..70f7269 100644 --- a/SpigotCore_8/src/de/steamwar/comms/BungeeReceiver_8.java +++ b/SpigotCore_Main/src/de/steamwar/core/WorldOfColorWrapper.java @@ -15,16 +15,20 @@ You should have received a copy of the GNU Affero General Public License 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 { +import java.util.Locale; - public static void playPling(Player player) { - player.playSound(player.getLocation(), Sound.ORB_PICKUP, 1, 1); +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/authlib/AuthlibInjector.java b/SpigotCore_Main/src/de/steamwar/core/authlib/AuthlibInjector.java similarity index 51% rename from SpigotCore_Main/src/de/steamwar/authlib/AuthlibInjector.java rename to SpigotCore_Main/src/de/steamwar/core/authlib/AuthlibInjector.java index f12bd3d..ace4936 100644 --- a/SpigotCore_Main/src/de/steamwar/authlib/AuthlibInjector.java +++ b/SpigotCore_Main/src/de/steamwar/core/authlib/AuthlibInjector.java @@ -17,31 +17,19 @@ * along with this program. If not, see . */ -package de.steamwar.authlib; +package de.steamwar.core.authlib; +import com.comphenix.tinyprotocol.Reflection; +import com.mojang.authlib.GameProfileRepository; import com.mojang.authlib.yggdrasil.YggdrasilGameProfileRepository; -import de.steamwar.core.Core; -import de.steamwar.core.VersionedCallable; - -import java.lang.reflect.Field; public class AuthlibInjector { + private AuthlibInjector() {} public static void inject() { - if (Core.getVersion() != 15) { - return; - } - - try { - Class minecraftServerClass = VersionedCallable.call(new VersionedCallable<>(() -> AuthlibInjector_15.getMinecraftClass(), 15)); - Field repo = minecraftServerClass.getDeclaredField("gameProfileRepository"); - repo.setAccessible(true); - Object instance = VersionedCallable.call(new VersionedCallable<>(() -> AuthlibInjector_15.getMinecraftServerInstance(), 15)); - repo.set(instance, new SteamwarGameProfileRepository((YggdrasilGameProfileRepository) repo.get(instance))); - } catch (NoSuchFieldException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } + Class minecraftServerClass = Reflection.getClass("{nms}.MinecraftServer"); + Reflection.FieldAccessor gameProfile = Reflection.getField(minecraftServerClass, GameProfileRepository.class, 0); + Object minecraftServer = Reflection.getTypedMethod(minecraftServerClass, "getServer", minecraftServerClass).invoke(null); + gameProfile.set(minecraftServer, new SteamwarGameProfileRepository((YggdrasilGameProfileRepository) gameProfile.get(minecraftServer))); } } diff --git a/SpigotCore_Main/src/de/steamwar/authlib/SteamwarGameProfileRepository.java b/SpigotCore_Main/src/de/steamwar/core/authlib/SteamwarGameProfileRepository.java similarity index 98% rename from SpigotCore_Main/src/de/steamwar/authlib/SteamwarGameProfileRepository.java rename to SpigotCore_Main/src/de/steamwar/core/authlib/SteamwarGameProfileRepository.java index 3a4ebae..9045de1 100644 --- a/SpigotCore_Main/src/de/steamwar/authlib/SteamwarGameProfileRepository.java +++ b/SpigotCore_Main/src/de/steamwar/core/authlib/SteamwarGameProfileRepository.java @@ -17,7 +17,7 @@ * along with this program. If not, see . */ -package de.steamwar.authlib; +package de.steamwar.core.authlib; import com.mojang.authlib.Agent; import com.mojang.authlib.GameProfile; diff --git a/SpigotCore_Main/src/de/steamwar/core/events/ChunkListener.java b/SpigotCore_Main/src/de/steamwar/core/events/ChunkListener.java index d6bf688..fe285fe 100644 --- a/SpigotCore_Main/src/de/steamwar/core/events/ChunkListener.java +++ b/SpigotCore_Main/src/de/steamwar/core/events/ChunkListener.java @@ -19,64 +19,42 @@ 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; + + 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..9f7c2b0 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() { @@ -90,6 +87,7 @@ public class SWItem { this(material, (byte)0, name, lore, enchanted, c); } + @SuppressWarnings("deprecation") public SWItem(Material material, byte meta, String name, List lore, boolean enchanted, InvCallback c) { try { itemStack = new ItemStack(material, 1, (short)0, meta); diff --git a/SpigotCore_Main/src/de/steamwar/message/Message.java b/SpigotCore_Main/src/de/steamwar/message/Message.java index 7ae38e0..efdf651 100644 --- a/SpigotCore_Main/src/de/steamwar/message/Message.java +++ b/SpigotCore_Main/src/de/steamwar/message/Message.java @@ -19,7 +19,8 @@ package de.steamwar.message; -import de.steamwar.core.VersionedCallable; +import de.steamwar.core.BountifulWrapper; +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 +74,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 */ @@ -109,10 +109,11 @@ public class Message { msg.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.fromLegacyText(onHover))); if(onClick != null) msg.setClickEvent(onClick); + if(sender instanceof Player) - ((Player)sender).spigot().sendMessage(type, msg); + BountifulWrapper.impl.sendMessage((Player)sender, type, msg); else - sender.spigot().sendMessage(msg); + sender.sendMessage(msg.toPlainText()); } /* Send message to all players */ diff --git a/SpigotCore_Main/src/de/steamwar/scoreboard/SWScoreboard.java b/SpigotCore_Main/src/de/steamwar/scoreboard/SWScoreboard.java index 809fc30..67cbeaa 100644 --- a/SpigotCore_Main/src/de/steamwar/scoreboard/SWScoreboard.java +++ b/SpigotCore_Main/src/de/steamwar/scoreboard/SWScoreboard.java @@ -19,57 +19,69 @@ 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]; + + public 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 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 +93,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); + FlatteningWrapper.impl.setScoreAction(packet); 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/SQL.java b/SpigotCore_Main/src/de/steamwar/sql/SQL.java index bbe2701..65546cd 100644 --- a/SpigotCore_Main/src/de/steamwar/sql/SQL.java +++ b/SpigotCore_Main/src/de/steamwar/sql/SQL.java @@ -24,18 +24,18 @@ import org.bukkit.configuration.file.YamlConfiguration; import java.io.File; import java.sql.*; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Level; public class SQL { - private SQL(){} - private static final String host; - private static final String port; - private static final String database; - private static final String user; - private static final String password; private static Connection con; + private static String url; + private static String user; + private static String password; static{ File file = new File(Core.getInstance().getDataFolder(), "MySQL.yml"); @@ -44,20 +44,47 @@ public class SQL { if(!file.exists()) throw new SecurityException("SQL-ConfigFile not found!"); - host = config.getString("HOST"); - port = config.getString("PORT"); - database = config.getString("DATABASE"); + url = "jdbc:mysql://" + config.getString("HOST") + ":" + config.getString("PORT") + "/" + config.getString("DATABASE"); user = config.getString("USER"); password = config.getString("PASSWORD"); connect(); } - - public static void closeConnection() { + + private static void connect() { + try { + con = DriverManager.getConnection(url + "?autoreconnect=true", user, password); + } catch (SQLException e) { + throw new SecurityException("Could not start SQL connection", e); + } + } + + public static void close() { + for (Statement statement : Statement.statements) { + try { + statement.st.close(); + } catch (SQLException e) { + Core.getInstance().getLogger().log(Level.INFO, "Could not close statement", e); + } + } + try { con.close(); - }catch (SQLException e) { - throw new SecurityException("Could not close connection", e); + } catch (SQLException e) { + Core.getInstance().getLogger().log(Level.WARNING, "Could not close SQL-Connection", e); + } + } + + private static void reset(SQLException e) { + Core.getInstance().getLogger().log(Level.WARNING, "SQL Exception thrown", e); + close(); + connect(); + try { + for (Statement statement : Statement.statements) { + statement.init(); + } + } catch (SQLException ex) { + throw new SecurityException("Could not reprepare SQL Statements", ex); } } @@ -65,7 +92,7 @@ public class SQL { try { prepare(qry, objects).executeUpdate(); } catch (SQLException e) { - reconnect(); + reset(e); try { prepare(qry, objects).executeUpdate(); } catch (SQLException ex) { @@ -78,7 +105,7 @@ public class SQL { try { return prepare(qry, objects).executeQuery(); } catch (SQLException e) { - reconnect(); + reset(e); try { return prepare(qry, objects).executeQuery(); } catch (SQLException ex) { @@ -91,7 +118,7 @@ public class SQL { try { return con.createBlob(); } catch (SQLException e) { - reconnect(); + reset(e); try { return con.createBlob(); } catch (SQLException ex) { @@ -108,18 +135,66 @@ public class SQL { return st; } - private static void connect() { - try { - con = DriverManager.getConnection("jdbc:mysql://" + host + ":" + port + "/" + database + "?autoreconnect=true", user, password); - if(con.isClosed()) - throw new SQLException("Could not connect to database!"); - }catch (SQLException e) { - throw new SecurityException("No connection to database.", e); + public static class Statement { + private static final List statements = new ArrayList<>(); + + private final String sql; + private PreparedStatement st; + + Statement(String sql) { + this.sql = sql; + statements.add(this); + try { + init(); + } catch (SQLException e) { + reset(e); + } + } + + private synchronized void init() throws SQLException { + st = con.prepareStatement(sql); + } + + T select(ResultSetUser user, Object... objects) { + return prepare(() -> { + ResultSet rs = st.executeQuery(); + T result = user.use(rs); + rs.close(); + return result; + }, objects); + } + + void update(Object... objects) { + prepare(st::executeUpdate, objects); + } + + private synchronized T prepare(SQLRunnable runnable, Object... objects) { + try { + setObjects(objects); + return runnable.run(); + } catch (SQLException e) { + reset(e); + try { + setObjects(objects); + return runnable.run(); + } catch (SQLException ex) { + throw new SecurityException("Could not execute SQL statement", ex); + } + } + } + + private void setObjects(Object... objects) throws SQLException { + for (int i = 0; i < objects.length; i++) { + st.setObject(i + 1, objects[i]); + } + } + + interface ResultSetUser { + T use(ResultSet rs) throws SQLException; + } + + private interface SQLRunnable { + T run() throws SQLException; } } - - private static void reconnect(){ - closeConnection(); - connect(); - } } diff --git a/SpigotCore_Main/src/de/steamwar/sql/SWException.java b/SpigotCore_Main/src/de/steamwar/sql/SWException.java index efee8ad..850c124 100644 --- a/SpigotCore_Main/src/de/steamwar/sql/SWException.java +++ b/SpigotCore_Main/src/de/steamwar/sql/SWException.java @@ -19,101 +19,13 @@ package de.steamwar.sql; -import org.apache.logging.log4j.core.LogEvent; import org.bukkit.Bukkit; import org.bukkit.entity.Player; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - public class SWException { private SWException(){} - private static boolean logDisabled = false; - private static final List ignorereasons; - - static { - List reasons = new ArrayList<>(); - reasons.add("Could not save the list after adding a user."); - reasons.add("Could not save spigot.yml"); - reasons.add("Failed to save operators list:"); - reasons.add("Block at"); - reasons.add("POI data mismatch"); - reasons.add("handleDisconnection() called twice"); - reasons.add("**** SERVER IS RUNNING IN OFFLINE/INSECURE MODE!"); - reasons.add("The server will make no attempt to authenticate usernames. Beware."); - reasons.add("Whilst this makes it possible to use BungeeCord,"); - reasons.add("Please see http://www.spigotmc.org/wiki/firewall-guide/ for further information."); - reasons.add("To change this, set \"online-mode\" to \"true\" in the server.properties file."); - reasons.add("This crash report has been saved to:"); - reasons.add("Could not pass event PlayerQuitEvent to WorldEditSUI"); - reasons.add("[ViaVersion] "); - reasons.add("[ViaBackwards] "); - reasons.add("Something went wrong upgrading!"); - reasons.add("Tried to load unrecognized recipe"); - reasons.add("Invalid BlockState in palette:"); - reasons.add("Could not register alias"); - reasons.add("Can't keep up! Is the server overloaded?"); - reasons.add("\tat "); - reasons.add("java.lang.Exception"); - reasons.add("An exceptionCaught()"); - reasons.add("Exception verifying"); - reasons.add("[WorldEditSUI]"); - reasons.add("Unsupported key:"); - reasons.add("ThrownPotion entity"); - reasons.add("Couldn't load custom particle"); - reasons.add("Chunk file at ["); - reasons.add("Ignoring unknown attribute"); - reasons.add("Skipping player strafe phase because no player was found"); - reasons.add("Couldn't save chunk; already in use by another instance of Minecraft?"); - reasons.add("Failed to save player data for "); - reasons.add("Failed to check session lock for world located at"); - reasons.add("Saving oversized chunk "); - ignorereasons = Collections.unmodifiableList(reasons); - } - - public static void log(LogEvent logEvent){ - if(logDisabled) - return; - - String message = logEvent.getMessage().getFormattedMessage(); - for(String reason : ignorereasons) - if(message.startsWith(reason)) - return; - - if(message.contains("moved too quickly!") || message.contains("moved wrongly!") || message.contains("was kicked for floating too long!") || message.contains("just tried to change non-editable sign")) - return; - - switch (message) { - case "The server has stopped responding!": - logDisabled = true; - return; - case "------------------------------": - message = "Server stopped responding"; - logDisabled = true; - break; - case "Exception stopping the server": - logDisabled = true; - break; - default: - } - - StringBuilder stacktrace = new StringBuilder(logEvent.getSource().toString()); - Throwable throwable = logEvent.getThrown(); - while(throwable != null){ - stacktrace.append("\nCaused by ").append(throwable.getClass().getName()).append(": ").append(throwable.getMessage()); - - for(StackTraceElement ste : throwable.getStackTrace()) - stacktrace.append("\n").append(ste.toString()); - - throwable = throwable.getCause(); - } - - String st = stacktrace.toString(); - if(st.contains("POI data mismatch")) - return; - + public static void log(String message, String stacktrace){ message += "\n"; for(Player player : Bukkit.getOnlinePlayers()) message += player.getName() + " "; @@ -124,7 +36,6 @@ public class SWException { else server = Bukkit.getWorlds().get(0).getName(); - SQL.update("INSERT INTO Exception (server, message, stacktrace) VALUES (?, ?, ?)", - server, message, st); + SQL.update("INSERT INTO Exception (server, message, stacktrace) VALUES (?, ?, ?)", server, message, stacktrace); } } diff --git a/SpigotCore_Main/src/de/steamwar/sql/Schematic.java b/SpigotCore_Main/src/de/steamwar/sql/Schematic.java index a7d8c45..dbbd123 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.WorldEditWrapper; import org.bukkit.entity.Player; import java.io.IOException; @@ -36,6 +35,8 @@ import java.util.zip.GZIPInputStream; public class Schematic { + private static final SQL.Statement getSchemsOfType = new SQL.Statement("SELECT DISTINCT s.SchemID, s.SchemName, s.SchemOwner, s.Item, s.SchemType, s.Rank, s.SchemFormat FROM Schematic s LEFT JOIN SchemMember sm ON sm.SchemName = s.SchemName AND sm.SchemOwner = s.SchemOwner WHERE s.SchemType = ? AND (s.SchemOwner = ? OR sm.Member = ?) ORDER BY s.SchemName"); + private final int schemID; private final String schemName; private final int schemOwner; @@ -104,7 +105,7 @@ public class Schematic { public static List getSchemsAccessibleByUser(int schemOwner){ try{ - ResultSet schematic = SQL.select("SELECT s.SchemID, s.SchemName, s.SchemOwner, s.Item, s.SchemType, s.Rank, s.SchemFormat FROM Schematic s LEFT JOIN SchemMember sm ON sm.SchemName = s.SchemName AND sm.SchemOwner = s.SchemOwner WHERE s.SchemOwner = ? OR sm.Member = ? GROUP BY s.SchemID ORDER BY s.SchemName", schemOwner, schemOwner); + ResultSet schematic = SQL.select("SELECT DISTINCT s.SchemID, s.SchemName, s.SchemOwner, s.Item, s.SchemType, s.Rank, s.SchemFormat FROM Schematic s LEFT JOIN SchemMember sm ON sm.SchemName = s.SchemName AND sm.SchemOwner = s.SchemOwner WHERE s.SchemOwner = ? OR sm.Member = ? ORDER BY s.SchemName", schemOwner, schemOwner); List schematics = new ArrayList<>(); while(schematic.next()) schematics.add(new Schematic(schematic)); @@ -119,12 +120,12 @@ public class Schematic { } public static List getSchemsOfType(int schemOwner, SchematicType schemType){ - //Unsauber, dafür auch geaddede Schematics dabei - List schems = getSchemsAccessibleByUser(schemOwner); - for(int i = schems.size()-1; i >= 0; i--) - if(!schems.get(i).getSchemType().equals(schemType)) - schems.remove(i); - return schems; + return getSchemsOfType.select(rs -> { + List schematics = new ArrayList<>(); + while(rs.next()) + schematics.add(new Schematic(rs)); + return schematics; + }, schemType.toDB(), schemOwner, schemOwner); } public static List getAllSchemsOfType(SchematicType schemType){ @@ -197,8 +198,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 WorldEditWrapper.impl.getClipboard(is, schemFormat); + } catch (IOException e) { + throw new SecurityException("Could not read schem", e); + } } public Clipboard load() throws IOException, NoClipboardException { @@ -207,8 +211,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)); + WorldEditWrapper.impl.setPlayerClipboard(player, is, schemFormat); } public void saveOldFormatFromPlayer(Player player) throws IOException, NoClipboardException { @@ -231,21 +234,12 @@ 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, WorldEditWrapper.impl.getPlayerClipboard(player, newFormat)); + } catch (SQLException e) { + throw new SecurityException(e.getMessage(), e); + } + updateDatabase(blob, newFormat); } 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 new file mode 100644 index 0000000..87b87f4 --- /dev/null +++ b/build.gradle @@ -0,0 +1,236 @@ +/* + * 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 . + */ + + +import org.apache.tools.ant.taskdefs.condition.Os + +import java.util.function.BiConsumer + +plugins { + // Adding the base plugin fixes the following gradle warnings in IntelliJ: + // + // Warning: root project 'module-work-multi': Unable to resolve all content root directories + // Details: java.lang.IllegalStateException: No value has been specified for this provider. + // + // Warning: root project 'module-work-multi': Unable to resolve additional project configuration. + // Details: java.lang.IllegalStateException: No value has been specified for this provider. + id 'base' + id 'application' + + id 'com.github.johnrengelman.shadow' version '5.0.0' +} + +group 'de.steamwar' +version '' + +Properties steamwarProperties = new Properties() +if (file("steamwar.properties").exists()) { + steamwarProperties.load(file("steamwar.properties").newDataInputStream()) +} + +ext { + buildName = 'SpigotCore' + artifactName = 'spigotcore' + + uberJarName = "${buildName}-all.jar" + jarName = "${artifactName}.jar" + libs = "${buildDir}/libs" + + if (Os.isFamily(Os.FAMILY_WINDOWS)) { + operatingSystem = "windows" + } else { + operatingSystem = "unix" + } +} + +compileJava.options.encoding = 'UTF-8' + +sourceCompatibility = 1.8 +targetCompatibility = 1.8 + +mainClassName = '' + +allprojects { + repositories { + mavenCentral() + jcenter() + + maven { + url = uri("https://repo.codemc.io/repository/maven-snapshots/") + } + } +} + +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 { + description 'Build this project' + group "Steamwar" + + dependsOn build +} + +task finalizeProject { + description 'Finalize this project' + group "Steamwar" + + doLast { + if ("${buildDir}" == null) { + return + } + delete fileTree("${libs}").matching { + exclude("${uberJarName}") + } + file(libs + "/" + uberJarName).renameTo(file(libs + "/" + jarName)) + } +} +build.finalizedBy(finalizeProject) + +if (steamwarProperties.containsKey("hostname")) { + String hostname = steamwarProperties.get("hostname") + String uploadPath = steamwarProperties.getOrDefault("uploadPath", "~") + + String server = steamwarProperties.getOrDefault("server", "Dev1.15") + String serverStartFlags = steamwarProperties.getOrDefault("serverStartFlags", "") + + task uploadProject { + description 'Upload this project' + group "Steamwar" + + doLast { + await(shell("scp ${libs}/${jarName} ${hostname}:${uploadPath}/${server}/plugins")) + if (!answer("Start ${server} server?")) { + return + } + serverStart(server, serverStartFlags, hostname) + } + } + uploadProject.dependsOn(buildProject) + + task startDevServer { + description 'Start the DevServer' + group "Steamwar" + + doLast { + serverStart(server, serverStartFlags, hostname) + } + } +} + +private def await(Process proc) { + def out = new StringBuilder() + def err = new StringBuilder() + proc.waitForProcessOutput(out, err) + return [out, err, proc.exitValue()] +} + +private def shell(String command) { + if (operatingSystem == "unix") { + return ['bash', '-c', command].execute() + } else { + return ["cmd", "/c", command].execute() + } +} + +private def serverStart(String serverName, String serverFlags, String hostname) { + def proc = shell("ssh -t ${hostname} \"./mc ${serverFlags} ${serverName}\"") + + Set strings = new HashSet<>() + File file = new File("${projectDir}/ignoredlog"); + if (file.exists()) { + new BufferedReader(new InputStreamReader(new FileInputStream(file))).readLines().forEach({ s -> + strings.add(s) + }) + } + + Thread outputThread = new Thread({ + Reader reader = proc.getInputStream().newReader(); + Writer writer = System.out.newWriter(); + try { + while (proc.alive) { + String s = reader.readLine() + if (s == null) { + return + } + if (strings.stream().anyMatch({check -> s.contains(check)})) { + continue + } + writer.write(s + "\n") + writer.flush() + } + } catch (IOException e) { + // Ignored + } + }) + outputThread.setName("${serverName} - OutputThread") + outputThread.start() + + Writer writer + Thread inputThread = new Thread({ + Reader reader = System.in.newReader() + writer = proc.getOutputStream().newWriter() + try { + while (proc.alive) { + String s = reader.readLine() + writer.write(s + "\n") + writer.flush() + } + } catch (IOException e) { + // Ignored + } + }) + inputThread.setName("${serverName} - InputThread") + inputThread.start() + + gradle.buildFinished { buildResult -> + if (!proc.alive) { + return + } + writer = proc.getOutputStream().newWriter() + writer.write("stop\n") + writer.flush() + awaitClose(proc, outputThread, inputThread) + } + awaitClose(proc, outputThread, inputThread) +}; + +private static def awaitClose(Process proc, Thread outputThread, Thread inputThread) { + while (proc.alive) { + Thread.sleep(10) + } + proc.closeStreams() + outputThread.interrupt() + inputThread.interrupt() +} + +private def answer(String question) { + while (System.in.available() > 0) System.in.read() + println(question) + boolean valid = "Yy".contains(((char) System.in.read()).toString()) + while (System.in.available() > 0) System.in.read() + return valid +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..dc56501 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,22 @@ +# +# 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 . +# + +org.gradle.daemon = true +org.gradle.parallel = true +org.gradle.workers.max = 4 \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..f3d88b1 Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..099d7b2 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Wed May 05 10:45:33 CEST 2021 +distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStorePath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew new file mode 100755 index 0000000..2fe81a7 --- /dev/null +++ b/gradlew @@ -0,0 +1,183 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..9618d8d --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,100 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/ignoredlog b/ignoredlog new file mode 100644 index 0000000..b28379b --- /dev/null +++ b/ignoredlog @@ -0,0 +1,2 @@ +SteamWar? Unbekannter Befehl. +moved too quickly! \ No newline at end of file diff --git a/pom.xml b/pom.xml deleted file mode 100644 index 43dabfc..0000000 --- a/pom.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - 4.0.0 - - steamwar - SpigotCore - 2.0 - pom - https://maven.apache.org - - - UTF-8 - ${project.basedir} - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.6.1 - - 1.8 - 1.8 - - - - ${project.name} - - - - SpigotCore_API - SpigotCore_8 - SpigotCore_9 - SpigotCore_10 - SpigotCore_12 - SpigotCore_14 - SpigotCore_15 - SpigotCore_Main - - \ No newline at end of file diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..44cbeeb --- /dev/null +++ b/settings.gradle @@ -0,0 +1,28 @@ +/* + * 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' + +include 'SpigotCore_Main' +include 'SpigotCore_15' +include 'SpigotCore_14' +include 'SpigotCore_12' +include 'SpigotCore_10' +include 'SpigotCore_9' +include 'SpigotCore_8'