diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/BauSystem.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/BauSystem.java index e1f7b11a..5a8cac69 100644 --- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/BauSystem.java +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/BauSystem.java @@ -32,6 +32,7 @@ import de.steamwar.bausystem.features.tracer.TraceManager; import de.steamwar.bausystem.features.tracer.TraceRecorder; import de.steamwar.bausystem.features.world.BauScoreboard; import de.steamwar.bausystem.linkage.BauGuiItem; +import de.steamwar.bausystem.region.Region; import de.steamwar.bausystem.region.RegionSystem; import de.steamwar.bausystem.utils.ScoreboardElement; import de.steamwar.bausystem.utils.TickManager; @@ -40,8 +41,9 @@ import de.steamwar.command.AbstractValidator; import de.steamwar.command.SWCommandUtils; import de.steamwar.core.CRIUSleepEvent; import de.steamwar.core.Core; -import de.steamwar.core.WorldEditRendererCUIEditor; import de.steamwar.core.WorldIdentifier; +import de.steamwar.core.worldedit.SteamEdit; +import de.steamwar.core.worldedit.WorldEditRendererCUIEditor; import de.steamwar.linkage.AbstractLinker; import de.steamwar.linkage.SpigotLinker; import de.steamwar.message.Message; @@ -49,6 +51,7 @@ import de.steamwar.providers.BauServerInfo; import lombok.Getter; import org.bukkit.Bukkit; import org.bukkit.GameRule; +import org.bukkit.Location; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; @@ -129,7 +132,19 @@ public class BauSystem extends JavaPlugin implements Listener { TraceManager.instance.init(); TraceRecorder.instance.init(); - new WorldEditRendererCUIEditor(); + SteamEdit.init(); + SteamEdit.ADJACENT_FILTERS = location -> { + Region region = Region.getRegion(location); + Region.Area area; + if (region.getBuildArea().inRegion(location, true)) { + area = region.getBuildArea(); + } else if (region.getTestblockArea().inRegion(location, true)) { + area = region.getTestblockArea(); + } else { + return SteamEdit.AdjacentFilter.ALWAYS; + } + return (x, y, z) -> area.inRegion(new Location(null, x, y, z), true); + }; Bukkit.getWorlds().get(0).setGameRule(GameRule.SEND_COMMAND_FEEDBACK, false); diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem.java index ebfbf7c1..c676308e 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem.java +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem.java @@ -21,7 +21,8 @@ package de.steamwar.fightsystem; import com.comphenix.tinyprotocol.TinyProtocol; import de.steamwar.core.Core; -import de.steamwar.core.WorldEditRendererCUIEditor; +import de.steamwar.core.worldedit.SteamEdit; +import de.steamwar.core.worldedit.WorldEditRendererCUIEditor; import de.steamwar.fightsystem.fight.Fight; import de.steamwar.fightsystem.fight.FightTeam; import de.steamwar.fightsystem.listener.ClickAnalyzer; @@ -107,7 +108,7 @@ public class FightSystem extends JavaPlugin { } }); new OneShotStateDependent(ArenaMode.All, FightState.PreSchemSetup, () -> Fight.playSound(SWSound.BLOCK_NOTE_PLING.getSound(), 100.0f, 2.0f)); - new OneShotStateDependent(ArenaMode.Test, FightState.All, WorldEditRendererCUIEditor::new); + new OneShotStateDependent(ArenaMode.Test, FightState.All, SteamEdit::init); Config.world.setGameRule(GameRule.REDUCED_DEBUG_INFO, ArenaMode.AntiTest.contains(Config.mode)); hullHider = new HullHider(); diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/record/PacketProcessor.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/record/PacketProcessor.java index 80fcf091..72d728c6 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/record/PacketProcessor.java +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/record/PacketProcessor.java @@ -20,7 +20,7 @@ package de.steamwar.fightsystem.record; import com.sk89q.worldedit.extent.clipboard.Clipboard; -import de.steamwar.core.WorldEditWrapper; +import de.steamwar.core.worldedit.WorldEditWrapper; import de.steamwar.entity.REntity; import de.steamwar.entity.REntityServer; import de.steamwar.entity.RPlayer; diff --git a/SpigotCore/SpigotCore_Main/src/SpigotCore.properties b/SpigotCore/SpigotCore_Main/src/SpigotCore.properties index 443c7583..e7e13eeb 100644 --- a/SpigotCore/SpigotCore_Main/src/SpigotCore.properties +++ b/SpigotCore/SpigotCore_Main/src/SpigotCore.properties @@ -108,19 +108,33 @@ UNNOSCHEMSUBMITTING = §e{0} §7may now submit §e§lschematics§7 again§8. WORLDEDIT_CUI_TITLE = WorldEdit CUI WORLDEDIT_CUI_TITLE_SUBMENU = WorldEdit CUI - {0} -WORLDEDIT_CUI_SELECTION = Own Selection -WORLDEDIT_CUI_CLIPBOARD = Own Clipboard -WORLDEDIT_CUI_SELECTION_OTHER = Other Selection -WORLDEDIT_CUI_CLIPBOARD_OTHER = Other Clipboard +WORLDEDIT_CUI_SELECTION = Selection +WORLDEDIT_CUI_CLIPBOARD = Clipboard +WORLDEDIT_CUI_CURSOR = Cursor WORLDEDIT_CUI_MATERIAL_NAME = §eWorldEdit {0} WORLDEDIT_CUI_MATERIAL_CLICK = §7Click to edit WORLDEDIT_CUI_WIDTH_NAME = §eWidth {0} +WORLDEDIT_CUI_WIDTH_NAME_DIST = §eRange {0} WORLDEDIT_CUI_WIDTH_LORE = §8> §7{0} WORLDEDIT_CUI_WIDTH_LORE_SELECTED = §8> §e{0} WORLDEDIT_CUI_WIDTH_CLICK = §7Click to change + WORLDEDIT_CUI_WIDTH_HUGE = 1/ 8 Block WORLDEDIT_CUI_WIDTH_LARGE = 1/16 Block WORLDEDIT_CUI_WIDTH_MEDIUM = 1/32 Block -WORLDEDIT_CUI_WIDTH_SLIM = 1/64 Block \ No newline at end of file +WORLDEDIT_CUI_WIDTH_SLIM = 1/64 Block + +WORLDEDIT_CUI_WIDTH_HUGE_DIST = 40 Blocks +WORLDEDIT_CUI_WIDTH_LARGE_DIST = 30 Blocks +WORLDEDIT_CUI_WIDTH_MEDIUM_DIST = 20 Blocks +WORLDEDIT_CUI_WIDTH_SLIM_DIST = 10 Blocks + +WORLDEDIT_CUI_TOOL_SOON = §7Tool cooming soon! +WORLDEDIT_CUI_TOOL_COPY = §eCopy Tool +WORLDEDIT_CUI_TOOL_COPY_LORE = §eClick§8:§7 copy selection +WORLDEDIT_CUI_TOOL_PASTE = §ePaste Tool +WORLDEDIT_CUI_TOOL_PASTE_LORE_1 = §eClick§8:§7 paste clipboard +WORLDEDIT_CUI_TOOL_PASTE_LORE_2 = §eShift §8+§e Click§8:§7 paste clipboard and select +WORLDEDIT_CUI_TOOL_PASTE_LORE_3 = §eDrop§8:§7 paste clipboard at copy origin \ No newline at end of file diff --git a/SpigotCore/SpigotCore_Main/src/SpigotCore_de.properties b/SpigotCore/SpigotCore_Main/src/SpigotCore_de.properties index ba204d5e..b7cba3c4 100644 --- a/SpigotCore/SpigotCore_Main/src/SpigotCore_de.properties +++ b/SpigotCore/SpigotCore_Main/src/SpigotCore_de.properties @@ -101,13 +101,20 @@ NOSCHEMSUBMITTING_UNTIL = §7Du bist §ebis zum {0} §7vom §e§lEinsenden von S UNNOSCHEMSUBMITTING_ERROR = §cDer Spieler ist nicht vom Einsenden von Schematics ausgeschlossen. UNNOSCHEMSUBMITTING = §e{0} §7darf nun wieder §e§lSchematis§7 einsenden§8. -WORLDEDIT_CUI_SELECTION = Eigene Auswahl -WORLDEDIT_CUI_CLIPBOARD = Eigene Kopie -WORLDEDIT_CUI_SELECTION_OTHER = Auswahl Anderer -WORLDEDIT_CUI_CLIPBOARD_OTHER = Kopie Anderer +WORLDEDIT_CUI_SELECTION = Auswahl +WORLDEDIT_CUI_CLIPBOARD = Kopie WORLDEDIT_CUI_MATERIAL_NAME = §eWorldEdit {0} WORLDEDIT_CUI_MATERIAL_CLICK = §7Klicke zum Editieren -WORLDEDIT_CUI_WIDTH_NAME = §eDicke - {0} -WORLDEDIT_CUI_WIDTH_CLICK = §7Klicke zum ändern \ No newline at end of file +WORLDEDIT_CUI_WIDTH_NAME = §eKlicke - {0} +WORLDEDIT_CUI_WIDTH_NAME_DIST = Reichweite§e {0} +WORLDEDIT_CUI_WIDTH_CLICK = §7Klicke zum ändern + +WORLDEDIT_CUI_TOOL_SOON = §7Werkzeug kommt in kürze! +WORLDEDIT_CUI_TOOL_COPY = §eCopy Werkzeug +WORLDEDIT_CUI_TOOL_COPY_LORE = §eKlick§8:§7 Auswahl zu kopieren +WORLDEDIT_CUI_TOOL_PASTE = §ePaste Werkzeug +WORLDEDIT_CUI_TOOL_PASTE_LORE_1 = §eKlick§8:§7 Clipboard einzufügen +WORLDEDIT_CUI_TOOL_PASTE_LORE_2 = §eUmschalt §8+§e Klick§8:§7 Clipboard einzufügen und auszuwählen +WORLDEDIT_CUI_TOOL_PASTE_LORE_3 = §eDrop§8:§7 Clipboard am Kopierpunkt einzufügen \ No newline at end of file diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/core/worldedit/SteamEdit.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/core/worldedit/SteamEdit.java new file mode 100644 index 00000000..03c7922e --- /dev/null +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/core/worldedit/SteamEdit.java @@ -0,0 +1,73 @@ +/* + * 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.core.worldedit; + +import de.steamwar.command.SWCommand; +import lombok.experimental.UtilityClass; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Function; + +@UtilityClass +public class SteamEdit { + + private static final AtomicBoolean INITIALIZED = new AtomicBoolean(); + + public static void init() { + INITIALIZED.set(true); + new Command(); + new SteamEditWand(); + new WorldEditRendererCUIEditor(); + } + + public boolean isInitialized() { + return INITIALIZED.get(); + } + + public static Function ADJACENT_FILTERS = location -> AdjacentFilter.ALWAYS; + + public interface AdjacentFilter { + AdjacentFilter ALWAYS = (x, y, z) -> true; + + boolean contains(int x, int y, int z); + } + + private static final class Command extends SWCommand { + + public Command() { + super("steamwand", "steamedit", "steameditwand", "swwand", "sweditwand", "swedit"); + } + + @Register + public void get(Player player) { + if (player.getInventory().contains(SteamEditWand.ITEM)) { + player.getInventory().remove(SteamEditWand.ITEM); + } + ItemStack handItem = player.getInventory().getItemInMainHand(); + player.getInventory().setItemInMainHand(SteamEditWand.ITEM); + if (!handItem.isEmpty()) { + player.getInventory().addItem(handItem); + } + } + } +} diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/core/worldedit/SteamEditSelectAdjacent.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/core/worldedit/SteamEditSelectAdjacent.java new file mode 100644 index 00000000..d30752aa --- /dev/null +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/core/worldedit/SteamEditSelectAdjacent.java @@ -0,0 +1,116 @@ +/* + * 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.core.worldedit; + +import com.sk89q.worldedit.math.BlockVector3; +import de.steamwar.core.Core; +import org.bukkit.Location; +import org.bukkit.block.BlockFace; +import org.bukkit.util.Vector; + +import java.util.LinkedHashSet; +import java.util.List; +import java.util.stream.Stream; + +public class SteamEditSelectAdjacent { + + private static final BlockFace[] FACES = { + BlockFace.NORTH, + BlockFace.SOUTH, + BlockFace.EAST, + BlockFace.WEST, + BlockFace.UP, + BlockFace.DOWN, + }; + + private Location min; + private Location max; + + private SteamEdit.AdjacentFilter filter; + + private LinkedHashSet frontier = new LinkedHashSet<>(); + + public SteamEditSelectAdjacent(Location origin) { + min = origin.clone(); + max = origin.clone(); + frontier.add(origin); + filter = SteamEdit.ADJACENT_FILTERS.apply(origin); + + long time = System.currentTimeMillis(); + for (int i = 0; i < 500_000 && !frontier.isEmpty(); i++) { + if (System.currentTimeMillis() - time > 1000) break; + expandNext(); + } + + Core.getInstance().getLogger().finer(System.currentTimeMillis() - time + "ms " + frontier.size() + " " + min + " to " + max); + } + + public BlockVector3 pos1() { + return BlockVector3.at(min.getBlockX(), min.getBlockY(), min.getBlockZ()); + } + + public BlockVector3 pos2() { + return BlockVector3.at(max.getBlockX(), max.getBlockY(), max.getBlockZ()); + } + + private boolean inside(Location loc, int offset) { + return loc.getBlockX() >= min.getBlockX() + offset && loc.getBlockX() <= max.getBlockX() - offset && + loc.getBlockY() >= min.getBlockY() + offset && loc.getBlockY() <= max.getBlockY() - offset && + loc.getBlockZ() >= min.getBlockZ() + offset && loc.getBlockZ() <= max.getBlockZ() - offset; + } + + public void expandNext() { + Location location = frontier.removeFirst(); + expand(location); + } + + private void expand(Location loc) { + for (BlockFace face : FACES) { + Vector direction = face.getDirection(); + Location location = loc.clone().add(direction); + if (!filter.contains(location.getBlockX(), location.getBlockY(), location.getBlockZ())) continue; + if (inside(location, 0)) continue; + List layer = Stream.concat(selectFrontier(direction.getBlockX() == 0 ? null : loc.getBlockX(), direction.getBlockY() == 0 ? null : loc.getBlockY(), direction.getBlockZ() == 0 ? null : loc.getBlockZ()) + .map(Location::clone) + .map(l -> l.add(direction)), Stream.of(location)) + .filter(l -> !l.getBlock().isEmpty()) + .filter(l -> !l.getBlock().isLiquid()) + .toList(); + if (layer.isEmpty()) continue; + + if (direction.getBlockX() < 0 || direction.getBlockY() < 0 || direction.getBlockZ() < 0) { + min.add(direction); + } else { + max.add(direction); + } + layer.stream().filter(l -> !inside(l, 1)) + .filter(l -> filter.contains(l.getBlockX(), l.getBlockY(), l.getBlockZ())) + .forEach(frontier::add); + } + } + + private Stream selectFrontier(Integer x, Integer y, Integer z) { + Stream stream = frontier.stream(); + if (x != null) stream = stream.filter(loc -> loc.getBlockX() == x); + if (y != null) stream = stream.filter(loc -> loc.getBlockY() == y); + if (z != null) stream = stream.filter(loc -> loc.getBlockZ() == z); + return stream; + } +} diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/core/worldedit/SteamEditWand.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/core/worldedit/SteamEditWand.java new file mode 100644 index 00000000..85b85d58 --- /dev/null +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/core/worldedit/SteamEditWand.java @@ -0,0 +1,406 @@ +/* + * 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.core.worldedit; + +import com.comphenix.tinyprotocol.TinyProtocol; +import com.sk89q.worldedit.LocalSession; +import com.sk89q.worldedit.bukkit.BukkitAdapter; +import com.sk89q.worldedit.bukkit.WorldEditPlugin; +import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.regions.RegionSelector; +import com.sk89q.worldedit.regions.selector.limit.PermissiveSelectorLimits; +import com.sk89q.worldedit.world.World; +import de.steamwar.core.Core; +import de.steamwar.core.SWPlayer; +import de.steamwar.entity.CWireframe; +import de.steamwar.entity.REntityServer; +import de.steamwar.inventory.SWItem; +import net.minecraft.core.BlockPos; +import net.minecraft.network.protocol.Packet; +import net.minecraft.network.protocol.game.*; +import org.bukkit.Bukkit; +import org.bukkit.FluidCollisionMode; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +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.PlayerInteractEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.scheduler.BukkitTask; +import org.bukkit.util.RayTraceResult; + +import java.util.List; + +public class SteamEditWand implements Listener { + + public static final Material MATERIAL = Material.GOLDEN_AXE; + public static final String NAME = "§eSteam§8Edit §7Wand"; + public static final String[] LORE = { + "§eL-Click§8: §7Set Pos1", + "§eR-Click§8: §7Set Pos2", + "§eShift §8+ §eR-Click§8: §7Set Pos2 or Expand Selection", + "§eM-Click§8: §7Select connected", + "§eSwap-Hands§8: §7Open CUI" + }; + public static final ItemStack ITEM = new SWItem(MATERIAL, NAME).setLore(LORE).getItemStack(); + + private boolean noWand(Player player) { + return player.getInventory().getItemInMainHand().getType() != SteamEditWand.MATERIAL; + } + + private final WorldEditPlugin we; + + SteamEditWand() { + we = WorldEditWrapper.getWorldEditPlugin(); + Bukkit.getPluginManager().registerEvents(this, Core.getInstance()); + + TinyProtocol.instance.addFilter(ServerboundSwingPacket.class, this::leftClick); + TinyProtocol.instance.addFilter(ServerboundInteractPacket.class, (player, packet) -> { + if (packet.isAttack()) { + return leftClick(player, packet); + } else { + return rightClick(player, packet); + } + }); + TinyProtocol.instance.addFilter(ServerboundUseItemPacket.class, this::rightClick); + TinyProtocol.instance.addFilter(ServerboundUseItemOnPacket.class, this::rightClick); + TinyProtocol.instance.addFilter(ServerboundPickItemFromBlockPacket.class, this::middleClick); + TinyProtocol.instance.addFilter(ServerboundPlayerActionPacket.class, this::swapHands); + TinyProtocol.instance.addFilter(ServerboundMovePlayerPacket.Pos.class, this::movePlayerPacket); + TinyProtocol.instance.addFilter(ServerboundMovePlayerPacket.Rot.class, this::movePlayerPacket); + TinyProtocol.instance.addFilter(ServerboundMovePlayerPacket.PosRot.class, this::movePlayerPacket); + + Bukkit.getScheduler().runTaskTimer(Core.getInstance(), () -> { + for (Player player : Bukkit.getOnlinePlayers()) { + if (noWand(player)) SWPlayer.of(player).removeComponent(SWEditCursor.class); + } + }, 1, 1); + } + + @EventHandler + public void onPlayerInteract(PlayerInteractEvent event) { + if (noWand(event.getPlayer())) return; + event.setCancelled(true); + } + + public static class SWEditCursor implements SWPlayer.Component { + private Player player; + private REntityServer entityServer = new REntityServer(); + private CWireframe wireframe; + + @Override + public void onMount(SWPlayer player) { + this.player = player.getPlayer(); + entityServer.addPlayer(player.getPlayer()); + wireframe = new CWireframe(entityServer); + } + + @Override + public void onUnmount(SWPlayer player) { + entityServer.close(); + } + + public void setLocation(Location location) { + float distance = (float) player.getLocation().distanceSquared(location); + wireframe.setPos1And2(location, location); + float width = distance / 1600; + width = ((int) (width * 16)) / 16F; + width = Math.max(width, 1 / 16F); + width = Math.min(width, 1 / 2F); + wireframe.setWidth(width); + wireframe.setBlock(WorldEditRendererCUIEditor.Type.CURSOR.getMaterial(player).createBlockData()); + } + } + + private Packet leftClick(Player player, Packet packet) { + if (noWand(player)) return packet; + if (player.getOpenInventory().getType() != InventoryType.CRAFTING) return packet; + double distance = WorldEditRendererCUIEditor.Type.CURSOR.getWidth(player).blocks; + RayTraceResult result = player.rayTraceBlocks(distance, FluidCollisionMode.NEVER); + if (result == null) return packet; + Block block = result.getHitBlock(); + if (block == null) return packet; + BlockVector3 pos1 = BlockVector3.at(block.getX(), block.getY(), block.getZ()); + setPos1(player, pos1); + return null; + } + + private void setPos1(Player player, BlockVector3 pos1) { + LocalSession session = we.getSession(player); + World world = session.getSelectionWorld(); + if (world == null) return; + selectPos1(session.getRegionSelector(world), player, session, pos1); + } + + private Packet rightClick(Player player, Packet packet) { + if (noWand(player)) return packet; + double distance = WorldEditRendererCUIEditor.Type.CURSOR.getWidth(player).blocks; + RayTraceResult result = player.rayTraceBlocks(distance, FluidCollisionMode.NEVER); + if (result == null) return packet; + Block block = result.getHitBlock(); + if (block == null) return packet; + BlockVector3 pos2 = BlockVector3.at(block.getX(), block.getY(), block.getZ()); + if (!player.isSneaking()) { + setPos2(player, pos2); + } else { + setPos2OrExpand(player, pos2); + } + return null; + } + + private void setPos2(Player player, BlockVector3 pos2) { + LocalSession session = we.getSession(player); + World world = session.getSelectionWorld(); + if (world == null) return; + selectPos2(session.getRegionSelector(world), player, session, pos2); + } + + private void setPos2OrExpand(Player player, BlockVector3 expand) { + LocalSession session = we.getSession(player); + World world = session.getSelectionWorld(); + if (world == null) return; + RegionSelector regionSelector = session.getRegionSelector(world); + + // Only primary set for now + if (!regionSelector.isDefined()) { + selectPos2(session.getRegionSelector(world), player, session, expand); + return; + } + + List vertices = regionSelector.getVertices(); + // Probably not a cuboid selection! + if (vertices.size() > 2) { + selectPos2(session.getRegionSelector(world), player, session, expand); + return; + } + + BlockVector3 pos1 = vertices.get(0); + BlockVector3 pos2 = vertices.get(1); + + BlockVector3 min = pos1.getMinimum(pos2); + BlockVector3 max = pos1.getMaximum(pos2); + if (expand.containedWithin(pos1, pos2)) { + return; + } + + Closer x = Closer.UNKNOWN; + Closer y = Closer.UNKNOWN; + Closer z = Closer.UNKNOWN; + + boolean insideX = min.x() < expand.x() && max.x() > expand.x(); + boolean insideY = min.y() < expand.y() && max.y() > expand.y(); + boolean insideZ = min.z() < expand.z() && max.z() > expand.z(); + + if (insideX) { + // No Change needed + } else if (Math.abs(pos1.x() - expand.x()) > Math.abs(pos2.x() - expand.x())) { + x = Closer.POS2; + } else if (Math.abs(pos1.x() - expand.x()) < Math.abs(pos2.x() - expand.x())) { + x = Closer.POS1; + } + + if (insideY) { + // No Change needed + } else if (Math.abs(pos1.y() - expand.y()) > Math.abs(pos2.y() - expand.y())) { + y = Closer.POS2; + } else if (Math.abs(pos1.y() - expand.y()) < Math.abs(pos2.y() - expand.y())) { + y = Closer.POS1; + } + + if (insideZ) { + // No Change needed + } else if (Math.abs(pos1.z() - expand.z()) > Math.abs(pos2.z() - expand.z())) { + z = Closer.POS2; + } else if (Math.abs(pos1.z() - expand.z()) < Math.abs(pos2.z() - expand.z())) { + z = Closer.POS1; + } + + Closer x1 = Closer.UNKNOWN; + Closer y1 = Closer.UNKNOWN; + Closer z1 = Closer.UNKNOWN; + + if (!insideX && pos1.x() != expand.x() && pos2.x() != expand.x() && x == Closer.UNKNOWN) { + x1 = y.and(z).or(Closer.POS1); + } + if (!insideY && pos1.y() != expand.y() && pos2.y() != expand.y() && y == Closer.UNKNOWN) { + y1 = x.and(z).or(Closer.POS1); + } + if (!insideZ && pos1.z() != expand.z() && pos2.z() != expand.z() && z == Closer.UNKNOWN) { + z1 = x.and(y).or(Closer.POS1); + } + + if (x1 != Closer.UNKNOWN) x = x1; + if (y1 != Closer.UNKNOWN) y = y1; + if (z1 != Closer.UNKNOWN) z = z1; + + boolean p1updated = false; + boolean p2updated = false; + + if (x == Closer.POS1) { + pos1 = pos1.withX(expand.x()); + p1updated = true; + } else if (x == Closer.POS2) { + pos2 = pos2.withX(expand.x()); + p2updated = true; + } + + if (y == Closer.POS1) { + pos1 = pos1.withY(expand.y()); + p1updated = true; + } else if (y == Closer.POS2) { + pos2 = pos2.withY(expand.y()); + p2updated = true; + } + + if (z == Closer.POS1) { + pos1 = pos1.withZ(expand.z()); + p1updated = true; + } else if (z == Closer.POS2) { + pos2 = pos2.withZ(expand.z()); + p2updated = true; + } + + if (p1updated) selectPos1(session.getRegionSelector(world), player, session, pos1); + if (p2updated) selectPos2(session.getRegionSelector(world), player, session, pos2); + } + + private enum Closer { + POS1, + POS2, + UNKNOWN, + ; + + public Closer and(Closer closer) { + if (this == closer) { + return this; + } else if (this == UNKNOWN) { + return closer; + } else if (closer == UNKNOWN) { + return this; + } else { + return UNKNOWN; + } + } + + public Closer or(Closer closer) { + if (this == UNKNOWN) return closer; + return this; + } + } + + private ServerboundPickItemFromBlockPacket middleClick(Player player, ServerboundPickItemFromBlockPacket packet) { + if (noWand(player)) return packet; + LocalSession session = we.getSession(player); + World world = session.getSelectionWorld(); + if (world == null) return packet; + RegionSelector regionSelector = session.getRegionSelector(world); + BlockPos pos = packet.pos(); + SteamEditSelectAdjacent selector = new SteamEditSelectAdjacent(new Location(player.getWorld(), pos.getX(), pos.getY(), pos.getZ())); + selectPos1(regionSelector, player, session, selector.pos1()); + selectPos2(regionSelector, player, session, selector.pos2()); + return null; + } + + private static class Pos1Message implements SWPlayer.Component { + private BukkitTask task; + + public Pos1Message(RegionSelector regionSelector, Player player, LocalSession session, BlockVector3 pos1) { + task = Bukkit.getScheduler().runTaskLater(Core.getInstance(), () -> { + regionSelector.explainPrimarySelection(BukkitAdapter.adapt(player), session, pos1); + SWPlayer.of(player).removeComponent(Pos1Message.class); + }, 1); + } + + @Override + public void onUnmount(SWPlayer player) { + task.cancel(); + } + } + + private void selectPos1(RegionSelector regionSelector, Player player, LocalSession session, BlockVector3 pos1) { + if (!pos1.equals(regionSelector.getPrimaryPosition())) { + SWPlayer.of(player).setComponent(new Pos1Message(regionSelector, player, session, pos1)); + } + regionSelector.selectPrimary(pos1, PermissiveSelectorLimits.getInstance()); + WorldEditRenderer.renderPlayer(player); + } + + private static class Pos2Message implements SWPlayer.Component { + private BukkitTask task; + + public Pos2Message(RegionSelector regionSelector, Player player, LocalSession session, BlockVector3 pos2) { + task = Bukkit.getScheduler().runTaskLater(Core.getInstance(), () -> { + regionSelector.explainSecondarySelection(BukkitAdapter.adapt(player), session, pos2); + SWPlayer.of(player).removeComponent(Pos1Message.class); + }, 1); + } + + @Override + public void onUnmount(SWPlayer player) { + task.cancel(); + } + } + + private void selectPos2(RegionSelector regionSelector, Player player, LocalSession session, BlockVector3 pos2) { + if (regionSelector.getVertices().size() == 2 && !pos2.equals(regionSelector.getVertices().get(1))) { + SWPlayer.of(player).setComponent(new Pos2Message(regionSelector, player, session, pos2)); + } + regionSelector.selectSecondary(pos2, PermissiveSelectorLimits.getInstance()); + WorldEditRenderer.renderPlayer(player); + } + + private ServerboundPlayerActionPacket swapHands(Player player, ServerboundPlayerActionPacket packet) { + if (noWand(player)) return packet; + if (packet.getAction() != ServerboundPlayerActionPacket.Action.SWAP_ITEM_WITH_OFFHAND) return packet; + Bukkit.getScheduler().runTask(Core.getInstance(), () -> { + WorldEditRendererCUIEditor.open(player); + }); + return null; + } + + public ServerboundMovePlayerPacket movePlayerPacket(Player player, ServerboundMovePlayerPacket packet) { + SWPlayer swPlayer = SWPlayer.of(player); + + if (noWand(player)) { + swPlayer.removeComponent(SWEditCursor.class); + return packet; + } + + double distance = WorldEditRendererCUIEditor.Type.CURSOR.getWidth(player).blocks; + RayTraceResult result = player.rayTraceBlocks(distance, FluidCollisionMode.NEVER); + Block block = result == null ? null : result.getHitBlock(); + if (result == null || block == null) { + swPlayer.removeComponent(SWEditCursor.class); + return packet; + } + + if (!swPlayer.hasComponent(SWEditCursor.class)) { + swPlayer.setComponent(new SWEditCursor()); + } + + swPlayer.getComponent(SWEditCursor.class).ifPresent(cursor -> { + cursor.setLocation(block.getLocation()); + }); + return packet; + } +} diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/core/WorldEditRenderer.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/core/worldedit/WorldEditRenderer.java similarity index 94% rename from SpigotCore/SpigotCore_Main/src/de/steamwar/core/WorldEditRenderer.java rename to SpigotCore/SpigotCore_Main/src/de/steamwar/core/worldedit/WorldEditRenderer.java index 8805327b..b66c67ad 100644 --- a/SpigotCore/SpigotCore_Main/src/de/steamwar/core/WorldEditRenderer.java +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/core/worldedit/WorldEditRenderer.java @@ -1,7 +1,7 @@ /* * This file is a part of the SteamWar software. * - * Copyright (C) 2025 SteamWar.de-Serverteam + * 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 @@ -17,7 +17,7 @@ * along with this program. If not, see . */ -package de.steamwar.core; +package de.steamwar.core.worldedit; import com.sk89q.worldedit.EmptyClipboardException; import com.sk89q.worldedit.IncompleteRegionException; @@ -28,6 +28,7 @@ import com.sk89q.worldedit.math.transform.Transform; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.RegionSelector; import com.sk89q.worldedit.world.World; +import de.steamwar.core.Core; import de.steamwar.linkage.Linked; import de.steamwar.linkage.PluginCheck; import org.bukkit.Bukkit; @@ -39,13 +40,15 @@ import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.event.player.*; import org.bukkit.util.Vector; +import java.util.Set; + @Linked @PluginCheck("FastAsyncWorldEdit") public class WorldEditRenderer implements Listener { private static WorldEditRenderer INSTANCE; - private static final Material WAND = Material.WOODEN_AXE; + private static final Set WANDS = Set.of(Material.WOODEN_AXE, SteamEditWand.MATERIAL); private final WorldEditPlugin we; @@ -102,7 +105,7 @@ public class WorldEditRenderer implements Listener { private void drawCuboid(Vector min, Vector max, boolean scheduled, boolean clipboard, Player owner) { //noinspection deprecation - if (owner.getItemInHand().getType() != WAND) { + if (!WANDS.contains(owner.getItemInHand().getType())) { WorldEditRendererWrapper.impl.hide(owner, true, true); WorldEditRendererWrapper.impl.hide(owner, false, true); } else { @@ -114,7 +117,8 @@ public class WorldEditRenderer implements Listener { @EventHandler public void onPlayerMove(PlayerMoveEvent event) { - if (event.getPlayer().getItemInHand().getType() == WAND) { + //noinspection deprecation + if (WANDS.contains(event.getPlayer().getItemInHand().getType())) { WorldEditRendererWrapper.impl.tick(event.getPlayer()); } renderClipboard(event.getPlayer(), we.getSession(event.getPlayer()), false); diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/core/WorldEditRendererCUIEditor.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/core/worldedit/WorldEditRendererCUIEditor.java similarity index 61% rename from SpigotCore/SpigotCore_Main/src/de/steamwar/core/WorldEditRendererCUIEditor.java rename to SpigotCore/SpigotCore_Main/src/de/steamwar/core/worldedit/WorldEditRendererCUIEditor.java index 8f7d3e2b..43f716fd 100644 --- a/SpigotCore/SpigotCore_Main/src/de/steamwar/core/WorldEditRendererCUIEditor.java +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/core/worldedit/WorldEditRendererCUIEditor.java @@ -1,7 +1,7 @@ /* * This file is a part of the SteamWar software. * - * Copyright (C) 2025 SteamWar.de-Serverteam + * 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 @@ -17,9 +17,11 @@ * along with this program. If not, see . */ -package de.steamwar.core; +package de.steamwar.core.worldedit; import de.steamwar.command.SWCommand; +import de.steamwar.core.CRIUSleepEvent; +import de.steamwar.core.Core; import de.steamwar.inventory.SWInventory; import de.steamwar.inventory.SWItem; import de.steamwar.sql.UserConfig; @@ -30,6 +32,7 @@ import org.bukkit.block.data.type.Light; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; +import org.bukkit.event.inventory.ClickType; import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.inventory.meta.BlockDataMeta; import org.bukkit.inventory.meta.ItemMeta; @@ -59,6 +62,7 @@ public class WorldEditRendererCUIEditor implements Listener { public enum Type { SELECTION("cui_selection_material", "cui_selection_width", Material.PURPLE_CONCRETE, Width.MEDIUM), CLIPBOARD("cui_clipboard_material", "cui_clipboard_width", Material.LIME_CONCRETE, Width.SLIM), + CURSOR("cui_cursor_material", "cui_cursor_range", Material.RED_CONCRETE, Width.SLIM), ; private final Map materialCache = new HashMap<>(); @@ -104,19 +108,27 @@ public class WorldEditRendererCUIEditor implements Listener { @AllArgsConstructor public enum Width { - HUGE(15, "WORLDEDIT_CUI_WIDTH_HUGE", 2 / 16f), - LARGE(8, "WORLDEDIT_CUI_WIDTH_LARGE", 1 / 16f), - MEDIUM(4, "WORLDEDIT_CUI_WIDTH_MEDIUM", 1 / 32f), - SLIM(0, "WORLDEDIT_CUI_WIDTH_SLIM", 1 / 64f); + HUGE(15, "WORLDEDIT_CUI_WIDTH_HUGE", 1 / 8f, 40), + LARGE(8, "WORLDEDIT_CUI_WIDTH_LARGE", 1 / 16f, 30), + MEDIUM(4, "WORLDEDIT_CUI_WIDTH_MEDIUM", 1 / 32f, 20), + SLIM(0, "WORLDEDIT_CUI_WIDTH_SLIM", 1 / 64f, 10); public final int lightLevel; public final String name; - public final float value; + public final float width; + public final int blocks; } + private static Command command = null; + public WorldEditRendererCUIEditor() { Bukkit.getPluginManager().registerEvents(this, Core.getInstance()); - new Command(); + command = new Command(); + } + + public static void open(Player player) { + if (command == null) return; + command.cuiEditor(player); } private static class Command extends SWCommand { @@ -128,8 +140,30 @@ public class WorldEditRendererCUIEditor implements Listener { @Register public void cuiEditor(Player player) { SWInventory inv = new SWInventory(player, 9 * 2, Core.MESSAGE.parse("WORLDEDIT_CUI_TITLE", player)); - setElement(inv, player, 3, "WORLDEDIT_CUI_SELECTION", Type.SELECTION); - setElement(inv, player, 5, "WORLDEDIT_CUI_CLIPBOARD", Type.CLIPBOARD); + if (SteamEdit.isInitialized()) { + setElement(inv, player, 1, "WORLDEDIT_CUI_SELECTION", Type.SELECTION); + setElement(inv, player, 2, "WORLDEDIT_CUI_CLIPBOARD", Type.CLIPBOARD); + setCursor(inv, player, 3, "WORLDEDIT_CUI_CURSOR"); + inv.setItem(5, new SWItem(Material.PAPER, "WORLDEDIT_CUI_TOOL_COPY").setLore("WORLDEDIT_CUI_TOOL_COPY_LORE").translate(player, Core.MESSAGE).getItemStack(), click -> { + player.performCommand("/copy"); + }); + inv.setItem(6, new SWItem(Material.STRUCTURE_VOID, "WORLDEDIT_CUI_TOOL_SOON").translate(player, Core.MESSAGE).getItemStack(), click -> {}); + inv.setItem(7, new SWItem(Material.GRASS_BLOCK, "WORLDEDIT_CUI_TOOL_PASTE").setLore("WORLDEDIT_CUI_TOOL_PASTE_LORE_1", "WORLDEDIT_CUI_TOOL_PASTE_LORE_2", "WORLDEDIT_CUI_TOOL_PASTE_LORE_3").translate(player, Core.MESSAGE).getItemStack(), click -> { + if (click == ClickType.DROP) { + player.performCommand("/paste -o"); + } else if (click == ClickType.SHIFT_LEFT || click == ClickType.SHIFT_RIGHT) { + player.performCommand("/paste -s"); + } else if (click == ClickType.LEFT || click == ClickType.RIGHT) { + player.performCommand("/paste"); + } + }); + inv.setItem(14, new SWItem(Material.STRUCTURE_VOID, "WORLDEDIT_CUI_TOOL_SOON").translate(player, Core.MESSAGE).getItemStack(), click -> {}); + inv.setItem(15, new SWItem(Material.STRUCTURE_VOID, "WORLDEDIT_CUI_TOOL_SOON").translate(player, Core.MESSAGE).getItemStack(), click -> {}); + inv.setItem(16, new SWItem(Material.STRUCTURE_VOID, "WORLDEDIT_CUI_TOOL_SOON").translate(player, Core.MESSAGE).getItemStack(), click -> {}); + } else { + setElement(inv, player, 3, "WORLDEDIT_CUI_SELECTION", Type.SELECTION); + setElement(inv, player, 5, "WORLDEDIT_CUI_CLIPBOARD", Type.CLIPBOARD); + } inv.open(); } @@ -163,6 +197,31 @@ public class WorldEditRendererCUIEditor implements Listener { inv.setItem(index + 9, lightItem); } + private void setCursor(SWInventory inv, Player player, int index, String uiName) { + Material material = Type.CURSOR.getMaterial(player); + Width width = Type.CURSOR.getWidth(player); + + inv.setItem(index, new SWItem(material, Core.MESSAGE.parse("WORLDEDIT_CUI_MATERIAL_NAME", player, Core.MESSAGE.parse(uiName, player)), Arrays.asList(Core.MESSAGE.parse("WORLDEDIT_CUI_MATERIAL_CLICK", player)), false, click -> { + cuiMaterial(player, uiName, Type.CURSOR, material); + })); + + List lore = new ArrayList<>(); + lore.add(Core.MESSAGE.parse("WORLDEDIT_CUI_WIDTH_CLICK", player)); + lore.add(""); + for (Width value : Width.values()) { + if (value == width) { + lore.add(Core.MESSAGE.parse("WORLDEDIT_CUI_WIDTH_LORE_SELECTED", player, Core.MESSAGE.parse(value.name + "_DIST", player))); + } else { + lore.add(Core.MESSAGE.parse("WORLDEDIT_CUI_WIDTH_LORE", player, Core.MESSAGE.parse(value.name + "_DIST", player))); + } + } + SWItem stickItem = new SWItem(Material.STICK, Core.MESSAGE.parse("WORLDEDIT_CUI_WIDTH_NAME_DIST", player, Core.MESSAGE.parse(uiName, player)), lore, false, click -> { + Type.CURSOR.setWidth(player, Width.values()[(width.ordinal() + 1) % Width.values().length]); + setCursor(inv, player, index, uiName); + }).setCustomModelData(1); + inv.setItem(index + 9, stickItem); + } + private final Material[] materials = {Material.WHITE_CONCRETE, Material.LIGHT_GRAY_CONCRETE, Material.GRAY_CONCRETE, Material.BLACK_CONCRETE, Material.BROWN_CONCRETE, Material.RED_CONCRETE, Material.ORANGE_CONCRETE, Material.YELLOW_CONCRETE, Material.LIME_CONCRETE, Material.GREEN_CONCRETE, Material.CYAN_CONCRETE, Material.LIGHT_BLUE_CONCRETE, Material.BLUE_CONCRETE, Material.PURPLE_CONCRETE, Material.MAGENTA_CONCRETE, Material.PINK_CONCRETE, null, Material.BARRIER}; private void cuiMaterial(Player player, String subMenu, Type type, Material currentSelection) { diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/core/WorldEditRendererFallback.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/core/worldedit/WorldEditRendererFallback.java similarity index 99% rename from SpigotCore/SpigotCore_Main/src/de/steamwar/core/WorldEditRendererFallback.java rename to SpigotCore/SpigotCore_Main/src/de/steamwar/core/worldedit/WorldEditRendererFallback.java index 736c2f8a..99d73885 100644 --- a/SpigotCore/SpigotCore_Main/src/de/steamwar/core/WorldEditRendererFallback.java +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/core/worldedit/WorldEditRendererFallback.java @@ -17,7 +17,7 @@ * along with this program. If not, see . */ -package de.steamwar.core; +package de.steamwar.core.worldedit; import org.bukkit.Location; import org.bukkit.Particle; diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/core/WorldEditRendererWrapper.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/core/worldedit/WorldEditRendererWrapper.java similarity index 96% rename from SpigotCore/SpigotCore_Main/src/de/steamwar/core/WorldEditRendererWrapper.java rename to SpigotCore/SpigotCore_Main/src/de/steamwar/core/worldedit/WorldEditRendererWrapper.java index 6d93d0b1..81ed2e2f 100644 --- a/SpigotCore/SpigotCore_Main/src/de/steamwar/core/WorldEditRendererWrapper.java +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/core/worldedit/WorldEditRendererWrapper.java @@ -1,7 +1,7 @@ /* * This file is a part of the SteamWar software. * - * Copyright (C) 2025 SteamWar.de-Serverteam + * 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 @@ -17,8 +17,9 @@ * along with this program. If not, see . */ -package de.steamwar.core; +package de.steamwar.core.worldedit; +import de.steamwar.core.PlayerVersion; import de.steamwar.entity.CWireframe; import de.steamwar.entity.REntityServer; import org.bukkit.Material; @@ -82,7 +83,7 @@ public class WorldEditRendererWrapper { }); WorldEditRendererCUIEditor.Type type = clipboard ? WorldEditRendererCUIEditor.Type.CLIPBOARD : WorldEditRendererCUIEditor.Type.SELECTION; - float width = type.getWidth(player).value; + float width = type.getWidth(player).width; Material material = type.getMaterial(player); if (material == Material.BARRIER) { hide(player, clipboard, true); diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/core/WorldEditWrapper.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/core/worldedit/WorldEditWrapper.java similarity index 98% rename from SpigotCore/SpigotCore_Main/src/de/steamwar/core/WorldEditWrapper.java rename to SpigotCore/SpigotCore_Main/src/de/steamwar/core/worldedit/WorldEditWrapper.java index d333ff3f..123870e4 100644 --- a/SpigotCore/SpigotCore_Main/src/de/steamwar/core/WorldEditWrapper.java +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/core/worldedit/WorldEditWrapper.java @@ -1,7 +1,7 @@ /* * This file is a part of the SteamWar software. * - * Copyright (C) 2025 SteamWar.de-Serverteam + * 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 @@ -17,7 +17,7 @@ * along with this program. If not, see . */ -package de.steamwar.core; +package de.steamwar.core.worldedit; import com.fastasyncworldedit.core.extent.clipboard.io.FastSchematicReaderV2; import com.fastasyncworldedit.core.extent.clipboard.io.FastSchematicReaderV3; @@ -34,6 +34,7 @@ import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.math.transform.Transform; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.session.ClipboardHolder; +import de.steamwar.core.Core; import de.steamwar.sql.NoClipboardException; import de.steamwar.sql.NodeData; import org.bukkit.Bukkit; diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/inventory/SWItem.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/inventory/SWItem.java index 68ec243f..0a0e0aa4 100644 --- a/SpigotCore/SpigotCore_Main/src/de/steamwar/inventory/SWItem.java +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/inventory/SWItem.java @@ -22,10 +22,12 @@ package de.steamwar.inventory; import com.destroystokyo.paper.profile.PlayerProfile; import com.google.gson.JsonArray; import com.google.gson.JsonObject; +import de.steamwar.message.Message; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.OfflinePlayer; import org.bukkit.enchantments.Enchantment; +import org.bukkit.entity.Player; import org.bukkit.inventory.ItemFlag; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; @@ -225,4 +227,14 @@ public class SWItem { itemStack.setAmount(count); return this; } + + public SWItem translate(Player player, Message message) { + setName(message.parse(itemMeta.getDisplayName(), player)); + if (itemMeta.hasLore()) { + setLore(itemMeta.getLore().stream() + .map(s -> message.parse(s, player)) + .toList()); + } + return this; + } } diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/sql/SchematicData.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/sql/SchematicData.java index 947d1adc..a603ee79 100644 --- a/SpigotCore/SpigotCore_Main/src/de/steamwar/sql/SchematicData.java +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/sql/SchematicData.java @@ -20,7 +20,7 @@ package de.steamwar.sql; import com.sk89q.worldedit.extent.clipboard.Clipboard; -import de.steamwar.core.WorldEditWrapper; +import de.steamwar.core.worldedit.WorldEditWrapper; import org.bukkit.entity.Player; import java.io.ByteArrayInputStream; diff --git a/Teamserver/src/de/steamwar/teamserver/Builder.java b/Teamserver/src/de/steamwar/teamserver/Builder.java index 7a625bd5..136810ae 100644 --- a/Teamserver/src/de/steamwar/teamserver/Builder.java +++ b/Teamserver/src/de/steamwar/teamserver/Builder.java @@ -19,7 +19,8 @@ package de.steamwar.teamserver; -import de.steamwar.core.WorldEditRendererCUIEditor; +import de.steamwar.core.worldedit.SteamEdit; +import de.steamwar.core.worldedit.WorldEditRendererCUIEditor; import de.steamwar.linkage.AbstractLinker; import de.steamwar.linkage.SpigotLinker; import de.steamwar.message.Message; @@ -51,7 +52,7 @@ public final class Builder extends JavaPlugin { } Bukkit.getWorlds().get(0).setGameRule(GameRule.REDUCED_DEBUG_INFO, false); - new WorldEditRendererCUIEditor(); + SteamEdit.init(); } @Override