Add support for player inventory integration in UI system

This commit is contained in:
2025-04-21 16:02:18 +02:00
parent ee9eb995f5
commit 4cb0ff292e
3 changed files with 49 additions and 5 deletions
@@ -24,6 +24,7 @@ import de.steamwar.Reflection;
import de.steamwar.command.*;
import de.steamwar.core.authlib.AuthlibInjector;
import de.steamwar.core.events.*;
import de.steamwar.inventory.ui.test.TestInvCommand;
import de.steamwar.message.Message;
import de.steamwar.network.NetworkReceiver;
import de.steamwar.network.handlers.ServerDataHandler;
@@ -67,6 +68,7 @@ public class Core extends JavaPlugin{
@Override
public void onEnable() {
new TestInvCommand();
errorHandler = new ErrorHandler();
crashDetector = new CrashDetector();
@@ -31,7 +31,13 @@ public abstract class StatefulUIInventory<T> extends UIInventory implements Upda
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;
}
@@ -27,7 +27,6 @@ import de.steamwar.inventory.ui.util.Size;
import de.steamwar.message.Message;
import lombok.AllArgsConstructor;
import lombok.Setter;
import org.bukkit.entity.Item;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
@@ -38,17 +37,25 @@ import org.bukkit.inventory.InventoryView;
import org.bukkit.inventory.ItemStack;
import java.util.*;
import java.util.function.Consumer;
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;
protected UIInventory() {
this(0);
}
protected UIInventory(int playerSlots) {
this.playerSlots = playerSlots;
}
public abstract UIComponent render();
public abstract Inventory createInventory(Player player);
@@ -65,6 +72,9 @@ public abstract class UIInventory {
}
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);
@@ -73,7 +83,13 @@ public abstract class UIInventory {
private void renderPlayer(Player player, Inventory inventory) {
int width = Math.min(inventory.getSize(), 9);
int height = Math.max(inventory.getSize() / 9, 1);
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;
ComponentRender render = render().render(new RenderContext(new Size(width, height), new Size(width, height), this));
@@ -86,10 +102,27 @@ public abstract class UIInventory {
Message message = getMessages();
ItemStack[] itemStacks = new ItemStack[inventory.getSize()];
ItemStack[] playerStacks = new ItemStack[playerSlots > 0 ? 4 * 9 : 0];
render.getItems().forEach(item -> itemStacks[item.getX() + item.getY() * 9] = item.getItemStack().message(message).build(player));
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)
@@ -159,6 +192,9 @@ public abstract class UIInventory {
viewers.remove(player);
UIInventory.this.callbacks.remove(player);
if (playerSlots > 0) {
player.getInventory().setContents(originalItems.remove(player));
}
onClose();
}