forked from SteamWar/SteamWar
Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ea0bb44416 | ||
|
|
4cb0ff292e | ||
|
|
ee9eb995f5 |
-37
@@ -1,37 +0,0 @@
|
|||||||
package de.steamwar.bausystem.features.printerTool;
|
|
||||||
|
|
||||||
import de.steamwar.bausystem.utils.ItemUtils;
|
|
||||||
import de.steamwar.inventory.SWItem;
|
|
||||||
import de.steamwar.linkage.Linked;
|
|
||||||
import org.bukkit.Material;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.event.EventHandler;
|
|
||||||
import org.bukkit.event.Listener;
|
|
||||||
import org.bukkit.event.player.PlayerInteractEvent;
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
|
||||||
import org.bukkit.inventory.meta.ItemMeta;
|
|
||||||
|
|
||||||
@Linked
|
|
||||||
public class PrinterToolItem implements Listener {
|
|
||||||
public static ItemStack getItem(Player p) {
|
|
||||||
ItemStack itemStack = new SWItem(Material.WOODEN_PICKAXE, "Printer Tool").getItemStack();
|
|
||||||
ItemMeta itemMeta = itemStack.getItemMeta();
|
|
||||||
itemMeta.setCustomModelData(1);
|
|
||||||
itemStack.setItemMeta(itemMeta);
|
|
||||||
ItemUtils.setItem(itemStack, "printer_tool");
|
|
||||||
return itemStack;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isItem(ItemStack itemStack) {
|
|
||||||
return itemStack != null && ItemUtils.isItem(itemStack, "printer_tool");
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public void onPlayerInteract(PlayerInteractEvent event) {
|
|
||||||
ItemStack item = event.getItem();
|
|
||||||
|
|
||||||
if(PrinterToolItem.isItem(item)) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+1
-1
@@ -226,7 +226,7 @@ public class FreezeListener implements Listener, ScoreboardElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
@EventHandler(priority = EventPriority.MONITOR)
|
||||||
public void onBlockBreak(BlockBreakEvent e) {
|
public void onBlockBreak(BlockBreakEvent e) {
|
||||||
if (Core.getVersion() < 19) return;
|
if (Core.getVersion() < 19) return;
|
||||||
if (e.getPlayer().getInventory().getItemInMainHand().getType() == Material.DEBUG_STICK) return;
|
if (e.getPlayer().getInventory().getItemInMainHand().getType() == Material.DEBUG_STICK) return;
|
||||||
|
|||||||
+1
-2
@@ -25,7 +25,6 @@ import com.sk89q.worldedit.world.block.BaseBlock;
|
|||||||
import com.sk89q.worldedit.world.block.BlockState;
|
import com.sk89q.worldedit.world.block.BlockState;
|
||||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||||
import de.steamwar.bausystem.utils.WorldEditUtils;
|
import de.steamwar.bausystem.utils.WorldEditUtils;
|
||||||
import de.steamwar.core.Core;
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
@@ -57,7 +56,7 @@ public class Panzern {
|
|||||||
|
|
||||||
private BaseBlock blockType;
|
private BaseBlock blockType;
|
||||||
private BaseBlock slabType;
|
private BaseBlock slabType;
|
||||||
private static final BaseBlock jukeboxType = (Core.getVersion() > 19 ? BlockTypes.get("lodestone"): BlockTypes.get("jukebox")).getDefaultState().toBaseBlock();
|
private static final BaseBlock jukeboxType = BlockTypes.JUKEBOX.getDefaultState().toBaseBlock();
|
||||||
private static final BaseBlock cobwebType = BlockTypes.COBWEB.getDefaultState().toBaseBlock();
|
private static final BaseBlock cobwebType = BlockTypes.COBWEB.getDefaultState().toBaseBlock();
|
||||||
private static final BaseBlock airType = BlockTypes.AIR.getDefaultState().toBaseBlock();
|
private static final BaseBlock airType = BlockTypes.AIR.getDefaultState().toBaseBlock();
|
||||||
|
|
||||||
|
|||||||
+1
-6
@@ -179,12 +179,7 @@ public class SpectatorListener implements Listener {
|
|||||||
|
|
||||||
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
|
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
|
||||||
public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event) {
|
public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event) {
|
||||||
if (event.getMessage().startsWith("/schem save") ||
|
if (event.getMessage().startsWith("/schem save") || event.getMessage().startsWith("//schem save") || event.getMessage().startsWith("/schematic save") || event.getMessage().startsWith("//schematic save")) {
|
||||||
event.getMessage().startsWith("//schem save") ||
|
|
||||||
event.getMessage().startsWith("/schematic save") ||
|
|
||||||
event.getMessage().startsWith("//schematic save") ||
|
|
||||||
event.getMessage().startsWith("/download") ||
|
|
||||||
event.getMessage().startsWith("//download")) {
|
|
||||||
if (!Permission.SUPERVISOR.hasPermission(event.getPlayer())) {
|
if (!Permission.SUPERVISOR.hasPermission(event.getPlayer())) {
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
event.setMessage("/");
|
event.setMessage("/");
|
||||||
|
|||||||
@@ -1,204 +0,0 @@
|
|||||||
package de.steamwar.bausystem.utils.cursor;
|
|
||||||
|
|
||||||
import de.steamwar.bausystem.utils.RayTraceUtils;
|
|
||||||
import de.steamwar.entity.REntity;
|
|
||||||
import de.steamwar.entity.REntityServer;
|
|
||||||
import de.steamwar.entity.RFallingBlockEntity;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.Location;
|
|
||||||
import org.bukkit.Material;
|
|
||||||
import org.bukkit.World;
|
|
||||||
import org.bukkit.block.BlockFace;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.event.EventHandler;
|
|
||||||
import org.bukkit.event.block.Action;
|
|
||||||
import org.bukkit.util.Vector;
|
|
||||||
import yapion.hierarchy.types.YAPIONType;
|
|
||||||
|
|
||||||
import java.util.function.BiConsumer;
|
|
||||||
import java.util.function.BiFunction;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
public class RCursor {
|
|
||||||
private final World WORLD = Bukkit.getWorlds().get(0);
|
|
||||||
|
|
||||||
private final REntityServer targetServer;
|
|
||||||
private final REntityServer cursorServer;
|
|
||||||
|
|
||||||
private final Player owner;
|
|
||||||
private final Material highlightMaterial;
|
|
||||||
private final ClickHandler onClickHandler;
|
|
||||||
|
|
||||||
private RFallingBlockEntity cursorEntity;
|
|
||||||
|
|
||||||
private Location cursorLocation;
|
|
||||||
private boolean isHittingEntity = false;
|
|
||||||
|
|
||||||
@Setter
|
|
||||||
private Material cursorMaterial;
|
|
||||||
@Setter
|
|
||||||
private CursorMode cursorMode;
|
|
||||||
private boolean visible = true;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public RCursor(REntityServer targetServer, Player owner, Material highlightMaterial, Material cursorMaterial, CursorMode cursorMode, ClickHandler onClickHandler) {
|
|
||||||
this.targetServer = targetServer;
|
|
||||||
this.owner = owner;
|
|
||||||
this.highlightMaterial = highlightMaterial;
|
|
||||||
this.cursorMaterial = cursorMaterial;
|
|
||||||
this.cursorMode = cursorMode;
|
|
||||||
this.onClickHandler = onClickHandler;
|
|
||||||
|
|
||||||
cursorServer = new REntityServer();
|
|
||||||
cursorServer.addPlayer(owner);
|
|
||||||
|
|
||||||
RCursorManager.getInstance().registerCursor(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void render() {
|
|
||||||
if (!visible) return;
|
|
||||||
|
|
||||||
RayTraceUtils.RRayTraceResult rayTraceResult = RayTraceUtils.traceREntity(owner, owner.getLocation(), targetServer.getEntities());
|
|
||||||
if (rayTraceResult == null) {
|
|
||||||
if(cursorEntity != null) cursorEntity.die();
|
|
||||||
cursorEntity = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
REntity hitEntity = rayTraceResult.getHitEntity() == cursorEntity ? null : rayTraceResult.getHitEntity();
|
|
||||||
|
|
||||||
|
|
||||||
Material activeCursorMaterial = hitEntity == null ? cursorMaterial : highlightMaterial;
|
|
||||||
Location activeCursorLocation = hitEntity == null ? cursorMode.positionTransform.apply(owner, rayTraceResult).toLocation(WORLD)
|
|
||||||
: new Vector(hitEntity.getX(), hitEntity.getY(), hitEntity.getZ()).toLocation(WORLD);
|
|
||||||
|
|
||||||
cursorLocation = activeCursorLocation;
|
|
||||||
isHittingEntity = hitEntity != null;
|
|
||||||
|
|
||||||
if (cursorEntity == null) {
|
|
||||||
cursorEntity = new RFallingBlockEntity(cursorServer, activeCursorLocation, activeCursorMaterial);
|
|
||||||
cursorEntity.setNoGravity(true);
|
|
||||||
} if (cursorEntity.getMaterial() == activeCursorMaterial) {
|
|
||||||
cursorEntity.move(activeCursorLocation);
|
|
||||||
} else {
|
|
||||||
cursorEntity.die();
|
|
||||||
cursorEntity = new RFallingBlockEntity(cursorServer, activeCursorLocation, activeCursorMaterial);
|
|
||||||
cursorEntity.setNoGravity(true);
|
|
||||||
if(activeCursorMaterial == highlightMaterial) {
|
|
||||||
cursorEntity.setGlowing(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void hide() {
|
|
||||||
visible = false;
|
|
||||||
if (cursorEntity != null) {
|
|
||||||
cursorEntity.die();
|
|
||||||
cursorEntity = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void show() {
|
|
||||||
visible = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void handleClick(Action action) {
|
|
||||||
if(!visible || cursorLocation == null) return;
|
|
||||||
|
|
||||||
onClickHandler.handle(cursorLocation, isHittingEntity, action);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void close() {
|
|
||||||
cursorServer.close();
|
|
||||||
RCursorManager.getInstance().unregisterCursor(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@AllArgsConstructor
|
|
||||||
public enum CursorMode {
|
|
||||||
FREE((player, rayTraceResult) -> {
|
|
||||||
Vector pos = rayTraceResult.getHitPosition();
|
|
||||||
|
|
||||||
BlockFace face = rayTraceResult.getHitBlockFace();
|
|
||||||
if (face != null) {
|
|
||||||
switch (face) {
|
|
||||||
case DOWN:
|
|
||||||
pos.setY(pos.getY() - 0.98);
|
|
||||||
break;
|
|
||||||
case EAST:
|
|
||||||
pos.setX(pos.getX() + 0.49);
|
|
||||||
break;
|
|
||||||
case WEST:
|
|
||||||
pos.setX(pos.getX() - 0.49);
|
|
||||||
break;
|
|
||||||
case NORTH:
|
|
||||||
pos.setZ(pos.getZ() - 0.49);
|
|
||||||
break;
|
|
||||||
case SOUTH:
|
|
||||||
pos.setZ(pos.getZ() + 0.49);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (face.getModY() == 0 && player.isSneaking()) {
|
|
||||||
pos.setY(pos.getY() - 0.49);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!player.isSneaking()) {
|
|
||||||
pos.setX(pos.getBlockX() + 0.5);
|
|
||||||
if (face == null || face.getModY() == 0)
|
|
||||||
pos.setY(pos.getBlockY() + 0.0);
|
|
||||||
pos.setZ(pos.getBlockZ() + 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
return pos;
|
|
||||||
}),
|
|
||||||
BLOCK_ALIGNED((player, rayTraceResult) -> {
|
|
||||||
Vector pos = rayTraceResult.getHitPosition();
|
|
||||||
|
|
||||||
BlockFace face = rayTraceResult.getHitBlockFace();
|
|
||||||
if (face != null) {
|
|
||||||
switch (face) {
|
|
||||||
case DOWN:
|
|
||||||
pos.setY(pos.getY() - 0.98);
|
|
||||||
break;
|
|
||||||
case EAST:
|
|
||||||
pos.setX(pos.getX() + 0.49);
|
|
||||||
break;
|
|
||||||
case WEST:
|
|
||||||
pos.setX(pos.getX() - 0.49);
|
|
||||||
break;
|
|
||||||
case NORTH:
|
|
||||||
pos.setZ(pos.getZ() - 0.49);
|
|
||||||
break;
|
|
||||||
case SOUTH:
|
|
||||||
pos.setZ(pos.getZ() + 0.49);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pos.setX(pos.getBlockX() + 0.5);
|
|
||||||
if (pos.getY() - pos.getBlockY() != 0 && face == BlockFace.UP) {
|
|
||||||
pos.setY(pos.getBlockY() + 1.0);
|
|
||||||
} else {
|
|
||||||
pos.setY(pos.getBlockY());
|
|
||||||
}
|
|
||||||
pos.setZ(pos.getBlockZ() + 0.5);
|
|
||||||
return pos;
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
private final BiFunction<Player, RayTraceUtils.RRayTraceResult, Vector> positionTransform;
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface ClickHandler{
|
|
||||||
public void handle(Location cursorLocation, boolean didHitEntity, Action action);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,112 +0,0 @@
|
|||||||
package de.steamwar.bausystem.utils.cursor;
|
|
||||||
|
|
||||||
import com.comphenix.tinyprotocol.TinyProtocol;
|
|
||||||
import de.steamwar.Reflection;
|
|
||||||
import de.steamwar.bausystem.BauSystem;
|
|
||||||
import de.steamwar.linkage.Linked;
|
|
||||||
import lombok.Getter;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.event.EventHandler;
|
|
||||||
import org.bukkit.event.Listener;
|
|
||||||
import org.bukkit.event.player.PlayerInteractEvent;
|
|
||||||
import org.bukkit.event.player.PlayerQuitEvent;
|
|
||||||
|
|
||||||
import java.lang.ref.SoftReference;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.function.BiFunction;
|
|
||||||
|
|
||||||
@Linked
|
|
||||||
public class RCursorManager implements Listener {
|
|
||||||
@Getter
|
|
||||||
private static RCursorManager instance;
|
|
||||||
|
|
||||||
private final Set<Player> calculationActive = new HashSet<>();
|
|
||||||
private final Map<Player, RCursor> activeCursors = new HashMap<>();
|
|
||||||
|
|
||||||
public RCursorManager() {
|
|
||||||
if (instance == null) {
|
|
||||||
instance = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
BiFunction<Player, Object, Object> function = (player, object) -> {
|
|
||||||
updateCursor(player);
|
|
||||||
return object;
|
|
||||||
};
|
|
||||||
|
|
||||||
Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> {
|
|
||||||
Set<Player> playersWithActiveCursor = activeCursors.keySet();
|
|
||||||
|
|
||||||
playersWithActiveCursor.forEach(this::updateCursor);
|
|
||||||
}, 0);
|
|
||||||
|
|
||||||
Class<?> positionPacketClass = Reflection.getClass("net.minecraft.network.protocol.game.ServerboundMovePlayerPacket$Pos");
|
|
||||||
Class<?> lookPacketClass = Reflection.getClass("net.minecraft.network.protocol.game.ServerboundMovePlayerPacket$Rot");
|
|
||||||
Class<?> positionLookPacketClass = Reflection.getClass("net.minecraft.network.protocol.game.ServerboundMovePlayerPacket$PosRot");
|
|
||||||
|
|
||||||
TinyProtocol.instance.addFilter(positionPacketClass, function);
|
|
||||||
TinyProtocol.instance.addFilter(lookPacketClass, function);
|
|
||||||
TinyProtocol.instance.addFilter(positionLookPacketClass, function);
|
|
||||||
}
|
|
||||||
|
|
||||||
void registerCursor(RCursor cursor) {
|
|
||||||
closeCursorOf(cursor.getOwner());
|
|
||||||
|
|
||||||
activeCursors.put(cursor.getOwner(), cursor);
|
|
||||||
}
|
|
||||||
|
|
||||||
void unregisterCursor(RCursor cursor) {
|
|
||||||
activeCursors.remove(cursor.getOwner());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void closeCursorOf(Player player) {
|
|
||||||
RCursor currentPlayerCursor = activeCursors.get(player);
|
|
||||||
|
|
||||||
if(currentPlayerCursor != null) {
|
|
||||||
currentPlayerCursor.close();
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void updateCursor(Player player) {
|
|
||||||
if (!activeCursors.containsKey(player)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
synchronized (calculationActive) {
|
|
||||||
if (calculationActive.contains(player)) {
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
calculationActive.add(player);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RCursor cursor = activeCursors.get(player);
|
|
||||||
|
|
||||||
if (cursor != null) {
|
|
||||||
cursor.render();
|
|
||||||
}
|
|
||||||
|
|
||||||
synchronized (calculationActive) {
|
|
||||||
calculationActive.remove(player);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
private void handlePlayerInteract(PlayerInteractEvent event) {
|
|
||||||
Player player = event.getPlayer();
|
|
||||||
|
|
||||||
RCursor cursorOfPlayer = activeCursors.get(player);
|
|
||||||
|
|
||||||
cursorOfPlayer.handleClick(event.getAction());
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
private void handlePlayerQuit(PlayerQuitEvent event) {
|
|
||||||
closeCursorOf(event.getPlayer());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -34,19 +34,3 @@ dependencies {
|
|||||||
implementation(project(":BauSystem:BauSystem_20"))
|
implementation(project(":BauSystem:BauSystem_20"))
|
||||||
implementation(project(":BauSystem:BauSystem_21"))
|
implementation(project(":BauSystem:BauSystem_21"))
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.register<DevServer>("DevBau20") {
|
|
||||||
group = "run"
|
|
||||||
description = "Run a 1.20 Dev Bau"
|
|
||||||
dependsOn(":SpigotCore:shadowJar")
|
|
||||||
dependsOn(":BauSystem:shadowJar")
|
|
||||||
template = "Bau20"
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.register<DevServer>("DevBau21") {
|
|
||||||
group = "run"
|
|
||||||
description = "Run a 1.21 Dev Bau"
|
|
||||||
dependsOn(":SpigotCore:shadowJar")
|
|
||||||
dependsOn(":BauSystem:shadowJar")
|
|
||||||
template = "Bau21"
|
|
||||||
}
|
|
||||||
|
|||||||
+15
-24
@@ -34,7 +34,6 @@ import org.bukkit.command.CommandSender;
|
|||||||
|
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.logging.Level;
|
|
||||||
|
|
||||||
public class TechhiderbugCommand implements CommandExecutor {
|
public class TechhiderbugCommand implements CommandExecutor {
|
||||||
|
|
||||||
@@ -46,33 +45,25 @@ public class TechhiderbugCommand implements CommandExecutor {
|
|||||||
public boolean onCommand(CommandSender sender, Command cmd, String alias, String[] args) {
|
public boolean onCommand(CommandSender sender, Command cmd, String alias, String[] args) {
|
||||||
StringWriter writer = new StringWriter();
|
StringWriter writer = new StringWriter();
|
||||||
|
|
||||||
try {
|
writer.append("ArenaMode: ").append(Config.mode.name()).append('\n');
|
||||||
writer.append("ArenaMode: ").append(Config.mode.name()).append('\n');
|
writer.append("FightState: ").append(FightState.getFightState().name()).append('\n');
|
||||||
writer.append("FightState: ").append(FightState.getFightState().name()).append('\n');
|
writer.append("TechHider enabled: ").append(FightState.getStateDependentFeatures().get(FightSystem.getTechHider()).toString()).append('\n');
|
||||||
writer.append("TechHider enabled: ").append(FightState.getStateDependentFeatures().get(FightSystem.getTechHider()).toString()).append('\n');
|
|
||||||
|
|
||||||
writer.append("Arena region: ").append(Config.ArenaRegion.toString()).append('\n');
|
writer.append("Arena region: ").append(Config.ArenaRegion.toString()).append('\n');
|
||||||
writer.append("Team regions: ");
|
writer.append("Team regions: ");
|
||||||
Fight.teams().forEach(t -> writer.append(t.getName()).append(':').append(t.getExtendRegion().toString()).append(' '));
|
Fight.teams().forEach(t -> writer.append(t.getName()).append(':').append(t.getExtendRegion().toString()).append(' '));
|
||||||
writer.append('\n');
|
writer.append('\n');
|
||||||
|
|
||||||
writer.append("HullHider regions: ");
|
writer.append("HullHider regions: ");
|
||||||
FightSystem.getHullHider().getHullMap().forEach((t, h) -> writer.append(t.getName()).append(':').append(h.getRegion().toString()).append(' '));
|
FightSystem.getHullHider().getHullMap().forEach((t, h) -> writer.append(t.getName()).append(':').append(h.getRegion().toString()).append(' '));
|
||||||
writer.append('\n');
|
writer.append('\n');
|
||||||
|
|
||||||
writer.append("Hidden regions: ");
|
writer.append("Hidden regions: ");
|
||||||
FightSystem.getTechHider().getHiddenRegion().forEach((p, r) -> writer.append(p.getName()).append(':').append(r.toString()).append(' '));
|
FightSystem.getTechHider().getHiddenRegion().forEach((p, r) -> writer.append(p.getName()).append(':').append(r.toString()).append(' '));
|
||||||
writer.append('\n');
|
writer.append('\n');
|
||||||
|
|
||||||
writer.append("TinyProtocol: ");
|
writer.append('\n').append("Netty pipelines:\n");
|
||||||
writer.append(TinyProtocol.instance.toString()).append('\n');
|
Bukkit.getOnlinePlayers().forEach(p -> writer.append(p.getName()).append(": ").append(String.join(" ", TinyProtocol.instance.getPlayerInterceptors().get(p).getChannel().pipeline().names())).append('\n'));
|
||||||
|
|
||||||
writer.append('\n').append("Netty pipelines:\n");
|
|
||||||
Bukkit.getOnlinePlayers().forEach(p -> writer.append(p.getName()).append(": ").append(String.join(" ", TinyProtocol.instance.getPlayerInterceptors().get(p).getChannel().pipeline().names())).append('\n'));
|
|
||||||
} catch (Exception e) {
|
|
||||||
writer.append("Error while generating bug report: ").append(e.getMessage()).append('\n');
|
|
||||||
Bukkit.getLogger().log(Level.SEVERE, "Error while generating bug report", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
SWException.log("Techhider-Bug reported by " + sender.getName() + ": " + Arrays.toString(args), writer.toString());
|
SWException.log("Techhider-Bug reported by " + sender.getName() + ": " + Arrays.toString(args), writer.toString());
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -29,15 +29,11 @@ import de.steamwar.fightsystem.states.FightState;
|
|||||||
import de.steamwar.fightsystem.states.StateDependentListener;
|
import de.steamwar.fightsystem.states.StateDependentListener;
|
||||||
import de.steamwar.fightsystem.states.StateDependentTask;
|
import de.steamwar.fightsystem.states.StateDependentTask;
|
||||||
import de.steamwar.fightsystem.utils.ItemBuilder;
|
import de.steamwar.fightsystem.utils.ItemBuilder;
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.Cancellable;
|
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import org.bukkit.event.block.Action;
|
import org.bukkit.event.block.Action;
|
||||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
|
||||||
import org.bukkit.event.inventory.InventoryOpenEvent;
|
|
||||||
import org.bukkit.event.player.PlayerInteractEvent;
|
import org.bukkit.event.player.PlayerInteractEvent;
|
||||||
import org.bukkit.inventory.EquipmentSlot;
|
import org.bukkit.inventory.EquipmentSlot;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
@@ -111,19 +107,6 @@ public class HotbarKit extends Kit {
|
|||||||
|
|
||||||
Player player = event.getPlayer();
|
Player player = event.getPlayer();
|
||||||
int slot = player.getInventory().getHeldItemSlot();
|
int slot = player.getInventory().getHeldItemSlot();
|
||||||
click(player, slot, event);
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public void onInventoryClick(InventoryClickEvent event) {
|
|
||||||
int slot = event.getSlot();
|
|
||||||
if (slot < 0 || slot >= HOTBAR_SIZE) return;
|
|
||||||
|
|
||||||
Player player = (Player) event.getWhoClicked();
|
|
||||||
click(player, slot, event);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void click(Player player, int slot, Cancellable event) {
|
|
||||||
Kit activeKit = activeKits.get(player);
|
Kit activeKit = activeKits.get(player);
|
||||||
if(!(activeKit instanceof HotbarKit) || PersonalKitCreator.inKitCreator(player) || activeKit.getInventory()[slot] == null)
|
if(!(activeKit instanceof HotbarKit) || PersonalKitCreator.inKitCreator(player) || activeKit.getInventory()[slot] == null)
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -39,13 +39,3 @@ dependencies {
|
|||||||
implementation(project(":FightSystem:FightSystem_20"))
|
implementation(project(":FightSystem:FightSystem_20"))
|
||||||
implementation(project(":FightSystem:FightSystem_21"))
|
implementation(project(":FightSystem:FightSystem_21"))
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.register<FightServer>("WarGear20") {
|
|
||||||
group = "run"
|
|
||||||
description = "Run a WarGear 1.20 Fight Server"
|
|
||||||
dependsOn(":SpigotCore:shadowJar")
|
|
||||||
dependsOn(":FightSystem:shadowJar")
|
|
||||||
template = "WarGear20"
|
|
||||||
worldName = "arenas/Pentraki"
|
|
||||||
config = "WarGear20.yml"
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ public class JumpAndRun extends BasicListener {
|
|||||||
|
|
||||||
int count = CLICKED_COUNT.getOrDefault(player, -1);
|
int count = CLICKED_COUNT.getOrDefault(player, -1);
|
||||||
if (count >= 0) {
|
if (count >= 0) {
|
||||||
if (count > 20) {
|
if (count > 60) {
|
||||||
toReset.add(player);
|
toReset.add(player);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -104,18 +104,12 @@ public class JumpAndRun extends BasicListener {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Vector point = points.get(index);
|
Vector point = points.get(index);
|
||||||
if (location.getY() < point.getY()) index = -2;
|
if (location.getY() < point.getY()) {
|
||||||
if (location.toVector().distanceSquared(point) >= 17) index = -2;
|
return;
|
||||||
if (index > 0 && index < points.size() - 1) {
|
}
|
||||||
Vector nextPoint = points.get(index + 1);
|
if (location.toVector().distanceSquared(point) >= 12.25) {
|
||||||
if (location.getY() >= nextPoint.getY() && location.toVector().distanceSquared(nextPoint) < 17) {
|
|
||||||
index = index + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (index == -2) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
CURRENT_POS.put(event.getPlayer(), index);
|
CURRENT_POS.put(event.getPlayer(), index);
|
||||||
event.getPlayer().playSound(event.getPlayer().getLocation(), Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 0.4F, 1);
|
event.getPlayer().playSound(event.getPlayer().getLocation(), Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 0.4F, 1);
|
||||||
if (index < points.size() - 1) {
|
if (index < points.size() - 1) {
|
||||||
|
|||||||
@@ -71,17 +71,6 @@ public class TinyProtocol implements Listener {
|
|||||||
@Getter
|
@Getter
|
||||||
private final Map<Player, PacketInterceptor> playerInterceptors = new HashMap<>();
|
private final Map<Player, PacketInterceptor> playerInterceptors = new HashMap<>();
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "TinyProtocol{" +
|
|
||||||
"plugin=" + plugin +
|
|
||||||
", connections=" + connections +
|
|
||||||
", closed=" + closed +
|
|
||||||
", packetFilters=" + packetFilters +
|
|
||||||
", playerInterceptors=" + playerInterceptors +
|
|
||||||
'}';
|
|
||||||
}
|
|
||||||
|
|
||||||
private TinyProtocol(final Plugin plugin) {
|
private TinyProtocol(final Plugin plugin) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
this.connections = networkManagers.get(getServerConnection(plugin));
|
this.connections = networkManagers.get(getServerConnection(plugin));
|
||||||
@@ -95,7 +84,6 @@ public class TinyProtocol implements Listener {
|
|||||||
|
|
||||||
@EventHandler(priority = EventPriority.LOWEST)
|
@EventHandler(priority = EventPriority.LOWEST)
|
||||||
public void onPlayerLogin(PlayerLoginEvent e) {
|
public void onPlayerLogin(PlayerLoginEvent e) {
|
||||||
plugin.getLogger().info("Creating PacketInterceptor for: " + e.getPlayer().getName() + " (" + closed + ")");
|
|
||||||
if(closed)
|
if(closed)
|
||||||
return;
|
return;
|
||||||
new PacketInterceptor(e.getPlayer());
|
new PacketInterceptor(e.getPlayer());
|
||||||
@@ -130,8 +118,6 @@ public class TinyProtocol implements Listener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final void close() {
|
public final void close() {
|
||||||
plugin.getLogger().log(Level.INFO, "Closing PacketInterceptor", new Exception("Stacktrace"));
|
|
||||||
|
|
||||||
if(closed)
|
if(closed)
|
||||||
return;
|
return;
|
||||||
closed = true;
|
closed = true;
|
||||||
@@ -171,7 +157,6 @@ public class TinyProtocol implements Listener {
|
|||||||
synchronized (playerInterceptors) {
|
synchronized (playerInterceptors) {
|
||||||
playerInterceptors.put(player, this);
|
playerInterceptors.put(player, this);
|
||||||
}
|
}
|
||||||
plugin.getLogger().info("Adding Techhider for: " + player.getName());
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
channel.pipeline().addBefore("packet_handler", HANDLER_NAME, this);
|
channel.pipeline().addBefore("packet_handler", HANDLER_NAME, this);
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import de.steamwar.Reflection;
|
|||||||
import de.steamwar.command.*;
|
import de.steamwar.command.*;
|
||||||
import de.steamwar.core.authlib.AuthlibInjector;
|
import de.steamwar.core.authlib.AuthlibInjector;
|
||||||
import de.steamwar.core.events.*;
|
import de.steamwar.core.events.*;
|
||||||
|
import de.steamwar.inventory.ui.test.TestInvCommand;
|
||||||
import de.steamwar.message.Message;
|
import de.steamwar.message.Message;
|
||||||
import de.steamwar.network.NetworkReceiver;
|
import de.steamwar.network.NetworkReceiver;
|
||||||
import de.steamwar.network.handlers.ServerDataHandler;
|
import de.steamwar.network.handlers.ServerDataHandler;
|
||||||
@@ -67,6 +68,7 @@ public class Core extends JavaPlugin{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEnable() {
|
public void onEnable() {
|
||||||
|
new TestInvCommand();
|
||||||
errorHandler = new ErrorHandler();
|
errorHandler = new ErrorHandler();
|
||||||
crashDetector = new CrashDetector();
|
crashDetector = new CrashDetector();
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
* This file is a part of the SteamWar software.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2025 SteamWar.de-Serverteam
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.inventory.ui;
|
||||||
|
|
||||||
|
import de.steamwar.inventory.ui.util.UpdateStream;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
public abstract class StatefulUIInventory<T> extends UIInventory implements UpdateStream.Subscriber<T> {
|
||||||
|
|
||||||
|
private T state;
|
||||||
|
private final UpdateStream<T> stream;
|
||||||
|
private UpdateStream.Unsubscriber unsubscriber;
|
||||||
|
|
||||||
|
protected abstract UIComponent render(T state);
|
||||||
|
protected abstract void update(T state);
|
||||||
|
|
||||||
|
public StatefulUIInventory(UpdateStream<T> stateObservable, int playerSlots) {
|
||||||
|
super(playerSlots);
|
||||||
|
this.stream = stateObservable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StatefulUIInventory(UpdateStream<T> stateObservable) {
|
||||||
|
super();
|
||||||
|
this.stream = stateObservable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void dispose() {
|
||||||
|
unsubscriber.unsubscribe();
|
||||||
|
this.unsubscriber = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UIComponent render() {
|
||||||
|
return render(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onUpdate(T current) {
|
||||||
|
state = current;
|
||||||
|
update(current);
|
||||||
|
updateUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void onClose() {
|
||||||
|
if (viewers.isEmpty()) {
|
||||||
|
dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addViewer(Player... players) {
|
||||||
|
if (viewers.isEmpty()) {
|
||||||
|
unsubscriber = stream.subscribe(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
super.addViewer(players);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
* This file is a part of the SteamWar software.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2025 SteamWar.de-Serverteam
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.inventory.ui;
|
||||||
|
|
||||||
|
import de.steamwar.inventory.ui.item.Enchanted;
|
||||||
|
import de.steamwar.inventory.ui.item.OnClick;
|
||||||
|
import de.steamwar.inventory.ui.layout.FixedSizeContainer;
|
||||||
|
import de.steamwar.inventory.ui.util.*;
|
||||||
|
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
public interface UIComponent {
|
||||||
|
ComponentRender render(RenderContext context);
|
||||||
|
|
||||||
|
default UIComponent onClick(Consumer<InventoryClickEvent> event) {
|
||||||
|
return onClick(false, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
default UIComponent onClick(boolean allowDoubleClick, Consumer<InventoryClickEvent> event) {
|
||||||
|
return new OnClick(this, allowDoubleClick, inventoryClickEvent -> {
|
||||||
|
event.accept(inventoryClickEvent);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
default UIComponent onClickWithUpdate(Function<InventoryClickEvent, Boolean> event) {
|
||||||
|
return onClickWithUpdate(false, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
default UIComponent onClickWithUpdate(boolean allowDoubleClick, Function<InventoryClickEvent, Boolean> event) {
|
||||||
|
return new OnClick(this, allowDoubleClick, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
default UIComponent onClickNoUpdate(Consumer<InventoryClickEvent> event) {
|
||||||
|
return onClickNoUpdate(false, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
default UIComponent onClickNoUpdate(boolean allowDoubleClick, Consumer<InventoryClickEvent> event) {
|
||||||
|
return new OnClick(this, allowDoubleClick, inventoryClickEvent -> {
|
||||||
|
event.accept(inventoryClickEvent);
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
default UIComponent cancelOnClick() {
|
||||||
|
return new OnClick(this, true, inventoryClickEvent -> false);
|
||||||
|
}
|
||||||
|
|
||||||
|
default UIComponent enchanted() {
|
||||||
|
return new Enchanted(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
default UIComponent enchanted(boolean enchanted) {
|
||||||
|
if (enchanted)
|
||||||
|
return enchanted();
|
||||||
|
else
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
default UIComponent size(Size size) {
|
||||||
|
return new FixedSizeContainer(size, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* This file is a part of the SteamWar software.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2025 SteamWar.de-Serverteam
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.inventory.ui;
|
||||||
|
|
||||||
|
import de.steamwar.inventory.ui.util.ComponentRender;
|
||||||
|
import de.steamwar.inventory.ui.util.RenderContext;
|
||||||
|
|
||||||
|
public abstract class UIFragment implements UIComponent {
|
||||||
|
|
||||||
|
abstract public UIComponent build(RenderContext context);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ComponentRender render(RenderContext context) {
|
||||||
|
return build(context).render(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,242 @@
|
|||||||
|
/*
|
||||||
|
* This file is a part of the SteamWar software.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2025 SteamWar.de-Serverteam
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.inventory.ui;
|
||||||
|
|
||||||
|
import de.steamwar.core.Core;
|
||||||
|
import de.steamwar.inventory.ui.util.ComponentRender;
|
||||||
|
import de.steamwar.inventory.ui.util.RenderContext;
|
||||||
|
import de.steamwar.inventory.ui.util.RenderItem;
|
||||||
|
import de.steamwar.inventory.ui.util.Size;
|
||||||
|
import de.steamwar.message.Message;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||||
|
import org.bukkit.event.inventory.InventoryCloseEvent;
|
||||||
|
import org.bukkit.inventory.Inventory;
|
||||||
|
import org.bukkit.inventory.InventoryView;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public abstract class UIInventory {
|
||||||
|
protected final List<Player> viewers = new ArrayList<>();
|
||||||
|
private final Map<Player, OpenPlayerInventory> callbacks = new HashMap<>();
|
||||||
|
private final Map<Player, ItemStack[]> originalItems = new HashMap<>();
|
||||||
|
|
||||||
|
private UIInventory parent;
|
||||||
|
private Player currentRender;
|
||||||
|
private final int playerSlots;
|
||||||
|
|
||||||
|
private List<MemoHookMeta<?>> memoHooks = new ArrayList<>();
|
||||||
|
private int buildHookCount = 0;
|
||||||
|
|
||||||
|
protected UIInventory() {
|
||||||
|
this(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected UIInventory(int playerSlots) {
|
||||||
|
this.playerSlots = playerSlots;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract UIComponent render();
|
||||||
|
public abstract Inventory createInventory(Player player);
|
||||||
|
public abstract Message getMessages();
|
||||||
|
|
||||||
|
void onClose() { }
|
||||||
|
|
||||||
|
public <T> T useMemo(Supplier<T> supplier, List<Object> dependencies) {
|
||||||
|
int currentHook = buildHookCount++;
|
||||||
|
|
||||||
|
if (currentHook >= memoHooks.size()) {
|
||||||
|
T value = supplier.get();
|
||||||
|
memoHooks.add(new MemoHookMeta<>(dependencies, value));
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
MemoHookMeta<T> hook = (MemoHookMeta<T>) memoHooks.get(currentHook);
|
||||||
|
|
||||||
|
if (!hook.getDependencies().equals(dependencies)) {
|
||||||
|
hook.setDependencies(dependencies);
|
||||||
|
T value = supplier.get();
|
||||||
|
hook.setValue(value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hook.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> T useMemo(Supplier<T> supplier) {
|
||||||
|
return useMemo(supplier, Collections.emptyList());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addViewer(Player... players) {
|
||||||
|
viewers.addAll(Arrays.asList(players));
|
||||||
|
|
||||||
|
for (Player player : players) {
|
||||||
|
openInventory(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void openInventory(Player player) {
|
||||||
|
if (playerSlots > 0) {
|
||||||
|
originalItems.put(player, player.getInventory().getContents());
|
||||||
|
}
|
||||||
|
Inventory inventory = createInventory(player);
|
||||||
|
renderPlayer(player, inventory);
|
||||||
|
InventoryView view = player.openInventory(inventory);
|
||||||
|
Core.getInstance().getLogger().info("[UIINV] Opened " + view.getTitle() + " for " + player.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void renderPlayer(Player player, Inventory inventory) {
|
||||||
|
int width = Math.min(inventory.getSize(), 9);
|
||||||
|
if (width < 9 && playerSlots > 0) {
|
||||||
|
throw new IllegalArgumentException("Player Inventory is only supported in Chests");
|
||||||
|
}
|
||||||
|
|
||||||
|
int inventoryHeight = Math.max(inventory.getSize() / 9, 1);
|
||||||
|
int height = inventoryHeight + playerSlots;
|
||||||
|
int invSize = inventoryHeight * width;
|
||||||
|
|
||||||
|
currentRender = player;
|
||||||
|
buildHookCount = 0;
|
||||||
|
ComponentRender render = render().render(new RenderContext(new Size(width, height), new Size(width, height), this));
|
||||||
|
buildHookCount = -1;
|
||||||
|
currentRender = null;
|
||||||
|
|
||||||
|
if (render.getSize().getWidth() > width || render.getSize().getHeight() > height) {
|
||||||
|
throw new IllegalArgumentException("The UIComponent does not fit in the inventory");
|
||||||
|
}
|
||||||
|
|
||||||
|
Message message = getMessages();
|
||||||
|
|
||||||
|
ItemStack[] itemStacks = new ItemStack[inventory.getSize()];
|
||||||
|
ItemStack[] playerStacks = new ItemStack[playerSlots > 0 ? 4 * 9 : 0];
|
||||||
|
|
||||||
|
for (RenderItem item : render.getItems()) {
|
||||||
|
int slot = item.getX() + item.getY() * 9;
|
||||||
|
if (slot < invSize) {
|
||||||
|
itemStacks[item.getX() + item.getY() * 9] = item.getItemStack().message(message).build(player);
|
||||||
|
} else {
|
||||||
|
playerStacks[(item.getX() + item.getY() * 9) - invSize] = item.getItemStack().message(message).build(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inventory.setContents(itemStacks);
|
||||||
|
if (playerSlots > 0) {
|
||||||
|
ItemStack[] lastRow = new ItemStack[9];
|
||||||
|
System.arraycopy(playerStacks, playerStacks.length - 9, lastRow, 0, 9);
|
||||||
|
System.arraycopy(playerStacks, 0, playerStacks, 9, playerStacks.length - 9);
|
||||||
|
System.arraycopy(lastRow, 0, playerStacks, 0, 9);
|
||||||
|
|
||||||
|
// TODO: Update to Client-Side Only Update
|
||||||
|
player.getInventory().setContents(playerStacks);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<Integer, Function<InventoryClickEvent, Boolean>> clickEventMap = render.getItems().stream()
|
||||||
|
.filter(item -> item.getClickEvent() != null)
|
||||||
|
.collect(Collectors.toMap(renderItem -> renderItem.getX() + renderItem.getY() * 9, RenderItem::getClickEvent));
|
||||||
|
|
||||||
|
callbacks.computeIfAbsent(player, p -> new OpenPlayerInventory(p, clickEventMap).register()).setCallbacks(clickEventMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void updateTitle(String title, Object... params) {
|
||||||
|
if (currentRender != null) {
|
||||||
|
currentRender.getOpenInventory().setTitle(getMessages().parse(title, currentRender, params));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void updateUI() {
|
||||||
|
viewers.forEach(player -> renderPlayer(player, player.getOpenInventory().getTopInventory()));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void push(Player player, UIInventory inventory) {
|
||||||
|
inventory.parent = this;
|
||||||
|
inventory.addViewer(player);
|
||||||
|
viewers.remove(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void pop(Player player) {
|
||||||
|
if(parent == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
parent.addViewer(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Setter
|
||||||
|
private class OpenPlayerInventory implements Listener {
|
||||||
|
private final Player player;
|
||||||
|
private Map<Integer, Function<InventoryClickEvent, Boolean>> callbacks;
|
||||||
|
|
||||||
|
OpenPlayerInventory register() {
|
||||||
|
Core.getInstance().getServer().getPluginManager().registerEvents(this, Core.getInstance());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onInventoryClick(InventoryClickEvent e) {
|
||||||
|
if (!player.equals(e.getWhoClicked()))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (callbacks.containsKey(e.getRawSlot()) && callbacks.get(e.getRawSlot()) != null) {
|
||||||
|
e.setCancelled(true);
|
||||||
|
Core.getInstance().getLogger().info("[UIINV] " + e.getWhoClicked().getName() + " " + e.getClick().name() + " clicked " + e.getRawSlot() + " on " + (e.getCurrentItem() != null ? e.getCurrentItem().getItemMeta().getDisplayName() : "[EMPTY]") + " in " + e.getView().getTitle());
|
||||||
|
if (callbacks.get(e.getRawSlot()).apply(e)) {
|
||||||
|
updateUI();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onInventoryClose(InventoryCloseEvent e){
|
||||||
|
if(!player.equals(e.getPlayer()))
|
||||||
|
return;
|
||||||
|
|
||||||
|
InventoryClickEvent.getHandlerList().unregister(this);
|
||||||
|
InventoryCloseEvent.getHandlerList().unregister(this);
|
||||||
|
Core.getInstance().getLogger().info("[UIINV] " + player.getName() + " closed " + e.getView().getTitle());
|
||||||
|
if(callbacks.containsKey(-1))
|
||||||
|
callbacks.get(-1).apply(null);
|
||||||
|
|
||||||
|
viewers.remove(player);
|
||||||
|
UIInventory.this.callbacks.remove(player);
|
||||||
|
if (playerSlots > 0) {
|
||||||
|
player.getInventory().setContents(originalItems.remove(player));
|
||||||
|
}
|
||||||
|
|
||||||
|
onClose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@AllArgsConstructor
|
||||||
|
private class MemoHookMeta<T> {
|
||||||
|
private List<Object> dependencies;
|
||||||
|
private T value;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* This file is a part of the SteamWar software.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2025 SteamWar.de-Serverteam
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.inventory.ui.fragments;
|
||||||
|
|
||||||
|
import de.steamwar.inventory.ui.UIComponent;
|
||||||
|
import de.steamwar.inventory.ui.UIFragment;
|
||||||
|
import de.steamwar.inventory.ui.item.ItemBuilder;
|
||||||
|
import de.steamwar.inventory.ui.item.UIItem;
|
||||||
|
import de.steamwar.inventory.ui.layout.Row;
|
||||||
|
import de.steamwar.inventory.ui.util.RenderContext;
|
||||||
|
import de.steamwar.inventory.ui.util.Size;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class ActionBar extends UIFragment {
|
||||||
|
private static final UIComponent DEFAULT_FILLER = new UIItem(ItemBuilder.of(Material.GRAY_STAINED_GLASS_PANE).displayName("§e")).cancelOnClick();
|
||||||
|
|
||||||
|
private final Map<Integer, UIComponent> actionBar;
|
||||||
|
private UIComponent filler = DEFAULT_FILLER;
|
||||||
|
|
||||||
|
public ActionBar(Map<Integer, UIComponent> actionBar) {
|
||||||
|
this.actionBar = actionBar;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ActionBar filler(UIComponent filler) {
|
||||||
|
this.filler = filler;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UIComponent build(RenderContext context) {
|
||||||
|
UIComponent[] components = context.useMemo(() -> {
|
||||||
|
UIComponent[] cmp = new UIComponent[context.getContainerSize().getWidth()];
|
||||||
|
for (int i = 0; i < cmp.length; i++) {
|
||||||
|
cmp[i] = actionBar.getOrDefault(i, filler);
|
||||||
|
}
|
||||||
|
|
||||||
|
return cmp;
|
||||||
|
}, Arrays.asList(actionBar));
|
||||||
|
|
||||||
|
return new Row(Arrays.asList(components)).size(new Size(context.getContainerSize().getWidth(), 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
+97
@@ -0,0 +1,97 @@
|
|||||||
|
/*
|
||||||
|
* This file is a part of the SteamWar software.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2025 SteamWar.de-Serverteam
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.inventory.ui.fragments;
|
||||||
|
|
||||||
|
import de.steamwar.core.Core;
|
||||||
|
import de.steamwar.inventory.ui.UIComponent;
|
||||||
|
import de.steamwar.inventory.ui.UIFragment;
|
||||||
|
import de.steamwar.inventory.ui.item.ItemBuilder;
|
||||||
|
import de.steamwar.inventory.ui.item.UIItem;
|
||||||
|
import de.steamwar.inventory.ui.layout.Column;
|
||||||
|
import de.steamwar.inventory.ui.layout.FixedSizeContainer;
|
||||||
|
import de.steamwar.inventory.ui.layout.Row;
|
||||||
|
import de.steamwar.inventory.ui.util.RenderContext;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.bukkit.DyeColor;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
@Setter
|
||||||
|
public class HorizontalScrollLayout extends UIFragment {
|
||||||
|
private List<UIComponent> data;
|
||||||
|
private int scroll = 0;
|
||||||
|
private final Map<Integer, UIComponent> actionBar = new HashMap<>();
|
||||||
|
|
||||||
|
public HorizontalScrollLayout(List<UIComponent> data) {
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int maxScroll() {
|
||||||
|
return Math.max(0, Math.min(scroll, data.size() - 9 + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
public HorizontalScrollLayout actionBar(Map<Integer, UIComponent> actionBar) {
|
||||||
|
this.actionBar.clear();
|
||||||
|
this.actionBar.putAll(actionBar);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HorizontalScrollLayout data(List<UIComponent> data) {
|
||||||
|
this.data = data;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UIComponent build(RenderContext context) {
|
||||||
|
scroll = maxScroll();
|
||||||
|
boolean hasPrev = scroll > 0;
|
||||||
|
boolean hasNext = data.size() - scroll > 9;
|
||||||
|
|
||||||
|
Map<Integer, UIComponent> actionBar = context.useMemo(() -> {
|
||||||
|
Map<Integer, UIComponent> content = new HashMap<>(this.actionBar);
|
||||||
|
|
||||||
|
content.put(0, new UIItem(ItemBuilder.color(hasPrev ? DyeColor.LIME : DyeColor.GRAY).message(Core.MESSAGE).translateName(hasPrev ? "SWLISINV_PREVIOUS_PAGE_ACTIVE" : "SWLISINV_PREVIOUS_PAGE_INACTIVE")).onClickWithUpdate(inventoryClickEvent -> {
|
||||||
|
if (scroll > 0) {
|
||||||
|
scroll = Math.max(0, scroll - 9);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
content.put(8, new UIItem(ItemBuilder.color(hasNext ? DyeColor.LIME : DyeColor.GRAY).message(Core.MESSAGE).translateName(hasNext ? "SWLISINV_NEXT_PAGE_ACTIVE" : "SWLISINV_NEXT_PAGE_INACTIVE")).onClickWithUpdate(inventoryClickEvent -> {
|
||||||
|
if (hasNext) {
|
||||||
|
scroll = Math.min(scroll + 9, data.size() - 9);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
return content;
|
||||||
|
}, Arrays.asList(hasPrev, hasNext));
|
||||||
|
|
||||||
|
return new Column(
|
||||||
|
new FixedSizeContainer(context.getContainerSize().shrink(0, 1),
|
||||||
|
new Row(data.subList(scroll, Math.min(data.size(), scroll + 9)))
|
||||||
|
),
|
||||||
|
new ActionBar(actionBar)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,114 @@
|
|||||||
|
/*
|
||||||
|
* This file is a part of the SteamWar software.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2025 SteamWar.de-Serverteam
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.inventory.ui.fragments;
|
||||||
|
|
||||||
|
import de.steamwar.core.Core;
|
||||||
|
import de.steamwar.inventory.ui.UIComponent;
|
||||||
|
import de.steamwar.inventory.ui.UIFragment;
|
||||||
|
import de.steamwar.inventory.ui.item.ItemBuilder;
|
||||||
|
import de.steamwar.inventory.ui.item.UIItem;
|
||||||
|
import de.steamwar.inventory.ui.layout.Column;
|
||||||
|
import de.steamwar.inventory.ui.layout.FixedSizeContainer;
|
||||||
|
import de.steamwar.inventory.ui.layout.Grid;
|
||||||
|
import de.steamwar.inventory.ui.util.RenderContext;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.bukkit.DyeColor;
|
||||||
|
import org.bukkit.event.inventory.ClickType;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class PageLayout<T> extends UIFragment {
|
||||||
|
|
||||||
|
private final List<UIListEntry<T>> items;
|
||||||
|
private final UIListCallback<T> callback;
|
||||||
|
private int page = 0;
|
||||||
|
private Consumer<Integer> onPageChange = null;
|
||||||
|
private Map<Integer, UIItem> itemsOnBar = Collections.emptyMap();
|
||||||
|
|
||||||
|
public PageLayout(List<UIListEntry<T>> items, UIListCallback<T> callback) {
|
||||||
|
System.out.println(items.size());
|
||||||
|
this.items = items;
|
||||||
|
this.callback = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UIComponent build(RenderContext context) {
|
||||||
|
|
||||||
|
int itemsOnPage = context.getContainerSize().getWidth() * (context.getContainerSize().getHeight() - 1);
|
||||||
|
|
||||||
|
List<UIComponent> uiItems = context.useMemo(() -> {
|
||||||
|
int i = page * itemsOnPage;
|
||||||
|
|
||||||
|
int ipageLimit = items.size() - page * itemsOnPage;
|
||||||
|
if (ipageLimit > itemsOnPage) {
|
||||||
|
ipageLimit = itemsOnPage;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<UIComponent> pageItems = new ArrayList<>();
|
||||||
|
for (int ipage = 0; ipage < ipageLimit; ipage++) {
|
||||||
|
UIListEntry<T> e = items.get(i);
|
||||||
|
|
||||||
|
pageItems.add(new UIItem(e.item).onClickNoUpdate(inventoryClickEvent -> callback.clicked(inventoryClickEvent.getClick(), e.object)));
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pageItems;
|
||||||
|
}, Arrays.asList(page, items.size(), itemsOnPage));
|
||||||
|
|
||||||
|
Map<Integer, UIComponent> uiBar = context.useMemo(() -> {
|
||||||
|
Map<Integer, UIComponent> content = new HashMap<>(itemsOnBar);
|
||||||
|
|
||||||
|
if (page != 0) {
|
||||||
|
content.put(0, new UIItem(ItemBuilder.color(DyeColor.LIME).message(Core.MESSAGE).translateName("SWLISINV_PREVIOUS_PAGE_ACTIVE")).onClick(inventoryClickEvent -> page--));
|
||||||
|
} else {
|
||||||
|
content.put(0, new UIItem(ItemBuilder.color(DyeColor.GRAY).message(Core.MESSAGE).translateName("SWLISINV_PREVIOUS_PAGE_INACTIVE")).cancelOnClick());
|
||||||
|
}
|
||||||
|
if (page < items.size() / itemsOnPage - (items.size() % itemsOnPage == 0 ? 1 : 0)) {
|
||||||
|
content.put(8, new UIItem(ItemBuilder.color(DyeColor.LIME).message(Core.MESSAGE).translateName("SWLISINV_NEXT_PAGE_ACTIVE")).onClick(inventoryClickEvent -> page++));
|
||||||
|
} else {
|
||||||
|
content.put(8, new UIItem(ItemBuilder.color(DyeColor.GRAY).message(Core.MESSAGE).translateName("SWLISINV_NEXT_PAGE_INACTIVE")).cancelOnClick());
|
||||||
|
}
|
||||||
|
|
||||||
|
return content;
|
||||||
|
}, Arrays.asList(page, items.size(), itemsOnPage));
|
||||||
|
|
||||||
|
return new Column(
|
||||||
|
new FixedSizeContainer(context.getContainerSize().shrink(0, 1),
|
||||||
|
new Grid(uiItems)),
|
||||||
|
new ActionBar(uiBar)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public interface UIListCallback<T>{
|
||||||
|
void clicked(ClickType click, T element);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class UIListEntry<T>{
|
||||||
|
final ItemBuilder item;
|
||||||
|
final T object;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* This file is a part of the SteamWar software.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2025 SteamWar.de-Serverteam
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.inventory.ui.item;
|
||||||
|
|
||||||
|
import de.steamwar.inventory.ui.UIComponent;
|
||||||
|
import de.steamwar.inventory.ui.util.ComponentRender;
|
||||||
|
import de.steamwar.inventory.ui.util.RenderContext;
|
||||||
|
import de.steamwar.inventory.ui.util.RenderItem;
|
||||||
|
|
||||||
|
public class Enchanted implements UIComponent {
|
||||||
|
private final UIComponent children;
|
||||||
|
|
||||||
|
public Enchanted(UIComponent children) {
|
||||||
|
this.children = children;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ComponentRender render(RenderContext context) {
|
||||||
|
ComponentRender render = children.render(context);
|
||||||
|
|
||||||
|
for (RenderItem item : render.getItems()) {
|
||||||
|
item.getItemStack().enchanted();
|
||||||
|
}
|
||||||
|
|
||||||
|
return render;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,205 @@
|
|||||||
|
/*
|
||||||
|
* This file is a part of the SteamWar software.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2025 SteamWar.de-Serverteam
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.inventory.ui.item;
|
||||||
|
|
||||||
|
import de.steamwar.core.FlatteningWrapper;
|
||||||
|
import de.steamwar.core.TrickyTrialsWrapper;
|
||||||
|
import de.steamwar.inventory.SWItem;
|
||||||
|
import de.steamwar.message.Message;
|
||||||
|
import de.steamwar.message.SubMessage;
|
||||||
|
import org.bukkit.DyeColor;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.OfflinePlayer;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.inventory.ItemFlag;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.inventory.meta.ItemMeta;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class ItemBuilder {
|
||||||
|
private static final Map<DyeColor, Integer> DYE_COLOR_INTEGER_MAP = new EnumMap<>(DyeColor.class);
|
||||||
|
|
||||||
|
static {
|
||||||
|
DYE_COLOR_INTEGER_MAP.put(DyeColor.BLACK, 16);
|
||||||
|
DYE_COLOR_INTEGER_MAP.put(DyeColor.RED, 1);
|
||||||
|
DYE_COLOR_INTEGER_MAP.put(DyeColor.GREEN, 2);
|
||||||
|
DYE_COLOR_INTEGER_MAP.put(DyeColor.BROWN, 3);
|
||||||
|
DYE_COLOR_INTEGER_MAP.put(DyeColor.BLUE, 4);
|
||||||
|
DYE_COLOR_INTEGER_MAP.put(DyeColor.PURPLE, 5);
|
||||||
|
DYE_COLOR_INTEGER_MAP.put(DyeColor.CYAN, 6);
|
||||||
|
DYE_COLOR_INTEGER_MAP.put(DyeColor.LIGHT_GRAY, 7);
|
||||||
|
DYE_COLOR_INTEGER_MAP.put(DyeColor.GRAY, 8);
|
||||||
|
DYE_COLOR_INTEGER_MAP.put(DyeColor.PINK, 9);
|
||||||
|
DYE_COLOR_INTEGER_MAP.put(DyeColor.LIME, 10);
|
||||||
|
DYE_COLOR_INTEGER_MAP.put(DyeColor.YELLOW, 11);
|
||||||
|
DYE_COLOR_INTEGER_MAP.put(DyeColor.LIGHT_BLUE, 12);
|
||||||
|
DYE_COLOR_INTEGER_MAP.put(DyeColor.MAGENTA, 13);
|
||||||
|
DYE_COLOR_INTEGER_MAP.put(DyeColor.ORANGE, 14);
|
||||||
|
DYE_COLOR_INTEGER_MAP.put(DyeColor.WHITE, 15);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final ItemStack itemStack;
|
||||||
|
private final ItemMeta itemMeta;
|
||||||
|
private Message message = null;
|
||||||
|
private SubMessage translateName = null;
|
||||||
|
private List<SubMessage> translateLore = null;
|
||||||
|
|
||||||
|
private ItemBuilder(Material material) {
|
||||||
|
this(new ItemStack(material));
|
||||||
|
}
|
||||||
|
private ItemBuilder(ItemStack item) {
|
||||||
|
this.itemStack = item;
|
||||||
|
this.itemMeta = itemStack.getItemMeta();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ItemBuilder of(Material material) {
|
||||||
|
return new ItemBuilder(material);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ItemBuilder of(ItemStack itemStack) {
|
||||||
|
return new ItemBuilder(itemStack.getType()).amount(itemStack.getAmount());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ItemBuilder of(Material material, Byte meta) {
|
||||||
|
ItemStack itemStack;
|
||||||
|
try {
|
||||||
|
itemStack = new ItemStack(material, 1, (short)0, meta);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
itemStack = new ItemStack(material, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ItemBuilder(itemStack);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ItemBuilder color(DyeColor color) {
|
||||||
|
return ItemBuilder.of(SWItem.getDye(DYE_COLOR_INTEGER_MAP.get(color)), DYE_COLOR_INTEGER_MAP.get(color).byteValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ItemBuilder skull(OfflinePlayer player) {
|
||||||
|
return skull(player.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ItemBuilder skull(String name) {
|
||||||
|
return ItemBuilder.of(FlatteningWrapper.impl.setSkullOwner(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemBuilder message(Message message) {
|
||||||
|
if (this.message == null) {
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemStack build(Player player) {
|
||||||
|
if (message != null) {
|
||||||
|
if (translateName != null) {
|
||||||
|
itemMeta.setDisplayName(message.parse(translateName.getMessage(), player, translateName.getParams()));
|
||||||
|
}
|
||||||
|
if (translateLore != null) {
|
||||||
|
itemMeta.setLore(translateLore.stream().map(subMessage -> message.parse(subMessage.getMessage(), player, subMessage.getParams())).collect(Collectors.toList()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
itemStack.setItemMeta(itemMeta);
|
||||||
|
return itemStack;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemBuilder amount(int amount) {
|
||||||
|
itemStack.setAmount(amount);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemBuilder displayName(String name) {
|
||||||
|
itemMeta.setDisplayName(name);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemBuilder lore(String... lore) {
|
||||||
|
if (itemMeta.hasLore()) {
|
||||||
|
List<String> loreList = itemMeta.getLore();
|
||||||
|
loreList.addAll(Arrays.asList(lore));
|
||||||
|
itemMeta.setLore(loreList);
|
||||||
|
} else {
|
||||||
|
itemMeta.setLore(Arrays.asList(lore));
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemBuilder translateName(String name, Object... params) {
|
||||||
|
this.translateName = new SubMessage(name, params);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemBuilder addTranslateLore(SubMessage... lore) {
|
||||||
|
if (this.translateLore == null) {
|
||||||
|
this.translateLore = Arrays.asList(lore);
|
||||||
|
} else {
|
||||||
|
this.translateLore.addAll(Arrays.asList(lore));
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemBuilder enchanted() {
|
||||||
|
itemMeta.addEnchant(TrickyTrialsWrapper.impl.getUnbreakingEnchantment(), 10, true);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemBuilder enchanted(boolean enchanted) {
|
||||||
|
if(enchanted) {
|
||||||
|
return enchanted();
|
||||||
|
} else {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemBuilder hideFlags() {
|
||||||
|
for (ItemFlag flag : EnumSet.allOf(ItemFlag.class)) {
|
||||||
|
itemMeta.addItemFlags(flag);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemBuilder customModel(int modelData) {
|
||||||
|
itemMeta.setCustomModelData(modelData);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
|
||||||
|
ItemBuilder that = (ItemBuilder) o;
|
||||||
|
return Objects.equals(itemStack, that.itemStack) && Objects.equals(itemMeta, that.itemMeta) && Objects.equals(message, that.message) && Objects.equals(translateName, that.translateName) && Objects.equals(translateLore, that.translateLore);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "ItemBuilder{" +
|
||||||
|
"itemStack=" + itemStack +
|
||||||
|
", itemMeta=" + itemMeta +
|
||||||
|
", message=" + message +
|
||||||
|
", translateName=" + translateName +
|
||||||
|
", translateLore=" + translateLore +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
* This file is a part of the SteamWar software.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2025 SteamWar.de-Serverteam
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.inventory.ui.item;
|
||||||
|
|
||||||
|
import de.steamwar.inventory.ui.UIComponent;
|
||||||
|
import de.steamwar.inventory.ui.util.ComponentRender;
|
||||||
|
import de.steamwar.inventory.ui.util.RenderContext;
|
||||||
|
import de.steamwar.inventory.ui.util.RenderItem;
|
||||||
|
import org.bukkit.event.inventory.ClickType;
|
||||||
|
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||||
|
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
public class OnClick implements UIComponent {
|
||||||
|
private final UIComponent children;
|
||||||
|
private final boolean allowDoubleClick;
|
||||||
|
private final Function<InventoryClickEvent, Boolean> event;
|
||||||
|
|
||||||
|
public OnClick(UIComponent children, boolean allowDoubleClick, Function<InventoryClickEvent, Boolean> event) {
|
||||||
|
this.children = children;
|
||||||
|
this.allowDoubleClick = allowDoubleClick;
|
||||||
|
this.event = event;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ComponentRender render(RenderContext context) {
|
||||||
|
ComponentRender render = children.render(context);
|
||||||
|
|
||||||
|
for (RenderItem item : render.getItems()) {
|
||||||
|
item.setClickEvent(ev -> {
|
||||||
|
if (ev.getClick() != ClickType.DOUBLE_CLICK || allowDoubleClick) {
|
||||||
|
return event.apply(ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return render;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "OnClick{" +
|
||||||
|
"children=" + children +
|
||||||
|
", allowDoubleClick=" + allowDoubleClick +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
|
||||||
|
OnClick onClick = (OnClick) o;
|
||||||
|
return allowDoubleClick == onClick.allowDoubleClick && children.equals(onClick.children);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* This file is a part of the SteamWar software.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2025 SteamWar.de-Serverteam
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.inventory.ui.item;
|
||||||
|
|
||||||
|
import de.steamwar.inventory.ui.UIComponent;
|
||||||
|
import de.steamwar.inventory.ui.util.ComponentRender;
|
||||||
|
import de.steamwar.inventory.ui.util.RenderContext;
|
||||||
|
import de.steamwar.inventory.ui.util.Size;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class Space implements UIComponent {
|
||||||
|
@Override
|
||||||
|
public ComponentRender render(RenderContext context) {
|
||||||
|
return new ComponentRender(
|
||||||
|
new ArrayList<>(),
|
||||||
|
new Size(1, 1)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
return obj instanceof Space;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
* This file is a part of the SteamWar software.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2025 SteamWar.de-Serverteam
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.inventory.ui.item;
|
||||||
|
|
||||||
|
import de.steamwar.inventory.ui.UIComponent;
|
||||||
|
import de.steamwar.inventory.ui.util.*;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public class UIItem implements UIComponent {
|
||||||
|
|
||||||
|
private final ItemBuilder itemStack;
|
||||||
|
|
||||||
|
public UIItem(ItemStack itemStack) {
|
||||||
|
this(ItemBuilder.of(itemStack));
|
||||||
|
}
|
||||||
|
|
||||||
|
public UIItem(ItemBuilder itemStack) {
|
||||||
|
this.itemStack = itemStack;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ComponentRender render(RenderContext context) {
|
||||||
|
return new ComponentRender(
|
||||||
|
Arrays.asList(new RenderItem(0, 0, itemStack, null)),
|
||||||
|
new Size(1, 1)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "UIItem{" +
|
||||||
|
"itemStack=" + itemStack +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
|
||||||
|
UIItem uiItem = (UIItem) o;
|
||||||
|
return Objects.equals(itemStack, uiItem.itemStack);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* This file is a part of the SteamWar software.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2025 SteamWar.de-Serverteam
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.inventory.ui.layout;
|
||||||
|
|
||||||
|
public enum Alignment {
|
||||||
|
START,
|
||||||
|
CENTER,
|
||||||
|
END,
|
||||||
|
BETWEEN
|
||||||
|
}
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
/*
|
||||||
|
* This file is a part of the SteamWar software.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2025 SteamWar.de-Serverteam
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.inventory.ui.layout;
|
||||||
|
|
||||||
|
import de.steamwar.inventory.ui.UIComponent;
|
||||||
|
import de.steamwar.inventory.ui.util.*;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class Column implements UIComponent {
|
||||||
|
|
||||||
|
private final List<UIComponent> components;
|
||||||
|
|
||||||
|
private Alignment alignment;
|
||||||
|
private boolean shrinkWrap = false;
|
||||||
|
|
||||||
|
public Column(UIComponent... components) {
|
||||||
|
this(Arrays.asList(components));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Column(List<UIComponent> components) {
|
||||||
|
this.components = components;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Column centered() {
|
||||||
|
this.alignment = Alignment.CENTER;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Column setShrinkWrap(boolean shrinkWrap) {
|
||||||
|
this.shrinkWrap = shrinkWrap;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ComponentRender render(RenderContext context) {
|
||||||
|
List<RenderItem> renderItems = new ArrayList<>();
|
||||||
|
|
||||||
|
int height = 0;
|
||||||
|
int maxWidth = 0;
|
||||||
|
|
||||||
|
for (UIComponent component : components) {
|
||||||
|
ComponentRender render = component.render(context.withContainerSize(context.getContainerSize().withHeight(context.getContainerSize().getHeight() - height)));
|
||||||
|
for(RenderItem item : render.getItems()){
|
||||||
|
renderItems.add(item.shift(0, height));
|
||||||
|
}
|
||||||
|
maxWidth = Math.max(maxWidth, render.getSize().getWidth());
|
||||||
|
height += render.getSize().getHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (alignment == Alignment.CENTER) {
|
||||||
|
int shiftAmount = (context.getContainerSize().getHeight() - height) / 2;
|
||||||
|
for (RenderItem item : renderItems) {
|
||||||
|
item.shift(0, shiftAmount);
|
||||||
|
}
|
||||||
|
} else if (alignment == Alignment.BETWEEN) {
|
||||||
|
int shiftAmount = (context.getContainerSize().getHeight() - height) / (components.size() - 1);
|
||||||
|
for (int i = 0; i < components.size() - 1; i++) {
|
||||||
|
RenderItem item = renderItems.get(i);
|
||||||
|
item.shift(0, shiftAmount * i);
|
||||||
|
}
|
||||||
|
} else if (alignment == Alignment.END) {
|
||||||
|
int shiftAmount = (context.getContainerSize().getHeight() - height);
|
||||||
|
for (RenderItem item : renderItems) {
|
||||||
|
item.shift(0, shiftAmount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ComponentRender(
|
||||||
|
renderItems,
|
||||||
|
new Size(maxWidth, shrinkWrap ? height : context.getContainerSize().getHeight())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
+40
@@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* This file is a part of the SteamWar software.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2025 SteamWar.de-Serverteam
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.inventory.ui.layout;
|
||||||
|
|
||||||
|
import de.steamwar.inventory.ui.UIComponent;
|
||||||
|
import de.steamwar.inventory.ui.util.ComponentRender;
|
||||||
|
import de.steamwar.inventory.ui.util.RenderContext;
|
||||||
|
import de.steamwar.inventory.ui.util.Size;
|
||||||
|
|
||||||
|
public class FixedSizeContainer implements UIComponent {
|
||||||
|
private final UIComponent children;
|
||||||
|
private final Size size;
|
||||||
|
|
||||||
|
public FixedSizeContainer(Size size, UIComponent children) {
|
||||||
|
this.children = children;
|
||||||
|
this.size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ComponentRender render(RenderContext context) {
|
||||||
|
return children.render(context.withContainerSize(size)).withSize(size);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* This file is a part of the SteamWar software.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2025 SteamWar.de-Serverteam
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.inventory.ui.layout;
|
||||||
|
|
||||||
|
import de.steamwar.inventory.ui.UIComponent;
|
||||||
|
import de.steamwar.inventory.ui.util.ComponentRender;
|
||||||
|
import de.steamwar.inventory.ui.util.RenderContext;
|
||||||
|
import de.steamwar.inventory.ui.util.RenderItem;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class Grid implements UIComponent {
|
||||||
|
private final List<UIComponent> children;
|
||||||
|
|
||||||
|
public Grid(UIComponent... children) {
|
||||||
|
this(Arrays.asList(children));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Grid(List<UIComponent> children) {
|
||||||
|
this.children = children;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ComponentRender render(RenderContext context) {
|
||||||
|
List<RenderItem> renderItems = new ArrayList<>();
|
||||||
|
int x = 0;
|
||||||
|
int y = 0;
|
||||||
|
int currentRowMaxHeight = 0;
|
||||||
|
|
||||||
|
for (UIComponent child : children) {
|
||||||
|
ComponentRender render = child.render(context.withContainerSize(
|
||||||
|
context.getContainerSize()
|
||||||
|
.withWidth(context.getContainerSize().getWidth() - x)
|
||||||
|
.withHeight(context.getContainerSize().getHeight() - y)));
|
||||||
|
currentRowMaxHeight = Math.max(currentRowMaxHeight, render.getSize().getHeight());
|
||||||
|
for (RenderItem item : render.getItems()) {
|
||||||
|
renderItems.add(item.shift(x, y));
|
||||||
|
}
|
||||||
|
x += render.getSize().getWidth();
|
||||||
|
if(x >= context.getContainerSize().getWidth()){
|
||||||
|
x = 0;
|
||||||
|
y += currentRowMaxHeight;
|
||||||
|
currentRowMaxHeight = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ComponentRender(renderItems, context.getContainerSize());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
/*
|
||||||
|
* This file is a part of the SteamWar software.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2025 SteamWar.de-Serverteam
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.inventory.ui.layout;
|
||||||
|
|
||||||
|
import de.steamwar.inventory.ui.UIComponent;
|
||||||
|
import de.steamwar.inventory.ui.util.*;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class Row implements UIComponent {
|
||||||
|
|
||||||
|
private final List<UIComponent> components;
|
||||||
|
|
||||||
|
private Alignment alignment;
|
||||||
|
private boolean shrinkWrap = false;
|
||||||
|
|
||||||
|
public Row(UIComponent... components) {
|
||||||
|
this(Arrays.asList(components));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Row(List<UIComponent> components) {
|
||||||
|
this.components = components;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Row centered() {
|
||||||
|
this.alignment = Alignment.CENTER;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Row alignment(Alignment alignment) {
|
||||||
|
this.alignment = alignment;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Row setShrinkWrap(boolean shrinkWrap) {
|
||||||
|
this.shrinkWrap = shrinkWrap;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ComponentRender render(RenderContext context) {
|
||||||
|
List<RenderItem> renderItems = new ArrayList<>();
|
||||||
|
|
||||||
|
int width = 0;
|
||||||
|
int maxHeight = 0;
|
||||||
|
|
||||||
|
for (UIComponent component : components) {
|
||||||
|
ComponentRender render = component.render(context.withContainerSize(context.getContainerSize().withWidth(context.getContainerSize().getWidth() - width)));
|
||||||
|
for(RenderItem item : render.getItems()){
|
||||||
|
renderItems.add(item.shift(width, 0));
|
||||||
|
}
|
||||||
|
maxHeight = Math.max(maxHeight, render.getSize().getHeight());
|
||||||
|
width += render.getSize().getWidth();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (alignment == Alignment.CENTER) {
|
||||||
|
int shiftAmount = (context.getContainerSize().getWidth() - width) / 2;
|
||||||
|
for (RenderItem item : renderItems) {
|
||||||
|
item.shift(shiftAmount, 0);
|
||||||
|
}
|
||||||
|
} else if (alignment == Alignment.BETWEEN) {
|
||||||
|
int shiftAmount = (context.getContainerSize().getWidth() - width) / (components.size() - 1);
|
||||||
|
for (int i = 0; i < components.size() - 1; i++) {
|
||||||
|
RenderItem item = renderItems.get(i);
|
||||||
|
item.shift(shiftAmount * i, 0);
|
||||||
|
}
|
||||||
|
} else if (alignment == Alignment.END) {
|
||||||
|
int shiftAmount = (context.getContainerSize().getWidth() - width);
|
||||||
|
for (RenderItem item : renderItems) {
|
||||||
|
item.shift(shiftAmount, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ComponentRender(
|
||||||
|
renderItems,
|
||||||
|
new Size(shrinkWrap ? width : context.getContainerSize().getWidth(), maxHeight)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* This file is a part of the SteamWar software.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2025 SteamWar.de-Serverteam
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.inventory.ui.test;
|
||||||
|
|
||||||
|
import de.steamwar.command.SWCommand;
|
||||||
|
import de.steamwar.inventory.ui.util.UpdateStream;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class TestInvCommand extends SWCommand {
|
||||||
|
|
||||||
|
public static final UpdateStream<List<Integer>> STREAM = new UpdateStream<>(new ArrayList<>());
|
||||||
|
|
||||||
|
public TestInvCommand() {
|
||||||
|
super("testinv");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Register
|
||||||
|
public void run(Player player) {
|
||||||
|
new TestInventory(STREAM).addViewer(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
* This file is a part of the SteamWar software.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2025 SteamWar.de-Serverteam
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.inventory.ui.test;
|
||||||
|
|
||||||
|
import de.steamwar.core.Core;
|
||||||
|
import de.steamwar.inventory.ui.StatefulUIInventory;
|
||||||
|
import de.steamwar.inventory.ui.UIComponent;
|
||||||
|
import de.steamwar.inventory.ui.fragments.HorizontalScrollLayout;
|
||||||
|
import de.steamwar.inventory.ui.item.ItemBuilder;
|
||||||
|
import de.steamwar.inventory.ui.item.UIItem;
|
||||||
|
import de.steamwar.inventory.ui.util.UpdateStream;
|
||||||
|
import de.steamwar.message.Message;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.inventory.Inventory;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static de.steamwar.inventory.ui.test.TestInvCommand.STREAM;
|
||||||
|
|
||||||
|
public class TestInventory extends StatefulUIInventory<List<Integer>> {
|
||||||
|
|
||||||
|
private HorizontalScrollLayout scrollLayout;
|
||||||
|
private static int counter = 1;
|
||||||
|
|
||||||
|
public TestInventory(UpdateStream<List<Integer>> stateObservable) {
|
||||||
|
super(stateObservable);
|
||||||
|
scrollLayout = new HorizontalScrollLayout(new ArrayList<>());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected UIComponent render(List<Integer> state) {
|
||||||
|
return scrollLayout;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void update(List<Integer> state) {
|
||||||
|
System.out.println("Update");
|
||||||
|
List<UIComponent> items = state.stream().map(integer -> new UIItem(ItemBuilder.of(Material.ACACIA_PLANKS).displayName(String.valueOf(integer))).onClickNoUpdate(inventoryClickEvent -> STREAM.update(current -> {
|
||||||
|
current.remove(integer);
|
||||||
|
return current;
|
||||||
|
}))).collect(Collectors.toList());
|
||||||
|
items.add(new UIItem(ItemBuilder.of(Material.BUCKET).displayName("Add")).onClickNoUpdate(inventoryClickEvent -> STREAM.update(current -> {
|
||||||
|
current.add(counter++);
|
||||||
|
return current;
|
||||||
|
})));
|
||||||
|
scrollLayout = scrollLayout.data(items);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Inventory createInventory(Player player) {
|
||||||
|
return Bukkit.createInventory(null, 9 * 6, "Test Inventory");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Message getMessages() {
|
||||||
|
return Core.MESSAGE;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* This file is a part of the SteamWar software.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2025 SteamWar.de-Serverteam
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.inventory.ui.util;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.With;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@With
|
||||||
|
public class ComponentRender {
|
||||||
|
private final List<RenderItem> items;
|
||||||
|
private final Size size;
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* This file is a part of the SteamWar software.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2025 SteamWar.de-Serverteam
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.inventory.ui.util;
|
||||||
|
|
||||||
|
import de.steamwar.inventory.ui.UIInventory;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.With;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@With
|
||||||
|
public class RenderContext {
|
||||||
|
private final Size inventorySize;
|
||||||
|
private final Size containerSize;
|
||||||
|
private final UIInventory inventory;
|
||||||
|
|
||||||
|
public <T> T useMemo(Supplier<T> supplier, List<Object> dependencies) {
|
||||||
|
return inventory.useMemo(supplier, dependencies);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> T useMemo(Supplier<T> supplier) {
|
||||||
|
return inventory.useMemo(supplier);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* This file is a part of the SteamWar software.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2025 SteamWar.de-Serverteam
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.inventory.ui.util;
|
||||||
|
|
||||||
|
import de.steamwar.inventory.ui.item.ItemBuilder;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.With;
|
||||||
|
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||||
|
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@With
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class RenderItem {
|
||||||
|
private int x;
|
||||||
|
private int y;
|
||||||
|
private ItemBuilder itemStack;
|
||||||
|
private Function<InventoryClickEvent, Boolean> clickEvent;
|
||||||
|
|
||||||
|
public RenderItem shift(int deltaX, int deltaY) {
|
||||||
|
return withX(x + deltaX).withY(y + deltaY);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* This file is a part of the SteamWar software.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2025 SteamWar.de-Serverteam
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.inventory.ui.util;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.With;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@With
|
||||||
|
public class Size {
|
||||||
|
private final int width;
|
||||||
|
private final int height;
|
||||||
|
|
||||||
|
public Size shrink(int width, int height) {
|
||||||
|
return new Size(this.width - width, this.height - height);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* This file is a part of the SteamWar software.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2025 SteamWar.de-Serverteam
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.inventory.ui.util;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class UpdateStream<T> {
|
||||||
|
|
||||||
|
private T current;
|
||||||
|
|
||||||
|
private final List<Subscriber<T>> subscribers = new ArrayList<>();
|
||||||
|
|
||||||
|
public UpdateStream(T current) {
|
||||||
|
this.current = current;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Unsubscriber subscribe(Subscriber<T> subscriber) {
|
||||||
|
subscribers.add(subscriber);
|
||||||
|
subscriber.onUpdate(current);
|
||||||
|
return () -> subscribers.remove(subscriber);
|
||||||
|
}
|
||||||
|
|
||||||
|
public T get() {
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void emit(T newCurrent) {
|
||||||
|
current = newCurrent;
|
||||||
|
subscribers.forEach(subscriber -> subscriber.onUpdate(newCurrent));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void update(Updater<T> updater) {
|
||||||
|
current = updater.update(current);
|
||||||
|
subscribers.forEach(subscriber -> subscriber.onUpdate(current));
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface Subscriber<T> {
|
||||||
|
void onUpdate(T current);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface Unsubscriber {
|
||||||
|
void unsubscribe();
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface Updater<T> {
|
||||||
|
T update(T current);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -66,12 +66,4 @@ dependencies {
|
|||||||
implementation(libs.apolloprotos)
|
implementation(libs.apolloprotos)
|
||||||
|
|
||||||
implementation(libs.nbt)
|
implementation(libs.nbt)
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.register<DevServer>("DevVelocity") {
|
|
||||||
group = "run"
|
|
||||||
description = "Run a Dev Velocity"
|
|
||||||
dependsOn(":VelocityCore:shadowJar")
|
|
||||||
dependsOn(":VelocityCore:Persistent:jar")
|
|
||||||
template = "DevVelocity"
|
|
||||||
}
|
|
||||||
@@ -44,7 +44,6 @@ public enum ServerVersion {
|
|||||||
PAPER_18("paper-1.18.2.jar", 15, ProtocolVersion.MINECRAFT_1_18_2),
|
PAPER_18("paper-1.18.2.jar", 15, ProtocolVersion.MINECRAFT_1_18_2),
|
||||||
PAPER_19("paper-1.19.3.jar", 19, ProtocolVersion.MINECRAFT_1_19_3),
|
PAPER_19("paper-1.19.3.jar", 19, ProtocolVersion.MINECRAFT_1_19_3),
|
||||||
PAPER_20("paper-1.20.1.jar", 20, ProtocolVersion.MINECRAFT_1_20),
|
PAPER_20("paper-1.20.1.jar", 20, ProtocolVersion.MINECRAFT_1_20),
|
||||||
DEVEL_21("paper-1.21.5.jar", 21, ProtocolVersion.MINECRAFT_1_21_5),
|
|
||||||
PAPER_21("paper-1.21.3.jar", 21, ProtocolVersion.MINECRAFT_1_21_2);
|
PAPER_21("paper-1.21.3.jar", 21, ProtocolVersion.MINECRAFT_1_21_2);
|
||||||
|
|
||||||
private static final Map<String, ServerVersion> chatMap = new HashMap<>();
|
private static final Map<String, ServerVersion> chatMap = new HashMap<>();
|
||||||
@@ -95,10 +94,6 @@ public enum ServerVersion {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static ServerVersion get(int version) {
|
public static ServerVersion get(int version) {
|
||||||
if (version == 21) {
|
|
||||||
return DEVEL_21;
|
|
||||||
}
|
|
||||||
|
|
||||||
return versionMap.get(version);
|
return versionMap.get(version);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -149,23 +149,6 @@ fun Route.configureSchematic() {
|
|||||||
return@let SchematicFormat.SPONGE_V2
|
return@let SchematicFormat.SPONGE_V2
|
||||||
}
|
}
|
||||||
|
|
||||||
if (version == SchematicFormat.SPONGE_V3) {
|
|
||||||
try {
|
|
||||||
val fawe = schem.getCompound("Metadata")
|
|
||||||
.getCompound("WorldEdit")
|
|
||||||
.getString("Version")
|
|
||||||
.value
|
|
||||||
|
|
||||||
if (fawe.equals("2.12.3-SNAPSHOT")) {
|
|
||||||
SWException.log("Schematic with Bugged Version Uploaded", """
|
|
||||||
Schematic=$schemName
|
|
||||||
User=${user.userName}
|
|
||||||
Id=${user.id}
|
|
||||||
""".trimIndent())
|
|
||||||
}
|
|
||||||
} catch (_: Exception) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
val data = NodeData(node.id, version)
|
val data = NodeData(node.id, version)
|
||||||
data.saveFromStream(content.inputStream(), version)
|
data.saveFromStream(content.inputStream(), version)
|
||||||
|
|
||||||
|
|||||||
@@ -1,214 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is a part of the SteamWar software.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2020 SteamWar.de-Serverteam
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
plugins {
|
|
||||||
}
|
|
||||||
|
|
||||||
class DevServer extends DefaultTask {
|
|
||||||
|
|
||||||
@Input
|
|
||||||
@Optional
|
|
||||||
String worldName = null
|
|
||||||
|
|
||||||
@Input
|
|
||||||
String template = null
|
|
||||||
|
|
||||||
@Input
|
|
||||||
@Optional
|
|
||||||
String plugins = null
|
|
||||||
|
|
||||||
@Input
|
|
||||||
@Optional
|
|
||||||
Integer port = null
|
|
||||||
|
|
||||||
@Input
|
|
||||||
@Optional
|
|
||||||
String jar = null
|
|
||||||
|
|
||||||
@Input
|
|
||||||
@Optional
|
|
||||||
Map<String, String> dParams = new HashMap<>()
|
|
||||||
|
|
||||||
DevServer() {
|
|
||||||
super()
|
|
||||||
doFirst {
|
|
||||||
List<Project> projects = []
|
|
||||||
projects.add(project)
|
|
||||||
while (projects.first.parent != null) {
|
|
||||||
projects.add(0, projects.first.parent)
|
|
||||||
}
|
|
||||||
|
|
||||||
def properties = new Properties()
|
|
||||||
projects.forEach {
|
|
||||||
def file = new File(it.projectDir, "steamwar.properties")
|
|
||||||
if (file.exists()) {
|
|
||||||
properties.load(new FileInputStream(file))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (worldName == null) worldName = properties.get("worldName")
|
|
||||||
host = properties.get("host")
|
|
||||||
|
|
||||||
if (host == null) {
|
|
||||||
throw new GradleException("Please supply the 'host' in a 'steamwar.properties' files either in this project dir or any parent project!")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
doLast {
|
|
||||||
checkHasTemplate()
|
|
||||||
uploadDependencies()
|
|
||||||
startDevServer()
|
|
||||||
}
|
|
||||||
finalizedBy(new Finalizer())
|
|
||||||
}
|
|
||||||
|
|
||||||
@Internal
|
|
||||||
BufferedWriter processInput
|
|
||||||
|
|
||||||
@Internal
|
|
||||||
String host
|
|
||||||
|
|
||||||
@Internal
|
|
||||||
Boolean running = true
|
|
||||||
|
|
||||||
class Finalizer extends DefaultTask {
|
|
||||||
|
|
||||||
Finalizer() {
|
|
||||||
super()
|
|
||||||
doLast {
|
|
||||||
running = false
|
|
||||||
if (processInput != null) {
|
|
||||||
processInput.write(template.endsWith("Velocity") ? "end\n" : "stop\n")
|
|
||||||
processInput.flush()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void checkHasTemplate() {
|
|
||||||
def process = new ProcessBuilder("ssh", host, "-T", "ls $template").start()
|
|
||||||
process.waitFor()
|
|
||||||
if (new BufferedReader(new InputStreamReader(process.inputStream)).lines().count() < 4) {
|
|
||||||
throw new GradleException("Used template is not in your user.home directory of the given host $host")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void uploadDependencies() {
|
|
||||||
def base = plugins == null ? "$template/plugins" : plugins
|
|
||||||
println("Uploading to ~/$base")
|
|
||||||
this.dependsOn.forEach {
|
|
||||||
Project resolved
|
|
||||||
AbstractArchiveTask archiveTask
|
|
||||||
if (it instanceof String) {
|
|
||||||
resolved = project.findProject(it.substring(0, it.lastIndexOf(':')))
|
|
||||||
archiveTask = (AbstractArchiveTask) resolved.tasks.findByName(it.substring(it.lastIndexOf(':') + 1))
|
|
||||||
} else {
|
|
||||||
throw new GradleException("Illegal argument for uploading dependencies")
|
|
||||||
}
|
|
||||||
|
|
||||||
def archive = archiveTask.archiveFile.get().asFile
|
|
||||||
println("Uploading $archive")
|
|
||||||
new ProcessBuilder("ssh", host, "-T", "rm $base/${archive.name.replace("-all", "")}").start().waitFor()
|
|
||||||
new ProcessBuilder("scp", archive.absolutePath, "$host:~/$base/${archive.name.replace("-all", "")}").start().waitFor()
|
|
||||||
println("Uploaded $archive")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void startDevServer() {
|
|
||||||
def devPy = new StringBuilder().append("dev.py")
|
|
||||||
if (port != null) devPy.append(" --port $port")
|
|
||||||
if (worldName != null) devPy.append(" -w $template/$worldName")
|
|
||||||
if (plugins != null) devPy.append(" -p $plugins")
|
|
||||||
if (jar != null) devPy.append(" --jar $jar")
|
|
||||||
for (Map.Entry<String, String> dParam : dParams.entrySet()) {
|
|
||||||
devPy.append(" -D${dParam.key}=${dParam.value}")
|
|
||||||
}
|
|
||||||
devPy.append(" $template")
|
|
||||||
println("Starting $template with command ${devPy.toString()}")
|
|
||||||
|
|
||||||
def process = new ProcessBuilder("ssh", host, "-T", devPy.toString()).start()
|
|
||||||
def processOutput = new BufferedReader(new InputStreamReader(process.inputStream))
|
|
||||||
new Thread({
|
|
||||||
while (running) {
|
|
||||||
if (processOutput.ready()) {
|
|
||||||
println(processOutput.readLine())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}).start()
|
|
||||||
|
|
||||||
processInput = new BufferedWriter(new OutputStreamWriter(process.outputStream))
|
|
||||||
def input = new BufferedReader(new InputStreamReader(System.in))
|
|
||||||
new Thread({
|
|
||||||
while (running) {
|
|
||||||
def text = input.readLine()
|
|
||||||
if (text == null) break
|
|
||||||
processInput.write(text)
|
|
||||||
processInput.newLine()
|
|
||||||
processInput.flush()
|
|
||||||
}
|
|
||||||
}).start()
|
|
||||||
|
|
||||||
process.waitFor()
|
|
||||||
processInput = null
|
|
||||||
running = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class FightServer extends DevServer {
|
|
||||||
|
|
||||||
@Input
|
|
||||||
@Optional
|
|
||||||
Integer checkSchemID = 0
|
|
||||||
|
|
||||||
@Input
|
|
||||||
@Optional
|
|
||||||
Integer prepareSchemID = 0
|
|
||||||
|
|
||||||
@Input
|
|
||||||
@Optional
|
|
||||||
Integer replay = 0
|
|
||||||
|
|
||||||
@Input
|
|
||||||
@Optional
|
|
||||||
String config = null
|
|
||||||
|
|
||||||
@Input
|
|
||||||
@Optional
|
|
||||||
// Property: fightID
|
|
||||||
Integer eventKampfID = 0
|
|
||||||
|
|
||||||
@Input
|
|
||||||
@Optional
|
|
||||||
UUID blueLeader = null
|
|
||||||
|
|
||||||
@Input
|
|
||||||
@Optional
|
|
||||||
UUID redLeader = null
|
|
||||||
|
|
||||||
FightServer() {
|
|
||||||
super()
|
|
||||||
doFirst {
|
|
||||||
if (checkSchemID != 0) dParams.put("checkSchemID", "$checkSchemID")
|
|
||||||
if (prepareSchemID != 0) dParams.put("prepareSchemID", "$prepareSchemID")
|
|
||||||
if (replay != 0) dParams.put("replay", "$replay")
|
|
||||||
if (eventKampfID != 0) dParams.put("fightID", "$eventKampfID")
|
|
||||||
if (blueLeader != null) dParams.put("blueLeader", blueLeader.toString())
|
|
||||||
if (redLeader != null) dParams.put("redLeader", redLeader.toString())
|
|
||||||
if (config != null) dParams.put("config", config)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user