diff --git a/demo/src/main/java/net/minestom/scratch/Scratch.java b/demo/src/main/java/net/minestom/scratch/Scratch.java index e3afc48ea..32573906b 100644 --- a/demo/src/main/java/net/minestom/scratch/Scratch.java +++ b/demo/src/main/java/net/minestom/scratch/Scratch.java @@ -4,6 +4,7 @@ import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.TextColor; import net.minestom.scratch.tools.ScratchBlockTools.BlockHolder; import net.minestom.scratch.tools.ScratchFeature; +import net.minestom.scratch.tools.ScratchInventoryUtils; import net.minestom.scratch.tools.ScratchNetworkTools.NetworkContext; import net.minestom.scratch.tools.ScratchVelocityTools; import net.minestom.server.ServerFlag; @@ -17,6 +18,8 @@ import net.minestom.server.entity.EntityType; import net.minestom.server.entity.GameMode; import net.minestom.server.instance.WorldBorder; import net.minestom.server.instance.block.Block; +import net.minestom.server.item.ItemStack; +import net.minestom.server.item.Material; import net.minestom.server.network.ConnectionState; import net.minestom.server.network.packet.client.ClientPacket; import net.minestom.server.network.packet.client.common.ClientPingRequestPacket; @@ -338,14 +341,19 @@ public final class Scratch { final Instance instance; final Synchronizer.Entry synchronizerEntry; + GameMode gameMode = GameMode.SURVIVAL; Pos position; Pos oldPosition; + ItemStack[] inventory = new ItemStack[46]; + ItemStack cursor = ItemStack.AIR; + final ScratchFeature.Messaging messaging; final ScratchFeature.Movement movement; final ScratchFeature.ChunkLoading chunkLoading; final ScratchFeature.EntityInteract entityInteract; final ScratchFeature.BlockInteract blockInteract; + final ScratchFeature.InventoryHandling inventoryHandling; Player(PlayerInfo info, Instance spawnInstance, Pos spawnPosition) { this.connection = info.connection; @@ -356,6 +364,9 @@ public final class Scratch { this.position = spawnPosition; this.oldPosition = spawnPosition; + Arrays.fill(inventory, ItemStack.AIR); + inventory[0] = ItemStack.of(Material.STONE, 64); + this.synchronizerEntry = instance.synchronizer.makeEntry(true, id, position, () -> { final var spawnPacket = new SpawnEntityPacket( @@ -441,7 +452,7 @@ public final class Scratch { this.blockInteract = new ScratchFeature.BlockInteract(new ScratchFeature.BlockInteract.Mapping() { @Override public boolean creative() { - return true; + return gameMode == GameMode.CREATIVE; } @Override @@ -462,6 +473,18 @@ public final class Scratch { } }); + this.inventoryHandling = new ScratchFeature.InventoryHandling(new ScratchFeature.InventoryHandling.Mapping() { + @Override + public void setPlayerItem(int slot, ItemStack itemStack) { + inventory[slot] = itemStack; + } + + @Override + public void setCursorItem(ItemStack itemStack) { + cursor = itemStack; + } + }); + this.connection.networkContext.writePlays(initPackets()); } @@ -475,7 +498,7 @@ public final class Scratch { 8, 8, false, true, false, dimensionType.toString(), "world", - 0, GameMode.CREATIVE, null, false, true, + 0, gameMode, null, false, true, new WorldPos("dimension", Vec.ZERO), 0); packets.add(joinGamePacket); packets.add(new SpawnPositionPacket(position, 0)); @@ -489,6 +512,8 @@ public final class Scratch { packets.add(new ChangeGameStatePacket(ChangeGameStatePacket.Reason.LEVEL_CHUNKS_LOAD_START, 0f)); + packets.add(ScratchInventoryUtils.makePlayerPacket(inventory, cursor)); + return packets; } @@ -507,7 +532,7 @@ public final class Scratch { private PlayerInfoUpdatePacket getAddPlayerToList() { final var infoEntry = new PlayerInfoUpdatePacket.Entry(uuid, username, List.of(), - true, 1, GameMode.CREATIVE, null, null); + true, 1, gameMode, null, null); return new PlayerInfoUpdatePacket(EnumSet.of(PlayerInfoUpdatePacket.Action.ADD_PLAYER, PlayerInfoUpdatePacket.Action.UPDATE_LISTED), List.of(infoEntry)); } diff --git a/demo/src/main/java/net/minestom/scratch/tools/ScratchFeature.java b/demo/src/main/java/net/minestom/scratch/tools/ScratchFeature.java index a59cbcf4c..8d300f659 100644 --- a/demo/src/main/java/net/minestom/scratch/tools/ScratchFeature.java +++ b/demo/src/main/java/net/minestom/scratch/tools/ScratchFeature.java @@ -4,13 +4,16 @@ import net.kyori.adventure.text.Component; import net.minestom.server.coordinate.Point; import net.minestom.server.coordinate.Pos; import net.minestom.server.instance.block.BlockFace; +import net.minestom.server.item.ItemStack; import net.minestom.server.network.packet.client.ClientPacket; import net.minestom.server.network.packet.client.play.*; import net.minestom.server.network.packet.server.ServerPacket; import net.minestom.server.network.packet.server.play.*; import net.minestom.server.utils.Direction; import net.minestom.server.utils.chunk.ChunkUtils; +import net.minestom.server.utils.inventory.PlayerInventoryUtils; +import java.util.List; import java.util.function.Consumer; public interface ScratchFeature extends Consumer { @@ -148,4 +151,26 @@ public interface ScratchFeature extends Consumer { void acknowledge(ServerPacket.Play packet); } } + + record InventoryHandling(Mapping mapping) implements ScratchFeature { + @Override + public void accept(ClientPacket packet) { + if (packet instanceof ClientClickWindowPacket( + byte windowId, int stateId, short slot, byte button, ClientClickWindowPacket.ClickType clickType, + List changedSlots, ItemStack clickedItem + )) { + for (ClientClickWindowPacket.ChangedSlot changedSlot : changedSlots) { + final int internalSlot = PlayerInventoryUtils.convertPlayerInventorySlot(changedSlot.slot(), PlayerInventoryUtils.OFFSET); + mapping.setPlayerItem(internalSlot, changedSlot.item()); + } + mapping.setCursorItem(clickedItem); + } + } + + public interface Mapping { + void setPlayerItem(int slot, ItemStack itemStack); + + void setCursorItem(ItemStack itemStack); + } + } } diff --git a/demo/src/main/java/net/minestom/scratch/tools/ScratchInventoryUtils.java b/demo/src/main/java/net/minestom/scratch/tools/ScratchInventoryUtils.java new file mode 100644 index 000000000..f0874386f --- /dev/null +++ b/demo/src/main/java/net/minestom/scratch/tools/ScratchInventoryUtils.java @@ -0,0 +1,19 @@ +package net.minestom.scratch.tools; + +import net.minestom.server.item.ItemStack; +import net.minestom.server.network.packet.server.play.WindowItemsPacket; +import net.minestom.server.utils.inventory.PlayerInventoryUtils; + +import java.util.ArrayList; +import java.util.List; + +public final class ScratchInventoryUtils { + public static WindowItemsPacket makePlayerPacket(ItemStack[] inventoryItems, ItemStack cursor) { + List items = new ArrayList<>(); + for (int i = 0; i < inventoryItems.length; i++) { + final int internalSlot = PlayerInventoryUtils.convertPlayerInventorySlot(i, PlayerInventoryUtils.OFFSET); + items.add(inventoryItems[internalSlot]); + } + return new WindowItemsPacket((byte) 0, 0, items, cursor); + } +}