From fa72e6ec037de72a7e7b443a8d66bc126663f5ff Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Sat, 28 Aug 2021 10:12:13 +0700 Subject: [PATCH] Working interaction with drives --- .../capability/drive/IItemViewListener.java | 11 + .../otm/capability/drive/IMatteryDrive.java | 7 +- .../mc/otm/capability/drive/MatteryDrive.java | 60 ++- .../mc/otm/menu/DriveViewerMenu.java | 352 +++++++++++++++-- .../mc/otm/menu/data/NetworkedItemView.java | 370 ------------------ .../mc/otm/menu/slot/ItemViewInputSlot.java | 35 -- .../mc/otm/network/MatteryNetworking.java | 67 +++- .../mc/otm/network/SetCarriedPacket.java | 32 ++ .../mc/otm/screen/DriveViewerScreen.java | 33 +- 9 files changed, 485 insertions(+), 482 deletions(-) create mode 100644 src/main/java/ru/dbotthepony/mc/otm/capability/drive/IItemViewListener.java delete mode 100644 src/main/java/ru/dbotthepony/mc/otm/menu/data/NetworkedItemView.java delete mode 100644 src/main/java/ru/dbotthepony/mc/otm/menu/slot/ItemViewInputSlot.java create mode 100644 src/main/java/ru/dbotthepony/mc/otm/network/SetCarriedPacket.java diff --git a/src/main/java/ru/dbotthepony/mc/otm/capability/drive/IItemViewListener.java b/src/main/java/ru/dbotthepony/mc/otm/capability/drive/IItemViewListener.java new file mode 100644 index 000000000..69d975341 --- /dev/null +++ b/src/main/java/ru/dbotthepony/mc/otm/capability/drive/IItemViewListener.java @@ -0,0 +1,11 @@ +package ru.dbotthepony.mc.otm.capability.drive; + +import net.minecraft.world.item.ItemStack; + +import java.util.UUID; + +public interface IItemViewListener { + void addViewItem(ItemStack stack, UUID id_upstream); + void changeViewItem(UUID id_upstream, int new_count); + void removeViewItem(UUID id_upstream); +} diff --git a/src/main/java/ru/dbotthepony/mc/otm/capability/drive/IMatteryDrive.java b/src/main/java/ru/dbotthepony/mc/otm/capability/drive/IMatteryDrive.java index 0e548877b..a221ba496 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/capability/drive/IMatteryDrive.java +++ b/src/main/java/ru/dbotthepony/mc/otm/capability/drive/IMatteryDrive.java @@ -5,6 +5,7 @@ import net.minecraft.nbt.CompoundTag; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraftforge.common.util.INBTSerializable; +import ru.dbotthepony.mc.otm.menu.DriveViewerMenu; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -36,8 +37,10 @@ public interface IMatteryDrive { */ List findItems(ItemStack stack); - @Nullable - StoredStack getItem(UUID id); + ItemStack getItem(UUID id); + + void addListener(IItemViewListener listener); + void removeListener(IItemViewListener listener); int getStoredCount(); int getCapacity(); diff --git a/src/main/java/ru/dbotthepony/mc/otm/capability/drive/MatteryDrive.java b/src/main/java/ru/dbotthepony/mc/otm/capability/drive/MatteryDrive.java index b8f723cda..06d1814e7 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/capability/drive/MatteryDrive.java +++ b/src/main/java/ru/dbotthepony/mc/otm/capability/drive/MatteryDrive.java @@ -115,10 +115,38 @@ public class MatteryDrive implements IMatteryDrive { return build_list; } - @Nullable + protected final ArrayList listeners = new ArrayList<>(); + @Override - public StoredStack getItem(UUID id) { - return items_by_id.get(id); + public void addListener(IItemViewListener listener) { + if (listeners.contains(listener)) + return; + + listeners.add(listener); + + for (var list : this.items.values()) { + for (var state : list) { + listener.addViewItem(state.stack(), state.id()); + } + } + } + + @Override + public void removeListener(IItemViewListener listener) { + if (listeners.remove(listener)) { + for (var list : this.items.values()) { + for (var state : list) { + listener.removeViewItem(state.id()); + } + } + } + } + + @Nonnull + @Override + public ItemStack getItem(UUID id) { + var stack = items_by_id.get(id); + return stack != null ? stack.stack() : ItemStack.EMPTY; } @Nonnull @@ -136,6 +164,11 @@ public class MatteryDrive implements IMatteryDrive { if (!simulate) { state.stack().grow(max_insert); stored += max_insert; + + for (var listener : listeners) { + listener.changeViewItem(state.id(), state.stack().getCount()); + } + markDirty(); } @@ -156,6 +189,11 @@ public class MatteryDrive implements IMatteryDrive { var state = new StoredStack(copy, UUID.randomUUID()); listing.add(state); items_by_id.put(state.id(), state); + + for (var listener : listeners) { + listener.addViewItem(state.stack(), state.id()); + } + markDirty(); } @@ -180,18 +218,30 @@ public class MatteryDrive implements IMatteryDrive { if (extract <= 0) return ItemStack.EMPTY; + var copy = get.stack().copy(); + copy.setCount(extract); + if (!simulate) { if (extract == get.stack().getCount()) { var listing = items.get(get.stack().getItem()); listing.remove(get); + + for (var listener : listeners) { + listener.removeViewItem(get.id()); + } } get.stack().shrink(extract); + + if (get.stack().getCount() != 0) { + for (var listener : listeners) { + listener.changeViewItem(get.id(), get.stack().getCount()); + } + } + markDirty(); } - var copy = get.stack().copy(); - copy.setCount(extract); return copy; } diff --git a/src/main/java/ru/dbotthepony/mc/otm/menu/DriveViewerMenu.java b/src/main/java/ru/dbotthepony/mc/otm/menu/DriveViewerMenu.java index 9fb84618f..bfdc4a6fb 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/menu/DriveViewerMenu.java +++ b/src/main/java/ru/dbotthepony/mc/otm/menu/DriveViewerMenu.java @@ -1,29 +1,36 @@ package ru.dbotthepony.mc.otm.menu; +import net.minecraft.client.Minecraft; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.SimpleContainer; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; +import net.minecraftforge.fmllegacy.network.NetworkEvent; +import net.minecraftforge.fmllegacy.network.PacketDistributor; import ru.dbotthepony.mc.otm.Registry; import ru.dbotthepony.mc.otm.block.entity.BlockEntityDriveViewer; import ru.dbotthepony.mc.otm.capability.MatteryCapability; +import ru.dbotthepony.mc.otm.capability.drive.IItemViewListener; import ru.dbotthepony.mc.otm.capability.drive.IMatteryDrive; -import ru.dbotthepony.mc.otm.menu.data.NetworkedItemView; -import ru.dbotthepony.mc.otm.menu.data.UUIDDataContainer; import ru.dbotthepony.mc.otm.menu.slot.MatterySlot; +import ru.dbotthepony.mc.otm.network.MatteryNetworking; +import ru.dbotthepony.mc.otm.network.SetCarriedPacket; import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.UUID; +import java.util.function.Supplier; public class DriveViewerMenu extends PoweredMatteryMenu { - public UUIDDataContainer view_uuid; public NetworkedItemView view; public MatterySlot drive_slot; protected IMatteryDrive last_drive; - public NetworkedItemView getView() { - return view != null ? view : NetworkedItemView.getRemote(view_uuid.getValue()); - } - public DriveViewerMenu(int containerID, Inventory inventory) { this(containerID, inventory, null); } @@ -31,7 +38,6 @@ public class DriveViewerMenu extends PoweredMatteryMenu { public DriveViewerMenu(int containerID, Inventory inventory, @Nullable BlockEntityDriveViewer tile) { super(Registry.Menus.DRIVE_VIEWER, containerID, inventory, tile); - view_uuid = new UUIDDataContainer(); var container = tile != null ? tile.drive_slot : new SimpleContainer(1); drive_slot = new MatterySlot(container, 0) { @@ -42,13 +48,7 @@ public class DriveViewerMenu extends PoweredMatteryMenu { }; addSlot(drive_slot); - - if (tile != null) { - view = new NetworkedItemView(inventory.player); - view_uuid.setValue(view.id); - } - - addDataSlots(view_uuid); + view = new NetworkedItemView(); addBatterySlot(); addInventorySlots(); @@ -63,6 +63,7 @@ public class DriveViewerMenu extends PoweredMatteryMenu { if (get.isEmpty()) { if (last_drive != null) { + last_drive.removeListener(view); view.clear(); } @@ -72,17 +73,18 @@ public class DriveViewerMenu extends PoweredMatteryMenu { if (get_cap.isEmpty()) { if (last_drive != null) { + last_drive.removeListener(view); view.clear(); } last_drive = null; } else { if (last_drive != get_cap.get()) { - view.clear(); + if (last_drive != null) + last_drive.removeListener(view); - for (var stack : get_cap.get().getItems()) { - view.addItem(stack.stack(), stack.id()); - } + view.clear(); + get_cap.get().addListener(view); } last_drive = get_cap.get(); @@ -93,18 +95,6 @@ public class DriveViewerMenu extends PoweredMatteryMenu { } } - @Override - public void removed(Player p_38940_) { - super.removed(p_38940_); - - if (!p_38940_.level.isClientSide) { - var view = getView(); - - if (view != null) - view.remove(); - } - } - @Override protected int getWorkingSlotStart() { return 0; @@ -114,4 +104,304 @@ public class DriveViewerMenu extends PoweredMatteryMenu { protected int getWorkingSlotEnd() { return 2; } + + @Override + public void removed(Player p_38940_) { + super.removed(p_38940_); + + if (last_drive != null) { + last_drive.removeListener(view); + view.clear(); + } + } + + /** + * Creates a virtual, slotless container for Player's interaction with. + */ + public class NetworkedItemView implements IItemViewListener { + public record NetworkedItem(int id, ItemStack stack, UUID id_upstream) { + public NetworkedItem(int id, ItemStack stack) { + this(id, stack, null); + } + } + + public record ClearPacket(int id) { + public void write(FriendlyByteBuf buffer) { + buffer.writeInt(id); + } + + public static ClearPacket read(FriendlyByteBuf buffer) { + return new ClearPacket(buffer.readInt()); + } + + public void play(Supplier context) { + context.get().setPacketHandled(true); + context.get().enqueueWork(() -> { + var get = Minecraft.getInstance().player.containerMenu instanceof DriveViewerMenu menu && menu.containerId == id ? menu.view : null; + + if (get == null) { + throw new IllegalStateException("No such item tracker with id " + id); + } + + get.clear(); + }); + } + } + + public record StackAddPacket(int id, int stack_id, ItemStack stack) { + public void write(FriendlyByteBuf buffer) { + buffer.writeInt(id); + buffer.writeInt(stack_id); + buffer.writeRegistryId(stack.getItem()); + buffer.writeInt(stack.getCount()); + buffer.writeBoolean(stack.getTag() != null); + + if (stack.getTag() != null) + buffer.writeNbt(stack.getShareTag()); + } + + public static StackAddPacket read(FriendlyByteBuf buffer) { + var id = buffer.readInt(); + var stack = buffer.readInt(); + var item = buffer.readRegistryIdSafe(Item.class); + var count = buffer.readInt(); + + var state = new ItemStack(item, count); + + if (buffer.readBoolean()) + state.readShareTag(buffer.readNbt()); + + return new StackAddPacket(id, stack, state); + } + + public void play(Supplier context) { + context.get().setPacketHandled(true); + context.get().enqueueWork(() -> { + var get = Minecraft.getInstance().player.containerMenu instanceof DriveViewerMenu menu && menu.containerId == id ? menu.view : null; + + if (get == null) { + throw new IllegalStateException("No such item tracker with id " + id); + } + + if (get.state.containsKey(stack_id)) { + throw new IllegalStateException("Item tracker " + id + " already has stack with id of " + stack_id); + } + + get.state.put(stack_id, new NetworkedItem(stack_id, stack)); + get.clearCache(); + }); + } + } + + public record StackChangePacket(int id, int stack_id, int new_count) { + public void write(FriendlyByteBuf buffer) { + buffer.writeInt(id); + buffer.writeInt(stack_id); + buffer.writeInt(new_count); + } + + public static StackChangePacket read(FriendlyByteBuf buffer) { + var id = buffer.readInt(); + var stack_id = buffer.readInt(); + var new_count = buffer.readInt(); + + return new StackChangePacket(id, stack_id, new_count); + } + + public void play(Supplier context) { + context.get().setPacketHandled(true); + context.get().enqueueWork(() -> { + var get = Minecraft.getInstance().player.containerMenu instanceof DriveViewerMenu menu && menu.containerId == id ? menu.view : null; + + if (get == null) { + throw new IllegalStateException("No such item tracker with id " + id); + } + + var get_state = get.state.get(stack_id); + + if (get_state == null) { + throw new IllegalStateException("Item tracker " + id + " has no stack with id of " + stack_id); + } + + get_state.stack.setCount(new_count); + get.clearCache(); + }); + } + } + + public record StackRemovePacket(int id, int stack_id) { + public void write(FriendlyByteBuf buffer) { + buffer.writeInt(id); + buffer.writeInt(stack_id); + } + + public static StackRemovePacket read(FriendlyByteBuf buffer) { + var id = buffer.readInt(); + var stack_id = buffer.readInt(); + + return new StackRemovePacket(id, stack_id); + } + + public void play(Supplier context) { + context.get().setPacketHandled(true); + context.get().enqueueWork(() -> { + var get = Minecraft.getInstance().player.containerMenu instanceof DriveViewerMenu menu && menu.containerId == id ? menu.view : null; + + if (get == null) { + throw new IllegalStateException("No such item tracker with id " + id); + } + + var get_state = get.state.remove(stack_id); + + if (get_state == null) { + throw new IllegalStateException("Item tracker " + id + " has no stack with id of " + stack_id); + } + + get.clearCache(); + }); + } + } + + public record InteractPacket(int id, int stack_id) { + public void write(FriendlyByteBuf buffer) { + buffer.writeInt(id); + buffer.writeInt(stack_id); + } + + public static InteractPacket read(FriendlyByteBuf buffer) { + var id = buffer.readInt(); + var stack = buffer.readInt(); + return new InteractPacket(id, stack); + } + + public void play(Supplier context) { + context.get().setPacketHandled(true); + context.get().enqueueWork(() -> { + var ply = context.get().getSender(); + + if (ply.containerMenu instanceof DriveViewerMenu menu) { + var get = menu.containerId == id ? menu.view : null; + + if (get == null) { + return; + } + + ply.resetLastActionTime(); + + if (menu.last_drive == null) + return; + + if (!menu.getCarried().isEmpty()) { + // try to put + menu.setCarried(menu.last_drive.insertItem(menu.getCarried(), false)); + MatteryNetworking.send(ply, new SetCarriedPacket(menu.getCarried())); + menu.setRemoteCarried(menu.getCarried().copy()); + } else if (stack_id > -1) { + var get_state = get.state.get(stack_id); + + if (get_state == null) { + return; + } + + menu.setCarried(menu.last_drive.extractItem(get_state.id_upstream, 64, false)); + MatteryNetworking.send(ply, new SetCarriedPacket(menu.getCarried())); + menu.setRemoteCarried(menu.getCarried().copy()); + } + } + }); + } + } + + protected int next_stack_id = 0; + + protected final HashMap state = new HashMap<>(); + protected final HashMap upstream_state = new HashMap<>(); + protected final ArrayList backlog = new ArrayList<>(); + + private List view_cache; + + public void clearCache() { + view_cache = null; + } + + public List getItems() { + if (view_cache != null) + return view_cache; + + return view_cache = List.copyOf(state.values()); + } + + @Override + public void addViewItem(ItemStack stack, UUID id_upstream) { + if (upstream_state.containsKey(id_upstream)) + throw new IllegalStateException("Already tracking ItemStack with upstream id " + id_upstream + "!"); + + var state = new NetworkedItem(next_stack_id++, stack.copy(), id_upstream); + this.state.put(state.id, state); + this.upstream_state.put(id_upstream, state); + + if (tile != null) { + backlog.add(new StackAddPacket(containerId, state.id, stack)); + } + + clearCache(); + } + + @Override + public void changeViewItem(UUID id_upstream, int new_count) { + var get = upstream_state.get(id_upstream); + + if (get == null) + throw new IllegalStateException("Unknown ItemStack with upstream id " + id_upstream + "!"); + + get.stack.setCount(new_count); + + if (tile != null) { + backlog.add(new StackChangePacket(containerId, get.id, new_count)); + } + + clearCache(); + } + + @Override + public void removeViewItem(UUID id_upstream) { + var get = upstream_state.get(id_upstream); + + if (get == null) + throw new IllegalStateException("Unknown ItemStack with upstream id " + id_upstream + "!"); + + upstream_state.remove(id_upstream); + state.remove(get.id); + + if (tile != null) { + backlog.add(new StackRemovePacket(containerId, get.id)); + } + + clearCache(); + } + + public void clear() { + clearCache(); + upstream_state.clear(); + state.clear(); + + if (tile != null) { + backlog.clear(); + backlog.add(new ClearPacket(containerId)); + } + } + + public void network() { + if (tile == null) + throw new IllegalStateException("Not a server"); + + var consumer = PacketDistributor.PLAYER.with(() -> (ServerPlayer) ply); + + for (var packet : backlog) { + MatteryNetworking.CHANNEL.send(consumer, packet); + } + + backlog.clear(); + } + } } diff --git a/src/main/java/ru/dbotthepony/mc/otm/menu/data/NetworkedItemView.java b/src/main/java/ru/dbotthepony/mc/otm/menu/data/NetworkedItemView.java deleted file mode 100644 index 0f773b273..000000000 --- a/src/main/java/ru/dbotthepony/mc/otm/menu/data/NetworkedItemView.java +++ /dev/null @@ -1,370 +0,0 @@ -package ru.dbotthepony.mc.otm.menu.data; - -import net.minecraft.client.Minecraft; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import net.minecraftforge.fmllegacy.network.NetworkEvent; -import net.minecraftforge.fmllegacy.network.PacketDistributor; -import ru.dbotthepony.mc.otm.network.MatteryNetworking; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.UUID; -import java.util.function.Supplier; - -/** - * Creates a virtual, slotless container for Player's interaction with. - */ -public class NetworkedItemView { - public record NetworkedItem(int id, ItemStack stack, UUID id_upstream) { - public NetworkedItem(int id, ItemStack stack) { - this(id, stack, null); - } - } - - public record ClearPacket(UUID id, boolean remove) { - public void write(FriendlyByteBuf buffer) { - buffer.writeLong(id.getMostSignificantBits()); - buffer.writeLong(id.getLeastSignificantBits()); - buffer.writeBoolean(remove); - } - - public static ClearPacket read(FriendlyByteBuf buffer) { - return new ClearPacket(new UUID(buffer.readLong(), buffer.readLong()), buffer.readBoolean()); - } - - public void play(Supplier context) { - context.get().setPacketHandled(true); - context.get().enqueueWork(() -> { - var get = TRACKERS_REMOTE.get(id); - - if (get == null) { - throw new IllegalStateException("No such item tracker with id " + id); - } - - if (remove) { - get.remove(); - } else { - get.clear(); - } - }); - } - } - - public record CreatedPacket(UUID id) { - public void write(FriendlyByteBuf buffer) { - buffer.writeLong(id.getMostSignificantBits()); - buffer.writeLong(id.getLeastSignificantBits()); - } - - public static CreatedPacket read(FriendlyByteBuf buffer) { - return new CreatedPacket(new UUID(buffer.readLong(), buffer.readLong())); - } - - public void play(Supplier context) { - context.get().setPacketHandled(true); - context.get().enqueueWork(() -> { - new NetworkedItemView(Minecraft.getInstance().player, id, true); - }); - } - } - - public record StackAddPacket(UUID id, int stack_id, ItemStack stack) { - public void write(FriendlyByteBuf buffer) { - buffer.writeLong(id.getMostSignificantBits()); - buffer.writeLong(id.getLeastSignificantBits()); - buffer.writeInt(stack_id); - buffer.writeRegistryId(stack.getItem()); - buffer.writeInt(stack.getCount()); - buffer.writeBoolean(stack.getTag() != null); - - if (stack.getTag() != null) - buffer.writeNbt(stack.getShareTag()); - } - - public static StackAddPacket read(FriendlyByteBuf buffer) { - var id = new UUID(buffer.readLong(), buffer.readLong()); - var stack = buffer.readInt(); - var item = buffer.readRegistryIdSafe(Item.class); - var count = buffer.readInt(); - - var state = new ItemStack(item, count); - - if (buffer.readBoolean()) - state.readShareTag(buffer.readNbt()); - - return new StackAddPacket(id, stack, state); - } - - public void play(Supplier context) { - context.get().setPacketHandled(true); - context.get().enqueueWork(() -> { - var get = TRACKERS_REMOTE.get(id); - - if (get == null) { - throw new IllegalStateException("No such item tracker with id " + id); - } - - if (get.state.containsKey(stack_id)) { - throw new IllegalStateException("Item tracker " + id + " already has stack with id of " + stack_id); - } - - get.state.put(stack_id, new NetworkedItem(stack_id, stack)); - get.clearCache(); - }); - } - } - - public record InteractPacket(UUID id, int stack_id) { - public void write(FriendlyByteBuf buffer) { - buffer.writeLong(id.getMostSignificantBits()); - buffer.writeLong(id.getLeastSignificantBits()); - buffer.writeInt(stack_id); - } - - public static InteractPacket read(FriendlyByteBuf buffer) { - var id = new UUID(buffer.readLong(), buffer.readLong()); - var stack = buffer.readInt(); - return new InteractPacket(id, stack); - } - - public void play(Supplier context) { - context.get().setPacketHandled(true); - context.get().enqueueWork(() -> { - var get = TRACKERS_REMOTE.get(id); - - if (get == null) { - return; - } - - var get_state = get.state.get(stack_id); - - if (get_state == null) { - return; - } - - var ply = context.get().getSender(); - ply.resetLastActionTime(); - }); - } - } - - public record StackChangePacket(UUID id, int stack_id, int new_count) { - public void write(FriendlyByteBuf buffer) { - buffer.writeLong(id.getMostSignificantBits()); - buffer.writeLong(id.getLeastSignificantBits()); - buffer.writeInt(stack_id); - buffer.writeInt(new_count); - } - - public static StackChangePacket read(FriendlyByteBuf buffer) { - var id = new UUID(buffer.readLong(), buffer.readLong()); - var stack_id = buffer.readInt(); - var new_count = buffer.readInt(); - - return new StackChangePacket(id, stack_id, new_count); - } - - public void play(Supplier context) { - context.get().setPacketHandled(true); - context.get().enqueueWork(() -> { - var get = TRACKERS_REMOTE.get(id); - - if (get == null) { - throw new IllegalStateException("No such item tracker with id " + id); - } - - var get_state = get.state.get(stack_id); - - if (get_state == null) { - throw new IllegalStateException("Item tracker " + id + " has no stack with id of " + stack_id); - } - - get_state.stack.setCount(new_count); - get.clearCache(); - }); - } - } - - public record StackRemovePacket(UUID id, int stack_id) { - public void write(FriendlyByteBuf buffer) { - buffer.writeLong(id.getMostSignificantBits()); - buffer.writeLong(id.getLeastSignificantBits()); - buffer.writeInt(stack_id); - } - - public static StackRemovePacket read(FriendlyByteBuf buffer) { - var id = new UUID(buffer.readLong(), buffer.readLong()); - var stack_id = buffer.readInt(); - - return new StackRemovePacket(id, stack_id); - } - - public void play(Supplier context) { - context.get().setPacketHandled(true); - context.get().enqueueWork(() -> { - var get = TRACKERS_REMOTE.get(id); - - if (get == null) { - throw new IllegalStateException("No such item tracker with id " + id); - } - - var get_state = get.state.remove(stack_id); - - if (get_state == null) { - throw new IllegalStateException("Item tracker " + id + " has no stack with id of " + stack_id); - } - - get.clearCache(); - }); - } - } - - public final Player ply; - public final UUID id; - public final boolean remote; - protected int next_stack_id = 0; - - protected final HashMap state = new HashMap<>(); - protected final HashMap upstream_state = new HashMap<>(); - protected final ArrayList backlog = new ArrayList<>(); - - // normally, filled only on server - private static final HashMap TRACKERS_LOCAL = new HashMap<>(); - - // normally, filled only on client - private static final HashMap TRACKERS_REMOTE = new HashMap<>(); - - public static NetworkedItemView getLocal(UUID id) { - return TRACKERS_LOCAL.get(id); - } - - public static NetworkedItemView getRemote(UUID id) { - return TRACKERS_REMOTE.get(id); - } - - public NetworkedItemView(Player ply) { - this(ply, UUID.randomUUID()); - } - - public NetworkedItemView(Player ply, UUID id) { - this(ply, id, false); - } - - public NetworkedItemView(Player ply, UUID id, boolean remote) { - this.remote = remote; - this.ply = ply; - this.id = id; - - if (remote) { - TRACKERS_REMOTE.put(this.id, this); - } else { - TRACKERS_LOCAL.put(this.id, this); - MatteryNetworking.CHANNEL.send(PacketDistributor.PLAYER.with(() -> (ServerPlayer) ply), new CreatedPacket(this.id)); - } - } - - private List view_cache; - - public void clearCache() { - view_cache = null; - } - - public boolean mayPlace(ItemStack stack) { - return false; - } - - public List getItems() { - if (view_cache != null) - return view_cache; - - var list = new ArrayList(state.size()); - - for (var state : this.state.values()) - list.add(state.stack); - - return view_cache = list; - } - - public void addItem(ItemStack stack, UUID id_upstream) { - if (upstream_state.containsKey(id_upstream)) - throw new IllegalStateException("Already tracking ItemStack with upstream id " + id_upstream + "!"); - - var state = new NetworkedItem(next_stack_id++, stack, id_upstream); - this.state.put(state.id, state); - this.upstream_state.put(id_upstream, state); - - if (!remote) { - backlog.add(new StackAddPacket(id, state.id, stack)); - } - - clearCache(); - } - - public void changeItem(UUID id_upstream, int new_count) { - var get = upstream_state.get(id_upstream); - - if (get == null) - throw new IllegalStateException("Unknown ItemStack with upstream id " + id_upstream + "!"); - - get.stack.setCount(new_count); - - if (!remote) { - backlog.add(new StackChangePacket(id, get.id, new_count)); - } - - clearCache(); - } - - public void removeItem(UUID id_upstream) { - var get = upstream_state.get(id_upstream); - - if (get == null) - throw new IllegalStateException("Unknown ItemStack with upstream id " + id_upstream + "!"); - - upstream_state.remove(id_upstream); - state.remove(get.id); - - if (!remote) { - backlog.add(new StackRemovePacket(id, get.id)); - } - - clearCache(); - } - - public void clear() { - clearCache(); - upstream_state.clear(); - state.clear(); - - if (!remote) { - backlog.clear(); - backlog.add(new ClearPacket(id, false)); - } - } - - public void remove() { - if (!remote) { - TRACKERS_LOCAL.remove(id); - backlog.clear(); - backlog.add(new ClearPacket(id, true)); - } - } - - public void network() { - if (remote) - throw new IllegalStateException("Not a server"); - - var consumer = PacketDistributor.PLAYER.with(() -> (ServerPlayer) ply); - - for (var packet : backlog) { - MatteryNetworking.CHANNEL.send(consumer, packet); - } - - backlog.clear(); - } -} diff --git a/src/main/java/ru/dbotthepony/mc/otm/menu/slot/ItemViewInputSlot.java b/src/main/java/ru/dbotthepony/mc/otm/menu/slot/ItemViewInputSlot.java deleted file mode 100644 index e92a01c75..000000000 --- a/src/main/java/ru/dbotthepony/mc/otm/menu/slot/ItemViewInputSlot.java +++ /dev/null @@ -1,35 +0,0 @@ -package ru.dbotthepony.mc.otm.menu.slot; - -import net.minecraft.world.Container; -import net.minecraft.world.item.ItemStack; -import ru.dbotthepony.mc.otm.menu.data.NetworkedItemView; - -public class ItemViewInputSlot extends MatterySlot { - public ItemViewInputSlot(Container p_40223_, int index, int x, int y, boolean auto_bg) { - super(p_40223_, index, x, y, auto_bg); - } - - public ItemViewInputSlot(Container p_40223_, int index, int x, int y) { - super(p_40223_, index, x, y); - } - - public ItemViewInputSlot(Container p_40223_, int index) { - super(p_40223_, index); - } - - public NetworkedItemView view; - - @Override - public boolean mayPlace(ItemStack p_40231_) { - if (view == null || view.remote) { - return true; - } - - return view.mayPlace(p_40231_); - } - - @Override - public void set(ItemStack p_40240_) { - super.set(p_40240_); - } -} diff --git a/src/main/java/ru/dbotthepony/mc/otm/network/MatteryNetworking.java b/src/main/java/ru/dbotthepony/mc/otm/network/MatteryNetworking.java index 028d88c26..38c5fcc7b 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/network/MatteryNetworking.java +++ b/src/main/java/ru/dbotthepony/mc/otm/network/MatteryNetworking.java @@ -1,11 +1,13 @@ package ru.dbotthepony.mc.otm.network; import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerPlayer; import net.minecraftforge.fmllegacy.network.NetworkDirection; import net.minecraftforge.fmllegacy.network.NetworkRegistry; +import net.minecraftforge.fmllegacy.network.PacketDistributor; import net.minecraftforge.fmllegacy.network.simple.SimpleChannel; import ru.dbotthepony.mc.otm.OverdriveThatMatters; -import ru.dbotthepony.mc.otm.menu.data.NetworkedItemView; +import ru.dbotthepony.mc.otm.menu.DriveViewerMenu; import ru.dbotthepony.mc.otm.network.android.*; import java.util.Optional; @@ -22,6 +24,20 @@ public class MatteryNetworking { PROTOCOL_VERSION::equals ); + public static void send(ServerPlayer ply, Object ...messages) { + var supplier = PacketDistributor.PLAYER.with(() -> ply); + + for (var message : messages) { + CHANNEL.send(supplier, message); + } + } + + public static void send(Object ...messages) { + for (var message : messages) { + CHANNEL.sendToServer(message); + } + } + public static void register() { CHANNEL.registerMessage( next_network_id++, @@ -133,46 +149,55 @@ public class MatteryNetworking { CHANNEL.registerMessage( next_network_id++, - NetworkedItemView.ClearPacket.class, - NetworkedItemView.ClearPacket::write, - NetworkedItemView.ClearPacket::read, - NetworkedItemView.ClearPacket::play, + DriveViewerMenu.NetworkedItemView.ClearPacket.class, + DriveViewerMenu.NetworkedItemView.ClearPacket::write, + DriveViewerMenu.NetworkedItemView.ClearPacket::read, + DriveViewerMenu.NetworkedItemView.ClearPacket::play, Optional.of(NetworkDirection.PLAY_TO_CLIENT) ); CHANNEL.registerMessage( next_network_id++, - NetworkedItemView.CreatedPacket.class, - NetworkedItemView.CreatedPacket::write, - NetworkedItemView.CreatedPacket::read, - NetworkedItemView.CreatedPacket::play, + DriveViewerMenu.NetworkedItemView.StackAddPacket.class, + DriveViewerMenu.NetworkedItemView.StackAddPacket::write, + DriveViewerMenu.NetworkedItemView.StackAddPacket::read, + DriveViewerMenu.NetworkedItemView.StackAddPacket::play, Optional.of(NetworkDirection.PLAY_TO_CLIENT) ); CHANNEL.registerMessage( next_network_id++, - NetworkedItemView.StackAddPacket.class, - NetworkedItemView.StackAddPacket::write, - NetworkedItemView.StackAddPacket::read, - NetworkedItemView.StackAddPacket::play, + DriveViewerMenu.NetworkedItemView.StackChangePacket.class, + DriveViewerMenu.NetworkedItemView.StackChangePacket::write, + DriveViewerMenu.NetworkedItemView.StackChangePacket::read, + DriveViewerMenu.NetworkedItemView.StackChangePacket::play, Optional.of(NetworkDirection.PLAY_TO_CLIENT) ); CHANNEL.registerMessage( next_network_id++, - NetworkedItemView.StackChangePacket.class, - NetworkedItemView.StackChangePacket::write, - NetworkedItemView.StackChangePacket::read, - NetworkedItemView.StackChangePacket::play, + DriveViewerMenu.NetworkedItemView.StackRemovePacket.class, + DriveViewerMenu.NetworkedItemView.StackRemovePacket::write, + DriveViewerMenu.NetworkedItemView.StackRemovePacket::read, + DriveViewerMenu.NetworkedItemView.StackRemovePacket::play, Optional.of(NetworkDirection.PLAY_TO_CLIENT) ); CHANNEL.registerMessage( next_network_id++, - NetworkedItemView.StackRemovePacket.class, - NetworkedItemView.StackRemovePacket::write, - NetworkedItemView.StackRemovePacket::read, - NetworkedItemView.StackRemovePacket::play, + DriveViewerMenu.NetworkedItemView.InteractPacket.class, + DriveViewerMenu.NetworkedItemView.InteractPacket::write, + DriveViewerMenu.NetworkedItemView.InteractPacket::read, + DriveViewerMenu.NetworkedItemView.InteractPacket::play, + Optional.of(NetworkDirection.PLAY_TO_SERVER) + ); + + CHANNEL.registerMessage( + next_network_id++, + SetCarriedPacket.class, + SetCarriedPacket::write, + SetCarriedPacket::read, + SetCarriedPacket::play, Optional.of(NetworkDirection.PLAY_TO_CLIENT) ); } diff --git a/src/main/java/ru/dbotthepony/mc/otm/network/SetCarriedPacket.java b/src/main/java/ru/dbotthepony/mc/otm/network/SetCarriedPacket.java new file mode 100644 index 000000000..16d9aa769 --- /dev/null +++ b/src/main/java/ru/dbotthepony/mc/otm/network/SetCarriedPacket.java @@ -0,0 +1,32 @@ +package ru.dbotthepony.mc.otm.network; + +import net.minecraft.client.Minecraft; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.fml.DistExecutor; +import net.minecraftforge.fmllegacy.network.NetworkEvent; +import ru.dbotthepony.mc.otm.capability.MatteryCapability; +import ru.dbotthepony.mc.otm.network.android.AndroidBatteryPacket; + +import java.util.function.Supplier; + +public record SetCarriedPacket(ItemStack carried) { + public void write(FriendlyByteBuf buffer) { + buffer.writeItem(carried); + } + + public void play(Supplier context) { + context.get().setPacketHandled(true); + context.get().enqueueWork(() -> { + if (Minecraft.getInstance().player.containerMenu != null) { + Minecraft.getInstance().player.containerMenu.setCarried(carried); + } + }); + } + + public static SetCarriedPacket read(FriendlyByteBuf buffer) { + return new SetCarriedPacket(buffer.readItem()); + } +} diff --git a/src/main/java/ru/dbotthepony/mc/otm/screen/DriveViewerScreen.java b/src/main/java/ru/dbotthepony/mc/otm/screen/DriveViewerScreen.java index b5c5d2aa6..326ed1d80 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/screen/DriveViewerScreen.java +++ b/src/main/java/ru/dbotthepony/mc/otm/screen/DriveViewerScreen.java @@ -9,6 +9,7 @@ import ru.dbotthepony.mc.otm.menu.MatteryMenu; import ru.dbotthepony.mc.otm.menu.slot.BatterySlot; import ru.dbotthepony.mc.otm.menu.slot.MatterySlot; import ru.dbotthepony.mc.otm.menu.widget.GaugeWidget; +import ru.dbotthepony.mc.otm.network.MatteryNetworking; import ru.dbotthepony.mc.otm.screen.panels.*; import javax.annotation.Nonnull; @@ -49,13 +50,7 @@ public class DriveViewerScreen extends MatteryScreen implements var scroll_bar = new ScrollBarPanel(this, frame, 0, 0, 0); scroll_bar.setDock(Dock.RIGHT); scroll_bar.setupRowMultiplier(() -> { - var view = menu.getView(); - - if (view != null) { - return view.getItems().size() / GRID_WIDTH; - } - - return 0; + return menu.view.getItems().size() / GRID_WIDTH; }); for (int i = 0; i < GRID_WIDTH * GRID_HEIGHT; i++) { @@ -65,27 +60,29 @@ public class DriveViewerScreen extends MatteryScreen implements @Nonnull @Override protected ItemStack getItemStack() { - int findex = index + scroll_bar.getScroll(GRID_WIDTH); + int findex = index + scroll_bar.getScroll(menu.view.getItems().size() / GRID_WIDTH); - var view = menu.getView(); + var list = menu.view.getItems(); - if (view != null) { - var list = view.getItems(); - - if (findex >= list.size()) { - return ItemStack.EMPTY; - } - - return list.get(findex); + if (findex >= list.size()) { + return ItemStack.EMPTY; } - return ItemStack.EMPTY; + return list.get(findex).stack(); } @Override protected boolean mouseScrolledInner(double mouse_x, double mouse_y, double scroll) { return scroll_bar.mouseScrolledInner(mouse_x, mouse_y, scroll); } + + @Override + protected boolean mouseClickedInner(double mouse_x, double mouse_y, int flag) { + int findex = index + scroll_bar.getScroll(GRID_WIDTH); + var list = menu.view.getItems(); + MatteryNetworking.send(new DriveViewerMenu.NetworkedItemView.InteractPacket(menu.containerId, findex >= list.size() ? -1 : list.get(findex).id())); + return true; + } }; }