diff --git a/BauSystem_15/src/de/steamwar/bausystem/features/slaves/MaterialUtils_15.java b/BauSystem_15/src/de/steamwar/bausystem/features/slaves/MaterialUtils_15.java new file mode 100644 index 00000000..d8a0df55 --- /dev/null +++ b/BauSystem_15/src/de/steamwar/bausystem/features/slaves/MaterialUtils_15.java @@ -0,0 +1,53 @@ +/* + * 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.bausystem.features.slaves; + +import lombok.experimental.UtilityClass; +import net.minecraft.server.v1_15_R1.WorldGenVines; +import org.bukkit.Material; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +@UtilityClass +public class MaterialUtils_15 { + + private static Set unpushable = new HashSet<>(Arrays.asList(Material.BARRIER, Material.BEACON, Material.COMMAND_BLOCK, Material.CHAIN_COMMAND_BLOCK, Material.REPEATING_COMMAND_BLOCK, Material.ENCHANTING_TABLE, Material.END_GATEWAY, Material.END_PORTAL, Material.ENDER_CHEST, Material.GRINDSTONE, Material.JIGSAW, Material.JUKEBOX, Material.NETHER_PORTAL, Material.OBSIDIAN, Material.STRUCTURE_VOID, Material.BARREL, Material.BEEHIVE, Material.BEE_NEST, Material.BLAST_FURNACE, Material.BREWING_STAND, Material.CHEST, Material.DAYLIGHT_DETECTOR, Material.DISPENSER, Material.DROPPER, Material.FURNACE, Material.HOPPER, Material.LECTERN, Material.SMOKER, Material.TRAPPED_CHEST)); + + // TODO: FLOWER + private static Set breaking = new HashSet<>(Arrays.asList(Material.BAMBOO, Material.CACTUS, Material.CAKE, Material.CARVED_PUMPKIN, Material.CHORUS_FLOWER, Material.CHORUS_PLANT, Material.COBWEB, Material.COCOA, Material.DRAGON_EGG, Material.FIRE, Material.FLOWER_POT, Material.JACK_O_LANTERN, Material.LADDER, Material.LAVA, Material.LAVA, Material.LEVER, Material.LILY_PAD, Material.MELON, Material.NETHER_WART, Material.PUMPKIN, Material.COMPARATOR, Material.REDSTONE_WIRE, Material.REPEATER, Material.TORCH, Material.STRUCTURE_VOID, Material.SCAFFOLDING, Material.SEA_PICKLE, Material.SNOW, Material.SUGAR_CANE, Material.TORCH, Material.TRIPWIRE, Material.TRIPWIRE_HOOK, Material.TURTLE_EGG, Material.VINE, Material.WATER, Material.WHEAT)); + + static boolean isUnpusheable(Material material) { + if (unpushable.contains(material)) { + return true; + } + String name = material.name(); + return name.contains("BANNER") || name.contains("SIGN"); + } + + static boolean isBreakingOnPush(Material material) { + if (breaking.contains(material)) { + return true; + } + String name = material.name(); + return name.contains("BED") || name.contains("BUTTON") || name.contains("CARPET") || (name.contains("DOOR") && !name.contains("TRAPDOOR")) || name.contains("HEAD") || name.contains("LEAVES") || name.contains("MUSHROOM") || name.contains("PRESSURE_PLATE") || name.contains("SHULKER_BOX"); + } +} diff --git a/BauSystem_Main/build.gradle b/BauSystem_Main/build.gradle index 9629d086..32d7760b 100644 --- a/BauSystem_Main/build.gradle +++ b/BauSystem_Main/build.gradle @@ -61,6 +61,5 @@ dependencies { compileOnly files("${projectDir}/../lib/Spigot-1.15.jar") compileOnly files("${projectDir}/../lib/WorldEdit-1.15.jar") - compileOnly files("${projectDir}/../lib/ProtocolLib.jar") compileOnly files("${projectDir}/../lib/SpigotCore.jar") } diff --git a/BauSystem_Main/src/BauSystem.properties b/BauSystem_Main/src/BauSystem.properties index 31feca0d..4458cbf0 100644 --- a/BauSystem_Main/src/BauSystem.properties +++ b/BauSystem_Main/src/BauSystem.properties @@ -38,7 +38,6 @@ SCOREBOARD_LOADER = Loader SCOREBOARD_TPS = TPS SCOREBOARD_TRACE_TICKS = Ticks -SCOREBOARD_TRACE_TNT-COUNT = Anzahl TNT # Flags FLAG_COLOR = Color @@ -96,7 +95,7 @@ AUTOSTART_MESSAGE_NO-REGION = §cDu befindest dich derzeit in keiner Region AUTOSTART_MESSAGE_RESET = §eDer AutostartTimer wurde zurückgesetzt AUTOSTART_MESSAGE_START = §eAutostartTimer gestartet AUTOSTART_MESSAGE_RESULT1 = §eZeit §7bis zur §eExplosion §7am Gegner§8:§e {0} -AUTOSTART_MESSAGE_RESULT2 = §eZeitdifferenz in ticks §7bis 60 Sekunden§8:§e {0} +AUTOSTART_MESSAGE_RESULT2 = §eZeitdifferenz in ticks §7bis {0} Sekunden§8:§e {1} AUTOSTART_MESSAGE_RESULT3 = §7Positiv, wenn zu wenig, negativ wenn zu viel # Backup @@ -171,8 +170,8 @@ DETONATOR_AUTOSTART_ENABLE=§7Autostart beim detonate §aangeschaltet DETONATOR_AUTOSTART_DISABLE=§7Autostart beim detonate §causgeschaltet DETONATOR_POINT_ACT=§eEinen Punkt ausgelöst DETONATOR_POINTS_ACT=§e{0} Punkte ausgelöst -DETONATOR_INVALID_POINT=§cEin Punkt konnte nicht ausgeführt werden und wurde entfernt -DETONATOR_INVALID_POINTS=§c{0} Punkte konnten nicht ausgeführt werden und wurden entfernt +DETONATOR_INVALID_POINT=§cEin Punkt konnte nicht ausgeführt werden +DETONATOR_INVALID_POINTS=§c{0} Punkte konnten nicht ausgeführt werden DETONATOR_INVALID_BLOCK=§eDer Block konnte nicht hinzugefügt werden # Hotbar HOTBAR_SAVED=§7Deine Hotbar wurde als Standard gespeichert @@ -199,6 +198,13 @@ GUI_EDITOR_ITEM_TRASH=§cTrashcan GUI_EDITOR_ITEM_TRASH_LORE=§7Item hier rein Legen GUI_EDITOR_ITEM_MORE=§eMehr Items GUI_EDITOR_TITLE_MORE=Item auswählen + +# SmartPlace +SMART_PLACE_HELP = §8/§esmartplace §8-§7 Toggled SmartPlace +SMART_PLACE_INFO = §7Plaziert rotierbare Blöcke beim §esneaken§7 von dir §eweg§7. +SMART_PLACE_ENABLE = §aSmartPlace aktiviert +SMART_PLACE_DISABLE = §cSmartPlace deaktiviert + # Trace TRACE_RECORD=§aan TRACE_RECORD-AUTO=§aan @@ -245,6 +251,18 @@ TRACE_SHOW_GUI_INTERPOLATE-XZ_ITEM = §eInterpolation §7XZ-Achse TRACE_SHOW_GUI_INTERPOLATE-XZ_LORE1 = §7Zeigt die Interpolation TRACE_SHOW_GUI_INTERPOLATE-XZ_LORE2 = §7auf der XZ-Achse. +TRACE_GUI_TITLE = Trace GUI +TRACE_GUI_ITEM_BACK = §eBack +TRACE_GUI_ITEM = §eTrace §8- §e{0} §7TNT +TRACE_GUI_CLEAR = §eTraces löschen +TRACE_GUI_RECORD_ITEM = §eTNT §8- §e{0} §7Positionen +TRACE_GUI_RECORD_CLEAR = §eTNT löschen +TRACE_GUI_POSITION_ITEM = §ePosition +TRACE_GUI_POSITION_X = §7X§8: §e{0} +TRACE_GUI_POSITION_Y = §7Y§8: §e{0} +TRACE_GUI_POSITION_Z = §7Z§8: §e{0} +TRACE_GUI_POSITION_EXPLODED = §7Explodiert§8: §e{0} + # Loader LOADER_OFF = §caus LOADER_SETUP = §eSetup @@ -365,9 +383,12 @@ OTHER_TELEPORT_SELF_4=§cFür eine solche Distanz? OTHER_TIME_HELP_1=§8/§etime §8<§7Zeit 0=Morgen§8, §76000=Mittag§8, §718000=Mitternacht§8> - §7Setzt die Zeit auf dem Bau OTHER_TIME_NO_PERM=§cDu darfst hier nicht die Zeit ändern OTHER_TIME_INVALID=§cBitte gib eine Zahl zwischen 0 und 24000 an +OTHER_TIME_RESULT=§7§oWhooosh OTHER_WORLDSPAWN_HELP_1=§8/§eworldspawn §8-§e Teleportiere dich zum Spawn # DebugStick DEBUG-STICK_COMMAND_HELP=§8/§edebugstick §8-§7 Erhalte einen DebugStick +# StructureVoid +STRUCTURE-VOID_COMMAND_HELP=§8/§estructureVoid §8-§7 Erhalte ein StructureVoid # NightVision NIGHT-VISION_COMMAND_HELP=§8/§enightvision §8-§7 Schalte Nightvision an oder aus. NIGHT-VISION_OFF=§eNightvision deaktiviert @@ -383,12 +404,15 @@ MATERIAL_SEARCH_GRAVITY=§eFallend MATERIAL_SEARCH_OCCLUDING=§eOccluding MATERIAL_SEARCH_INTERACTEABLE=§eInterargierbar MATERIAL_SEARCH_FLAMMABLE=§eFlammbar +MATERIAL_SEARCH_BURNABLE=§eBrennbar +MATERIAL_SEARCH_WATERLOGGABLE=§eWasserspeicherbar MATERIAL_SEARCH_BLASTRESISTANCE=§eBlast Resistance MATERIAL_SEARCH_BLASTRESISTANCE_MIN=§eBlast Resistance mindestens MATERIAL_SEARCH_BLASTRESISTANCE_MAX=§eBlast Resistance maximal MATERIAL_SEARCH_BLASTRESISTANCE_EXACT=§eBlast Resistance MATERIAL_SEARCH_VALUE=§8: §e{0} MATERIAL_BLAST-RESISTANCE=§8- §eBlast Resistance§8: §7{0} +MATERIAL_HARDNESS=§8- §eHärte§8: §7{0} MATERIAL_TNT_BREAKABLE=§8- §eZerstörbar durch TNT MATERIAL_TNT_UNBREAKABLE=§8- §eNicht Zerstörbar durch TNT MATERIAL_TRANSPARENT=§8- §eTransparenter Block @@ -397,6 +421,8 @@ MATERIAL_GRAVITY=§8- §eFallender Block MATERIAL_OCCLUDING=§8- §eOccluding Block MATERIAL_INTERACT-ABLE=§8- §eInterargierbarer Block MATERIAL_FLAMMABLE=§8- §eFlammbarer Block +MATERIAL_BURNABLE=§8- §eBrennbarer Block +MATERIAL_WATERLOGGABLE=§8- §eWasserspeicherbarer Block # Redstonetester RT_HELP_1=§8/§eredstonetester §8-§7 Gibt den RedstoneTester RT_GIVEN=§7Messe die Zeit zwischen der Aktivierung zweier Redstone Komponenten @@ -457,6 +483,7 @@ REGION_REGION_HELP_4=§8/§eregion §8[§7RegionsTyp§8] §8- §7Wähle einen Re REGION_REGION_HELP_5=§8/§eregion §8[§7RegionsTyp§8] §8[§7Extension§8] §8- §7Wähle einen RegionsTyp aus mit oder ohne Extension REGION_REGION_HELP_6=§8/§eregion color §8[§7Color§8] §8- §7Ändere die Regions Farbe REGION_REGION_HELP_7=§8/§eregion copypoint §8- §7Teleportiere dich zum Regions Kopierpunkt +REGION_REGION_HELP_8=§8/§eregion testblockpoint §8- §7Teleportiere dich zum Regions Testblockpunkt REGION_REGION_NOTHING_UNDO=§cNichts zum rückgängig machen REGION_REGION_UNDID=§7Letzte Aktion rückgangig gemacht REGION_REGION_NOTHING_REDO=§cNichts zum wiederhohlen @@ -468,6 +495,8 @@ REGION_REGION_COLORED_FAILED=§7Nutze §e/rg restore§7 um manuell die Farbe zu REGION_REGION_FAILED_COLORED=§cFehler beim umfärben der Region REGION_REGION_NO_SCHEM=§cSchematic nicht gefunden REGION_REGION_TP_COPY=§7Zum Kopierpunkt teleportiert +REGION_REGION_TP_TEST_BLOCK=§7Zum Testblock teleportiert +REGION_REGION_TP_UNKNOWN=§cNicht definierter Teleportierpunkt REGION_REGION_NO_REGION=§cDu bist in keiner Region REGION_REGION_NO_PERMS=§cDu darfst hier nicht die Region verändern REGION_REGION_CHANGETYPE_INFO=§7Regions Type ist §e{0} @@ -505,6 +534,18 @@ LOCK_SCHEM_LOCKED=§e{0} §7von §e{1} §7wurde von §e{2} §7auf §eNORMAL §7z LOCK_SCHEM_HELP=§8/§eschemlock §8[§7Owner§8] [§7Schematic§8] [§7Grund§8] - §7Sperre eine Schematic AFK_KICK_MESSAGE=§cAuf diesem Server ist seit 5 Minuten nichts passiert. AFK_WARNING_MESSAGE=§cDieser Server wird bei weiterer Inaktivität in einer Minute gestoppt + +# Panzern +PANZERN_HELP = §8/§epanzern §8[§7Block§8] §8[§7Slab§8] §8- §7Panzer deine WorldEdit Auswahl +PANZERN_PREPARE1 = §71. Gucke nochmal nach, ob Läufe auch bis zur Panzergrenze führen. +PANZERN_PREPARE2 = §72. Teppich in Gänge auf dem Boden vereinfacht das panzern. +PANZERN_PREPARE3 = §73. Schildtechnik sollte explizit eingeschlossen sein. +PANZERN_PREPARE4 = §74. Innerhalb der zu panzernden Region zu stehen, beim Befehlausführen kann das Panzern verbessern. +PANZERN_NO_PERM = §cDu darfst hier nicht das Panzern System verwenden +PANZERN_NO_WORLDEDIT = §cDu hast keine WorldEdit Selection +PANZERN_PROGRESS = §e{0} §7Blöcke übrig, §e{1} §7Blöcke pro Sekunde, §e{2} §7Block Delta +PANZERN_DONE = §aZuende gepanzert + # Warp WARP_EXISTS=§7Der Warp mit dem namen §e{0} §7existiert bereits WARP_NAME_RESERVED=§7Du kannst nicht §c{0} §7als name für einen Warp nutzen diff --git a/BauSystem_Main/src/de/steamwar/bausystem/BauSystem.java b/BauSystem_Main/src/de/steamwar/bausystem/BauSystem.java index 291d9aa6..3cbd13e5 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/BauSystem.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/BauSystem.java @@ -19,12 +19,14 @@ package de.steamwar.bausystem; +import com.comphenix.tinyprotocol.TinyProtocol; import de.steamwar.bausystem.config.ColorConfig; import de.steamwar.bausystem.configplayer.Config; import de.steamwar.bausystem.linkage.LinkageUtils; import de.steamwar.bausystem.region.loader.PrototypeLoader; import de.steamwar.bausystem.region.loader.RegionLoader; import de.steamwar.bausystem.region.loader.Updater; +import de.steamwar.bausystem.utils.ProtocolAPI; import de.steamwar.bausystem.worlddata.WorldData; import de.steamwar.message.Message; import de.steamwar.scoreboard.SWScoreboard; @@ -87,6 +89,7 @@ public class BauSystem extends JavaPlugin implements Listener { WorldData.write(); Config.getInstance().saveAll(); + ProtocolAPI.tinyProtocol.close(); } private void fixLogging() { @@ -114,6 +117,7 @@ public class BauSystem extends JavaPlugin implements Listener { int number = -1; try { String string = new File(world.getWorldFolder(), "sections.yml").getCanonicalPath(); + if (string.endsWith("/sections2.yml")) number = 2; if (string.endsWith("/sections3.yml")) number = 3; if (string.endsWith("/sections4.yml")) number = 4; } catch (IOException e) { @@ -134,8 +138,8 @@ public class BauSystem extends JavaPlugin implements Listener { private void createLink(String source, String destination) { try { - Bukkit.getLogger().log(Level.INFO, "Executing: ln -s /home/minecraft/backbone/server/Bau15/{0} {1}", new String[]{source, destination}); - ProcessBuilder processBuilder = new ProcessBuilder("ln", "-s", "/home/minecraft/backbone/server/Bau15/" + source, destination); + Bukkit.getLogger().log(Level.INFO, "Executing: ln -s /home/minecraft/server/Bau15/{0} {1}", new String[]{source, destination}); + ProcessBuilder processBuilder = new ProcessBuilder("ln", "-s", "/home/minecraft/server/Bau15/" + source, destination); processBuilder.directory(world.getWorldFolder()); processBuilder.inheritIO(); diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/autostart/AutostartListener.java b/BauSystem_Main/src/de/steamwar/bausystem/features/autostart/AutostartListener.java index 9f90799c..46c311ba 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/autostart/AutostartListener.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/autostart/AutostartListener.java @@ -104,7 +104,7 @@ public class AutostartListener implements Listener { if (!region.inRegion(block.getLocation(), RegionType.TESTBLOCK, RegionExtensionType.EXTENSION)) return; long tickDiff = TPSUtils.currentTick.get() - regionStartTime.remove(region); RegionUtils.message(region, "AUTOSTART_MESSAGE_RESULT1", new SimpleDateFormat("mm:ss SSSS").format(new Date(tickDiff * 50))); - RegionUtils.message(region, "AUTOSTART_MESSAGE_RESULT2", (1200 - tickDiff)); + RegionUtils.message(region, "AUTOSTART_MESSAGE_RESULT2", 30, (600 - tickDiff)); RegionUtils.message(region, "AUTOSTART_MESSAGE_RESULT3"); }); } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/detonator/Detonator.java b/BauSystem_Main/src/de/steamwar/bausystem/features/detonator/Detonator.java index 599200c3..35a40af1 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/detonator/Detonator.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/detonator/Detonator.java @@ -109,7 +109,6 @@ public class Detonator { SWUtils.sendToActionbar(p, BauSystem.MESSAGE.parse("DETONATOR_POINTS_ACT", p, s)); } - invalid.forEach(detonator::removeLocation); if (!invalid.isEmpty()) { int invalidPoints = invalid.size(); if (invalidPoints == 1) { diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/detonator/DetonatorListener.java b/BauSystem_Main/src/de/steamwar/bausystem/features/detonator/DetonatorListener.java index c699211e..8b6b91da 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/detonator/DetonatorListener.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/detonator/DetonatorListener.java @@ -19,17 +19,14 @@ package de.steamwar.bausystem.features.detonator; -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.tinyprotocol.Reflection; import de.steamwar.bausystem.BauSystem; import de.steamwar.bausystem.SWUtils; import de.steamwar.bausystem.features.detonator.storage.DetonatorStorage; import de.steamwar.bausystem.features.detonator.storage.ItemStorage; import de.steamwar.bausystem.linkage.LinkageType; import de.steamwar.bausystem.linkage.Linked; +import de.steamwar.bausystem.utils.ProtocolAPI; import org.bukkit.Location; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; @@ -41,7 +38,6 @@ import org.bukkit.event.player.PlayerItemHeldEvent; import org.bukkit.event.player.PlayerMoveEvent; import org.bukkit.event.player.PlayerSwapHandItemsEvent; -import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -49,30 +45,29 @@ import java.util.Set; @Linked(LinkageType.LISTENER) public class DetonatorListener implements Listener { + public static final Class useEntity = Reflection.getClass("{nms}.PacketPlayInUseEntity"); + private static final Reflection.FieldAccessor entityIdFieldAccessor = Reflection.getField(useEntity, int.class, 0); + private static final Set HAS_UPDATED = new HashSet<>(); public DetonatorListener() { - ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(BauSystem.getInstance(), PacketType.Play.Client.USE_ENTITY) { - @Override - public void onPacketReceiving(PacketEvent event) { - List entities = new ArrayList<>(Detonator.getDetoEntities(event.getPlayer())); - if (entities.isEmpty()) { - return; - } - - PacketContainer container = event.getPacket(); - int entityId = container.getIntegers().read(0); - entities.removeIf(abstractDetonatorEntity -> abstractDetonatorEntity.getId() != entityId); - - if (entities.isEmpty()) { - return; - } - AbstractDetonatorEntity entity = entities.get(0); - Location location = entity.getBukkitEntity().getLocation().getBlock().getLocation(); - addLocationToDetonator(location, event.getPlayer()); - HAS_UPDATED.add(event.getPlayer()); - event.setCancelled(true); + ProtocolAPI.setIncomingHandler(useEntity, (player, o) -> { + List entities = Detonator.getDetoEntities(player); + if (entities.isEmpty()) { + return o; } + + int entityId = entityIdFieldAccessor.get(o); + AbstractDetonatorEntity entity = entities.stream().filter(abstractDetonatorEntity -> abstractDetonatorEntity.getId() == entityId).findFirst().orElse(null); + + if (entity == null) { + return o; + } + + Location location = entity.getBukkitEntity().getLocation().getBlock().getLocation(); + addLocationToDetonator(location, player); + HAS_UPDATED.add(player); + return null; }); } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/gui/BauGuiListener.java b/BauSystem_Main/src/de/steamwar/bausystem/features/gui/BauGuiListener.java index 5602f90d..e8c48493 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/gui/BauGuiListener.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/gui/BauGuiListener.java @@ -19,38 +19,16 @@ package de.steamwar.bausystem.features.gui; -import de.steamwar.bausystem.BauSystem; import de.steamwar.bausystem.linkage.LinkageType; import de.steamwar.bausystem.linkage.Linked; -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.block.Action; import org.bukkit.event.player.PlayerInteractEvent; -import org.bukkit.event.player.PlayerSwapHandItemsEvent; - -import java.util.HashSet; -import java.util.Set; @Linked(LinkageType.LISTENER) public class BauGuiListener implements Listener { - private static final Set LAST_FS = new HashSet<>(); - - public BauGuiListener() { - Bukkit.getScheduler().runTaskTimer(BauSystem.getInstance(), LAST_FS::clear, 20, 20); - } - - @EventHandler - public void onPlayerSwapHandItems(PlayerSwapHandItemsEvent event) { - if (LAST_FS.contains(event.getPlayer())) { - BauGUI.openBauGui(event.getPlayer()); - } else { - LAST_FS.add(event.getPlayer()); - } - } - @EventHandler public void onPlayerInteract(PlayerInteractEvent event) { if (event.getItem() == null) { diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/other/NoClipCommand.java b/BauSystem_Main/src/de/steamwar/bausystem/features/other/NoClipCommand.java index 4d8d5f1f..ae2034b7 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/other/NoClipCommand.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/other/NoClipCommand.java @@ -19,23 +19,17 @@ package de.steamwar.bausystem.features.other; -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.wrappers.EnumWrappers; -import com.comphenix.protocol.wrappers.PlayerInfoData; -import com.comphenix.protocol.wrappers.WrappedChatComponent; -import com.comphenix.protocol.wrappers.WrappedGameProfile; +import com.comphenix.tinyprotocol.Reflection; +import com.mojang.authlib.GameProfile; import de.steamwar.bausystem.BauSystem; import de.steamwar.bausystem.features.tpslimit.TPSUtils; import de.steamwar.bausystem.linkage.LinkageType; import de.steamwar.bausystem.linkage.Linked; +import de.steamwar.bausystem.utils.ProtocolAPI; import de.steamwar.command.SWCommand; +import de.steamwar.core.Core; import de.steamwar.core.VersionedRunnable; import lombok.Getter; -import org.bukkit.Bukkit; import org.bukkit.GameMode; import org.bukkit.craftbukkit.v1_15_R1.entity.CraftPlayer; import org.bukkit.entity.Player; @@ -46,42 +40,64 @@ import org.bukkit.event.player.PlayerGameModeChangeEvent; import org.bukkit.event.player.PlayerTeleportEvent; import org.bukkit.event.player.PlayerToggleFlightEvent; -import java.lang.reflect.InvocationTargetException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.logging.Level; +import java.util.*; +import java.util.function.BiFunction; @Linked(LinkageType.COMMAND) @Linked(LinkageType.LISTENER) public class NoClipCommand extends SWCommand implements Listener { + private static final Class playerInfoPacket = Reflection.getClass("{nms}.PacketPlayOutPlayerInfo"); + private static final Reflection.ConstructorInvoker playerInfoConstructor = Reflection.getConstructor(playerInfoPacket); + private static final Class playerInfoActionClass = Reflection.getClass("{nms}.PacketPlayOutPlayerInfo$EnumPlayerInfoAction"); + private static final Reflection.FieldAccessor playerInfoAction = Reflection.getField(playerInfoPacket, playerInfoActionClass, 0); + private static final Object updateGamemode = playerInfoActionClass.getEnumConstants()[1]; + private static final Reflection.FieldAccessor playerInfoData = Reflection.getField(playerInfoPacket, List.class, 0); + private static final Class playerInfoDataClass = Reflection.getClass("{nms}.PacketPlayOutPlayerInfo$PlayerInfoData"); + private static final Class enumGamemode = Reflection.getClass("{nms}.EnumGamemode"); + private static final Object spectator = enumGamemode.getEnumConstants()[4]; + private static final Class iChatBaseComponent = Reflection.getClass("{nms}.IChatBaseComponent"); + + private static final Reflection.ConstructorInvoker playerInfoDataConstructor = Reflection.getConstructor(playerInfoDataClass, playerInfoPacket, GameProfile.class, int.class, enumGamemode, iChatBaseComponent); + + private static final Class gameStateChange = Reflection.getClass("{nms}.PacketPlayOutGameStateChange"); + private static final Reflection.FieldAccessor integerFieldAccessor = Reflection.getField(gameStateChange, int.class, 0); + private static final Reflection.FieldAccessor floatFieldAccessor = Reflection.getField(gameStateChange, float.class, 0); + + private static final Class position = Reflection.getClass("{nms}.PacketPlayInFlying$PacketPlayInPosition"); + private static final Class positionLook = Reflection.getClass("{nms}.PacketPlayInFlying$PacketPlayInPositionLook"); + private static final Class useItem = Reflection.getClass("{nms}.PacketPlayInUseItem"); + private static final Class blockDig = Reflection.getClass("{nms}.PacketPlayInBlockDig"); + private static final Class windowClick = Reflection.getClass("{nms}.PacketPlayInWindowClick"); + @Getter private static final List NOCLIPS = new ArrayList<>(); private static final Map LAST_TICKS = new HashMap<>(); protected NoClipCommand() { super("noclip", "nc"); - ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(BauSystem.getInstance(), PacketType.Play.Client.POSITION, PacketType.Play.Client.POSITION_LOOK) { - @Override - public void onPacketReceiving(PacketEvent event) { - if (NOCLIPS.contains(event.getPlayer())) { - if (LAST_TICKS.getOrDefault(event.getPlayer(), -1L).equals(TPSUtils.currentTick.get())) return; - VersionedRunnable.call(new VersionedRunnable(() -> NoClipCommand_15.setGameModeInternal(event.getPlayer(), GameMode.SPECTATOR), 15)); - LAST_TICKS.put(event.getPlayer(), TPSUtils.currentTick.get()); - } + + BiFunction first = (player, o) -> { + if (NOCLIPS.contains(player)) { + if (LAST_TICKS.getOrDefault(player, -1L).equals(TPSUtils.currentTick.get())) return o; + VersionedRunnable.call(new VersionedRunnable(() -> NoClipCommand_15.setGameModeInternal(player, GameMode.SPECTATOR), 15)); + LAST_TICKS.put(player, TPSUtils.currentTick.get()); } - }); - ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(BauSystem.getInstance(), PacketType.Play.Client.USE_ITEM, PacketType.Play.Client.BLOCK_DIG, PacketType.Play.Client.WINDOW_CLICK) { - @Override - public void onPacketReceiving(PacketEvent event) { - if (NOCLIPS.contains(event.getPlayer())) { - VersionedRunnable.call(new VersionedRunnable(() -> NoClipCommand_15.setGameModeInternal(event.getPlayer(), GameMode.CREATIVE), 15)); - LAST_TICKS.put(event.getPlayer(), TPSUtils.currentTick.get()); - } + return o; + }; + ProtocolAPI.setIncomingHandler(position, first); + ProtocolAPI.setIncomingHandler(positionLook, first); + + BiFunction second = (player, o) -> { + if (NOCLIPS.contains(player)) { + VersionedRunnable.call(new VersionedRunnable(() -> NoClipCommand_15.setGameModeInternal(player, GameMode.CREATIVE), 15)); + LAST_TICKS.put(player, TPSUtils.currentTick.get()); } - }); + return o; + }; + ProtocolAPI.setIncomingHandler(useItem, second); + ProtocolAPI.setIncomingHandler(blockDig, second); + ProtocolAPI.setIncomingHandler(windowClick, second); } @Register(help = true) @@ -93,23 +109,15 @@ public class NoClipCommand extends SWCommand implements Listener { player.setGameMode(GameMode.SPECTATOR); ((CraftPlayer) player).getHandle().abilities.mayBuild = true; ((CraftPlayer) player).getHandle().abilities.canInstantlyBuild = true; - PacketContainer gm3packet = ProtocolLibrary.getProtocolManager().createPacket(PacketType.Play.Server.PLAYER_INFO); - gm3packet.getPlayerInfoAction().write(0, EnumWrappers.PlayerInfoAction.UPDATE_GAME_MODE); - List playerInfoActions = new ArrayList<>(); - playerInfoActions.add(new PlayerInfoData(WrappedGameProfile.fromPlayer(player), 1, EnumWrappers.NativeGameMode.SPECTATOR, WrappedChatComponent.fromText(player.getDisplayName()))); - gm3packet.getPlayerInfoDataLists().write(0, playerInfoActions); - PacketContainer gm1packet = ProtocolLibrary.getProtocolManager().createPacket(PacketType.Play.Server.GAME_STATE_CHANGE); - gm1packet.getIntegers().write(0, 3); - gm1packet.getFloat().write(0, 1F); + + Object gameStateChangeObject = Reflection.newInstance(gameStateChange); + integerFieldAccessor.set(gameStateChangeObject, 3); + floatFieldAccessor.set(gameStateChangeObject, 1F); + NOCLIPS.add(player); BauSystem.MESSAGE.send("OTHER_NOCLIP_SLOT_INFO", player); - try { - ProtocolLibrary.getProtocolManager().sendServerPacket(player, gm1packet); - ProtocolLibrary.getProtocolManager().sendServerPacket(player, gm3packet); - } catch (InvocationTargetException e) { - Bukkit.getLogger().log(Level.SEVERE, "Invocation target exception", e); - player.performCommand("noclip"); - } + ProtocolAPI.tinyProtocol.sendPacket(player, gameStateChangeObject); + pseudoSpectator(player); } } @@ -145,4 +153,15 @@ public class NoClipCommand extends SWCommand implements Listener { event.setCancelled(true); } } + + private static void pseudoSpectator(Player player) { + ProtocolAPI.tinyProtocol.sendPacket(player, playerInfoPacket(updateGamemode, new GameProfile(player.getUniqueId(), player.getName()), spectator)); + } + + private static Object playerInfoPacket(Object action, GameProfile profile, Object mode) { + Object packet = playerInfoConstructor.invoke(); + playerInfoAction.set(packet, action); + playerInfoData.set(packet, Collections.singletonList(playerInfoDataConstructor.invoke(packet, profile, 0, mode, null))); + return packet; + } } \ No newline at end of file diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/other/SlotCommand.java b/BauSystem_Main/src/de/steamwar/bausystem/features/other/SlotCommand.java index a741d763..0adb7f86 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/other/SlotCommand.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/other/SlotCommand.java @@ -40,6 +40,11 @@ public class SlotCommand extends SWCommand { super("slot", "s"); } + @Register(help = true) + public void genericHelp(Player p, String... args) { + BauSystem.MESSAGE.send("OTHER_NOCLIP_SLOT_INFO", p); + } + @Register public void slotCommand(Player player, Integer slot) { if (slot < 1 || slot > 9) { diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/other/TimeCommand.java b/BauSystem_Main/src/de/steamwar/bausystem/features/other/TimeCommand.java index f08cfc31..a946a9cd 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/other/TimeCommand.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/other/TimeCommand.java @@ -23,6 +23,7 @@ import de.steamwar.bausystem.BauSystem; import de.steamwar.bausystem.Permission; import de.steamwar.bausystem.linkage.LinkageType; import de.steamwar.bausystem.linkage.Linked; +import de.steamwar.command.CommandParseException; import de.steamwar.command.SWCommand; import de.steamwar.command.SWCommandUtils; import de.steamwar.command.TypeMapper; @@ -54,6 +55,7 @@ public class TimeCommand extends SWCommand { return; } Bukkit.getWorlds().get(0).setTime(time.getValue()); + BauSystem.MESSAGE.send("OTHER_TIME_RESULT", p); } @Register @@ -67,6 +69,7 @@ public class TimeCommand extends SWCommand { return; } Bukkit.getWorlds().get(0).setTime(time); + BauSystem.MESSAGE.send("OTHER_TIME_RESULT", p); } @ClassMapper(value = int.class, local = true) @@ -75,7 +78,7 @@ public class TimeCommand extends SWCommand { try { return Integer.parseInt(s); } catch (NumberFormatException e) { - return 0; + return null; } }, s -> tabCompletions); } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/region/RegionCommand.java b/BauSystem_Main/src/de/steamwar/bausystem/features/region/RegionCommand.java index 7126fc32..9e30068c 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/region/RegionCommand.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/region/RegionCommand.java @@ -82,6 +82,7 @@ public class RegionCommand extends SWCommand { BauSystem.MESSAGE.sendPrefixless("REGION_REGION_HELP_5", player); BauSystem.MESSAGE.sendPrefixless("REGION_REGION_HELP_6", player); BauSystem.MESSAGE.sendPrefixless("REGION_REGION_HELP_7", player); + BauSystem.MESSAGE.sendPrefixless("REGION_REGION_HELP_8", player); } @Register("undo") @@ -170,10 +171,29 @@ public class RegionCommand extends SWCommand { if (checkGlobalRegion(region, p)) { return; } + if (region.getCopyPoint() == null) { + BauSystem.MESSAGE.send("REGION_REGION_TP_UNKNOWN", p); + return; + } p.teleport(region.getCopyPoint().toLocation(p, 0.5, 0, 0.5), PlayerTeleportEvent.TeleportCause.COMMAND); BauSystem.MESSAGE.send("REGION_REGION_TP_COPY", p); } + @Register("testblockpoint") + @Register("tbpoint") + public void testBlockPointCommand(Player p) { + Region region = Region.getRegion(p.getLocation()); + if (checkGlobalRegion(region, p)) { + return; + } + if (region.getTestBlockPoint() == null) { + BauSystem.MESSAGE.send("REGION_REGION_TP_UNKNOWN", p); + return; + } + p.teleport(region.getTestBlockPoint().toLocation(p, 0.5, 0, 0.5), PlayerTeleportEvent.TeleportCause.COMMAND); + BauSystem.MESSAGE.send("REGION_REGION_TP_TEST_BLOCK", p); + } + @Register("changetype") @Register("type") public void changeTypeCommand(Player p) { diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/script/CustomCommandListener.java b/BauSystem_Main/src/de/steamwar/bausystem/features/script/CustomCommandListener.java deleted file mode 100644 index 9712ef4d..00000000 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/script/CustomCommandListener.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * 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.bausystem.features.script; - -import de.steamwar.bausystem.features.script.variables.Value; -import de.steamwar.bausystem.linkage.LinkageType; -import de.steamwar.bausystem.linkage.Linked; -import de.steamwar.core.VersionedCallable; -import lombok.AccessLevel; -import lombok.RequiredArgsConstructor; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.inventory.InventoryCloseEvent; -import org.bukkit.event.player.PlayerCommandPreprocessEvent; -import org.bukkit.event.player.PlayerJoinEvent; -import org.bukkit.event.player.PlayerQuitEvent; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.BookMeta; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -@Linked(LinkageType.LISTENER) -public class CustomCommandListener implements Listener { - - @RequiredArgsConstructor(access = AccessLevel.PRIVATE) - private static class CustomCommand { - private final BookMeta bookMeta; - private final String[] args; - - public boolean execute(String[] command, PlayerCommandPreprocessEvent e) { - if (args.length != command.length) { - return false; - } - - if (!args[0].equals(command[0])) { - return false; - } - - Map arguments = new HashMap<>(); - for (int i = 1; i < args.length; i++) { - String current = args[i]; - if (current.startsWith("<") && current.endsWith(">")) { - arguments.put(current.substring(1, current.length() - 1), new Value.StringValue(command[i])); - } else { - if (!current.equals(command[i])) { - return false; - } - } - } - e.setCancelled(true); - new ScriptExecutor(bookMeta, e.getPlayer(), arguments); - return true; - } - } - - private Map> playerMap = new HashMap<>(); - - private void updateInventory(Player p) { - playerMap.remove(p); - for (ItemStack item : p.getInventory().getContents()) { - if (item == null || isNoBook(item) || item.getItemMeta() == null) { - continue; - } - - BookMeta bookMeta = ((BookMeta) item.getItemMeta()); - if (bookMeta.getPageCount() == 0) { - continue; - } - if (bookMeta.getPage(1).isEmpty()) { - continue; - } - String s = bookMeta.getPage(1).split("\n")[0]; - if (!s.startsWith("#!CMD /")) { - continue; - } - playerMap.computeIfAbsent(p, player -> new ArrayList<>()).add(new CustomCommand(bookMeta, s.substring(6).split(" "))); - } - } - - @EventHandler - public void onPlayerJoin(PlayerJoinEvent event) { - updateInventory(event.getPlayer()); - } - - @EventHandler - public void onPlayerQuit(PlayerQuitEvent e) { - playerMap.remove(e.getPlayer()); - } - - @EventHandler - public void onInventoryClose(InventoryCloseEvent e) { - if (e.getPlayer() instanceof Player) { - updateInventory((Player) e.getPlayer()); - } - } - - @EventHandler - public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent e) { - if (e.getMessage().startsWith("/script:")) { - e.setMessage("/" + e.getMessage().substring(8)); - return; - } - - List customCommands = playerMap.get(e.getPlayer()); - if (customCommands == null) { - return; - } - - String[] command = e.getMessage().split(" "); - customCommands.stream().map(customCommand -> customCommand.execute(command, e)).filter(b -> !b).findFirst(); - } - - private boolean isNoBook(ItemStack item) { - return VersionedCallable.call(new VersionedCallable<>(() -> ScriptListener_15.isNoBook(item), 15)); - } -} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/script/CustomScript.java b/BauSystem_Main/src/de/steamwar/bausystem/features/script/CustomScript.java new file mode 100644 index 00000000..deb73c3e --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/script/CustomScript.java @@ -0,0 +1,240 @@ +/* + * 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.bausystem.features.script; + +import de.steamwar.bausystem.features.script.variables.Value; +import de.steamwar.inventory.SWItem; +import lombok.RequiredArgsConstructor; +import lombok.experimental.UtilityClass; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.bukkit.event.player.PlayerCommandPreprocessEvent; +import org.bukkit.inventory.meta.BookMeta; +import yapion.hierarchy.types.YAPIONArray; +import yapion.hierarchy.types.YAPIONMap; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@UtilityClass +public class CustomScript { + + public interface Script { + } + + public interface MenuScript { + void toYAPION(YAPIONMap yapionMap); + SWItem toItem(); + } + + public interface CustomEvent extends Script { + String eventName(); + boolean execute(Event e, Player p, Map variables); + } + + @RequiredArgsConstructor + public static class InventoryEvent implements CustomEvent { + public final BookMeta bookMeta; + public final String[] args; + + @Override + public String eventName() { + return args[0]; + } + + @Override + public boolean execute(Event e, Player p, Map variables) { + new ScriptExecutor(bookMeta, p, variables); + return true; + } + } + + @RequiredArgsConstructor + public static class MenuEvent implements CustomEvent, MenuScript { + public final List pages; + public final String[] args; + + @Override + public String eventName() { + return args[0]; + } + + @Override + public boolean execute(Event e, Player p, Map variables) { + new ScriptExecutor(pages, p, variables); + return false; + } + + @Override + public void toYAPION(YAPIONMap yapionMap) { + YAPIONArray yapionArray = new YAPIONArray(); + pages.forEach(yapionArray::add); + yapionMap.put(String.join(" ", args), yapionArray); + } + + @Override + public SWItem toItem() { + StringBuilder st = new StringBuilder(); + for (int i = 0; i < args.length; i++) { + if (i != 0) st.append(" "); + if (i == 0) st.append("§e"); + st.append(args[i]); + if (i == 0) st.append("§8 -§7"); + } + + SWItem swItem = new SWItem(Material.WRITABLE_BOOK, "§7Event§8: " + st); + BookMeta bookMeta = (BookMeta) swItem.getItemMeta(); + bookMeta.setPages(pages.toArray(new String[0])); + swItem.setItemMeta(bookMeta); + return swItem; + } + } + + public interface CustomCommand extends Script { + default Map check(String[] args, String[] command) { + if (args.length < command.length) { + return null; + } + + if (!args[0].equals(command[0])) { + return null; + } + + Map arguments = new HashMap<>(); + if (!check(arguments, args, command, 0, 0)) { + return null; + } + return arguments; + } + + default boolean check(Map arguments, String[] args, String[] command, int argsIndex, int commandIndex) { + if (command.length <= commandIndex) { + for (int i = argsIndex; i < args.length; i++) { + if (!(args[i].startsWith("(") && args[i].endsWith(")"))) { + return false; + } + } + return true; + } + if (args.length <= argsIndex) return true; + + String currentArg = args[argsIndex]; + String currentCommand = command[commandIndex]; + + if (currentArg.startsWith("<") && currentArg.endsWith(">")) { + arguments.put(trim(currentArg, 1), new Value.StringValue(currentCommand)); + return check(arguments, args, command, argsIndex + 1, commandIndex + 1); + } else if (currentArg.startsWith("(<") && currentArg.endsWith(">)")) { + arguments.put(trim(currentArg, 2), new Value.StringValue(currentCommand)); + return check(arguments, args, command, argsIndex + 1, commandIndex + 1); + } else if (currentArg.startsWith("(") && currentArg.endsWith(")")) { + if (!trim(currentArg, 1).equals(currentCommand)) { + arguments.put(trim(currentArg, 1), new Value.BooleanValue(false)); + return check(arguments, args, command, argsIndex + 1, commandIndex); + } else { + arguments.put(trim(currentArg, 1), new Value.BooleanValue(true)); + return check(arguments, args, command, argsIndex + 1, commandIndex + 1); + } + } else { + if (!currentArg.equals(currentCommand)) return false; + return check(arguments, args, command, argsIndex + 1, commandIndex + 1); + } + } + + default String trim(String s, int count) { + return s.substring(count, s.length() - count); + } + + boolean execute(String[] command, PlayerCommandPreprocessEvent e); + } + + @RequiredArgsConstructor + public static class InventoryCommand implements CustomCommand { + public final BookMeta bookMeta; + public final String[] args; + + public boolean execute(String[] command, PlayerCommandPreprocessEvent e) { + Map arguments = check(args, command); + if (arguments == null) { + return false; + } + + e.setCancelled(true); + new ScriptExecutor(bookMeta, e.getPlayer(), arguments); + return true; + } + } + + @RequiredArgsConstructor + public static class MenuCommand implements CustomCommand, MenuScript { + public final List pages; + public final String[] args; + + public boolean execute(String[] command, PlayerCommandPreprocessEvent e) { + Map arguments = check(args, command); + if (arguments == null) { + return false; + } + + e.setCancelled(true); + new ScriptExecutor(pages, e.getPlayer(), arguments); + return true; + } + + public boolean equals(MenuCommand menuCommand) { + if (menuCommand.args.length != args.length) { + return false; + } + for (int i = 0; i < args.length; i++) { + if (i == 0) continue; + String s1 = args[i]; + String s2 = menuCommand.args[i]; + if (s1.equals(s2)) { + return true; + } + if (s1.startsWith("<") && s1.endsWith(">") && s2.startsWith("<") && s2.endsWith(">")) { + return true; + } + if (s1.startsWith("(<") && s1.endsWith(">)") && s2.startsWith("(<") && s2.endsWith(">)")) { + return true; + } + } + return false; + } + + @Override + public void toYAPION(YAPIONMap yapionMap) { + YAPIONArray yapionArray = new YAPIONArray(); + pages.forEach(yapionArray::add); + yapionMap.put(String.join(" ", args), yapionArray); + } + + @Override + public SWItem toItem() { + SWItem swItem = new SWItem(Material.WRITABLE_BOOK, "§7Command§8: §e" + String.join(" ", args)); + BookMeta bookMeta = (BookMeta) swItem.getItemMeta(); + bookMeta.setPages(pages.toArray(new String[0])); + swItem.setItemMeta(bookMeta); + return swItem; + } + } +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/script/CustomScriptListener.java b/BauSystem_Main/src/de/steamwar/bausystem/features/script/CustomScriptListener.java new file mode 100644 index 00000000..008ec820 --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/script/CustomScriptListener.java @@ -0,0 +1,404 @@ +/* + * 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.bausystem.features.script; + +import de.steamwar.bausystem.BauSystem; +import de.steamwar.bausystem.SWUtils; +import de.steamwar.bausystem.features.script.variables.Value; +import de.steamwar.bausystem.linkage.LinkageType; +import de.steamwar.bausystem.linkage.Linked; +import de.steamwar.bausystem.region.Region; +import de.steamwar.core.VersionedCallable; +import de.steamwar.inventory.SWItem; +import de.steamwar.inventory.SWListInv; +import de.steamwar.sql.UserConfig; +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.entity.EntitySpawnEvent; +import org.bukkit.event.inventory.InventoryCloseEvent; +import org.bukkit.event.player.*; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.BookMeta; +import yapion.hierarchy.output.LengthOutput; +import yapion.hierarchy.output.StringOutput; +import yapion.hierarchy.types.YAPIONArray; +import yapion.hierarchy.types.YAPIONMap; +import yapion.hierarchy.types.YAPIONObject; +import yapion.hierarchy.types.YAPIONValue; +import yapion.parser.YAPIONParser; + +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; + +@Linked(LinkageType.LISTENER) +public class CustomScriptListener implements Listener { + + private Map> playerMap = new HashMap<>(); + + private void updateInventory(Player p) { + playerMap.computeIfPresent(p, (player, customCommands) -> { + customCommands.removeIf(script -> !(script instanceof CustomScript.MenuScript)); + return customCommands; + }); + for (ItemStack item : p.getInventory().getContents()) { + if (item == null || isNoBook(item) || item.getItemMeta() == null) { + continue; + } + + BookMeta bookMeta = ((BookMeta) item.getItemMeta()); + if (bookMeta.getPageCount() == 0) { + continue; + } + if (bookMeta.getPage(1).isEmpty()) { + continue; + } + String s = bookMeta.getPage(1).split("\n")[0]; + if (s.startsWith("#!CMD /")) { + playerMap.computeIfAbsent(p, player -> new ArrayList<>()).add(new CustomScript.InventoryCommand(bookMeta, s.substring(6).split(" "))); + } else if (s.startsWith("#!EVENT ")) { + playerMap.computeIfAbsent(p, player -> new ArrayList<>()).add(new CustomScript.InventoryEvent(bookMeta, s.substring(8).split(" "))); + } + } + } + + @EventHandler + public void onPlayerJoin(PlayerJoinEvent e) { + Player p = e.getPlayer(); + updateInventory(p); + + String s = UserConfig.getConfig(p.getUniqueId(), "bausystem-scripts"); + if (s == null) { + s = UserConfig.getConfig(p.getUniqueId(), "bausystem-commands"); + UserConfig.removePlayerConfig(p.getUniqueId(), "bausystem-commands"); + } + YAPIONObject yapionObject; + if (s == null) { + yapionObject = new YAPIONObject(); + yapionObject.getYAPIONMapOrSetDefault("events", new YAPIONMap()).add("FF", new YAPIONArray().add("#!EVENT FF /gui Kürzel\ngui")); + } else { + yapionObject = YAPIONParser.parse(s); + if (yapionObject.containsKey("")) { + yapionObject.add("commands", yapionObject.getMap("")); + yapionObject.remove(""); + yapionObject.getYAPIONMapOrSetDefault("events", new YAPIONMap()).add("FF", new YAPIONArray().add("#!EVENT FF /gui Kürzel\ngui")); + } + } + + yapionObject.getYAPIONMapOrSetDefault("commands", new YAPIONMap()).forEach((key, value) -> { + String[] command = ((YAPIONValue) key).get().split(" "); + List pages = ((YAPIONArray) value).stream().map(YAPIONValue.class::cast).map(YAPIONValue::get).map(String.class::cast).collect(Collectors.toList()); + playerMap.computeIfAbsent(p, player -> new ArrayList<>()).add(new CustomScript.MenuCommand(pages, command)); + }); + + yapionObject.getYAPIONMapOrSetDefault("events", new YAPIONMap()).forEach((key, value) -> { + String[] event = ((YAPIONValue) key).get().split(" "); + List pages = ((YAPIONArray) value).stream().map(YAPIONValue.class::cast).map(YAPIONValue::get).map(String.class::cast).collect(Collectors.toList()); + playerMap.computeIfAbsent(p, player -> new ArrayList<>()).add(new CustomScript.MenuEvent(pages, event)); + }); + } + + @EventHandler + public void onPlayerQuit(PlayerQuitEvent e) { + save(e.getPlayer()); + playerMap.remove(e.getPlayer()); + } + + private YAPIONObject output(Player p) { + if (!playerMap.containsKey(p)) return new YAPIONObject(); + YAPIONObject yapionObject = new YAPIONObject(); + YAPIONMap commandsMap = new YAPIONMap(); + yapionObject.add("commands", commandsMap); + playerMap.get(p).stream().filter(CustomScript.MenuCommand.class::isInstance).map(CustomScript.MenuCommand.class::cast).forEach(menuCommand -> { + menuCommand.toYAPION(commandsMap); + }); + YAPIONMap eventsMap = new YAPIONMap(); + yapionObject.add("events", eventsMap); + playerMap.get(p).stream().filter(CustomScript.MenuEvent.class::isInstance).map(CustomScript.MenuEvent.class::cast).forEach(menuCommand -> { + menuCommand.toYAPION(eventsMap); + }); + return yapionObject; + } + + private boolean save(Player p) { + if (!playerMap.containsKey(p)) { + UserConfig.removePlayerConfig(p.getUniqueId(), "bausystem-scripts"); + return true; + } + YAPIONObject yapionObject = output(p); + if (yapionObject.toYAPION(new LengthOutput()).getLength() > 64 * 1024) { + return false; + } + UserConfig.updatePlayerConfig(p.getUniqueId(), "bausystem-scripts", yapionObject.toYAPION(new StringOutput()).getResult()); + return true; + } + + @EventHandler + public void onInventoryClose(InventoryCloseEvent e) { + if (e.getPlayer() instanceof Player) { + updateInventory((Player) e.getPlayer()); + } + } + + private boolean isNoBook(ItemStack item) { + return VersionedCallable.call(new VersionedCallable<>(() -> ScriptListener_15.isNoBook(item), 15)); + } + + public void openCommandsMenu(Player p) { + List> menuCommands = new ArrayList<>(); + playerMap.getOrDefault(p, new ArrayList<>()).stream().filter(CustomScript.MenuScript.class::isInstance).map(CustomScript.MenuScript.class::cast).forEach(menuItem -> { + SWItem swItem = menuItem.toItem(); + ItemStack itemStack = swItem.getItemStack(); + if (menuItem instanceof CustomScript.MenuEvent) { + itemStack.setType(Material.REPEATING_COMMAND_BLOCK); + } else { + itemStack.setType(Material.COMMAND_BLOCK); + } + swItem.setItemStack(itemStack); + swItem.setLore(Arrays.asList("§7Klicke zum rausnehmen", "§7Middle Klicke zum kopieren")); + + menuCommands.add(new SWListInv.SWListEntry<>(swItem, menuItem)); + }); + + int length = (int) output(p).toYAPION(new LengthOutput()).getLength(); + StringBuilder menuName = new StringBuilder(); + menuName.append("§eScript Commands "); + double percentage = ((int) ((length / 655336.0) * 1000)) / 10.0; + if (percentage > 99) { + menuName.append("§c"); + } else if (percentage >= 75) { + menuName.append("§6"); + } else { + menuName.append("§a"); + } + menuName.append(percentage).append("§7%"); + + SWListInv menuCommandSWListInv = new SWListInv<>(p, menuName.toString(), false, menuCommands, (clickType, menuCommand) -> { + if (!clickType.isCreativeAction()) { + playerMap.get(p).removeIf(customCommand -> customCommand == menuCommand); + } + SWUtils.giveItemToPlayer(p, menuCommand.toItem().getItemStack()); + p.closeInventory(); + save(p); + }); + menuCommandSWListInv.setItem(49, new SWItem(Material.HOPPER, "§eHinzufügen", Arrays.asList("§7Klicke mit einem Buch zum hinzufügen"), false, clickType -> { + ItemStack item = p.getItemOnCursor(); + if (item.getType().isAir()) { + return; + } + if (isNoBook(item) || item.getItemMeta() == null) { + return; + } + + BookMeta bookMeta = ((BookMeta) item.getItemMeta()); + if (bookMeta.getPageCount() == 0) { + return; + } + if (bookMeta.getPage(1).isEmpty()) { + return; + } + String s = bookMeta.getPage(1).split("\n")[0]; + if (s.startsWith("#!CMD /")) { + CustomScript.MenuCommand menuCommand = new CustomScript.MenuCommand(bookMeta.getPages(), s.substring(6).split(" ")); + for (CustomScript.Script script : playerMap.computeIfAbsent(p, player -> new ArrayList<>())) { + if (!(script instanceof CustomScript.MenuCommand)) { + continue; + } + if (((CustomScript.MenuCommand) script).equals(menuCommand)) { + p.sendMessage("§cCommand '" + (String.join(" ", menuCommand.args)) + "' bereits definiert"); + return; + } + } + scriptBookLimit(p, menuCommand); + } else if (s.startsWith("#!EVENT ")) { + CustomScript.MenuEvent menuEvent = new CustomScript.MenuEvent(bookMeta.getPages(), s.substring(8).split(" ")); + try { + EventType.valueOf(menuEvent.eventName()); + } catch (Exception e) { + p.sendMessage("§cEvent '" + menuEvent.eventName() + "' ist nicht definierbar"); + return; + } + scriptBookLimit(p, menuEvent); + } + })); + menuCommandSWListInv.open(); + } + + private void scriptBookLimit(Player p, CustomScript.Script menuScript) { + playerMap.computeIfAbsent(p, player -> new ArrayList<>()).add(menuScript); + if (!save(p)) { + playerMap.get(p).removeIf(script -> script == menuScript); + p.closeInventory(); + SWUtils.giveItemToPlayer(p, p.getItemOnCursor()); + save(p); + p.sendMessage("§cScript-Buch Limit erreicht"); + return; + } + p.setItemOnCursor(null); + openCommandsMenu(p); + } + + @Getter + public enum EventType { + FF(PlayerSwapHandItemsEvent.class, event -> null), + PlaceBlock(BlockPlaceEvent.class, event -> { + Map valueMap = new HashMap<>(); + valueMap.put("blockX", new Value.LongValue(event.getBlockPlaced().getX())); + valueMap.put("blockY", new Value.LongValue(event.getBlockPlaced().getY())); + valueMap.put("blockZ", new Value.LongValue(event.getBlockPlaced().getZ())); + valueMap.put("blockType", new Value.StringValue(event.getBlockPlaced().getType().name())); + return valueMap; + }), + BreakBlock(BlockBreakEvent.class, event -> { + Map valueMap = new HashMap<>(); + valueMap.put("blockX", new Value.LongValue(event.getBlock().getX())); + valueMap.put("blockY", new Value.LongValue(event.getBlock().getY())); + valueMap.put("blockZ", new Value.LongValue(event.getBlock().getZ())); + valueMap.put("blockType", new Value.StringValue(event.getBlock().getType().name())); + return valueMap; + }), + RightClick(PlayerInteractEvent.class, event -> { + Map valueMap = new HashMap<>(); + valueMap.put("blockInHand", new Value.BooleanValue(event.isBlockInHand())); + return valueMap; + }), + LeftClick(PlayerInteractEvent.class, event -> { + Map valueMap = new HashMap<>(); + valueMap.put("blockInHand", new Value.BooleanValue(event.isBlockInHand())); + return valueMap; + }), + TNTSpawn(EntitySpawnEvent.class, event -> null); + + private Class eventType; + private Function> eventValues; + + EventType(Class eventType, Function> eventValues) { + this.eventType = eventType; + this.eventValues = event -> eventValues.apply((T) event); + } + } + + private void callEvent(EventType eventType, Player p, Event e) { + if (!eventType.getEventType().equals(e.getClass())) { + return; + } + + List customEvents = playerMap.getOrDefault(p, new ArrayList<>()).stream().filter(CustomScript.CustomEvent.class::isInstance).map(CustomScript.CustomEvent.class::cast).collect(Collectors.toList()); + for (CustomScript.CustomEvent customEvent : customEvents) { + if (customEvent.eventName().equals(eventType.name())) { + Map variables = eventType.getEventValues().apply(e); + if (variables == null) { + variables = new HashMap<>(); + } + if (e instanceof Cancellable) { + variables.put("cancel", new Value.BooleanValue(false)); + } + customEvent.execute(e, p, variables); + if (variables.containsKey("cancel")) { + Value value = variables.get("cancel"); + if (value.asBoolean()) { + ((Cancellable) e).setCancelled(true); + } + } + } + } + } + + // EventListener for Commands as well as Events + + // Event Command + @EventHandler + public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent e) { + if (e.getMessage().startsWith("/script:")) { + e.setMessage("/" + e.getMessage().substring(8)); + return; + } + + List customCommands = playerMap.getOrDefault(e.getPlayer(), new ArrayList<>()).stream().filter(CustomScript.CustomCommand.class::isInstance).map(CustomScript.CustomCommand.class::cast).collect(Collectors.toList()); + String[] command = e.getMessage().split(" "); + for (CustomScript.CustomCommand customCommand : customCommands) { + if (customCommand.execute(command, e)) { + return; + } + } + } + + // Event FF + private static final Set LAST_FS = new HashSet<>(); + + { + Bukkit.getScheduler().runTaskTimer(BauSystem.getInstance(), LAST_FS::clear, 20, 20); + } + + @EventHandler + public void onPlayerSwapHandItems(PlayerSwapHandItemsEvent event) { + if (LAST_FS.contains(event.getPlayer())) { + callEvent(EventType.FF, event.getPlayer(), event); + } else { + LAST_FS.add(event.getPlayer()); + } + } + + @EventHandler + public void onBlockPlace(BlockPlaceEvent event) { + callEvent(EventType.PlaceBlock, event.getPlayer(), event); + } + + @EventHandler + public void onBlockBreak(BlockBreakEvent event) { + callEvent(EventType.BreakBlock, event.getPlayer(), event); + } + + @EventHandler + public void onPlayerInteract(PlayerInteractEvent event) { + if (event.getAction() == Action.RIGHT_CLICK_AIR || event.getAction() == Action.RIGHT_CLICK_BLOCK) { + callEvent(EventType.RightClick, event.getPlayer(), event); + } + if (event.getAction() == Action.LEFT_CLICK_AIR || event.getAction() == Action.LEFT_CLICK_BLOCK) { + callEvent(EventType.LeftClick, event.getPlayer(), event); + } + } + + @EventHandler + public void onEntitySpawn(EntitySpawnEvent event) { + if (event.getEntityType() != EntityType.PRIMED_TNT) { + return; + } + Region tntRegion = Region.getRegion(event.getLocation()); + + for (Player player : Bukkit.getOnlinePlayers()) { + Region region = Region.getRegion(player.getLocation()); + if (region == tntRegion) { + callEvent(EventType.TNTSpawn, player, event); + } + } + } +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/script/ScriptCommand.java b/BauSystem_Main/src/de/steamwar/bausystem/features/script/ScriptCommand.java index 2c2b886c..0880f4ae 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/script/ScriptCommand.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/script/ScriptCommand.java @@ -1,8 +1,8 @@ package de.steamwar.bausystem.features.script; -import de.steamwar.bausystem.BauSystem; import de.steamwar.bausystem.linkage.LinkageType; import de.steamwar.bausystem.linkage.Linked; +import de.steamwar.bausystem.linkage.LinkedInstance; import de.steamwar.command.SWCommand; import de.steamwar.inventory.SWItem; import de.steamwar.inventory.SWListInv; @@ -23,23 +23,31 @@ public class ScriptCommand extends SWCommand { super("script"); } - private static List> swItems = new ArrayList<>(); + @LinkedInstance + private CustomScriptListener customScriptListener = null; + + private static List> swItems = new ArrayList<>(); @Register(help = true) public void genericHelp(Player p, String... args) { - p.sendMessage("§8/§escript §8- §7Gibt das Script Buch"); + p.sendMessage("§8/§escript §8- §7Öffnet die ScriptGUI"); + p.sendMessage("§8/§escript menu §8- §7Öffnet die ScriptMenuGUI für Custom Command b auübergreifend"); } @Register - public void giveCommand(Player p) { + public void menuCommand(Player p) { if (swItems.isEmpty()) { - for (int i = 0; i < 4; i++) { + for (int i = 0; i < 3; i++) { swItems.add(new SWListInv.SWListEntry<>(new SWItem(Material.GRAY_STAINED_GLASS_PANE, "§7", new ArrayList<>(), false, clickType -> { }), null)); } - swItems.add(new SWListInv.SWListEntry<>(new SWItem(Material.BOOK, "§eCustom Commands", Arrays.asList("§7Schreibe§8: §7#!CMD 'COMMAND'", "§7an den Anfang eines Script Buches um", "§7ein Custom Command zu nutzen. Der", "§7Befehl startet immer mit / und kann dann so", "§7aufgebaut sein wie du willst. Alles was in Spitzen", "§7Klammern steht (<>) wird als Parameter und somit", "§7als Variable gewertet."), false, clickType -> { + swItems.add(new SWListInv.SWListEntry<>(new SWItem(Material.BOOK, "§eCustom Commands", Arrays.asList("§7Schreibe§8: §7#!CMD 'COMMAND'", "§7an den Anfang eines Script Buches um", "§7ein Custom Command zu nutzen. Der", "§7Befehl startet immer mit / und kann dann so", "§7aufgebaut sein wie du willst. Alles was in Spitzen", "§7Klammern steht '<>' wird als Parameter und somit", "§7als Variable gewertet.", "§7Parameter, welche in runden Klammern", "§7stehen sind Optional. Einfache", "§7Texte als Parameter bekommen", "§7eine gleichnamige Variable mit", "§7true/false als Wert je nachdem", "§7ob dieser angegeben wurde oder nicht"), false, clickType -> { }), null)); - for (int i = 0; i < 4; i++) { + swItems.add(new SWListInv.SWListEntry<>(new SWItem(Material.BOOK, "§eCustom Events", Arrays.asList("§7Schreibe§8: §7#!EVENT 'EventName'", "§7an den Anfang eines Script Buches um", "§7ein Custom Event zu nutzen. Jedes Event kann durch", "§7'var cancel true' gecancelt werden.", "§7Hinter dem Event Namen stehen die Variablen,", "§7welche im Script durch das Event nutztbar sind.", "§7Nutzbare Events sind:", "§eFF", "§ePlaceBlock §8-§7 blockX, blockY, blockZ, blockType", "§eBreakBlock §8-§7 blockX, blockY, blockZ, blockType", "§eRightClick §8-§7 blockInHand", "§eLeftClick §8-§7 blockInHand", "§eTNTSpawn"), false, clickType -> { + }), null)); + swItems.add(new SWListInv.SWListEntry<>(new SWItem(Material.BOOK, "§eOther", Arrays.asList("§7Kommentare fangen mit §e#§7 an.", "§7Jump_Points fangen mit §e.§7 an.", "§7Eine Variablen Namen in '<>'", "§7eingeschlossen wird ersetzt, bis zu zwei mal.", "§7Eine Variable in '<>' kann mit 'const.'", "§7oder 'local.' oder 'global.' prefixed werden", "§7für den genauen type wo nach geguckt werden soll"), false, clickType -> { + }), null)); + for (int i = 0; i < 3; i++) { swItems.add(new SWListInv.SWListEntry<>(new SWItem(Material.GRAY_STAINED_GLASS_PANE, "§7", new ArrayList<>(), false, clickType -> { }), null)); } @@ -69,14 +77,10 @@ public class ScriptCommand extends SWCommand { } SWItem swItem = new SWItem(specialCommand.material(), "§7Command: §e" + specialCommand.command(), strings, false, clickType -> { - p.sendMessage("§eScript Command§8: §e" + specialCommand.command()); - for (String s : specialCommand.description()) { - p.sendMessage("§7" + s); - } }); - swItems.add(new SWListInv.SWListEntry<>(swItem, null)); + swItems.add(new SWListInv.SWListEntry<>(swItem, specialCommand)); }); - for (int i = 0; i < 9 + 4; i++) { + for (int i = 0; i < 9 + 3; i++) { swItems.add(new SWListInv.SWListEntry<>(new SWItem(Material.GRAY_STAINED_GLASS_PANE, "§7", new ArrayList<>(), false, clickType -> { }), null)); } @@ -92,31 +96,52 @@ public class ScriptCommand extends SWCommand { }), null)); swItems.add(new SWListInv.SWListEntry<>(new SWItem(Material.TNT, "§7Constant §etnt", Arrays.asList("§etrue§7 wenn TNT nicht ausgeschaltet ist."), false, clickType -> { }), null)); + swItems.add(new SWListInv.SWListEntry<>(new SWItem(Material.TNT, "§7Constant §etnt-onlytb", Arrays.asList("§etrue§7 wenn TNT Nur Testblock an ist."), false, clickType -> { + }), null)); swItems.add(new SWListInv.SWListEntry<>(new SWItem(Material.GUNPOWDER, "§7Constant §efreeze", Arrays.asList("§etrue§7 wenn Freeze nicht ausgeschaltet ist."), false, clickType -> { }), null)); swItems.add(new SWListInv.SWListEntry<>(new SWItem(Material.FIRE_CHARGE, "§7Constant §efire", Arrays.asList("§etrue§7 wenn Fire nicht ausgeschaltet ist."), false, clickType -> { }), null)); swItems.add(new SWListInv.SWListEntry<>(new SWItem(Material.OBSIDIAN, "§7Constant §eprotect", Arrays.asList("§etrue§7 wenn Protect angeschaltet ist."), false, clickType -> { }), null)); - swItems.add(new SWListInv.SWListEntry<>(new SWItem(Material.PLAYER_HEAD, "§7Constant §ex", Arrays.asList("§ex§7 Position des Spielers."), false, clickType -> { + swItems.add(new SWListInv.SWListEntry<>(new SWItem(Material.PLAYER_HEAD, "§7Constant §ex", Arrays.asList("§ex§7 Position des Spielers.", "§eÜberschreibbar"), false, clickType -> { }), null)); - swItems.add(new SWListInv.SWListEntry<>(new SWItem(Material.PLAYER_HEAD, "§7Constant §ey", Arrays.asList("§ey§7 Position des Spielers."), false, clickType -> { + swItems.add(new SWListInv.SWListEntry<>(new SWItem(Material.PLAYER_HEAD, "§7Constant §ey", Arrays.asList("§ey§7 Position des Spielers.", "§eÜberschreibbar"), false, clickType -> { }), null)); - swItems.add(new SWListInv.SWListEntry<>(new SWItem(Material.PLAYER_HEAD, "§7Constant §ez", Arrays.asList("§ez§7 Position des Spielers."), false, clickType -> { + swItems.add(new SWListInv.SWListEntry<>(new SWItem(Material.PLAYER_HEAD, "§7Constant §ez", Arrays.asList("§ez§7 Position des Spielers.", "§eÜberschreibbar"), false, clickType -> { }), null)); swItems.add(new SWListInv.SWListEntry<>(new SWItem(Material.NAME_TAG, "§7Constant §ename", Arrays.asList("§eDisplay§7 Name des Spielers."), false, clickType -> { }), null)); swItems.add(new SWListInv.SWListEntry<>(new SWItem(Material.IRON_BOOTS, "§7Constant §esneak", Arrays.asList("§etrue§7 wenn der Spieler gerade sneakt."), false, clickType -> { }), null)); - for (int i = 0; i < 7 + 2 * 9; i++) { + swItems.add(new SWListInv.SWListEntry<>(new SWItem(Material.DIAMOND_BOOTS, "§7Constant §esprinting", Arrays.asList("§etrue§7 wenn der Spieler gerade rennt."), false, clickType -> { + }), null)); + swItems.add(new SWListInv.SWListEntry<>(new SWItem(Material.ARROW, "§7Constant §eslot", Arrays.asList("§e0-8§7 für den ausgewählten slot.", "§eÜberschreibbar"), false, clickType -> { + }), null)); + swItems.add(new SWListInv.SWListEntry<>(new SWItem(Material.GRASS_BLOCK, "§7Constant §eslotmaterial", Arrays.asList("§eMaterial§7 des Items im Slot"), false, clickType -> { + }), null)); + swItems.add(new SWListInv.SWListEntry<>(new SWItem(Material.IRON_BLOCK, "§7Constant §eoffhandmaterial", Arrays.asList("§eMaterial§7 des Items in oder Off Hand"), false, clickType -> { + }), null)); + for (int i = 0; i < 2 + 2 * 9; i++) { swItems.add(new SWListInv.SWListEntry<>(new SWItem(Material.GRAY_STAINED_GLASS_PANE, "§7", new ArrayList<>(), false, clickType -> { }), null)); } } - SWListInv swListInv = new SWListInv<>(p, "Script Elements", swItems, (clickType, o) -> { + SWListInv swListInv = new SWListInv<>(p, "Script Elements", swItems, (clickType, o) -> { + if (o != null) { + p.sendMessage("§eScript Command§8: §e" + o.command()); + for (String s : o.description()) { + p.sendMessage("§7" + s); + } + p.closeInventory(); + } }); swListInv.open(); } + @Register({"menu"}) + public void menuGUICommand(Player p) { + customScriptListener.openCommandsMenu(p); + } } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/script/ScriptExecutor.java b/BauSystem_Main/src/de/steamwar/bausystem/features/script/ScriptExecutor.java index 01ffc8e6..d2da1bb6 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/script/ScriptExecutor.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/script/ScriptExecutor.java @@ -42,34 +42,64 @@ public final class ScriptExecutor { this(bookMeta, player, new HashMap<>()); } + public ScriptExecutor(List pages, Player player) { + this(pages, player, new HashMap<>()); + } + public ScriptExecutor(BookMeta bookMeta, Player player, Map localVariables) { this.player = player; globalVariables = ScriptListener.getGlobalContext(player); - boolean initial = true; - for (String page : bookMeta.getPages()) { - for (String command : page.split("\n")) { - command = command.replaceAll(" +", " "); - if (command.startsWith("#") || command.trim().isEmpty()) { - if (initial && command.startsWith("#!CMD /")) { - specialCommand = command.substring(7).split(" ")[0]; - } - initial = false; - continue; - } - initial = false; - if (command.startsWith(".")) { - jumpPoints.put(command.substring(1), commands.size()); - continue; - } - commands.add(command); - } - } + parseMeta(bookMeta); if (commands.isEmpty()) return; localVariables.forEach(this.localVariables::putValue); resume(); } + public ScriptExecutor(List pages, Player player, Map localVariables) { + this.player = player; + globalVariables = ScriptListener.getGlobalContext(player); + + parseList(pages); + if (commands.isEmpty()) return; + localVariables.forEach(this.localVariables::putValue); + resume(); + } + + private void parseMeta(BookMeta bookMeta) { + boolean initial = true; + for (String page : bookMeta.getPages()) { + initial = parsePage(page, initial); + } + } + + private void parseList(List pages) { + boolean initial = true; + for (String page : pages) { + initial = parsePage(page, initial); + } + } + + private boolean parsePage(String page, boolean initial) { + for (String command : page.split("\n")) { + command = command.replaceAll(" +", " "); + if (command.startsWith("#") || command.trim().isEmpty()) { + if (initial && command.startsWith("#!CMD /")) { + specialCommand = command.substring(7).split(" ")[0]; + } + initial = false; + continue; + } + initial = false; + if (command.startsWith(".")) { + jumpPoints.put(command.substring(1), commands.size()); + continue; + } + commands.add(command); + } + return initial; + } + public void resume() { if (!player.isOnline()) { return; @@ -138,10 +168,22 @@ public final class ScriptExecutor { } return s.split(" "); } + + public Value parse(String varValue) { + try { + return new Value.LongValue(Long.parseLong(varValue)); + } catch (NumberFormatException e) { + if (varValue.equalsIgnoreCase("true") || varValue.equalsIgnoreCase("false")) { + return new Value.BooleanValue(varValue.equalsIgnoreCase("true")); + } else { + return new Value.StringValue(varValue); + } + } + } public Value getOrItselfValue(String variable) { if (!isVariable(variable)) { - return new Value.StringValue(variable); + return parse(variable); } if (Constants.isConstant(variable)) { diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/arithmetic/Add.java b/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/arithmetic/Add.java index b8103f8f..4bb50b4e 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/arithmetic/Add.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/arithmetic/Add.java @@ -14,8 +14,8 @@ public class Add implements SpecialCommand { @Override public String[] description() { return new String[]{ - "§eadd §8<§7Variable§8> §8<§7Variable§8>", - "§eadd §8<§7Variable§8> §8<§7Variable§8> §8<§7Variable§8>", + "§eadd §8<§7Variable§8> §8<§7Variable§8|§7Wert§8>", + "§eadd §8<§7Variable§8> §8<§7Variable§8§8|§7Wert> §8<§7Variable§8|§7Wert§8>", "", "Addition zwischen den letzten beiden Variablen und schreibt es in die erste." }; @@ -44,11 +44,11 @@ public class Add implements SpecialCommand { Value v1 = scriptExecutor.getOrItselfValue(command[command.length - 2]); Value v2 = scriptExecutor.getOrItselfValue(command[command.length - 1]); - if (v1.getClass() != Value.LongValue.class) { + if (!(v1 instanceof Value.LongValue)) { scriptExecutor.getPlayer().sendMessage(BauSystem.PREFIX + "§cNur Zahlen können addiert werden"); return true; } - if (v2.getClass() != Value.LongValue.class) { + if (!(v2 instanceof Value.LongValue)) { scriptExecutor.getPlayer().sendMessage(BauSystem.PREFIX + "§cNur Zahlen können addiert werden"); return true; } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/arithmetic/Div.java b/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/arithmetic/Div.java index 8049b627..ff4499f7 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/arithmetic/Div.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/arithmetic/Div.java @@ -14,8 +14,8 @@ public class Div implements SpecialCommand { @Override public String[] description() { return new String[]{ - "§ediv §8<§7Variable§8> §8<§7Variable§8>", - "§ediv §8<§7Variable§8> §8<§7Variable§8> §8<§7Variable§8>", + "§ediv §8<§7Variable§8> §8<§7Variable§8|§7Wert§8>", + "§ediv §8<§7Variable§8> §8<§7Variable§8|§7Wert§8> §8<§7Variable§8|§7Wert§8>", "", "Division zwischen den letzten beiden Variablen und schreibt es in die erste." }; @@ -44,11 +44,11 @@ public class Div implements SpecialCommand { Value v1 = scriptExecutor.getOrItselfValue(command[command.length - 2]); Value v2 = scriptExecutor.getOrItselfValue(command[command.length - 1]); - if (v1.getClass() != Value.LongValue.class) { + if (!(v1 instanceof Value.LongValue)) { scriptExecutor.getPlayer().sendMessage(BauSystem.PREFIX + "§cNur Zahlen können dividiert werden"); return true; } - if (v2.getClass() != Value.LongValue.class) { + if (!(v2 instanceof Value.LongValue)) { scriptExecutor.getPlayer().sendMessage(BauSystem.PREFIX + "§cNur Zahlen können dividiert werden"); return true; } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/arithmetic/Mul.java b/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/arithmetic/Mul.java index 59bd9072..a1238ef6 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/arithmetic/Mul.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/arithmetic/Mul.java @@ -14,8 +14,8 @@ public class Mul implements SpecialCommand { @Override public String[] description() { return new String[]{ - "§emul §8<§7Variable§8> §8<§7Variable§8>", - "§emul §8<§7Variable§8> §8<§7Variable§8> §8<§7Variable§8>", + "§emul §8<§7Variable§8> §8<§7Variable§8|§7Wert§8>", + "§emul §8<§7Variable§8> §8<§7Variable§8|§7Wert§8> §8<§7Variable§8|§7Wert§8>", "", "Multiplikation zwischen den letzten beiden Variablen und schreibt es in die erste." }; @@ -44,11 +44,11 @@ public class Mul implements SpecialCommand { Value v1 = scriptExecutor.getOrItselfValue(command[command.length - 2]); Value v2 = scriptExecutor.getOrItselfValue(command[command.length - 1]); - if (v1.getClass() != Value.LongValue.class) { + if (!(v1 instanceof Value.LongValue)) { scriptExecutor.getPlayer().sendMessage(BauSystem.PREFIX + "§cNur Zahlen können multipliziert werden"); return true; } - if (v2.getClass() != Value.LongValue.class) { + if (!(v2 instanceof Value.LongValue)) { scriptExecutor.getPlayer().sendMessage(BauSystem.PREFIX + "§cNur Zahlen können multipliziert werden"); return true; } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/arithmetic/Sub.java b/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/arithmetic/Sub.java index 06d4345f..e7ff65b2 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/arithmetic/Sub.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/arithmetic/Sub.java @@ -14,8 +14,8 @@ public class Sub implements SpecialCommand { @Override public String[] description() { return new String[]{ - "§esub §8<§7Variable§8> §8<§7Variable§8>", - "§esub §8<§7Variable§8> §8<§7Variable§8> §8<§7Variable§8>", + "§esub §8<§7Variable§8> §8<§7Variable§8|§7Wert§8>", + "§esub §8<§7Variable§8> §8<§7Variable§8|§7Wert§8> §8<§7Variable§8|§7Wert§8>", "", "Subtraktion zwischen den letzten beiden Variablen und schreibt es in die erste." }; @@ -44,11 +44,11 @@ public class Sub implements SpecialCommand { Value v1 = scriptExecutor.getOrItselfValue(command[command.length - 2]); Value v2 = scriptExecutor.getOrItselfValue(command[command.length - 1]); - if (v1.getClass() != Value.LongValue.class) { + if (!(v1 instanceof Value.LongValue)) { scriptExecutor.getPlayer().sendMessage(BauSystem.PREFIX + "§cNur Zahlen können subtrahiert werden"); return true; } - if (v2.getClass() != Value.LongValue.class) { + if (!(v2 instanceof Value.LongValue)) { scriptExecutor.getPlayer().sendMessage(BauSystem.PREFIX + "§cNur Zahlen können subtrahiert werden"); return true; } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/logic/And.java b/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/logic/And.java index e7526748..e19f2c59 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/logic/And.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/logic/And.java @@ -44,11 +44,11 @@ public class And implements SpecialCommand { Value v1 = scriptExecutor.getOrItselfValue(command[command.length - 2]); Value v2 = scriptExecutor.getOrItselfValue(command[command.length - 1]); - if (v1.getClass() != Value.BooleanValue.class) { + if (!(v1 instanceof Value.BooleanValue)) { scriptExecutor.getPlayer().sendMessage(BauSystem.PREFIX + "§cNur Booleans können verglichen werden"); return true; } - if (v2.getClass() != Value.BooleanValue.class) { + if (!(v2 instanceof Value.BooleanValue)) { scriptExecutor.getPlayer().sendMessage(BauSystem.PREFIX + "§cNur Booleans können verglichen werden"); return true; } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/logic/Equal.java b/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/logic/Equal.java index a02aaf71..6fe644a7 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/logic/Equal.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/logic/Equal.java @@ -45,7 +45,7 @@ public class Equal implements SpecialCommand { Value v1 = scriptExecutor.getOrItselfValue(command[command.length - 2]); Value v2 = scriptExecutor.getOrItselfValue(command[command.length - 1]); Value result; - if (v1.getClass() != v2.getClass()) { + if (!v1.getClass().isInstance(v2.getClass()) && !v2.getClass().isInstance(v1.getClass())) { result = new Value.BooleanValue(false); } else if (v1.asString().equals(v2.asString())) { result = new Value.BooleanValue(true); diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/logic/Greater.java b/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/logic/Greater.java index 196b3ad4..8539de02 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/logic/Greater.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/logic/Greater.java @@ -44,11 +44,11 @@ public class Greater implements SpecialCommand { Value v1 = scriptExecutor.getOrItselfValue(command[command.length - 2]); Value v2 = scriptExecutor.getOrItselfValue(command[command.length - 1]); - if (v1.getClass() != Value.LongValue.class) { + if (!(v1 instanceof Value.LongValue)) { scriptExecutor.getPlayer().sendMessage(BauSystem.PREFIX + "§cNur Zahlen können verglichen werden"); return true; } - if (v2.getClass() != Value.LongValue.class) { + if (!(v2 instanceof Value.LongValue)) { scriptExecutor.getPlayer().sendMessage(BauSystem.PREFIX + "§cNur Zahlen können verglichen werden"); return true; } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/logic/Less.java b/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/logic/Less.java index 32cfd20d..a9e086d4 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/logic/Less.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/logic/Less.java @@ -44,11 +44,11 @@ public class Less implements SpecialCommand { Value v1 = scriptExecutor.getOrItselfValue(command[command.length - 2]); Value v2 = scriptExecutor.getOrItselfValue(command[command.length - 1]); - if (v1.getClass() != Value.LongValue.class) { + if (!(v1 instanceof Value.LongValue)) { scriptExecutor.getPlayer().sendMessage(BauSystem.PREFIX + "§cNur Zahlen können verglichen werden"); return true; } - if (v2.getClass() != Value.LongValue.class) { + if (!(v2 instanceof Value.LongValue)) { scriptExecutor.getPlayer().sendMessage(BauSystem.PREFIX + "§cNur Zahlen können verglichen werden"); return true; } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/logic/Not.java b/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/logic/Not.java index 72c9a59f..9be6f034 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/logic/Not.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/logic/Not.java @@ -39,7 +39,7 @@ public class Not implements SpecialCommand { } Value v1 = scriptExecutor.getOrItselfValue(command[command.length - 1]); - if (v1.getClass() != Value.BooleanValue.class) { + if (!(v1 instanceof Value.BooleanValue)) { scriptExecutor.getPlayer().sendMessage(BauSystem.PREFIX + "§cNur Booleans können genichtet werden"); return true; } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/logic/Or.java b/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/logic/Or.java index ce67eede..7d6c9bae 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/logic/Or.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/logic/Or.java @@ -44,11 +44,11 @@ public class Or implements SpecialCommand { Value v1 = scriptExecutor.getOrItselfValue(command[command.length - 2]); Value v2 = scriptExecutor.getOrItselfValue(command[command.length - 1]); - if (v1.getClass() != Value.BooleanValue.class) { + if (!(v1 instanceof Value.BooleanValue)) { scriptExecutor.getPlayer().sendMessage(BauSystem.PREFIX + "§cNur Booleans können verglichen werden"); return true; } - if (v2.getClass() != Value.BooleanValue.class) { + if (!(v2 instanceof Value.BooleanValue)) { scriptExecutor.getPlayer().sendMessage(BauSystem.PREFIX + "§cNur Booleans können verglichen werden"); return true; } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/string/Insert.java b/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/string/Insert.java index e3629d0e..0036af54 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/string/Insert.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/string/Insert.java @@ -70,15 +70,15 @@ public class Insert implements SpecialCommand { Value v2 = scriptExecutor.getOrItselfValue(command[command.length - 2]); Value v3 = scriptExecutor.getOrItselfValue(command[command.length - 1]); - if (v1.getClass() != Value.StringValue.class) { + if (!(v1 instanceof Value.StringValue)) { scriptExecutor.getPlayer().sendMessage(BauSystem.PREFIX + "§cNur Strings können verwendet werden"); return true; } - if (v2.getClass() != Value.StringValue.class) { + if (!(v2 instanceof Value.StringValue)) { scriptExecutor.getPlayer().sendMessage(BauSystem.PREFIX + "§cNur Strings können verwendet werden"); return true; } - if (v3.getClass() != Value.LongValue.class) { + if (!(v3 instanceof Value.StringValue)) { scriptExecutor.getPlayer().sendMessage(BauSystem.PREFIX + "§cNur Zahlen können verwendet werden"); return true; } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/string/Length.java b/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/string/Length.java index 749c1511..77d463eb 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/string/Length.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/string/Length.java @@ -64,7 +64,7 @@ public class Length implements SpecialCommand { String resultName = command[1]; Value v2 = scriptExecutor.getOrItselfValue(command[command.length - 1]); - if (v2.getClass() != Value.StringValue.class) { + if (!(v2 instanceof Value.StringValue)) { scriptExecutor.getPlayer().sendMessage(BauSystem.PREFIX + "§cNur Strings können verwendet werden"); return true; } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/string/Remove.java b/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/string/Remove.java index f6bad4d7..ff692ee0 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/string/Remove.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/string/Remove.java @@ -65,11 +65,11 @@ public class Remove implements SpecialCommand { Value v1 = scriptExecutor.getOrItselfValue(command[command.length - 2]); Value v2 = scriptExecutor.getOrItselfValue(command[command.length - 1]); - if (v1.getClass() != Value.StringValue.class) { + if (!(v1 instanceof Value.StringValue)) { scriptExecutor.getPlayer().sendMessage(BauSystem.PREFIX + "§cNur Strings können verwendet werden"); return true; } - if (v2.getClass() != Value.StringValue.class) { + if (!(v2 instanceof Value.StringValue)) { scriptExecutor.getPlayer().sendMessage(BauSystem.PREFIX + "§cNur Strings können verwendet werden"); return true; } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/string/Replace.java b/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/string/Replace.java index 3aacb7de..0e8eebd1 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/string/Replace.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/string/Replace.java @@ -70,15 +70,15 @@ public class Replace implements SpecialCommand { Value v2 = scriptExecutor.getOrItselfValue(command[command.length - 2]); Value v3 = scriptExecutor.getOrItselfValue(command[command.length - 1]); - if (v1.getClass() != Value.StringValue.class) { + if (!(v1 instanceof Value.StringValue)) { scriptExecutor.getPlayer().sendMessage(BauSystem.PREFIX + "§cNur Strings können verwendet werden"); return true; } - if (v2.getClass() != Value.StringValue.class) { + if (!(v2 instanceof Value.StringValue)) { scriptExecutor.getPlayer().sendMessage(BauSystem.PREFIX + "§cNur Strings können verwendet werden"); return true; } - if (v3.getClass() != Value.StringValue.class) { + if (!(v3 instanceof Value.StringValue)) { scriptExecutor.getPlayer().sendMessage(BauSystem.PREFIX + "§cNur Strings können verwendet werden"); return true; } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/string/Substring.java b/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/string/Substring.java index edba61f8..88623656 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/string/Substring.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/string/Substring.java @@ -65,11 +65,11 @@ public class Substring implements SpecialCommand { Value v1 = scriptExecutor.getOrItselfValue(command[command.length - 2]); Value v2 = scriptExecutor.getOrItselfValue(command[command.length - 1]); - if (v1.getClass() != Value.StringValue.class) { + if (!(v1 instanceof Value.StringValue)) { scriptExecutor.getPlayer().sendMessage(BauSystem.PREFIX + "§cNur Strings können verwendet werden"); return true; } - if (v2.getClass() != Value.LongValue.class) { + if (!(v2 instanceof Value.LongValue)) { scriptExecutor.getPlayer().sendMessage(BauSystem.PREFIX + "§cNur Zahlen können verwendet werden"); return true; } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/variable/Const.java b/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/variable/Const.java new file mode 100644 index 00000000..79915ddc --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/variable/Const.java @@ -0,0 +1,73 @@ +/* + * 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.bausystem.features.script.command.variable; + +import de.steamwar.bausystem.BauSystem; +import de.steamwar.bausystem.features.script.ScriptExecutor; +import de.steamwar.bausystem.features.script.SpecialCommand; +import de.steamwar.bausystem.features.script.variables.Constants; +import de.steamwar.bausystem.linkage.LinkageType; +import de.steamwar.bausystem.linkage.Linked; +import org.bukkit.Material; + +@Linked(LinkageType.SCRIPT_COMMAND) +public class Const implements SpecialCommand { + + @Override + public String[] description() { + return new String[]{ + "§econst §8<§7Variable§8> §8[§7Value§8(§7s§8)§8]", + "", + "Schreibt in eine Konstante einen Wert rein, welcher eine Zahl sein kann, ein Boolscher Wert oder ein Text." + }; + } + + @Override + public Material material() { + return Material.STRUCTURE_BLOCK; + } + + @Override + public String command() { + return "const"; + } + + @Override + public boolean execute(String[] command, ScriptExecutor scriptExecutor) { + if (command.length <= 1) { + scriptExecutor.getPlayer().sendMessage(BauSystem.PREFIX + "§cDas erste Argument fehlt und sollte eine Variable sein"); + return true; + } + if (command.length <= 2) { + scriptExecutor.getPlayer().sendMessage(BauSystem.PREFIX + "§cDas zweite Argument fehlt und sollte ein Wert sein"); + return true; + } + String varName = command[1]; + StringBuilder varValue = new StringBuilder(); + for (int i = 2; i < command.length; i++) { + if (varValue.length() != 0) { + varValue.append(" "); + } + varValue.append(command[i]); + } + Constants.getConstant(varName, scriptExecutor.getPlayer()).fromValue(scriptExecutor.parse(varValue.toString())); + return true; + } +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/variable/Global.java b/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/variable/Global.java index 9c983fd6..97821477 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/variable/Global.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/variable/Global.java @@ -3,7 +3,6 @@ package de.steamwar.bausystem.features.script.command.variable; import de.steamwar.bausystem.BauSystem; import de.steamwar.bausystem.features.script.ScriptExecutor; import de.steamwar.bausystem.features.script.SpecialCommand; -import de.steamwar.bausystem.features.script.variables.Value; import de.steamwar.bausystem.linkage.LinkageType; import de.steamwar.bausystem.linkage.Linked; import org.bukkit.Material; @@ -48,17 +47,7 @@ public class Global implements SpecialCommand { } varValue.append(command[i]); } - try { - long value = Long.parseLong(varValue.toString()); - scriptExecutor.getLocalVariables().putValue(varName, new Value.LongValue(value)); - } catch (NumberFormatException e) { - String s = varValue.toString(); - if (s.equalsIgnoreCase("true") || s.equalsIgnoreCase("false")) { - scriptExecutor.getGlobalVariables().putValue(varName, new Value.BooleanValue(s.equalsIgnoreCase("true"))); - } else { - scriptExecutor.getGlobalVariables().putValue(varName, new Value.StringValue(s)); - } - } + scriptExecutor.getGlobalVariables().putValue(varName, scriptExecutor.parse(varValue.toString())); return true; } } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/variable/Var.java b/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/variable/Var.java index 5204940c..82033387 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/variable/Var.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/script/command/variable/Var.java @@ -3,6 +3,7 @@ package de.steamwar.bausystem.features.script.command.variable; import de.steamwar.bausystem.BauSystem; import de.steamwar.bausystem.features.script.ScriptExecutor; import de.steamwar.bausystem.features.script.SpecialCommand; +import de.steamwar.bausystem.features.script.variables.Constants; import de.steamwar.bausystem.features.script.variables.Value; import de.steamwar.bausystem.linkage.LinkageType; import de.steamwar.bausystem.linkage.Linked; @@ -48,17 +49,7 @@ public class Var implements SpecialCommand { } varValue.append(command[i]); } - try { - long value = Long.parseLong(varValue.toString()); - scriptExecutor.getLocalVariables().putValue(varName, new Value.LongValue(value)); - } catch (NumberFormatException e) { - String s = varValue.toString(); - if (s.equalsIgnoreCase("true") || s.equalsIgnoreCase("false")) { - scriptExecutor.getLocalVariables().putValue(varName, new Value.BooleanValue(s.equalsIgnoreCase("true"))); - } else { - scriptExecutor.getLocalVariables().putValue(varName, new Value.StringValue(s)); - } - } + scriptExecutor.getLocalVariables().putValue(varName, scriptExecutor.parse(varValue.toString())); return true; } } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/script/ScriptBookBauGuiItem.java b/BauSystem_Main/src/de/steamwar/bausystem/features/script/items/ScriptMenuBauGuiItem.java similarity index 92% rename from BauSystem_Main/src/de/steamwar/bausystem/features/script/ScriptBookBauGuiItem.java rename to BauSystem_Main/src/de/steamwar/bausystem/features/script/items/ScriptMenuBauGuiItem.java index 35e2b2ad..c7bed6f3 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/script/ScriptBookBauGuiItem.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/script/items/ScriptMenuBauGuiItem.java @@ -17,7 +17,7 @@ * along with this program. If not, see . */ -package de.steamwar.bausystem.features.script; +package de.steamwar.bausystem.features.script.items; import de.steamwar.bausystem.Permission; import de.steamwar.bausystem.config.ColorConfig; @@ -31,9 +31,9 @@ import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; @Linked(LinkageType.BAU_GUI_ITEM) -public class ScriptBookBauGuiItem extends BauGuiItem { +public class ScriptMenuBauGuiItem extends BauGuiItem { - public ScriptBookBauGuiItem() { + public ScriptMenuBauGuiItem() { super(15); } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/script/variables/Constants.java b/BauSystem_Main/src/de/steamwar/bausystem/features/script/variables/Constants.java index 7e5508ff..eeb53f07 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/script/variables/Constants.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/script/variables/Constants.java @@ -8,51 +8,212 @@ import de.steamwar.bausystem.region.flags.flagvalues.FreezeMode; import de.steamwar.bausystem.region.flags.flagvalues.ProtectMode; import de.steamwar.bausystem.region.flags.flagvalues.TNTMode; import lombok.experimental.UtilityClass; +import org.bukkit.Location; import org.bukkit.entity.Player; import java.util.HashMap; import java.util.Map; import java.util.Set; +import java.util.function.Consumer; import java.util.function.Function; +import java.util.function.Supplier; @UtilityClass public class Constants { private final Map> CONSTANTS = new HashMap<>(); + private static class ConstantLongValue extends Value.LongValue { + + private Supplier longSupplier; + private Consumer longConsumer = ignored -> {}; + + public ConstantLongValue(Supplier longSupplier) { + super(longSupplier.get()); + this.longSupplier = longSupplier; + } + + public ConstantLongValue(Supplier longSupplier, Consumer longConsumer) { + super(longSupplier.get()); + this.longSupplier = longSupplier; + this.longConsumer = longConsumer; + } + + @Override + public long asLong() { + value = longSupplier.get(); + return super.asLong(); + } + + @Override + public boolean asBoolean() { + value = longSupplier.get(); + return super.asBoolean(); + } + + @Override + public String asString() { + value = longSupplier.get(); + return super.asString(); + } + + @Override + public void fromValue(Value value) { + super.fromValue(value); + longConsumer.accept(this.value); + } + } + + private static class ConstantBooleanValue extends Value.BooleanValue { + + private Supplier booleanSupplier; + private Consumer booleanConsumer = ignored -> {}; + + public ConstantBooleanValue(Supplier booleanSupplier) { + super(booleanSupplier.get()); + this.booleanSupplier = booleanSupplier; + } + + public ConstantBooleanValue(Supplier booleanSupplier, Consumer booleanConsumer) { + super(booleanSupplier.get()); + this.booleanSupplier = booleanSupplier; + this.booleanConsumer = booleanConsumer; + } + + @Override + public long asLong() { + value = booleanSupplier.get(); + return super.asLong(); + } + + @Override + public boolean asBoolean() { + value = booleanSupplier.get(); + return super.asBoolean(); + } + + @Override + public String asString() { + value = booleanSupplier.get(); + return super.asString(); + } + + @Override + public void fromValue(Value value) { + super.fromValue(value); + booleanConsumer.accept(this.value); + } + } + + private static class ConstantStringValue extends Value.StringValue { + + private Supplier stringSupplier; + private Consumer stringConsumer = ignored -> {}; + + public ConstantStringValue(Supplier stringSupplier) { + super(stringSupplier.get()); + this.stringSupplier = stringSupplier; + } + + public ConstantStringValue(Supplier stringSupplier, Consumer stringConsumer) { + super(stringSupplier.get()); + this.stringSupplier = stringSupplier; + this.stringConsumer = stringConsumer; + } + + @Override + public long asLong() { + value = stringSupplier.get(); + return super.asLong(); + } + + @Override + public boolean asBoolean() { + value = stringSupplier.get(); + return super.asBoolean(); + } + + @Override + public String asString() { + value = stringSupplier.get(); + return super.asString(); + } + + @Override + public void fromValue(Value value) { + super.fromValue(value); + stringConsumer.accept(this.value); + } + } + static { CONSTANTS.put("trace", player -> { - return new Value.BooleanValue(RecordStateMachine.getRecordStatus().isTracing()); + return new ConstantBooleanValue(RecordStateMachine.getRecordStatus()::isTracing); }); CONSTANTS.put("autotrace", player -> { - return new Value.BooleanValue(RecordStateMachine.getRecordStatus().isAutoTrace()); + return new ConstantBooleanValue(RecordStateMachine.getRecordStatus()::isAutoTrace); }); CONSTANTS.put("tnt", player -> { - return new Value.BooleanValue(Region.getRegion(player.getLocation()).getPlain(Flag.TNT, TNTMode.class) != TNTMode.DENY); + return new ConstantBooleanValue(() -> Region.getRegion(player.getLocation()).getPlain(Flag.TNT, TNTMode.class) != TNTMode.DENY); + }); + CONSTANTS.put("tnt-onlytb", player -> { + return new ConstantBooleanValue(() -> Region.getRegion(player.getLocation()).getPlain(Flag.TNT, TNTMode.class) != TNTMode.ONLY_TB); }); CONSTANTS.put("freeze", player -> { - return new Value.BooleanValue(Region.getRegion(player.getLocation()).getPlain(Flag.FREEZE, FreezeMode.class) == FreezeMode.ACTIVE); + return new ConstantBooleanValue(() -> Region.getRegion(player.getLocation()).getPlain(Flag.FREEZE, FreezeMode.class) == FreezeMode.ACTIVE); }); CONSTANTS.put("fire", player -> { - return new Value.BooleanValue(Region.getRegion(player.getLocation()).getPlain(Flag.FIRE, FireMode.class) == FireMode.ALLOW); + return new ConstantBooleanValue(() -> Region.getRegion(player.getLocation()).getPlain(Flag.FIRE, FireMode.class) == FireMode.ALLOW); }); CONSTANTS.put("protect", player -> { - return new Value.BooleanValue(Region.getRegion(player.getLocation()).getPlain(Flag.PROTECT, ProtectMode.class) == ProtectMode.ACTIVE); + return new ConstantBooleanValue(() -> Region.getRegion(player.getLocation()).getPlain(Flag.PROTECT, ProtectMode.class) == ProtectMode.ACTIVE); }); CONSTANTS.put("x", player -> { - return new Value.LongValue(player.getLocation().getBlockX()); + return new ConstantLongValue(() -> (long) player.getLocation().getBlockX(), aLong -> { + Location location = player.getLocation(); + location.setX((double) aLong); + player.teleport(location); + }); }); CONSTANTS.put("y", player -> { - return new Value.LongValue(player.getLocation().getBlockY()); + return new ConstantLongValue(() -> (long) player.getLocation().getBlockY(), aLong -> { + Location location = player.getLocation(); + location.setY((double) aLong); + player.teleport(location); + }); }); CONSTANTS.put("z", player -> { - return new Value.LongValue(player.getLocation().getBlockZ()); + return new ConstantLongValue(() -> (long) player.getLocation().getBlockZ(), aLong -> { + Location location = player.getLocation(); + location.setZ((double) aLong); + player.teleport(location); + }); }); CONSTANTS.put("name", player -> { - return new Value.StringValue(player.getDisplayName()); + return new ConstantStringValue(player::getDisplayName); }); CONSTANTS.put("sneaking", player -> { - return new Value.BooleanValue(player.isSneaking()); + return new ConstantBooleanValue(player::isSneaking); + }); + CONSTANTS.put("sprinting", player -> { + return new ConstantBooleanValue(player::isSprinting); + }); + CONSTANTS.put("slot", player -> { + return new ConstantLongValue(() -> (long) player.getInventory().getHeldItemSlot(), slot -> { + if (slot > 8) { + slot = 8L; + } + if (slot < 0) { + slot = 0L; + } + player.getInventory().setHeldItemSlot((int) (long) slot); + }); + }); + CONSTANTS.put("slotmaterial", player -> { + return new ConstantStringValue(() -> player.getInventory().getItemInMainHand().getType().name()); + }); + CONSTANTS.put("offhandmaterial", player -> { + return new ConstantStringValue(() -> player.getInventory().getItemInOffHand().getType().name()); }); } @@ -67,5 +228,4 @@ public class Constants { public Value getConstant(String variableName, Player player) { return CONSTANTS.get(variableName).apply(player); } - } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/script/variables/Context.java b/BauSystem_Main/src/de/steamwar/bausystem/features/script/variables/Context.java index a5bb62f8..1ad1e22b 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/script/variables/Context.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/script/variables/Context.java @@ -9,7 +9,11 @@ public class Context { private Map variables = new HashMap<>(); public void putValue(String variableName, Value value) { - variables.put(variableName, value); + if (variables.containsKey(variableName)) { + variables.get(variableName).fromValue(value); + } else { + variables.put(variableName, value); + } } public void removeValue(String variableName) { diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/script/variables/Value.java b/BauSystem_Main/src/de/steamwar/bausystem/features/script/variables/Value.java index 98c1cb46..b70c776e 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/script/variables/Value.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/script/variables/Value.java @@ -8,15 +8,13 @@ public interface Value { boolean asBoolean(); String asString(); - void fromLong(long value); - void fromBoolean(boolean value); - void fromString(String value); + void fromValue(Value value); @AllArgsConstructor @ToString class LongValue implements Value { - private long value; + protected long value; @Override public long asLong() { @@ -34,22 +32,8 @@ public interface Value { } @Override - public void fromLong(long value) { - this.value = value; - } - - @Override - public void fromBoolean(boolean value) { - this.value = value ? 1 : 0; - } - - @Override - public void fromString(String value) { - try { - this.value = Long.parseLong(value); - } catch (NumberFormatException e) { - this.value = 0; - } + public void fromValue(Value value) { + this.value = value.asLong(); } } @@ -57,7 +41,7 @@ public interface Value { @ToString class BooleanValue implements Value { - private boolean value; + protected boolean value; @Override public long asLong() { @@ -75,18 +59,8 @@ public interface Value { } @Override - public void fromLong(long value) { - this.value = value != 0; - } - - @Override - public void fromBoolean(boolean value) { - this.value = value; - } - - @Override - public void fromString(String value) { - this.value = value.equalsIgnoreCase("true") || value.equalsIgnoreCase("yes"); + public void fromValue(Value value) { + this.value = value.asBoolean(); } } @@ -94,7 +68,7 @@ public interface Value { @ToString class StringValue implements Value { - private String value; + protected String value; @Override public long asLong() { @@ -116,18 +90,8 @@ public interface Value { } @Override - public void fromLong(long value) { - this.value = value + ""; - } - - @Override - public void fromBoolean(boolean value) { - this.value = value + ""; - } - - @Override - public void fromString(String value) { - this.value = value; + public void fromValue(Value value) { + this.value = value.asString(); } } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/TNTSimulator.java b/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/TNTSimulator.java index e4452738..f7db47b2 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/TNTSimulator.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/TNTSimulator.java @@ -25,10 +25,12 @@ import de.steamwar.bausystem.BauSystem; import de.steamwar.bausystem.SWUtils; import de.steamwar.bausystem.config.ColorConfig; import de.steamwar.bausystem.features.simulator.show.SimulatorEntityShowMode; +import de.steamwar.bausystem.worlddata.WorldData; import de.steamwar.inventory.SWAnvilInv; import de.steamwar.inventory.SWInventory; import de.steamwar.inventory.SWItem; import de.steamwar.inventory.SWListInv; +import de.steamwar.sql.SteamwarUser; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.World; @@ -40,6 +42,8 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.util.Consumer; import org.bukkit.util.RayTraceResult; import org.bukkit.util.Vector; +import yapion.hierarchy.types.YAPIONArray; +import yapion.hierarchy.types.YAPIONObject; import java.util.*; import java.util.concurrent.atomic.AtomicInteger; @@ -56,14 +60,39 @@ public class TNTSimulator { private static final List EMPTY = new ArrayList<>(); public static final ItemStack WAND = new SWItem(Material.BLAZE_ROD, "§eKanonensimulator", Arrays.asList("§eRechtsklick §8- §7Füge eine Position hinzu", "§eSneaken §8- §7Auf den Block zentrieren", "§eLinksklick §8- §7Starte die Simulation", "§eRechtsklick Luft §8- §7Öffne die GUI"), false, null).getItemStack(); - private static final Map TNT_SIMULATOR_MAP = new HashMap<>(); + static final Map TNT_SIMULATOR_MAP = new HashMap<>(); public static TNTSimulator get(Player player) { - return TNT_SIMULATOR_MAP.computeIfAbsent(player, p -> new TNTSimulator(player)); + return TNT_SIMULATOR_MAP.computeIfAbsent(player, p -> { + YAPIONArray yapionArray = WorldData.getSimulatorData().getYAPIONArrayOrSetDefault(SteamwarUser.get(player.getUniqueId()).getId() + "", new YAPIONArray()); + TNTSimulator simulator = new TNTSimulator(player); + if (!yapionArray.isEmpty()) { + yapionArray.forEach(yapionAnyType -> { + simulator.spawns.add(simulator.new TNTSpawn((YAPIONObject) yapionAnyType)); + }); + } + return simulator; + }); + } + + public void saveAndDelete() { + TNTSimulator simulator = TNT_SIMULATOR_MAP.remove(player); + YAPIONArray yapionArray = new YAPIONArray(); + simulator.spawns.forEach(tntSpawn -> { + yapionArray.add(tntSpawn.output()); + }); + String userID = SteamwarUser.get(player.getUniqueId()).getId() + ""; + if (yapionArray.isEmpty()) { + WorldData.getSimulatorData().remove(userID); + } else { + WorldData.getSimulatorData().add(userID, yapionArray); + } + simulator.hide(); } public void delete() { TNTSimulator simulator = TNT_SIMULATOR_MAP.remove(player); + WorldData.getSimulatorData().remove(SteamwarUser.get(player.getUniqueId()).getId() + ""); simulator.hide(); } @@ -211,7 +240,23 @@ public class TNTSimulator { private void spawnRandomList(List tntSpawns) { if (tntSpawns.isEmpty()) return; - Collections.shuffle(tntSpawns); + + List toShuffle = new ArrayList<>(); + List indices = new ArrayList<>(); + + for (int i = 0; i < tntSpawns.size(); i++) { + TNTSpawn tntSpawn = tntSpawns.get(i); + if (tntSpawn.xVelocity || tntSpawn.yVelocity || tntSpawn.zVelocity) { + toShuffle.add(tntSpawn); + indices.add(i); + } + } + Collections.shuffle(indices); + + for (TNTSpawn tntSpawn : toShuffle) { + tntSpawns.set(indices.remove(0), tntSpawn); + } + for (TNTSpawn tntSpawn : tntSpawns) { tntSpawn.spawn(); } @@ -278,6 +323,33 @@ public class TNTSimulator { editTNT(); } + private TNTSpawn(YAPIONObject yapionObject) { + this.position = new Vector(yapionObject.getPlainValueOrDefault("positionX", 0.0), yapionObject.getPlainValueOrDefault("positionY", 0.0), yapionObject.getPlainValueOrDefault("positionZ", 0.0)); + this.entity = SimulatorEntityShowMode.createEntity(player, position, false); + this.fuseTicks = yapionObject.getPlainValue("fuseTicks"); + this.count = yapionObject.getPlainValue("count"); + this.tickOffset = yapionObject.getPlainValue("tickOffset"); + this.xVelocity = yapionObject.getPlainValue("xVelocity"); + this.yVelocity = yapionObject.getPlainValue("yVelocity"); + this.zVelocity = yapionObject.getPlainValue("zVelocity"); + this.comparator = yapionObject.getPlainValue("comparator"); + } + + private YAPIONObject output() { + YAPIONObject yapionObject = new YAPIONObject(); + yapionObject.add("positionX", position.getX()); + yapionObject.add("positionY", position.getY()); + yapionObject.add("positionZ", position.getZ()); + yapionObject.add("fuseTicks", fuseTicks); + yapionObject.add("count", count); + yapionObject.add("tickOffset", tickOffset); + yapionObject.add("xVelocity", xVelocity); + yapionObject.add("yVelocity", yVelocity); + yapionObject.add("zVelocity", zVelocity); + yapionObject.add("comparator", comparator); + return yapionObject; + } + private void show() { if (printed) return; diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/TNTSimulatorListener.java b/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/TNTSimulatorListener.java index 58289a9b..8a93e29f 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/TNTSimulatorListener.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/TNTSimulatorListener.java @@ -23,6 +23,7 @@ package de.steamwar.bausystem.features.simulator; import de.steamwar.bausystem.BauSystem; import de.steamwar.bausystem.Permission; +import de.steamwar.bausystem.linkage.Disable; import de.steamwar.bausystem.linkage.LinkageType; import de.steamwar.bausystem.linkage.Linked; import org.bukkit.FluidCollisionMode; @@ -47,7 +48,8 @@ import static de.steamwar.bausystem.features.simulator.TNTSimulator.WAND; import static de.steamwar.bausystem.features.simulator.TNTSimulator.get; @Linked(LinkageType.LISTENER) -public class TNTSimulatorListener implements Listener { +@Linked(LinkageType.DISABLE_LINK) +public class TNTSimulatorListener implements Listener, Disable { private boolean permissionCheck(Player player) { if (!Permission.hasPermission(player, Permission.WORLD)) { @@ -139,7 +141,13 @@ public class TNTSimulatorListener implements Listener { @EventHandler public void onPlayerQuit(PlayerQuitEvent event) { - get(event.getPlayer()).delete(); + get(event.getPlayer()).saveAndDelete(); } + @Override + public void disable() { + for (TNTSimulator simulator : TNTSimulator.TNT_SIMULATOR_MAP.values()) { + simulator.saveAndDelete(); + } + } } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/MaterialUtils.java b/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/MaterialUtils.java new file mode 100644 index 00000000..35c27649 --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/MaterialUtils.java @@ -0,0 +1,38 @@ +/* + * 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.bausystem.features.slaves; + +import de.steamwar.core.VersionedCallable; +import org.bukkit.Material; + +public class MaterialUtils { + + public static boolean isUnpusheable(Material material) { + return VersionedCallable.call( + new VersionedCallable<>(() -> MaterialUtils_15.isUnpusheable(material), 15) + ); + } + + public static boolean isBreakingOnPush(Material material) { + return VersionedCallable.call( + new VersionedCallable<>(() -> MaterialUtils_15.isBreakingOnPush(material), 15) + ); + } +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/WorldEditUtils.java b/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/WorldEditUtils.java new file mode 100644 index 00000000..43748537 --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/WorldEditUtils.java @@ -0,0 +1,63 @@ +/* + * 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.bausystem.features.slaves; + +import com.sk89q.worldedit.EditSession; +import com.sk89q.worldedit.IncompleteRegionException; +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.bukkit.BukkitAdapter; +import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.regions.RegionSelector; +import de.steamwar.bausystem.shared.Pair; +import lombok.experimental.UtilityClass; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.entity.Player; + +@UtilityClass +public class WorldEditUtils { + + public EditSession getEditSession(World world) { + return WorldEdit.getInstance().getEditSessionFactory().getEditSession(BukkitAdapter.adapt(world), Integer.MAX_VALUE); + } + + public void addToPlayer(Player player, EditSession editSession) { + WorldEdit.getInstance().getSessionManager().get(BukkitAdapter.adapt(player)).remember(editSession); + } + + public Pair getSelection(Player player) { + RegionSelector regionSelector = WorldEdit.getInstance() + .getSessionManager() + .get(BukkitAdapter.adapt(player)) + .getRegionSelector(BukkitAdapter.adapt(player.getWorld())); + + try { + BlockVector3 min = regionSelector.getRegion().getMinimumPoint(); + BlockVector3 max = regionSelector.getRegion().getMaximumPoint(); + return new Pair<>(adapt(player.getWorld(), min), adapt(player.getWorld(), max)); + } catch (IncompleteRegionException e) { + return null; + } + } + + private Location adapt(World world, BlockVector3 blockVector3) { + return new Location(world, blockVector3.getBlockX(), blockVector3.getBlockY(), blockVector3.getBlockZ()); + } +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/panzern/Panzern.java b/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/panzern/Panzern.java new file mode 100644 index 00000000..021c20c5 --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/panzern/Panzern.java @@ -0,0 +1,164 @@ +/* + * 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.bausystem.features.slaves.panzern; + +import com.sk89q.worldedit.EditSession; +import com.sk89q.worldedit.bukkit.BukkitAdapter; +import com.sk89q.worldedit.history.change.BlockChange; +import com.sk89q.worldedit.world.block.BaseBlock; +import com.sk89q.worldedit.world.block.BlockTypes; +import de.steamwar.bausystem.features.slaves.WorldEditUtils; +import lombok.Getter; +import lombok.SneakyThrows; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.util.Vector; + +import java.util.*; + +public class Panzern { + + private static List panzernAlgorithmList = new ArrayList<>(); + + public static void add(PanzernAlgorithm panzernAlgorithm) { + panzernAlgorithmList.add(panzernAlgorithm); + } + + private static final BlockFace[] BLOCK_FACES = new BlockFace[]{BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST, BlockFace.WEST, BlockFace.UP, BlockFace.DOWN}; + + private Set current = new LinkedHashSet<>(); + private Set emptyBlocks = new HashSet<>(); + + private World world; + private Location pos1; + private Location pos2; + private Material blockMaterial; + private Material slabMaterial; + + private BaseBlock blockType; + private BaseBlock slabType; + private static final BaseBlock jukeboxType = BlockTypes.JUKEBOX.getDefaultState().toBaseBlock(); + private static final BaseBlock airType = BlockTypes.AIR.getDefaultState().toBaseBlock(); + + @Getter + private EditSession editSession; + + public Panzern(Location pos1, Location pos2, Location possibleSource, Material blockMaterial, Material slabMaterial) { + this.world = pos1.getWorld(); + this.pos1 = new Location(world, Math.min(pos1.getBlockX(), pos2.getBlockX()), Math.min(pos1.getBlockY(), pos2.getBlockY()), Math.min(pos1.getBlockZ(), pos2.getBlockZ())); + this.pos2 = new Location(world, Math.max(pos1.getBlockX(), pos2.getBlockX()), Math.max(pos1.getBlockY(), pos2.getBlockY()), Math.max(pos1.getBlockZ(), pos2.getBlockZ())); + if (inRegion(possibleSource)) { + current.add(possibleSource); + } else { + current.add(this.pos1); + current.add(this.pos2); + } + this.blockMaterial = blockMaterial; + this.slabMaterial = slabMaterial; + + blockType = BlockTypes.get("minecraft:" + blockMaterial.name().toLowerCase()).getDefaultState().toBaseBlock(); + slabType = BlockTypes.get("minecraft:" + slabMaterial.name().toLowerCase()).getDefaultState().toBaseBlock(); + + editSession = WorldEditUtils.getEditSession(world); + } + + public boolean hasNext() { + return !current.isEmpty(); + } + + @SneakyThrows + public void next() { + Location toCheck = current.iterator().next(); + current.remove(toCheck); + + Map adjacent = new HashMap<>(); + Set adjacentMaterials = new HashSet<>(); + for (BlockFace blockFace : BLOCK_FACES) { + Location now = toCheck.clone().add(blockFace.getModX(), blockFace.getModY(), blockFace.getModZ()); + if (inRegion(now)) { + Block temp = world.getBlockAt(now); + adjacent.put(blockFace, temp); + adjacentMaterials.add(temp.getType()); + } + } + Block currentBlock = world.getBlockAt(toCheck); + + PanzernResult panzernResult = PanzernResult.DEFAULT; + for (PanzernAlgorithm panzernAlgorithm : panzernAlgorithmList) { + PanzernResult temp = panzernAlgorithm.check(currentBlock, adjacent, adjacentMaterials); + if (temp != null && temp != PanzernResult.DEFAULT) { + panzernResult = temp; + break; + } + } + + switch (panzernResult) { + case EMPTY: + emptyBlocks.add(currentBlock.getLocation().toVector()); + return; + case SLAB: + currentBlock.setType(slabMaterial); + editSession.getChangeSet().add(new BlockChange(BukkitAdapter.asBlockVector(currentBlock.getLocation()), airType, slabType)); + break; + case BLOCK: + case DEFAULT: + currentBlock.setType(blockMaterial); + editSession.getChangeSet().add(new BlockChange(BukkitAdapter.asBlockVector(currentBlock.getLocation()), airType, blockType)); + break; + case UNMOVABLE: + currentBlock.setType(Material.JUKEBOX); + editSession.getChangeSet().add(new BlockChange(BukkitAdapter.asBlockVector(currentBlock.getLocation()), airType, jukeboxType)); + break; + default: + emptyBlocks.add(currentBlock.getLocation().toVector()); + break; + } + + adjacent.forEach((blockFace, temp) -> { + if (temp.getType().isAir() && !emptyBlocks.contains(temp.getLocation().toVector())) { + current.add(temp.getLocation()); + } + }); + } + + private boolean inRegion(Location location) { + if (location.getBlockX() >= pos1.getBlockX()) { + if (location.getBlockY() >= pos1.getBlockY()) { + if (location.getBlockZ() >= pos1.getBlockZ()) { + if (location.getBlockX() <= pos2.getBlockX()) { + if (location.getBlockY() <= pos2.getBlockY()) { + if (location.getBlockZ() <= pos2.getBlockZ()) { + return true; + } + } + } + } + } + } + return false; + } + + public int blocksLeft() { + return current.size(); + } +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/panzern/PanzernAlgorithm.java b/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/panzern/PanzernAlgorithm.java new file mode 100644 index 00000000..f77be675 --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/panzern/PanzernAlgorithm.java @@ -0,0 +1,34 @@ +/* + * 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.bausystem.features.slaves.panzern; + +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; + +import java.util.Map; +import java.util.Set; + +public interface PanzernAlgorithm { + final BlockFace[] BLOCK_FACES = new BlockFace[]{BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST, BlockFace.WEST, BlockFace.UP, BlockFace.DOWN}; + final BlockFace[] HORIZONTAL_FACES = new BlockFace[]{BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST, BlockFace.WEST}; + + PanzernResult check(Block source, Map adjacent, Set adjacentMaterials); +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/panzern/PanzernCommand.java b/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/panzern/PanzernCommand.java new file mode 100644 index 00000000..ade00776 --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/panzern/PanzernCommand.java @@ -0,0 +1,155 @@ +/* + * 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.bausystem.features.slaves.panzern; + +import de.steamwar.bausystem.BauSystem; +import de.steamwar.bausystem.Permission; +import de.steamwar.bausystem.SWUtils; +import de.steamwar.bausystem.features.slaves.WorldEditUtils; +import de.steamwar.bausystem.linkage.LinkageType; +import de.steamwar.bausystem.linkage.Linked; +import de.steamwar.bausystem.shared.Pair; +import de.steamwar.command.SWCommand; +import de.steamwar.command.TypeMapper; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +@Linked(LinkageType.COMMAND) +public class PanzernCommand extends SWCommand { + + public PanzernCommand() { + super("panzern", "panzersklave"); + } + + private boolean permissionCheck(Player player, Permission permission) { + if (Permission.hasPermission(player, permission)) { + return true; + } + BauSystem.MESSAGE.send("PANZERN_NO_PERM", player); + return false; + } + + @Register(help = true) + public void genericHelp(Player player, String... args) { + BauSystem.MESSAGE.send("COMMAND_HELP_HEAD", player, "panzern"); + BauSystem.MESSAGE.send("PANZERN_HELP", player); + BauSystem.MESSAGE.send("PANZERN_PREPARE1", player); + BauSystem.MESSAGE.send("PANZERN_PREPARE2", player); + BauSystem.MESSAGE.send("PANZERN_PREPARE3", player); + BauSystem.MESSAGE.send("PANZERN_PREPARE4", player); + } + + @Register + public void panzerSelection(Player player, @Mapper("block") Material blockMaterial, @Mapper("slab") Material slabMaterial) { + if (!permissionCheck(player, Permission.WORLDEDIT)) { + return; + } + Pair selection = WorldEditUtils.getSelection(player); + if (selection == null) { + BauSystem.MESSAGE.send("PANZERN_NO_WORLDEDIT", player); + return; + } + Panzern panzern = new Panzern(selection.getKey(), selection.getValue(), player.getLocation(), blockMaterial, slabMaterial); + new BukkitRunnable() { + @Override + public void run() { + int blockLeft = panzern.blocksLeft(); + long totalTime = 0; + long blocks = 0; + while (true) { + if (!panzern.hasNext()) { + BauSystem.MESSAGE.send("PANZERN_DONE", player); + WorldEditUtils.addToPlayer(player, panzern.getEditSession()); + cancel(); + return; + } + long time = System.currentTimeMillis(); + panzern.next(); + totalTime += System.currentTimeMillis() - time; + blocks++; + if (totalTime > 40) { + break; + } + } + SWUtils.sendToActionbar(player, BauSystem.MESSAGE.parse("PANZERN_PROGRESS", player, panzern.blocksLeft(), blocks * 20, panzern.blocksLeft() - blockLeft)); + } + }.runTaskTimer(BauSystem.getInstance(), 1, 1); + } + + @Mapper(value = "block", local = true) + private TypeMapper blockMapper() { + Set strings = new HashSet<>(); + for (Material material : Material.values()) { + if (!material.isBlock()) { + continue; + } + strings.add(material.name().toLowerCase()); + } + return new TypeMapper() { + @Override + public List tabCompletes(CommandSender commandSender, String[] ignored, String s) { + return new ArrayList<>(strings); + } + + @Override + public Material map(CommandSender commandSender, String[] previousArguments, String s) { + if (strings.contains(s.toLowerCase())) { + return Material.valueOf(s.toUpperCase()); + } + return null; + } + }; + } + + @Mapper(value = "slab", local = true) + private TypeMapper slabMapper() { + Set strings = new HashSet<>(); + for (Material material : Material.values()) { + if (!material.isBlock()) { + continue; + } + if (material.name().contains("STAIRS") || material.name().contains("SLAB")) { + strings.add(material.name().toLowerCase()); + } + } + return new TypeMapper() { + @Override + public List tabCompletes(CommandSender commandSender, String[] ignored, String s) { + return new ArrayList<>(strings); + } + + @Override + public Material map(CommandSender commandSender, String[] previousArguments, String s) { + if (strings.contains(s.toLowerCase())) { + return Material.valueOf(s.toUpperCase()); + } + return null; + } + }; + } +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/panzern/PanzernResult.java b/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/panzern/PanzernResult.java new file mode 100644 index 00000000..74f7a24c --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/panzern/PanzernResult.java @@ -0,0 +1,28 @@ +/* + * 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.bausystem.features.slaves.panzern; + +public enum PanzernResult { + EMPTY, + SLAB, + UNMOVABLE, + BLOCK, + DEFAULT +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/panzern/algorithms/AdjacentHoney.java b/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/panzern/algorithms/AdjacentHoney.java new file mode 100644 index 00000000..4703515a --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/panzern/algorithms/AdjacentHoney.java @@ -0,0 +1,43 @@ +/* + * 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.bausystem.features.slaves.panzern.algorithms; + +import de.steamwar.bausystem.features.slaves.panzern.PanzernAlgorithm; +import de.steamwar.bausystem.features.slaves.panzern.PanzernResult; +import de.steamwar.bausystem.linkage.LinkageType; +import de.steamwar.bausystem.linkage.Linked; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; + +import java.util.Map; +import java.util.Set; + +@Linked(LinkageType.PANZERN) +public class AdjacentHoney implements PanzernAlgorithm { + + @Override + public PanzernResult check(Block source, Map adjacent, Set adjacentMaterials) { + if (adjacentMaterials.contains(Material.HONEY_BLOCK)) { + return PanzernResult.UNMOVABLE; + } + return PanzernResult.DEFAULT; + } +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/panzern/algorithms/AdjacentSlime.java b/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/panzern/algorithms/AdjacentSlime.java new file mode 100644 index 00000000..11523e5b --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/panzern/algorithms/AdjacentSlime.java @@ -0,0 +1,43 @@ +/* + * 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.bausystem.features.slaves.panzern.algorithms; + +import de.steamwar.bausystem.features.slaves.panzern.PanzernAlgorithm; +import de.steamwar.bausystem.features.slaves.panzern.PanzernResult; +import de.steamwar.bausystem.linkage.LinkageType; +import de.steamwar.bausystem.linkage.Linked; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; + +import java.util.Map; +import java.util.Set; + +@Linked(LinkageType.PANZERN) +public class AdjacentSlime implements PanzernAlgorithm { + + @Override + public PanzernResult check(Block source, Map adjacent, Set adjacentMaterials) { + if (adjacentMaterials.contains(Material.SLIME_BLOCK)) { + return PanzernResult.UNMOVABLE; + } + return PanzernResult.DEFAULT; + } +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/panzern/algorithms/CarpetWalkWay.java b/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/panzern/algorithms/CarpetWalkWay.java new file mode 100644 index 00000000..302e951e --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/panzern/algorithms/CarpetWalkWay.java @@ -0,0 +1,43 @@ +/* + * 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.bausystem.features.slaves.panzern.algorithms; + +import de.steamwar.bausystem.features.slaves.panzern.PanzernAlgorithm; +import de.steamwar.bausystem.features.slaves.panzern.PanzernResult; +import de.steamwar.bausystem.linkage.LinkageType; +import de.steamwar.bausystem.linkage.Linked; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; + +import java.util.Map; +import java.util.Set; + +@Linked(LinkageType.PANZERN) +public class CarpetWalkWay implements PanzernAlgorithm { + + @Override + public PanzernResult check(Block source, Map adjacent, Set adjacentMaterials) { + if (adjacent.containsKey(BlockFace.DOWN) && adjacent.get(BlockFace.DOWN).getType().name().contains("CARPET")) { + return PanzernResult.EMPTY; + } + return PanzernResult.DEFAULT; + } +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/panzern/algorithms/LadderWalkWay.java b/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/panzern/algorithms/LadderWalkWay.java new file mode 100644 index 00000000..37ca6002 --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/panzern/algorithms/LadderWalkWay.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.bausystem.features.slaves.panzern.algorithms; + +import de.steamwar.bausystem.features.slaves.panzern.PanzernAlgorithm; +import de.steamwar.bausystem.features.slaves.panzern.PanzernResult; +import de.steamwar.bausystem.linkage.LinkageType; +import de.steamwar.bausystem.linkage.Linked; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; + +import java.util.Map; +import java.util.Set; + +@Linked(LinkageType.PANZERN) +public class LadderWalkWay implements PanzernAlgorithm { + + @Override + public PanzernResult check(Block source, Map adjacent, Set adjacentMaterials) { + if (adjacent.containsKey(BlockFace.DOWN) && adjacent.get(BlockFace.DOWN).getType() == Material.LADDER) { + return PanzernResult.EMPTY; + } + if (source.getRelative(0, -2, 0).getType() == Material.LADDER) { + return PanzernResult.EMPTY; + } + return PanzernResult.DEFAULT; + } +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/panzern/algorithms/PistonLine.java b/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/panzern/algorithms/PistonLine.java new file mode 100644 index 00000000..de5c04f2 --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/panzern/algorithms/PistonLine.java @@ -0,0 +1,65 @@ +/* + * 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.bausystem.features.slaves.panzern.algorithms; + +import de.steamwar.bausystem.features.slaves.MaterialUtils; +import de.steamwar.bausystem.features.slaves.panzern.PanzernAlgorithm; +import de.steamwar.bausystem.features.slaves.panzern.PanzernResult; +import de.steamwar.bausystem.linkage.LinkageType; +import de.steamwar.bausystem.linkage.Linked; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.block.data.BlockData; +import org.bukkit.block.data.type.Piston; + +import java.util.Map; +import java.util.Set; + +@Linked(LinkageType.PANZERN) +public class PistonLine implements PanzernAlgorithm { + + @Override + public PanzernResult check(Block source, Map adjacent, Set adjacentMaterials) { + for (BlockFace blockFace : BLOCK_FACES) { + for (int i = 1; i < 14; i++) { + Block relativeBlock = source.getRelative(blockFace.getModX() * i, blockFace.getModY() * i, blockFace.getModZ() * i); + if (relativeBlock.getType().isAir()) { + break; + } + BlockData blockData = relativeBlock.getBlockData(); + if (!(blockData instanceof Piston)) { + if (MaterialUtils.isUnpusheable(relativeBlock.getType())) { + break; + } + if (MaterialUtils.isBreakingOnPush(relativeBlock.getType())) { + break; + } + continue; + } + Piston piston = (Piston) blockData; + if (piston.getFacing() == blockFace.getOppositeFace()) { + return PanzernResult.EMPTY; + } + } + } + return PanzernResult.DEFAULT; + } +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/panzern/algorithms/PowerableActivation.java b/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/panzern/algorithms/PowerableActivation.java new file mode 100644 index 00000000..121e97c4 --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/panzern/algorithms/PowerableActivation.java @@ -0,0 +1,89 @@ +/* + * 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.bausystem.features.slaves.panzern.algorithms; + +import de.steamwar.bausystem.features.slaves.panzern.PanzernAlgorithm; +import de.steamwar.bausystem.features.slaves.panzern.PanzernResult; +import de.steamwar.bausystem.linkage.LinkageType; +import de.steamwar.bausystem.linkage.Linked; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.block.data.AnaloguePowerable; +import org.bukkit.block.data.Directional; +import org.bukkit.block.data.Powerable; +import org.bukkit.block.data.type.RedstoneWire; + +import java.util.Map; +import java.util.Set; + +@Linked(LinkageType.PANZERN) +public class PowerableActivation implements PanzernAlgorithm { + + @Override + public PanzernResult check(Block source, Map adjacent, Set adjacentMaterials) { + int powered = 0; + int powerable = 0; + for (BlockFace blockFace : BLOCK_FACES) { + if (!adjacent.containsKey(blockFace)) { + continue; + } + Block block = adjacent.get(blockFace); + if ((block.getType() == Material.HOPPER || block.getBlockData() instanceof Powerable || block.getBlockData() instanceof AnaloguePowerable) && block.getType() != Material.OBSERVER) { + powerable++; + } + if (block.getType() == Material.TNT) { + powerable++; + } + if (blockFace == BlockFace.DOWN || blockFace == BlockFace.UP) { + continue; + } + switch (block.getType()) { + case REDSTONE_WIRE: + RedstoneWire redstoneWire = (RedstoneWire) block.getBlockData(); + boolean dot = true; + for (BlockFace current : HORIZONTAL_FACES) { + dot &= redstoneWire.getFace(current) == RedstoneWire.Connection.NONE; + } + if (dot) { + powered++; + } else if (redstoneWire.getAllowedFaces().contains(blockFace)) { + if (redstoneWire.getFace(blockFace) == RedstoneWire.Connection.SIDE) { + powered++; + } + } + break; + case REPEATER: + case COMPARATOR: + case OBSERVER: + if (((Directional) block.getBlockData()).getFacing() == blockFace) { + powered++; + } + break; + default: + break; + } + } + if (powered <= 1 && powerable <= 1) { + return PanzernResult.DEFAULT; + } + return PanzernResult.SLAB; + } +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/panzern/algorithms/SlabOnRedstone.java b/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/panzern/algorithms/SlabOnRedstone.java new file mode 100644 index 00000000..74c2ddf3 --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/panzern/algorithms/SlabOnRedstone.java @@ -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 . + */ + +package de.steamwar.bausystem.features.slaves.panzern.algorithms; + +import de.steamwar.bausystem.features.slaves.panzern.PanzernAlgorithm; +import de.steamwar.bausystem.features.slaves.panzern.PanzernResult; +import de.steamwar.bausystem.linkage.LinkageType; +import de.steamwar.bausystem.linkage.Linked; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; + +import java.util.Map; +import java.util.Set; + +@Linked(LinkageType.PANZERN) +public class SlabOnRedstone implements PanzernAlgorithm { + + @Override + public PanzernResult check(Block source, Map adjacent, Set adjacentMaterials) { + boolean hasRedstone = false; + for (BlockFace blockFace : HORIZONTAL_FACES) { + if (adjacent.containsKey(blockFace) && adjacent.get(blockFace).getType() == Material.REDSTONE_WIRE) { + hasRedstone = true; + } + } + if (hasRedstone && adjacent.containsKey(BlockFace.DOWN) && adjacent.get(BlockFace.DOWN).getType() == Material.REDSTONE_WIRE) { + return PanzernResult.SLAB; + } + return PanzernResult.DEFAULT; + } +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/panzern/algorithms/SlabOnTorch.java b/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/panzern/algorithms/SlabOnTorch.java new file mode 100644 index 00000000..8050303b --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/panzern/algorithms/SlabOnTorch.java @@ -0,0 +1,64 @@ +/* + * 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.bausystem.features.slaves.panzern.algorithms; + +import de.steamwar.bausystem.features.slaves.panzern.PanzernAlgorithm; +import de.steamwar.bausystem.features.slaves.panzern.PanzernResult; +import de.steamwar.bausystem.linkage.LinkageType; +import de.steamwar.bausystem.linkage.Linked; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.block.data.AnaloguePowerable; +import org.bukkit.block.data.Powerable; + +import java.util.Map; +import java.util.Set; + +@Linked(LinkageType.PANZERN) +public class SlabOnTorch implements PanzernAlgorithm { + + @Override + public PanzernResult check(Block source, Map adjacent, Set adjacentMaterials) { + boolean hasRedstone = false; + for (BlockFace blockFace : HORIZONTAL_FACES) { + if (!adjacent.containsKey(blockFace)) { + continue; + } + Block block = adjacent.get(blockFace); + if (block.getType() == Material.OBSERVER) { + continue; + } + if (block.getBlockData() instanceof Powerable) { + hasRedstone = true; + } + if (block.getBlockData() instanceof AnaloguePowerable) { + hasRedstone = true; + } + if (block.getType() == Material.TNT) { + hasRedstone = true; + } + } + if (hasRedstone && adjacent.containsKey(BlockFace.DOWN) && (adjacent.get(BlockFace.DOWN).getType() == Material.REDSTONE_WALL_TORCH || adjacent.get(BlockFace.DOWN).getType() == Material.REDSTONE_TORCH)) { + return PanzernResult.SLAB; + } + return PanzernResult.DEFAULT; + } +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/panzern/algorithms/StairWalkWay.java b/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/panzern/algorithms/StairWalkWay.java new file mode 100644 index 00000000..ee08a485 --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/panzern/algorithms/StairWalkWay.java @@ -0,0 +1,63 @@ +/* + * 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.bausystem.features.slaves.panzern.algorithms; + +import de.steamwar.bausystem.features.slaves.panzern.PanzernAlgorithm; +import de.steamwar.bausystem.features.slaves.panzern.PanzernResult; +import de.steamwar.bausystem.linkage.LinkageType; +import de.steamwar.bausystem.linkage.Linked; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.block.data.Bisected; +import org.bukkit.block.data.type.Stairs; + +import java.util.Map; +import java.util.Set; + +@Linked(LinkageType.PANZERN) +public class StairWalkWay implements PanzernAlgorithm { + + @Override + public PanzernResult check(Block source, Map adjacent, Set adjacentMaterials) { + if (adjacent.containsKey(BlockFace.DOWN) && stairCheck(adjacent.get(BlockFace.DOWN))) { + return PanzernResult.EMPTY; + } + if (stairCheck(source.getRelative(0, -2, 0))) { + return PanzernResult.EMPTY; + } + for (BlockFace blockFace : HORIZONTAL_FACES) { + Block current = source.getRelative(blockFace.getModX(), -2, blockFace.getModZ()); + if (stairCheck(current)) { + if (((Stairs) current.getBlockData()).getFacing() == blockFace) { + return PanzernResult.EMPTY; + } + } + } + return PanzernResult.DEFAULT; + } + + private boolean stairCheck(Block block) { + if (block.getBlockData() instanceof Stairs) { + return ((Stairs) block.getBlockData()).getHalf() == Bisected.Half.BOTTOM; + } + return false; + } +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/smartplace/SmartPlaceCommand.java b/BauSystem_Main/src/de/steamwar/bausystem/features/smartplace/SmartPlaceCommand.java new file mode 100644 index 00000000..1cddd42f --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/smartplace/SmartPlaceCommand.java @@ -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 . + */ + +package de.steamwar.bausystem.features.smartplace; + +import de.steamwar.bausystem.BauSystem; +import de.steamwar.bausystem.SWUtils; +import de.steamwar.bausystem.configplayer.Config; +import de.steamwar.bausystem.linkage.LinkageType; +import de.steamwar.bausystem.linkage.Linked; +import de.steamwar.command.SWCommand; +import org.bukkit.entity.Player; + +@Linked(LinkageType.COMMAND) +public class SmartPlaceCommand extends SWCommand { + + public SmartPlaceCommand() { + super("smartplace", "sp"); + } + + @Register(help = true) + public void genericHelp(Player p, String... args) { + BauSystem.MESSAGE.sendPrefixless("COMMAND_HELP_HEAD", p, "Smart Place"); + BauSystem.MESSAGE.sendPrefixless("SMART_PLACE_HELP", p); + BauSystem.MESSAGE.sendPrefixless("SMART_PLACE_INFO", p); + } + + @Register + public void genericToggle(Player p) { + boolean smartPlace = Config.getInstance().get(p).getPlainValueOrDefault("smartPlace", false); + Config.getInstance().get(p).put("smartPlace", !smartPlace); + if (!smartPlace) { + SWUtils.sendToActionbar(p, BauSystem.MESSAGE.parse("SMART_PLACE_ENABLE", p)); + BauSystem.MESSAGE.send("SMART_PLACE_INFO", p); + } else { + SWUtils.sendToActionbar(p, BauSystem.MESSAGE.parse("SMART_PLACE_DISABLE", p)); + } + } +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/smartplace/SmartPlaceListener.java b/BauSystem_Main/src/de/steamwar/bausystem/features/smartplace/SmartPlaceListener.java new file mode 100644 index 00000000..7ee8fd45 --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/smartplace/SmartPlaceListener.java @@ -0,0 +1,133 @@ +/* + * 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.bausystem.features.smartplace; + +import de.steamwar.bausystem.configplayer.Config; +import de.steamwar.bausystem.linkage.LinkageType; +import de.steamwar.bausystem.linkage.Linked; +import org.bukkit.GameMode; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.block.data.BlockData; +import org.bukkit.block.data.Directional; +import org.bukkit.block.data.Rotatable; +import org.bukkit.block.data.type.Repeater; +import org.bukkit.event.Event; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryHolder; + +@Linked(LinkageType.LISTENER) +public class SmartPlaceListener implements Listener { + + @EventHandler + public void onBlockPlace(BlockPlaceEvent event) { + if (event.getPlayer().isSneaking() && Config.getInstance().get(event.getPlayer()).getPlainValueOrDefault("smartPlace", false)) { + Block block = event.getBlockPlaced(); + BlockData blockData = block.getBlockData(); + if (blockData instanceof Directional) { + Directional directional = (Directional) blockData; + BlockFace blockFace = directional.getFacing().getOppositeFace(); + if (directional.getFaces().contains(blockFace)) { + directional.setFacing(blockFace); + } + } else if (blockData instanceof Rotatable) { + Rotatable rotatable = (Rotatable) blockData; + rotatable.setRotation(rotatable.getRotation()); + } + block.setBlockData(blockData); + } + } + + @EventHandler + public void onPlayerInteract(PlayerInteractEvent event) { + if (event.getAction() != Action.RIGHT_CLICK_BLOCK) return; + if (event.getPlayer().getGameMode() == GameMode.SPECTATOR) return; + if (!Config.getInstance().get(event.getPlayer()).getPlainValueOrDefault("smartPlace", false)) return; + + // Reverse repeater + if (event.getPlayer().isSneaking()) { + if (event.getClickedBlock().getType() == Material.REPEATER) { + if (event.getItem() != null && event.getMaterial() != Material.REPEATER) { + return; + } + Repeater repeater = (Repeater) event.getClickedBlock().getBlockData(); + int i = repeater.getDelay() - 1; + if (i <= 0) i += 4; + repeater.setDelay(i); + event.getClickedBlock().setBlockData(repeater); + event.setCancelled(true); + } + return; + } + + if (!event.getClickedBlock().getType().isInteractable()) return; + if (event.getItem() == null) return; + if (!event.getMaterial().isBlock()) return; + try { + BlockData blockData = event.getItem().getType().createBlockData(); + if (!(blockData instanceof Directional) && !(blockData instanceof Rotatable)) { + return; + } + } catch (Exception e) { + return; + } + + if (event.getClickedBlock().getType() == event.getMaterial() || event.getMaterial() == Material.HOPPER) { + if (!(event.getClickedBlock().getState() instanceof InventoryHolder)) { + return; + } + } else { + BlockData blockData = event.getMaterial().createBlockData(); + if (blockData instanceof Directional) { + return; + } + if (blockData instanceof Rotatable) { + return; + } + } + + // TODO: Fix block setting + event.setUseInteractedBlock(Event.Result.DENY); + World world = event.getPlayer().getWorld(); + Block block = world.getBlockAt(event.getClickedBlock().getX() + event.getBlockFace().getModX(), event.getClickedBlock().getY() + event.getBlockFace().getModY(), event.getClickedBlock().getZ() + event.getBlockFace().getModZ()); + block.setType(event.getMaterial()); + BlockData blockData = event.getItem().getType().createBlockData(); + BlockFace blockFace = event.getBlockFace(); + if (block.getType() == Material.HOPPER || block.getType() == Material.OBSERVER) { + blockFace = blockFace.getOppositeFace(); + } + if (blockData instanceof Directional) { + Directional directional = (Directional) blockData; + if (directional.getFaces().contains(blockFace)) { + directional.setFacing(blockFace); + } + } else if (blockData instanceof Rotatable) { + ((Rotatable) blockData).setRotation(blockFace); + } + block.setBlockData(blockData); + } +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/TraceCommand.java b/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/TraceCommand.java index f526babd..dc7fcb45 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/TraceCommand.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/TraceCommand.java @@ -21,6 +21,7 @@ package de.steamwar.bausystem.features.tracer; import de.steamwar.bausystem.BauSystem; import de.steamwar.bausystem.Permission; +import de.steamwar.bausystem.features.tracer.gui.TraceGui; import de.steamwar.bausystem.features.tracer.gui.TraceShowGui; import de.steamwar.bausystem.features.tracer.record.RecordStateMachine; import de.steamwar.bausystem.features.tracer.show.ShowModeParameter; @@ -92,15 +93,21 @@ public class TraceCommand extends SWCommand { BauSystem.MESSAGE.sendPrefixless("TRACE_COMMAND_HELP_START", p); BauSystem.MESSAGE.sendPrefixless("TRACE_COMMAND_HELP_STOP", p); BauSystem.MESSAGE.sendPrefixless("TRACE_COMMAND_HELP_AUTO", p); - // p.sendMessage("§8/§etrace show gui §8- §7Zeigt die Trace show gui"); + p.sendMessage("§8/§etrace show gui §8- §7Zeigt die Trace show gui"); BauSystem.MESSAGE.sendPrefixless("TRACE_COMMAND_HELP_SHOW", p); BauSystem.MESSAGE.sendPrefixless("TRACE_COMMAND_HELP_HIDE", p); BauSystem.MESSAGE.sendPrefixless("TRACE_COMMAND_HELP_DELETE", p); // p.sendMessage("§8/§etrace list §8<§7FRAME-ID§8> §8- §7Listet alle TNT auf"); - // p.sendMessage("§8/§etrace gui §8- §7Zeigt die Trace Oberfläche an"); + p.sendMessage("§8/§etrace gui §8- §7Zeigt die Trace Oberfläche an"); // p.sendMessage("§7Optionale Parameter mit §8<>§7, Benötigte Parameter mit §8[]"); } + @Register({"gui"}) + public void guiCommand(Player p) { + if (!permissionCheck(p)) return; + TraceGui.openGui(p); + } + @Register({"start"}) public void startCommand(Player p) { if (!permissionCheck(p)) return; diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/gui/TraceGui.java b/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/gui/TraceGui.java new file mode 100644 index 00000000..1b87bbf4 --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/gui/TraceGui.java @@ -0,0 +1,101 @@ +/* + * 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.bausystem.features.tracer.gui; + +import de.steamwar.bausystem.BauSystem; +import de.steamwar.bausystem.features.tracer.TNTPosition; +import de.steamwar.bausystem.features.tracer.show.Record; +import de.steamwar.bausystem.features.tracer.show.StoredRecords; +import de.steamwar.bausystem.features.tracer.show.TraceShowManager; +import de.steamwar.inventory.SWItem; +import de.steamwar.inventory.SWListInv; +import lombok.experimental.UtilityClass; +import org.bukkit.Material; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +@UtilityClass +public class TraceGui { + + public static void openGui(Player player) { + List> recordList = new ArrayList<>(); + StoredRecords.getRecords().forEach(record -> { + if (record.getTnt().isEmpty()) { + return; + } + SWItem swItem = new SWItem(Material.TNT, BauSystem.MESSAGE.parse("TRACE_GUI_ITEM", player, record.size())); + recordList.add(new SWListInv.SWListEntry<>(swItem, record)); + }); + SWListInv recordSWListInv = new SWListInv<>(player, BauSystem.MESSAGE.parse("TRACE_GUI_TITLE", player), false, recordList, (clickType, record) -> { + openRecordGui(player, record); + }); + recordSWListInv.setItem(48, new SWItem(Material.BUCKET, BauSystem.MESSAGE.parse("TRACE_GUI_CLEAR", player), clickType -> { + StoredRecords.clear(); + player.getOpenInventory().close(); + })); + recordSWListInv.setItem(50, new SWItem(Material.GLASS, "§e" + BauSystem.MESSAGE.parse("TRACE_SHOW_GUI_TITLE", player), clickType -> { + TraceShowGui.openGui(player); + })); + recordSWListInv.open(); + } + + public static void openRecordGui(Player player, Record record) { + List> recordList = new ArrayList<>(); + record.getTnt().forEach(tntRecord -> { + SWItem swItem = new SWItem(Material.TNT_MINECART, BauSystem.MESSAGE.parse("TRACE_GUI_RECORD_ITEM", player, tntRecord.getPositions().size())); + recordList.add(new SWListInv.SWListEntry<>(swItem, tntRecord)); + }); + SWListInv tntRecordSWListInv = new SWListInv<>(player, BauSystem.MESSAGE.parse("TRACE_GUI_TITLE", player), false, recordList, (clickType, tntRecord) -> { + openTntGui(player, record, tntRecord); + }); + tntRecordSWListInv.setItem(48, new SWItem(Material.BUCKET, BauSystem.MESSAGE.parse("TRACE_GUI_RECORD_CLEAR", player), clickType -> { + StoredRecords.getRecords().remove(record); + TraceShowManager.reshow(); + openGui(player); + })); + tntRecordSWListInv.setItem(49, new SWItem(Material.ARROW, BauSystem.MESSAGE.parse("TRACE_GUI_ITEM_BACK", player), clickType -> { + openGui(player); + })); + // 48, 51 + tntRecordSWListInv.open(); + } + + public static void openTntGui(Player player, Record record, Record.TNTRecord tntRecord) { + List> positionList = new ArrayList<>(); + tntRecord.getPositions().forEach(tntPosition -> { + SWItem swItem = new SWItem(Material.PAPER, BauSystem.MESSAGE.parse("TRACE_GUI_POSITION_ITEM", player)); + swItem.setLore(Arrays.asList( + BauSystem.MESSAGE.parse("TRACE_GUI_POSITION_X", player, tntPosition.getLocation().getX()), + BauSystem.MESSAGE.parse("TRACE_GUI_POSITION_Y", player, tntPosition.getLocation().getY()), + BauSystem.MESSAGE.parse("TRACE_GUI_POSITION_Z", player, tntPosition.getLocation().getZ()), + BauSystem.MESSAGE.parse("TRACE_GUI_POSITION_EXPLODED", player, tntPosition.isExploded()))); + positionList.add(new SWListInv.SWListEntry<>(swItem, tntPosition)); + }); + SWListInv tntPositionSWListInv = new SWListInv<>(player, BauSystem.MESSAGE.parse("TRACE_GUI_TITLE", player), false, positionList, (clickType, tntPosition) -> { + }); + tntPositionSWListInv.setItem(49, new SWItem(Material.ARROW, BauSystem.MESSAGE.parse("TRACE_GUI_ITEM_BACK", player), clickType -> { + openRecordGui(player, record); + })); + tntPositionSWListInv.open(); + } +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/show/Record.java b/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/show/Record.java index 63f39cfa..ae580283 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/show/Record.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/show/Record.java @@ -22,6 +22,7 @@ package de.steamwar.bausystem.features.tracer.show; import de.steamwar.bausystem.features.tpslimit.TPSUtils; import de.steamwar.bausystem.features.tracer.TNTPosition; import de.steamwar.bausystem.shared.ShowMode; +import lombok.Getter; import org.bukkit.entity.TNTPrimed; import java.util.ArrayList; @@ -30,6 +31,8 @@ import java.util.List; public class Record { private final long startTime; + + @Getter private final List tnt = new ArrayList<>(); public int size() { @@ -62,6 +65,8 @@ public class Record { } public static class TNTRecord { + + @Getter private final List positions = new ArrayList<>(41); public void showAll(ShowMode mode) { @@ -88,9 +93,5 @@ public class Record { public void explode(TNTPrimed tntPrimed) { add(tntPrimed, true); } - - public List getPositions() { - return positions; - } } } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/show/StoredRecords.java b/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/show/StoredRecords.java index 09cd96d8..8fe8fb08 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/show/StoredRecords.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/show/StoredRecords.java @@ -22,12 +22,14 @@ package de.steamwar.bausystem.features.tracer.show; import de.steamwar.bausystem.features.tracer.TNTPosition; import de.steamwar.bausystem.features.tracer.record.RecordStateMachine; import de.steamwar.bausystem.shared.ShowMode; +import lombok.Getter; import java.util.ArrayList; import java.util.List; public class StoredRecords { + @Getter private static final List records = new ArrayList<>(); public static void add(Record record) { diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/show/TraceShowManager.java b/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/show/TraceShowManager.java index fca38c75..3f93a0cb 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/show/TraceShowManager.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/show/TraceShowManager.java @@ -31,6 +31,11 @@ public class TraceShowManager implements Listener { traceShowMode.hide(); } + public static void reshow() { + Map> current = new HashMap<>(showModes); + current.forEach(TraceShowManager::show); + } + /* Only to be called by record */ static void show(TNTPosition tnt) { for (ShowMode mode : showModes.values()) diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/show/mode/TraceEntityShowMode.java b/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/show/mode/TraceEntityShowMode.java index 5b73c865..6e7801ac 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/show/mode/TraceEntityShowMode.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/show/mode/TraceEntityShowMode.java @@ -125,5 +125,4 @@ public class TraceEntityShowMode implements ShowMode { updateEntityMap.forEach((roundedPosition, abstractTraceEntity) -> abstractTraceEntity.hide(player, true)); updateEntityMap.clear(); } - } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/util/MaterialCommand.java b/BauSystem_Main/src/de/steamwar/bausystem/features/util/MaterialCommand.java index 152a65ca..8b466194 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/util/MaterialCommand.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/util/MaterialCommand.java @@ -30,6 +30,8 @@ import de.steamwar.inventory.SWListInv; import lombok.Getter; import lombok.Setter; import org.bukkit.Material; +import org.bukkit.block.data.BlockData; +import org.bukkit.block.data.Waterlogged; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; @@ -40,6 +42,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.regex.Pattern; @Linked(LinkageType.COMMAND) @Linked(LinkageType.LISTENER) @@ -70,24 +73,31 @@ public class MaterialCommand extends SWCommand implements Listener { private String name; private double blastResistance; + private double hardness; private boolean transparent; private boolean solid; private boolean gravity; private boolean occluding; private boolean interacteable; private boolean flammable; + private boolean burnable; + private boolean waterloggable; public MaterialData(Material material) { this.originalMaterial = material; name = material.name(); blastResistance = material.getBlastResistance(); + hardness = material.getHardness(); transparent = material.isTransparent(); solid = material.isSolid(); gravity = material.hasGravity(); occluding = material.isOccluding(); interacteable = material.isInteractable(); flammable = material.isFlammable(); + burnable = material.isBurnable(); + BlockData blockData = material.createBlockData(); + waterloggable = blockData instanceof Waterlogged; if (material.isItem() && material != Material.AIR) { this.material = material; @@ -100,6 +110,7 @@ public class MaterialCommand extends SWCommand implements Listener { List lore = new ArrayList<>(); lore.add(BauSystem.MESSAGE.parse("MATERIAL_BLAST-RESISTANCE", p, blastResistance)); lore.add(BauSystem.MESSAGE.parse(blastResistance > 9 ? "MATERIAL_TNT_UNBREAKABLE" : "MATERIAL_TNT_BREAKABLE", p)); + lore.add(BauSystem.MESSAGE.parse("MATERIAL_HARDNESS", p, hardness)); if (transparent) { lore.add(BauSystem.MESSAGE.parse("MATERIAL_TRANSPARENT", p)); } @@ -118,7 +129,14 @@ public class MaterialCommand extends SWCommand implements Listener { if (flammable) { lore.add(BauSystem.MESSAGE.parse("MATERIAL_FLAMMABLE", p)); } - return new SWListInv.SWListEntry<>(new SWItem(material, "§e" + name, lore, false, clickType -> {}), originalMaterial); + if (burnable) { + lore.add(BauSystem.MESSAGE.parse("MATERIAL_BURNABLE", p)); + } + if (waterloggable) { + lore.add(BauSystem.MESSAGE.parse("MATERIAL_WATERLOGGABLE", p)); + } + return new SWListInv.SWListEntry<>(new SWItem(material, "§e" + name, lore, false, clickType -> { + }), originalMaterial); } public boolean is(Search search) { @@ -141,6 +159,12 @@ public class MaterialCommand extends SWCommand implements Listener { if (search.flammable) { result &= flammable; } + if (search.burnable) { + result &= burnable; + } + if (search.waterloggable) { + result &= waterloggable; + } if (!result) { return false; } @@ -150,10 +174,7 @@ public class MaterialCommand extends SWCommand implements Listener { if (search.name.isEmpty()) { return true; } - if (!name.toLowerCase().contains(search.name.toLowerCase())) { - return false; - } - return true; + return Pattern.compile(".*" + search.name.toLowerCase().replace(' ', '.') + ".*").asPredicate().test(name.toLowerCase()); } } @@ -166,6 +187,8 @@ public class MaterialCommand extends SWCommand implements Listener { private boolean occluding = false; private boolean interacteable = false; private boolean flammable = false; + private boolean burnable = false; + private boolean waterloggable = false; private double blastResistanceMin = 0; private double blastResistanceMax = 5000000; @@ -180,7 +203,8 @@ public class MaterialCommand extends SWCommand implements Listener { swListEntries.add(data.toSWItem(p)); } }); - SWListInv materialSWListInv = new SWListInv<>(p, BauSystem.MESSAGE.parse("MATERIAL_INV_NAME", p, swListEntries.size(), materialData.size()), false, swListEntries, (clickType, material) -> {}); + SWListInv materialSWListInv = new SWListInv<>(p, BauSystem.MESSAGE.parse("MATERIAL_INV_NAME", p, swListEntries.size(), materialData.size()), false, swListEntries, (clickType, material) -> { + }); materialSWListInv.setItem(49, new SWItem(Material.NAME_TAG, BauSystem.MESSAGE.parse("MATERIAL_SEARCH", p), clickType -> { searchGUI(p); })); @@ -225,14 +249,23 @@ public class MaterialCommand extends SWCommand implements Listener { search.flammable = !search.flammable; searchGUI(p); })); - swInventory.setItem(28, new SWItem(Material.FIRE_CHARGE, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_BLASTRESISTANCE_MIN", p) + BauSystem.MESSAGE.parse("MATERIAL_SEARCH_VALUE", p, search.blastResistanceMin), clickType -> { + swInventory.setItem(25, new SWItem(Material.LAVA_BUCKET, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_BURNABLE", p) + BauSystem.MESSAGE.parse("MATERIAL_SEARCH_VALUE", p, search.burnable), clickType -> { + search.burnable = !search.burnable; + searchGUI(p); + })); + swInventory.setItem(28, new SWItem(Material.WATER_BUCKET, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_WATERLOGGABLE", p) + BauSystem.MESSAGE.parse("MATERIAL_SEARCH_VALUE", p, search.waterloggable), clickType -> { + search.waterloggable = !search.waterloggable; + searchGUI(p); + })); + swInventory.setItem(30, new SWItem(Material.FIRE_CHARGE, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_BLASTRESISTANCE_MIN", p) + BauSystem.MESSAGE.parse("MATERIAL_SEARCH_VALUE", p, search.blastResistanceMin), clickType -> { SWAnvilInv swAnvilInv = new SWAnvilInv(p, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_BLASTRESISTANCE", p), search.blastResistanceMin + ""); swAnvilInv.setCallback(s -> { try { search.blastResistanceMin = Double.parseDouble(s); if (search.blastResistanceMin < 0) search.blastResistanceMin = 0; if (search.blastResistanceMin > 5000000) search.blastResistanceMin = 5000000; - if (search.blastResistanceMin > search.blastResistanceMax) search.blastResistanceMin = search.blastResistanceMax; + if (search.blastResistanceMin > search.blastResistanceMax) + search.blastResistanceMin = search.blastResistanceMax; } catch (NumberFormatException e) { // Ignored } @@ -240,14 +273,15 @@ public class MaterialCommand extends SWCommand implements Listener { }); swAnvilInv.open(); })); - swInventory.setItem(29, new SWItem(Material.TNT, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_BLASTRESISTANCE_MAX", p) + BauSystem.MESSAGE.parse("MATERIAL_SEARCH_VALUE", p, search.blastResistanceMax), clickType -> { + swInventory.setItem(31, new SWItem(Material.TNT, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_BLASTRESISTANCE_MAX", p) + BauSystem.MESSAGE.parse("MATERIAL_SEARCH_VALUE", p, search.blastResistanceMax), clickType -> { SWAnvilInv swAnvilInv = new SWAnvilInv(p, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_BLASTRESISTANCE", p), search.blastResistanceMax + ""); swAnvilInv.setCallback(s -> { try { search.blastResistanceMax = Double.parseDouble(s); if (search.blastResistanceMax > 5000000) search.blastResistanceMax = 5000000; if (search.blastResistanceMax < 0) search.blastResistanceMax = 0; - if (search.blastResistanceMax < search.blastResistanceMin) search.blastResistanceMax = search.blastResistanceMin; + if (search.blastResistanceMax < search.blastResistanceMin) + search.blastResistanceMax = search.blastResistanceMin; } catch (NumberFormatException e) { // Ignored } @@ -255,7 +289,7 @@ public class MaterialCommand extends SWCommand implements Listener { }); swAnvilInv.open(); })); - swInventory.setItem(31, new SWItem(Material.NETHER_BRICK, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_BLASTRESISTANCE_EXACT", p) + BauSystem.MESSAGE.parse("MATERIAL_SEARCH_VALUE", p, search.blastResistanceMin + "-" + search.blastResistanceMax), clickType -> { + swInventory.setItem(32, new SWItem(Material.NETHER_BRICK, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_BLASTRESISTANCE_EXACT", p) + BauSystem.MESSAGE.parse("MATERIAL_SEARCH_VALUE", p, search.blastResistanceMin + "-" + search.blastResistanceMax), clickType -> { SWAnvilInv swAnvilInv = new SWAnvilInv(p, BauSystem.MESSAGE.parse("MATERIAL_SEARCH_BLASTRESISTANCE", p), search.blastResistanceMax + ""); swAnvilInv.setCallback(s -> { try { diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/util/SelectCommand.java b/BauSystem_Main/src/de/steamwar/bausystem/features/util/SelectCommand.java index 0af7429f..0adf7316 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/util/SelectCommand.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/util/SelectCommand.java @@ -39,7 +39,7 @@ public class SelectCommand extends SWCommand { } if (!region.hasType(regionType)) { - p.sendMessage(BauSystem.PREFIX + "§cDiese Region hat keinen " + regionType.getChatValue()); + p.sendMessage(BauSystem.PREFIX + "§cDiese Region hat keinen " + BauSystem.MESSAGE.parse(regionType.getChatValue(), p)); return; } @@ -60,7 +60,7 @@ public class SelectCommand extends SWCommand { } if (!region.hasType(regionType)) { - p.sendMessage(BauSystem.PREFIX + "§cDiese Region hat keinen " + regionType.getChatValue()); + p.sendMessage(BauSystem.PREFIX + "§cDiese Region hat keinen " + BauSystem.MESSAGE.parse(regionType.getChatValue(), p)); return; } if (regionExtensionType == RegionExtensionType.EXTENSION && !region.hasExtensionType(regionType)) { diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/util/StructureVoidCommand.java b/BauSystem_Main/src/de/steamwar/bausystem/features/util/StructureVoidCommand.java new file mode 100644 index 00000000..a2f435c2 --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/util/StructureVoidCommand.java @@ -0,0 +1,48 @@ +/* + * 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.bausystem.features.util; + +import de.steamwar.bausystem.BauSystem; +import de.steamwar.bausystem.SWUtils; +import de.steamwar.bausystem.linkage.LinkageType; +import de.steamwar.bausystem.linkage.Linked; +import de.steamwar.command.SWCommand; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +@Linked(LinkageType.COMMAND) +public class StructureVoidCommand extends SWCommand { + + public StructureVoidCommand() { + super("structureVoid", "structure", "void", "structurevoid"); + } + + @Register(help = true) + public void genericHelp(Player p, String... args) { + BauSystem.MESSAGE.send("COMMAND_HELP_HEAD", p, "structureVoid"); + BauSystem.MESSAGE.send("STRUCTURE-VOID_COMMAND_HELP", p); + } + + @Register + public void genericCommand(Player p) { + SWUtils.giveItemToPlayer(p, new ItemStack(Material.STRUCTURE_VOID, 1)); + } +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/world/AutoShutdownListener.java b/BauSystem_Main/src/de/steamwar/bausystem/features/world/AutoShutdownListener.java index be994a49..edba5698 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/world/AutoShutdownListener.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/world/AutoShutdownListener.java @@ -59,6 +59,10 @@ public class AutoShutdownListener implements Listener { autoShutdown.cancel(); } TPSLimitUtils.setTPS(20.0); + if (true) { + Bukkit.shutdown(); + return; + } autoShutdown = Bukkit.getScheduler().runTaskTimer(BauSystem.getInstance(), new Runnable() { int count = 0; diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/world/BauScoreboard.java b/BauSystem_Main/src/de/steamwar/bausystem/features/world/BauScoreboard.java index 7ba3545a..17865922 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/world/BauScoreboard.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/world/BauScoreboard.java @@ -40,7 +40,13 @@ public class BauScoreboard implements Listener { @Override public String getTitle() { - return "§eSteam§8War"; + // ■ + Region region = Region.getRegion(player.getLocation()); + if (GlobalRegion.getInstance() == region) { + return "§eSteam§8War"; + } + String colorCode = BauSystem.MESSAGE.parse(region.get(Flag.COLOR).getChatValue(), player).substring(0, 2); + return colorCode + "■ §eSteam§8War " + colorCode + "■"; } }); } @@ -68,16 +74,16 @@ public class BauScoreboard implements Listener { } strings.add("§3"); - strings.add(colorCode + BauSystem.MESSAGE.parse("SCOREBOARD_TRACE", p) + "§8: " + BauSystem.MESSAGE.parse(RecordStateMachine.getRecordStatus().getName(), p)); + StringBuilder st = new StringBuilder(); + st.append(colorCode).append(BauSystem.MESSAGE.parse("SCOREBOARD_TRACE", p)).append("§8: ").append(BauSystem.MESSAGE.parse(RecordStateMachine.getRecordStatus().getName(), p)); + if (RecordStateMachine.getRecordStatus().isTracing()) { + st.append(" §8| §e").append(traceTicks()).append(" §7").append(BauSystem.MESSAGE.parse("SCOREBOARD_TRACE_TICKS", p)); + } + strings.add(st.toString()); + Loader loader = Loader.getLoader(p); strings.add(colorCode + BauSystem.MESSAGE.parse("SCOREBOARD_LOADER", p) + "§8: " + BauSystem.MESSAGE.parse(loader != null ? loader.getStage().getChatValue() : "LOADER_OFF", p)); - if (RecordStateMachine.getRecordStatus().isTracing()) { - strings.add("§4"); - strings.add(colorCode + BauSystem.MESSAGE.parse("SCOREBOARD_TRACE_TICKS", p) + "§8: §7" + traceTicks()); - strings.add(colorCode + BauSystem.MESSAGE.parse("SCOREBOARD_TRACE_TNT-COUNT", p) + "§8: §7" + RecordStateMachine.size()); - } - strings.add("§5"); strings.add(colorCode + BauSystem.MESSAGE.parse("SCOREBOARD_TPS", p) + "§8 " + tpsColor() + TPSWarpUtils.getTps(TPSWatcher.TPSType.ONE_SECOND) + tpsLimit()); diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/world/SignEdit.java b/BauSystem_Main/src/de/steamwar/bausystem/features/world/SignEdit.java index dc15ef2a..5d525f0c 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/world/SignEdit.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/world/SignEdit.java @@ -19,17 +19,15 @@ package de.steamwar.bausystem.features.world; -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.wrappers.BlockPosition; +import com.comphenix.tinyprotocol.Reflection; import de.steamwar.bausystem.BauSystem; import de.steamwar.bausystem.linkage.LinkageType; import de.steamwar.bausystem.linkage.Linked; +import de.steamwar.bausystem.utils.ProtocolAPI; +import net.minecraft.server.v1_15_R1.BlockPosition; import org.bukkit.Bukkit; import org.bukkit.ChatColor; +import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.block.Sign; @@ -38,13 +36,18 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.block.Action; import org.bukkit.event.player.PlayerInteractEvent; - -import java.lang.reflect.InvocationTargetException; -import java.util.logging.Level; +import org.bukkit.util.Vector; @Linked(LinkageType.LISTENER) public class SignEdit implements Listener { + public static final Class openSign = Reflection.getClass("{nms}.PacketPlayOutOpenSignEditor"); + private static final Reflection.FieldAccessor blockPositionFieldAccessor = Reflection.getField(openSign, net.minecraft.server.v1_15_R1.BlockPosition.class, 0); + + public static final Class updateSign = Reflection.getClass("{nms}.PacketPlayInUpdateSign"); + private static final Reflection.FieldAccessor getBlockPositionFieldAccessor = Reflection.getField(updateSign, BlockPosition.class, 0); + private static final Reflection.FieldAccessor stringFieldAccessor = Reflection.getField(updateSign, String[].class, 0); + @EventHandler public void editSign(PlayerInteractEvent event) { if (event.getAction() != Action.RIGHT_CLICK_BLOCK || @@ -62,38 +65,29 @@ public class SignEdit implements Listener { } sign.update(); - PacketContainer signOpen = ProtocolLibrary.getProtocolManager().createPacket(PacketType.Play.Server.OPEN_SIGN_EDITOR); - signOpen.getBlockPositionModifier().write(0, new BlockPosition(event.getClickedBlock().getLocation().toVector())); - try { - ProtocolLibrary.getProtocolManager().sendServerPacket(player, signOpen); - } catch (InvocationTargetException e) { - Bukkit.getLogger().log(Level.SEVERE, "Invocation target exception", e); - } + Object openSignObject = Reflection.newInstance(openSign); + Vector vector = event.getClickedBlock().getLocation().toVector(); + blockPositionFieldAccessor.set(openSignObject, new BlockPosition(vector.getBlockX(), vector.getBlockY(), vector.getBlockZ())); + ProtocolAPI.tinyProtocol.sendPacket(player, openSignObject); + } - ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(BauSystem.getInstance(), PacketType.Play.Client.UPDATE_SIGN) { - @Override - public void onPacketReceiving(PacketEvent event) { - if (!event.getPlayer().equals(player)) + { + ProtocolAPI.setIncomingHandler(updateSign, (player, o) -> { + Bukkit.getScheduler().runTask(BauSystem.getInstance(), () -> { + BlockPosition position = getBlockPositionFieldAccessor.get(o); + String[] lines = stringFieldAccessor.get(o); + + Block signLoc = new Location(player.getWorld(), position.getX(), position.getY(), position.getZ()).getBlock(); + if (!signLoc.getType().name().contains("SIGN")) return; - event.setCancelled(true); - Bukkit.getScheduler().runTask(BauSystem.getInstance(), () -> { - PacketContainer packetContainer = event.getPacket(); - BlockPosition position = packetContainer.getBlockPositionModifier().read(0); - String[] lines = packetContainer.getStringArrays().read(0); - Block signLoc = position.toLocation(player.getWorld()).getBlock(); - if (!signLoc.getType().name().contains("SIGN")) - return; - - org.bukkit.block.Sign sign = ((Sign) signLoc.getState()); - for (int i = 0; i < lines.length; i++) { - sign.setLine(i, ChatColor.translateAlternateColorCodes('&', lines[i])); - } - sign.update(); - - ProtocolLibrary.getProtocolManager().removePacketListener(this); - }); - } + org.bukkit.block.Sign sign = ((Sign) signLoc.getState()); + for (int i = 0; i < lines.length; i++) { + sign.setLine(i, ChatColor.translateAlternateColorCodes('&', lines[i])); + } + sign.update(); + }); + return o; }); } } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/world/SignListener.java b/BauSystem_Main/src/de/steamwar/bausystem/features/world/SignListener.java new file mode 100644 index 00000000..36058c83 --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/world/SignListener.java @@ -0,0 +1,42 @@ +/* + * 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.bausystem.features.world; + +import de.steamwar.bausystem.linkage.LinkageType; +import de.steamwar.bausystem.linkage.Linked; +import org.bukkit.ChatColor; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.SignChangeEvent; + +@Linked(LinkageType.LISTENER) +public class SignListener implements Listener { + + @EventHandler + public void onSignChange(SignChangeEvent event) { + for (int i = 0; i <= 3; ++i) { + String line = event.getLine(i); + if (line == null) + continue; + line = ChatColor.translateAlternateColorCodes('&', line); + event.setLine(i, line); + } + } +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/linkage/LinkageType.java b/BauSystem_Main/src/de/steamwar/bausystem/linkage/LinkageType.java index c6684b35..30c1d5b5 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/linkage/LinkageType.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/linkage/LinkageType.java @@ -23,6 +23,8 @@ import de.steamwar.bausystem.BauSystem; import de.steamwar.bausystem.configplayer.ConfigConverter; import de.steamwar.bausystem.configplayer.Config; import de.steamwar.bausystem.features.gui.BauGUI; +import de.steamwar.bausystem.features.slaves.panzern.Panzern; +import de.steamwar.bausystem.features.slaves.panzern.PanzernAlgorithm; import de.steamwar.bausystem.features.script.ScriptExecutor; import de.steamwar.bausystem.features.script.SpecialCommand; import de.steamwar.bausystem.linkage.specific.BauGuiItem; @@ -45,8 +47,8 @@ public enum LinkageType { // NORMAL COMMAND(-1, false, SWCommand.class::isAssignableFrom), - ENABLE_LINK(0, false, Enable.class::isAssignableFrom, o -> ((Enable) o).enable()), - DISABLE_LINK(0, true, Disable.class::isAssignableFrom, o -> ((Disable) o).disable()), + ENABLE_LINK(0, false, Enable.class::isInstance, o -> ((Enable) o).enable()), + DISABLE_LINK(0, true, Disable.class::isInstance, o -> ((Disable) o).disable()), PLAIN(1, false, clazz -> true), LISTENER(2, false, Listener.class::isAssignableFrom, o -> Bukkit.getPluginManager().registerEvents((Listener) o, BauSystem.getInstance())), UNLINK_LISTENER(2, true, Listener.class::isAssignableFrom, o -> HandlerList.unregisterAll((Listener) o)), @@ -55,7 +57,8 @@ public enum LinkageType { BAU_GUI_ITEM(3, false, BauGuiItem.class::isAssignableFrom, o -> BauGUI.addItem((BauGuiItem) o)), SCRIPT_COMMAND(4, false, SpecialCommand.class::isAssignableFrom, o -> ScriptExecutor.SPECIAL_COMMANDS.add((SpecialCommand) o)), CONFIG_CONVERTER(5, false, ConfigConverter.class::isAssignableFrom, o -> Config.addConfigConverter((ConfigConverter) o)), - SCOREBOARD(6, false, ScoreboardItem.class::isAssignableFrom, o -> {}); + SCOREBOARD(6, false, ScoreboardItem.class::isAssignableFrom, o -> {}), + PANZERN(7, false, PanzernAlgorithm.class::isAssignableFrom, o -> Panzern.add((PanzernAlgorithm) o)); private final int order; diff --git a/BauSystem_Main/src/de/steamwar/bausystem/linkage/LinkageUtils.java b/BauSystem_Main/src/de/steamwar/bausystem/linkage/LinkageUtils.java index 03b0ffc0..429d96cc 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/linkage/LinkageUtils.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/linkage/LinkageUtils.java @@ -31,6 +31,7 @@ import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.util.*; import java.util.logging.Level; +import java.util.stream.Collectors; @UtilityClass public class LinkageUtils { @@ -90,18 +91,7 @@ public class LinkageUtils { return; } - List linkageTypeList = new ArrayList<>(); - for (Linked linked : linkages) { - if (linked == null) { - continue; - } - LinkageType linkageType = linked.value(); - if (linkageType.getLinkagePredicate().test(clazz)) { - linkageTypeList.add(linked.value()); - } - } - - linkageTypeList.removeIf(linkageType -> linkageType.isUnlink() != unlink); + List linkageTypeList = Arrays.stream(linkages).filter(Objects::nonNull).map(Linked::value).filter(linkageType -> linkageType.getLinkagePredicate().test(clazz)).filter(linkageType -> linkageType.isUnlink() == unlink).collect(Collectors.toList()); if (linkageTypeList.isEmpty()) { return; } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/region/BackupScheduler.java b/BauSystem_Main/src/de/steamwar/bausystem/region/BackupScheduler.java index ffb6de3a..e9b7ac8f 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/region/BackupScheduler.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/region/BackupScheduler.java @@ -20,6 +20,7 @@ package de.steamwar.bausystem.region; import de.steamwar.bausystem.BauSystem; +import de.steamwar.bausystem.linkage.Disable; import de.steamwar.bausystem.linkage.Enable; import de.steamwar.bausystem.linkage.LinkageType; import de.steamwar.bausystem.linkage.Linked; @@ -29,7 +30,10 @@ import org.bukkit.scheduler.BukkitRunnable; @Linked(LinkageType.ENABLE_LINK) -public class BackupScheduler implements Enable { +@Linked(LinkageType.DISABLE_LINK) +public class BackupScheduler implements Enable, Disable { + + private static final long PERIOD = 20 * 60 * 30; @Override public void enable() { @@ -39,7 +43,15 @@ public class BackupScheduler implements Enable { final Iterator regions = Region.getREGION_MAP().values().stream().filter(region -> region.get(Tag.CHANGED)).iterator(); BackupScheduler.this.doBackup(regions); } - }.runTaskTimer(BauSystem.getInstance(), 20, 20*60*30); + }.runTaskTimer(BauSystem.getInstance(), PERIOD, PERIOD); + } + + @Override + public void disable() { + Region.getREGION_MAP().values().stream().filter(region -> region.get(Tag.CHANGED)).iterator().forEachRemaining(region -> { + region.backup(); + region.remove(Tag.CHANGED); + }); } public void doBackup(final Iterator regionIterator) { @@ -56,6 +68,6 @@ public class BackupScheduler implements Enable { region.remove(Tag.CHANGED); } } - }.runTaskTimer(BauSystem.getInstance(), 0, 20); + }.runTaskTimer(BauSystem.getInstance(), 0, 100); } } \ No newline at end of file diff --git a/BauSystem_Main/src/de/steamwar/bausystem/region/Prototype.java b/BauSystem_Main/src/de/steamwar/bausystem/region/Prototype.java index 1c1815ae..0fa57349 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/region/Prototype.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/region/Prototype.java @@ -89,7 +89,7 @@ public class Prototype { if (PROTOTYPE_MAP.containsKey(name)) { Region.getRegion(PROTOTYPE_MAP.remove(name)).forEach(region -> { - region.setPrototype(this); + region._setPrototype(this); }); } PROTOTYPE_MAP.put(name, this); @@ -117,6 +117,11 @@ public class Prototype { private boolean extensionRegistered; + private final boolean hasCopyPoint; + private final int copyOffsetX; + private final int copyOffsetY; + private final int copyOffsetZ; + private SubPrototype(YAPIONObject yapionObject) { offsetX = yapionObject.getPlainValueOrDefault("offsetX", 0); offsetY = yapionObject.getPlainValueOrDefault("offsetY", 0); @@ -157,6 +162,11 @@ public class Prototype { } extensionRegistered = extensionNegativeX != 0 || extensionPositiveX != 0 || extensionNegativeY != 0 || extensionPositiveY != 0 || extensionNegativeZ != 0 || extensionPositiveZ != 0; + + copyOffsetX = yapionObject.getPlainValueOrDefault("copyOffsetX", 0); + copyOffsetY = yapionObject.getPlainValueOrDefault("copyOffsetY", 0); + copyOffsetZ = yapionObject.getPlainValueOrDefault("copyOffsetZ", 0); + hasCopyPoint = yapionObject.containsKey("copyOffsetX") || yapionObject.containsKey("copyOffsetY") || yapionObject.containsKey("copyOffsetZ"); } } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/region/Region.java b/BauSystem_Main/src/de/steamwar/bausystem/region/Region.java index c88516de..c8cc81ba 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/region/Region.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/region/Region.java @@ -20,6 +20,7 @@ package de.steamwar.bausystem.region; import com.sk89q.worldedit.EditSession; +import com.sk89q.worldedit.extent.clipboard.Clipboard; import de.steamwar.bausystem.region.flags.Flag; import de.steamwar.bausystem.region.flags.flagvalues.ColorMode; import de.steamwar.bausystem.region.flags.flagvalues.TNTMode; @@ -98,6 +99,7 @@ public class Region { private int waterLevel; private Point copyPoint; // Nullable + private Point testBlockPoint; // Nullable private String linkedRegionName = null; // Nullable private Region linkedRegion = null; // Nullable @@ -155,6 +157,12 @@ public class Region { this.minPointTestblockExtension = this.minPointTestblock.subtract(prototype.getTestblock().getExtensionNegativeX(), prototype.getTestblock().getExtensionNegativeY(), prototype.getTestblock().getExtensionNegativeZ()); this.maxPointTestblockExtension = this.maxPointTestblock.add(prototype.getTestblock().getExtensionPositiveX(), prototype.getTestblock().getExtensionPositiveY(), prototype.getTestblock().getExtensionPositiveZ()); + + if (prototype.getTestblock().getCopyOffsetX() != 0 || prototype.getTestblock().getCopyOffsetY() != 0 || prototype.getTestblock().getCopyOffsetZ() != 0) { + this.testBlockPoint = this.minPointTestblock.add(prototype.getTestblock().getCopyOffsetX(), prototype.getTestblock().getCopyOffsetY(), prototype.getTestblock().getCopyOffsetZ()); + } else { + this.testBlockPoint = this.minPointTestblock.add(prototype.getTestblock().getSizeX() / 2, 0, -1); + } } if (prototype.getBuild() != null) { @@ -163,6 +171,16 @@ public class Region { this.minPointBuildExtension = this.minPointBuild.subtract(prototype.getBuild().getExtensionNegativeX(), prototype.getBuild().getExtensionNegativeY(), prototype.getBuild().getExtensionNegativeZ()); this.maxPointBuildExtension = this.maxPointBuild.add(prototype.getBuild().getExtensionPositiveX(), prototype.getBuild().getExtensionPositiveY(), prototype.getBuild().getExtensionPositiveZ()); + + if (!prototype.getBuild().isHasCopyPoint() && (prototype.getCopyPointOffsetX() != 0 || prototype.getCopyPointOffsetY() != 0 || prototype.getCopyPointOffsetZ() != 0)) { + this.copyPoint = minPoint.add(prototype.getCopyPointOffsetX(), prototype.getCopyPointOffsetY(), prototype.getCopyPointOffsetZ()); + } else if (prototype.getBuild().getCopyOffsetX() != 0 || prototype.getBuild().getCopyOffsetY() != 0 || prototype.getBuild().getCopyOffsetZ() != 0) { + this.copyPoint = this.minPointBuild.add(prototype.getBuild().getCopyOffsetX(), prototype.getBuild().getCopyOffsetY(), prototype.getBuild().getCopyOffsetZ()); + } else { + this.copyPoint = this.minPointBuild.add(prototype.getBuild().getSizeX() / 2, 0, prototype.getBuild().getSizeZ()); + } + } else if (prototype.getCopyPointOffsetX() != 0 || prototype.getCopyPointOffsetY() != 0 || prototype.getCopyPointOffsetZ() != 0) { + this.copyPoint = minPoint.add(prototype.getCopyPointOffsetX(), prototype.getCopyPointOffsetY(), prototype.getCopyPointOffsetZ()); } if (prototype.getFloorOffset() != 0) { @@ -176,8 +194,6 @@ public class Region { } else { waterLevel = 0; } - - copyPoint = this.minPoint.add(prototype.getCopyPointOffsetX(), prototype.getCopyPointOffsetY(), prototype.getCopyPointOffsetZ()); } public boolean inRegion(Location location, RegionType regionType, RegionExtensionType regionExtensionType) { @@ -270,6 +286,10 @@ public class Region { if (!prototypes.contains(prototype.getName()) && !prototypes.isEmpty()) { return false; } + return _setPrototype(prototype); + } + + boolean _setPrototype(@NonNull Prototype prototype) { generatePrototypeData(prototype, minPoint); RegionUtils.save(this); setLinkedRegion(region -> { @@ -392,6 +412,7 @@ public class Region { Point pastePoint; File tempFile = null; + Clipboard clipboard = null; switch (regionType) { case BUILD: pastePoint = minPointBuild.add(prototype.getBuild().getSizeX() / 2, 0, prototype.getBuild().getSizeZ() / 2); @@ -400,9 +421,19 @@ public class Region { } break; case TESTBLOCK: - pastePoint = minPointTestblock.add(prototype.getTestblock().getSizeX() / 2, 0, prototype.getTestblock().getSizeZ() / 2); + pastePoint = minPointTestblock.add(prototype.getTestblock().getSizeX() / 2, 0, 0); if (schematic == null) { tempFile = prototype.getTestblock().getSchematicFile(); + pastePoint = pastePoint.add(0, 0, prototype.getTestblock().getSizeZ() / 2); + } else { + clipboard = schematic.load(); + if (Math.abs(clipboard.getOrigin().getZ() - clipboard.getMinimumPoint().getZ()) < 2 || Math.abs(clipboard.getOrigin().getZ() - clipboard.getMinimumPoint().getZ()) > prototype.getTestblock().getSizeZ()) { + pastePoint = pastePoint.add(0, 0, prototype.getTestblock().getSizeZ() / 2); + } else if (clipboard.getDimensions().getZ() != prototype.getTestblock().getSizeZ()) { + pastePoint = pastePoint.add(0, 0, clipboard.getDimensions().getZ() / 2 - (clipboard.getOrigin().getZ() - clipboard.getMinimumPoint().getZ()) - 1); + } else { + pastePoint = pastePoint.add(0, 0, prototype.getTestblock().getSizeZ() / 2); + } } break; default: @@ -416,7 +447,7 @@ public class Region { EditSession editSession = null; if (schematic != null) { - editSession = paste(schematic.load(), pastePoint, pasteOptions); + editSession = paste(clipboard != null ? clipboard : schematic.load(), pastePoint, pasteOptions); } else { editSession = paste(tempFile, pastePoint, pasteOptions); } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/region/loader/PrototypeLoader.java b/BauSystem_Main/src/de/steamwar/bausystem/region/loader/PrototypeLoader.java index 6324fff8..ce92924c 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/region/loader/PrototypeLoader.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/region/loader/PrototypeLoader.java @@ -46,7 +46,7 @@ public class PrototypeLoader { throw new SecurityException(e.getMessage(), e); } - if (loaded != null && new YAPIONDiff(loaded, yapionObject).getDiffs().stream().anyMatch(diffBase -> !(diffBase instanceof DiffBase.DiffChange))) { + if (loaded != null && new YAPIONDiff(loaded, yapionObject).getDiffs().stream().anyMatch(diffBase -> (diffBase instanceof DiffBase.DiffDelete))) { throw new SecurityException("Version was not the specified version needed."); } loaded = yapionObject; diff --git a/BauSystem_Main/src/de/steamwar/bausystem/region/loader/RegionLoader.java b/BauSystem_Main/src/de/steamwar/bausystem/region/loader/RegionLoader.java index 2cce1ef0..ecd13afc 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/region/loader/RegionLoader.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/region/loader/RegionLoader.java @@ -27,7 +27,6 @@ import lombok.experimental.UtilityClass; import org.bukkit.Bukkit; import yapion.hierarchy.diff.DiffBase; import yapion.hierarchy.diff.YAPIONDiff; -import yapion.hierarchy.output.FileOutput; import yapion.hierarchy.types.YAPIONObject; import yapion.hierarchy.types.YAPIONType; import yapion.parser.YAPIONParser; diff --git a/BauSystem_Main/src/de/steamwar/bausystem/shared/ShowMode.java b/BauSystem_Main/src/de/steamwar/bausystem/shared/ShowMode.java index edc10243..a37daa40 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/shared/ShowMode.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/shared/ShowMode.java @@ -19,8 +19,6 @@ package de.steamwar.bausystem.shared; -import de.steamwar.bausystem.shared.Position; - public interface ShowMode { void show(T position); diff --git a/BauSystem_Main/src/de/steamwar/bausystem/utils/ProtocolAPI.java b/BauSystem_Main/src/de/steamwar/bausystem/utils/ProtocolAPI.java new file mode 100644 index 00000000..351a27fb --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/utils/ProtocolAPI.java @@ -0,0 +1,76 @@ +/* + * 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.bausystem.utils; + +import com.comphenix.tinyprotocol.TinyProtocol; +import de.steamwar.bausystem.BauSystem; +import io.netty.channel.Channel; +import lombok.experimental.UtilityClass; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +import java.util.HashMap; +import java.util.Map; +import java.util.function.BiFunction; + +@UtilityClass +public class ProtocolAPI { + + private static final Map, BiFunction> outgoingHandler = new HashMap<>(); + private static final Map, BiFunction> incomingHandler = new HashMap<>(); + + public static final TinyProtocol tinyProtocol = new TinyProtocol(BauSystem.getInstance()) { + @Override + public Object onPacketOutAsync(Player receiver, Channel channel, Object packet) { + BiFunction handler = outgoingHandler.get(packet.getClass()); + if (handler == null) + return packet; + return handler.apply(receiver, packet); + } + + @Override + public Object onPacketInAsync(Player sender, Channel channel, Object packet) { + BiFunction handler = incomingHandler.get(packet.getClass()); + if (handler == null) + return packet; + return handler.apply(sender, packet); + } + }; + + public static void setOutgoingHandler(Class packetClass, BiFunction handler) { + outgoingHandler.put(packetClass, handler); + } + + public static void removeOutgoingHandler(Class packetClass) { + outgoingHandler.remove(packetClass); + } + + public static void setIncomingHandler(Class packetClass, BiFunction handler) { + incomingHandler.put(packetClass, handler); + } + + public static void removeIncomingHandler(Class packetClass) { + incomingHandler.remove(packetClass); + } + + public static void broadcastPacket(Object packet) { + Bukkit.getOnlinePlayers().stream().map(tinyProtocol::getChannel).filter(tinyProtocol::hasInjected).forEach(channel -> tinyProtocol.sendPacket(channel, packet)); + } +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/worlddata/WorldData.java b/BauSystem_Main/src/de/steamwar/bausystem/worlddata/WorldData.java index 62f54e8f..def31d3a 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/worlddata/WorldData.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/worlddata/WorldData.java @@ -52,6 +52,10 @@ public class WorldData { return getWorldData().getYAPIONArrayOrSetDefault("warps", new YAPIONArray()); } + public YAPIONObject getSimulatorData() { + return getWorldData().getYAPIONObjectOrSetDefault("simulators", new YAPIONObject()); + } + private void read() { worldData = new YAPIONObject(); if (optionsFile.length() != 0) { @@ -61,6 +65,7 @@ public class WorldData { YAPIONObject yapionObject = new YAPIONObject(); yapionObject.add("regions", worldData); worldData = yapionObject; + write(); } } catch (IOException e) { // Ignored diff --git a/BauSystem_Main/src/plugin.yml b/BauSystem_Main/src/plugin.yml index 36a8d970..a75ce068 100644 --- a/BauSystem_Main/src/plugin.yml +++ b/BauSystem_Main/src/plugin.yml @@ -1,7 +1,7 @@ name: BauSystem authors: [Lixfel, YoyoNow, Chaoscaot, Zeanon] version: "2.0" -depend: [WorldEdit, SpigotCore, ProtocolLib] +depend: [WorldEdit, SpigotCore] load: POSTWORLD main: de.steamwar.bausystem.BauSystem api-version: "1.13" diff --git a/build.gradle b/build.gradle index 88904c51..0392b342 100644 --- a/build.gradle +++ b/build.gradle @@ -124,9 +124,9 @@ if (steamwarProperties.containsKey("hostname")) { doLast { await(shell("scp ${libs}/${jarName} ${hostname}:${uploadPath}/${server}/plugins")) - /*if (!answer("Start ${server} server?")) { + if (steamwarProperties.getOrDefault("directStart", "false") == "false" && !answer("Start ${server} server?")) { return - }*/ + } serverStart(server, serverStartFlags, hostname) } } diff --git a/steamwarci.yml b/steamwarci.yml new file mode 100644 index 00000000..2488bfa6 --- /dev/null +++ b/steamwarci.yml @@ -0,0 +1,8 @@ +build: + - "ln -s /home/gitea/lib" + - "cp ~/gradle.properties ." + - "chmod u+x build.gradle" + - "./gradlew buildProject" + +artifacts: + "/binarys/bausystem2.0.jar": "build/libs/bausystem2.0.jar" diff --git a/yapion/prototypes2.yapion b/yapion/prototypes2.yapion new file mode 100644 index 00000000..79b2965a --- /dev/null +++ b/yapion/prototypes2.yapion @@ -0,0 +1,82 @@ +{ + as{ + displayName(AirShip) + schematic(sections2/ASMinArena.schematicatic) + sizeX(95) + sizeY(220) + sizeZ(165) + testblock{ + offsetX(0) + offsetY(0) + offsetZ(100) + schematic(sections2/ASTestblock.schematic) + sizeX(95) + sizeY(45) + sizeZ(65) + } + } + mwg{ + displayName(MiniWarGear) + schematic(sections2/MWGArena.schematic) + sizeX(63) + sizeY(256) + sizeZ(120) + testblock{ + offsetX(13) + offsetY(44) + offsetZ(85) + schematic(sections2/MWGTestblock.schematic) + sizeX(37) + sizeY(26) + sizeZ(22) + } + } + wg{ + displayName(WarGear) + schematic(sections2/WGArena.schematic) + sizeX(133) + sizeY(255) + sizeZ(214) + testblock{ + offsetX(33) + offsetY(44) + offsetZ(128) + schematic(sections2/WGTestblock.schematic) + sizeX(67) + sizeY(41) + sizeZ(47) + } + } + ws{ + displayName(WarShip) + schematic(sections2/WSArena.schematic) + sizeX(253) + sizeY(256) + sizeZ(194) + testblock{ + offsetX(11) + offsetY(0) + offsetZ(11) + schematic(sections2/WSTestblock.schematic) + sizeX(230) + sizeY(57) + sizeZ(35) + } + } + ws_in{ + displayName(WarShip) + schematic(sections2/WSMinArena.schematic) + sizeX(253) + sizeY(256) + sizeZ(59) + testblock{ + offsetX(12) + offsetY(0) + offsetZ(147) + schematic(sections2/WSTestblock.schematic) + sizeX(230) + sizeY(57) + sizeZ(35) + } + } +} \ No newline at end of file diff --git a/yapion/prototypes4.yapion b/yapion/prototypes4.yapion index c675ab3c..7e93f3bb 100644 --- a/yapion/prototypes4.yapion +++ b/yapion/prototypes4.yapion @@ -5,9 +5,6 @@ sizeX(178) sizeY(119) sizeZ(221) - copyOffsetX(89) - copyOffsetY(45) - copyOffsetZ(85) floorOffset(45) testblock{ sizeX(67) @@ -41,9 +38,6 @@ sizeX(178) sizeY(119) sizeZ(221) - copyOffsetX(89) - copyOffsetY(45) - copyOffsetZ(85) floorOffset(45) testblock{ sizeX(67) @@ -77,9 +71,6 @@ sizeX(107) sizeY(94) sizeZ(141) - copyOffsetX(53) - copyOffsetY(45) - copyOffsetZ(45) floorOffset(45) testblock{ sizeX(37) @@ -113,9 +104,6 @@ sizeX(121) sizeY(64) sizeZ(177) - copyOffsetX(2) - copyOffsetY(11) - copyOffsetZ(38) testblock{ sizeX(115) sizeY(45) @@ -123,15 +111,21 @@ offsetX(3) offsetY(10) offsetZ(106) + copyOffsetX(-1) + copyOffsetY(1) + copyOffsetZ(32) schematic(sections4/ASTestblock.schem) } build{ sizeX(115) sizeY(45) sizeZ(65) - offsetX(6) + offsetX(3) offsetY(10) offsetZ(6) + copyOffsetX(-1) + copyOffsetY(1) + copyOffsetZ(32) } } ws{ diff --git a/yapion/regions2.yapion b/yapion/regions2.yapion new file mode 100644 index 00000000..a3c307f3 --- /dev/null +++ b/yapion/regions2.yapion @@ -0,0 +1,140 @@ +{ + as1{ + minX(33) + minY(33) + minZ(23) + prototype(as) + } + as2{ + minX(205) + minY(33) + minZ(23) + prototype(as) + } + as3{ + minX(369) + minY(33) + minZ(23) + prototype(as) + } + as4{ + minX(33) + minY(33) + minZ(339) + prototype(as) + } + as5{ + minX(205) + minY(33) + minZ(339) + prototype(as) + } + as6{ + minX(369) + minY(33) + minZ(339) + prototype(as) + } + mwg1{ + minX(-97) + minY(1) + minZ(-154) + prototype(mwg) + } + mwg2{ + minX(-177) + minY(1) + minZ(-154) + prototype(mwg) + } + mwg3{ + minX(-278) + minY(1) + minZ(-154) + prototype(mwg) + } + mwg4{ + minX(-97) + minY(1) + minZ(-295) + prototype(mwg) + } + mwg5{ + minX(-177) + minY(2) + minZ(-295) + prototype(mwg) + } + mwg6{ + minX(-278) + minY(1) + minZ(-295) + prototype(mwg) + } + mwg7{ + minX(-97) + minY(1) + minZ(-439) + prototype(mwg) + } + mwg8{ + minX(-177) + minY(1) + minZ(-439) + prototype(mwg) + } + mwg9{ + minX(-278) + minY(1) + minZ(-439) + prototype(mwg) + } + wg1{ + minX(-161) + minY(1) + minZ(35) + prototype(wg) + } + wg2{ + minX(-309) + minY(1) + minZ(35) + prototype(wg) + } + wg3{ + minX(-161) + minY(1) + minZ(252) + prototype(wg) + } + wg4{ + minX(-309) + minY(1) + minZ(252) + prototype(wg) + } + ws1{ + minX(23) + minY(25) + minZ(-231) + prototype(ws) + } + ws2{ + minX(275) + minY(25) + minZ(-231) + prototype(ws) + } + ws3{ + minX(22) + minY(25) + minZ(-366) + prototype(ws_in) + } + ws4{ + minX(274) + minY(25) + minZ(-366) + prototype(ws_in) + } +} \ No newline at end of file