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 73eb44c9..74ab6bc1 100644 --- a/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/DynamicRegionCommand.java +++ b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/DynamicRegionCommand.java @@ -29,6 +29,7 @@ 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; @@ -44,6 +45,18 @@ public class DynamicRegionCommand extends SWCommand { super(""); } + @Register({"dynamic", "visualize"}) + 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 { + swPlayer.setComponent(new DynamicRegionVisualizer()); + } + } + @Register({"dynamic", "place"}) public void placeRegion(Player player, @Mapper("regionType") String regionType) { Region region = DynamicRegionSystem.INSTANCE.get(player.getLocation()); diff --git a/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/DynamicRegionVisualizer.java b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/DynamicRegionVisualizer.java new file mode 100644 index 00000000..27d6a68a --- /dev/null +++ b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/DynamicRegionVisualizer.java @@ -0,0 +1,146 @@ +/* + * 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 de.steamwar.bausystem.BauSystem; +import de.steamwar.bausystem.region.dynamic.Tile; +import de.steamwar.core.SWPlayer; +import de.steamwar.entity.*; +import de.steamwar.inventory.SWInventory; +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.stream.Collectors; + +public class DynamicRegionVisualizer implements SWPlayer.Component, Listener { + + private final REntityServer entityServer; + private Player player; + private Location sourceLocation; + private Tile sourceTile; + + public DynamicRegionVisualizer() { + this.entityServer = new REntityServer(); + } + + @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(); + } + + @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 void renderTiles(int dx, int dz) { + Set tileSet = entityServer.getEntitiesByType(CTile.class) + .stream() + .filter(cTile -> { + if (Math.abs(cTile.tile.getTileX() - dx) > 20 || Math.abs(cTile.tile.getTileZ() - dz) > 20) { + cTile.die(); + return false; + } else { + return true; + } + }) + .map(cTile -> cTile.tile) + .collect(Collectors.toSet()); + + for (int x = dx - 10; x <= dx + 10; x++) { + for (int z = dz - 10; z <= dz + 10; z++) { + Tile tile = sourceTile.add(x, z).orElse(null); + if (tile == null || tileSet.contains(tile)) continue; + new CTile(entityServer, tile); + } + } + } + + private class CTile extends CEntity { + + private final Tile tile; + + public CTile(REntityServer server, Tile tile) { + super(server); + this.tile = tile; + + Material material = switch (DynamicRegionSystem.INSTANCE.get(tile).getType()) { + 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 spawn = new CCubedTextDisplay(entityServer, location); + spawn.setText("§eORIGIN"); + spawn.setBackgroundColor(0); + spawn.setShadowed(false); + entities.add(spawn); + } + + RBlockDisplay entity = new RBlockDisplay(entityServer, location); + entity.setBlock(material.createBlockData()); + entities.add(entity); + + 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(); + }); + entities.add(entity); + } + } +} 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 68f77a35..3f327d97 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 @@ -20,14 +20,18 @@ package de.steamwar.bausystem.region.dynamic; import de.steamwar.bausystem.region.Point; +import lombok.EqualsAndHashCode; import lombok.Getter; import org.bukkit.Location; import java.util.Optional; @Getter +@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 = 1023; @@ -122,12 +126,12 @@ public class Tile { return fromTile(tileX + offsetX, tileZ + offsetZ); } - public static long getID(int tileX, int tileZ) { + public static long getId(int tileX, int tileZ) { return (tileX + maxTile) * tilesPerAxis + tileZ + maxTile; } public long getId() { - return getID(tileX, tileZ); + return getId(tileX, tileZ); } @Override diff --git a/BauSystem/build.gradle.kts b/BauSystem/build.gradle.kts index 5a8b572d..1034e4eb 100644 --- a/BauSystem/build.gradle.kts +++ b/BauSystem/build.gradle.kts @@ -44,6 +44,7 @@ tasks.register("DevBau21") { tasks.register("DevBau21Dynamic") { group = "run" description = "Run a 1.21 Dynamic Dev Bau" + dependsOn(":SpigotCore:shadowJar") dependsOn(":BauSystem:shadowJar") dependsOn(":SchematicSystem:shadowJar") template = "Bau21-Dynamic"