diff --git a/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/DynamicRegionCommand.java b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/DynamicRegionCommand.java index 74ab6bc1..d45a1b90 100644 --- a/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/DynamicRegionCommand.java +++ b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/DynamicRegionCommand.java @@ -20,24 +20,12 @@ package de.steamwar.bausystem.region; import de.steamwar.bausystem.features.region.RegionCommand; -import de.steamwar.bausystem.region.dynamic.DynamicRegion; -import de.steamwar.bausystem.region.dynamic.DynamicRegionRepository; -import de.steamwar.bausystem.region.dynamic.RegionConstructorData; import de.steamwar.bausystem.region.dynamic.Tile; -import de.steamwar.bausystem.utils.PasteBuilder; import de.steamwar.command.AbstractSWCommand; -import de.steamwar.command.PreviousArguments; import de.steamwar.command.SWCommand; -import de.steamwar.command.TypeMapper; import de.steamwar.core.SWPlayer; -import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -import java.util.Collection; -import java.util.Map; -import java.util.UUID; -import java.util.stream.Collectors; - @AbstractSWCommand.PartOf(RegionCommand.class) public class DynamicRegionCommand extends SWCommand { @@ -45,7 +33,7 @@ public class DynamicRegionCommand extends SWCommand { super(""); } - @Register({"dynamic", "visualize"}) + @Register({"dynamic"}) public void visualizeRegions(Player player) { Tile tile = Tile.fromLocation(player.getLocation()).orElse(null); if (tile == null) return; @@ -56,53 +44,4 @@ public class DynamicRegionCommand extends SWCommand { swPlayer.setComponent(new DynamicRegionVisualizer()); } } - - @Register({"dynamic", "place"}) - public void placeRegion(Player player, @Mapper("regionType") String regionType) { - Region region = DynamicRegionSystem.INSTANCE.get(player.getLocation()); - if (!region.getType().isGlobal()) return; - Tile tile = Tile.fromLocation(player.getLocation()).orElse(null); - if (tile == null) return; - - // Check location! - - Class regionClass = DynamicRegionSystem.identifierDataMap.get(regionType); - DynamicRegion dynamicRegion = DynamicRegionRepository.constructRegion(regionClass, UUID.randomUUID(), tile.getMinX(), tile.getMinZ()); - if (dynamicRegion == null) { - // TODO: Give error to user - return; - } - - dynamicRegion.getArea().place(new PasteBuilder(new PasteBuilder.FileProvider(dynamicRegion.getArea().getResetFile())), false); - dynamicRegion.updateNeighbours(); - } - - @Register({"dynamic", "delete"}) - public void deleteRegion(Player player) { - Region region = DynamicRegionSystem.INSTANCE.get(player.getLocation()); - if (!region.getType().isDeletable()) return; - region.delete(); - } - - @Mapper("regionType") - private TypeMapper regionType() { - return new TypeMapper<>() { - @Override - public String map(CommandSender commandSender, String[] previousArguments, String s) { - for (Map.Entry, RegionConstructorData> entry : DynamicRegionSystem.constructorDataMap.entrySet()) { - if (entry.getValue().name().equalsIgnoreCase(s)) { - return s; - } - } - return null; - } - - @Override - public Collection tabCompletes(CommandSender sender, PreviousArguments previousArguments, String s) { - return DynamicRegionSystem.constructorDataMap.values() - .stream().map(RegionConstructorData::name) - .collect(Collectors.toSet()); - } - }; - } } diff --git a/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/DynamicRegionSystem.java b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/DynamicRegionSystem.java index 97e8576d..a3e28ea3 100644 --- a/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/DynamicRegionSystem.java +++ b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/DynamicRegionSystem.java @@ -100,6 +100,19 @@ public class DynamicRegionSystem implements RegionSystem { return GlobalRegion.INSTANCE; } + public Set getTilesOfRegion(@NonNull Region region) { + Point minPoint = region.getArea().getMinPoint(false); + Point maxPoint = region.getArea().getMaxPoint(false); + + Set tiles = new HashSet<>(); + for (int x = minPoint.getX(); x < maxPoint.getX(); x += Tile.tileSize) { + for (int z = minPoint.getZ(); z < maxPoint.getZ(); z += Tile.tileSize) { + tiles.add(Tile.fromXZ(x, z).orElseThrow()); + } + } + return Collections.unmodifiableSet(tiles); + } + public @NonNull Region get(@Nullable Tile tile) { if (tile == null) return getGlobalRegion(); return get(tile.getCenterLocation().getBlockX(), tile.getCenterLocation().getBlockZ(), true, regionMap.values()); diff --git a/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/DynamicRegionVisualizer.java b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/DynamicRegionVisualizer.java index 27d6a68a..7c645b99 100644 --- a/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/DynamicRegionVisualizer.java +++ b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/DynamicRegionVisualizer.java @@ -20,20 +20,25 @@ package de.steamwar.bausystem.region; import de.steamwar.bausystem.BauSystem; +import de.steamwar.bausystem.region.dynamic.DynamicRegion; +import de.steamwar.bausystem.region.dynamic.DynamicRegionRepository; +import de.steamwar.bausystem.region.dynamic.RegionConstructorData; import de.steamwar.bausystem.region.dynamic.Tile; +import de.steamwar.bausystem.utils.PasteBuilder; import de.steamwar.core.SWPlayer; import de.steamwar.entity.*; import de.steamwar.inventory.SWInventory; +import de.steamwar.inventory.SWItem; +import de.steamwar.inventory.SWListInv; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; -import org.bukkit.event.inventory.InventoryType; import org.bukkit.event.player.PlayerMoveEvent; -import java.util.Set; +import java.util.*; import java.util.stream.Collectors; public class DynamicRegionVisualizer implements SWPlayer.Component, Listener { @@ -43,6 +48,8 @@ public class DynamicRegionVisualizer implements SWPlayer.Component, Listener { private Location sourceLocation; private Tile sourceTile; + private Placement placement = null; + public DynamicRegionVisualizer() { this.entityServer = new REntityServer(); } @@ -101,6 +108,21 @@ public class DynamicRegionVisualizer implements SWPlayer.Component, Listener { } } + private void resetTiles(Set tiles) { + entityServer.getEntitiesByType(CTile.class) + .stream() + .filter(cTile -> tiles.contains(cTile.tile)) + .peek(CTile::die) + .map(cTile -> cTile.tile) + .forEach(tile -> { + new CTile(entityServer, tile); + }); + + if (placement != null) { + placement.check(); + } + } + private class CTile extends CEntity { private final Tile tile; @@ -109,7 +131,8 @@ public class DynamicRegionVisualizer implements SWPlayer.Component, Listener { super(server); this.tile = tile; - Material material = switch (DynamicRegionSystem.INSTANCE.get(tile).getType()) { + RegionType regionType = DynamicRegionSystem.INSTANCE.get(tile).getType(); + Material material = switch (regionType) { case SPAWN, SPAWN_EXTENSION -> Material.LODESTONE; case SPAWN_PATH, PATH -> Material.DIRT_PATH; case DRY, DRY_SPECIAL -> Material.IRON_BLOCK; @@ -124,23 +147,176 @@ public class DynamicRegionVisualizer implements SWPlayer.Component, Listener { spawn.setShadowed(false); entities.add(spawn); } else if (tile.equals(sourceTile)) { - CCubedTextDisplay spawn = new CCubedTextDisplay(entityServer, location); - spawn.setText("§eORIGIN"); - spawn.setBackgroundColor(0); - spawn.setShadowed(false); - entities.add(spawn); + CCubedTextDisplay origin = new CCubedTextDisplay(entityServer, location); + origin.setText("§eORIGIN"); + origin.setBackgroundColor(0); + origin.setShadowed(false); + entities.add(origin); } - RBlockDisplay entity = new RBlockDisplay(entityServer, location); - entity.setBlock(material.createBlockData()); - entities.add(entity); + RBlockDisplay blockDisplay = new RBlockDisplay(entityServer, location); + blockDisplay.setBlock(material.createBlockData()); + entities.add(blockDisplay); RInteraction interaction = new RInteraction(entityServer, location.clone().add(0.5, 0, 0.5)); interaction.setInteraction((player, entityAction) -> { - SWInventory swInv = new SWInventory(player, () -> Bukkit.createInventory(null, InventoryType.DROPPER, tile.toString())); - swInv.open(); + if (placement != null) { + if (regionType.isGlobal()) placement.click(tile); + return; + } + + if (!regionType.isGlobal()) { + SWInventory inv = new SWInventory(player, 9, "Delete Region: " + tile.display()); + inv.setItem(0, new SWItem(SWItem.getDye(10), "§8Cancel", click -> { + player.closeInventory(); + })); + inv.setItem(8, new SWItem(SWItem.getDye(1), "§cDelete", click -> { + player.closeInventory(); + Region region = DynamicRegionSystem.INSTANCE.get(tile); + Set tiles = DynamicRegionSystem.INSTANCE.getTilesOfRegion(region); + region.delete(); + + SWPlayer.allWithSingleComponent(DynamicRegionVisualizer.class) + .forEach(pair -> { + pair.getComponent().resetTiles(tiles); + }); + })); + inv.open(); + } else { + List, RegionConstructorData>>> entries = new ArrayList<>(); + DynamicRegionSystem.constructorDataMap.entrySet() + .stream() + .filter(entry -> entry.getValue().placeable()) + .sorted(Comparator.comparing(entry -> entry.getValue().name())) + .forEach(entry -> { + entries.add(new SWListInv.SWListEntry<>(new SWItem(entry.getValue().material(), entry.getValue().name()), entry)); + }); + + SWListInv, RegionConstructorData>> listInv = new SWListInv<>(player, "Select Region for: " + tile.display(), entries, (click, entry) -> { + new Placement(entry.getKey(), entry.getValue(), tile); + player.closeInventory(); + }); + listInv.open(); + } }); - entities.add(entity); + entities.add(interaction); + } + } + + private class Placement { + private final Class regionType; + private final RegionConstructorData constructorData; + + private CWireframe wireframe; + private Tile sourceTile; + private int dx; + private int dz; + private boolean valid = false; + + private Location getMinLocation() { + Tile tile = sourceTile.add(-DynamicRegionVisualizer.this.sourceTile.getTileX(), -DynamicRegionVisualizer.this.sourceTile.getTileZ()).orElseThrow(); + return sourceLocation.clone().add(tile.getTileX(), 0, tile.getTileZ()); + } + + private Location getMaxLocation() { + Tile tile = sourceTile.add(-DynamicRegionVisualizer.this.sourceTile.getTileX(), -DynamicRegionVisualizer.this.sourceTile.getTileZ()).orElseThrow(); + return sourceLocation.clone().add(tile.getTileX(), 0, tile.getTileZ()).add(dx, 0, dz); + } + + public Placement(Class regionType, RegionConstructorData constructorData, Tile sourceTile) { + this.regionType = regionType; + this.constructorData = constructorData; + this.sourceTile = sourceTile; + dx = constructorData.widthX() / Tile.tileSize - 1; + dz = constructorData.widthZ() / Tile.tileSize - 1; + if (dx == 0 && dz == 0) { + place(); + return; + } + + placement = this; + wireframe = new CWireframe(entityServer); + check(); + } + + private void check() { + wireframe.setPos1And2(getMinLocation(), getMaxLocation()); + for (int x = 0; x <= dx; x++) { + for (int z = 0; z <= dz; z++) { + if (!DynamicRegionSystem.INSTANCE.get(sourceTile.add(x, z).orElseThrow()).getType().isGlobal()) { + wireframe.setBlock(Material.RED_CONCRETE.createBlockData()); + valid = false; + return; + } + } + } + wireframe.setBlock(Material.LIME_CONCRETE.createBlockData()); + valid = true; + } + + public void click(Tile tile) { + if (sourceTile.getTileX() >= tile.getTileX() && sourceTile.getTileX() + dx <= tile.getTileX()) { + if (sourceTile.getTileZ() >= tile.getTileZ() && sourceTile.getTileZ() + dz <= tile.getTileZ()) { + if (valid) { + SWInventory inv = new SWInventory(player, 9, "Place Region: " + constructorData.name()); + inv.setItem(0, new SWItem(SWItem.getDye(1), "§cDeselect", click -> { + placement = null; + wireframe.die(); + player.closeInventory(); + })); + inv.setItem(8, new SWItem(SWItem.getDye(10), "§aPlace", click -> { + player.closeInventory(); + place(); + })); + inv.open(); + } + return; + } + } + + if (dx == 0 && dz == 0) { + sourceTile = tile; + } else { + Set tiles = new HashSet<>(); + for (int x = 0; x <= dx; x++) { + for (int z = 0; z <= dz; z++) { + tiles.add(Tile.fromTile(x + sourceTile.getTileX(), z + sourceTile.getTileZ()).orElseThrow()); + } + } + Tile selected = tiles.stream().min(Comparator.comparing(current -> { + int dx = current.getTileX() - tile.getTileX(); + int dz = current.getTileZ() - tile.getTileZ(); + return dx * dx + dz * dz; + })) + .orElseThrow(); + + int dx = tile.getTileX() - selected.getTileX(); + int dz = tile.getTileZ() - selected.getTileZ(); + sourceTile = sourceTile.add(dx, dz).orElseThrow(); + } + check(); + } + + private void place() { + DynamicRegion dynamicRegion = DynamicRegionRepository.constructRegion(regionType, UUID.randomUUID(), sourceTile.getMinX(), sourceTile.getMinZ()); + if (dynamicRegion == null) { + // TODO: Give error to user + return; + } + + dynamicRegion.getArea().place(new PasteBuilder(new PasteBuilder.FileProvider(dynamicRegion.getArea().getResetFile())), false); + dynamicRegion.updateNeighbours(); + + placement = null; + if (wireframe != null) wireframe.die(); + Set tiles = new HashSet<>(); + for (int x = 0; x <= dx; x++) { + for (int z = 0; z <= dz; z++) { + tiles.add(Tile.fromTile(x + sourceTile.getTileX(), z + sourceTile.getTileZ()).orElseThrow()); + } + } + SWPlayer.allWithSingleComponent(DynamicRegionVisualizer.class) + .forEach(pair -> pair.getComponent().resetTiles(tiles)); } } } diff --git a/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/RegionConstructorData.java b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/RegionConstructorData.java index 87e3ab76..1008d5de 100644 --- a/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/RegionConstructorData.java +++ b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/RegionConstructorData.java @@ -20,6 +20,7 @@ package de.steamwar.bausystem.region.dynamic; import org.atteo.classindex.IndexAnnotated; +import org.bukkit.Material; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -32,6 +33,7 @@ import java.lang.annotation.Target; public @interface RegionConstructorData { String identifier(); String name(); + Material material(); int widthX(); int widthZ(); boolean placeable() default true; diff --git a/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/Tile.java b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/Tile.java index 3f327d97..b3a6e3b2 100644 --- a/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/Tile.java +++ b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/Tile.java @@ -138,4 +138,20 @@ public class Tile { public String toString() { return tileX + ":" + tileZ; } + + public String display() { + StringBuilder st = new StringBuilder(); + if (tileX >= 0) { + st.append("+"); + } + st.append(tileX); + + st.append(" / "); + + if (tileZ >= 0) { + st.append("+"); + } + st.append(tileZ); + return st.toString(); + } } diff --git a/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/modes/microwargear_7/display/MiWG7DisplayRegion.java b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/modes/microwargear_7/display/MiWG7DisplayRegion.java index 02801c2d..05d90607 100644 --- a/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/modes/microwargear_7/display/MiWG7DisplayRegion.java +++ b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/modes/microwargear_7/display/MiWG7DisplayRegion.java @@ -38,6 +38,7 @@ import java.util.UUID; @RegionConstructorData( identifier = "microwargear_display", name = "MicoWarGearDisplay", + material = Material.STONE_BUTTON, widthX = Tile.tileSize, widthZ = Tile.tileSize ) diff --git a/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/path/PathRegion.java b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/path/PathRegion.java index 9bf55f39..4d859d60 100644 --- a/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/path/PathRegion.java +++ b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/path/PathRegion.java @@ -31,6 +31,7 @@ import java.util.UUID; @RegionConstructorData( identifier = "path", name = "Path", + material = Material.DIRT_PATH, widthX = Tile.tileSize, widthZ = Tile.tileSize ) diff --git a/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/special/dry/DryRegion.java b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/special/dry/DryRegion.java index c7090f7e..211a72c9 100644 --- a/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/special/dry/DryRegion.java +++ b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/special/dry/DryRegion.java @@ -38,6 +38,7 @@ import static de.steamwar.bausystem.region.dynamic.special.SpecialArea.SPECIAL_P @RegionConstructorData( identifier = "special_dry", name = "Dry", + material = Material.SAND, widthX = Tile.tileSize, widthZ = Tile.tileSize ) diff --git a/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/special/wet/WetRegion.java b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/special/wet/WetRegion.java index 5c1faddd..904f080d 100644 --- a/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/special/wet/WetRegion.java +++ b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/special/wet/WetRegion.java @@ -37,6 +37,7 @@ import static de.steamwar.bausystem.region.dynamic.special.SpecialArea.SPECIAL_P @RegionConstructorData( identifier = "special_wet", name = "Wet", + material = Material.LIGHT_BLUE_CONCRETE_POWDER, widthX = Tile.tileSize, widthZ = Tile.tileSize )