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 064179b5..b0e7c6e5 100644 --- a/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/DynamicRegionCommand.java +++ b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/DynamicRegionCommand.java @@ -36,15 +36,15 @@ public class DynamicRegionCommand extends SWCommand { @Register({"dynamic"}) public void visualizeRegions(Player player) { - Tile tile = Tile.fromLocation(player.getLocation()).orElse(null); - if (tile == null) return; SWPlayer swPlayer = SWPlayer.of(player); if (swPlayer.hasComponent(DynamicRegionVisualizer.class)) { swPlayer.removeComponent(DynamicRegionVisualizer.class); - } else if (Permission.SUPERVISOR.hasPermission(player)) { - swPlayer.setComponent(new DynamicRegionVisualizer()); + swPlayer.removeComponent(DynamicRegionEditor.class); } else { - // TODO: Add Message + swPlayer.setComponent(DynamicRegionVisualizer.INSTANCE); + if (Permission.SUPERVISOR.hasPermission(player)) { + swPlayer.setComponent(new DynamicRegionEditor(player.getPlayer())); + } } } } diff --git a/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/DynamicRegionEditor.java b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/DynamicRegionEditor.java new file mode 100644 index 00000000..7ac91e95 --- /dev/null +++ b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/DynamicRegionEditor.java @@ -0,0 +1,354 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2026 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.region; + +import com.comphenix.tinyprotocol.TinyProtocol; +import de.steamwar.Reflection; +import de.steamwar.bausystem.BauSystem; +import de.steamwar.bausystem.Permission; +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.CArea; +import de.steamwar.entity.REntityServer; +import de.steamwar.entity.RInteraction; +import de.steamwar.inventory.SWInventory; +import de.steamwar.inventory.SWItem; +import de.steamwar.inventory.SWListInv; +import lombok.NonNull; +import net.md_5.bungee.api.ChatMessageType; +import net.md_5.bungee.api.chat.TextComponent; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.data.BlockData; +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.PlayerInteractEvent; +import org.bukkit.event.player.PlayerMoveEvent; +import org.bukkit.event.player.PlayerSwapHandItemsEvent; +import org.bukkit.scheduler.BukkitTask; +import org.bukkit.util.Vector; +import org.joml.RayAabIntersection; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.function.BiFunction; + +public class DynamicRegionEditor implements SWPlayer.Component, Listener { + + private static final Class position = Reflection.getClass("net.minecraft.network.protocol.game.ServerboundMovePlayerPacket$Pos"); + private static final Class look = Reflection.getClass("net.minecraft.network.protocol.game.ServerboundMovePlayerPacket$Rot"); + private static final Class positionLook = Reflection.getClass("net.minecraft.network.protocol.game.ServerboundMovePlayerPacket$PosRot"); + + static { + BiFunction function = (player, object) -> { + SWPlayer.of(player).getComponent(DynamicRegionEditor.class).ifPresent(DynamicRegionEditor::calcCursor); + return object; + }; + TinyProtocol.instance.addFilter(position, function); + TinyProtocol.instance.addFilter(look, function); + TinyProtocol.instance.addFilter(positionLook, function); + } + + private final REntityServer entityServer = new REntityServer(); + private final CArea area = new CArea(entityServer); + + private static final BlockData DELETE = Material.RED_CONCRETE.createBlockData(); + private static final BlockData INVALID = Material.YELLOW_CONCRETE.createBlockData(); + private static final BlockData PLACE = Material.LIME_CONCRETE.createBlockData(); + + { + area.hide(true); + } + + private final Player player; + + private final BukkitTask task; + private Type type = new Delete(); + + public DynamicRegionEditor(Player player) { + this.player = player; + entityServer.addPlayer(player); + + Bukkit.getPluginManager().registerEvents(this, BauSystem.getInstance()); + + for (int i = 0; i < 121; i++) { + new RInteraction(entityServer, player.getLocation()); + } + moveInteractionEntities(Point.fromLocation(player.getLocation())); + + CArea area = new CArea(entityServer); + area.setPos1And2(new Location(null, -Tile.maxTile, 1, -Tile.maxTile), new Location(null, Tile.maxTile, 1, Tile.maxTile)); + area.setBlock(Material.BEDROCK.createBlockData()); + + task = Bukkit.getScheduler().runTaskTimer(BauSystem.getInstance(), this::showHotbar, 0, 20); + } + + private void showHotbar() { + entityServer.tick(); + + StringBuilder st = new StringBuilder(); + st.append(type.title()); + st.append(" §8(§7Change with §eSwap Hands§8)"); + player.spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(st.toString())); + } + + @Override + public void onUnmount(SWPlayer player) { + entityServer.close(); + task.cancel(); + PlayerMoveEvent.getHandlerList().unregister(this); + } + + @EventHandler + public void onPlayerMove(PlayerMoveEvent event) { + if (event.getPlayer() != player) return; + if (!Permission.SUPERVISOR.hasPermission(player)) { + SWPlayer.of(player).removeComponent(DynamicRegionEditor.class); + return; + } + if (event.getTo() == null) return; + if (event.getFrom().getBlockX() == event.getTo().getBlockX() && event.getFrom().getBlockZ() == event.getTo().getBlockZ()) { + return; + } + moveInteractionEntities(Point.fromLocation(event.getTo())); + } + + private void moveInteractionEntities(Point position) { + List interactionList = entityServer.getEntitiesByType(RInteraction.class); + for (int x = -5; x <= 5; x++) { + for (int z = -5; z <= 5; z++) { + interactionList.removeFirst().move(position.getX() + x + 0.5, 0, position.getZ() + z + 0.5, 0, 0, (byte) 0); + } + } + } + + @EventHandler(priority = EventPriority.LOWEST) + public void onPlayerSwapHandItems(PlayerSwapHandItemsEvent event) { + event.setCancelled(true); + + List> list = new ArrayList<>(); + list.add(new SWListInv.SWListEntry<>(new SWItem(Material.BARRIER, "§cDelete"), new Delete())); + + DynamicRegionSystem.constructorDataMap.values() + .stream() + .sorted(Comparator.comparing(RegionConstructorData::name)) + .forEach(data -> { + list.add(new SWListInv.SWListEntry<>(new SWItem(data.material(), "§f" + data.name()), new Place(data))); + }); + + SWListInv inventory = new SWListInv<>(player, "Select Region to place", list, (click, type) -> { + this.type = type; + player.closeInventory(); + showHotbar(); + }); + inventory.open(); + } + + private void calcCursor() { + Location startPos = player.getLocation().clone().add(0.0, player.getEyeHeight(), 0.0); + Vector direction = player.getLocation().getDirection(); + + RayAabIntersection intersection = new RayAabIntersection((float) startPos.getX(), (float) startPos.getY(), (float) startPos.getZ(), (float) direction.getX(), (float) direction.getY(), (float) direction.getZ()); + boolean hide = true; + for (RInteraction interaction : entityServer.getEntitiesByType(RInteraction.class)) { + float x = (float) (interaction.getX() - 0.5); + float z = (float) (interaction.getZ() - 0.5); + if (intersection.test(x, (float) 0.95, z, x + 1, (float) 1.05, z + 1)) { + int tileX = (int) x; + int tileZ = (int) z; + if (type.visualize(area, tileX, tileZ)) { + hide = false; + break; + } + } + } + area.hide(hide); + } + + @EventHandler + public void onPlayerInteract(PlayerInteractEvent event) { + Location startPos = player.getLocation().clone().add(0.0, player.getEyeHeight(), 0.0); + Vector direction = player.getLocation().getDirection(); + if (direction.getY() > 0) return; + + RayAabIntersection intersection = new RayAabIntersection((float) startPos.getX(), (float) startPos.getY(), (float) startPos.getZ(), (float) direction.getX(), (float) direction.getY(), (float) direction.getZ()); + for (RInteraction interaction : entityServer.getEntitiesByType(RInteraction.class)) { + float x = (float) (interaction.getX() - 0.5); + float z = (float) (interaction.getZ() - 0.5); + if (intersection.test(x, (float) 0.95, z, x + 1, (float) 1.05, z + 1)) { + int tileX = (int) x; + int tileZ = (int) z; + type.run(event.getPlayer(), tileX, tileZ); + break; + } + } + } + + private interface Type { + + String title(); + + boolean visualize(CArea area, int tileX, int tileZ); + + void run(Player player, int tileX, int tileZ); + } + + private static class Delete implements Type { + + private boolean valid = false; + + private Delete() { + } + + @Override + public String title() { + return "§cDelete"; + } + + @Override + public boolean visualize(CArea area, int tileX, int tileZ) { + Tile tile = Tile.fromTile(tileX, tileZ).orElse(null); + if (tile == null) { + valid = false; + return false; + } + Region region = DynamicRegionSystem.INSTANCE.get(tile); + if (region.getType().isGlobal()) { + valid = false; + return false; + } + Tile minTile = Tile.fromPoint(region.getArea().getMinPoint(false)).orElse(null); + Tile maxTile = Tile.fromPoint(region.getArea().getMaxPoint(false)).orElse(null); + if (minTile == null || maxTile == null) { + valid = false; + return false; + } + Location minLoc = new Location(null, minTile.getTileX(), 1, minTile.getTileZ()); + Location maxLoc = new Location(null, maxTile.getTileX(), 1, maxTile.getTileZ()); + area.setBlock(DELETE); + area.setPos1And2(minLoc, maxLoc); + valid = true; + return true; + } + + @Override + public void run(Player player, int tileX, int tileZ) { + if (!valid) return; + Tile tile = Tile.fromTile(tileX, tileZ).orElse(null); + if (tile == null) return; + Region region = DynamicRegionSystem.INSTANCE.get(tile); + if (region.getType().isGlobal()) return; + + if (region.getType().isPath()) { + region.delete(); + return; + } + + RegionConstructorData data = DynamicRegionSystem.constructorDataMap.get(region.getClass()); + SWInventory inventory = new SWInventory(player, 9, "Confirm delete: " + data.name()); + inventory.setItem(0, new SWItem(Material.GRAY_CONCRETE, "§7Cancel", click -> { + player.closeInventory(); + })); + inventory.setItem(8, new SWItem(Material.RED_CONCRETE, "§cDelete: " + data.name(), click -> { + Region checkRegion = DynamicRegionSystem.INSTANCE.get(tile); + if (region == checkRegion) region.delete(); + player.closeInventory(); + })); + inventory.open(); + } + } + + private static class Place implements Type { + + private final RegionConstructorData data; + private final int widthX; + private final int widthZ; + + private boolean valid = false; + + private Place(@NonNull RegionConstructorData data) { + this.data = data; + this.widthX = data.widthX() - 1; + this.widthZ = data.widthZ() - 1; + } + + @Override + public String title() { + return "§ePlace§8: §a" + data.name(); + } + + private boolean validPlacement(int tileX, int tileZ) { + for (int x = 0; x <= widthX; x++) { + for (int z = 0; z <= widthZ; z++) { + Tile tile = Tile.fromTile(tileX + x, tileZ + z).orElse(null); + if (tile == null) return false; + Region region = DynamicRegionSystem.INSTANCE.get(tile); + if (!region.getType().isGlobal()) return false; + } + } + return true; + } + + @Override + public boolean visualize(CArea area, int tileX, int tileZ) { + Tile tile = Tile.fromTile(tileX, tileZ).orElse(null); + if (tile == null) { + valid = false; + return false; + } + // Center Tile placement! + tileX -= widthX / 2; + tileZ -= widthZ / 2; + // Validate placements! + if (validPlacement(tileX, tileZ)) { + area.setBlock(PLACE); + valid = true; + } else { + area.setBlock(INVALID); + valid = false; + } + area.setPos1And2(new Location(null, tileX, 1, tileZ), new Location(null, tileX + widthX, 1, tileZ + widthZ)); + return true; + } + + @Override + public void run(Player player, int tileX, int tileZ) { + if (!valid) return; + // Center Tile placement! + tileX -= widthX / 2; + tileZ -= widthZ / 2; + if (!validPlacement(tileX, tileZ)) return; + Tile tile = Tile.fromTile(tileX, tileZ).orElse(null); + if (tile == null) return; + DynamicRegion region = DynamicRegionRepository.constructRegion(DynamicRegionSystem.identifierDataMap.get(data.identifier()), tile); + if (region == null) return; + region.getArea().place(new PasteBuilder(), false); + region.updateNeighbours(); + } + } +} 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 22e0f8c8..199975c6 100644 --- a/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/DynamicRegionSystem.java +++ b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/DynamicRegionSystem.java @@ -56,12 +56,14 @@ public class DynamicRegionSystem implements RegionSystem { regionCache.clear(); regionMap.put(region.getID(), region); regionTypeMap.computeIfAbsent(region.getType(), __ -> new HashSet<>()).add(region); + DynamicRegionVisualizer.INSTANCE.addRegion(region); } public void remove(DynamicRegion region) { regionCache.clear(); regionMap.remove(region.getID()); regionTypeMap.getOrDefault(region.getType(), Collections.emptySet()).remove(region); + DynamicRegionVisualizer.INSTANCE.removeRegion(region); } public static Map, RegionConstructorData> constructorDataMap = new HashMap<>(); @@ -197,31 +199,37 @@ public class DynamicRegionSystem implements RegionSystem { Set> neighbours = new HashSet<>(); if (!noCorners) { - neighbours.add(new Neighbour<>(get(minTile.add(-1, -1).orElseThrow(), fastCache, regions), minTile, NeighbourDirection.NorthWest)); + neighbours.add(new Neighbour<>(get(minTile.add(-1, -1).orElse(null), fastCache, regions), minTile, NeighbourDirection.NorthWest)); - Tile cornerMinMaxSelf = Tile.fromTile(minTile.getTileX(), maxTile.getTileZ()).orElseThrow(); - neighbours.add(new Neighbour<>(get(cornerMinMaxSelf.add(-1, 1).orElseThrow(), fastCache, regions), cornerMinMaxSelf, NeighbourDirection.SouthWest)); + Tile.fromTile(minTile.getTileX(), maxTile.getTileZ()).ifPresent(cornerMinMaxSelf -> { + neighbours.add(new Neighbour<>(get(cornerMinMaxSelf.add(-1, 1).orElse(null), fastCache, regions), cornerMinMaxSelf, NeighbourDirection.SouthWest)); + }); - Tile cornerMaxMinSelf = Tile.fromTile(maxTile.getTileX(), minTile.getTileZ()).orElseThrow(); - neighbours.add(new Neighbour<>(get(cornerMaxMinSelf.add(1, -1).orElseThrow(), fastCache, regions), cornerMaxMinSelf, NeighbourDirection.NorthEast)); + Tile.fromTile(maxTile.getTileX(), minTile.getTileZ()).ifPresent(cornerMaxMinSelf -> { + neighbours.add(new Neighbour<>(get(cornerMaxMinSelf.add(1, -1).orElse(null), fastCache, regions), cornerMaxMinSelf, NeighbourDirection.NorthEast)); + }); - neighbours.add(new Neighbour<>(get(maxTile.add(1, 1).orElseThrow(), fastCache, regions), maxTile, NeighbourDirection.SouthEast)); + neighbours.add(new Neighbour<>(get(maxTile.add(1, 1).orElse(null), fastCache, regions), maxTile, NeighbourDirection.SouthEast)); } for (int x = minTile.getTileX(); x <= maxTile.getTileX(); x++) { - Tile tileMinZSelf = Tile.fromTile(x, minTile.getTileZ()).orElseThrow(); - neighbours.add(new Neighbour<>(get(tileMinZSelf.add(0, -1).orElseThrow(), fastCache, regions), tileMinZSelf, NeighbourDirection.North)); + Tile.fromTile(x, minTile.getTileZ()).ifPresent(tileMinZSelf -> { + neighbours.add(new Neighbour<>(get(tileMinZSelf.add(0, -1).orElse(null), fastCache, regions), tileMinZSelf, NeighbourDirection.North)); + }); - Tile tileMaxZSelf = Tile.fromTile(x, maxTile.getTileZ()).orElseThrow(); - neighbours.add(new Neighbour<>(get(tileMaxZSelf.add(0, 1).orElseThrow(), fastCache, regions), tileMaxZSelf, NeighbourDirection.South)); + Tile.fromTile(x, maxTile.getTileZ()).ifPresent(tileMaxZSelf -> { + neighbours.add(new Neighbour<>(get(tileMaxZSelf.add(0, 1).orElse(null), fastCache, regions), tileMaxZSelf, NeighbourDirection.South)); + }); } for (int z = minTile.getTileZ(); z <= maxTile.getTileZ(); z++) { - Tile tileMinXSelf = Tile.fromTile(minTile.getTileX(), z).orElseThrow(); - neighbours.add(new Neighbour<>(get(tileMinXSelf.add(-1, 0).orElseThrow(), fastCache, regions), tileMinXSelf, NeighbourDirection.West)); + Tile.fromTile(minTile.getTileX(), z).ifPresent(tileMinXSelf -> { + neighbours.add(new Neighbour<>(get(tileMinXSelf.add(-1, 0).orElse(null), fastCache, regions), tileMinXSelf, NeighbourDirection.West)); + }); - Tile tileMaxXSelf = Tile.fromTile(maxTile.getTileX(), z).orElseThrow(); - neighbours.add(new Neighbour<>(get(tileMaxXSelf.add(1, 0).orElseThrow(), fastCache, regions), tileMaxXSelf, NeighbourDirection.East)); + Tile.fromTile(maxTile.getTileX(), z).ifPresent(tileMaxXSelf -> { + neighbours.add(new Neighbour<>(get(tileMaxXSelf.add(1, 0).orElse(null), fastCache, regions), tileMaxXSelf, NeighbourDirection.East)); + }); } neighbours.removeIf(neighbour -> neighbour.region.getType().isGlobal()); 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 160e1a0b..994dbc4e 100644 --- a/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/DynamicRegionVisualizer.java +++ b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/DynamicRegionVisualizer.java @@ -19,313 +19,96 @@ 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.player.PlayerMoveEvent; +import org.bukkit.World; +import org.bukkit.entity.Display; +import org.bukkit.util.Transformation; +import org.joml.Quaternionf; +import org.joml.Vector3f; -import java.util.*; -import java.util.stream.Collectors; +public class DynamicRegionVisualizer implements SWPlayer.Component { -public class DynamicRegionVisualizer implements SWPlayer.Component, Listener { + public static final DynamicRegionVisualizer INSTANCE = new DynamicRegionVisualizer(); - private final REntityServer entityServer; - private Player player; - private Location sourceLocation; - private Tile sourceTile; + private final REntityServer entityServer = new REntityServer(); - private Placement placement = null; + private DynamicRegionVisualizer() { + RTextDisplay text = new RTextDisplay(entityServer, new Location(null, 0.5, 1.1, 0.5)); + text.setText("Spawn"); + text.setBillboard(Display.Billboard.VERTICAL); + text.setBackgroundColor(0); + text.setShadowed(false); + text.setTransform(new Transformation(new Vector3f(0, 0, 0), new Quaternionf().rotationX((float) Math.toRadians(270)), new Vector3f(1, 1, 1), new Quaternionf())); + } - public DynamicRegionVisualizer() { - this.entityServer = new REntityServer(); + public void addRegion(DynamicRegion region) { + new CRegion(entityServer, region); + } + + public void removeRegion(DynamicRegion region) { + entityServer.getEntitiesByType(CRegion.class) + .stream() + .filter(cRegion -> cRegion.region == region) + .forEach(CRegion::die); } @Override public void onMount(SWPlayer player) { - this.player = player.getPlayer(); - sourceTile = Tile.fromLocation(player.getLocation()).orElse(null); - if (sourceTile == null) { - player.removeComponent(DynamicRegionVisualizer.class); - return; - } - sourceLocation = player.getLocation().add(0, -5, 0).getBlock().getLocation(); entityServer.addPlayer(player.getPlayer()); - - Bukkit.getPluginManager().registerEvents(this, BauSystem.getInstance()); - - renderTiles(0, 0); } @Override public void onUnmount(SWPlayer player) { - Bukkit.getPluginManager().registerEvents(this, BauSystem.getInstance()); - entityServer.close(); + entityServer.removePlayer(player.getPlayer()); } - @EventHandler - public void onPlayerMove(PlayerMoveEvent event) { - if (event.getPlayer() != player) return; - Location position = event.getTo().getBlock().getLocation(); - int dx = position.getBlockX() - sourceLocation.getBlockX(); - int dz = position.getBlockZ() - sourceLocation.getBlockZ(); - renderTiles(dx, dz); + private static final Vector3f VEC_ZERO = new Vector3f(0, 0, 0); + private static final Quaternionf QUT_ZERO = new Quaternionf(0, 0, 0, 1); + + public static Point toVisualization(Location worldLocation) { + Tile tile = Tile.fromLocation(worldLocation).orElseThrow(); + return new Point(tile.getTileX(), 0, tile.getTileZ()); } - private void renderTiles(int dx, int dz) { - Set tileSet = entityServer.getEntitiesByType(CTile.class) - .stream() - .filter(cTile -> { - if (Math.abs(cTile.tile.getTileX() - dx) > 40 || Math.abs(cTile.tile.getTileZ() - dz) > 40) { - cTile.die(); - return false; - } else { - return true; - } - }) - .map(cTile -> cTile.tile) - .collect(Collectors.toSet()); + private static class CRegion extends CEntity { - for (int x = dx - 20; x <= dx + 20; x++) { - for (int z = dz - 20; z <= dz + 20; z++) { - Tile tile = sourceTile.add(x, z).orElse(null); - if (tile == null || tileSet.contains(tile)) continue; - new CTile(entityServer, tile); - } - } - } + private final DynamicRegion region; - 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; - - public CTile(REntityServer server, Tile tile) { + private CRegion(REntityServer server, DynamicRegion region) { super(server); - this.tile = tile; + this.region = region; - 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; - case WET, WET_SPECIAL -> Material.LAPIS_BLOCK; - default -> Material.WHITE_CARPET; - }; - Location location = sourceLocation.clone().add(tile.getTileX() - sourceTile.getTileX(), 0, tile.getTileZ() - sourceTile.getTileZ()); - if (tile.equals(Tile.ZERO)) { - CCubedTextDisplay spawn = new CCubedTextDisplay(entityServer, location); - spawn.setText("§eSPAWN"); - spawn.setBackgroundColor(0); - spawn.setShadowed(false); - entities.add(spawn); - } else if (tile.equals(sourceTile)) { - CCubedTextDisplay origin = new CCubedTextDisplay(entityServer, location); - origin.setText("§eORIGIN"); - origin.setBackgroundColor(0); - origin.setShadowed(false); - entities.add(origin); + RegionConstructorData data = DynamicRegionSystem.constructorDataMap.get(region.getClass()); + int widthX = data.widthX(); + int widthZ = data.widthZ(); + + Point point = toVisualization(region.getArea().getMinPoint(false).toLocation((World) null)); + + if (widthX != 1 || widthZ != 1) { + CArea area = new CArea(server); + area.setBlock(Material.WHITE_CONCRETE.createBlockData()); + area.setPos1And2(point.toLocation((World) null).add(0, 1 - CArea.DEFAULT_WIDTH, 0), point.toLocation((World) null).add(widthX - 1, 1 - CArea.DEFAULT_WIDTH, widthZ - 1)); + entities.add(area); + + RTextDisplay text = new RTextDisplay(server, point.toLocation((World) null).add(widthX / 2.0, 1.1, widthZ / 2.0)); + text.setText(data.name()); + text.setBillboard(Display.Billboard.VERTICAL); + text.setBackgroundColor(0); + text.setShadowed(false); + text.setTransform(new Transformation(new Vector3f(0, 0, 0), new Quaternionf().rotationX((float) Math.toRadians(270)), new Vector3f(1, 1, 1), new Quaternionf())); + entities.add(text); } - 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) -> { - if (placement != null) { - placement.click(tile, regionType.isGlobal()); - 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(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()).orElse(null); - if (tile == null) tile = Tile.ZERO; - return sourceLocation.clone().add(tile.getTileX(), 0, tile.getTileZ()); - } - - private Location getMaxLocation() { - Tile tile = sourceTile.add(-DynamicRegionVisualizer.this.sourceTile.getTileX(), -DynamicRegionVisualizer.this.sourceTile.getTileZ()).orElse(null); - if (tile == null) tile = Tile.ZERO; - 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++) { - Tile tile = sourceTile.add(x, z).orElse(null); - if (tile == null || !DynamicRegionSystem.INSTANCE.get(tile).getType().isGlobal()) { - wireframe.setBlock(Material.RED_CONCRETE.createBlockData()); - valid = false; - return; - } - } - } - wireframe.setBlock(Material.LIME_CONCRETE.createBlockData()); - valid = true; - } - - public void click(Tile tile, boolean global) { - if (tile.getTileX() >= sourceTile.getTileX() && tile.getTileX() <= sourceTile.getTileX() + dx && tile.getTileZ() >= sourceTile.getTileZ() && tile.getTileZ() <= sourceTile.getTileZ() + dz) { - 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(); - })); - if (valid) { - inv.setItem(8, new SWItem(SWItem.getDye(10), "§aPlace", click -> { - player.closeInventory(); - place(); - })); - } else { - inv.setItem(8, new SWItem(SWItem.getDye(8), "§8Place", click -> { - })); - } - inv.open(); - return; - } - - if (!global) { - return; - } - - 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()).orElse(null)); - } - } - tiles.remove(null); - 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; - })) - .orElse(null); - if (selected == null) return; - - int dx = tile.getTileX() - selected.getTileX(); - int dz = tile.getTileZ() - selected.getTileZ(); - Tile newSourceTile = sourceTile.add(dx, dz).orElse(null); - if (newSourceTile == null) return; - sourceTile = newSourceTile; - check(); - } - - private void place() { - DynamicRegion dynamicRegion = DynamicRegionRepository.constructRegion(regionType, sourceTile); - if (dynamicRegion == null) { - // TODO: Give error to user - return; - } - - dynamicRegion.getArea().place(new PasteBuilder(), 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()).orElse(null)); - } - } - tiles.remove(null); - SWPlayer.allWithSingleComponent(DynamicRegionVisualizer.class) - .forEach(pair -> pair.getComponent().resetTiles(tiles)); + RBlockDisplay display = new RBlockDisplay(server, point.toLocation((World) null)); + display.setTransform(new Transformation(VEC_ZERO, QUT_ZERO, new Vector3f(widthX, 1, widthZ), QUT_ZERO)); + display.setBlock(data.material().createBlockData()); + entities.add(display); } } } 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 a498c130..6055543f 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 @@ -33,11 +33,9 @@ import java.util.stream.Stream; @EqualsAndHashCode public class Tile { - public static final Tile ZERO = new Tile(0, 0); - public static final int tileSize = 21; public static final int tileOffset = tileSize / 2; - public static final int maxTile = 255; + public static final int maxTile = 127; public static final int minTile = -maxTile; public static final int tilesPerAxis = maxTile * 2 + 1; diff --git a/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/global/GlobalRegion.java b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/global/GlobalRegion.java index 79652ccb..1028cc9b 100644 --- a/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/global/GlobalRegion.java +++ b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/global/GlobalRegion.java @@ -29,7 +29,6 @@ import org.bukkit.Location; import org.bukkit.Material; import javax.annotation.Nullable; -import java.io.File; import java.util.UUID; import java.util.function.BiConsumer; diff --git a/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/modes/AreaBlock.java b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/modes/AreaBlock.java index d6a3f75a..eb25edcb 100644 --- a/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/modes/AreaBlock.java +++ b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/modes/AreaBlock.java @@ -28,7 +28,6 @@ import de.steamwar.bausystem.utils.PasteBuilder; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.NonNull; -import org.bukkit.Location; @AllArgsConstructor(access = AccessLevel.PRIVATE) public class AreaBlock implements Region.Area { diff --git a/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/modes/microwargear_7/MiWG7DisplayRegion.java b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/modes/microwargear_7/MiWG7DisplayRegion.java index 9fb0c9fa..fb17b630 100644 --- a/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/modes/microwargear_7/MiWG7DisplayRegion.java +++ b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/modes/microwargear_7/MiWG7DisplayRegion.java @@ -40,9 +40,9 @@ import java.util.UUID; @RegionConstructorData( identifier = "microwargear_display_7", name = "MicroWarGearDisplay", - material = Material.STONE_BUTTON, - widthX = MiWG7DisplayRegion.TILE_X * Tile.tileSize, - widthZ = MiWG7DisplayRegion.TILE_Z * Tile.tileSize + material = Material.GRAY_CONCRETE, + widthX = MiWG7DisplayRegion.TILE_X, + widthZ = MiWG7DisplayRegion.TILE_Z ) public class MiWG7DisplayRegion extends DynamicRegion { diff --git a/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/modes/microwargear_7/MiWG7PlotRegion.java b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/modes/microwargear_7/MiWG7PlotRegion.java index 4f698d6c..24284c8b 100644 --- a/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/modes/microwargear_7/MiWG7PlotRegion.java +++ b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/modes/microwargear_7/MiWG7PlotRegion.java @@ -41,9 +41,9 @@ import java.util.UUID; @RegionConstructorData( identifier = "microwargear_plot_7", name = "MicroWarGearPlot", - material = Material.STONE_BUTTON, - widthX = Tile.tileSize * MiWG7PlotRegion.TILE_X, - widthZ = Tile.tileSize * MiWG7PlotRegion.TILE_Z + material = Material.GRAY_CONCRETE, + widthX = MiWG7PlotRegion.TILE_X, + widthZ = MiWG7PlotRegion.TILE_Z ) public class MiWG7PlotRegion extends DynamicRegion { diff --git a/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/modes/miniwargear/MWGDisplayRegion.java b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/modes/miniwargear/MWGDisplayRegion.java index 707f7e5a..f601ec0b 100644 --- a/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/modes/miniwargear/MWGDisplayRegion.java +++ b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/modes/miniwargear/MWGDisplayRegion.java @@ -40,9 +40,9 @@ import java.util.UUID; @RegionConstructorData( identifier = "miniwargear_display", name = "MiniWarGearDisplay", - material = Material.END_STONE_BRICK_SLAB, - widthX = MWGDisplayRegion.TILE_X * Tile.tileSize, - widthZ = MWGDisplayRegion.TILE_Z * Tile.tileSize + material = Material.YELLOW_CONCRETE, + widthX = MWGDisplayRegion.TILE_X, + widthZ = MWGDisplayRegion.TILE_Z ) public class MWGDisplayRegion extends DynamicRegion { diff --git a/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/modes/miniwargear/MWGPlotRegion.java b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/modes/miniwargear/MWGPlotRegion.java index f581bd8e..46fe88f4 100644 --- a/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/modes/miniwargear/MWGPlotRegion.java +++ b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/modes/miniwargear/MWGPlotRegion.java @@ -41,9 +41,9 @@ import java.util.UUID; @RegionConstructorData( identifier = "miniwargear_plot", name = "MiniWarGearPlot", - material = Material.END_STONE_BRICK_SLAB, - widthX = Tile.tileSize * MWGPlotRegion.TILE_X, - widthZ = Tile.tileSize * MWGPlotRegion.TILE_Z + material = Material.YELLOW_CONCRETE, + widthX = MWGPlotRegion.TILE_X, + widthZ = MWGPlotRegion.TILE_Z ) public class MWGPlotRegion extends DynamicRegion { diff --git a/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/modes/wargear_45/WG45DisplayRegion.java b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/modes/wargear_45/WG45DisplayRegion.java index 06d13033..1f47110e 100644 --- a/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/modes/wargear_45/WG45DisplayRegion.java +++ b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/modes/wargear_45/WG45DisplayRegion.java @@ -40,9 +40,9 @@ import java.util.UUID; @RegionConstructorData( identifier = "wargear_display_45", name = "WarGearDisplay 45", - material = Material.END_STONE_BRICKS, - widthX = WG45DisplayRegion.TILE_X * Tile.tileSize, - widthZ = WG45DisplayRegion.TILE_Z * Tile.tileSize + material = Material.YELLOW_CONCRETE, + widthX = WG45DisplayRegion.TILE_X, + widthZ = WG45DisplayRegion.TILE_Z ) public class WG45DisplayRegion extends DynamicRegion { diff --git a/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/modes/wargear_45/WG45PlotRegion.java b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/modes/wargear_45/WG45PlotRegion.java index 164018a6..7f026876 100644 --- a/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/modes/wargear_45/WG45PlotRegion.java +++ b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/modes/wargear_45/WG45PlotRegion.java @@ -41,9 +41,9 @@ import java.util.UUID; @RegionConstructorData( identifier = "wargear_plot_45", name = "WarGearPlot 45", - material = Material.END_STONE_BRICKS, - widthX = Tile.tileSize * WG45PlotRegion.TILE_X, - widthZ = Tile.tileSize * WG45PlotRegion.TILE_Z + material = Material.YELLOW_CONCRETE, + widthX = WG45PlotRegion.TILE_X, + widthZ = WG45PlotRegion.TILE_Z ) public class WG45PlotRegion extends DynamicRegion { diff --git a/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/modes/warship_175/WS175DisplayRegion.java b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/modes/warship_175/WS175DisplayRegion.java index a5726290..534f9712 100644 --- a/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/modes/warship_175/WS175DisplayRegion.java +++ b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/modes/warship_175/WS175DisplayRegion.java @@ -40,9 +40,9 @@ import java.util.UUID; @RegionConstructorData( identifier = "warship_display_175", name = "WarShipDisplay 175", - material = Material.BIRCH_BOAT, - widthX = WS175DisplayRegion.TILE_X * Tile.tileSize, - widthZ = WS175DisplayRegion.TILE_Z * Tile.tileSize + material = Material.BLUE_CONCRETE, + widthX = WS175DisplayRegion.TILE_X, + widthZ = WS175DisplayRegion.TILE_Z ) public class WS175DisplayRegion extends DynamicRegion { diff --git a/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/modes/warship_175/WS175PlotRegion.java b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/modes/warship_175/WS175PlotRegion.java index 7473006c..c12dc67b 100644 --- a/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/modes/warship_175/WS175PlotRegion.java +++ b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/modes/warship_175/WS175PlotRegion.java @@ -41,9 +41,9 @@ import java.util.UUID; @RegionConstructorData( identifier = "warship_plot_175", name = "WarShipPlot 175", - material = Material.BIRCH_BOAT, - widthX = Tile.tileSize * WS175PlotRegion.TILE_X, - widthZ = Tile.tileSize * WS175PlotRegion.TILE_Z + material = Material.BLUE_CONCRETE, + widthX = WS175PlotRegion.TILE_X, + widthZ = WS175PlotRegion.TILE_Z ) public class WS175PlotRegion extends DynamicRegion { diff --git a/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/modes/warship_230/WS230DisplayRegion.java b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/modes/warship_230/WS230DisplayRegion.java index 9596cb8f..6b867725 100644 --- a/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/modes/warship_230/WS230DisplayRegion.java +++ b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/modes/warship_230/WS230DisplayRegion.java @@ -40,9 +40,9 @@ import java.util.UUID; @RegionConstructorData( identifier = "warship_display_230", name = "WarShipDisplay 230", - material = Material.BIRCH_BOAT, - widthX = WS230DisplayRegion.TILE_X * Tile.tileSize, - widthZ = WS230DisplayRegion.TILE_Z * Tile.tileSize + material = Material.BLUE_CONCRETE, + widthX = WS230DisplayRegion.TILE_X, + widthZ = WS230DisplayRegion.TILE_Z ) public class WS230DisplayRegion extends DynamicRegion { diff --git a/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/modes/warship_230/WS230PlotRegion.java b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/modes/warship_230/WS230PlotRegion.java index 76296145..58bf13a2 100644 --- a/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/modes/warship_230/WS230PlotRegion.java +++ b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/modes/warship_230/WS230PlotRegion.java @@ -41,9 +41,9 @@ import java.util.UUID; @RegionConstructorData( identifier = "warship_plot_230", name = "WarShipPlot 230", - material = Material.BIRCH_BOAT, - widthX = Tile.tileSize * WS230PlotRegion.TILE_X, - widthZ = Tile.tileSize * WS230PlotRegion.TILE_Z + material = Material.BLUE_CONCRETE, + widthX = WS230PlotRegion.TILE_X, + widthZ = WS230PlotRegion.TILE_Z ) public class WS230PlotRegion extends DynamicRegion { 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 7cf28877..3d80f402 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 @@ -37,11 +37,14 @@ import java.util.stream.Collectors; identifier = "path", name = "Path", material = Material.DIRT_PATH, - widthX = Tile.tileSize, - widthZ = Tile.tileSize + widthX = PathRegion.TILE_X, + widthZ = PathRegion.TILE_Z ) public class PathRegion extends DynamicRegion { + protected static final int TILE_X = 1; + protected static final int TILE_Z = 1; + private final PathArea area; @Getter private final Tile tile; diff --git a/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/special/SpecialArea.java b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/special/SpecialArea.java index 116c978a..ffa68666 100644 --- a/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/special/SpecialArea.java +++ b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/special/SpecialArea.java @@ -31,12 +31,9 @@ import de.steamwar.bausystem.utils.PasteBuilder; import lombok.Getter; import lombok.NonNull; import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.jetbrains.annotations.Nullable; import java.io.File; import java.util.List; -import java.util.UUID; import java.util.concurrent.atomic.AtomicBoolean; public class SpecialArea implements Region.Area { 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 470d5cce..5a570841 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 @@ -26,8 +26,6 @@ import de.steamwar.bausystem.region.RegionData; import de.steamwar.bausystem.region.RegionHistory; import de.steamwar.bausystem.region.RegionType; import de.steamwar.bausystem.region.dynamic.*; -import de.steamwar.bausystem.region.dynamic.modes.AreaTile; -import de.steamwar.bausystem.region.dynamic.modes.DisplayRegionData; import de.steamwar.bausystem.region.dynamic.special.SpecialArea; import de.steamwar.bausystem.region.dynamic.special.SpecialRegionData; import de.steamwar.sql.GameModeConfig; @@ -43,12 +41,15 @@ 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 + material = Material.IRON_BLOCK, + widthX = DryRegion.TILE_X, + widthZ = DryRegion.TILE_Z ) public class DryRegion extends DynamicRegion { + protected static final int TILE_X = 1; + protected static final int TILE_Z = 1; + private static final VariantSelector DRY = VariantSelector.Get(new File(SPECIAL_PATH_DIR, "dry")); private final SpecialArea area; 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 183e7a57..bae2f070 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 @@ -27,7 +27,6 @@ import de.steamwar.bausystem.region.RegionHistory; import de.steamwar.bausystem.region.RegionType; import de.steamwar.bausystem.region.dynamic.*; import de.steamwar.bausystem.region.dynamic.special.SpecialArea; -import de.steamwar.bausystem.region.dynamic.special.SpecialRegionData; import de.steamwar.sql.GameModeConfig; import lombok.NonNull; import org.bukkit.Material; @@ -41,12 +40,15 @@ 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 + material = Material.LAPIS_BLOCK, + widthX = WetRegion.TILE_X, + widthZ = WetRegion.TILE_Z ) public class WetRegion extends DynamicRegion { + protected static final int TILE_X = 1; + protected static final int TILE_Z = 1; + private static final VariantSelector WET = VariantSelector.Get(new File(SPECIAL_PATH_DIR, "wet")); private final SpecialArea area; diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/entity/CArea.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/entity/CArea.java new file mode 100644 index 00000000..635b45b2 --- /dev/null +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/entity/CArea.java @@ -0,0 +1,83 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2026 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.entity; + +import org.bukkit.Location; +import org.bukkit.block.data.BlockData; +import org.bukkit.util.Vector; + +import java.util.List; + +public class CArea extends CEntity { + + public static final float DEFAULT_WIDTH = 1 / 16f; + + private Location pos1; + private Location pos2; + private float width = DEFAULT_WIDTH; + + public CArea(REntityServer server) { + super(server); + for (int i = 0; i < 4; i++) { + entities.add(new CLine(server)); + } + } + + public CArea setPos1And2(Location pos1, Location pos2) { + if (pos1.getY() != pos2.getY()) return this; + this.pos1 = pos1; + this.pos2 = pos2; + updateAndSpawnLines(); + return this; + } + + public CArea setWidth(float width) { + this.width = width; + updateAndSpawnLines(); + getEntitiesByType(CLine.class).forEach(haaLine -> { + haaLine.setWidth(width); + }); + return this; + } + + public CArea setBlock(BlockData blockData) { + getEntitiesByType(CLine.class).forEach(haaLine -> { + haaLine.setBlock(blockData); + }); + return this; + } + + private void updateAndSpawnLines() { + List lines = getEntitiesByType(CLine.class); + if (pos1 == null || pos2 == null) { + lines.forEach(line -> line.setFromAndTo(null, null)); + return; + } + + Vector min = Vector.getMinimum(pos1.toVector(), pos2.toVector()); + Vector max = Vector.getMaximum(pos1.toVector(), pos2.toVector()) + .add(new Vector(1 - width, 0, 1 - width)); + + lines.get(0).setFromAndTo(new Location(null, min.getX(), min.getY(), min.getZ()), new Location(null, max.getX() + width, min.getY(), min.getZ())); + lines.get(1).setFromAndTo(new Location(null, min.getX(), min.getY(), max.getZ()), new Location(null, max.getX() + width, min.getY(), max.getZ())); + lines.get(2).setFromAndTo(new Location(null, min.getX(), min.getY(), min.getZ()), new Location(null, min.getX(), min.getY(), max.getZ() + width)); + lines.get(3).setFromAndTo(new Location(null, max.getX(), min.getY(), min.getZ()), new Location(null, max.getX(), min.getY(), max.getZ() + width)); + } +} diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/entity/RInteraction.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/entity/RInteraction.java index 530aca91..29281372 100644 --- a/SpigotCore/SpigotCore_Main/src/de/steamwar/entity/RInteraction.java +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/entity/RInteraction.java @@ -22,7 +22,6 @@ package de.steamwar.entity; import de.steamwar.core.BountifulWrapper; import lombok.AccessLevel; import lombok.Getter; -import lombok.Setter; import org.bukkit.Location; import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; @@ -40,9 +39,8 @@ public class RInteraction extends REntity { protected final Consumer updatePacketSink = o -> server.updateEntity(this, o); - @Setter @Getter(AccessLevel.PRIVATE) - protected BiConsumer interaction; + protected RInteractionCallback callback; private float interactionWidth = 1.0f; private float interactionHeight = 1.0f; @@ -116,4 +114,12 @@ public class RInteraction extends REntity { dataSink.accept(responsiveWatcher, responsive); } } + + public void setCallback(RInteractionCallback callback) { + this.callback = callback; + } + + public void setCallback(BiConsumer callback) { + this.callback = (player, interaction, entityAction) -> callback.accept(player, entityAction); + } } diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/entity/RInteractionCallback.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/entity/RInteractionCallback.java new file mode 100644 index 00000000..938cbfa3 --- /dev/null +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/entity/RInteractionCallback.java @@ -0,0 +1,26 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2026 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.entity; + +import org.bukkit.entity.Player; + +public interface RInteractionCallback { + void call(Player player, RInteraction interaction, REntityServer.EntityAction entityAction); +}