diff --git a/BauSystem/BauSystem_15/src/de/steamwar/bausystem/utils/FlatteningWrapper15.java b/BauSystem/BauSystem_15/src/de/steamwar/bausystem/utils/FlatteningWrapper15.java index 9407f542..266326e0 100644 --- a/BauSystem/BauSystem_15/src/de/steamwar/bausystem/utils/FlatteningWrapper15.java +++ b/BauSystem/BauSystem_15/src/de/steamwar/bausystem/utils/FlatteningWrapper15.java @@ -109,7 +109,7 @@ public class FlatteningWrapper15 implements FlatteningWrapper { @Override public void setSelection(Player p, Point minPoint, Point maxPoint) { - WORLDEDIT_PLUGIN.getSession(p).setRegionSelector(BUKKITWORLD, new CuboidRegionSelector(BUKKITWORLD, toBlockVector3(minPoint), toBlockVector3(maxPoint))); + WORLDEDIT_PLUGIN.getSession(p).setRegionSelector(BUKKITWORLD, new CuboidRegionSelector(BUKKITWORLD, minPoint.toBlockVector3(), maxPoint.toBlockVector3())); } @Override @@ -178,9 +178,9 @@ public class FlatteningWrapper15 implements FlatteningWrapper { pastePoint.set(v); if (pasteBuilder.isReset()) { - e.setBlocks(new CuboidRegion(toBlockVector3(pasteBuilder.getMinPoint()), toBlockVector3(pasteBuilder.getMaxPoint())), Objects.requireNonNull(BlockTypes.AIR).getDefaultState().toBaseBlock()); + e.setBlocks(new CuboidRegion(pasteBuilder.getMinPoint().toBlockVector3(), pasteBuilder.getMaxPoint().toBlockVector3()), Objects.requireNonNull(BlockTypes.AIR).getDefaultState().toBaseBlock()); if (pasteBuilder.getWaterLevel() != 0) { - e.setBlocks(new CuboidRegion(toBlockVector3(pasteBuilder.getMinPoint()), toBlockVector3(pasteBuilder.getMaxPoint()).withY(pasteBuilder.getWaterLevel())), Objects.requireNonNull(BlockTypes.WATER).getDefaultState().toBaseBlock()); + e.setBlocks(new CuboidRegion(pasteBuilder.getMinPoint().toBlockVector3(), pasteBuilder.getMaxPoint().toBlockVector3().withY(pasteBuilder.getWaterLevel())), Objects.requireNonNull(BlockTypes.WATER).getDefaultState().toBaseBlock()); } } Operations.completeBlindly(ch.createPaste(e).to(v).ignoreAirBlocks(pasteBuilder.isIgnoreAir()).build()); @@ -193,7 +193,7 @@ public class FlatteningWrapper15 implements FlatteningWrapper { @Override public Clipboard copy(Point minPoint, Point maxPoint, Point copyPoint) { BukkitWorld bukkitWorld = new BukkitWorld(Bukkit.getWorlds().get(0)); - CuboidRegion region = new CuboidRegion(bukkitWorld, toBlockVector3(minPoint), toBlockVector3(maxPoint)); + CuboidRegion region = new CuboidRegion(bukkitWorld, minPoint.toBlockVector3(), maxPoint.toBlockVector3()); BlockArrayClipboard clipboard = new BlockArrayClipboard(region); try (EditSession e = WorldEdit.getInstance().getEditSessionFactory().getEditSession(bukkitWorld, -1)) { ForwardExtentCopy copy = new ForwardExtentCopy( @@ -204,7 +204,7 @@ public class FlatteningWrapper15 implements FlatteningWrapper { copy.setCopyingBiomes(false); Operations.complete(copy); - clipboard.setOrigin(toBlockVector3(copyPoint)); + clipboard.setOrigin(copyPoint.toBlockVector3()); return clipboard; } catch (WorldEditException e) { Bukkit.getLogger().log(Level.SEVERE, e.getMessage(), e); @@ -224,10 +224,6 @@ public class FlatteningWrapper15 implements FlatteningWrapper { } } - private BlockVector3 toBlockVector3(Point point) { - return BlockVector3.at(point.getX(), point.getY(), point.getZ()); - } - @Override public boolean inWater(org.bukkit.World world, Vector tntPosition) { Block block = world.getBlockAt(tntPosition.getBlockX(), tntPosition.getBlockY(), tntPosition.getBlockZ()); diff --git a/BauSystem/BauSystem_Main/src/BauSystem.properties b/BauSystem/BauSystem_Main/src/BauSystem.properties index e4dc1b27..90f1d4cf 100644 --- a/BauSystem/BauSystem_Main/src/BauSystem.properties +++ b/BauSystem/BauSystem_Main/src/BauSystem.properties @@ -947,6 +947,9 @@ SPEED_TAB_NAME=Input speed WORLDEDIT_WAND=WorldEdit Wand WORLDEDIT_LEFTCLICK=Left click: select pos #1 WORLDEDIT_RIGHTCLICK=Right click: select pos #2 +TNT_DETAILS_COMMAND=§8/§etntdetails §8-§7 Toggle information printed after clicking on a TNT +TNT_DETAILS_ON = §eTNTDetails §aactivated +TNT_DETAILS_OFF = §eTNTDetails §cdeactivated TNT_CLICK_HEADER=§8---=== §eTNT §8===--- TNT_CLICK_ORDER=§eEntity Order§8: §e{0} TNT_CLICK_FUSE_TIME=§eFuseTime§8: §e{0} diff --git a/BauSystem/BauSystem_Main/src/BauSystem_de.properties b/BauSystem/BauSystem_Main/src/BauSystem_de.properties index ea6826ed..fca76eb9 100644 --- a/BauSystem/BauSystem_Main/src/BauSystem_de.properties +++ b/BauSystem/BauSystem_Main/src/BauSystem_de.properties @@ -889,6 +889,9 @@ SPEED_TAB_NAME=Geschwindigkeit eingeben WORLDEDIT_WAND=WorldEdit Wand WORLDEDIT_LEFTCLICK=Left click: select pos #1 WORLDEDIT_RIGHTCLICK=Right click: select pos #2 +TNT_DETAILS_COMMAND=§8/§etntdetails §8-§7 Aktiviert/Deaktiviert das senden von Details beim Klick auf TNT +TNT_DETAILS_ON = §eTNTDetails §aaktiviert +TNT_DETAILS_OFF = §eTNTDetails §cdeaktiviert TNT_CLICK_HEADER=§8---=== §eTNT §8===--- TNT_CLICK_ORDER=§eEntity Order§8: §e{0} TNT_CLICK_FUSE_TIME=§eFuseTime§8: §e{0} diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/region/FreezeListener.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/region/FreezeListener.java index a284cfa8..673867e7 100644 --- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/region/FreezeListener.java +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/region/FreezeListener.java @@ -11,8 +11,9 @@ import de.steamwar.linkage.Linked; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.block.Block; +import org.bukkit.block.BlockState; +import org.bukkit.block.data.type.NoteBlock; import org.bukkit.block.data.type.Switch; -import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; @@ -60,6 +61,24 @@ public class FreezeListener implements Listener, ScoreboardElement { @EventHandler public void onPhysicsEvent(BlockPhysicsEvent e) { if (Region.getRegion(e.getBlock().getLocation()).get(Flag.FREEZE) == FreezeMode.ACTIVE) { + if (e.getSourceBlock().getType() == Material.NOTE_BLOCK) { + BlockState state = e.getSourceBlock().getState(); + NoteBlock noteBlock = (NoteBlock) state.getBlockData(); + if (noteBlock.isPowered()) { + Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> { + state.update(true, false); + }, 1); + } + } + if (e.getBlock().getType() == Material.NOTE_BLOCK) { + BlockState state = e.getBlock().getState(); + NoteBlock noteBlock = (NoteBlock) state.getBlockData(); + if (noteBlock.isPowered()) { + Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> { + state.update(true, false); + }, 1); + } + } e.setCancelled(true); } } @@ -71,6 +90,105 @@ public class FreezeListener implements Listener, ScoreboardElement { } } + @EventHandler + public void onNotePlay(NotePlayEvent event) { + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=45, z=98},type=CYAN_TERRACOTTA,data=Block{minecraft:cyan_terracotta},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} -> CraftBlock{pos=BlockPosition{x=-107, y=45, z=98},type=SMOOTH_STONE,data=Block{minecraft:smooth_stone},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=45, z=98},type=CYAN_TERRACOTTA,data=Block{minecraft:cyan_terracotta},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} -> CraftBlock{pos=BlockPosition{x=-105, y=45, z=98},type=CYAN_TERRACOTTA,data=Block{minecraft:cyan_terracotta},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=45, z=98},type=CYAN_TERRACOTTA,data=Block{minecraft:cyan_terracotta},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} -> CraftBlock{pos=BlockPosition{x=-106, y=44, z=98},type=CYAN_TERRACOTTA,data=Block{minecraft:cyan_terracotta},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=45, z=98},type=CYAN_TERRACOTTA,data=Block{minecraft:cyan_terracotta},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} -> CraftBlock{pos=BlockPosition{x=-106, y=46, z=98},type=BARRIER,data=Block{minecraft:barrier},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=45, z=98},type=CYAN_TERRACOTTA,data=Block{minecraft:cyan_terracotta},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} -> CraftBlock{pos=BlockPosition{x=-106, y=45, z=97},type=CYAN_TERRACOTTA,data=Block{minecraft:cyan_terracotta},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=45, z=98},type=CYAN_TERRACOTTA,data=Block{minecraft:cyan_terracotta},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} -> CraftBlock{pos=BlockPosition{x=-106, y=45, z=99},type=SMOOTH_STONE,data=Block{minecraft:smooth_stone},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} + + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=47, z=98},type=NOTE_BLOCK,data=Block{minecraft:note_block}[instrument=custom_head,note=9,powered=true],fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} -> CraftBlock{pos=BlockPosition{x=-107, y=47, z=98},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=47, z=98},type=NOTE_BLOCK,data=Block{minecraft:note_block}[instrument=custom_head,note=9,powered=true],fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} -> CraftBlock{pos=BlockPosition{x=-105, y=47, z=98},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=47, z=98},type=NOTE_BLOCK,data=Block{minecraft:note_block}[instrument=custom_head,note=9,powered=true],fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} -> CraftBlock{pos=BlockPosition{x=-106, y=46, z=98},type=BARRIER,data=Block{minecraft:barrier},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=47, z=98},type=NOTE_BLOCK,data=Block{minecraft:note_block}[instrument=custom_head,note=9,powered=true],fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} -> CraftBlock{pos=BlockPosition{x=-106, y=48, z=98},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=47, z=98},type=NOTE_BLOCK,data=Block{minecraft:note_block}[instrument=custom_head,note=9,powered=true],fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} -> CraftBlock{pos=BlockPosition{x=-106, y=47, z=97},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=47, z=98},type=NOTE_BLOCK,data=Block{minecraft:note_block}[instrument=custom_head,note=9,powered=true],fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} -> CraftBlock{pos=BlockPosition{x=-106, y=47, z=99},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} + + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=46, z=97},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} -> CraftBlock{pos=BlockPosition{x=-107, y=46, z=97},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=46, z=97},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} -> CraftBlock{pos=BlockPosition{x=-105, y=46, z=97},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=46, z=97},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} -> CraftBlock{pos=BlockPosition{x=-106, y=45, z=97},type=CYAN_TERRACOTTA,data=Block{minecraft:cyan_terracotta},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=46, z=97},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} -> CraftBlock{pos=BlockPosition{x=-106, y=47, z=97},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=46, z=97},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} -> CraftBlock{pos=BlockPosition{x=-106, y=46, z=96},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=46, z=97},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} -> CraftBlock{pos=BlockPosition{x=-106, y=46, z=98},type=BARRIER,data=Block{minecraft:barrier},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=46, z=99},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} -> CraftBlock{pos=BlockPosition{x=-107, y=46, z=99},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=46, z=99},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} -> CraftBlock{pos=BlockPosition{x=-105, y=46, z=99},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=46, z=99},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} -> CraftBlock{pos=BlockPosition{x=-106, y=45, z=99},type=SMOOTH_STONE,data=Block{minecraft:smooth_stone},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=46, z=99},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} -> CraftBlock{pos=BlockPosition{x=-106, y=47, z=99},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=46, z=99},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} -> CraftBlock{pos=BlockPosition{x=-106, y=46, z=98},type=BARRIER,data=Block{minecraft:barrier},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=46, z=99},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} -> CraftBlock{pos=BlockPosition{x=-106, y=46, z=100},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-107, y=46, z=98},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} -> CraftBlock{pos=BlockPosition{x=-108, y=46, z=98},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-107, y=46, z=98},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} -> CraftBlock{pos=BlockPosition{x=-106, y=46, z=98},type=BARRIER,data=Block{minecraft:barrier},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-107, y=46, z=98},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} -> CraftBlock{pos=BlockPosition{x=-107, y=45, z=98},type=SMOOTH_STONE,data=Block{minecraft:smooth_stone},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-107, y=46, z=98},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} -> CraftBlock{pos=BlockPosition{x=-107, y=47, z=98},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-107, y=46, z=98},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} -> CraftBlock{pos=BlockPosition{x=-107, y=46, z=97},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-107, y=46, z=98},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} -> CraftBlock{pos=BlockPosition{x=-107, y=46, z=99},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-105, y=46, z=98},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} -> CraftBlock{pos=BlockPosition{x=-106, y=46, z=98},type=BARRIER,data=Block{minecraft:barrier},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-105, y=46, z=98},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} -> CraftBlock{pos=BlockPosition{x=-104, y=46, z=98},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-105, y=46, z=98},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} -> CraftBlock{pos=BlockPosition{x=-105, y=45, z=98},type=CYAN_TERRACOTTA,data=Block{minecraft:cyan_terracotta},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-105, y=46, z=98},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} -> CraftBlock{pos=BlockPosition{x=-105, y=47, z=98},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-105, y=46, z=98},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} -> CraftBlock{pos=BlockPosition{x=-105, y=46, z=97},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-105, y=46, z=98},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} -> CraftBlock{pos=BlockPosition{x=-105, y=46, z=99},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} + + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=47, z=98},type=NOTE_BLOCK,data=Block{minecraft:note_block}[instrument=harp,note=9,powered=true],fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} -> CraftBlock{pos=BlockPosition{x=-106, y=47, z=98},type=NOTE_BLOCK,data=Block{minecraft:note_block}[instrument=harp,note=9,powered=true],fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=47, z=98},type=NOTE_BLOCK,data=Block{minecraft:note_block}[instrument=harp,note=9,powered=false],fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} -> CraftBlock{pos=BlockPosition{x=-107, y=47, z=98},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=47, z=98},type=NOTE_BLOCK,data=Block{minecraft:note_block}[instrument=harp,note=9,powered=false],fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} -> CraftBlock{pos=BlockPosition{x=-105, y=47, z=98},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=47, z=98},type=NOTE_BLOCK,data=Block{minecraft:note_block}[instrument=harp,note=9,powered=false],fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} -> CraftBlock{pos=BlockPosition{x=-106, y=46, z=98},type=BARRIER,data=Block{minecraft:barrier},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=47, z=98},type=NOTE_BLOCK,data=Block{minecraft:note_block}[instrument=harp,note=9,powered=false],fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} -> CraftBlock{pos=BlockPosition{x=-106, y=48, z=98},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=47, z=98},type=NOTE_BLOCK,data=Block{minecraft:note_block}[instrument=harp,note=9,powered=false],fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} -> CraftBlock{pos=BlockPosition{x=-106, y=47, z=97},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=47, z=98},type=NOTE_BLOCK,data=Block{minecraft:note_block}[instrument=harp,note=9,powered=false],fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} -> CraftBlock{pos=BlockPosition{x=-106, y=47, z=99},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=47, z=98},type=NOTE_BLOCK,data=Block{minecraft:note_block}[instrument=harp,note=9,powered=false],fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} -> CraftBlock{pos=BlockPosition{x=-106, y=47, z=98},type=NOTE_BLOCK,data=Block{minecraft:note_block}[instrument=harp,note=9,powered=false],fluid=net.minecraft.world.level.material.FluidTypeEmpty@78078831} + + + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=46, z=100},type=SMOOTH_STONE,data=Block{minecraft:smooth_stone},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} -> CraftBlock{pos=BlockPosition{x=-107, y=46, z=100},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=46, z=100},type=SMOOTH_STONE,data=Block{minecraft:smooth_stone},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} -> CraftBlock{pos=BlockPosition{x=-105, y=46, z=100},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=46, z=100},type=SMOOTH_STONE,data=Block{minecraft:smooth_stone},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} -> CraftBlock{pos=BlockPosition{x=-106, y=45, z=100},type=SMOOTH_STONE,data=Block{minecraft:smooth_stone},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=46, z=100},type=SMOOTH_STONE,data=Block{minecraft:smooth_stone},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} -> CraftBlock{pos=BlockPosition{x=-106, y=47, z=100},type=STONE_SLAB,data=Block{minecraft:stone_slab}[type=bottom,waterlogged=false],fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=46, z=100},type=SMOOTH_STONE,data=Block{minecraft:smooth_stone},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} -> CraftBlock{pos=BlockPosition{x=-106, y=46, z=99},type=SMOOTH_STONE,data=Block{minecraft:smooth_stone},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=46, z=100},type=SMOOTH_STONE,data=Block{minecraft:smooth_stone},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} -> CraftBlock{pos=BlockPosition{x=-106, y=46, z=101},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} + + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=48, z=100},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} -> CraftBlock{pos=BlockPosition{x=-107, y=48, z=100},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=48, z=100},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} -> CraftBlock{pos=BlockPosition{x=-105, y=48, z=100},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=48, z=100},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} -> CraftBlock{pos=BlockPosition{x=-106, y=47, z=100},type=STONE_SLAB,data=Block{minecraft:stone_slab}[type=bottom,waterlogged=false],fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=48, z=100},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} -> CraftBlock{pos=BlockPosition{x=-106, y=49, z=100},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=48, z=100},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} -> CraftBlock{pos=BlockPosition{x=-106, y=48, z=99},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=48, z=100},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} -> CraftBlock{pos=BlockPosition{x=-106, y=48, z=101},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=47, z=99},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} -> CraftBlock{pos=BlockPosition{x=-107, y=47, z=99},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=47, z=99},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} -> CraftBlock{pos=BlockPosition{x=-105, y=47, z=99},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=47, z=99},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} -> CraftBlock{pos=BlockPosition{x=-106, y=46, z=99},type=SMOOTH_STONE,data=Block{minecraft:smooth_stone},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=47, z=99},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} -> CraftBlock{pos=BlockPosition{x=-106, y=48, z=99},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} + ////[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=47, z=99},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} -> CraftBlock{pos=BlockPosition{x=-106, y=47, z=98},type=NOTE_BLOCK,data=Block{minecraft:note_block}[instrument=basedrum,note=9,powered=true],fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=47, z=99},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} -> CraftBlock{pos=BlockPosition{x=-106, y=47, z=100},type=STONE_SLAB,data=Block{minecraft:stone_slab}[type=bottom,waterlogged=false],fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=47, z=101},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} -> CraftBlock{pos=BlockPosition{x=-107, y=47, z=101},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=47, z=101},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} -> CraftBlock{pos=BlockPosition{x=-105, y=47, z=101},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=47, z=101},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} -> CraftBlock{pos=BlockPosition{x=-106, y=46, z=101},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=47, z=101},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} -> CraftBlock{pos=BlockPosition{x=-106, y=48, z=101},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=47, z=101},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} -> CraftBlock{pos=BlockPosition{x=-106, y=47, z=100},type=STONE_SLAB,data=Block{minecraft:stone_slab}[type=bottom,waterlogged=false],fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=47, z=101},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} -> CraftBlock{pos=BlockPosition{x=-106, y=47, z=102},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-107, y=47, z=100},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} -> CraftBlock{pos=BlockPosition{x=-108, y=47, z=100},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-107, y=47, z=100},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} -> CraftBlock{pos=BlockPosition{x=-106, y=47, z=100},type=STONE_SLAB,data=Block{minecraft:stone_slab}[type=bottom,waterlogged=false],fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-107, y=47, z=100},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} -> CraftBlock{pos=BlockPosition{x=-107, y=46, z=100},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-107, y=47, z=100},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} -> CraftBlock{pos=BlockPosition{x=-107, y=48, z=100},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-107, y=47, z=100},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} -> CraftBlock{pos=BlockPosition{x=-107, y=47, z=99},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-107, y=47, z=100},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} -> CraftBlock{pos=BlockPosition{x=-107, y=47, z=101},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-105, y=47, z=100},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} -> CraftBlock{pos=BlockPosition{x=-106, y=47, z=100},type=STONE_SLAB,data=Block{minecraft:stone_slab}[type=bottom,waterlogged=false],fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-105, y=47, z=100},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} -> CraftBlock{pos=BlockPosition{x=-104, y=47, z=100},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-105, y=47, z=100},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} -> CraftBlock{pos=BlockPosition{x=-105, y=46, z=100},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-105, y=47, z=100},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} -> CraftBlock{pos=BlockPosition{x=-105, y=48, z=100},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-105, y=47, z=100},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} -> CraftBlock{pos=BlockPosition{x=-105, y=47, z=99},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-105, y=47, z=100},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} -> CraftBlock{pos=BlockPosition{x=-105, y=47, z=101},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} + + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=47, z=98},type=NOTE_BLOCK,data=Block{minecraft:note_block}[instrument=basedrum,note=9,powered=false],fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} -> CraftBlock{pos=BlockPosition{x=-107, y=47, z=98},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=47, z=98},type=NOTE_BLOCK,data=Block{minecraft:note_block}[instrument=basedrum,note=9,powered=false],fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} -> CraftBlock{pos=BlockPosition{x=-105, y=47, z=98},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=47, z=98},type=NOTE_BLOCK,data=Block{minecraft:note_block}[instrument=basedrum,note=9,powered=false],fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} -> CraftBlock{pos=BlockPosition{x=-106, y=46, z=98},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=47, z=98},type=NOTE_BLOCK,data=Block{minecraft:note_block}[instrument=basedrum,note=9,powered=false],fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} -> CraftBlock{pos=BlockPosition{x=-106, y=48, z=98},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=47, z=98},type=NOTE_BLOCK,data=Block{minecraft:note_block}[instrument=basedrum,note=9,powered=false],fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} -> CraftBlock{pos=BlockPosition{x=-106, y=47, z=97},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=47, z=98},type=NOTE_BLOCK,data=Block{minecraft:note_block}[instrument=basedrum,note=9,powered=false],fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} -> CraftBlock{pos=BlockPosition{x=-106, y=47, z=99},type=AIR,data=Block{minecraft:air},fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} + //[STDOUT] CraftBlock{pos=BlockPosition{x=-106, y=47, z=98},type=NOTE_BLOCK,data=Block{minecraft:note_block}[instrument=basedrum,note=9,powered=false],fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} -> CraftBlock{pos=BlockPosition{x=-106, y=47, z=98},type=NOTE_BLOCK,data=Block{minecraft:note_block}[instrument=basedrum,note=9,powered=false],fluid=net.minecraft.world.level.material.FluidTypeEmpty@1531ed7b} + } + + @EventHandler public void onPistonRetract(BlockPistonRetractEvent e) { if (Region.getRegion(e.getBlock().getLocation()).get(Flag.FREEZE) == FreezeMode.ACTIVE) { @@ -108,13 +226,13 @@ public class FreezeListener implements Listener, ScoreboardElement { } } - @EventHandler(priority = EventPriority.MONITOR) + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onBlockBreak(BlockBreakEvent e) { if (Core.getVersion() < 19) return; if (e.getPlayer().getInventory().getItemInMainHand().getType() == Material.DEBUG_STICK) return; if (Region.getRegion(e.getBlock().getLocation()).get(Flag.FREEZE) == FreezeMode.ACTIVE) { - if (e.isCancelled()) return; e.setCancelled(true); + e.getBlock().setType(Material.BARRIER, false); e.getBlock().setType(Material.AIR, false); } } diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/script/lua/libs/TpsLib.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/script/lua/libs/TpsLib.java index 1435aa44..6b9435e1 100644 --- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/script/lua/libs/TpsLib.java +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/script/lua/libs/TpsLib.java @@ -51,7 +51,7 @@ public class TpsLib implements LuaLib { tpsLib.set("fiveMinute", getter(() -> TPSWatcher.getTPS(TPSWatcher.TPSType.FIVE_MINUTES))); tpsLib.set("tenMinute", getter(() -> TPSWatcher.getTPS(TPSWatcher.TPSType.TEN_MINUTES))); tpsLib.set("current", getter(TPSWatcher::getTPS)); - tpsLib.set("limit", getter(tpsSystem::getCurrentTPSLimit)); + tpsLib.set("limit", getter(TPSSystem::getCurrentTPSLimit)); return tpsLib; } } diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/script/lua/libs/TracerLib.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/script/lua/libs/TracerLib.java new file mode 100644 index 00000000..5178bdf9 --- /dev/null +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/script/lua/libs/TracerLib.java @@ -0,0 +1,113 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2023 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.lua.libs; + +import de.steamwar.bausystem.features.tracer.TNTPoint; +import de.steamwar.bausystem.features.tracer.Trace; +import de.steamwar.bausystem.features.tracer.TraceManager; +import de.steamwar.linkage.Linked; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; +import org.luaj.vm2.LuaTable; +import org.luaj.vm2.LuaValue; +import org.luaj.vm2.lib.ZeroArgFunction; + +@Linked +public class TracerLib implements LuaLib { + @Override + public String name() { + return "tracer"; + } + + private static LuaTable convertTrace(Trace trace) { + LuaTable luaTrace = new LuaTable(); + + luaTrace.set("getRecords", new ZeroArgFunction() { + @Override + public LuaValue call() { + return LuaValue.listOf( + trace.getHistories() + .stream() + .map((history) -> LuaValue.listOf(history + .stream() + .map(TracerLib::convertTntPoint) + .toArray(LuaValue[]::new))) + .toArray(LuaValue[]::new)); + } + }); + + luaTrace.set("getId", new ZeroArgFunction() { + @Override + public LuaValue call() { + return LuaValue.valueOf(trace.getUuid().toString()); + } + }); + + + return luaTrace; + } + + private static LuaTable convertTntPoint(TNTPoint tntPoint) { + Location pointPos = tntPoint.getLocation(); + LuaTable luaPos = LuaValue.tableOf(new LuaValue[]{ + LuaValue.valueOf("x"), LuaValue.valueOf(pointPos.getX()), + LuaValue.valueOf("y"), LuaValue.valueOf(pointPos.getY()), + LuaValue.valueOf("z"), LuaValue.valueOf(pointPos.getZ()), + }); + + Vector pointVel = tntPoint.getVelocity(); + LuaTable luaVel = LuaValue.tableOf(new LuaValue[]{ + LuaValue.valueOf("x"), LuaValue.valueOf(pointVel.getX()), + LuaValue.valueOf("y"), LuaValue.valueOf(pointVel.getY()), + LuaValue.valueOf("z"), LuaValue.valueOf(pointVel.getZ()), + }); + + return LuaValue.tableOf(new LuaValue[]{ + LuaValue.valueOf("pos"), luaPos, + LuaValue.valueOf("vel"), luaVel, + LuaValue.valueOf("ticksSinceStart"), LuaValue.valueOf(tntPoint.getTicksSinceStart()), + LuaValue.valueOf("fuse"), LuaValue.valueOf(tntPoint.getFuse()), + LuaValue.valueOf("isExplosion"), LuaValue.valueOf(tntPoint.isExplosion()), + LuaValue.valueOf("isInWater"), LuaValue.valueOf(tntPoint.isInWater()), + LuaValue.valueOf("hasDestroyedBuild"), LuaValue.valueOf(tntPoint.isDestroyedBuildArea()), + LuaValue.valueOf("hasDestroyedTestblock"), LuaValue.valueOf(tntPoint.isDestroyedTestBlock()) + }); + } + + @Override + public LuaTable get(Player player) { + LuaTable rootTable = LuaValue.tableOf(); + + rootTable.set("getTraces", new ZeroArgFunction() { + @Override + public LuaValue call() { + return LuaValue.listOf(TraceManager.instance.getAll() + .stream() + .map(TracerLib::convertTrace) + .toArray(LuaValue[]::new)); + } + } + + ); + + return rootTable; + } +} diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/SimulatorCommand.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/SimulatorCommand.java index de0c4b74..bf329b3b 100644 --- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/SimulatorCommand.java +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/SimulatorCommand.java @@ -76,7 +76,7 @@ public class SimulatorCommand extends SWCommand { @Register(value = "start", description = "SIMULATOR_START_HELP") public void start(@Validator Player p, @ErrorMessage("SIMULATOR_NOT_EXISTS") Simulator simulator) { - SimulatorExecutor.run(simulator); + SimulatorExecutor.run(simulator, () -> {}); } @Register(value = "rename", description = "SIMULATOR_RENAME_HELP") diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/SimulatorCursor.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/SimulatorCursor.java index de9dae3f..f9629c3d 100644 --- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/SimulatorCursor.java +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/SimulatorCursor.java @@ -168,9 +168,19 @@ public class SimulatorCursor implements Listener { } return; } - Simulator simulator = SimulatorStorage.getSimulator(player); - SimulatorWatcher.show(simulator, player); + Simulator simulator = SimulatorStorage.getSimulator(player); + if (simulator != null && simulator.getStabGenerator() != null) { + removeCursor(player); + SimulatorWatcher.show(null, player); + SWUtils.sendToActionbar(player, "§cGenerating Stab"); + synchronized (calculating) { + calculating.remove(player); + } + return; + } + + SimulatorWatcher.show(simulator, player); List entities = SimulatorWatcher.getEntitiesOfSimulator(simulator); RayTraceUtils.RRayTraceResult rayTraceResult = RayTraceUtils.traceREntity(player, player.getLocation(), entities); if (rayTraceResult == null) { @@ -357,7 +367,7 @@ public class SimulatorCursor implements Listener { if (simulator == null) { return; } - SimulatorExecutor.run(simulator); + SimulatorExecutor.run(simulator, () -> {}); return; } diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/data/Simulator.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/data/Simulator.java index 91b7a8e1..8dcb8321 100644 --- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/data/Simulator.java +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/data/Simulator.java @@ -20,6 +20,7 @@ package de.steamwar.bausystem.features.simulator.data; import de.steamwar.bausystem.features.simulator.execute.SimulatorAction; +import de.steamwar.bausystem.features.simulator.execute.SimulatorStabGenerator; import de.steamwar.inventory.InvCallback; import de.steamwar.inventory.SWItem; import lombok.Getter; @@ -30,13 +31,13 @@ import org.bukkit.entity.Player; import java.util.ArrayList; import java.util.List; -import java.util.Map; import java.util.function.BiConsumer; @Getter @Setter @RequiredArgsConstructor public final class Simulator { + private SimulatorStabGenerator stabGenerator = null; private Material material = Material.BARREL; private final String name; private boolean autoTrace = false; diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/data/tnt/TNTPhase.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/data/tnt/TNTPhase.java index 4c03ac9b..29f59d93 100644 --- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/data/tnt/TNTPhase.java +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/data/tnt/TNTPhase.java @@ -60,6 +60,7 @@ public final class TNTPhase extends SimulatorPhase { @Override public void toSimulatorActions(Vector position, BiConsumer tickStart, BiConsumer tickEnd) { + if (count <= 0) return; tickStart.accept(tickOffset, new SimulatorAction(order, count) { @Override public void accept(World world) { diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/execute/Direction.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/execute/Direction.java new file mode 100644 index 00000000..31737266 --- /dev/null +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/execute/Direction.java @@ -0,0 +1,34 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem.features.simulator.execute; + +import lombok.AllArgsConstructor; +import org.bukkit.util.Vector; + +import java.util.function.Function; + +@AllArgsConstructor +public enum Direction { + X(Vector::getBlockX), + Y(Vector::getBlockY), + Z(Vector::getBlockZ); + + public final Function component; +} diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/execute/SimulatorExecutor.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/execute/SimulatorExecutor.java index 5c3d30e0..b052e4c8 100644 --- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/execute/SimulatorExecutor.java +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/execute/SimulatorExecutor.java @@ -46,7 +46,7 @@ public class SimulatorExecutor implements Listener { private static Map>> tickStartActions = new HashMap<>(); private static Map> tickEndActions = new HashMap<>(); - public static boolean run(Simulator simulator) { + public static boolean run(Simulator simulator, Runnable onEnd) { if (currentlyRunning.contains(simulator)) return false; currentlyRunning.add(simulator); @@ -69,7 +69,7 @@ public class SimulatorExecutor implements Listener { public void accept(World world) { currentlyRunning.remove(simulator); - if (simulator.isAutoTrace()) { + if (simulator.isAutoTrace() && onEnd == null) { simulator.getGroups() .stream() .map(SimulatorGroup::getElements) @@ -82,10 +82,12 @@ public class SimulatorExecutor implements Listener { TraceRecorder.instance.stopRecording(region); }); } + + onEnd.run(); } }); - if (simulator.isAutoTrace()) { + if (simulator.isAutoTrace() && onEnd == null) { simulator.getGroups() .stream() .map(SimulatorGroup::getElements) diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/execute/SimulatorStabGenerator.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/execute/SimulatorStabGenerator.java new file mode 100644 index 00000000..37ca8bf3 --- /dev/null +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/execute/SimulatorStabGenerator.java @@ -0,0 +1,45 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem.features.simulator.execute; + +import de.steamwar.bausystem.features.simulator.data.Simulator; +import de.steamwar.bausystem.features.simulator.data.tnt.TNTElement; +import de.steamwar.bausystem.region.Region; +import de.steamwar.bausystem.utils.bossbar.BossBarService; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +public class SimulatorStabGenerator { + + private final StabData stabData; + + public SimulatorStabGenerator(Region region, Simulator simulator, TNTElement tntElement, int depthLimit) { + stabData = new StabData(region, simulator, tntElement, tntElement.getPhases(), depthLimit); + new StabSetup(stabData); + } + + public void cancel() { + stabData.cancel = true; + stabData.simulator.setStabGenerator(null); + for (Player player : Bukkit.getOnlinePlayers()) { + BossBarService.instance.remove(player, stabData.region, "simulator_stab_generator"); + } + } +} diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/execute/StabData.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/execute/StabData.java new file mode 100644 index 00000000..dc1a6e0e --- /dev/null +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/execute/StabData.java @@ -0,0 +1,52 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem.features.simulator.execute; + +import com.sk89q.worldedit.extent.clipboard.Clipboard; +import de.steamwar.bausystem.features.simulator.data.Simulator; +import de.steamwar.bausystem.features.simulator.data.tnt.TNTElement; +import de.steamwar.bausystem.features.simulator.data.tnt.TNTPhase; +import de.steamwar.bausystem.region.Region; +import lombok.RequiredArgsConstructor; + +import java.util.List; +import java.util.logging.Level; + +@RequiredArgsConstructor +public class StabData { + + protected static final int MAX_RECORDINGS = 5; + protected static final int MAX_TICK_DIFFERENCE = 3; + protected static final Level LEVEL = Level.INFO; + protected static final int TNT_INCREASE = 10; + protected static final int MIN_BLOCK_TO_COUNT_AS_DEPTH = 20; + + protected final Region region; + protected final Simulator simulator; + protected final TNTElement tntElement; + protected final List phases; + protected final int depthLimit; + + protected Clipboard clipboard; + protected boolean cancel = false; + + protected Direction direction = null; + protected int currentDepth = 0; +} diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/execute/StabDirection.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/execute/StabDirection.java new file mode 100644 index 00000000..4be5284b --- /dev/null +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/execute/StabDirection.java @@ -0,0 +1,103 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem.features.simulator.execute; + +import com.sk89q.worldedit.EditSession; +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.bukkit.BukkitWorld; +import com.sk89q.worldedit.regions.CuboidRegion; +import com.sk89q.worldedit.world.block.BlockTypes; +import de.steamwar.bausystem.features.simulator.data.SimulatorPhase; +import de.steamwar.bausystem.features.tracer.TNTPoint; +import de.steamwar.bausystem.features.tracer.Trace; +import de.steamwar.bausystem.features.tracer.TraceManager; +import de.steamwar.bausystem.features.tracer.TraceRecorder; +import de.steamwar.bausystem.utils.bossbar.BauSystemBossbar; +import org.bukkit.Bukkit; +import org.bukkit.util.Vector; + +import java.util.List; +import java.util.Objects; + +public class StabDirection extends StabStep { + + public StabDirection(StabData data) { + super(data); + } + + @Override + protected void start() { + try (EditSession e = WorldEdit.getInstance().getEditSessionFactory().getEditSession(new BukkitWorld(Bukkit.getWorlds().get(0)), -1)) { + e.setBlocks((com.sk89q.worldedit.regions.Region) new CuboidRegion(data.region.getMinPointTestblockExtension().toBlockVector3(), data.region.getMaxPointTestblockExtension().toBlockVector3()), Objects.requireNonNull(BlockTypes.AIR).getDefaultState().toBaseBlock()); + } + + Trace trace = TraceRecorder.instance.startRecording(data.region); + runSimulator(() -> { + TraceRecorder.instance.stopRecording(data.region); + calculateDirection(trace); + }); + } + + private void calculateDirection(Trace trace) { + long tickSinceStart = -1; + List points = null; + for (List current : trace.getHistories()) { + long ticks = current.get(0).getTicksSinceStart(); + if (points == null || ticks > tickSinceStart) { + tickSinceStart = ticks; + points = current; + } else if (ticks == tickSinceStart && points.get(0).getTntId() < current.get(0).getTntId()) { + points = current; + } + } + TraceManager.instance.remove(trace); + if (points == null) { + stop(); + return; + } + + TNTPoint current = points.getLast(); + Vector velocity = current.getVelocity(); + if (velocity.getX() < 0) velocity.setX(-velocity.getX()); + if (velocity.getY() < 0) velocity.setY(-velocity.getY()); + if (velocity.getZ() < 0) velocity.setZ(-velocity.getZ()); + if (velocity.getX() > velocity.getY() && velocity.getX() > velocity.getZ()) { + data.direction = Direction.X; + } else if (velocity.getY() > velocity.getX() && velocity.getY() > velocity.getZ()) { + data.direction = Direction.Y; + } else if (velocity.getZ() > velocity.getX() && velocity.getZ() > velocity.getY()) { + data.direction = Direction.Z; + } else { + stop(); + return; + } + + Bukkit.getLogger().log(StabData.LEVEL, "Direction: {0}", data.direction); + data.phases.getFirst().setOrder(SimulatorPhase.ORDER_LIMIT); + data.phases.getFirst().setCount(StabData.TNT_INCREASE); + new StabGenerator(data); + } + + @Override + protected void bossbar(BauSystemBossbar bossbar, boolean finished) { + bossbar.setProgress(0); + bossbar.setTitle("§eCalculating Stab Direction"); + } +} diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/execute/StabFinalizer.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/execute/StabFinalizer.java new file mode 100644 index 00000000..5c0d77aa --- /dev/null +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/execute/StabFinalizer.java @@ -0,0 +1,61 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem.features.simulator.execute; + +import de.steamwar.bausystem.features.tracer.Trace; +import de.steamwar.bausystem.features.tracer.TraceRecorder; +import de.steamwar.bausystem.region.flags.Flag; +import de.steamwar.bausystem.region.flags.flagvalues.ColorMode; +import de.steamwar.bausystem.region.utils.RegionExtensionType; +import de.steamwar.bausystem.region.utils.RegionType; +import de.steamwar.bausystem.utils.PasteBuilder; +import de.steamwar.bausystem.utils.bossbar.BauSystemBossbar; + +public class StabFinalizer extends StabStep { + + public StabFinalizer(StabData data) { + super(data); + } + + @Override + protected void start() { + try { + PasteBuilder.ClipboardProvider clipboardProvider = new PasteBuilder.ClipboardProviderImpl(data.clipboard); + PasteBuilder pasteBuilder = new PasteBuilder(clipboardProvider) + .color(data.region.getPlain(Flag.COLOR, ColorMode.class).getColor()); + data.region.reset(pasteBuilder, RegionType.TESTBLOCK, RegionExtensionType.EXTENSION); + } catch (SecurityException e) { + stop(); + throw e; + } + + TraceRecorder.instance.startRecording(data.region); + runSimulator(() -> { + TraceRecorder.instance.stopRecording(data.region); + stop(); + }); + } + + @Override + protected void bossbar(BauSystemBossbar bossbar, boolean stopped) { + bossbar.setProgress(Math.min(data.currentDepth / (double) data.depthLimit, 1.0)); + bossbar.setTitle("§e" + data.currentDepth + "§8/§7" + data.depthLimit); + } +} diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/execute/StabGenerator.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/execute/StabGenerator.java new file mode 100644 index 00000000..4a15ebcb --- /dev/null +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/execute/StabGenerator.java @@ -0,0 +1,250 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem.features.simulator.execute; + +import de.steamwar.bausystem.features.simulator.data.tnt.TNTPhase; +import de.steamwar.bausystem.region.Region; +import de.steamwar.bausystem.region.flags.Flag; +import de.steamwar.bausystem.region.flags.flagvalues.ColorMode; +import de.steamwar.bausystem.region.utils.RegionExtensionType; +import de.steamwar.bausystem.region.utils.RegionType; +import de.steamwar.bausystem.utils.PasteBuilder; +import de.steamwar.bausystem.utils.bossbar.BauSystemBossbar; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.event.EventHandler; +import org.bukkit.event.HandlerList; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityExplodeEvent; + +import java.util.*; +import java.util.stream.Collectors; + +import static de.steamwar.bausystem.features.simulator.execute.Direction.Y; + +public class StabGenerator extends StabStep implements Listener { + + private int recordings = 0; + private List currentDepths = new ArrayList<>(); + private int lastDepth = 0; + + private int retries = 0; + + private final Map> destroyedBlocksPerSlice = new HashMap<>(); + + private Set gabStart = new HashSet<>(); + private Set failedAtLeastOnce = new HashSet<>(); + + @EventHandler + public void onEntityExplode(EntityExplodeEvent event) { + if (Region.getRegion(event.getEntity().getLocation()) == data.region) { + event.blockList().forEach(block -> { + if (!data.region.inRegion(block.getLocation(), RegionType.TESTBLOCK, RegionExtensionType.EXTENSION)) return; + int component = data.direction.component.apply(block.getLocation().toVector()); + destroyedBlocksPerSlice.computeIfAbsent(component, __ -> new HashSet<>()) + .add(block.getLocation()); + }); + } + } + + public StabGenerator(StabData data) { + super(data); + } + + @Override + protected void start() { + try { + PasteBuilder.ClipboardProvider clipboardProvider = new PasteBuilder.ClipboardProviderImpl(data.clipboard); + PasteBuilder pasteBuilder = new PasteBuilder(clipboardProvider) + .color(data.region.getPlain(Flag.COLOR, ColorMode.class).getColor()); + data.region.reset(pasteBuilder, RegionType.TESTBLOCK, RegionExtensionType.EXTENSION); + } catch (SecurityException e) { + stop(); + throw e; + } + + if (data.cancel) { + HandlerList.unregisterAll(this); + return; + } + + runSimulator(this::calculateStab); + } + + private void calculateStab() { + TNTPhase lastPhase = data.phases.getLast(); + + List>> locations = destroyedBlocksPerSlice.entrySet() + .stream() + .sorted(Comparator.comparingInt(Map.Entry::getKey)) + .collect(Collectors.toList()); + int depth = 0; + for (int i = 0; i < locations.size(); i++) { + if (data.direction != Y && i > 0 && Math.abs(locations.get(i - 1).getKey() - locations.get(i).getKey()) > 3) { + if (gabStart.add(locations.get(i).getKey())) { + Bukkit.getLogger().log(StabData.LEVEL, "Increasing tnt count by {0} because of gap", StabData.TNT_INCREASE); + lastPhase.setCount(lastPhase.getCount() + StabData.TNT_INCREASE); + recordings = 0; + currentDepths.clear(); + + run(); + return; + } + } + if (i == 0 || i == locations.size() - 1) { + if (locations.get(i).getValue().size() > StabData.MIN_BLOCK_TO_COUNT_AS_DEPTH) { + depth++; + } + } else { + depth++; + } + } + + if (depth > 0) { + Bukkit.getLogger().log(StabData.LEVEL, "{0} {1} {2}", new Object[]{depth, destroyedBlocksPerSlice.size(), destroyedBlocksPerSlice.values().stream().map(Set::size).collect(Collectors.toList())}); + destroyedBlocksPerSlice.clear(); + currentDepths.add(depth); + } else { + destroyedBlocksPerSlice.clear(); + lastPhase.setTickOffset(lastPhase.getTickOffset() + 1); + Bukkit.getLogger().log(StabData.LEVEL, "No dimension - Increasing tickOffset to: {0}", lastPhase.getTickOffset()); + lastPhase.setOrder(0); + if (lastPhase.getTickOffset() > 80) { + stop(); + } else { + run(); + } + return; + } + + int minDepth = currentDepths.stream().min(Integer::compareTo).orElse(0); + int maxDepth = currentDepths.stream().max(Integer::compareTo).orElse(0); + data.currentDepth = maxDepth; + + int countWithoutLast = 0; + for (int i = 0; i < data.phases.size() - 1; i++) { + countWithoutLast += data.phases.get(i).getCount(); + } + countWithoutLast -= gabStart.size(); + + boolean moreTNTNeeded = maxDepth - countWithoutLast >= lastPhase.getCount() - 5; + if (moreTNTNeeded) { + Bukkit.getLogger().log(StabData.LEVEL, "Increasing tnt count by {0}", StabData.TNT_INCREASE); + lastPhase.setCount(lastPhase.getCount() + StabData.TNT_INCREASE); + recordings = 0; + currentDepths.clear(); + + run(); + return; + } + + if (recordings++ < StabData.MAX_RECORDINGS) { + run(); + return; + } + + recordings = 0; + currentDepths.clear(); + + if (maxDepth - minDepth > lastPhase.getCount()) { + Bukkit.getLogger().log(StabData.LEVEL, "Stab failed at least once. Adding one tnt to {0}", minDepth - 3); + int current = 0; + TNTPhase last = null; + for (TNTPhase phase : data.phases) { + if (current < minDepth - 3) { + current += phase.getCount(); + last = phase; + continue; + } + + if (failedAtLeastOnce.add(last)) { + last = null; + break; + } + + if (last != null) { + last.setCount(last.getCount() + 1); + Bukkit.getLogger().log(StabData.LEVEL, "Added to phase {0} now has {1} tnt", new Object[]{data.phases.indexOf(last), last.getCount()}); + } + break; + } + + if (last != null) { + run(); + return; + } + } + + Bukkit.getLogger().log(StabData.LEVEL, "No more TNT needed on phase adjusting - {0} new count; {1} current count", new Object[]{maxDepth - countWithoutLast, lastPhase.getCount()}); + lastPhase.setCount(maxDepth - countWithoutLast); + if (lastPhase.getCount() <= 0) { + Bukkit.getLogger().log(StabData.LEVEL, "Count was 0 or negative - removing last phase"); + data.phases.removeLast(); + } + + if (maxDepth > data.depthLimit) { + Bukkit.getLogger().log(StabData.LEVEL, "Depth is greater than {0} - finished", data.depthLimit); + new StabFinalizer(data); + return; + } + if (maxDepth <= lastDepth) { + if (lastPhase.getCount() <= 0) { + retries++; + } + if (lastPhase.getCount() > 0 || retries > StabData.MAX_TICK_DIFFERENCE) { + Bukkit.getLogger().log(StabData.LEVEL, "Depth is equal to last depth recorded {0} - finished", maxDepth); + new StabFinalizer(data); + return; + } + } + lastDepth = maxDepth; + + newPhase(data, lastPhase); + run(); + } + + public static void newPhase(StabData data, TNTPhase lastPhase) { + Bukkit.getLogger().log(StabData.LEVEL, "Adding new phase in next tick"); + TNTPhase nextPhase = new TNTPhase(); + nextPhase.setCount(StabData.TNT_INCREASE); + nextPhase.setTickOffset(lastPhase.getTickOffset() + 1); + nextPhase.setXJump(lastPhase.isXJump()); + nextPhase.setYJump(lastPhase.isYJump()); + nextPhase.setZJump(lastPhase.isZJump()); + data.phases.add(nextPhase); + } + + @Override + protected void bossbar(BauSystemBossbar bossbar, boolean finished) { + bossbar.setProgress(Math.min(data.currentDepth / (double) data.depthLimit, 1.0)); + if (finished) { + bossbar.setTitle("§e" + data.currentDepth + "§8/§7" + data.depthLimit); + return; + } + + StringBuilder st = new StringBuilder(); + st.append("§7Direction §e").append(data.direction); + st.append(" §e").append(data.currentDepth).append("§8/§7").append(data.depthLimit); + if (recordings > 0) { + st.append(" §7Retries§8:§e ").append(recordings).append("§8/§7").append(StabData.MAX_RECORDINGS); + } + bossbar.setTitle(st.toString()); + } +} diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/execute/StabSetup.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/execute/StabSetup.java new file mode 100644 index 00000000..9662a638 --- /dev/null +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/execute/StabSetup.java @@ -0,0 +1,85 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem.features.simulator.execute; + +import de.steamwar.bausystem.features.simulator.data.SimulatorGroup; +import de.steamwar.bausystem.features.simulator.data.tnt.TNTElement; +import de.steamwar.bausystem.features.simulator.data.tnt.TNTPhase; +import de.steamwar.bausystem.features.tracer.TraceRecorder; +import de.steamwar.bausystem.utils.FlatteningWrapper; +import de.steamwar.bausystem.utils.bossbar.BauSystemBossbar; + +import java.util.Comparator; +import java.util.List; +import java.util.Optional; + +public class StabSetup extends StabStep { + + public StabSetup(StabData data) { + super(data); + } + + @Override + protected void start() { + TNTPhase tntPhase = data.simulator.getGroups().stream() + .filter(simulatorGroup -> !simulatorGroup.isDisabled()) + .map(SimulatorGroup::getElements) + .flatMap(List::stream) + .filter(TNTElement.class::isInstance) + .map(TNTElement.class::cast) + .filter(tntElement -> !tntElement.isDisabled()) + .filter(tntElement -> data.tntElement != tntElement) + .map(tntElement -> tntElement.getPhases().stream().max(Comparator.comparingInt(TNTPhase::getTickOffset))) + .filter(Optional::isPresent) + .map(Optional::get) + .peek(phase -> { + if (phase.getOrder() > TNTPhase.ORDER_LIMIT) { + phase.setOrder(TNTPhase.ORDER_LIMIT); + } + }) + .filter(phase -> phase != data.phases.get(0)) + .max(Comparator.comparingInt(TNTPhase::getTickOffset)) + .orElse(null); + if (tntPhase == null) { + throw new SecurityException(""); + } + + TNTPhase phase = data.phases.get(0); + data.phases.clear(); + data.phases.add(phase); + phase.setCount(1); + phase.setTickOffset(tntPhase.getTickOffset()); + phase.setOrder(100); + + TraceRecorder.instance.stopRecording(data.region); + if (TraceRecorder.instance.isAutoTraceEnabledInRegion(data.region)) { + TraceRecorder.instance.removeAutoTraceRegion(data.region); + } + data.clipboard = FlatteningWrapper.impl.copy(data.region.getMinPointTestblockExtension(), data.region.getMaxPointTestblockExtension(), data.region.getTestBlockPoint()); + + new StabDirection(data); + } + + @Override + protected void bossbar(BauSystemBossbar bossbar, boolean finished) { + bossbar.setProgress(0); + bossbar.setTitle("§eSetting up Simulator"); + } +} diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/execute/StabStep.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/execute/StabStep.java new file mode 100644 index 00000000..ad0d05ee --- /dev/null +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/execute/StabStep.java @@ -0,0 +1,95 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem.features.simulator.execute; + +import de.steamwar.bausystem.BauSystem; +import de.steamwar.bausystem.features.simulator.SimulatorWatcher; +import de.steamwar.bausystem.utils.bossbar.BauSystemBossbar; +import de.steamwar.bausystem.utils.bossbar.BossBarService; +import org.bukkit.Bukkit; +import org.bukkit.boss.BarColor; +import org.bukkit.boss.BarStyle; +import org.bukkit.entity.Player; +import org.bukkit.event.HandlerList; +import org.bukkit.event.Listener; + +public abstract class StabStep { + + protected final StabData data; + + protected StabStep(StabData data) { + this.data = data; + run(); + } + + protected final void run() { + Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> { + for (Player player : Bukkit.getOnlinePlayers()) { + BauSystemBossbar bossbar = BossBarService.instance.get(player, data.region, "simulator_stab_generator"); + bossbar.setColor(BarColor.GREEN); + bossbar.setStyle(BarStyle.SEGMENTED_10); + bossbar(bossbar, false); + } + }, 1); + + if (this instanceof Listener) { + Bukkit.getPluginManager().registerEvents((Listener) this, BauSystem.getInstance()); + } + Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), this::start, 20); + } + + protected abstract void start(); + + protected final void runSimulator(Runnable onFinish) { + SimulatorExecutor.run(data.simulator, () -> { + Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> { + if (this instanceof Listener) { + HandlerList.unregisterAll((Listener) this); + } + onFinish.run(); + }, 20); + }); + } + + protected abstract void bossbar(BauSystemBossbar bossbar, boolean stopped); + + protected final void stop() { + data.simulator.setStabGenerator(null); + SimulatorWatcher.update(data.simulator); + + for (Player player : Bukkit.getOnlinePlayers()) { + BauSystemBossbar bossbar = BossBarService.instance.get(player, data.region, "simulator_stab_generator"); + bossbar.setColor(BarColor.GREEN); + bossbar.setStyle(BarStyle.SEGMENTED_10); + bossbar(bossbar, true); + } + new Thread(() -> { + try { + Thread.sleep(4000); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } finally { + for (Player player : Bukkit.getOnlinePlayers()) { + BossBarService.instance.remove(player, data.region, "simulator_stab_generator"); + } + } + }).start(); + } +} diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/SimulatorTNTGui.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/SimulatorTNTGui.java index a9c178ce..3520720e 100644 --- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/SimulatorTNTGui.java +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/SimulatorTNTGui.java @@ -24,8 +24,11 @@ import de.steamwar.bausystem.features.simulator.data.Simulator; import de.steamwar.bausystem.features.simulator.data.SimulatorGroup; import de.steamwar.bausystem.features.simulator.data.tnt.TNTElement; import de.steamwar.bausystem.features.simulator.data.tnt.TNTPhase; +import de.steamwar.bausystem.features.simulator.execute.SimulatorStabGenerator; +import de.steamwar.bausystem.features.simulator.gui.base.SimulatorAnvilGui; import de.steamwar.bausystem.features.simulator.gui.base.SimulatorBaseGui; import de.steamwar.bausystem.features.simulator.gui.base.SimulatorScrollGui; +import de.steamwar.bausystem.region.Region; import de.steamwar.inventory.SWItem; import org.bukkit.Material; import org.bukkit.entity.Player; @@ -97,6 +100,14 @@ public class SimulatorTNTGui extends SimulatorScrollGui { tnt.setDisabled(!tnt.isDisabled()); SimulatorWatcher.update(simulator); })); + inventory.setItem(49, new SWItem(Material.CALIBRATED_SCULK_SENSOR, "§eCreate Stab", click -> { + new SimulatorAnvilGui<>(player, "Depth Limit", "", Integer::parseInt, depthLimit -> { + if (depthLimit <= 0) return false; + simulator.setStabGenerator(new SimulatorStabGenerator(Region.getRegion(player.getLocation()), simulator, tnt, depthLimit)); + SimulatorWatcher.update(simulator); + return true; + }, null).open(); + })); inventory.setItem(50, new SWItem(Material.CHEST, parent.getElements().size() == 1 ? "§eMake Group" : "§eAdd another TNT to Group", clickType -> { TNTElement tntElement = new TNTElement(tnt.getPosition().clone()); tntElement.add(new TNTPhase()); diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/base/SimulatorAnvilGui.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/base/SimulatorAnvilGui.java index 380dc618..e22c807a 100644 --- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/base/SimulatorAnvilGui.java +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/base/SimulatorAnvilGui.java @@ -44,7 +44,7 @@ public class SimulatorAnvilGui { if (error.get()) { anvilInv.open(); } else { - back.open(); + if (back != null) back.open(); } error.set(false); }, 0); diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/base/SimulatorBaseGui.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/base/SimulatorBaseGui.java index 6fa35d4c..aeb4da13 100644 --- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/base/SimulatorBaseGui.java +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/base/SimulatorBaseGui.java @@ -22,7 +22,6 @@ package de.steamwar.bausystem.features.simulator.gui.base; import de.steamwar.bausystem.features.simulator.SimulatorWatcher; import de.steamwar.bausystem.features.simulator.data.Simulator; import de.steamwar.core.Core; -import de.steamwar.core.TrickyTrialsWrapper; import de.steamwar.inventory.SWInventory; import de.steamwar.inventory.SWItem; import org.bukkit.Bukkit; @@ -64,7 +63,11 @@ public abstract class SimulatorBaseGui { if (Core.getVersion() > 19) { player.getOpenInventory().setTitle(title()); } - populate(); + if (simulator != null && simulator.getStabGenerator() != null) { + populateStabGenerator(); + } else { + populate(); + } if (player.getOpenInventory().getTopInventory() == inv) { inventory.open(); SimulatorWatcher.watch(player, simulator, this::open); @@ -84,10 +87,21 @@ public abstract class SimulatorBaseGui { }); SimulatorWatcher.watch(player, simulator, this::open); - populate(); + if (simulator != null && simulator.getStabGenerator() != null) { + populateStabGenerator(); + } else { + populate(); + } inventory.open(); } + private void populateStabGenerator() { + inventory.setItem(22, new SWItem(Material.BARRIER, "§cCancel Stab Generator", click -> { + simulator.getStabGenerator().cancel(); + SimulatorWatcher.update(simulator); + })); + } + public boolean shouldOpen() { return true; } diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/panzern/Panzern.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/panzern/Panzern.java index 3eca97f4..2823beb0 100644 --- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/panzern/Panzern.java +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/panzern/Panzern.java @@ -25,6 +25,7 @@ import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockTypes; import de.steamwar.bausystem.utils.WorldEditUtils; +import de.steamwar.core.Core; import lombok.Getter; import lombok.SneakyThrows; import org.bukkit.Location; @@ -56,7 +57,7 @@ public class Panzern { private BaseBlock blockType; private BaseBlock slabType; - private static final BaseBlock jukeboxType = BlockTypes.JUKEBOX.getDefaultState().toBaseBlock(); + private static final BaseBlock jukeboxType = (Core.getVersion() > 19 ? BlockTypes.get("lodestone"): BlockTypes.get("jukebox")).getDefaultState().toBaseBlock(); private static final BaseBlock cobwebType = BlockTypes.COBWEB.getDefaultState().toBaseBlock(); private static final BaseBlock airType = BlockTypes.AIR.getDefaultState().toBaseBlock(); diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/smartplace/SmartPlaceListener.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/smartplace/SmartPlaceListener.java index 75b3f8b7..17e0d9f3 100644 --- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/smartplace/SmartPlaceListener.java +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/smartplace/SmartPlaceListener.java @@ -19,8 +19,8 @@ package de.steamwar.bausystem.features.smartplace; -import de.steamwar.Reflection; import com.comphenix.tinyprotocol.TinyProtocol; +import de.steamwar.Reflection; import de.steamwar.bausystem.BauSystem; import de.steamwar.bausystem.Permission; import de.steamwar.bausystem.configplayer.Config; @@ -223,7 +223,7 @@ public class SmartPlaceListener implements Listener { Block block = event.getBlock().getRelative(BlockFace.DOWN); BlockState old = block.getState(); Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> { - block.setType(Material.GLASS); + block.setType(Material.GLASS, true); old.update(true, false); }, 1); } diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/TPSCommand.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/TPSCommand.java index 1b5b51eb..c1d09c63 100644 --- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/TPSCommand.java +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/TPSCommand.java @@ -42,16 +42,16 @@ public class TPSCommand extends SWCommand { public void genericCommand(Player p, String... args) { BauSystem.MESSAGE.sendPrefixless("OTHER_TPS_HEAD", p); BauSystem.MESSAGE.sendPrefixless("OTHER_TPS_MESSAGE", p, - TPSWatcher.getTPS(TPSWatcher.TPSType.ONE_SECOND), - TPSWatcher.getTPS(TPSWatcher.TPSType.TEN_SECONDS), - TPSWatcher.getTPS(TPSWatcher.TPSType.ONE_MINUTE), - TPSWatcher.getTPS(TPSWatcher.TPSType.FIVE_MINUTES), - TPSWatcher.getTPS(TPSWatcher.TPSType.TEN_MINUTES) + TPSWatcher.getTPSUnlimited(TPSWatcher.TPSType.ONE_SECOND), + TPSWatcher.getTPSUnlimited(TPSWatcher.TPSType.TEN_SECONDS), + TPSWatcher.getTPSUnlimited(TPSWatcher.TPSType.ONE_MINUTE), + TPSWatcher.getTPSUnlimited(TPSWatcher.TPSType.FIVE_MINUTES), + TPSWatcher.getTPSUnlimited(TPSWatcher.TPSType.TEN_MINUTES) ); } @Register public void genericCommand(Player p, TPSWatcher.TPSType type) { - BauSystem.MESSAGE.sendPrefixless("OTHER_TPS_SINGLE", p, tpsSystem.getTPS(type)); + BauSystem.MESSAGE.sendPrefixless("OTHER_TPS_SINGLE", p, TPSWatcher.getTPSUnlimited(type)); } } diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/TPSSystem.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/TPSSystem.java index 1e25ff18..ac393e57 100644 --- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/TPSSystem.java +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/TPSSystem.java @@ -56,11 +56,7 @@ import java.util.Arrays; public class TPSSystem implements Listener { @Getter - private double currentTPSLimit = 20; - - public double getTPS(TPSWatcher.TPSType tpsType) { - return TPSWatcher.getTPSUnlimited(tpsType); - } + private static double currentTPSLimit = 20; public TPSSystem() { if (TPSFreezeUtils.isCanFreeze()) { @@ -338,26 +334,26 @@ public class TPSSystem implements Listener { } else if (TPSFreezeUtils.frozen()) { return "§e" + BauSystem.MESSAGE.parse("SCOREBOARD_TPS", p) + "§8: " + BauSystem.MESSAGE.parse("SCOREBOARD_TPS_FROZEN", p); } else { - return "§e" + BauSystem.MESSAGE.parse("SCOREBOARD_TPS", p) + "§8: " + tpsColor() + tpsSystem.getTPS(TPSWatcher.TPSType.ONE_SECOND) + tpsLimit(); + return "§e" + BauSystem.MESSAGE.parse("SCOREBOARD_TPS", p) + "§8: " + tpsColor() + TPSWatcher.getTPSUnlimited(TPSWatcher.TPSType.ONE_SECOND) + tpsLimit(); } } private String tpsColor() { - double tps = tpsSystem.getTPS(TPSWatcher.TPSType.ONE_SECOND); - if (tps > tpsSystem.getCurrentTPSLimit() * 0.9) { + double tps = TPSWatcher.getTPSUnlimited(TPSWatcher.TPSType.ONE_SECOND); + if (tps > TPSSystem.getCurrentTPSLimit() * 0.9) { return "§a"; } - if (tps > tpsSystem.getCurrentTPSLimit() * 0.5) { + if (tps > TPSSystem.getCurrentTPSLimit() * 0.5) { return "§e"; } return "§c"; } private String tpsLimit() { - if (tpsSystem.getCurrentTPSLimit() == 20) { + if (TPSSystem.getCurrentTPSLimit() == 20) { return ""; } - return "§8/§7" + tpsSystem.getCurrentTPSLimit(); + return "§8/§7" + TPSSystem.getCurrentTPSLimit(); } } diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/TraceRecorder.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/TraceRecorder.java index 6a0a2314..208b49e8 100644 --- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/TraceRecorder.java +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/TraceRecorder.java @@ -102,11 +102,14 @@ public class TraceRecorder implements Listener { * * @param region region to be recorded */ - public void startRecording(Region region) { - if (activeTraces.containsKey(region)) return; + public Trace startRecording(Region region) { + if (activeTraces.containsKey(region)) { + return activeTraces.get(region).getTrace(); + } TraceRecordingWrapper wrappedTrace = new TraceRecordingWrapper(region); activeTraces.put(region, wrappedTrace); + return wrappedTrace.getTrace(); } /** diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/rendering/TraceEntity.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/rendering/TraceEntity.java index 0f785468..75b893ab 100644 --- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/rendering/TraceEntity.java +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/rendering/TraceEntity.java @@ -20,6 +20,7 @@ package de.steamwar.bausystem.features.tracer.rendering; import de.steamwar.bausystem.BauSystem; +import de.steamwar.bausystem.configplayer.Config; import de.steamwar.bausystem.features.tracer.TNTPoint; import de.steamwar.bausystem.features.tracer.Trace; import de.steamwar.bausystem.features.tracer.TraceManager; @@ -30,10 +31,13 @@ import net.md_5.bungee.api.chat.ClickEvent; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.entity.Player; +import yapion.hierarchy.types.YAPIONValue; import java.util.List; import java.util.stream.Collectors; +import static de.steamwar.bausystem.features.util.TNTClickListener.TNT_CLICK_DETAILS; + /** * Wrapper for the rendering of a record bundle */ @@ -66,6 +70,7 @@ public class TraceEntity extends RFallingBlockEntity { * @param player the player the message should be printed for */ public void printIntoChat(Player player) { + if (!Config.getInstance().get(player).getOrSetDefault(TNT_CLICK_DETAILS, new YAPIONValue<>(true)).asBoolean().orElse(true)) return; TNTPoint representative = records.get(0); BauSystem.MESSAGE.sendPrefixless("TNT_CLICK_HEADER", player); diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/util/SkullCommand.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/util/SkullCommand.java index 1f50a2ae..e7da48d1 100644 --- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/util/SkullCommand.java +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/util/SkullCommand.java @@ -42,6 +42,15 @@ public class SkullCommand extends SWCommand { super("skull", "head"); } + @Register + public void giveCommand(@Validator Player p) { + if (p.getName().startsWith(".")) { + BauSystem.MESSAGE.send("SKULL_INVALID", p); + return; + } + giveCommand(p, p.getName()); + } + @Register(description = "SKULL_HELP") public void giveCommand(@Validator Player p, @Mapper("player") @ErrorMessage("SKULL_INVALID") String skull) { ItemStack is = SWItem.getPlayerSkull(skull).getItemStack(); @@ -63,7 +72,7 @@ public class SkullCommand extends SWCommand { @Override public List tabCompletes(CommandSender commandSender, PreviousArguments previousArguments, String s) { - return Bukkit.getOnlinePlayers().stream().map(Player::getName).filter(s1 -> !s1.endsWith("⍇")).collect(Collectors.toList()); + return Bukkit.getOnlinePlayers().stream().map(Player::getName).filter(s1 -> !s1.startsWith(".")).collect(Collectors.toList()); } }; } diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/util/TNTClickListener.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/util/TNTClickListener.java index 3284876a..f412b8ad 100644 --- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/util/TNTClickListener.java +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/util/TNTClickListener.java @@ -21,22 +21,46 @@ package de.steamwar.bausystem.features.util; import de.steamwar.bausystem.BauSystem; import de.steamwar.bausystem.Permission; +import de.steamwar.bausystem.configplayer.Config; +import de.steamwar.command.SWCommand; import de.steamwar.linkage.Linked; import org.bukkit.Bukkit; import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; import org.bukkit.entity.TNTPrimed; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerInteractEntityEvent; import org.bukkit.inventory.EquipmentSlot; +import yapion.hierarchy.types.YAPIONObject; +import yapion.hierarchy.types.YAPIONValue; @Linked -public class TNTClickListener implements Listener { +public class TNTClickListener extends SWCommand implements Listener { + + public static final String TNT_CLICK_DETAILS = "tnt_click_details"; + + public TNTClickListener() { + super("tntdetails"); + } + + @Register(description = "TNT_DETAILS_COMMAND") + public void toggle(Player player) { + YAPIONObject yapionObject = Config.getInstance().get(player); + if (yapionObject.getOrSetDefault(TNT_CLICK_DETAILS, new YAPIONValue<>(true)).asBoolean().orElse(true)) { + yapionObject.put(TNT_CLICK_DETAILS, false); + BauSystem.MESSAGE.send("TNT_DETAILS_OFF", player); + } else { + yapionObject.put(TNT_CLICK_DETAILS, true); + BauSystem.MESSAGE.send("TNT_DETAILS_ON", player); + } + } @EventHandler public void onPlayerInteractEntity(PlayerInteractEntityEvent event) { if (!Permission.BUILD.hasPermission(event.getPlayer())) return; if (event.getHand() != EquipmentSlot.HAND) return; + if (!Config.getInstance().get(event.getPlayer()).getOrSetDefault(TNT_CLICK_DETAILS, new YAPIONValue<>(true)).asBoolean().orElse(true)) return; Entity entity = event.getRightClicked(); if (event.getRightClicked() instanceof TNTPrimed) { diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/world/SpectatorListener.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/world/SpectatorListener.java index 3b3ea664..f1aed39f 100644 --- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/world/SpectatorListener.java +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/world/SpectatorListener.java @@ -179,7 +179,12 @@ public class SpectatorListener implements Listener { @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event) { - if (event.getMessage().startsWith("/schem save") || event.getMessage().startsWith("//schem save") || event.getMessage().startsWith("/schematic save") || event.getMessage().startsWith("//schematic save")) { + if (event.getMessage().startsWith("/schem save") || + event.getMessage().startsWith("//schem save") || + event.getMessage().startsWith("/schematic save") || + event.getMessage().startsWith("//schematic save") || + event.getMessage().startsWith("/download") || + event.getMessage().startsWith("//download")) { if (!Permission.SUPERVISOR.hasPermission(event.getPlayer())) { event.setCancelled(true); event.setMessage("/"); diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/region/Point.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/region/Point.java index 0fa5496e..6f8c5929 100644 --- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/region/Point.java +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/region/Point.java @@ -73,4 +73,8 @@ public class Point { public Location toLocation(Player player, double dx, double dy, double dz) { return new Location(player.getWorld(), x + dx, y + dy, z + dz, player.getLocation().getYaw(), player.getLocation().getPitch()); } + + public BlockVector3 toBlockVector3() { + return BlockVector3.at(this.x, this.y, this.z); + } } \ No newline at end of file diff --git a/BauSystem/build.gradle.kts b/BauSystem/build.gradle.kts index 712238c8..fd9dca11 100644 --- a/BauSystem/build.gradle.kts +++ b/BauSystem/build.gradle.kts @@ -34,3 +34,19 @@ dependencies { implementation(project(":BauSystem:BauSystem_20")) implementation(project(":BauSystem:BauSystem_21")) } + +tasks.register("DevBau20") { + group = "run" + description = "Run a 1.20 Dev Bau" + dependsOn(":SpigotCore:shadowJar") + dependsOn(":BauSystem:shadowJar") + template = "Bau20" +} + +tasks.register("DevBau21") { + group = "run" + description = "Run a 1.21 Dev Bau" + dependsOn(":SpigotCore:shadowJar") + dependsOn(":BauSystem:shadowJar") + template = "Bau21" +} diff --git a/BauSystem/hotkeys.lua b/BauSystem/hotkeys.lua new file mode 100644 index 00000000..f1182e7a --- /dev/null +++ b/BauSystem/hotkeys.lua @@ -0,0 +1,87 @@ +-- This file is a part of the SteamWar software. +-- +-- Copyright (C) 2025 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 . + +--- +--- This serves both as an example and a quick start to the Stewamwar Script Api +--- + +function hotkeys_freeze(pressed) + if pressed then + exec("/freeze") + end +end + +function hotkeys_rgc(pressed) + if pressed then + exec("/rgc") + end +end + +function hotkeys_rgp(pressed) + if pressed then + exec("/rgp") + end +end + +trace_cycle_counter = 0; +function hotkeys_cycle_trace_view(pressed) + if not pressed then + return + end + trace_cycle = (trace_cycle + 1) % 3 + trace_commands = {"trace hide", "trace show", "trace show -e -c"} + exec(trace_commands[trace_cycle + 1]) +end + +function hotkeys_tick_step(pressed) + if pressed then + exec("tick step") + end +end + +function hotkeys_tpslimit(pressed) + if not pressed then + return + end + if tps.limit() == 20 then + exec("tpslimit 200") + else + exec("tpslimit 20") + end +end + +function hotkeys_tb(pressed) + if pressed then + exec("tb -e") + end +end + +function hotkeys_trace_delete(pressed) + if pressed then + exec("trace delete") + end +end + +hotkey("ctrl+g", hotkeys_freeze) +hotkey("ctrl+c", hotkeys_rgc) +hotkey("ctrl+v", hotkeys_rgp) +hotkey("ctrl+x", hotkeys_tick_step) +hotkey("shift+x", hotkeys_cycle_trace_view) +hotkey("ctrl+y", hotkeys_tb) +hotkey("ctrl+alt", hotkeys_trace_delete) +hotkey("ctrl+h", hotkeys_trace_delete) + diff --git a/BauSystem/sw.def.lua b/BauSystem/sw.def.lua index 613437a1..50095a2d 100644 --- a/BauSystem/sw.def.lua +++ b/BauSystem/sw.def.lua @@ -200,21 +200,6 @@ function tnt.onlyTb() return nil end ---@return boolean function tnt.onlyBuild() return nil end ----@class trace -local trace = {} - ----@return boolean -function trace.active() return nil end - ----@return boolean -function trace.auto() return nil end - ----@return string -function trace.status() return nil end - ----@return number -function trace.time() return nil end - ---@param name string ---@return iregion function region.get(name) return nil end @@ -222,6 +207,25 @@ function region.get(name) return nil end ---@return iregion[] function region.list() return nil end +---@class tracerLib +tracer = {} + +---@class TraceRecord +---@field pos Position +---@field vel Position +---@field ticksSinceStart number +---@field fuse number +---@field isExplosion boolean +---@field isInWater boolean +---@field hasDestroyedBuild boolean +---@field hasDestroyedTestblock boolean + +---@class Tracer +---@field getId fun(): string +---@field getRecords fun(): {[number]: {[number]: TraceRecord}} + +function tracer.getTraces() return nil end + ---@class Position ---@field x number ---@field y number diff --git a/CommonCore/SQL/src/de/steamwar/sql/NodeData.java b/CommonCore/SQL/src/de/steamwar/sql/NodeData.java index a8d7c099..08179979 100644 --- a/CommonCore/SQL/src/de/steamwar/sql/NodeData.java +++ b/CommonCore/SQL/src/de/steamwar/sql/NodeData.java @@ -30,7 +30,6 @@ import java.util.zip.GZIPInputStream; @AllArgsConstructor @Getter public class NodeData { - static { new SqlTypeMapper<>(PipedInputStream.class, "BLOB", (rs, identifier) -> { throw new SecurityException("PipedInputStream is write only datatype"); }, PreparedStatement::setBinaryStream); new SqlTypeMapper<>(ByteArrayInputStream.class, "BLOB", (rs, identifier) -> { throw new SecurityException("ByteArrayInputStream is write only datatype"); }, PreparedStatement::setBinaryStream); diff --git a/CommonCore/SQL/src/de/steamwar/sql/NodeDownload.java b/CommonCore/SQL/src/de/steamwar/sql/NodeDownload.java index 71cf83f4..b56a5994 100644 --- a/CommonCore/SQL/src/de/steamwar/sql/NodeDownload.java +++ b/CommonCore/SQL/src/de/steamwar/sql/NodeDownload.java @@ -1,7 +1,7 @@ /* * This file is a part of the SteamWar software. * - * Copyright (C) 2021 SteamWar.de-Serverteam + * Copyright (C) 2025 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 diff --git a/CommonCore/SQL/src/de/steamwar/sql/SchematicNode.java b/CommonCore/SQL/src/de/steamwar/sql/SchematicNode.java index bece8549..87b7cac4 100644 --- a/CommonCore/SQL/src/de/steamwar/sql/SchematicNode.java +++ b/CommonCore/SQL/src/de/steamwar/sql/SchematicNode.java @@ -31,10 +31,13 @@ public class SchematicNode { static { SchematicType.Normal.name(); // Ensure SchematicType is loaded. - new SqlTypeMapper<>(SchematicNode.class, null, (rs, identifier) -> { throw new SecurityException("SchematicNode cannot be used as type (recursive select)"); }, (st, index, value) -> st.setInt(index, value.nodeId)); + new SqlTypeMapper<>(SchematicNode.class, null, (rs, identifier) -> { + throw new SecurityException("SchematicNode cannot be used as type (recursive select)"); + }, (st, index, value) -> st.setInt(index, value.nodeId)); } private static final Map>> TAB_CACHE = new HashMap<>(); + public static void clear() { TAB_CACHE.clear(); } @@ -42,39 +45,60 @@ public class SchematicNode { private static final String nodeSelector = "SELECT NodeId, NodeOwner, NodeOwner AS EffectiveOwner, NodeName, ParentNode, LastUpdate, NodeItem, NodeType, NodeRank, ReplaceColor, AllowReplay FROM SchematicNode "; private static final Table table = new Table<>(SchematicNode.class); - private static final Statement create = table.insertFields(true, "NodeOwner", "NodeName", "ParentNode", "NodeItem", "NodeType"); - private static final Statement update = table.update(Table.PRIMARY, "NodeName", "ParentNode", "NodeItem", "NodeType", "NodeRank", "ReplaceColor", "AllowReplay"); + private static final Statement create = table.insertFields(true, "NodeOwner", "NodeName", "ParentNode", "NodeItem", + "NodeType"); + private static final Statement update = table.update(Table.PRIMARY, "NodeName", "ParentNode", "NodeItem", + "NodeType", "NodeRank", "ReplaceColor", "AllowReplay"); private static final Statement delete = table.delete(Table.PRIMARY); - private static final SelectStatement byId = new SelectStatement<>(table, nodeSelector + "WHERE NodeId = ?"); - private static final SelectStatement byOwnerNameParent = new SelectStatement<>(table, nodeSelector + "WHERE NodeOwner = ? AND NodeName = ? AND ParentNode " + Statement.NULL_SAFE_EQUALS + "?"); - private static final SelectStatement byParent = new SelectStatement<>(table, nodeSelector + "WHERE ParentNode" + Statement.NULL_SAFE_EQUALS + "? ORDER BY NodeName"); - private static final SelectStatement dirsByParent = new SelectStatement<>(table, nodeSelector + "WHERE ParentNode" + Statement.NULL_SAFE_EQUALS + "? AND NodeType is NULL ORDER BY NodeName"); - private static final SelectStatement byOwnerType = new SelectStatement<>(table, nodeSelector + "WHERE NodeOwner = ? AND NodeType = ? ORDER BY NodeName"); - private static final SelectStatement byType = new SelectStatement<>(table, nodeSelector + "WHERE NodeType = ? ORDER BY NodeName"); - private static final SelectStatement all = new SelectStatement<>(table, "SELECT * FROM EffectiveSchematicNode WHERE EffectiveOwner = ? ORDER BY NodeName"); - private static final SelectStatement list = new SelectStatement<>(table, "SELECT SchematicNode.NodeId, NodeOwner, ? AS EffectiveOwner, NodeName, NM.ParentId AS ParentNode, LastUpdate, NodeItem, NodeType, NodeRank, ReplaceColor, AllowReplay FROM SchematicNode INNER JOIN NodeMember NM on SchematicNode.NodeId = NM.NodeId WHERE NM.ParentId " + Statement.NULL_SAFE_EQUALS + "? AND NM.UserId = ? UNION ALL SELECT SchematicNode.NodeId, NodeOwner, ? AS EffectiveOwner, NodeName, ParentNode, LastUpdate, NodeItem, NodeType, NodeRank, ReplaceColor, AllowReplay FROM SchematicNode WHERE (? IS NULL AND ParentNode IS NULL AND NodeOwner = ?) OR (? IS NOT NULL AND ParentNode = ?) ORDER BY NodeName"); - private static final SelectStatement byParentName = new SelectStatement<>(table, "SELECT SchematicNode.NodeId, NodeOwner, ? AS EffectiveOwner, NodeName, NM.ParentId AS ParentNode, LastUpdate, NodeItem, NodeType, NodeRank, ReplaceColor, AllowReplay FROM SchematicNode INNER JOIN NodeMember NM on SchematicNode.NodeId = NM.NodeId WHERE NM.ParentId " + Statement.NULL_SAFE_EQUALS + "? AND NM.UserId = ? AND SchematicNode.NodeName = ? UNION ALL SELECT SchematicNode.NodeId, NodeOwner, ? AS EffectiveOwner, NodeName, ParentNode, LastUpdate, NodeItem, NodeType, NodeRank, ReplaceColor, AllowReplay FROM SchematicNode WHERE ((? IS NULL AND ParentNode IS NULL AND NodeOwner = ?) OR (? IS NOT NULL AND ParentNode = ?)) AND NodeName = ?"); - private static final SelectStatement schematicAccessibleForUser = new SelectStatement<>(table, "SELECT COUNT(DISTINCT NodeId) FROM EffectiveSchematicNode WHERE EffectiveOwner = ? AND NodeId = ?"); - private static final SelectStatement accessibleByUserTypeInParent = new SelectStatement<>(table, "WITH RECURSIVE RSASN AS(WITH RECURSIVE RSAN AS (WITH RSANH AS (WITH RECURSIVE RSA AS (SELECT SN.NodeId, NM.ParentId FROM SchematicNode SN LEFT JOIN NodeMember NM on SN.NodeId = NM.NodeId WHERE NM.UserId = ? UNION SELECT SN.NodeId, SN.ParentNode FROM SchematicNode SN INNER JOIN RSA ON RSA.NodeId = SN.ParentNode) SELECT * FROM RSA UNION SELECT NodeId, ParentNode FROM SchematicNode WHERE NodeOwner = ?) SELECT * FROM RSANH UNION SELECT SN.NodeId, SN.ParentNode FROM RSANH JOIN SchematicNode SN ON SN.ParentNode = RSANH.NodeId) SELECT RSAN.NodeId, RSAN.ParentId FROM RSAN JOIN SchematicNode SN ON SN.NodeId = RSAN.NodeId WHERE NodeType = ? UNION SELECT SN.NodeId, SN.ParentNode FROM SchematicNode SN JOIN RSASN ON SN.NodeId = RSASN.ParentId) SELECT SN.*, ? as EffectiveOwner, RSASN.ParentId AS ParentNode FROM RSASN JOIN SchematicNode SN ON SN.NodeId = RSASN.NodeId WHERE RSASN.ParentId" + Statement.NULL_SAFE_EQUALS + "? ORDER BY NodeName"); - private static final SelectStatement accessibleByUserType = new SelectStatement<>(table, "WITH RECURSIVE Nodes AS (SELECT NodeId, ParentId as ParentNode FROM NodeMember WHERE UserId = ? UNION SELECT NodeId, ParentNode FROM SchematicNode WHERE NodeOwner = ?), RSN AS ( SELECT NodeId, ParentNode FROM Nodes UNION SELECT SN.NodeId, SN.ParentNode FROM SchematicNode SN, RSN WHERE SN.ParentNode = RSN.NodeId ) SELECT SN.*, ? AS EffectiveOwner FROM RSN INNER JOIN SchematicNode SN ON RSN.NodeId = SN.NodeId WHERE NodeType = ?"); - private static final SelectStatement byIdAndUser = new SelectStatement<>(table, "SELECT NodeId, NodeOwner, ? AS EffectiveOwner, NodeName, ParentNode, LastUpdate, NodeItem, NodeType, NodeRank, ReplaceColor, AllowReplay FROM SchematicNode WHERE NodeId = ?"); - private static final SelectStatement allParentsOfNode = new SelectStatement<>(table, "WITH RECURSIVE R AS (SELECT NodeId, ParentNode FROM EffectiveSchematicNode WHERE NodeId = ? AND EffectiveOwner = ? UNION SELECT E.NodeId, E.ParentNode FROM R, EffectiveSchematicNode E WHERE R.ParentNode = E.NodeId AND E.EffectiveOwner = ?) SELECT SN.NodeId, SN.NodeOwner, ? AS EffectiveOwner, SN.NodeName, R.ParentNode, SN.LastUpdate, SN.NodeItem, SN.NodeType, SN.NodeRank, SN.ReplaceColor, SN.AllowReplay FROM R INNER JOIN SchematicNode SN ON SN.NodeId = R.NodeId"); + private static final SelectStatement byId = new SelectStatement<>(table, + nodeSelector + "WHERE NodeId = ?"); + private static final SelectStatement byOwnerNameParent = new SelectStatement<>(table, + nodeSelector + "WHERE NodeOwner = ? AND NodeName = ? AND ParentNode " + Statement.NULL_SAFE_EQUALS + "?"); + private static final SelectStatement byParent = new SelectStatement<>(table, + nodeSelector + "WHERE ParentNode" + Statement.NULL_SAFE_EQUALS + "? ORDER BY NodeName"); + private static final SelectStatement dirsByParent = new SelectStatement<>(table, nodeSelector + + "WHERE ParentNode" + Statement.NULL_SAFE_EQUALS + "? AND NodeType is NULL ORDER BY NodeName"); + private static final SelectStatement byOwnerType = new SelectStatement<>(table, + nodeSelector + "WHERE NodeOwner = ? AND NodeType = ? ORDER BY NodeName"); + private static final SelectStatement byType = new SelectStatement<>(table, + nodeSelector + "WHERE NodeType = ? ORDER BY NodeName"); + private static final SelectStatement all = new SelectStatement<>(table, + "WITH RECURSIVE Nodes AS (SELECT NodeId, ParentId as ParentNode FROM NodeMember WHERE UserId = ? UNION SELECT NodeId, ParentNode FROM SchematicNode WHERE NodeOwner = ?), RSN AS ( SELECT NodeId, ParentNode FROM Nodes UNION SELECT SN.NodeId, SN.ParentNode FROM SchematicNode SN, RSN WHERE SN.ParentNode = RSN.NodeId ) SELECT SN.*, ? AS EffectiveOwner FROM RSN INNER JOIN SchematicNode SN ON RSN.NodeId = SN.NodeId"); + private static final SelectStatement list = new SelectStatement<>(table, + "SELECT SchematicNode.NodeId, NodeOwner, ? AS EffectiveOwner, NodeName, NM.ParentId AS ParentNode, LastUpdate, NodeItem, NodeType, NodeRank, ReplaceColor, AllowReplay FROM SchematicNode INNER JOIN NodeMember NM on SchematicNode.NodeId = NM.NodeId WHERE NM.ParentId " + + Statement.NULL_SAFE_EQUALS + + "? AND NM.UserId = ? UNION ALL SELECT SchematicNode.NodeId, NodeOwner, ? AS EffectiveOwner, NodeName, ParentNode, LastUpdate, NodeItem, NodeType, NodeRank, ReplaceColor, AllowReplay FROM SchematicNode WHERE (? IS NULL AND ParentNode IS NULL AND NodeOwner = ?) OR (? IS NOT NULL AND ParentNode = ?) ORDER BY NodeName"); + private static final SelectStatement byParentName = new SelectStatement<>(table, + "SELECT SchematicNode.NodeId, NodeOwner, ? AS EffectiveOwner, NodeName, NM.ParentId AS ParentNode, LastUpdate, NodeItem, NodeType, NodeRank, ReplaceColor, AllowReplay FROM SchematicNode INNER JOIN NodeMember NM on SchematicNode.NodeId = NM.NodeId WHERE NM.ParentId " + + Statement.NULL_SAFE_EQUALS + + "? AND NM.UserId = ? AND SchematicNode.NodeName = ? UNION ALL SELECT SchematicNode.NodeId, NodeOwner, ? AS EffectiveOwner, NodeName, ParentNode, LastUpdate, NodeItem, NodeType, NodeRank, ReplaceColor, AllowReplay FROM SchematicNode WHERE ((? IS NULL AND ParentNode IS NULL AND NodeOwner = ?) OR (? IS NOT NULL AND ParentNode = ?)) AND NodeName = ?"); + private static final SelectStatement schematicAccessibleForUser = new SelectStatement<>(table, + "WITH RECURSIVE Nodes AS (SELECT NodeId, ParentId as ParentNode FROM NodeMember WHERE UserId = ? UNION SELECT NodeId, ParentNode FROM SchematicNode WHERE NodeOwner = ?), RSN AS ( SELECT NodeId, ParentNode FROM Nodes UNION SELECT SN.NodeId, SN.ParentNode FROM SchematicNode SN, RSN WHERE SN.ParentNode = RSN.NodeId ) SELECT SN.*, ? AS EffectiveOwner FROM RSN INNER JOIN SchematicNode SN ON RSN.NodeId = SN.NodeId WHERE NodeId = ?"); + private static final SelectStatement accessibleByUserTypeInParent = new SelectStatement<>(table, + "WITH RECURSIVE RSASN AS(WITH RECURSIVE RSAN AS (WITH RSANH AS (WITH RECURSIVE RSA AS (SELECT SN.NodeId, NM.ParentId FROM SchematicNode SN LEFT JOIN NodeMember NM on SN.NodeId = NM.NodeId WHERE NM.UserId = ? UNION SELECT SN.NodeId, SN.ParentNode FROM SchematicNode SN INNER JOIN RSA ON RSA.NodeId = SN.ParentNode) SELECT * FROM RSA UNION SELECT NodeId, ParentNode FROM SchematicNode WHERE NodeOwner = ?) SELECT * FROM RSANH UNION SELECT SN.NodeId, SN.ParentNode FROM RSANH JOIN SchematicNode SN ON SN.ParentNode = RSANH.NodeId) SELECT RSAN.NodeId, RSAN.ParentId FROM RSAN JOIN SchematicNode SN ON SN.NodeId = RSAN.NodeId WHERE NodeType = ? UNION SELECT SN.NodeId, SN.ParentNode FROM SchematicNode SN JOIN RSASN ON SN.NodeId = RSASN.ParentId) SELECT SN.*, ? as EffectiveOwner, RSASN.ParentId AS ParentNode FROM RSASN JOIN SchematicNode SN ON SN.NodeId = RSASN.NodeId WHERE RSASN.ParentId" + + Statement.NULL_SAFE_EQUALS + "? ORDER BY NodeName"); + private static final SelectStatement accessibleByUserType = new SelectStatement<>(table, + "WITH RECURSIVE Nodes AS (SELECT NodeId, ParentId as ParentNode FROM NodeMember WHERE UserId = ? UNION SELECT NodeId, ParentNode FROM SchematicNode WHERE NodeOwner = ?), RSN AS ( SELECT NodeId, ParentNode FROM Nodes UNION SELECT SN.NodeId, SN.ParentNode FROM SchematicNode SN, RSN WHERE SN.ParentNode = RSN.NodeId ) SELECT SN.*, ? AS EffectiveOwner FROM RSN INNER JOIN SchematicNode SN ON RSN.NodeId = SN.NodeId WHERE NodeType = ?"); + private static final SelectStatement byIdAndUser = new SelectStatement<>(table, + "SELECT NodeId, NodeOwner, ? AS EffectiveOwner, NodeName, ParentNode, LastUpdate, NodeItem, NodeType, NodeRank, ReplaceColor, AllowReplay FROM SchematicNode WHERE NodeId = ?"); + private static final SelectStatement allParentsOfNode = new SelectStatement<>(table, + "WITH RECURSIVE R AS (SELECT NodeId, ParentNode FROM EffectiveSchematicNode WHERE NodeId = ? AND EffectiveOwner = ? UNION SELECT E.NodeId, E.ParentNode FROM R, EffectiveSchematicNode E WHERE R.ParentNode = E.NodeId AND E.EffectiveOwner = ?) SELECT SN.NodeId, SN.NodeOwner, ? AS EffectiveOwner, SN.NodeName, R.ParentNode, SN.LastUpdate, SN.NodeItem, SN.NodeType, SN.NodeRank, SN.ReplaceColor, SN.AllowReplay FROM R INNER JOIN SchematicNode SN ON SN.NodeId = R.NodeId"); static { NodeMember.init(); } - @Field(keys = {Table.PRIMARY}, autoincrement = true) + @Field(keys = { Table.PRIMARY }, autoincrement = true) private final int nodeId; - @Field(keys = {"OwnerNameParent"}) + @Field(keys = { "OwnerNameParent" }) private final int nodeOwner; @Field(def = "0") @Getter private final int effectiveOwner; - @Field(keys = {"OwnerNameParent"}) + @Field(keys = { "OwnerNameParent" }) private String nodeName; - @Field(keys = {"OwnerNameParent"}, nullable = true) + @Field(keys = { "OwnerNameParent" }, nullable = true) private Integer parentNode; @Field(def = "CURRENT_TIMESTAMP") private Timestamp lastUpdate; @@ -102,8 +126,7 @@ public class SchematicNode { SchematicType nodeType, int nodeRank, boolean replaceColor, - boolean allowReplay - ) { + boolean allowReplay) { this.nodeId = nodeId; this.nodeOwner = nodeOwner; this.effectiveOwner = effectiveOwner; @@ -118,7 +141,7 @@ public class SchematicNode { } public static List getAll(SteamwarUser user) { - return all.listSelect(user); + return all.listSelect(user, user, user); } public static Map> getAllMap(SteamwarUser user) { @@ -130,7 +153,8 @@ public class SchematicNode { } public static SchematicNode byParentName(SteamwarUser user, Integer schematicId, String name) { - return byParentName.select(user, schematicId, user, name, user, schematicId, user, schematicId, schematicId, name); + return byParentName.select(user, schematicId, user, name, user, schematicId, user, schematicId, schematicId, + name); } public static List accessibleByUserType(SteamwarUser user, SchematicType type) { @@ -142,10 +166,11 @@ public class SchematicNode { } public static boolean schematicAccessibleForUser(SteamwarUser user, Integer schematicId) { - return schematicAccessibleForUser.select(user, schematicId) != null; + return schematicAccessibleForUser.select(user, user, user, schematicId) != null; } - public static List accessibleByUserTypeParent(SteamwarUser user, SchematicType type, Integer parentId) { + public static List accessibleByUserTypeParent(SteamwarUser user, SchematicType type, + Integer parentId) { return accessibleByUserTypeInParent.listSelect(user, user, type, user, parentId); } @@ -160,7 +185,8 @@ public class SchematicNode { private static Map> map(List in) { Map> map = new HashMap<>(); for (SchematicNode effectiveSchematicNode : in) { - map.computeIfAbsent(effectiveSchematicNode.getOptionalParent().orElse(0), k -> new ArrayList<>()).add(effectiveSchematicNode); + map.computeIfAbsent(effectiveSchematicNode.getOptionalParent().orElse(0), k -> new ArrayList<>()) + .add(effectiveSchematicNode); } return map; } @@ -218,7 +244,8 @@ public class SchematicNode { return byId.select(id); } - public static List getAccessibleSchematicsOfTypeInParent(int owner, String schemType, Integer parent) { + public static List getAccessibleSchematicsOfTypeInParent(int owner, String schemType, + Integer parent) { return accessibleByUserTypeParent(SteamwarUser.get(owner), SchematicType.fromDB(schemType), parent); } @@ -283,10 +310,12 @@ public class SchematicNode { } if (s.contains("/")) { String[] layers = s.split("/"); - Optional currentNode = Optional.ofNullable(SchematicNode.byParentName(user, null, layers[0])); + Optional currentNode = Optional + .ofNullable(SchematicNode.byParentName(user, null, layers[0])); for (int i = 1; i < layers.length; i++) { int finalI = i; - Optional node = currentNode.map(effectiveSchematicNode -> SchematicNode.byParentName(user, effectiveSchematicNode.getId(), layers[finalI])); + Optional node = currentNode.map(effectiveSchematicNode -> SchematicNode + .byParentName(user, effectiveSchematicNode.getId(), layers[finalI])); if (!node.isPresent()) { return null; } else { @@ -365,7 +394,7 @@ public class SchematicNode { @Deprecated public void setType(String type) { - if(isDir()) + if (isDir()) throw new SecurityException("Node is Directory"); this.nodeType = SchematicType.fromDB(type); updateDB(); @@ -376,13 +405,13 @@ public class SchematicNode { } public String getFileEnding() { - if(isDir()) + if (isDir()) throw new SecurityException("Node is Directory"); return NodeData.get(this).getNodeFormat().getFileEnding(); } public int getRank() { - if(isDir()) + if (isDir()) throw new SecurityException("Node is Directory"); return nodeRank; } @@ -393,19 +422,19 @@ public class SchematicNode { } public void setRank(int rank) { - if(isDir()) + if (isDir()) throw new SecurityException("Node is Directory"); this.nodeRank = rank; } public SchematicType getSchemtype() { - if(isDir()) + if (isDir()) throw new SecurityException("Is Directory"); return nodeType; } public void setSchemtype(SchematicType type) { - if(isDir()) + if (isDir()) throw new SecurityException("Is Directory"); this.nodeType = type; updateDB(); @@ -416,7 +445,7 @@ public class SchematicNode { } public void setReplaceColor(boolean replaceColor) { - if(isDir()) + if (isDir()) throw new SecurityException("Is Directory"); this.replaceColor = replaceColor; updateDB(); @@ -427,14 +456,15 @@ public class SchematicNode { } public void setAllowReplay(boolean allowReplay) { - if(isDir()) + if (isDir()) throw new SecurityException("Is Directory"); this.allowReplay = allowReplay; updateDB(); } public SchematicNode getParentNode() { - if(parentNode == null) return null; + if (parentNode == null) + return null; return SchematicNode.getSchematicNode(parentNode); } @@ -486,7 +516,7 @@ public class SchematicNode { } public String generateBreadcrumbs() { - if(brCache == null) { + if (brCache == null) { brCache = generateBreadcrumbs("/"); } return brCache; @@ -495,11 +525,15 @@ public class SchematicNode { public String generateBreadcrumbs(String split) { StringBuilder builder = new StringBuilder(getName()); Optional currentNode = Optional.of(this); - if(currentNode.map(SchematicNode::isDir).orElse(false)) { + if (currentNode.map(SchematicNode::isDir).orElse(false)) { builder.append(split); } while (currentNode.isPresent()) { - currentNode = currentNode.flatMap(schematicNode -> Optional.ofNullable(NodeMember.getNodeMember(schematicNode.getId(), effectiveOwner)).map(NodeMember::getParent).orElse(schematicNode.getOptionalParent())).map(SchematicNode::getSchematicNode); + currentNode = currentNode + .flatMap(schematicNode -> Optional + .ofNullable(NodeMember.getNodeMember(schematicNode.getId(), effectiveOwner)) + .map(NodeMember::getParent).orElse(schematicNode.getOptionalParent())) + .map(SchematicNode::getSchematicNode); currentNode.ifPresent(node -> builder.insert(0, split).insert(0, node.getName())); } return builder.toString(); @@ -508,17 +542,22 @@ public class SchematicNode { public List> generateBreadcrumbsMap(SteamwarUser user) { List> map = new ArrayList<>(); Optional currentNode = Optional.of(this); - if(currentNode.map(SchematicNode::isDir).orElse(false)) { + if (currentNode.map(SchematicNode::isDir).orElse(false)) { map.add(new AbstractMap.SimpleEntry<>(getName(), getId())); } while (currentNode.isPresent()) { - currentNode = currentNode.flatMap(schematicNode -> Optional.ofNullable(NodeMember.getNodeMember(schematicNode.getId(), effectiveOwner)).map(NodeMember::getParent).orElse(schematicNode.getOptionalParent())).map(SchematicNode::getSchematicNode); + currentNode = currentNode + .flatMap(schematicNode -> Optional + .ofNullable(NodeMember.getNodeMember(schematicNode.getId(), effectiveOwner)) + .map(NodeMember::getParent).orElse(schematicNode.getOptionalParent())) + .map(SchematicNode::getSchematicNode); currentNode.ifPresent(node -> map.add(0, new AbstractMap.SimpleEntry<>(node.getName(), node.getId()))); } return map; } private static final List FORBIDDEN_NAMES = Collections.unmodifiableList(Arrays.asList("public")); + public static boolean invalidSchemName(String[] layers) { for (String layer : layers) { if (layer.isEmpty()) { @@ -535,7 +574,7 @@ public class SchematicNode { layer.contains(" ")) { return true; } - if(FORBIDDEN_NAMES.contains(layer.toLowerCase())) { + if (FORBIDDEN_NAMES.contains(layer.toLowerCase())) { return true; } } @@ -549,14 +588,15 @@ public class SchematicNode { } int index = s.lastIndexOf("/"); String cacheKey = index == -1 ? "" : s.substring(0, index); - if(TAB_CACHE.containsKey(user.getId()) && TAB_CACHE.get(user.getId()).containsKey(cacheKey)) { + if (TAB_CACHE.containsKey(user.getId()) && TAB_CACHE.get(user.getId()).containsKey(cacheKey)) { return new ArrayList<>(TAB_CACHE.get(user.getId()).get(cacheKey)); } List list = new ArrayList<>(); if (s.contains("/")) { String preTab = s.substring(0, s.lastIndexOf("/") + 1); SchematicNode pa = SchematicNode.getNodeFromPath(user, preTab); - if (pa == null) return new ArrayList<>(); + if (pa == null) + return new ArrayList<>(); List nodes = SchematicNode.list(user, pa.getId()); String br = pa.generateBreadcrumbs(); nodes.forEach(node -> list.add((sws ? "/" : "") + br + node.getName() + (node.isDir() ? "/" : ""))); diff --git a/CommonCore/SQL/src/de/steamwar/sql/UserElo.java b/CommonCore/SQL/src/de/steamwar/sql/UserElo.java index 235fc302..d9876c4c 100644 --- a/CommonCore/SQL/src/de/steamwar/sql/UserElo.java +++ b/CommonCore/SQL/src/de/steamwar/sql/UserElo.java @@ -75,15 +75,7 @@ public class UserElo { public static void setElo(int userId, String gameMode, int elo) { emblemCache.remove(userId); - - int oldPlacement = getPlacement(getElo(userId, gameMode).orElse(0), gameMode); - int newPlacement = getPlacement(elo, gameMode); - gameModeUserEloCache.getOrDefault(gameMode, Collections.emptyMap()).remove(userId); - if (oldPlacement <= 3 || newPlacement <= 3) { - emblemCache.clear(); - } - setElo.update(Season.getSeason(), gameMode, userId, elo); } @@ -112,27 +104,17 @@ public class UserElo { public static String getEmblemProgression(String gameMode, int userId) { switch (getProgression(userId, gameMode)) { case -1: - return "§f/ §8∨ ∧ ∨ ∧ ∨ ∧ ❂ III II I"; + return "§8❱❱❱❱ ❂"; case 0: - return "§8/ §6∨ §8∧ ∨ ∧ ∨ ∧ ❂ III II I"; + return "§e❱§8❱❱❱ ❂"; case 1: - return "§8/ ∨ §6∧ §8∨ ∧ ∨ ∧ ❂ III II I"; + return "§e❱❱§8❱❱ ❂"; case 2: - return "§8/ ∨ ∧ §7∨ §8∧ ∨ ∧ ❂ III II I"; + return "§e❱❱❱§8❱ ❂"; case 3: - return "§8/ ∨ ∧ ∨ §7∧ §8∨ ∧ ❂ III II I"; + return "§e❱❱❱❱§8 ❂"; case 4: - return "§8/ ∨ ∧ ∨ ∧ §e∨ §8∧ ❂ III II I"; - case 5: - return "§8/ ∨ ∧ ∨ ∧ ∨ §e∧ §8❂ III II I"; - case 6: - return "§8/ ∨ ∧ ∨ ∧ ∨ ∧ §5❂ §8III II I"; - case 7: - return "§8/ ∨ ∧ ∨ ∧ ∨ ∧ ❂ §5III §8II I"; - case 8: - return "§8/ ∨ ∧ ∨ ∧ ∨ ∧ ❂ III §5II §8I"; - case 9: - return "§8/ ∨ ∧ ∨ ∧ ∨ ∧ ❂ III II §5I"; + return "§8❱❱❱❱ §5❂"; default: throw new SecurityException("Progression is not in range"); } @@ -142,19 +124,11 @@ public class UserElo { int elo = getElo(userId, gameMode).orElse(-1); if (elo < 0) return -1; - if (elo <= 100) return 0; - if (elo <= 200) return 1; - if (elo <= 400) return 2; - if (elo <= 600) return 3; - if (elo <= 900) return 4; - if (elo <= 1200) return 5; - - int placement = getPlacement(elo, gameMode); - if (placement == 1) return 9; - if (placement == 2) return 8; - if (placement == 3) return 7; - - return 6; + if (elo < 150) return 0; + if (elo < 350) return 1; + if (elo < 600) return 2; + if (elo < 900) return 3; + return 4; } public static String toEmblem(int progression) { @@ -162,25 +136,15 @@ public class UserElo { case -1: return ""; case 0: - return "§6∨ "; + return "§e❱ "; case 1: - return "§6∧ "; + return "§e❱❱ "; case 2: - return "§7∨ "; + return "§e❱❱❱ "; case 3: - return "§7∧ "; + return "§e❱❱❱❱ "; case 4: - return "§e∨ "; - case 5: - return "§e∧ "; - case 6: return "§5❂ "; - case 7: - return "§5III "; - case 8: - return "§5II "; - case 9: - return "§5I "; default: throw new SecurityException("Progression out of range"); } diff --git a/FightSystem/FightSystem_Core/build.gradle.kts b/FightSystem/FightSystem_Core/build.gradle.kts index 2f044447..93dd59c4 100644 --- a/FightSystem/FightSystem_Core/build.gradle.kts +++ b/FightSystem/FightSystem_Core/build.gradle.kts @@ -29,4 +29,5 @@ dependencies { compileOnly(libs.worldedit15) compileOnly(libs.fastutil) compileOnly(libs.authlib) + compileOnly(libs.netty) } diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem.java index 57400063..bff38170 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem.java +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem.java @@ -23,10 +23,7 @@ import com.comphenix.tinyprotocol.TinyProtocol; import de.steamwar.core.Core; import de.steamwar.fightsystem.commands.*; import de.steamwar.fightsystem.countdown.*; -import de.steamwar.fightsystem.event.HellsBells; -import de.steamwar.fightsystem.event.Meteor; -import de.steamwar.fightsystem.event.PersistentDamage; -import de.steamwar.fightsystem.event.TNTDistributor; +import de.steamwar.fightsystem.event.*; import de.steamwar.fightsystem.fight.Fight; import de.steamwar.fightsystem.fight.FightTeam; import de.steamwar.fightsystem.fight.FightWorld; @@ -97,6 +94,7 @@ public class FightSystem extends JavaPlugin { new PrepareSchem(); new TestJoin(); new NormalJoin(); + new Spectator(); new RunningWorldInteraction(); new PersonalKitCreator(); new ArrowStopper(); @@ -135,6 +133,7 @@ public class FightSystem extends JavaPlugin { new PersistentDamage(); new TNTDistributor(); new WinconditionAmongUs(); + new NoGravity(); new NoPlayersOnlineCountdown(); new PreSchemCountdown(); @@ -156,6 +155,7 @@ public class FightSystem extends JavaPlugin { new LockschemCommand(); new StateCommand(); new SkipCommand(); + new TechhiderbugCommand(); new TPSWarpCommand(); new UnrankCommand(); new WinCommand(); diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem.properties b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem.properties index dde4e266..455e0444 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem.properties +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem.properties @@ -76,6 +76,7 @@ KITSEARCH_TITLE=Search for kit SCHEM_NO_ENEMY=§cNo schematic selection without an opponent SCHEM_TITLE={0} selection +SCHEM_DIRT=§eDirt Block SCHEM_PUBLIC=§ePublic {0} SCHEM_UNCHECKED=§eUnchecked {0} SCHEM_PRIVATE=§ePrivate {0} diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem_de.properties b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem_de.properties index 470226a8..cd294425 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem_de.properties +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem_de.properties @@ -70,6 +70,7 @@ KITSEARCH_TITLE=Nach Kit suchen SCHEM_NO_ENEMY=§cKeine Schematicwahl ohne Gegner SCHEM_TITLE={0}-Auswahl +SCHEM_DIRT=§eErdblock SCHEM_PUBLIC=§eÖffentliches {0} SCHEM_UNCHECKED=§eUngeprüftes {0} SCHEM_PRIVATE=§ePrivates {0} diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/commands/GUI.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/commands/GUI.java index 2ca6849c..237d860e 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/commands/GUI.java +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/commands/GUI.java @@ -24,15 +24,14 @@ import de.steamwar.fightsystem.Config; import de.steamwar.fightsystem.FightSystem; import de.steamwar.fightsystem.ai.AIManager; import de.steamwar.fightsystem.fight.*; +import de.steamwar.fightsystem.fight.Fight; +import de.steamwar.fightsystem.fight.FightPlayer; import de.steamwar.fightsystem.listener.PersonalKitCreator; import de.steamwar.fightsystem.states.FightState; import de.steamwar.fightsystem.utils.ColorConverter; import de.steamwar.inventory.*; import de.steamwar.message.Message; -import de.steamwar.sql.PersonalKit; -import de.steamwar.sql.SchematicNode; -import de.steamwar.sql.SchematicType; -import de.steamwar.sql.SteamwarUser; +import de.steamwar.sql.*; import net.md_5.bungee.api.ChatMessageType; import org.bukkit.Bukkit; import org.bukkit.Material; @@ -40,7 +39,10 @@ import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; -import java.util.*; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.function.Consumer; import java.util.stream.Collectors; public class GUI { @@ -206,6 +208,14 @@ public class GUI { for (int i = 0; i < Config.SubTypes.size(); i++) { setupSchemTypeRow(p, inv, Config.SubTypes.get(i), i + 1); } + if (!Config.test() && SteamwarUser.get(p.getUniqueId()).hasPerm(UserPerm.TEAM)) { + SchematicNode node = SchematicNode.getSchematicNode(-1, Config.GameName, (Integer) null); + if (node != null) { + inv.setItem(2, new SWItem(SWItem.getMaterial(node.getItem()), msg.parse("SCHEM_DIRT", p), click -> { + schemSelect(p, node); + })); + } + } inv.setCallback(-999, (ClickType click) -> p.closeInventory()); inv.open(); } @@ -241,14 +251,18 @@ public class GUI { private static void schemDialog(Player p, SchematicType type, boolean publicSchems, boolean unchecked){ SchematicSelector selector = new SchematicSelector(p, Config.test() ? SchematicSelector.selectSchematic() : SchematicSelector.selectSchematicType(unchecked ? type.checkType() : type), node -> { - FightTeam fightTeam = Fight.getPlayerTeam(p); - if(fightTeam == null) - return; - if(Config.test() || FightState.getFightState() != FightState.POST_SCHEM_SETUP) - fightTeam.pasteSchem(node); - p.closeInventory(); + schemSelect(p, node); }); selector.setPublicMode(publicSchems?SchematicSelector.PublicMode.PUBLIC_ONLY:SchematicSelector.PublicMode.PRIVATE_ONLY); selector.open(); } + + private static void schemSelect(Player p, SchematicNode node) { + FightTeam fightTeam = Fight.getPlayerTeam(p); + if(fightTeam == null) + return; + if(Config.test() || FightState.getFightState() != FightState.POST_SCHEM_SETUP) + fightTeam.pasteSchem(node); + p.closeInventory(); + } } diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/commands/TechhiderbugCommand.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/commands/TechhiderbugCommand.java new file mode 100644 index 00000000..3080c13e --- /dev/null +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/commands/TechhiderbugCommand.java @@ -0,0 +1,80 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2025 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.fightsystem.commands; + +import com.comphenix.tinyprotocol.TinyProtocol; +import de.steamwar.fightsystem.ArenaMode; +import de.steamwar.fightsystem.Config; +import de.steamwar.fightsystem.FightSystem; +import de.steamwar.fightsystem.fight.Fight; +import de.steamwar.fightsystem.states.FightState; +import de.steamwar.fightsystem.states.StateDependentCommand; +import de.steamwar.sql.SWException; +import org.bukkit.Bukkit; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; + +import java.io.StringWriter; +import java.util.Arrays; +import java.util.logging.Level; + +public class TechhiderbugCommand implements CommandExecutor { + + public TechhiderbugCommand() { + new StateDependentCommand(ArenaMode.All, FightState.All, "techhiderbug", this); + } + + @Override + public boolean onCommand(CommandSender sender, Command cmd, String alias, String[] args) { + StringWriter writer = new StringWriter(); + + try { + writer.append("ArenaMode: ").append(Config.mode.name()).append('\n'); + writer.append("FightState: ").append(FightState.getFightState().name()).append('\n'); + writer.append("TechHider enabled: ").append(FightState.getStateDependentFeatures().get(FightSystem.getTechHider()).toString()).append('\n'); + + writer.append("Arena region: ").append(Config.ArenaRegion.toString()).append('\n'); + writer.append("Team regions: "); + Fight.teams().forEach(t -> writer.append(t.getName()).append(':').append(t.getExtendRegion().toString()).append(' ')); + writer.append('\n'); + + writer.append("HullHider regions: "); + FightSystem.getHullHider().getHullMap().forEach((t, h) -> writer.append(t.getName()).append(':').append(h.getRegion().toString()).append(' ')); + writer.append('\n'); + + writer.append("Hidden regions: "); + FightSystem.getTechHider().getHiddenRegion().forEach((p, r) -> writer.append(p.getName()).append(':').append(r.toString()).append(' ')); + writer.append('\n'); + + writer.append("TinyProtocol: "); + writer.append(TinyProtocol.instance.toString()).append('\n'); + + writer.append('\n').append("Netty pipelines:\n"); + Bukkit.getOnlinePlayers().forEach(p -> writer.append(p.getName()).append(": ").append(String.join(" ", TinyProtocol.instance.getPlayerInterceptors().get(p).getChannel().pipeline().names())).append('\n')); + } catch (Exception e) { + writer.append("Error while generating bug report: ").append(e.getMessage()).append('\n'); + Bukkit.getLogger().log(Level.SEVERE, "Error while generating bug report", e); + } + + SWException.log("Techhider-Bug reported by " + sender.getName() + ": " + Arrays.toString(args), writer.toString()); + return false; + } +} diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/event/NoGravity.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/event/NoGravity.java new file mode 100644 index 00000000..12246f8e --- /dev/null +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/event/NoGravity.java @@ -0,0 +1,41 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.fightsystem.event; + +import de.steamwar.fightsystem.states.FightState; +import de.steamwar.fightsystem.states.StateDependentListener; +import de.steamwar.fightsystem.winconditions.Winconditions; +import org.bukkit.entity.EntityType; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntitySpawnEvent; + +public class NoGravity implements Listener { + + public NoGravity() { + new StateDependentListener(Winconditions.NO_GRAVITY, FightState.All, this); + } + + @EventHandler + public void onEntitySpawn(EntitySpawnEvent event) { + if (event.getEntityType() == EntityType.PLAYER) return; + event.getEntity().setGravity(false); + } +} diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/fight/Fight.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/fight/Fight.java index 5b8f62f9..1f205122 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/fight/Fight.java +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/fight/Fight.java @@ -104,40 +104,6 @@ public class Fight { return null; } - @SuppressWarnings("deprecation") - public static void setPlayerGamemode(Player player, GameMode gameMode) { - player.setGameMode(gameMode); - - if(gameMode == GameMode.SPECTATOR) { - for(Player currentPlayer : Bukkit.getServer().getOnlinePlayers()) { - if(currentPlayer.getUniqueId() != player.getUniqueId() && currentPlayer.getGameMode() == GameMode.SPECTATOR) { - currentPlayer.hidePlayer(player); - player.hidePlayer(currentPlayer); - } - } - - if(Config.test() || Config.isReferee(player)) - return; - - Bukkit.getScheduler().runTaskLater(FightSystem.getPlugin(), () -> { - if(!player.isOnline()) - return; - pseudoSpectator(player, true); - }, 1); - }else if(gameMode == GameMode.SURVIVAL) { - for(Player currentPlayer : Bukkit.getServer().getOnlinePlayers()) { - if(currentPlayer.getUniqueId() != player.getUniqueId() && currentPlayer.getGameMode() == GameMode.SPECTATOR) { - currentPlayer.showPlayer(player); - player.showPlayer(currentPlayer); - } - } - } - } - - public static void pseudoSpectator(Player player, boolean enable) { - TinyProtocol.instance.sendPacket(player, ProtocolWrapper.impl.playerInfoPacketConstructor(ProtocolWrapper.PlayerInfoAction.GAMEMODE, new GameProfile(player.getUniqueId(), player.getName()), enable ? GameMode.CREATIVE : GameMode.SPECTATOR)); - } - public static boolean publicOnly() { if (Config.OnlyPublicSchematics) { return true; diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/fight/FightTeam.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/fight/FightTeam.java index 3a6a12a2..0cb68f71 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/fight/FightTeam.java +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/fight/FightTeam.java @@ -73,7 +73,6 @@ public class FightTeam { if(ArenaMode.VariableTeams.contains(Config.mode)){ notReadyKit.setItem(2, "REQUESTS", new ItemBuilder(Material.PAPER).build(), GUI::chooseJoinRequests); - notReadyKit.setItem(3, "MANAGE_PLAYERS", SWItem.getPlayerSkull("AdmiralSeekrank").getItemStack(), GUI::managePlayers); if(!AIManager.availableAIs().isEmpty()) notReadyKit.setItem(6, "ADD_AI", new ItemBuilder(Material.REDSTONE).build(), GUI::addAI); } @@ -81,6 +80,7 @@ public class FightTeam { if(Config.test()) notReadyKit.setItem(5, "CHOOSE_SCHEMATIC", new ItemBuilder(SWItem.getMaterial("CAULDRON_ITEM")).enchant().build(), GUI::preSchemDialog); + notReadyKit.setItem(3, "MANAGE_PLAYERS", SWItem.getPlayerSkull("AdmiralSeekrank").getItemStack(), GUI::managePlayers); notReadyKit.setItem(4, "TEAM_NOT_READY", new ItemBuilder(SWItem.getDye(10), (short) 10).enchant().build(), player -> Objects.requireNonNull(Fight.getPlayerTeam(player)).setReady(true)); } private static final HotbarKit chooseSchemKit = new HotbarKit(notReadyKit); @@ -282,9 +282,9 @@ public class FightTeam { FightSystem.getHullHider().updatePlayer(player); if(FightState.Spectate.contains(FightState.getFightState())) { - Fight.setPlayerGamemode(player, GameMode.SPECTATOR); + player.setGameMode(GameMode.SPECTATOR); } else { - Fight.setPlayerGamemode(player, GameMode.SURVIVAL); + player.setGameMode(GameMode.SURVIVAL); (FightState.ingame() ? fightPlayer.getKit() : memberKit).loadToPlayer(player); } }); @@ -317,7 +317,7 @@ public class FightTeam { entity.teleport(Config.SpecSpawn); fightPlayer.ifPlayer(player -> { - Fight.setPlayerGamemode(player, GameMode.SPECTATOR); + player.setGameMode(GameMode.SPECTATOR); player.getInventory().clear(); if(player.isOnline()){ @@ -517,14 +517,14 @@ public class FightTeam { @Override public void enable() { players.values().forEach(fightPlayer -> { - fightPlayer.ifPlayer(player -> Fight.setPlayerGamemode(player, GameMode.SPECTATOR)); + fightPlayer.ifPlayer(player -> player.setGameMode(GameMode.SPECTATOR)); fightPlayer.getEntity().teleport(FightTeam.this.spawn); }); } @Override public void disable() { - players.values().forEach(fightPlayer -> fightPlayer.ifPlayer(player -> Fight.setPlayerGamemode(player, GameMode.SURVIVAL))); + players.values().forEach(fightPlayer -> fightPlayer.ifPlayer(player -> player.setGameMode(GameMode.SURVIVAL))); } } } diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/fight/HotbarKit.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/fight/HotbarKit.java index 5bc1d844..6b3df110 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/fight/HotbarKit.java +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/fight/HotbarKit.java @@ -29,11 +29,15 @@ import de.steamwar.fightsystem.states.FightState; import de.steamwar.fightsystem.states.StateDependentListener; import de.steamwar.fightsystem.states.StateDependentTask; import de.steamwar.fightsystem.utils.ItemBuilder; +import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.block.Action; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryOpenEvent; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.ItemStack; @@ -107,6 +111,19 @@ public class HotbarKit extends Kit { Player player = event.getPlayer(); int slot = player.getInventory().getHeldItemSlot(); + click(player, slot, event); + } + + @EventHandler + public void onInventoryClick(InventoryClickEvent event) { + int slot = event.getSlot(); + if (slot < 0 || slot >= HOTBAR_SIZE) return; + + Player player = (Player) event.getWhoClicked(); + click(player, slot, event); + } + + private void click(Player player, int slot, Cancellable event) { Kit activeKit = activeKits.get(player); if(!(activeKit instanceof HotbarKit) || PersonalKitCreator.inKitCreator(player) || activeKit.getInventory()[slot] == null) return; diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/LeaveableArena.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/LeaveableArena.java index 9d0bb4e2..36a5a189 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/LeaveableArena.java +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/LeaveableArena.java @@ -84,6 +84,6 @@ public class LeaveableArena implements Listener { private void markInArena(Player player) { spectatorsInArena.put(player, player.getGameMode()); - Fight.setPlayerGamemode(player, GameMode.SPECTATOR); + player.setGameMode(GameMode.SPECTATOR); } } diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/Permanent.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/Permanent.java index 2f3138ec..4976463c 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/Permanent.java +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/Permanent.java @@ -74,7 +74,7 @@ public class Permanent implements Listener { public void handlePlayerRespawn(PlayerRespawnEvent event){ Player player = event.getPlayer(); if(Fight.fighting(player)) { - Fight.setPlayerGamemode(player, GameMode.SPECTATOR); + player.setGameMode(GameMode.SPECTATOR); FightTeam team = Fight.getPlayerTeam(player); event.setRespawnLocation(team == null ? Config.SpecSpawn : team.getSpawn()); @@ -98,11 +98,11 @@ public class Permanent implements Listener { FightPlayer fp = Fight.getFightPlayer(player); if (!Config.ArenaLeaveable && fp == null) { - Fight.setPlayerGamemode(player, GameMode.SPECTATOR); + player.setGameMode(GameMode.SPECTATOR); spectatorTeam.addEntry(player.getName()); player.teleport(Config.SpecSpawn); } else if(fp != null && !fp.isLiving()) { - Fight.setPlayerGamemode(player, GameMode.SPECTATOR); + player.setGameMode(GameMode.SPECTATOR); player.teleport(fp.getTeam().getSpawn()); } } diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/PrepareSchem.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/PrepareSchem.java index 288eda76..29ccc434 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/PrepareSchem.java +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/PrepareSchem.java @@ -86,7 +86,10 @@ public class PrepareSchem implements Listener { if(schemExists(schem)) return; + SchematicNode old = schem; schem = SchematicNode.createSchematicNode(schem.getOwner(), preparedName(schem), schem.getParent(), Config.SchematicType.checkType().toDB(), schem.getItem()); + schem.setReplaceColor(old.replaceColor()); + schem.setAllowReplay(old.allowReplay()); try{ WorldeditWrapper.impl.saveSchem(schem, region, minY); diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/Spectator.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/Spectator.java new file mode 100644 index 00000000..399970ca --- /dev/null +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/Spectator.java @@ -0,0 +1,114 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2025 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.fightsystem.listener; + +import java.util.HashSet; +import java.util.Set; + +import org.bukkit.Bukkit; +import org.bukkit.GameMode; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerGameModeChangeEvent; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerQuitEvent; + +import com.comphenix.tinyprotocol.TinyProtocol; +import com.mojang.authlib.GameProfile; + +import de.steamwar.core.ProtocolWrapper; +import de.steamwar.fightsystem.ArenaMode; +import de.steamwar.fightsystem.Config; +import de.steamwar.fightsystem.fight.Fight; +import de.steamwar.fightsystem.fight.FightPlayer; +import de.steamwar.fightsystem.states.FightState; +import de.steamwar.fightsystem.states.StateDependentListener; +import de.steamwar.fightsystem.states.StateDependentTask; + + +public class Spectator implements Listener { + + private final Set pseudoSpectator = new HashSet<>(); + + public Spectator() { + new StateDependentListener(ArenaMode.AntiTest, FightState.All, this); + new StateDependentTask(ArenaMode.AntiTest, FightState.All, this::pseudoSpectatorCheck, 1, 1); + } + + @EventHandler(priority = EventPriority.MONITOR) + public void handlePlayerJoin(PlayerJoinEvent e) { + Player player = e.getPlayer(); + + if(player.getGameMode() == GameMode.SPECTATOR) + gameModeChange(player, GameMode.SPECTATOR); + } + + @EventHandler + public void onGameModeChange(PlayerGameModeChangeEvent e) { + gameModeChange(e.getPlayer(), e.getNewGameMode()); + } + + @SuppressWarnings("deprecation") + private void gameModeChange(Player player, GameMode gameMode) { + if (gameMode == GameMode.SPECTATOR) { + for(Player p : Bukkit.getServer().getOnlinePlayers()) { + if(p.getUniqueId() != player.getUniqueId()) + p.hidePlayer(player); + } + } else { + for(Player p : Bukkit.getServer().getOnlinePlayers()) { + if(p.getUniqueId() != player.getUniqueId()) + p.showPlayer(player); + } + } + } + + @EventHandler + public void playerQuit(PlayerQuitEvent e) { + pseudoSpectator.remove(e.getPlayer()); + } + + private void pseudoSpectatorCheck() { + for (Player player : Bukkit.getOnlinePlayers()) { + if (player.getGameMode() != GameMode.SPECTATOR) { + pseudoSpectator.remove(player); + continue; + } + + if (Config.isReferee(player)) + continue; + + FightPlayer fightPlayer = Fight.getFightPlayer(player); + if (fightPlayer == null || !fightPlayer.getTeam().getExtendRegion().playerInRegion(player.getLocation())) { + if (pseudoSpectator.add(player)) + pseudoSpectator(player, true); + } else { + if (pseudoSpectator.remove(player)) + pseudoSpectator(player, false); + } + } + } + + private static void pseudoSpectator(Player player, boolean enable) { + TinyProtocol.instance.sendPacket(player, ProtocolWrapper.impl.playerInfoPacketConstructor(ProtocolWrapper.PlayerInfoAction.GAMEMODE, new GameProfile(player.getUniqueId(), player.getName()), enable ? GameMode.CREATIVE : GameMode.SPECTATOR)); + } +} diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/TeamArea.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/TeamArea.java index 2720b25c..2f888452 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/TeamArea.java +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/TeamArea.java @@ -19,9 +19,14 @@ package de.steamwar.fightsystem.listener; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerQuitEvent; + import de.steamwar.fightsystem.ArenaMode; import de.steamwar.fightsystem.Config; -import de.steamwar.fightsystem.FightSystem; import de.steamwar.fightsystem.events.BoardingEvent; import de.steamwar.fightsystem.events.TeamDeathEvent; import de.steamwar.fightsystem.events.TeamLeaveEvent; @@ -32,23 +37,12 @@ import de.steamwar.fightsystem.fight.FightTeam; import de.steamwar.fightsystem.states.FightState; import de.steamwar.fightsystem.states.OneShotStateDependent; import de.steamwar.fightsystem.states.StateDependentListener; -import de.steamwar.fightsystem.states.StateDependentTask; -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.player.PlayerJoinEvent; -import org.bukkit.event.player.PlayerQuitEvent; - -import java.util.HashSet; -import java.util.Set; public class TeamArea implements Listener { private final FightTeam team; private final Border spectatorBorder; private final Border bordingBorder; - private final Set realSpectator = new HashSet<>(); public TeamArea(FightTeam team) { this.team = team; @@ -56,7 +50,6 @@ public class TeamArea implements Listener { this.bordingBorder = new Border(team.getExtendRegion().to2d(), true, 1, "NO_ENTERN", team.getName() + ".boardingBorder"); new StateDependentListener(ArenaMode.AntiTest, FightState.All, this); - new StateDependentTask(ArenaMode.AntiTest, FightState.TeamFix, this::realSpectatorCheck, 1, 1); new OneShotStateDependent(ArenaMode.AntiTest, FightState.Spectate, () -> Fight.teams().forEach(t -> t.getPlayers().forEach(this::teamSpectator))); } @@ -114,30 +107,5 @@ public class TeamArea implements Listener { Player player = e.getPlayer(); spectatorBorder.removePlayer(player); bordingBorder.removePlayer(player); - realSpectator.remove(player); - } - - private void realSpectatorCheck() { - for(FightPlayer fightPlayer : team.getPlayers()) { - if(fightPlayer.isLiving()) - continue; - - fightPlayer.ifPlayer(player -> { - boolean inRegion = team.getExtendRegion().playerInRegion(player.getLocation()); - if(inRegion && !realSpectator.contains(player)) { - realSpectator.add(player); - - //Later to prevent race condition with Fight.setSpecatator() during respawn - Bukkit.getScheduler().runTaskLater(FightSystem.getPlugin(), () -> { - if(!player.isOnline()) - return; - Fight.pseudoSpectator(player, false); - }, 2); - }else if(!inRegion && realSpectator.contains(player)) { - Fight.pseudoSpectator(player, true); - realSpectator.remove(player); - } - }); - } } } diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/states/FightState.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/states/FightState.java index 1d5acf35..cadcec66 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/states/FightState.java +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/states/FightState.java @@ -49,6 +49,7 @@ public enum FightState { public static final Set AntiIngame = Collections.unmodifiableSet(EnumSet.complementOf(EnumSet.of(PRE_RUNNING, RUNNING))); public static final Set AntiSpectate = Collections.unmodifiableSet(EnumSet.complementOf(EnumSet.of(SPECTATE))); + @Getter private static final Map stateDependentFeatures = new HashMap<>(); @Getter private static FightState fightState = PRE_LEADER_SETUP; diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/Hull.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/Hull.java index a67c6d5d..caf39e79 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/Hull.java +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/Hull.java @@ -45,6 +45,7 @@ public class Hull { return material.isOccluding() || Config.HiddenBlocks.contains(material); } + @Getter private final Region region; private final boolean groundVisible; private final IntVector[] directions; diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/HullHider.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/HullHider.java index 455b960d..c050656d 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/HullHider.java +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/HullHider.java @@ -33,6 +33,7 @@ import de.steamwar.fightsystem.states.StateDependent; import de.steamwar.fightsystem.states.StateDependentListener; import de.steamwar.fightsystem.states.StateDependentTask; import de.steamwar.techhider.TechHider; +import lombok.Getter; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; @@ -56,6 +57,7 @@ import java.util.function.Function; public class HullHider implements Listener { + @Getter private final Map hullMap = new HashMap<>(); private final Hull[] hulls; private final Map, BiFunction> packetHiders = new HashMap<>(); diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/Region.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/Region.java index 6a559799..60d37be8 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/Region.java +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/Region.java @@ -159,4 +159,9 @@ public class Region { public interface TriConsumer{ void accept(T x, V y, U z); } + + @Override + public String toString() { + return minX + "," + minY + "," + minZ + "->" + maxX + "," + maxY + "," + maxZ; + } } diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/TechHiderWrapper.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/TechHiderWrapper.java index c45d7ab6..bf890168 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/TechHiderWrapper.java +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/TechHiderWrapper.java @@ -32,6 +32,7 @@ import de.steamwar.fightsystem.states.StateDependent; import de.steamwar.fightsystem.states.StateDependentListener; import de.steamwar.sql.SteamwarUser; import de.steamwar.techhider.TechHider; +import lombok.Getter; import org.bukkit.GameMode; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; @@ -51,6 +52,7 @@ public class TechHiderWrapper extends StateDependent implements TechHider.Locati public static final boolean ENABLED = !Config.OnlyPublicSchematics && !Config.test() && Config.TechhiderActive; + @Getter private final ConcurrentHashMap hiddenRegion = new ConcurrentHashMap<>(); private final ConcurrentHashMap patterns = new ConcurrentHashMap<>(); private final TechHider techHider; diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/winconditions/WinconditionBlocks.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/winconditions/WinconditionBlocks.java index b9b0c9f7..72c0873a 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/winconditions/WinconditionBlocks.java +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/winconditions/WinconditionBlocks.java @@ -84,6 +84,9 @@ public class WinconditionBlocks extends Wincondition implements PrintableWincond } private void check() { + // Edge Case for DirtBlock + if (blocks.isEmpty()) return; + blocks.removeIf(block -> !isOfType.test(block)); if(blocks.isEmpty()) win(Fight.getOpposite(team), "WIN_TECHKO", team.getColoredName()); diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/winconditions/WinconditionPercent.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/winconditions/WinconditionPercent.java index 37d3fafa..f98bdecc 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/winconditions/WinconditionPercent.java +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/winconditions/WinconditionPercent.java @@ -78,6 +78,7 @@ public class WinconditionPercent extends Wincondition implements PrintableWincon private int totalBlocks = 0; private int currentBlocks = 0; + private boolean countAnyBlock = false; private TeamPercent(FightTeam team, Winconditions wincondition) { this.team = team; @@ -98,7 +99,7 @@ public class WinconditionPercent extends Wincondition implements PrintableWincon } event.blockList().forEach(block -> { - if (Config.PercentBlocks.contains(block.getType()) == Config.PercentBlocksWhitelist) { + if (countAnyBlock || Config.PercentBlocks.contains(block.getType()) == Config.PercentBlocksWhitelist) { currentBlocks--; } }); @@ -108,10 +109,16 @@ public class WinconditionPercent extends Wincondition implements PrintableWincon private void enable() { totalBlocks = 0; + countAnyBlock = false; team.getSchemRegion().forEach((x, y, z) -> { if (Config.PercentBlocks.contains(Config.world.getBlockAt(x, y, z).getType()) == Config.PercentBlocksWhitelist) totalBlocks++; }); + // Edge Case for DirtBlock + if (totalBlocks == 0) { + totalBlocks = team.getSchemRegion().volume(); + countAnyBlock = true; + } currentBlocks = totalBlocks; postEnable.accept(team); } diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/winconditions/Winconditions.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/winconditions/Winconditions.java index 296cf97e..2aaecae6 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/winconditions/Winconditions.java +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/winconditions/Winconditions.java @@ -39,5 +39,6 @@ public enum Winconditions { METEOR, AMONG_US, PERSISTENT_DAMAGE, - TNT_DISTRIBUTION + TNT_DISTRIBUTION, + NO_GRAVITY, } diff --git a/FightSystem/FightSystem_Core/src/plugin.yml b/FightSystem/FightSystem_Core/src/plugin.yml index 64ece716..6925bf69 100644 --- a/FightSystem/FightSystem_Core/src/plugin.yml +++ b/FightSystem/FightSystem_Core/src/plugin.yml @@ -27,4 +27,5 @@ commands: resettb: tpslimit: tpswarp: + techhiderbug: unrank: \ No newline at end of file diff --git a/FightSystem/build.gradle.kts b/FightSystem/build.gradle.kts index 0cd412bc..87849826 100644 --- a/FightSystem/build.gradle.kts +++ b/FightSystem/build.gradle.kts @@ -39,3 +39,13 @@ dependencies { implementation(project(":FightSystem:FightSystem_20")) implementation(project(":FightSystem:FightSystem_21")) } + +tasks.register("WarGear20") { + group = "run" + description = "Run a WarGear 1.20 Fight Server" + dependsOn(":SpigotCore:shadowJar") + dependsOn(":FightSystem:shadowJar") + template = "WarGear20" + worldName = "arenas/Pentraki" + config = "WarGear20.yml" +} diff --git a/LobbySystem/src/de/steamwar/lobby/jumpandrun/JumpAndRun.java b/LobbySystem/src/de/steamwar/lobby/jumpandrun/JumpAndRun.java index f8ce3338..68097463 100644 --- a/LobbySystem/src/de/steamwar/lobby/jumpandrun/JumpAndRun.java +++ b/LobbySystem/src/de/steamwar/lobby/jumpandrun/JumpAndRun.java @@ -67,7 +67,7 @@ public class JumpAndRun extends BasicListener { int count = CLICKED_COUNT.getOrDefault(player, -1); if (count >= 0) { - if (count > 60) { + if (count > 20) { toReset.add(player); return; } @@ -104,12 +104,18 @@ public class JumpAndRun extends BasicListener { return; } Vector point = points.get(index); - if (location.getY() < point.getY()) { - return; - } - if (location.toVector().distanceSquared(point) >= 12.25) { + if (location.getY() < point.getY()) index = -2; + if (location.toVector().distanceSquared(point) >= 17) index = -2; + if (index > 0 && index < points.size() - 1) { + Vector nextPoint = points.get(index + 1); + if (location.getY() >= nextPoint.getY() && location.toVector().distanceSquared(nextPoint) < 17) { + index = index + 1; + } + } + if (index == -2) { return; } + CURRENT_POS.put(event.getPlayer(), index); event.getPlayer().playSound(event.getPlayer().getLocation(), Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 0.4F, 1); if (index < points.size() - 1) { diff --git a/MissileWars/src/de/steamwar/misslewars/MWTeam.java b/MissileWars/src/de/steamwar/misslewars/MWTeam.java index 8abc5bc9..b5ee7c51 100644 --- a/MissileWars/src/de/steamwar/misslewars/MWTeam.java +++ b/MissileWars/src/de/steamwar/misslewars/MWTeam.java @@ -184,6 +184,7 @@ public class MWTeam { public void leave(Player p) { if (!players.contains(p)) return; + players.remove(p); for (ItemStack stack : p.getInventory().getContents()) { if (stack == null) continue; @@ -198,7 +199,6 @@ public class MWTeam { if (players.isEmpty() && MissileWars.getFightState() == FightState.FIGHTING) MissileWars.end(WinReasons.NO_ENEMY, enemy()); - players.remove(p); sbteam.removePlayer(p); } diff --git a/MissileWars/src/de/steamwar/misslewars/countdowns/EndCountdown.java b/MissileWars/src/de/steamwar/misslewars/countdowns/EndCountdown.java index 292071a6..f2d3183b 100644 --- a/MissileWars/src/de/steamwar/misslewars/countdowns/EndCountdown.java +++ b/MissileWars/src/de/steamwar/misslewars/countdowns/EndCountdown.java @@ -37,7 +37,7 @@ public class EndCountdown extends StateDependent { @Override public void enable() { if (Config.isEvent()) { - task = Bukkit.getScheduler().runTaskLater(MissileWars.getPlugin(), this::stop, 1200); + task = Bukkit.getScheduler().runTaskLater(MissileWars.getPlugin(), this::stop, 200); } else { task = Bukkit.getScheduler().runTaskLater(MissileWars.getPlugin(), this::restart, Config.EndTime); } diff --git a/SchematicSystem/SchematicSystem_15/src/de/steamwar/schematicsystem/autocheck/AutoChecker15.java b/SchematicSystem/SchematicSystem_15/src/de/steamwar/schematicsystem/autocheck/AutoChecker15.java index 9dd5e456..a97cb133 100644 --- a/SchematicSystem/SchematicSystem_15/src/de/steamwar/schematicsystem/autocheck/AutoChecker15.java +++ b/SchematicSystem/SchematicSystem_15/src/de/steamwar/schematicsystem/autocheck/AutoChecker15.java @@ -31,57 +31,6 @@ import java.util.*; import java.util.stream.Collectors; public class AutoChecker15 implements AutoChecker.IAutoChecker { - private static final Set INVENTORY = EnumSet.of( - Material.BARREL, - Material.BLAST_FURNACE, - Material.BREWING_STAND, - Material.CAMPFIRE, - Material.CHEST, - Material.DISPENSER, - Material.DROPPER, - Material.FURNACE, - Material.HOPPER, - Material.JUKEBOX, - Material.SHULKER_BOX, - Material.WHITE_SHULKER_BOX, - Material.ORANGE_SHULKER_BOX, - Material.MAGENTA_SHULKER_BOX, - Material.LIGHT_BLUE_SHULKER_BOX, - Material.YELLOW_SHULKER_BOX, - Material.LIME_SHULKER_BOX, - Material.PINK_SHULKER_BOX, - Material.GRAY_SHULKER_BOX, - Material.LIGHT_GRAY_SHULKER_BOX, - Material.CYAN_SHULKER_BOX, - Material.PURPLE_SHULKER_BOX, - Material.BLUE_SHULKER_BOX, - Material.BROWN_SHULKER_BOX, - Material.GREEN_SHULKER_BOX, - Material.RED_SHULKER_BOX, - Material.BLACK_SHULKER_BOX, - Material.SMOKER, - Material.TRAPPED_CHEST); - - private static final Set FLOWERS = EnumSet.of( - Material.CORNFLOWER, - Material.POPPY, - Material.FERN, - Material.DANDELION, - Material.BLUE_ORCHID, - Material.ALLIUM, - Material.AZURE_BLUET, - Material.RED_TULIP, - Material.ORANGE_TULIP, - Material.WHITE_TULIP, - Material.PINK_TULIP, - Material.OXEYE_DAISY, - Material.LILY_OF_THE_VALLEY, - Material.WITHER_ROSE, - Material.SUNFLOWER, - Material.DIAMOND_HORSE_ARMOR, - Material.IRON_HORSE_ARMOR, - Material.GOLDEN_HORSE_ARMOR, - Material.HONEY_BOTTLE); public AutoChecker.BlockScanResult scan(Clipboard clipboard) { AutoChecker.BlockScanResult result = new AutoChecker.BlockScanResult(); @@ -98,7 +47,7 @@ public class AutoChecker15 implements AutoChecker.IAutoChecker { result.getBlockCounts().merge(material, 1, Integer::sum); - if(INVENTORY.contains(material)) { + if(AutoCheckerItems.impl.getInventoryMaterials().contains(material)) { checkInventory(result, block, material, new BlockPos(x, y, z)); } @@ -125,7 +74,7 @@ public class AutoChecker15 implements AutoChecker.IAutoChecker { )); itemsInInv.put(Material.FIRE_CHARGE, EnumSet.of(Material.DISPENSER)); itemsInInv.put(Material.ARROW, EnumSet.of(Material.DISPENSER)); - FLOWERS.forEach(material -> itemsInInv.put(material, INVENTORY)); + AutoCheckerItems.impl.getAllowedMaterialsInInventory().forEach(material -> itemsInInv.put(material, AutoCheckerItems.impl.getInventoryMaterials())); } private void checkInventory(AutoChecker.BlockScanResult result, BaseBlock block, Material material, BlockPos pos) { diff --git a/SchematicSystem/SchematicSystem_15/src/de/steamwar/schematicsystem/autocheck/AutoCheckerItems15.java b/SchematicSystem/SchematicSystem_15/src/de/steamwar/schematicsystem/autocheck/AutoCheckerItems15.java new file mode 100644 index 00000000..0d853c16 --- /dev/null +++ b/SchematicSystem/SchematicSystem_15/src/de/steamwar/schematicsystem/autocheck/AutoCheckerItems15.java @@ -0,0 +1,90 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.schematicsystem.autocheck; + +import org.bukkit.Material; + +import java.util.EnumSet; +import java.util.Set; + +public class AutoCheckerItems15 implements AutoCheckerItems { + + private static final Set INVENTORY = EnumSet.of( + Material.BARREL, + Material.BLAST_FURNACE, + Material.BREWING_STAND, + Material.CAMPFIRE, + Material.CHEST, + Material.DISPENSER, + Material.DROPPER, + Material.FURNACE, + Material.HOPPER, + Material.JUKEBOX, + Material.SHULKER_BOX, + Material.WHITE_SHULKER_BOX, + Material.ORANGE_SHULKER_BOX, + Material.MAGENTA_SHULKER_BOX, + Material.LIGHT_BLUE_SHULKER_BOX, + Material.YELLOW_SHULKER_BOX, + Material.LIME_SHULKER_BOX, + Material.PINK_SHULKER_BOX, + Material.GRAY_SHULKER_BOX, + Material.LIGHT_GRAY_SHULKER_BOX, + Material.CYAN_SHULKER_BOX, + Material.PURPLE_SHULKER_BOX, + Material.BLUE_SHULKER_BOX, + Material.BROWN_SHULKER_BOX, + Material.GREEN_SHULKER_BOX, + Material.RED_SHULKER_BOX, + Material.BLACK_SHULKER_BOX, + Material.SMOKER, + Material.TRAPPED_CHEST); + + private static final Set FLOWERS = EnumSet.of( + Material.CORNFLOWER, + Material.POPPY, + Material.FERN, + Material.DANDELION, + Material.BLUE_ORCHID, + Material.ALLIUM, + Material.AZURE_BLUET, + Material.RED_TULIP, + Material.ORANGE_TULIP, + Material.WHITE_TULIP, + Material.PINK_TULIP, + Material.OXEYE_DAISY, + Material.LILY_OF_THE_VALLEY, + Material.WITHER_ROSE, + Material.SUNFLOWER, + Material.DIAMOND_HORSE_ARMOR, + Material.IRON_HORSE_ARMOR, + Material.GOLDEN_HORSE_ARMOR, + Material.HONEY_BOTTLE); + + @Override + public Set getInventoryMaterials() { + return INVENTORY; + } + + @Override + public Set getAllowedMaterialsInInventory() { + return FLOWERS; + } +} diff --git a/SchematicSystem/SchematicSystem_19/build.gradle.kts b/SchematicSystem/SchematicSystem_19/build.gradle.kts new file mode 100644 index 00000000..38fcd471 --- /dev/null +++ b/SchematicSystem/SchematicSystem_19/build.gradle.kts @@ -0,0 +1,33 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2025 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +plugins { + steamwar.java +} + +dependencies { + compileOnly(project(":SpigotCore", "default")) + compileOnly(project(":SchematicSystem:SchematicSystem_Core", "default")) + compileOnly(project(":SchematicSystem:SchematicSystem_15", "default")) + + compileOnly(libs.spigotapi) + + compileOnly(libs.nms19) + compileOnly(libs.fawe18) +} diff --git a/SchematicSystem/SchematicSystem_19/src/de/steamwar/schematicsystem/autocheck/AutoCheckerItems19.java b/SchematicSystem/SchematicSystem_19/src/de/steamwar/schematicsystem/autocheck/AutoCheckerItems19.java new file mode 100644 index 00000000..0c004cfe --- /dev/null +++ b/SchematicSystem/SchematicSystem_19/src/de/steamwar/schematicsystem/autocheck/AutoCheckerItems19.java @@ -0,0 +1,75 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.schematicsystem.autocheck; + +import org.bukkit.Material; + +import java.util.EnumSet; +import java.util.Set; + +public class AutoCheckerItems19 extends AutoCheckerItems15 { + + private static final Set ALLOWED_ITEMS_IN_INVENTORY = EnumSet.of( + // 64-stackable Items + Material.CORNFLOWER, + Material.POPPY, + Material.FERN, + Material.DANDELION, + Material.BLUE_ORCHID, + Material.ALLIUM, + Material.AZURE_BLUET, + Material.RED_TULIP, + Material.ORANGE_TULIP, + Material.WHITE_TULIP, + Material.PINK_TULIP, + Material.OXEYE_DAISY, + Material.LILY_OF_THE_VALLEY, + Material.WITHER_ROSE, + Material.SUNFLOWER, + // 16-stackable Items + Material.HONEY_BOTTLE, + // Non-stackable items + Material.DIAMOND_HORSE_ARMOR, + Material.IRON_HORSE_ARMOR, + Material.GOLDEN_HORSE_ARMOR, + // Disks + Material.MUSIC_DISC_11, + Material.MUSIC_DISC_13, + Material.MUSIC_DISC_CAT, + Material.MUSIC_DISC_BLOCKS, + Material.MUSIC_DISC_CHIRP, + Material.MUSIC_DISC_FAR, + Material.MUSIC_DISC_MALL, + Material.MUSIC_DISC_MELLOHI, + Material.MUSIC_DISC_STAL, + Material.MUSIC_DISC_STRAD, + Material.MUSIC_DISC_WAIT, + Material.MUSIC_DISC_WARD, + Material.MUSIC_DISC_OTHERSIDE, + Material.MUSIC_DISC_PIGSTEP, + Material.MUSIC_DISC_RELIC, + Material.MUSIC_DISC_5 + ); + + @Override + public Set getAllowedMaterialsInInventory() { + return ALLOWED_ITEMS_IN_INVENTORY; + } +} diff --git a/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/autocheck/AutoCheckerItems.java b/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/autocheck/AutoCheckerItems.java new file mode 100644 index 00000000..fb103f67 --- /dev/null +++ b/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/autocheck/AutoCheckerItems.java @@ -0,0 +1,34 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.schematicsystem.autocheck; + +import de.steamwar.core.VersionDependent; +import de.steamwar.schematicsystem.SchematicSystem; +import org.bukkit.Material; + +import java.util.Set; + +public interface AutoCheckerItems { + + AutoCheckerItems impl = VersionDependent.getVersionImpl(SchematicSystem.getInstance()); + + Set getInventoryMaterials(); + Set getAllowedMaterialsInInventory(); +} diff --git a/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/DownloadCommand.java b/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/DownloadCommand.java index ff797b67..31c29bd0 100644 --- a/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/DownloadCommand.java +++ b/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/DownloadCommand.java @@ -35,10 +35,10 @@ public class DownloadCommand extends SWCommand { @Register(help = true) public void genericCommand(Player player, String... args) { SteamwarUser user = SteamwarUser.get(player.getUniqueId()); - SchematicNode copyNode = SchematicNode.getSchematicNode(user.getId(), "//copy", 0); + SchematicNode copyNode = SchematicNode.getSchematicNode(user.getId(), "//copy", (Integer) null); boolean newSchem = false; - if(copyNode == null) { - copyNode = SchematicNode.createSchematicNode(user.getId(), "//copy", 0, SchematicType.Normal.toDB(), ""); + if (copyNode == null) { + copyNode = SchematicNode.createSchematicNode(user.getId(), "//copy", null, SchematicType.Normal.toDB(), ""); newSchem = true; } @@ -46,13 +46,13 @@ public class DownloadCommand extends SWCommand { new SchematicData(copyNode).saveFromPlayer(player); } catch (IOException e) { SchematicSystem.MESSAGE.send("DOWNLOAD_ERROR", player); - if(newSchem) { + if (newSchem) { copyNode.delete(); } throw new SecurityException(e); } catch (NoClipboardException e) { SchematicSystem.MESSAGE.send("COMMAND_SAVE_CLIPBOARD_EMPTY", player); - if(newSchem) { + if (newSchem) { copyNode.delete(); } return; diff --git a/SchematicSystem/build.gradle.kts b/SchematicSystem/build.gradle.kts index f9871adc..813550b2 100644 --- a/SchematicSystem/build.gradle.kts +++ b/SchematicSystem/build.gradle.kts @@ -30,4 +30,5 @@ dependencies { implementation(project(":SchematicSystem:SchematicSystem_Core")) implementation(project(":SchematicSystem:SchematicSystem_8")) implementation(project(":SchematicSystem:SchematicSystem_15")) + implementation(project(":SchematicSystem:SchematicSystem_19")) } diff --git a/SpigotCore/SpigotCore_14/src/de/steamwar/techhider/BlockIds14.java b/SpigotCore/SpigotCore_14/src/de/steamwar/techhider/BlockIds14.java index ebf5e952..6e2c0397 100644 --- a/SpigotCore/SpigotCore_14/src/de/steamwar/techhider/BlockIds14.java +++ b/SpigotCore/SpigotCore_14/src/de/steamwar/techhider/BlockIds14.java @@ -66,8 +66,8 @@ public class BlockIds14 implements BlockIds { return getBlock.invoke(null, material); } - private static final Reflection.Method getCombinedId = Reflection.getTypedMethod(TechHider.block, null, int.class, TechHider.iBlockData); - private int getCombinedId(Object blockData) { + @Override + public int getCombinedId(Object blockData) { return (int) getCombinedId.invoke(null, blockData); } } diff --git a/SpigotCore/SpigotCore_8/src/de/steamwar/techhider/BlockIds8.java b/SpigotCore/SpigotCore_8/src/de/steamwar/techhider/BlockIds8.java index 538e8dbd..64ac6c41 100644 --- a/SpigotCore/SpigotCore_8/src/de/steamwar/techhider/BlockIds8.java +++ b/SpigotCore/SpigotCore_8/src/de/steamwar/techhider/BlockIds8.java @@ -25,6 +25,12 @@ import java.util.Collections; import java.util.Set; public class BlockIds8 implements BlockIds { + @Override + public int getCombinedId(Object iBlockData) { + int id = (int) getCombinedId.invoke(null, iBlockData); // blockState << 12 | blockId + return (id & 4095) | (id >> 12); + } + @Override @SuppressWarnings("deprecation") public int materialToId(Material material) { diff --git a/SpigotCore/SpigotCore_Main/src/com/comphenix/tinyprotocol/TinyProtocol.java b/SpigotCore/SpigotCore_Main/src/com/comphenix/tinyprotocol/TinyProtocol.java index 7cca9c95..6f1dbf1a 100644 --- a/SpigotCore/SpigotCore_Main/src/com/comphenix/tinyprotocol/TinyProtocol.java +++ b/SpigotCore/SpigotCore_Main/src/com/comphenix/tinyprotocol/TinyProtocol.java @@ -23,6 +23,7 @@ import de.steamwar.Reflection; import de.steamwar.Reflection.Field; import de.steamwar.core.Core; import io.netty.channel.*; +import lombok.Getter; import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; @@ -67,8 +68,20 @@ public class TinyProtocol implements Listener { private boolean closed; private final Map, List>> packetFilters = new HashMap<>(); + @Getter private final Map playerInterceptors = new HashMap<>(); + @Override + public String toString() { + return "TinyProtocol{" + + "plugin=" + plugin + + ", connections=" + connections + + ", closed=" + closed + + ", packetFilters=" + packetFilters + + ", playerInterceptors=" + playerInterceptors + + '}'; + } + private TinyProtocol(final Plugin plugin) { this.plugin = plugin; this.connections = networkManagers.get(getServerConnection(plugin)); @@ -82,6 +95,7 @@ public class TinyProtocol implements Listener { @EventHandler(priority = EventPriority.LOWEST) public void onPlayerLogin(PlayerLoginEvent e) { + plugin.getLogger().info("Creating PacketInterceptor for: " + e.getPlayer().getName() + " (" + closed + ")"); if(closed) return; new PacketInterceptor(e.getPlayer()); @@ -116,6 +130,8 @@ public class TinyProtocol implements Listener { } public final void close() { + plugin.getLogger().log(Level.INFO, "Closing PacketInterceptor", new Exception("Stacktrace")); + if(closed) return; closed = true; @@ -136,17 +152,18 @@ public class TinyProtocol implements Listener { private static final Field getChannel = Reflection.getField(networkManager, Channel.class, 0); private static final Field getUUID = Reflection.getField(networkManager, UUID.class, 0); - private final class PacketInterceptor extends ChannelDuplexHandler { + public final class PacketInterceptor extends ChannelDuplexHandler { private final Player player; + @Getter private final Channel channel; private PacketInterceptor(Player player) { this.player = player; - channel = getChannel.get(connections.stream().filter(connection -> player.getUniqueId().equals(getUUID.get(connection))).findAny().orElseThrow(() -> { + channel = connections.stream().filter(connection -> player.getUniqueId().equals(getUUID.get(connection))).map(getChannel::get).filter(Channel::isActive).findAny().orElseThrow(() -> { Bukkit.getScheduler().runTask(plugin, () -> player.kickPlayer("Connection failure.")); return new SecurityException("Could not find channel for player " + player.getName()); - })); + }); if(!channel.isActive()) return; @@ -154,14 +171,15 @@ public class TinyProtocol implements Listener { synchronized (playerInterceptors) { playerInterceptors.put(player, this); } + plugin.getLogger().info("Adding Techhider for: " + player.getName()); try { channel.pipeline().addBefore("packet_handler", HANDLER_NAME, this); - } catch (IllegalArgumentException e) { + } catch (IllegalArgumentException | NoSuchElementException e) { Bukkit.getScheduler().runTask(plugin, () -> player.kickPlayer("Connection failure.")); throw new SecurityException(e); } - } + } private void sendPacket(Object packet) { channel.pipeline().writeAndFlush(packet); diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/sql/PersonalKit.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/sql/PersonalKit.java index fcc5a092..36e31490 100644 --- a/SpigotCore/SpigotCore_Main/src/de/steamwar/sql/PersonalKit.java +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/sql/PersonalKit.java @@ -1,7 +1,7 @@ /* This file is a part of the SteamWar software. - Copyright (C) 2020 SteamWar.de-Serverteam + Copyright (C) 2020 SteamWar.de-Serverteam This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/sql/SchematicData.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/sql/SchematicData.java index 62f00369..5ab944dc 100644 --- a/SpigotCore/SpigotCore_Main/src/de/steamwar/sql/SchematicData.java +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/sql/SchematicData.java @@ -1,7 +1,7 @@ /* * This file is a part of the SteamWar software. * - * Copyright (C) 2022 SteamWar.de-Serverteam + * Copyright (C) 2025 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 diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/BlockIds.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/BlockIds.java index 8e129a1d..fa2f7f6e 100644 --- a/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/BlockIds.java +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/BlockIds.java @@ -19,6 +19,7 @@ package de.steamwar.techhider; +import de.steamwar.Reflection; import de.steamwar.core.Core; import de.steamwar.core.VersionDependent; import org.bukkit.Material; @@ -28,6 +29,9 @@ import java.util.Set; public interface BlockIds { BlockIds impl = VersionDependent.getVersionImpl(Core.getInstance()); + Reflection.Method getCombinedId = Reflection.getTypedMethod(TechHider.block, null, int.class, TechHider.iBlockData); + + int getCombinedId(Object iBlockData); int materialToId(Material material); Set materialToAllIds(Material material); } diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/TechHider.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/TechHider.java index 03063eb8..021d2fe4 100644 --- a/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/TechHider.java +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/TechHider.java @@ -49,10 +49,8 @@ public class TechHider { public static final Class craftMagicNumbers = Reflection.getClass("org.bukkit.craftbukkit.util.CraftMagicNumbers"); private static final Reflection.Method getBlockByMaterial = Reflection.getTypedMethod(craftMagicNumbers, "getBlock", block, Material.class); - private static final Reflection.Method getBlockByBlockData = Reflection.getTypedMethod(iBlockData, null, block); - private static final Reflection.Method getMaterialByBlock = Reflection.getTypedMethod(craftMagicNumbers, "getMaterial", Material.class, block); public boolean iBlockDataHidden(Object iBlockData) { - return obfuscate.contains((Material) getMaterialByBlock.invoke(null, getBlockByBlockData.invoke(iBlockData))); + return obfuscateIds.contains(BlockIds.impl.getCombinedId(iBlockData)); } public static final Object AIR = getBlockDataByBlock.invoke(getBlockByMaterial.invoke(null, Material.AIR)); @@ -66,15 +64,12 @@ public class TechHider { @Getter private final int obfuscationTargetId; @Getter - private final Set obfuscate; - @Getter private final Set obfuscateIds; @Getter private final Set hiddenBlockEntities; public TechHider(LocationEvaluator locationEvaluator, Material obfuscationTarget, Set obfuscate, Set hiddenBlockEntities) { this.locationEvaluator = locationEvaluator; - this.obfuscate = obfuscate; this.obfuscateIds = obfuscate.stream().flatMap(m -> BlockIds.impl.materialToAllIds(m).stream()).collect(Collectors.toSet()); this.hiddenBlockEntities = hiddenBlockEntities; this.obfuscationTarget = getBlockDataByBlock.invoke(getBlockByMaterial.invoke(null, obfuscationTarget)); diff --git a/TNTLeague/src/de/steamwar/tntleague/events/IngameListener.kt b/TNTLeague/src/de/steamwar/tntleague/events/IngameListener.kt index f3722c22..7ae0618f 100644 --- a/TNTLeague/src/de/steamwar/tntleague/events/IngameListener.kt +++ b/TNTLeague/src/de/steamwar/tntleague/events/IngameListener.kt @@ -35,6 +35,8 @@ import org.bukkit.event.player.PlayerAttemptPickupItemEvent import org.bukkit.event.player.PlayerInteractEntityEvent import org.bukkit.event.player.PlayerJoinEvent import org.bukkit.event.player.PlayerMoveEvent +import org.bukkit.event.player.* +import org.bukkit.persistence.PersistentDataType object IngameListener : Listener { @@ -75,9 +77,9 @@ object IngameListener : Listener { @EventHandler fun onPickupCoins(e: PlayerAttemptPickupItemEvent) { - if (e.item.itemStack.isSimilar(DealerInventory.coins)) { - TNTLeagueGame.getTeam(e.player)?.coins = - e.item.itemStack.amount + (TNTLeagueGame.getTeam(e.player)?.coins ?: 0) + if (e.item.itemStack.persistentDataContainer.has(DealerInventory.coinKey)) { + val numberOfCoins = e.item.itemStack.persistentDataContainer[DealerInventory.coinKey, PersistentDataType.INTEGER] ?: 0 + TNTLeagueGame.getTeam(e.player)?.coins = (e.item.itemStack.amount * numberOfCoins) + (TNTLeagueGame.getTeam(e.player)?.coins ?: 0) e.item.itemStack.amount = 0 e.isCancelled = true diff --git a/TNTLeague/src/de/steamwar/tntleague/game/TNTLeagueGame.kt b/TNTLeague/src/de/steamwar/tntleague/game/TNTLeagueGame.kt index 80c86314..440cfa37 100644 --- a/TNTLeague/src/de/steamwar/tntleague/game/TNTLeagueGame.kt +++ b/TNTLeague/src/de/steamwar/tntleague/game/TNTLeagueGame.kt @@ -24,8 +24,6 @@ import de.steamwar.message.SubMessage import de.steamwar.network.NetworkSender import de.steamwar.network.packets.common.FightInfoPacket import de.steamwar.scoreboard.SWScoreboard -import de.steamwar.sql.Fight -import de.steamwar.sql.FightPlayer import de.steamwar.sql.SteamwarUser import de.steamwar.tntleague.colorByTeam import de.steamwar.tntleague.config.TNTLeagueConfig @@ -37,10 +35,9 @@ import de.steamwar.tntleague.events.LobbyListener import de.steamwar.tntleague.inventory.DealerInventory import de.steamwar.tntleague.message import de.steamwar.tntleague.plugin -import de.steamwar.tntleague.util.* +import de.steamwar.tntleague.util.TNTLeagueScoreboard import org.bukkit.GameMode import org.bukkit.Location -import org.bukkit.Material import org.bukkit.Sound import org.bukkit.entity.Item import org.bukkit.entity.Player @@ -51,6 +48,7 @@ import org.bukkit.inventory.ItemStack import org.bukkit.scheduler.BukkitTask import java.sql.Timestamp import java.time.Instant +import kotlin.random.Random object TNTLeagueGame { var state: GameState = GameState.LOBBY @@ -87,18 +85,24 @@ object TNTLeagueGame { message.broadcast("GAME_STARTED") - val tnt = ItemStack(Material.TNT) - start = Timestamp.from(Instant.now()) + var spawnCount = 0 spawnerTask = plugin.server.scheduler.runTaskTimer(plugin, bukkit { + val coinsToSpawn = if (spawnCount % 28 == 0) { + DealerInventory.huge_coins + } else if (spawnCount % 7 == 0) { + DealerInventory.big_coins + } else { + DealerInventory.coins + } + spawnCount++ + if (world.getNearbyEntitiesByType(Item::class.java, TNTLeagueWorldConfig.blueTeam.itemSpawn, 3.0).sumOf { it.itemStack.amount } <= 256) { - spawnItems(TNTLeagueWorldConfig.blueTeam.itemSpawn, tnt) - spawnItems(TNTLeagueWorldConfig.blueTeam.itemSpawn, DealerInventory.coins) + spawnItems(TNTLeagueWorldConfig.blueTeam.itemSpawn, coinsToSpawn) } if (world.getNearbyEntitiesByType(Item::class.java, TNTLeagueWorldConfig.redTeam.itemSpawn, 3.0).sumOf { it.itemStack.amount } <= 256) { - spawnItems(TNTLeagueWorldConfig.redTeam.itemSpawn, tnt) - spawnItems(TNTLeagueWorldConfig.redTeam.itemSpawn, DealerInventory.coins) + spawnItems(TNTLeagueWorldConfig.redTeam.itemSpawn, coinsToSpawn) } }, 5, 10) diff --git a/TNTLeague/src/de/steamwar/tntleague/inventory/DealerInventory.kt b/TNTLeague/src/de/steamwar/tntleague/inventory/DealerInventory.kt index 418c15fb..c9bbe635 100644 --- a/TNTLeague/src/de/steamwar/tntleague/inventory/DealerInventory.kt +++ b/TNTLeague/src/de/steamwar/tntleague/inventory/DealerInventory.kt @@ -59,13 +59,31 @@ class DealerInventory(player: Player): KotlinInventory(player) { companion object { private val priceKey = NamespacedKey(plugin, "price") private val amountKey = NamespacedKey(plugin, "amount") - private val coinKey = NamespacedKey(plugin, "coin") + val coinKey = NamespacedKey(plugin, "coin") val coins = ItemStack(Material.RAW_GOLD).apply { itemMeta = itemMeta.apply { displayName(Component.text("Coins").color(NamedTextColor.GOLD)) persistentDataContainer.apply { - set(coinKey, PersistentDataType.BOOLEAN, true) + set(coinKey, PersistentDataType.INTEGER, 1) + } + } + } + + val big_coins = ItemStack(Material.GOLD_INGOT).apply { + itemMeta = itemMeta.apply { + displayName(Component.text("Big Coins").color(NamedTextColor.GOLD)) + persistentDataContainer.apply { + set(coinKey, PersistentDataType.INTEGER, 3) + } + } + } + + val huge_coins = ItemStack(Material.GOLD_BLOCK).apply { + itemMeta = itemMeta.apply { + displayName(Component.text("Huge Coins").color(NamedTextColor.GOLD)) + persistentDataContainer.apply { + set(coinKey, PersistentDataType.INTEGER, 9) } } } diff --git a/TowerRun/src/TowerRun.properties b/TowerRun/src/TowerRun.properties index 88c2ecd9..0935bd83 100644 --- a/TowerRun/src/TowerRun.properties +++ b/TowerRun/src/TowerRun.properties @@ -17,20 +17,23 @@ # along with this program. If not, see . # -PREFIX=eTowerRun8r +PREFIX=§eTowerRun§8»§r -PLAYER_DIED=c{0} 7died8! -PLAYER_ESCAPE=a{0} 7escaped8! -GAME_START=aThe game has started8! -GAME_WIN=a{0} 7has won the game8! -GAME_STARTING=7Starting: e{0}s8! -GAME_WAITING=7Waiting for players8... -SERVER_STOPPING=cThe server stops in e{0}s8! -SERVER_RESET=cThe server will be reset in e{0}s8! -KEY_NAME=eKey -KEY_FOUND=a{0} 7found a key8! -GAME_TIE=aThe game ended in a tie8! -GAME_TIME=a{0}:{1} -CATCH_UP_WARNING=4!! cYou should catch up 4!! +PLAYER_DIED=§c{0} §7died§8! +PLAYER_ESCAPE=§a{0} §7escaped§8! +GAME_START=§aThe game has started§8! +GAME_WIN=§a{0} §7has won the game§8! +GAME_STARTING=§7Starting: §e{0}s§8! +GAME_WAITING=§7Waiting for players§8... +SERVER_STOPPING=§cThe server stops in §e{0}s§8! +SERVER_RESET=§cThe server will be reset in §e{0}s§8! +KEY_NAME=§eKey +KEY_FOUND=§a{0} §7found a key§8! +GAME_TIE=§aThe game ended in a tie§8! +GAME_TIME=§a{0}:{1} +CATCH_UP_WARNING=§4!! §cYou should catch up §4!! -COMMAND_START=aThe game will start soon8! \ No newline at end of file +COMMAND_START=§aThe game will start soon§8! + +PARTICIPANT_CHAT={0} {1}§8» §7{2} +SPECTATOR_CHAT=§7{0}§8» §7{1} \ No newline at end of file diff --git a/TowerRun/src/TowerRun_de.properties b/TowerRun/src/TowerRun_de.properties index 2c88c3b6..82fd014b 100644 --- a/TowerRun/src/TowerRun_de.properties +++ b/TowerRun/src/TowerRun_de.properties @@ -17,19 +17,19 @@ # along with this program. If not, see . # -PLAYER_DIED=c{0} 7ist gestorben8! -PLAYER_ESCAPE=a{0} 7ist entkommen8! -GAME_START=aDas Spiel beginnt8! -GAME_WIN=a{0} 7hat das Spiel gewonnen8! -GAME_STARTING=7Das Spiel startet in e{0}s8! -GAME_WAITING=7Warte auf weitere Spieler8... -SERVER_STOPPING=cDer Server stoppt in e{0}s8! -SERVER_RESET=cDer Server wird in e{0}s czurckgesetzt8! -GAME_TIE=7Keiner hat gewonnen8! +PLAYER_DIED=§c{0} §7ist gestorben§8! +PLAYER_ESCAPE=§a{0} §7ist entkommen§8! +GAME_START=§aDas Spiel beginnt§8! +GAME_WIN=§a{0} §7hat das Spiel gewonnen§8! +GAME_STARTING=§7Das Spiel startet in §e{0}s§8! +GAME_WAITING=§7Warte auf weitere Spieler§8... +SERVER_STOPPING=§cDer Server stoppt in §e{0}s§8! +SERVER_RESET=§cDer Server wird in §e{0}s §czur§ckgesetzt§8! +GAME_TIE=§7Keiner hat gewonnen§8! -KEY_NAME=eSchlssel -KEY_FOUND=a{0} 7hat einen Schlssel gefunden8! +KEY_NAME=§eSchl§ssel +KEY_FOUND=§a{0} §7hat einen Schl§ssel gefunden§8! -CATCH_UP_WARNING=4!! cDu solltest aufholen 4!! +CATCH_UP_WARNING=§4!! §cDu solltest aufholen §4!! -COMMAND_START=7Das Spiel startet bald8! \ No newline at end of file +COMMAND_START=§7Das Spiel startet bald§8! \ No newline at end of file diff --git a/TowerRun/src/de/steamwar/towerrun/TowerRun.java b/TowerRun/src/de/steamwar/towerrun/TowerRun.java index 7e6df112..4503c5da 100644 --- a/TowerRun/src/de/steamwar/towerrun/TowerRun.java +++ b/TowerRun/src/de/steamwar/towerrun/TowerRun.java @@ -80,7 +80,5 @@ public class TowerRun extends JavaPlugin { gameCountdown = new GameCountdown(); Bukkit.getScheduler().runTaskTimer(this, new FightInfoPacketSender(), 20, 20); - - TowerRunGame.reset(); } } diff --git a/TowerRun/src/de/steamwar/towerrun/config/WorldConfig.java b/TowerRun/src/de/steamwar/towerrun/config/WorldConfig.java index fafdd453..56e90034 100644 --- a/TowerRun/src/de/steamwar/towerrun/config/WorldConfig.java +++ b/TowerRun/src/de/steamwar/towerrun/config/WorldConfig.java @@ -35,7 +35,8 @@ import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.util.Vector; import java.io.File; -import java.util.*; +import java.util.ArrayList; +import java.util.List; @UtilityClass public class WorldConfig { @@ -54,7 +55,7 @@ public class WorldConfig { public static final int MAP_MIN_Z; public static final int MAP_MAX_X; public static final int MAP_MAX_Z; - public static final Map MELTING_TIMES; + public static final boolean MELTING; public static final TowerGeneratorConfig TOWER_GENERATOR_CONFIG; public static final List WINCONDITIONS = new ArrayList<>(); @@ -161,16 +162,7 @@ public class WorldConfig { MAP_MAX_X = config.getInt("maxX"); MAP_MAX_Z = config.getInt("maxZ"); - ConfigurationSection meltingBlocksSection = tower.getConfigurationSection("meltingBlocks"); - if (meltingBlocksSection != null) { - Map meltingTimes = new HashMap<>(); - meltingBlocksSection.getKeys(false).forEach(s -> { - meltingTimes.put(Material.valueOf(s), meltingBlocksSection.getInt(s)); - }); - MELTING_TIMES = Collections.unmodifiableMap(meltingTimes); - } else { - MELTING_TIMES = Collections.emptyMap(); - } + MELTING = tower.getBoolean("melting") || tower.contains("meltingBlocks"); // Backwards compatibility with meltingBlocks key! ACTIVE_WINCONDITIONS = config.getStringList("winconditions"); WINCONDITIONS.stream().filter(winCondition -> ACTIVE_WINCONDITIONS.contains(winCondition.getName())).forEach(winCondition -> winCondition.setActive(true)); diff --git a/TowerRun/src/de/steamwar/towerrun/countdowns/EndCountdown.java b/TowerRun/src/de/steamwar/towerrun/countdowns/EndCountdown.java index dbe0d40d..6d631e02 100644 --- a/TowerRun/src/de/steamwar/towerrun/countdowns/EndCountdown.java +++ b/TowerRun/src/de/steamwar/towerrun/countdowns/EndCountdown.java @@ -20,6 +20,7 @@ package de.steamwar.towerrun.countdowns; import de.steamwar.towerrun.TowerRun; +import de.steamwar.towerrun.config.Config; import de.steamwar.towerrun.game.TowerRunGame; import de.steamwar.towerrun.state.GameStates; import org.bukkit.Bukkit; @@ -41,14 +42,18 @@ public class EndCountdown extends Countdown { @Override int defaultTime() { - return 10; + return 30; } @Override void timerEnd() { Bukkit.getOnlinePlayers().forEach(player -> player.playSound(player.getLocation(), Sound.BLOCK_NOTE_BLOCK_PLING, 1, 1)); if (RESETS) { - TowerRunGame.reset(); + if (Config.event()) { + Bukkit.shutdown(); + } else { + TowerRunGame.reset(); + } lobbyCountdown.setTime(lobbyCountdown.defaultTime()); } else { Bukkit.shutdown(); diff --git a/TowerRun/src/de/steamwar/towerrun/game/TowerRunGame.java b/TowerRun/src/de/steamwar/towerrun/game/TowerRunGame.java index 2c014cb5..c1514db4 100644 --- a/TowerRun/src/de/steamwar/towerrun/game/TowerRunGame.java +++ b/TowerRun/src/de/steamwar/towerrun/game/TowerRunGame.java @@ -46,6 +46,10 @@ public class TowerRunGame { public static final List PLAYERS_ESCAPED = new ArrayList<>(); private static final World world = Bukkit.getWorlds().get(0); + public static boolean isEscaped(TowerRunPlayer player) { + return PLAYERS_ESCAPED.contains(player); + } + public static boolean isAlive(TowerRunPlayer player) { return PLAYERS_ALIVE.contains(player); } @@ -143,6 +147,7 @@ public class TowerRunGame { player.setGameMode(GameMode.SURVIVAL); } player.teleport(WorldConfig.SPAWN); + PLAYERS_ALIVE.add(TowerRunPlayer.get(player)); }); } diff --git a/TowerRun/src/de/steamwar/towerrun/generator/TowerGenerator.java b/TowerRun/src/de/steamwar/towerrun/generator/TowerGenerator.java index 4f379547..63cd94ee 100644 --- a/TowerRun/src/de/steamwar/towerrun/generator/TowerGenerator.java +++ b/TowerRun/src/de/steamwar/towerrun/generator/TowerGenerator.java @@ -140,8 +140,10 @@ public class TowerGenerator { noKeyFloors--; if (!chestBlocks.isEmpty() && noKeyFloors < 0 && random.nextDouble() < config.keyChance) { noKeyFloors = random.nextInt(config.maxNoKeyFloors - config.minNoKeyFloors) + config.minNoKeyFloors; - Container container = chestBlocks.get(random.nextInt(chestBlocks.size())); - keys.add(container.getLocation()); + for (int i = 0; i < 2; i++) { + Container container = chestBlocks.get(random.nextInt(chestBlocks.size())); + keys.add(container.getLocation()); + } for (WorldConfig.TowerGeneratorDoorBlock doorBlock : config.doorBlocks) { int x = doorBlock.getX(); diff --git a/TowerRun/src/de/steamwar/towerrun/listener/GlobalListener.java b/TowerRun/src/de/steamwar/towerrun/listener/GlobalListener.java index 5c2956b2..c20dd391 100644 --- a/TowerRun/src/de/steamwar/towerrun/listener/GlobalListener.java +++ b/TowerRun/src/de/steamwar/towerrun/listener/GlobalListener.java @@ -19,20 +19,20 @@ package de.steamwar.towerrun.listener; +import de.steamwar.towerrun.TowerRun; import de.steamwar.towerrun.config.WorldConfig; import de.steamwar.towerrun.game.TowerRunGame; import de.steamwar.towerrun.game.TowerRunPlayer; +import de.steamwar.towerrun.state.GameState; import de.steamwar.towerrun.state.GameStateBukkitListener; import de.steamwar.towerrun.state.GameStates; +import lombok.val; import org.bukkit.Bukkit; +import org.bukkit.GameMode; import org.bukkit.Location; -import org.bukkit.World; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; -import org.bukkit.event.player.PlayerJoinEvent; -import org.bukkit.event.player.PlayerMoveEvent; -import org.bukkit.event.player.PlayerQuitEvent; -import org.bukkit.event.player.PlayerRespawnEvent; +import org.bukkit.event.player.*; import java.util.EnumSet; @@ -67,4 +67,25 @@ public class GlobalListener extends GameStateBukkitListener implements Listener public void onPlayerRespawn(PlayerRespawnEvent event) { event.setRespawnLocation(WorldConfig.SPAWN); } + + @EventHandler + public void onAsyncPlayerChat(AsyncPlayerChatEvent event) { + TowerRunPlayer player = TowerRunPlayer.get(event.getPlayer()); + if (GameState.getCurrentState() == GameStates.RUNNING && (TowerRunGame.isAlive(player) || TowerRunGame.isEscaped(player))) { + String prefix; + if (TowerRunGame.isAlive(player)) { + if (event.getPlayer().getGameMode() == GameMode.SPECTATOR) { + prefix = "§c☠"; + } else { + prefix = "§6❤"; + } + } else { + prefix = "§a✔"; + } + TowerRun.getMessage().broadcastPrefixless("PARTICIPANT_CHAT", prefix, event.getPlayer().getName(), event.getMessage()); + } else { + TowerRun.getMessage().broadcastPrefixless("SPECTATOR_CHAT", event.getPlayer().getName(), event.getMessage()); + } + event.setCancelled(true); + } } diff --git a/TowerRun/src/de/steamwar/towerrun/listener/IngameListener.java b/TowerRun/src/de/steamwar/towerrun/listener/IngameListener.java index befc7d47..bc74e57f 100644 --- a/TowerRun/src/de/steamwar/towerrun/listener/IngameListener.java +++ b/TowerRun/src/de/steamwar/towerrun/listener/IngameListener.java @@ -26,6 +26,8 @@ import de.steamwar.towerrun.config.WorldConfig; import de.steamwar.towerrun.game.TowerRunGame; import de.steamwar.towerrun.state.GameStateBukkitListener; import de.steamwar.towerrun.state.GameStates; +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; import org.bukkit.*; import org.bukkit.block.Block; import org.bukkit.entity.EntityType; @@ -42,16 +44,24 @@ import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.scheduler.BukkitRunnable; import java.util.*; -import java.util.function.Function; +import java.util.stream.Collectors; import java.util.stream.Stream; public class IngameListener extends GameStateBukkitListener { private int time = 0; - private final Map> blocksToMelt = new HashMap<>(); + private final Map blocksToMelt = new HashMap<>(); private BukkitRunnable blocksToMeltRunnable; private BukkitRunnable antiCampRunnable; + @AllArgsConstructor + @EqualsAndHashCode + private class Pos { + private final int x; + private final int y; + private final int z; + } + public IngameListener() { super(EnumSet.of(GameStates.RUNNING)); } @@ -62,16 +72,21 @@ public class IngameListener extends GameStateBukkitListener { blocksToMeltRunnable = new BukkitRunnable() { @Override public void run() { - List blocks = blocksToMelt.get(time); + List blocksToBreak = blocksToMelt.entrySet().stream() + .filter(entry -> entry.getValue() <= time) + .map(Map.Entry::getKey) + .collect(Collectors.toList()); time++; - if (blocks == null) { + if (blocksToBreak.isEmpty()) { return; } - blocks.forEach(block -> { - if (!WorldConfig.MELTING_TIMES.containsKey(block.getType())) return; + for (Pos pos : blocksToBreak) { + blocksToMelt.remove(pos); + Block block = Bukkit.getWorlds().get(0).getBlockAt(pos.x, pos.y, pos.z); + if (block.getType() == Material.AIR || block.getType() == Material.LAVA) continue; block.setType(Material.AIR); block.getWorld().playSound(block.getLocation(), Sound.BLOCK_FIRE_EXTINGUISH, 0.1F, 1); - }); + } } }; blocksToMeltRunnable.runTaskTimer(TowerRun.getInstance(), 0, 1); @@ -80,16 +95,16 @@ public class IngameListener extends GameStateBukkitListener { @Override public void run() { double minY = TowerRunGame.PLAYERS_ALIVE.stream() - .map(p -> p.player().getLocation().getY()) - .min(Comparator.comparing(Function.identity())) + .mapToDouble(p -> p.player().getLocation().getY()) + .average() .orElse(0.0); List toDamage = new ArrayList<>(); TowerRunGame.PLAYERS_ALIVE.forEach(towerRunPlayer -> { - if (towerRunPlayer.player().getLocation().getY() - minY > 20) { - towerRunPlayer.player().sendTitle("§a", TowerRun.getMessage().parse("CATCH_UP_WARNING", towerRunPlayer.player()), 5, 30, 5); - } if (towerRunPlayer.player().getLocation().getY() - minY > 30) { + towerRunPlayer.player().sendTitle("", TowerRun.getMessage().parse("CATCH_UP_WARNING", towerRunPlayer.player()), 5, 30, 5); + } + if (towerRunPlayer.player().getLocation().getY() - minY > 50) { toDamage.add(towerRunPlayer.player()); } }); @@ -115,12 +130,12 @@ public class IngameListener extends GameStateBukkitListener { public void onPlayerDeath(PlayerDeathEvent event) { event.setDeathMessage(null); Bukkit.getScheduler().runTaskLater(TowerRun.getInstance(), () -> { - if (TowerRun.getTowerGenerator() != null) { - event.getEntity().teleport(TowerRun.getTowerGenerator().getSpawn()); - } else { - event.getEntity().teleport(WorldConfig.SPAWN); - } - }, 5 + if (TowerRun.getTowerGenerator() != null) { + event.getEntity().teleport(TowerRun.getTowerGenerator().getSpawn()); + } else { + event.getEntity().teleport(WorldConfig.SPAWN); + } + }, 5 ); event.getEntity().setGameMode(GameMode.SPECTATOR); Bukkit.getOnlinePlayers().forEach(player -> { @@ -181,14 +196,19 @@ public class IngameListener extends GameStateBukkitListener { } event.getPlayer().getInventory().addItem(new SWItem(Material.LEVER, TowerRun.getMessage().parse("KEY_NAME", event.getPlayer())).getItemStack()); - event.getClickedBlock().setType(Material.ENDER_CHEST); - event.getPlayer().playSound(event.getPlayer().getLocation(), Sound.BLOCK_ENDER_CHEST_OPEN, 1, 1); - TowerRun.getMessage().broadcast("KEY_FOUND", event.getPlayer().getName()); + + Bukkit.getOnlinePlayers().forEach(player -> { + player.playSound(event.getPlayer().getLocation(), Sound.BLOCK_ENDER_CHEST_OPEN, 1, 1); + player.sendTitle("", TowerRun.getMessage().parse("KEY_FOUND", player, event.getPlayer().getName()), 10, 70, 20); + }); } @EventHandler public void onBlockPhysics(BlockPhysicsEvent event) { + if (!WorldConfig.MELTING) { + return; + } if (event.getSourceBlock().getType() != Material.LAVA) { return; } @@ -202,11 +222,52 @@ public class IngameListener extends GameStateBukkitListener { } private void shouldMelt(Block block) { - int meltingTime = WorldConfig.MELTING_TIMES.getOrDefault(block.getType(), -1); - if (meltingTime == -1) { - return; + if (block.getType().isBurnable()) return; + if (block.getType().isAir()) return; + if (block.isLiquid()) return; + int meltingTime = (int) (block.getType().getHardness() * 48 * 20); + switch (block.getType()) { + case TINTED_GLASS: + meltingTime = meltingTime * 2; + break; + case WHITE_STAINED_GLASS: + case ORANGE_STAINED_GLASS: + case MAGENTA_STAINED_GLASS: + case LIGHT_BLUE_STAINED_GLASS: + case YELLOW_STAINED_GLASS: + case LIME_STAINED_GLASS: + case PINK_STAINED_GLASS: + case GRAY_STAINED_GLASS: + case LIGHT_GRAY_STAINED_GLASS: + case CYAN_STAINED_GLASS: + case PURPLE_STAINED_GLASS: + case BLUE_STAINED_GLASS: + case BROWN_STAINED_GLASS: + case GREEN_STAINED_GLASS: + case RED_STAINED_GLASS: + case BLACK_STAINED_GLASS: + case WHITE_STAINED_GLASS_PANE: + case ORANGE_STAINED_GLASS_PANE: + case MAGENTA_STAINED_GLASS_PANE: + case LIGHT_BLUE_STAINED_GLASS_PANE: + case YELLOW_STAINED_GLASS_PANE: + case LIME_STAINED_GLASS_PANE: + case PINK_STAINED_GLASS_PANE: + case GRAY_STAINED_GLASS_PANE: + case LIGHT_GRAY_STAINED_GLASS_PANE: + case CYAN_STAINED_GLASS_PANE: + case PURPLE_STAINED_GLASS_PANE: + case BLUE_STAINED_GLASS_PANE: + case BROWN_STAINED_GLASS_PANE: + case GREEN_STAINED_GLASS_PANE: + case RED_STAINED_GLASS_PANE: + case BLACK_STAINED_GLASS_PANE: + meltingTime = meltingTime * 10; + default: + break; } - blocksToMelt.computeIfAbsent(time + meltingTime * 20, integer -> new ArrayList<>()).add(block); + Pos pos = new Pos(block.getLocation().getBlockX(), block.getLocation().getBlockY(), block.getLocation().getBlockZ()); + blocksToMelt.putIfAbsent(pos, time + meltingTime + 1); } @EventHandler diff --git a/TowerRun/src/de/steamwar/towerrun/listener/LobbyListener.java b/TowerRun/src/de/steamwar/towerrun/listener/LobbyListener.java index c93bc4bb..0a4e4358 100644 --- a/TowerRun/src/de/steamwar/towerrun/listener/LobbyListener.java +++ b/TowerRun/src/de/steamwar/towerrun/listener/LobbyListener.java @@ -68,6 +68,8 @@ public class LobbyListener extends GameStateBukkitListener { if (TowerRunGame.PLAYERS_ALIVE.stream().map(towerRunPlayer -> SteamwarUser.get(towerRunPlayer.player().getUniqueId()).getTeam()).filter(integer -> integer == team).count() < Config.EVENT_MAXIMUM_TEAM_MEMBERS) { TowerRunGame.PLAYERS_ALIVE.add(TowerRunPlayer.get(player)); + } else { + player.setGameMode(GameMode.SPECTATOR); } } else { TowerRunGame.PLAYERS_ALIVE.add(TowerRunPlayer.get(player)); diff --git a/VelocityCore/build.gradle.kts b/VelocityCore/build.gradle.kts index 844e9f21..f81416a3 100644 --- a/VelocityCore/build.gradle.kts +++ b/VelocityCore/build.gradle.kts @@ -66,4 +66,12 @@ dependencies { implementation(libs.apolloprotos) implementation(libs.nbt) -} \ No newline at end of file +} + +tasks.register("DevVelocity") { + group = "run" + description = "Run a Dev Velocity" + dependsOn(":VelocityCore:shadowJar") + dependsOn(":VelocityCore:Persistent:jar") + template = "DevVelocity" +} diff --git a/VelocityCore/src/de/steamwar/messages/BungeeCore.properties b/VelocityCore/src/de/steamwar/messages/BungeeCore.properties index 863d1099..c46cd317 100644 --- a/VelocityCore/src/de/steamwar/messages/BungeeCore.properties +++ b/VelocityCore/src/de/steamwar/messages/BungeeCore.properties @@ -154,7 +154,7 @@ UNPUNISHMENT_USAGE=§8/§7{0} §8[§eplayer§8] PUNISHMENT_UNTIL=until {0} PUNISHMENT_PERMA=permanent -BAN_TEAM={0} §e{1} §7was §e§lbanned§7 by §e{2} {3}§8: §f{4} +BAN_TEAM=§e{0} §7was §e§lbanned§7 by §e{1} {2}§8: §f{3} BAN_PERMA=§7You are §e§lbanned §epermanently§8: §e{0} BAN_UNTIL=§7You are §e§lbanned §euntil {0}§8: §e{1} UNBAN_ERROR=§cThe player isn't banned. @@ -164,49 +164,49 @@ BAN_AVOIDING_ALERT=§cPotential ban bypass by §r{0}§c: {1} BAN_AVOIDING_LIST=§c{0} §e{1} BAN_AVOIDING_BAN_HOVER=§cBan player because of bann bypass. -MUTE_TEAM={0} §e{1} §7was §e§lmuted§7 by §e{2} {3}§8: §f{4} +MUTE_TEAM=§e{0} §7was §e§lmuted§7 by §e{1} {2}§8: §f{3} MUTE_PERMA=§7You are §epermanently §e§lmuted§8: §e{0} MUTE_UNTIL=§7You are §e§lmuted §euntil {0}§8: §e{1} UNMUTE_ERROR=§cThe player isn't muted. UNMUTE=§7You have §e§lunmuted §e{0}. -NOSCHEMRECEIVING_TEAM={0} §e{1} §7was excluded from §e{2} {3} §7from §e§lrecieving schematics§8: §f{4} +NOSCHEMRECEIVING_TEAM=§e{0} §7was excluded from §e{1} {2} §7from §e§lrecieving schematics§8: §f{3} NOSCHEMRECEIVING_PERMA=§7You are §epermanently§7 excluded from receiving §e§lschematics§8: §e{0} NOSCHEMRECEIVING_UNTIL=§7You are excluded from receiving §e§lschematics §euntil {0}§8: §e{1} UNNOSCHEMRECEIVING_ERROR=§cThe player is not excluded from receiving schematics. UNNOSCHEMRECEIVING=§e{0} §7may now receive §e§lschematics§7 again§8. -NOSCHEMSHARING_TEAM={0} §e{1} §7was excluded from §e{2} {3} §7from §e§lsharing schematics§8: §f{4} +NOSCHEMSHARING_TEAM=§e{0} §7was excluded from §e{1} {2} §7from §e§lsharing schematics§8: §f{3} NOSCHEMSHARING_PERMA=§7You are §epermanently§7 excluded from sharing §e§lschematics§8: §e{0} NOSCHEMSHARING_UNTIL=§7You are excluded from sharing §e§lschematics §euntil {0}§8: §e{1} UNNOSCHEMSHARING_ERROR=§cThe player is not excluded from sharing schematics. UNNOSCHEMSHARING=§e{0} §7may now share §e§lschematics§7 again§8. -NOSCHEMSUBMITTING_TEAM={0} §e{1} §7was excluded from §e{2} {3} §7from §e§lsubmitting schematics§8: §f{4} +NOSCHEMSUBMITTING_TEAM=§e{0} §7was excluded from §e{1} {2} §7from §e§lsubmitting schematics§8: §f{3} NOSCHEMSUBMITTING_PERMA=§7You are §epermanently§7 excluded from submitting §e§lschematics§8: §e{0} NOSCHEMSUBMITTING_UNTIL=§7You are excluded from submitting §e§lschematics §euntil {0}§8: §e{1} UNNOSCHEMSUBMITTING_ERROR=§cThe player is not excluded from submitting schematics. UNNOSCHEMSUBMITTING=§e{0} §7may now submit §e§lschematics§7 again§8. -NODEVSERVER_TEAM={0} §e{1} §7has annoyed §e{2} §7with reason §f{4}§7 and therefore has received §e§ldev server prohibition§7§8, §f{3} +NODEVSERVER_TEAM=§e{0} §7has annoyed §e{1} §7with reason §f{3}§7 and therefore has received §e§ldev server prohibition§7§8, §f{2} NODEVSERVER_PERMA=§7You are §epermanently§7 excluded from §e§ldev servers§8: §e{0} NODEVSERVER_UNTIL=§7You are excluded from §e§ldev servers§7 §euntil {0}§8: §e{1} UNNODEVSERVER_ERROR=§cThe player is not excluded from dev servers. UNNODEVSERVER=§e{0} §7may now join §e§ldev servers§7 again§8. -NOFIGHTSERVER_TEAM={0} §e{1} §7was excluded from §e{2} {3} §7from §e§lfighting§8: §f{4} +NOFIGHTSERVER_TEAM=§e{0} §7was excluded from §e{1} {2} §7from §e§lfighting§8: §f{3} NOFIGHTSERVER_PERMA=§7You are §epermanently§7 excluded from §e§lfighting§8: §e{0} NOFIGHTSERVER_UNTIL=§7You are excluded from §e§lfighting§7 §euntil {0}§8: §e{1} UNNOFIGHTSERVER_ERROR=§cThe player is not excluded from fighting. UNNOFIGHTSERVER=§e{0} §7may now join §e§lfights§7 again§8. -NOTEAMSERVER_TEAM={0} §e{1} §7was excluded from §e{2} {3} §7from §e§lteam servers§8: §f{4} +NOTEAMSERVER_TEAM=§e{0} §7was excluded from §e{1} {2} §7from §e§lteam servers§8: §f{3} NOTEAMSERVER_PERMA=§7You are §epermanently§7 excluded from §e§lteam servers§8: §e{0} NOTEAMSERVER_UNTIL=§7You are excluded from §e§lteam servers§7 §euntil {0}§8: §e{1} UNNOTEAMSERVER_ERROR=§cThe player is not excluded from team servers. UNNOTEAMSERVER=§e{0} §7may now set §e§lteam servers§7 again§8. -NOTE_TEAM={0} §e{1} §7received a §e§lnote§7 from §e{2} {3}: §f{4} +NOTE_TEAM=§e{0} §7received a §e§lnote§7 from §e{1} {2}: §f{3} #BugCommand BUG_MESSAGE=§7Please describe the issue in a Discord ticket with the bug ID §e{0} §7further§8. @@ -572,6 +572,7 @@ CHAT_NO_RECEIVER=§cNobody receives your message CHAT_EMPTY=§cDon\'t write meaningless empty messages. CHAT_SERVERTEAM=§8STC §e{0}§8» §f{2} +CHAT_DISCORD_SERVERTEAM=§8STC §e{0}§8» §f{2} CHAT_GLOBAL={3}{4}{5}{6}{0}§8» {7}{2} CHAT_DISCORD_GLOBAL=§8Dc {5}{6}{0}§8» {7}{2} CHAT_TEAM=§8TC §e{0}§8» §f{2} diff --git a/VelocityCore/src/de/steamwar/messages/BungeeCore_de.properties b/VelocityCore/src/de/steamwar/messages/BungeeCore_de.properties index b758353c..51a47cc3 100644 --- a/VelocityCore/src/de/steamwar/messages/BungeeCore_de.properties +++ b/VelocityCore/src/de/steamwar/messages/BungeeCore_de.properties @@ -138,7 +138,7 @@ UNPUNISHMENT_USAGE=§8/§7{0} §8[§eSpieler§8] PUNISHMENT_UNTIL=bis zum {0} PUNISHMENT_PERMA=permanent -BAN_TEAM={0} §e{1} §7wurde von §e{2} {3} §e§lgebannt§8. §7Grund§8: §f{4} +BAN_TEAM=§e{1} §7wurde von §e{2} {3} §e§lgebannt§8. §7Grund§8: §f{4} BAN_PERMA=§7Du bist §epermanent §e§lgebannt§8. §7Grund§8: §e{0} BAN_UNTIL=§7Du bist §ebis zum {0} §e§lgebannt§8. §7Grund§8: §e{1} UNBAN_ERROR=§cDer Spieler ist nicht gebannt. @@ -148,49 +148,49 @@ BAN_AVOIDING_ALERT=§cMögliche Bannumgehung durch §r{0}§c: {1} BAN_AVOIDING_LIST=§c{0} §e{1} BAN_AVOIDING_BAN_HOVER=§cBanne Spieler wegen Bannumgehung -MUTE_TEAM={0} §e{1} §7wurde von §e{2} {3} §e§lgemuted§8. §7Grund§8: §f{4} +MUTE_TEAM=§e{0} §7wurde von §e{1} {2} §e§lgemuted§8. §7Grund§8: §f{3} MUTE_PERMA=§7Du bist §epermanent §e§lgemuted§8. §7Grund§8: §e{0} MUTE_UNTIL=§7Du bist §ebis zum {0} §e§lgemuted§8. §7Grund§8: §e{1} UNMUTE_ERROR=§cDer Spieler ist nicht gemuted. UNMUTE=§7Du hast §e{0} §e§lentmuted. -NOSCHEMRECEIVING_TEAM={0} §e{1} §7wurde von §e{2} {3} §7vom §e§lSchematicerhalten§7 ausgeschlossen§8: §f{4} +NOSCHEMRECEIVING_TEAM=§e{0} §7wurde von §e{1} {2} §7vom §e§lSchematicerhalten§7 ausgeschlossen§8: §f{3} NOSCHEMRECEIVING_PERMA=§7Du bist §epermanent §7vom Erhalten von §e§lSchematics§7 ausgeschlossen§8: §e{0} NOSCHEMRECEIVING_UNTIL=§7Du bist §ebis zum {0} §7vom Erhalten von §e§lSchematics§7 ausgeschlossen§8: §e{1} UNNOSCHEMRECEIVING_ERROR=§cDer Spieler ist nicht vom Erhalten von Schematics ausgeschlossen. UNNOSCHEMRECEIVING=§e{0} §7darf nun wieder §e§lSchematics§7 erhalten§8. -NOSCHEMSHARING_TEAM={0} §e{1} §7wurde von §e{2} {3} §7vom §e§lSchematicverteilen§7 ausgeschlossen§8: §f{4} +NOSCHEMSHARING_TEAM=§e{0} §7wurde von §e{1} {2} §7vom §e§lSchematicverteilen§7 ausgeschlossen§8: §f{3} NOSCHEMSHARING_PERMA=§7Du bist §epermanent §7vom §e§lVerteilen von Schematics§7 ausgeschlossen§8: §e{0} NOSCHEMSHARING_UNTIL=§7Du bist §ebis zum {0} §7vom §e§lVerteilen von Schematics§7 ausgeschlossen§8: §e{1} UNNOSCHEMSHARING_ERROR=§cDer Spieler ist nicht vom Verteilen von Schematics ausgeschlossen. UNNOSCHEMSHARING=§e{0} §7darf nun wieder §e§lSchematics§7 verteilen§8. -NOSCHEMSUBMITTING_TEAM={0} §e{1} §7wurde von §e{2} {3} §7vom §e§lSchematiceinsenden§7 ausgeschlossen§8: §f{4} +NOSCHEMSUBMITTING_TEAM=§e{0} §7wurde von §e{1} {2} §7vom §e§lSchematiceinsenden§7 ausgeschlossen§8: §f{3} NOSCHEMSUBMITTING_PERMA=§7Du bist §epermanent §7vom §e§lEinsenden von Schematics§7 ausgeschlossen§8: §e{0} NOSCHEMSUBMITTING_UNTIL=§7Du bist §ebis zum {0} §7vom §e§lEinsenden von Schematics§7 ausgeschlossen§8: §e{1} UNNOSCHEMSUBMITTING_ERROR=§cDer Spieler ist nicht vom Einsenden von Schematics ausgeschlossen. UNNOSCHEMSUBMITTING=§e{0} §7darf nun wieder §e§lSchematis§7 einsenden§8. -NODEVSERVER_TEAM={0} §e{1} §7hat §e{2} §7mit Grund §f{4}§7 zu genervt und hat daher §e§lDevserververbot§7 erhalten§8, §f{3} +NODEVSERVER_TEAM=§e{0} §7hat §e{1} §7mit Grund §f{3}§7 zu genervt und hat daher §e§lDevserververbot§7 erhalten§8, §f{2} NODEVSERVER_PERMA=§7Du bist §epermanent §7vom §e§lDevserver§7 ausgeschlossen§8: §e{0} NODEVSERVER_UNTIL=§7Du bist §ebis zum {0} §7vom §e§lDevserver§7 ausgeschlossen§8: §e{1} UNNODEVSERVER_ERROR=§cDer Spieler ist nicht vom Devserver ausgeschlossen. UNNODEVSERVER=§e{0} §7darf nun wieder dem §e§lDevserver§7 beitreten§8. -NOFIGHTSERVER_TEAM={0} §e{1} §7wurde von §e{2} {3} §7vom §e§lKämpfen§7 ausgeschlossen§8: §f{4} +NOFIGHTSERVER_TEAM=§e{0} §7wurde von §e{1} {2} §7vom §e§lKämpfen§7 ausgeschlossen§8: §f{3} NOFIGHTSERVER_PERMA=§7Du bist §epermanent §7vom §e§lKämpfen§7 ausgeschlossen§8: §e{0} NOFIGHTSERVER_UNTIL=§7Du bist §ebis zum {0} §7vom §e§lKämpfen§7 ausgeschlossen§8: §e{1} UNNOFIGHTSERVER_ERROR=§cDer Spieler ist nicht vom Kämpfen ausgeschlossen. UNNOFIGHTSERVER=§e{0} §7darf nun wieder §e§lKämpfen§7 beitreten§8. -NOTEAMSERVER_TEAM={0} §e{1} §7wurde von §e{2} {3} §7vom §e§lTeamserver§7 setzen ausgeschlossen§8: §f{4} +NOTEAMSERVER_TEAM=§e{0} §7wurde von §e{1} {2} §7vom §e§lTeamserver§7 setzen ausgeschlossen§8: §f{3} NOTEAMSERVER_PERMA=§7Du bist §epermanent §7vom §e§lTeamserver§7 setzen ausgeschlossen§8: §e{0} NOTEAMSERVER_UNTIL=§7Du bist §ebis zum {0} §7vom §e§lTeamserver§7 setzen ausgeschlossen§8: §e{1} UNNOTEAMSERVER_ERROR=§cDer Spieler ist nicht vom Teamserver setzten ausgeschlossen. UNNOTEAMSERVER=§e{0} §7darf nun wieder §e§lTeamserver§7 setzen§8. -NOTE_TEAM={0} §e{1} §7erhielt von §e{2} {3} §7die §e§lNotiz§7§8: §f{4} +NOTE_TEAM=§e{0} §7erhielt von §e{1} {2} §7die §e§lNotiz§7§8: §f{3} #BugCommand BUG_MESSAGE=§7Bitte beschreibe das Problem in einem Discordticket genauer und gebe dabei die Bug-ID §e{0} §7an§8. @@ -536,9 +536,9 @@ CHAT_YOYONOW_3=Vielen Dank. CHAT_YOYONOW_4=Ich wünsche dir noch weiterhin ein reibungsloses Spielerlebnis. CHAT_CHAOSCAOT_1=Du hast mich gerufen! CHAT_CHAOSCAOT_2=Wenn etwas nicht funktioniert, dann nen es einfach ein Feature. -CHAT_CHAOSCAOT_3=Und wenn es ein Feature ist, dann kann es nicht kaputt. -CHAT_CHAOSCAOT_4=Kaputt ist nur eine Definition. Wenn du es als Feature definiert, dann kann es nicht kaputt sein. -CHAT_CHAOSCAOT_5=Und wenn du es als kaputt definiert, dann sag uns bescheid mit dem Befehl "/bug ". +CHAT_CHAOSCAOT_3=Und wenn es ein Feature ist, dann kann es nicht kaputt sein. +CHAT_CHAOSCAOT_4=Kaputt ist nur eine Definition. Wenn du alles als Feature definierst, dann kann es auch keine Bugs geben. +CHAT_CHAOSCAOT_5=Solltest du es aber doch als Bug definieren, dann sag uns bescheid mit dem Befehl "/bug ". CHAT_CHAOSCAOT_6=Vielen Dank. CHAT_RECEIVE=§cUm Chatnachrichten versenden zu können, musst du auch welche empfangen! CHAT_NO_LINKS=§cDu darfst keine Links versenden. @@ -547,6 +547,7 @@ CHAT_NO_RECEIVER=§cNiemand empfängt deine Nachricht CHAT_EMPTY=§cSchreibe keine inhaltslosen Nachrichten. CHAT_SERVERTEAM=§8STC §e{0}§8» §f{2} +CHAT_DISCORD_SERVERTEAM=§8STC §e{0}§8» §f{2} CHAT_GLOBAL={3}{4}{5}{6}{0}§8» {7}{2} CHAT_DISCORD_GLOBAL=§8Dc {5}{6}{0}§8» {7}{2} CHAT_TEAM=§8TC §e{0}§8» §f{2} diff --git a/VelocityCore/src/de/steamwar/velocitycore/ArenaMode.java b/VelocityCore/src/de/steamwar/velocitycore/ArenaMode.java index 5595d9d9..4490c172 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/ArenaMode.java +++ b/VelocityCore/src/de/steamwar/velocitycore/ArenaMode.java @@ -22,6 +22,7 @@ package de.steamwar.velocitycore; import de.steamwar.sql.SchematicType; import lombok.Getter; +import java.time.LocalDateTime; import java.util.*; public class ArenaMode extends GameModeConfig { @@ -76,7 +77,7 @@ public class ArenaMode extends GameModeConfig { public static List getAllChatNames(boolean historic) { List chatNames = new LinkedList<>(); for(ArenaMode mode : byInternal.values()){ - if(historic == mode.isHistoric()) + if(mode.isActive() && historic == mode.isHistoric()) chatNames.addAll(mode.getServer().getChatNames()); } return chatNames; @@ -94,6 +95,9 @@ public class ArenaMode extends GameModeConfig { @Getter private String config; + @Getter + private List ActiveMonths = Collections.emptyList(); + public String hasMap(String map){ for(String m : getMaps()) { if(m.equalsIgnoreCase(map)) @@ -114,8 +118,10 @@ public class ArenaMode extends GameModeConfig { return getServer().getChatNames().get(0); } - public boolean withoutChatName(){ - return getServer().getChatNames().isEmpty(); + public boolean isActive() { + if (getServer().getChatNames().isEmpty()) return false; + if (ActiveMonths.isEmpty()) return true; + return ActiveMonths.contains(LocalDateTime.now().getMonth().getValue()); } public String getSchemTypeOrInternalName() { diff --git a/VelocityCore/src/de/steamwar/velocitycore/Node.java b/VelocityCore/src/de/steamwar/velocitycore/Node.java index 9c717886..308d9938 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/Node.java +++ b/VelocityCore/src/de/steamwar/velocitycore/Node.java @@ -35,7 +35,7 @@ public abstract class Node { private static final List OPENJ9_ARGS = Arrays.asList( "-XX:+EnableCRIUSupport", "-XX:-CRIURestoreNonPortableMode", "-Xgc:excessiveGCratio=80", "-Xdisableexplicitgc", "-Xnoclassgc", "-Xmos128M", "-Xmns48M", "-XX:+ExitOnOutOfMemoryError", // initial heap half values of memory observed by 1.19 spectate server - "-Xsyslog:none", "-Xtrace:none", "-Xverify:none", "-Xdump:system:none", "-Xdump:jit:none", "-Xdump:snap:none", + "-Xsyslog:none", "-Xtrace:none", "-Xverify:none", "-Xdump:system:none", "-Xdump:jit:none", "-Xdump:snap:none", "-Xdump:heap:opts=hprof", "-XX:+EnableDynamicAgentLoading", "-Dlog4j.configurationFile=log4j2.xml" ); private static final Set JAVA_8 = new HashSet<>(); diff --git a/VelocityCore/src/de/steamwar/velocitycore/ServerVersion.java b/VelocityCore/src/de/steamwar/velocitycore/ServerVersion.java index a5e08b55..d8952118 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/ServerVersion.java +++ b/VelocityCore/src/de/steamwar/velocitycore/ServerVersion.java @@ -44,6 +44,7 @@ public enum ServerVersion { PAPER_18("paper-1.18.2.jar", 15, ProtocolVersion.MINECRAFT_1_18_2), PAPER_19("paper-1.19.3.jar", 19, ProtocolVersion.MINECRAFT_1_19_3), PAPER_20("paper-1.20.1.jar", 20, ProtocolVersion.MINECRAFT_1_20), + DEVEL_21("paper-1.21.5.jar", 21, ProtocolVersion.MINECRAFT_1_21_5), PAPER_21("paper-1.21.3.jar", 21, ProtocolVersion.MINECRAFT_1_21_2); private static final Map chatMap = new HashMap<>(); @@ -94,6 +95,10 @@ public enum ServerVersion { } public static ServerVersion get(int version) { + if (version == 21) { + return DEVEL_21; + } + return versionMap.get(version); } diff --git a/VelocityCore/src/de/steamwar/velocitycore/commands/BugCommand.java b/VelocityCore/src/de/steamwar/velocitycore/commands/BugCommand.java index 22c9f391..088acb09 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/commands/BugCommand.java +++ b/VelocityCore/src/de/steamwar/velocitycore/commands/BugCommand.java @@ -19,9 +19,11 @@ package de.steamwar.velocitycore.commands; +import de.steamwar.persistent.Subserver; import de.steamwar.sql.SWException; import de.steamwar.command.SWCommand; import de.steamwar.messages.Chatter; +import de.steamwar.velocitycore.SubserverSystem; public class BugCommand extends SWCommand { public BugCommand() { @@ -35,5 +37,9 @@ public class BugCommand extends SWCommand { sender.withPlayerOrOffline(player -> player.getCurrentServer().map(connection -> connection.getServerInfo().getName()).orElse("offline"), () -> "offline") + " " + sender.user().getUserName() + " " + sender.user().getId() ); sender.system("BUG_MESSAGE", id); + + if (Subserver.isArena(Subserver.getSubserver(sender.getPlayer()))) { + sender.getPlayer().spoofChatInput("/techhiderbug"); + } } } diff --git a/VelocityCore/src/de/steamwar/velocitycore/commands/DevCommand.java b/VelocityCore/src/de/steamwar/velocitycore/commands/DevCommand.java index 71b4427c..bf74e672 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/commands/DevCommand.java +++ b/VelocityCore/src/de/steamwar/velocitycore/commands/DevCommand.java @@ -135,12 +135,12 @@ public class DevCommand extends SWCommand { }); devServerPorts.forEach((username, value) -> { - if (devServers.containsKey(username)) - return; - SteamwarUser user = SteamwarUser.get(username); String name = "Dev " + user.getUserName(); ((VelocityViaConfig) Via.getConfig()).getVelocityServerProtocols().put(name, ServerVersion.get(devServerVersions.get(username)).getProtocolVersion().getProtocol()); + + if (devServers.containsKey(username)) + return; devServers.put(user.getUserName().toLowerCase(), VelocityCore.getProxy().registerServer(new ServerInfo(name, new InetSocketAddress("127.0.0.1", value)))); }); } diff --git a/VelocityCore/src/de/steamwar/velocitycore/commands/FightCommand.java b/VelocityCore/src/de/steamwar/velocitycore/commands/FightCommand.java index 6c320758..ee82988c 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/commands/FightCommand.java +++ b/VelocityCore/src/de/steamwar/velocitycore/commands/FightCommand.java @@ -45,7 +45,7 @@ public class FightCommand extends SWCommand { private static void getModes(Chatter sender, String precommand, boolean historic){ Component start = Component.empty(); for(ArenaMode mode : ArenaMode.getAllModes()){ - if(mode.withoutChatName() || mode.isHistoric() != historic) + if (!mode.isActive() || mode.isHistoric() != historic) continue; String command = precommand + mode.getChatName(); diff --git a/VelocityCore/src/de/steamwar/velocitycore/commands/MsgCommand.java b/VelocityCore/src/de/steamwar/velocitycore/commands/MsgCommand.java index 8341318f..5300909d 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/commands/MsgCommand.java +++ b/VelocityCore/src/de/steamwar/velocitycore/commands/MsgCommand.java @@ -20,6 +20,8 @@ package de.steamwar.velocitycore.commands; import com.velocitypowered.api.proxy.Player; +import com.velocitypowered.proxy.Velocity; +import de.steamwar.velocitycore.VelocityCore; import de.steamwar.velocitycore.listeners.ChatListener; import de.steamwar.command.SWCommand; import de.steamwar.messages.Chatter; @@ -41,7 +43,7 @@ public class MsgCommand extends SWCommand { } public static void msg(PlayerChatter sender, Player target, String[] args) { - if(target == null) { + if(target == null || VelocityCore.getProxy().getPlayer(target.getUniqueId()).orElse(null) == null) { sender.system("MSG_OFFLINE"); return; } diff --git a/VelocityCore/src/de/steamwar/velocitycore/commands/PunishmentCommand.java b/VelocityCore/src/de/steamwar/velocitycore/commands/PunishmentCommand.java index 1dc8ebde..4932de02 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/commands/PunishmentCommand.java +++ b/VelocityCore/src/de/steamwar/velocitycore/commands/PunishmentCommand.java @@ -210,7 +210,7 @@ public class PunishmentCommand { target.punish(punishmentType, banTime, msg, punisher.getId(), isPerma); if(punishmentType == Punishment.PunishmentType.Ban) ban(target, banTime, msg, punisher, isPerma); - Chatter.serverteam().system(punishmentType.getTeamMessage(), new Message("PREFIX"), target, sender, new Message((isPerma ? "PUNISHMENT_PERMA" : "PUNISHMENT_UNTIL"), banTime), msg); + Chatter.serverteam().system(punishmentType.getTeamMessage(), target, sender, new Message((isPerma ? "PUNISHMENT_PERMA" : "PUNISHMENT_UNTIL"), banTime), msg); } @Register diff --git a/VelocityCore/src/de/steamwar/velocitycore/commands/TeamCommand.java b/VelocityCore/src/de/steamwar/velocitycore/commands/TeamCommand.java index 0dd865b1..0655ac8b 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/commands/TeamCommand.java +++ b/VelocityCore/src/de/steamwar/velocitycore/commands/TeamCommand.java @@ -20,12 +20,11 @@ package de.steamwar.velocitycore.commands; import com.velocitypowered.api.proxy.ConnectionRequestBuilder; +import com.velocitypowered.api.proxy.server.RegisteredServer; import com.velocitypowered.api.proxy.server.ServerInfo; -import de.steamwar.persistent.Storage; -import de.steamwar.velocitycore.VelocityCore; -import de.steamwar.velocitycore.discord.DiscordBot; -import de.steamwar.velocitycore.inventory.SWItem; -import de.steamwar.velocitycore.inventory.SWListInv; +import com.velocitypowered.api.proxy.server.ServerPing; +import com.viaversion.viaversion.api.Via; +import com.viaversion.viaversion.velocity.platform.VelocityViaConfig; import de.steamwar.command.PreviousArguments; import de.steamwar.command.SWCommand; import de.steamwar.command.TypeMapper; @@ -33,7 +32,12 @@ import de.steamwar.command.TypeValidator; import de.steamwar.messages.Chatter; import de.steamwar.messages.Message; import de.steamwar.messages.PlayerChatter; +import de.steamwar.persistent.Storage; import de.steamwar.sql.*; +import de.steamwar.velocitycore.VelocityCore; +import de.steamwar.velocitycore.discord.DiscordBot; +import de.steamwar.velocitycore.inventory.SWItem; +import de.steamwar.velocitycore.inventory.SWListInv; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.event.ClickEvent; import net.kyori.adventure.text.event.HoverEvent; @@ -401,12 +405,21 @@ public class TeamCommand extends SWCommand { return; } - InetSocketAddress address = new InetSocketAddress(targetTeam.getAddress(), targetTeam.getPort()); - ServerInfo serverInfo = Storage.teamServers.computeIfAbsent(targetTeam.getTeamId(), integer -> { - ServerInfo info = new ServerInfo("Team " + targetTeam.getTeamKuerzel(), address); - VelocityCore.getProxy().registerServer(info); - return info; - }); + InetSocketAddress address; + ServerInfo serverInfo; + try { + address = new InetSocketAddress(targetTeam.getAddress(), targetTeam.getPort()); + serverInfo = Storage.teamServers.computeIfAbsent(targetTeam.getTeamId(), integer -> { + ServerInfo info = new ServerInfo("Team " + targetTeam.getTeamKuerzel(), address); + RegisteredServer server = VelocityCore.getProxy().registerServer(info); + ServerPing serverPing = server.ping().join(); + ((VelocityViaConfig) Via.getConfig()).getVelocityServerProtocols().put(info.getName(), serverPing.getVersion().getProtocol()); + return info; + }); + } catch (Exception e) { + sender.system("TEAM_NO_ADDRESS"); + return; + } if (!address.equals(serverInfo.getAddress())) { VelocityCore.getProxy().unregisterServer(Storage.teamServers.remove(targetTeam.getTeamId())); diff --git a/VelocityCore/src/de/steamwar/velocitycore/commands/TypeMappers.java b/VelocityCore/src/de/steamwar/velocitycore/commands/TypeMappers.java index 8036272f..e2c1176a 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/commands/TypeMappers.java +++ b/VelocityCore/src/de/steamwar/velocitycore/commands/TypeMappers.java @@ -49,7 +49,11 @@ public class TypeMappers { return new TypeMapper<>() { @Override public ArenaMode map(Chatter sender, PreviousArguments previousArguments, String s) { - return ArenaMode.getByChat(s); + ArenaMode arenaMode = ArenaMode.getByChat(s); + if (arenaMode == null) return null; + if (arenaMode.isHistoric() != historic) return null; + if (!arenaMode.isActive()) return null; + return arenaMode; } @Override diff --git a/VelocityCore/src/de/steamwar/velocitycore/discord/DiscordBot.java b/VelocityCore/src/de/steamwar/velocitycore/discord/DiscordBot.java index ecdc5a53..28cd0c22 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/discord/DiscordBot.java +++ b/VelocityCore/src/de/steamwar/velocitycore/discord/DiscordBot.java @@ -167,14 +167,19 @@ public class DiscordBot { checklistChannel = new ChecklistChannel(config.channel("checklist")); config.getCouncilThread().forEach((roleId, threadId) -> new CouncilChannel(DiscordBot.getGuild().getRoleById(roleId), DiscordBot.getGuild().getThreadChannelById(threadId))); - announcementChannel = new DiscordChannel(config.channel("announcement")) { + announcementChannel = new DiscordChannel(config.channel("announcement"), 0) { @Override public void received(MessageReceivedEvent event) { Chatter.broadcast().system("ALERT", event.getMessage().getContentDisplay()); } }; - ingameChat = new DiscordChatRoom(config.channel("ingame"), "CHAT_DISCORD_GLOBAL", Chatter::broadcast); - serverTeamChat = new DiscordChatRoom(config.channel("serverteam"), "CHAT_SERVERTEAM", Chatter::serverteam); + + // There is a hard limit of 30 messages per minute to send as a webhook, thus with 8 webhooks we can send + // 240 messages per minute. Which means 4 every second. I looked at the WGS fights and there were around + // ~70 in a short burst and then rather long no new message. + ingameChat = new DiscordChatRoom(config.channel("ingame"), "CHAT_DISCORD_GLOBAL", Chatter::globalChat, 8); + // 60 messages per minute should be enough for the server team! + serverTeamChat = new DiscordChatRoom(config.channel("serverteam"), "CHAT_DISCORD_SERVERTEAM", Chatter::serverteam, 2); VelocityCore.schedule(() -> { try { diff --git a/VelocityCore/src/de/steamwar/velocitycore/discord/channels/ChecklistChannel.java b/VelocityCore/src/de/steamwar/velocitycore/discord/channels/ChecklistChannel.java index 2e6de441..18bbff4a 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/discord/channels/ChecklistChannel.java +++ b/VelocityCore/src/de/steamwar/velocitycore/discord/channels/ChecklistChannel.java @@ -23,6 +23,7 @@ import de.steamwar.sql.SchematicNode; import de.steamwar.sql.SteamwarUser; import de.steamwar.velocitycore.commands.CheckCommand; +import java.time.Instant; import java.util.ArrayList; import java.util.List; @@ -31,7 +32,7 @@ public class ChecklistChannel extends DiscordChannel { private final List lastSchematics = new ArrayList<>(); public ChecklistChannel(String channel) { - super(channel); + super(channel, 0); } public void update() { @@ -41,7 +42,8 @@ public class ChecklistChannel extends DiscordChannel { schems.removeIf(schem -> lastSchematics.contains(schem.getId())); for(SchematicNode schem : schems) { - system("CHECK_LIST_TO_CHECK", CheckCommand.getWaitTime(schem), schem.getSchemtype().getKuerzel(), SteamwarUser.get(schem.getOwner()).getUserName(), schem.getName()); + String waitTime = ""; + system("CHECK_LIST_TO_CHECK", waitTime, schem.getSchemtype().getKuerzel(), SteamwarUser.get(schem.getOwner()).getUserName(), schem.getName()); lastSchematics.add(schem.getId()); } } diff --git a/VelocityCore/src/de/steamwar/velocitycore/discord/channels/DiscordChannel.java b/VelocityCore/src/de/steamwar/velocitycore/discord/channels/DiscordChannel.java index b420f601..5fcbcf6a 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/discord/channels/DiscordChannel.java +++ b/VelocityCore/src/de/steamwar/velocitycore/discord/channels/DiscordChannel.java @@ -27,13 +27,20 @@ import de.steamwar.velocitycore.discord.listeners.ChannelListener; import lombok.AllArgsConstructor; import lombok.Getter; import net.dv8tion.jda.api.entities.User; +import net.dv8tion.jda.api.entities.Webhook; +import net.dv8tion.jda.api.entities.WebhookClient; +import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import net.dv8tion.jda.api.events.interaction.component.GenericComponentInteractionCreateEvent; import net.dv8tion.jda.api.events.message.MessageReceivedEvent; import net.dv8tion.jda.api.utils.messages.MessageCreateBuilder; +import net.dv8tion.jda.internal.requests.IncomingWebhookClientImpl; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; +import java.util.ArrayDeque; +import java.util.Queue; + @AllArgsConstructor public class DiscordChannel extends Chatter.PlayerlessChatter { @@ -43,30 +50,82 @@ public class DiscordChannel extends Chatter.PlayerlessChatter { return user != null ? user : SteamwarUser.get(0); } + private final Queue webhooks = new ArrayDeque<>(); + private final SteamwarUser user; @Getter private final MessageChannel channel; + private final int maxNumberOfWebhooks; + public DiscordChannel(User user) { - this(userOrPublic(user), user.openPrivateChannel().complete()); + this(userOrPublic(user), user.openPrivateChannel().complete(), 0); } - public DiscordChannel(String channel) { - this(DiscordBot.getGuild().getTextChannelById(channel)); + public DiscordChannel(String channel, int maxNumberOfWebhooks) { + this(DiscordBot.getGuild().getTextChannelById(channel), maxNumberOfWebhooks); } - public DiscordChannel(MessageChannel channel) { - this(SteamwarUser.get(-1), channel); + public DiscordChannel(MessageChannel channel, int maxNumberOfWebhooks) { + this(SteamwarUser.get(-1), channel, maxNumberOfWebhooks); ChannelListener.getChannels().put(this.channel, this); + + if (channel instanceof TextChannel) { + TextChannel textChannel = (TextChannel) channel; + webhooks.addAll(textChannel.retrieveWebhooks().complete()); + while (webhooks.size() > maxNumberOfWebhooks) { + webhooks.remove().delete().queue(); + } + while (webhooks.size() < maxNumberOfWebhooks) { + webhooks.add(textChannel.createWebhook(DiscordBot.getInstance().getJda().getSelfUser().getName()).complete()); + } + } } public void send(String message) { + message = message + .replace("&", "") + .replace("@everyone", "`@everyone`") + .replace("@here", "`@here`") + .replaceAll("<[@#]!?\\d+>", "`$0`"); + + if (maxNumberOfWebhooks > 0 && getChannel() instanceof TextChannel && message.contains("»")) { + String[] strings = message.split("»", 2); + String userName = strings[0]; + String sendMessage = strings[1]; + strings = userName.split(" "); + + String ingameName = strings[strings.length - 1]; + + SteamwarUser user = SteamwarUser.get(ingameName); + if (user == null) { + send(new MessageCreateBuilder() + .setContent(message)); + return; + } + + String avatarUrl; + if (user.getDiscordId() != null) { + avatarUrl = DiscordBot.getGuild().retrieveMemberById(user.getDiscordId()).complete().getEffectiveAvatarUrl(); + } else { + avatarUrl = DiscordBot.getInstance().getJda().getSelfUser().getAvatarUrl(); + } + + Webhook webhook = webhooks.poll(); + webhooks.add(webhook); + + // This works as per this documentation: https://discord.com/developers/docs/resources/webhook#execute-webhook + IncomingWebhookClientImpl webhookClient = (IncomingWebhookClientImpl) WebhookClient.createClient(DiscordBot.getInstance().getJda(), webhook.getUrl()); + webhookClient.sendRequest() + .setUsername(userName) + .setAvatarUrl(avatarUrl) + .setContent(sendMessage) + .queue(); + return; + } + send(new MessageCreateBuilder() - .setContent(message - .replace("&", "") - .replace("@everyone", "`@everyone`") - .replace("@here", "`@here`") - .replaceAll("<[@#]!?\\d+>", "`$0`"))); + .setContent(message)); } public void send(MessageCreateBuilder builder) { diff --git a/VelocityCore/src/de/steamwar/velocitycore/discord/channels/DiscordChatRoom.java b/VelocityCore/src/de/steamwar/velocitycore/discord/channels/DiscordChatRoom.java index 7b05357c..2db981f1 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/discord/channels/DiscordChatRoom.java +++ b/VelocityCore/src/de/steamwar/velocitycore/discord/channels/DiscordChatRoom.java @@ -33,8 +33,8 @@ public class DiscordChatRoom extends DiscordChannel { private final String format; private final Supplier target; - public DiscordChatRoom(String channel, String format, Supplier target) { - super(channel); + public DiscordChatRoom(String channel, String format, Supplier target, int maxNumberOfWebhooks) { + super(channel, maxNumberOfWebhooks); this.format = format; this.target = target; } diff --git a/VelocityCore/src/de/steamwar/velocitycore/discord/channels/StaticMessageChannel.java b/VelocityCore/src/de/steamwar/velocitycore/discord/channels/StaticMessageChannel.java index 69549d38..9ab2920e 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/discord/channels/StaticMessageChannel.java +++ b/VelocityCore/src/de/steamwar/velocitycore/discord/channels/StaticMessageChannel.java @@ -46,14 +46,14 @@ public class StaticMessageChannel extends DiscordChannel { } public StaticMessageChannel(String channel, Supplier supplier, Consumer interaction) { - super(channel); + super(channel, 0); this.supplier = supplier; this.interaction = interaction; init(); } public StaticMessageChannel(MessageChannel channel, Supplier supplier, Consumer interaction) { - super(channel); + super(channel, 0); this.supplier = supplier; this.interaction = interaction; init(); diff --git a/VelocityCore/src/de/steamwar/velocitycore/discord/listeners/DiscordTicketHandler.java b/VelocityCore/src/de/steamwar/velocitycore/discord/listeners/DiscordTicketHandler.java index f32b4767..5c5e708b 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/discord/listeners/DiscordTicketHandler.java +++ b/VelocityCore/src/de/steamwar/velocitycore/discord/listeners/DiscordTicketHandler.java @@ -70,7 +70,7 @@ public class DiscordTicketHandler extends ListenerAdapter { Permission.MESSAGE_HISTORY).complete(); ticketChannel.getManager().setTopic(event.getUser().getId()).complete(); - DiscordChannel channel = new DiscordChannel(DiscordChannel.userOrPublic(event.getUser()), ticketChannel); + DiscordChannel channel = new DiscordChannel(DiscordChannel.userOrPublic(event.getUser()), ticketChannel, 0); channel.send(new MessageCreateBuilder() .setEmbeds(new EmbedBuilder() .setTitle(channel.parseToPlain("DC_TICKET_TITLE")) diff --git a/VelocityCore/src/de/steamwar/velocitycore/listeners/PluginMessage.java b/VelocityCore/src/de/steamwar/velocitycore/listeners/PluginMessage.java index af208aed..5d84eb17 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/listeners/PluginMessage.java +++ b/VelocityCore/src/de/steamwar/velocitycore/listeners/PluginMessage.java @@ -33,6 +33,8 @@ import com.velocitypowered.api.proxy.messages.MinecraftChannelIdentifier; import com.velocitypowered.proxy.protocol.ProtocolUtils; import de.steamwar.messages.Chatter; import de.steamwar.network.packets.NetworkPacket; +import de.steamwar.sql.SteamwarUser; +import de.steamwar.sql.UserPerm; import de.steamwar.velocitycore.VelocityCore; import de.steamwar.velocitycore.commands.TeamCommand; import de.steamwar.velocitycore.mods.*; @@ -360,6 +362,23 @@ public class PluginMessage extends BasicListener { )) channelRegisterHandlers.put(channel, player -> Chatter.disconnect(player).prefixless("MOD_YELLOW_SING", "minimap")); + for(String channel : Arrays.asList( + "flashback:remote_food_data", + "flashback:remote_set_slot", + "flashback:force_client_tick", + "flashback:accurate_entity_position", + "flashback:instantly_lerp", + "flashback:remote_experience", + "flashback:clear_particles", + "flashback:remote_select_hotbar_slot", // https://github.com/Moulberry/Flashback/tree/master/src/main/java/com/moulberry/flashback/packet + "flashback:clear_entities" // https://github.com/Moulberry/Flashback + )) + channelRegisterHandlers.put(channel, player -> { + if (!SteamwarUser.get(player.getUniqueId()).hasPerm(UserPerm.RESTRICTED_MODS)) { + Chatter.disconnect(player).prefixless("MOD_YELLOW_SING", "flashback"); + } + }); + for(String channel : Arrays.asList("bedrockify:cauldron_particles", "bedrockify:eat-particles")) //https://github.com/juancarloscp52/BedrockIfy (Bedrock features on Java, banned for reach-around block placement) channelRegisterHandlers.put(channel, player -> Chatter.disconnect(player).prefixless("MOD_YELLOW_SING", "bedrockify")); @@ -377,7 +396,8 @@ public class PluginMessage extends BasicListener { "axiom:hello", "axiom:set_gamemode", "axiom:set_fly_speed", "axiom:set_world_time", "axiom:set_world_property", "axiom:set_block", "axiom:set_hotbar_slot", "axiom:switch_active_hotbar", "axiom:teleport", "axiom:request_chunk_data", "axiom:spawn_entity", "axiom:response_entity_data", - "axiom:manipulate_entity", "axiom:delete_entity", "axiom:marker_nbt_request", "axiom:set_buffer" + "axiom:manipulate_entity", "axiom:delete_entity", "axiom:marker_nbt_request", "axiom:set_buffer", + "axiom:allowed_gamemodes", "axiom:ignore_display_entities", "axiom:add_server_heightmap" )) { channelRegisterHandlers.put(channel, player -> {}); registerPassthroughToServer(channel); @@ -385,7 +405,7 @@ public class PluginMessage extends BasicListener { for(String channel : Arrays.asList( "floodgate:skin", - "watut:nbt", //https://github.com/Corosauce/WATUT + "watut:nbt", "watut:nbt_server", //https://github.com/Corosauce/WATUT "bclib:hello_server", "vivecraft:data", //https://github.com/Vivecraft/VivecraftMod https://github.com/jrbudda/Vivecraft_Spigot_Extensions https://github.com/Techjar/Vivecraft_BungeeCord_Extensions (VR support) "badpackets:channel_sync", //https://github.com/badasintended/badpackets (Forge fabric translation layer) diff --git a/VelocityCore/src/de/steamwar/velocitycore/tablist/Tablist.java b/VelocityCore/src/de/steamwar/velocitycore/tablist/Tablist.java index f15bc79c..6195bd73 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/tablist/Tablist.java +++ b/VelocityCore/src/de/steamwar/velocitycore/tablist/Tablist.java @@ -185,7 +185,6 @@ public class Tablist extends ChannelInboundHandlerAdapter { if(msg instanceof UpsertPlayerInfoPacket packet) { packet.getActions().remove(UpsertPlayerInfoPacket.Action.INITIALIZE_CHAT); packet.getActions().remove(UpsertPlayerInfoPacket.Action.UPDATE_LATENCY); - packet.getActions().remove(UpsertPlayerInfoPacket.Action.UPDATE_DISPLAY_NAME); packet.getActions().remove(UpsertPlayerInfoPacket.Action.UPDATE_LISTED); if(packet.getActions().isEmpty()) { ReferenceCountUtil.release(msg); diff --git a/WebsiteBackend/src/de/steamwar/routes/Schematic.kt b/WebsiteBackend/src/de/steamwar/routes/Schematic.kt index 1beb0f29..ec3b54fb 100644 --- a/WebsiteBackend/src/de/steamwar/routes/Schematic.kt +++ b/WebsiteBackend/src/de/steamwar/routes/Schematic.kt @@ -149,6 +149,23 @@ fun Route.configureSchematic() { return@let SchematicFormat.SPONGE_V2 } + if (version == SchematicFormat.SPONGE_V3) { + try { + val fawe = schem.getCompound("Metadata") + .getCompound("WorldEdit") + .getString("Version") + .value + + if (fawe.equals("2.12.3-SNAPSHOT")) { + SWException.log("Schematic with Bugged Version Uploaded", """ + Schematic=$schemName + User=${user.userName} + Id=${user.id} + """.trimIndent()) + } + } catch (_: Exception) {} + } + val data = NodeData(node.id, version) data.saveFromStream(content.inputStream(), version) diff --git a/buildSrc/src/steamwar.devserver.gradle b/buildSrc/src/steamwar.devserver.gradle new file mode 100644 index 00000000..53f8be3d --- /dev/null +++ b/buildSrc/src/steamwar.devserver.gradle @@ -0,0 +1,214 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +plugins { +} + +class DevServer extends DefaultTask { + + @Input + @Optional + String worldName = null + + @Input + String template = null + + @Input + @Optional + String plugins = null + + @Input + @Optional + Integer port = null + + @Input + @Optional + String jar = null + + @Input + @Optional + Map dParams = new HashMap<>() + + DevServer() { + super() + doFirst { + List projects = [] + projects.add(project) + while (projects.first.parent != null) { + projects.add(0, projects.first.parent) + } + + def properties = new Properties() + projects.forEach { + def file = new File(it.projectDir, "steamwar.properties") + if (file.exists()) { + properties.load(new FileInputStream(file)) + } + } + + if (worldName == null) worldName = properties.get("worldName") + host = properties.get("host") + + if (host == null) { + throw new GradleException("Please supply the 'host' in a 'steamwar.properties' files either in this project dir or any parent project!") + } + } + doLast { + checkHasTemplate() + uploadDependencies() + startDevServer() + } + finalizedBy(new Finalizer()) + } + + @Internal + BufferedWriter processInput + + @Internal + String host + + @Internal + Boolean running = true + + class Finalizer extends DefaultTask { + + Finalizer() { + super() + doLast { + running = false + if (processInput != null) { + processInput.write(template.endsWith("Velocity") ? "end\n" : "stop\n") + processInput.flush() + } + } + } + } + + void checkHasTemplate() { + def process = new ProcessBuilder("ssh", host, "-T", "ls $template").start() + process.waitFor() + if (new BufferedReader(new InputStreamReader(process.inputStream)).lines().count() < 4) { + throw new GradleException("Used template is not in your user.home directory of the given host $host") + } + } + + void uploadDependencies() { + def base = plugins == null ? "$template/plugins" : plugins + println("Uploading to ~/$base") + this.dependsOn.forEach { + Project resolved + AbstractArchiveTask archiveTask + if (it instanceof String) { + resolved = project.findProject(it.substring(0, it.lastIndexOf(':'))) + archiveTask = (AbstractArchiveTask) resolved.tasks.findByName(it.substring(it.lastIndexOf(':') + 1)) + } else { + throw new GradleException("Illegal argument for uploading dependencies") + } + + def archive = archiveTask.archiveFile.get().asFile + println("Uploading $archive") + new ProcessBuilder("ssh", host, "-T", "rm $base/${archive.name.replace("-all", "")}").start().waitFor() + new ProcessBuilder("scp", archive.absolutePath, "$host:~/$base/${archive.name.replace("-all", "")}").start().waitFor() + println("Uploaded $archive") + } + } + + void startDevServer() { + def devPy = new StringBuilder().append("dev.py") + if (port != null) devPy.append(" --port $port") + if (worldName != null) devPy.append(" -w $template/$worldName") + if (plugins != null) devPy.append(" -p $plugins") + if (jar != null) devPy.append(" --jar $jar") + for (Map.Entry dParam : dParams.entrySet()) { + devPy.append(" -D${dParam.key}=${dParam.value}") + } + devPy.append(" $template") + println("Starting $template with command ${devPy.toString()}") + + def process = new ProcessBuilder("ssh", host, "-T", devPy.toString()).start() + def processOutput = new BufferedReader(new InputStreamReader(process.inputStream)) + new Thread({ + while (running) { + if (processOutput.ready()) { + println(processOutput.readLine()) + } + } + }).start() + + processInput = new BufferedWriter(new OutputStreamWriter(process.outputStream)) + def input = new BufferedReader(new InputStreamReader(System.in)) + new Thread({ + while (running) { + def text = input.readLine() + if (text == null) break + processInput.write(text) + processInput.newLine() + processInput.flush() + } + }).start() + + process.waitFor() + processInput = null + running = false + } +} + +class FightServer extends DevServer { + + @Input + @Optional + Integer checkSchemID = 0 + + @Input + @Optional + Integer prepareSchemID = 0 + + @Input + @Optional + Integer replay = 0 + + @Input + @Optional + String config = null + + @Input + @Optional + // Property: fightID + Integer eventKampfID = 0 + + @Input + @Optional + UUID blueLeader = null + + @Input + @Optional + UUID redLeader = null + + FightServer() { + super() + doFirst { + if (checkSchemID != 0) dParams.put("checkSchemID", "$checkSchemID") + if (prepareSchemID != 0) dParams.put("prepareSchemID", "$prepareSchemID") + if (replay != 0) dParams.put("replay", "$replay") + if (eventKampfID != 0) dParams.put("fightID", "$eventKampfID") + if (blueLeader != null) dParams.put("blueLeader", blueLeader.toString()) + if (redLeader != null) dParams.put("redLeader", redLeader.toString()) + if (config != null) dParams.put("config", config) + } + } +} \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index 87430368..9a649445 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -27,7 +27,6 @@ private val isInCi by lazy { Os.isFamily(Os.FAMILY_UNIX) && ProcessBuilder("host dependencyResolutionManagement { repositories { - maven { url = URI("https://m2.dv8tion.net/releases") content { @@ -46,7 +45,7 @@ dependencyResolutionManagement { if (isInCi) { url = URI("file:///var/www/maven/") } else { - url = URI("https://steamwar.de/maven/") + url = URI("https://maven.steamwar.de/") credentials { val swProps = Properties() swProps.load(rootDir.resolve("steamwar.properties").inputStream()) @@ -139,7 +138,7 @@ dependencyResolutionManagement { library("velocityapi", "com.velocitypowered:velocity-api:3.3.0-SNAPSHOT") library("viaapi", "com.viaversion:viaversion-api:4.3.1") library("viavelocity", "com.viaversion:viaversion-velocity:4.3.1") - library("jda", "net.dv8tion:JDA:5.2.0") + library("jda", "net.dv8tion:JDA:5.5.1") library("msgpack", "org.msgpack:msgpack-core:0.9.8") library("apolloprotos", "com.lunarclient:apollo-protos:1.0-SNAPSHOT") @@ -219,6 +218,7 @@ include( "SchematicSystem", "SchematicSystem:SchematicSystem_8", "SchematicSystem:SchematicSystem_15", + "SchematicSystem:SchematicSystem_19", "SchematicSystem:SchematicSystem_Core" )