diff --git a/src/main/java/ru/dbotthepony/mc/otm/OverdriveThatMatters.java b/src/main/java/ru/dbotthepony/mc/otm/OverdriveThatMatters.java index 6fbedd9a2..141c18002 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/OverdriveThatMatters.java +++ b/src/main/java/ru/dbotthepony/mc/otm/OverdriveThatMatters.java @@ -33,6 +33,7 @@ import ru.dbotthepony.mc.otm.matter.MatterRegistry; import ru.dbotthepony.mc.otm.network.MatteryNetworking; import ru.dbotthepony.mc.otm.storage.ItemStackWrapper; import ru.dbotthepony.mc.otm.storage.StorageObjectRegistry; +import ru.dbotthepony.mc.otm.storage.StorageObjectTuple; import javax.annotation.ParametersAreNonnullByDefault; import java.util.ArrayList; @@ -160,13 +161,15 @@ public class OverdriveThatMatters { }; } + public static StorageObjectTuple ITEM_STORAGE; + private void setup(final FMLCommonSetupEvent event) { MatteryNetworking.register(); // LOGGER.info("Registered network"); MatterRegistry.registerInitialItems(); - StorageObjectRegistry.register(ItemStackWrapper.class, ItemStackWrapper.EMPTY, new Fraction("3.125")); + ITEM_STORAGE = StorageObjectRegistry.register(ItemStackWrapper.class, ItemStackWrapper.EMPTY, new Fraction("3.125")); } private void setupClient(final FMLClientSetupEvent event) { diff --git a/src/main/java/ru/dbotthepony/mc/otm/client/screen/DriveViewerScreen.java b/src/main/java/ru/dbotthepony/mc/otm/client/screen/DriveViewerScreen.java deleted file mode 100644 index 5263dddf3..000000000 --- a/src/main/java/ru/dbotthepony/mc/otm/client/screen/DriveViewerScreen.java +++ /dev/null @@ -1,250 +0,0 @@ -package ru.dbotthepony.mc.otm.client.screen; - -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.TranslatableComponent; -import net.minecraft.world.entity.player.Inventory; -import net.minecraft.world.item.ItemStack; -import ru.dbotthepony.mc.otm.client.screen.panels.*; -import ru.dbotthepony.mc.otm.item.ItemPortableCondensationDrive; -import ru.dbotthepony.mc.otm.menu.DriveViewerMenu; -import ru.dbotthepony.mc.otm.network.MatteryNetworking; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.ArrayList; - -public class DriveViewerScreen extends MatteryScreen { - public static final int FRAME_WIDTH = 210; - public static final int FRAME_HEIGHT = 110; - - public static final int GRID_WIDTH = 9; - public static final int GRID_HEIGHT = 5; - - public DriveViewerScreen(DriveViewerMenu menu, Inventory inventory, Component title) { - super(menu, inventory, title); - } - - @Nullable - @Override - protected FramePanel makeMainFrame() { - var frame = new FramePanel(this, null, 0, 0, FRAME_WIDTH, FRAME_HEIGHT, getTitle()); - - var view_panels = new ArrayList(); - var settings_panels = new ArrayList(); - - var view_button = frame.addTab(FramePanel.FrameTabPosition.TOP); - var settings_button = frame.addTab(FramePanel.FrameTabPosition.TOP); - - view_button.bindOnOpen(() -> { - for (var panel : view_panels) { - panel.setVisible(true); - } - }); - - view_button.bindOnClose(() -> { - for (var panel : view_panels) { - panel.setVisible(false); - } - }); - - settings_button.bindOnOpen(() -> { - for (var panel : settings_panels) { - panel.setVisible(true); - } - }); - - settings_button.bindOnClose(() -> { - for (var panel : settings_panels) { - panel.setVisible(false); - } - }); - - var grid = new GridPanel(this, frame, 0, 0, 0, 0, GRID_WIDTH, GRID_HEIGHT); - grid.setDock(Dock.FILL); - grid.setDockMargin(2, 2, 2, 2); - - var scroll_bar = new ScrollBarPanel(this, frame, 0, 0, 0); - scroll_bar.setDock(Dock.RIGHT); - scroll_bar.setupRowMultiplier(() -> { - return menu.view.getItems().size() / GRID_WIDTH; - }); - - view_panels.add(grid); - view_panels.add(scroll_bar); - - for (int i = 0; i < GRID_WIDTH * GRID_HEIGHT; i++) { - final int index = i; - - new AbstractSlotPanel(this, grid, 0, 0) { - @Nonnull - @Override - protected ItemStack getItemStack() { - int findex = index + scroll_bar.getScroll(menu.view.getItems().size() / GRID_WIDTH); - - var list = menu.view.getItems(); - - if (findex >= list.size()) { - 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 mouse_click_type) { - int findex = index + scroll_bar.getScroll(GRID_WIDTH); - menu.view.mouseClick(findex, mouse_click_type); - - return true; - } - }; - } - - var dock_left = new FlexGridPanel(this, frame, 0, 0, 90, 0); - dock_left.setDock(Dock.LEFT); - dock_left.setDockMargin(4, 0, 4, 0); - - var grid_filter = new FlexGridPanel(this, frame); - grid_filter.setDock(Dock.FILL); - - settings_panels.add(dock_left); - settings_panels.add(grid_filter); - - for (int i = 0; i < ItemPortableCondensationDrive.FilterSettings.MAX_FILTERS; i++) { - final int index = i; - - new AbstractSlotPanel(this, grid_filter, 0, 0) { - @Nonnull - @Override - protected ItemStack getItemStack() { - var filter = menu.getFilter(); - - if (filter == null) - return ItemStack.EMPTY; - - return filter.items[index]; - } - - private boolean clicking = false; - - @Override - protected boolean mouseClickedInner(double mouse_x, double mouse_y, int flag) { - clicking = true; - return true; - } - - @Override - protected boolean mouseReleasedInner(double mouse_x, double mouse_y, int flag) { - if (clicking) - MatteryNetworking.send(null, new DriveViewerMenu.FilterSetPacket(menu.containerId, index, menu.getCarried())); - - clicking = false; - - return true; - } - }; - } - - final var no = new TranslatableComponent("otm.filter.no"); - final var yes = new TranslatableComponent("otm.filter.yes"); - - var match_nbt = new ButtonPanel(this, dock_left, 0, 0, 90, 20, new TranslatableComponent("otm.filter.match_nbt", no)) { - @Override - public void tick() { - super.tick(); - - var filter = menu.getFilter(); - - if (filter != null) { - getOrCreateWidget().setMessage(new TranslatableComponent("otm.filter.match_nbt", filter.matchNbt ? yes : no)); - getOrCreateWidget().active = !isWidgetDisabled(); - } else { - getOrCreateWidget().active = false; - } - } - - @Override - protected void onPress() { - super.onPress(); - - var filter = menu.getFilter(); - - if (filter != null) { - MatteryNetworking.send(null, new DriveViewerMenu.FilterSwitchPacket(menu.containerId, DriveViewerMenu.FilterSwitch.MATCH_NBT, !filter.matchNbt)); - disableFor(20); - } - } - }; - - var match_tag = new ButtonPanel(this, dock_left, 0, 0, 90, 20, new TranslatableComponent("otm.filter.match_tag", no)) { - @Override - public void tick() { - super.tick(); - - var filter = menu.getFilter(); - - if (filter != null) { - getOrCreateWidget().setMessage(new TranslatableComponent("otm.filter.match_tag", filter.matchTag ? yes : no)); - getOrCreateWidget().active = !isWidgetDisabled(); - } else { - getOrCreateWidget().active = false; - } - } - - @Override - protected void onPress() { - super.onPress(); - - var filter = menu.getFilter(); - - if (filter != null) { - MatteryNetworking.send(null, new DriveViewerMenu.FilterSwitchPacket(menu.containerId, DriveViewerMenu.FilterSwitch.MATCH_TAG, !filter.matchTag)); - disableFor(20); - } - } - }; - - var blacklist = new ButtonPanel(this, dock_left, 0, 0, 90, 20, new TranslatableComponent("otm.filter.blacklist", no)) { - @Override - public void tick() { - super.tick(); - - var filter = menu.getFilter(); - - if (filter != null) { - getOrCreateWidget().setMessage(new TranslatableComponent("otm.filter.blacklist", filter.isBlacklist ? yes : no)); - getOrCreateWidget().active = !isWidgetDisabled(); - } else { - getOrCreateWidget().active = false; - } - } - - @Override - protected void onPress() { - super.onPress(); - - var filter = menu.getFilter(); - - if (filter != null) { - MatteryNetworking.send(null, new DriveViewerMenu.FilterSwitchPacket(menu.containerId, DriveViewerMenu.FilterSwitch.BLACKLIST, !filter.isBlacklist)); - disableFor(20); - } - } - }; - - match_nbt.setDockMargin(0, 4, 0, 0); - match_tag.setDockMargin(0, 4, 0, 0); - blacklist.setDockMargin(0, 4, 0, 0); - - for (var panel : settings_panels) { - panel.setVisible(false); - } - - return frame; - } -} diff --git a/src/main/java/ru/dbotthepony/mc/otm/client/screen/MatteryScreen.java b/src/main/java/ru/dbotthepony/mc/otm/client/screen/MatteryScreen.java index 4771dc04b..b7f57143e 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/client/screen/MatteryScreen.java +++ b/src/main/java/ru/dbotthepony/mc/otm/client/screen/MatteryScreen.java @@ -115,11 +115,11 @@ public abstract class MatteryScreen extends AbstractConta this.menu = menu; playerInventoryTitle = inventory.getDisplayName(); - if (menu.inventory_slots.size() != 0) { + if (menu.inventorySlots.size() != 0) { inventory_frame = new FramePanel(this, null, 0, 0, INVENTORY_FRAME_WIDTH, INVENTORY_FRAME_HEIGHT, inventory.getDisplayName()); panels.add(inventory_frame); - for (var slot : menu.inventory_slots) { + for (var slot : menu.inventorySlots) { new SlotPanel<>( this, inventory_frame, @@ -359,10 +359,6 @@ public abstract class MatteryScreen extends AbstractConta if (main_frame != null) { addPanel(main_frame); - - for (var slot : menu.main_slots) { - new SlotPanel<>(this, main_frame, slot); - } } movePanels(); diff --git a/src/main/java/ru/dbotthepony/mc/otm/menu/DriveViewerMenu.java b/src/main/java/ru/dbotthepony/mc/otm/menu/DriveViewerMenu.java deleted file mode 100644 index 9384a7537..000000000 --- a/src/main/java/ru/dbotthepony/mc/otm/menu/DriveViewerMenu.java +++ /dev/null @@ -1,266 +0,0 @@ -package ru.dbotthepony.mc.otm.menu; - -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.world.SimpleContainer; -import net.minecraft.world.entity.player.Inventory; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraftforge.energy.CapabilityEnergy; -import net.minecraftforge.network.NetworkEvent; -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.IMatteryDrive; -import ru.dbotthepony.mc.otm.item.ItemPortableCondensationDrive; -import ru.dbotthepony.mc.otm.menu.data.INetworkedItemViewSupplier; -import ru.dbotthepony.mc.otm.menu.data.NetworkedItemView; -import ru.dbotthepony.mc.otm.storage.ItemStackWrapper; - -import javax.annotation.Nullable; -import java.util.function.Supplier; - -public class DriveViewerMenu extends PoweredMatteryMenu implements INetworkedItemViewSupplier { - public final NetworkedItemView view; - public MatterySlot drive_slot; - public IMatteryDrive last_drive; - - @Override - public NetworkedItemView getNetworkedItemView() { - return view; - } - - public DriveViewerMenu(int containerID, Inventory inventory) { - this(containerID, inventory, null); - } - - public DriveViewerMenu(int containerID, Inventory inventory, @Nullable BlockEntityDriveViewer tile) { - super(Registry.Menus.DRIVE_VIEWER, containerID, inventory, tile); - - var container = tile != null ? tile.drive_slot : new SimpleContainer(1); - - drive_slot = new MatterySlot(container, 0) { - @Override - public boolean mayPlace(ItemStack stack) { - return stack.getCapability(MatteryCapability.DRIVE).isPresent(); - } - }; - - view = new NetworkedItemView(inventory.player, this, tile == null) { - @Override - public int calculateIOAmount(int desired_amount) { - if (tile != null) - return tile.getIOItemCount(desired_amount, true); - - return super.calculateIOAmount(desired_amount); - } - - @Override - public void doneIOAmount(int done_amount) { - if (tile != null) { - tile.getIOItemCount(done_amount, false); - return; - } - - super.doneIOAmount(done_amount); - } - }; - - addSlot(drive_slot); - addBatterySlot(); - addInventorySlots(); - } - - @Override - @SuppressWarnings("unchecked") - public void broadcastChanges() { - super.broadcastChanges(); - - if (tile != null) { - var get = ((BlockEntityDriveViewer) tile).drive_slot.getItem(0); - - if (get.isEmpty()) { - last_drive = null; - } else { - var get_cap = get.getCapability(MatteryCapability.DRIVE).resolve(); - - if (get_cap.isEmpty() || get_cap.get().storageIdentity() != ItemStackWrapper.class) { - last_drive = null; - } else { - last_drive = (IMatteryDrive) get_cap.get(); - } - } - - view.setComponent(last_drive); - view.network(); - } - } - - @Override - protected int getWorkingSlotStart() { - return 0; - } - - @Override - 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(); - } - } - - @Override - public ItemStack quickMoveStack(Player ply, int slot_index) { - var slot = slots.get(slot_index); - var item = slot.getItem(); - - if (item.isEmpty() || item.getCapability(MatteryCapability.DRIVE).isPresent() || item.getCapability(CapabilityEnergy.ENERGY).isPresent()) - return super.quickMoveStack(ply, slot_index); - - if (last_drive == null || tile == null) - return ItemStack.EMPTY; - - var tile = (BlockEntityDriveViewer) this.tile; - int amount = tile.getIOItemCount(item.getCount(), true); - - if (amount == 0) - return ItemStack.EMPTY; - - if (amount == item.getCount()) { - var remaining = last_drive.insertStack(new ItemStackWrapper(item), false); - - if (remaining.getCount().toInt() == item.getCount()) - return ItemStack.EMPTY; - - if (remaining.isEmpty()) { - var copy = item.copy(); - slot.set(ItemStack.EMPTY); - tile.getIOItemCount(item.getCount(), false); - return copy; - } - - var copy = item.copy(); - tile.getIOItemCount(item.getCount() - remaining.getCount().toInt(), false); - item.shrink(remaining.getCount().toInt()); - slot.setChanged(); - - return copy; - } - - var copy_insert = item.copy(); - copy_insert.setCount(amount); - - var remaining = last_drive.insertStack(new ItemStackWrapper(copy_insert), false); - - if (remaining.getCount().toInt() == copy_insert.getCount()) - return ItemStack.EMPTY; - - var copy = item.copy(); - tile.getIOItemCount(amount - remaining.getCount().toInt(), false); - item.shrink(amount - remaining.getCount().toInt()); - slot.setChanged(); - - return copy; - } - - public enum FilterSwitch { - MATCH_NBT, - MATCH_TAG, - BLACKLIST - } - - public ItemPortableCondensationDrive.FilterSettings getFilter() { - if (drive_slot.getItem().isEmpty()) - return null; - - if (drive_slot.getItem().getItem() instanceof ItemPortableCondensationDrive item) - return item.getFilterSettings(drive_slot.getItem()); - - return null; - } - - public record FilterSetPacket(int id, int slot, ItemStack value) { - public void write(FriendlyByteBuf buffer) { - buffer.writeInt(id); - buffer.writeInt(slot); - buffer.writeItem(value); - } - - public static FilterSetPacket read(FriendlyByteBuf buffer) { - return new FilterSetPacket(buffer.readInt(), buffer.readInt(), buffer.readItem()); - } - - public void play(Supplier context) { - context.get().setPacketHandled(true); - - if (slot < 0 || slot >= ItemPortableCondensationDrive.FilterSettings.MAX_FILTERS) - return; - - if (value.getCount() > 1) - value.setCount(1); - - context.get().enqueueWork(() -> { - var ply = context.get().getSender(); - - if (ply.containerMenu instanceof DriveViewerMenu menu && menu.containerId == id) { - if (menu.drive_slot.getItem().isEmpty()) - return; - - if (menu.drive_slot.getItem().getItem() instanceof ItemPortableCondensationDrive drive) { - var filter = drive.getFilterSettings(menu.drive_slot.getItem()); - filter.items[slot] = value; - filter.serializeNBT(menu.drive_slot.getItem()); - } - } - }); - } - } - - public record FilterSwitchPacket(int id, FilterSwitch type, boolean value) { - public void write(FriendlyByteBuf buffer) { - buffer.writeInt(id); - buffer.writeEnum(type); - buffer.writeBoolean(value); - } - - public static FilterSwitchPacket read(FriendlyByteBuf buffer) { - return new FilterSwitchPacket(buffer.readInt(), buffer.readEnum(FilterSwitch.class), buffer.readBoolean()); - } - - public void play(Supplier context) { - context.get().setPacketHandled(true); - context.get().enqueueWork(() -> { - var ply = context.get().getSender(); - - if (ply.containerMenu instanceof DriveViewerMenu menu && menu.containerId == id) { - var settings = menu.getFilter(); - - if (settings == null) - return; - - switch (type) { - case MATCH_NBT -> { - settings.matchNbt = value; - } - - case MATCH_TAG -> { - settings.matchTag = value; - } - - case BLACKLIST -> { - settings.isBlacklist = value; - } - } - - settings.serializeNBT(menu.drive_slot.getItem()); - } - }); - } - } -} 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 a4fbd666e..000000000 --- a/src/main/java/ru/dbotthepony/mc/otm/menu/data/NetworkedItemView.java +++ /dev/null @@ -1,293 +0,0 @@ -package ru.dbotthepony.mc.otm.menu.data; - -import com.mojang.blaze3d.platform.InputConstants; -import net.minecraft.MethodsReturnNonnullByDefault; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.inventory.ClickAction; -import net.minecraft.world.inventory.ClickType; -import net.minecraft.world.item.ItemStack; -import net.minecraftforge.network.PacketDistributor; -import ru.dbotthepony.mc.otm.core.Fraction; -import ru.dbotthepony.mc.otm.menu.MatteryMenu; -import ru.dbotthepony.mc.otm.network.MatteryNetworking; -import ru.dbotthepony.mc.otm.network.SetCarriedPacket; -import ru.dbotthepony.mc.otm.storage.*; - -import javax.annotation.Nullable; -import javax.annotation.ParametersAreNonnullByDefault; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.UUID; - -import static net.minecraft.client.gui.screens.Screen.hasShiftDown; - -/** - * Creates a virtual, slotless container for Player's interaction with. - */ - -@MethodsReturnNonnullByDefault -@ParametersAreNonnullByDefault -public class NetworkedItemView implements IStorageListener { - public final boolean remote; - public final MatteryMenu menu; - public final Player ply; - - 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<>(); - - @Nullable - public NetworkedItem get(int id) { - return state.get(id); - } - - private List view_cache; - - protected IStorageComponent provider; - - public NetworkedItemView(Player ply, MatteryMenu menu, boolean remote) { - this.remote = remote; - this.menu = menu; - this.ply = ply; - } - - public void mouseClick(int index, int mouse_click_type) { - var list = getItems(); - var action = mouse_click_type == InputConstants.MOUSE_BUTTON_LEFT ? ClickAction.PRIMARY : ClickAction.SECONDARY; - var type = mouse_click_type == InputConstants.MOUSE_BUTTON_MIDDLE ? ClickType.CLONE : hasShiftDown() ? ClickType.QUICK_MOVE : ClickType.PICKUP; - - MatteryNetworking.send(null, new InteractPacket(menu.containerId, index >= list.size() ? -1 : list.get(index).id(), type, action)); - } - - public void setComponent(@Nullable IStorageComponent provider) { - if (provider == this.provider) - return; - - if (this.provider != null) - this.provider.removeListenerAuto(this); - - this.provider = provider; - - if (provider != null) - provider.addListenerAuto(this); - } - - public void removed() { - if (this.provider != null) - this.provider.removeListenerAuto(this); - } - - public record NetworkedItem(int id, ItemStack stack, @Nullable UUID id_upstream) { - public NetworkedItem(int id, ItemStack stack) { - this(id, stack, null); - } - } - - 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 addObject(ItemStackWrapper stack, UUID id, IStorageView provider) { - addObject(stack.stack(), id); - } - - @Override - public void changeObject(UUID id, Fraction newCount) { - changeObject(id, newCount.toInt()); - } - - @Override - public void removeObject(UUID id) { - var get = upstream_state.get(id); - - if (get == null) - throw new IllegalStateException("Unknown ItemStack with upstream id " + id + "!"); - - upstream_state.remove(id); - state.remove(get.id); - - if (!remote) { - backlog.add(new StackRemovePacket(menu.containerId, get.id)); - } - - clearCache(); - } - - public void addObject(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 (!remote) { - backlog.add(new StackAddPacket(menu.containerId, state.id, stack)); - } - - clearCache(); - } - - public void changeObject(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(menu.containerId, get.id, new_count)); - } - - clearCache(); - } - - public void clear() { - clearCache(); - upstream_state.clear(); - state.clear(); - - if (!remote) { - backlog.clear(); - backlog.add(new ClearPacket(menu.containerId)); - } - } - - 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(); - } - - public int calculateIOAmount(int desired_amount) { - return desired_amount; - } - - public void doneIOAmount(int done_amount) { - - } - - public void playerInteract(InteractPacket packet) { - if (provider == null) - return; - - var click = packet.click(); - var action = packet.action(); - var stack_id = packet.stack_id(); - - if (click == ClickType.CLONE) { - if (stack_id < 0 || !ply.getAbilities().instabuild) - return; - - var get_state = get(stack_id); - - if (get_state == null) { - return; - } - - var copy = get_state.stack().copy(); - copy.setCount(Math.min(copy.getCount(), copy.getMaxStackSize())); - - ply.containerMenu.setCarried(copy); - MatteryNetworking.send((ServerPlayer) ply, new SetCarriedPacket(ply.containerMenu.getCarried())); - ply.containerMenu.setRemoteCarried(ply.containerMenu.getCarried().copy()); - return; - } - - if (click == ClickType.QUICK_MOVE && stack_id > -1) { - var get_state = get(stack_id); - - if (get_state == null) { - return; - } - - int amount = calculateIOAmount(action == ClickAction.PRIMARY ? get_state.stack().getMaxStackSize() : Math.max(1, get_state.stack().getMaxStackSize() / 2)); - var extracted = provider.extractStack(get_state.id_upstream(), new Fraction(amount), true); - - if (!extracted.isEmpty()) { - var move = menu.quickMoveToInventory(extracted.stack(), false); - - if (move.remaining().getCount() != extracted.stack().getCount()) { - provider.extractStack(get_state.id_upstream(), new Fraction(extracted.stack().getCount() - move.remaining().getCount()), false); - doneIOAmount(extracted.stack().getCount() - move.remaining().getCount()); - } - } - - return; - } - - if (!menu.getCarried().isEmpty() && click != ClickType.QUICK_MOVE) { - // try to put - if (action == ClickAction.PRIMARY) { - var carried = menu.getCarried(); - int amount = calculateIOAmount(carried.getCount()); - - if (amount == carried.getCount()) { - var leftover = provider.insertStack(new ItemStackWrapper(menu.getCarried()), false); - menu.setCarried(leftover.stack()); - doneIOAmount(amount - leftover.stack().getCount()); - - MatteryNetworking.send((ServerPlayer) ply, new SetCarriedPacket(menu.getCarried())); - menu.setRemoteCarried(menu.getCarried().copy()); - } else if (amount != 0) { - var copy = carried.copy(); - copy.setCount(amount); - - var leftover = provider.insertStack(new ItemStackWrapper(copy), false); - doneIOAmount(amount - leftover.stack().getCount()); - - leftover.setCount(carried.getCount() - amount + leftover.getCountInt()); - menu.setCarried(leftover.stack()); - - MatteryNetworking.send((ServerPlayer) ply, new SetCarriedPacket(menu.getCarried())); - menu.setRemoteCarried(menu.getCarried().copy()); - } - } else { - var copy = menu.getCarried().copy(); - copy.setCount(1); - - if (calculateIOAmount(1) == 1 && provider.insertStack(new ItemStackWrapper(copy), false).isEmpty()) { - menu.getCarried().shrink(1); - doneIOAmount(1); - MatteryNetworking.send((ServerPlayer) ply, new SetCarriedPacket(menu.getCarried())); - menu.setRemoteCarried(menu.getCarried().copy()); - } - } - } else if (stack_id > -1) { - var get_state = get(stack_id); - - if (get_state == null) { - return; - } - - int amount = calculateIOAmount(action == ClickAction.PRIMARY ? get_state.stack().getMaxStackSize() : Math.max(1, get_state.stack().getMaxStackSize() / 2)); - - var extracted = provider.extractStack(get_state.id_upstream(), new Fraction(amount), false); - - doneIOAmount(extracted.getCountInt()); - menu.setCarried(extracted.stack()); - MatteryNetworking.send((ServerPlayer) ply, new SetCarriedPacket(menu.getCarried())); - menu.setRemoteCarried(menu.getCarried().copy()); - } - } -} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/BlockDriveViewer.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/BlockDriveViewer.kt index b967af2a2..90757c61a 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/BlockDriveViewer.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/BlockDriveViewer.kt @@ -1,45 +1,42 @@ -package ru.dbotthepony.mc.otm.block; +package ru.dbotthepony.mc.otm.block -import net.minecraft.MethodsReturnNonnullByDefault; -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.EntityBlock; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.entity.BlockEntityTicker; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.StateDefinition; -import net.minecraft.world.level.block.state.properties.BooleanProperty; -import ru.dbotthepony.mc.otm.Registry; -import ru.dbotthepony.mc.otm.block.entity.BlockEntityDriveViewer; +import net.minecraft.core.BlockPos +import net.minecraft.world.level.Level +import net.minecraft.world.level.block.Block +import net.minecraft.world.level.block.EntityBlock +import net.minecraft.world.level.block.entity.BlockEntity +import net.minecraft.world.level.block.entity.BlockEntityTicker +import net.minecraft.world.level.block.entity.BlockEntityType +import net.minecraft.world.level.block.state.BlockState +import net.minecraft.world.level.block.state.StateDefinition +import net.minecraft.world.level.block.state.properties.BooleanProperty +import ru.dbotthepony.mc.otm.Registry +import ru.dbotthepony.mc.otm.block.entity.BlockEntityDriveViewer +import ru.dbotthepony.mc.otm.block.entity.worker.WorkerState -import javax.annotation.Nullable; -import javax.annotation.ParametersAreNonnullByDefault; - -import static ru.dbotthepony.mc.otm.block.entity.worker.WorkerState.SEMI_WORKER_STATE; - -@MethodsReturnNonnullByDefault -@ParametersAreNonnullByDefault -public class BlockDriveViewer extends BlockMatteryRotatable implements EntityBlock { - @Nullable - @Override - public BlockEntity newBlockEntity(BlockPos blockPos, BlockState blockState) { - return new BlockEntityDriveViewer(blockPos, blockState); +class BlockDriveViewer : BlockMatteryRotatable(), EntityBlock { + override fun newBlockEntity(blockPos: BlockPos, blockState: BlockState): BlockEntity { + return BlockEntityDriveViewer(blockPos, blockState) } - @Nullable - @Override - public BlockEntityTicker getTicker(Level p_153212_, BlockState p_153213_, BlockEntityType p_153214_) { - return p_153212_.isClientSide || p_153214_ != Registry.BlockEntities.DRIVE_VIEWER ? null : BlockEntityDriveViewer::ticker; + override fun getTicker( + p_153212_: Level, + p_153213_: BlockState, + p_153214_: BlockEntityType + ): BlockEntityTicker? { + if (p_153212_.isClientSide || p_153214_ !== Registry.BlockEntities.DRIVE_VIEWER) + return null + + return BlockEntityTicker { _, _, _, tile -> if (tile is BlockEntityDriveViewer) tile.tick() } } - public static final BooleanProperty DRIVE_PRESENT = BooleanProperty.create("drive"); + override fun createBlockStateDefinition(builder: StateDefinition.Builder) { + super.createBlockStateDefinition(builder) + builder.add(WorkerState.SEMI_WORKER_STATE) + builder.add(DRIVE_PRESENT) + } - @Override - protected void createBlockStateDefinition(StateDefinition.Builder builder) { - super.createBlockStateDefinition(builder); - builder.add(SEMI_WORKER_STATE); - builder.add(DRIVE_PRESENT); + companion object { + val DRIVE_PRESENT = BooleanProperty.create("drive") } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BlockEntityDriveViewer.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BlockEntityDriveViewer.kt index b4568ebc8..2334bc957 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BlockEntityDriveViewer.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BlockEntityDriveViewer.kt @@ -1,137 +1,113 @@ -package ru.dbotthepony.mc.otm.block.entity; +package ru.dbotthepony.mc.otm.block.entity -import net.minecraft.MethodsReturnNonnullByDefault; -import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.TranslatableComponent; -import net.minecraft.world.entity.player.Inventory; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.inventory.AbstractContainerMenu; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.state.BlockState; -import ru.dbotthepony.mc.otm.OverdriveThatMatters; -import ru.dbotthepony.mc.otm.Registry; -import ru.dbotthepony.mc.otm.block.BlockDriveViewer; -import ru.dbotthepony.mc.otm.block.entity.worker.WorkerState; -import ru.dbotthepony.mc.otm.capability.MatteryCapability; -import ru.dbotthepony.mc.otm.capability.MatteryMachineEnergyStorage; -import ru.dbotthepony.mc.otm.container.MatteryContainer; -import ru.dbotthepony.mc.otm.core.Fraction; -import ru.dbotthepony.mc.otm.menu.DriveViewerMenu; - -import javax.annotation.Nullable; -import javax.annotation.ParametersAreNonnullByDefault; +import net.minecraft.MethodsReturnNonnullByDefault +import net.minecraft.core.BlockPos +import net.minecraft.nbt.CompoundTag +import net.minecraft.network.chat.Component +import net.minecraft.network.chat.TranslatableComponent +import net.minecraft.world.entity.player.Inventory +import net.minecraft.world.entity.player.Player +import net.minecraft.world.inventory.AbstractContainerMenu +import net.minecraft.world.item.ItemStack +import net.minecraft.world.level.Level +import net.minecraft.world.level.block.Block +import net.minecraft.world.level.block.state.BlockState +import ru.dbotthepony.mc.otm.OverdriveThatMatters +import ru.dbotthepony.mc.otm.Registry +import ru.dbotthepony.mc.otm.block.BlockDriveViewer +import ru.dbotthepony.mc.otm.block.entity.worker.WorkerState +import ru.dbotthepony.mc.otm.capability.MatteryCapability +import ru.dbotthepony.mc.otm.capability.MatteryMachineEnergyStorage +import ru.dbotthepony.mc.otm.container.MatteryContainer +import ru.dbotthepony.mc.otm.core.Fraction +import ru.dbotthepony.mc.otm.ifHas +import ru.dbotthepony.mc.otm.menu.DriveViewerMenu +import ru.dbotthepony.mc.otm.set +import javax.annotation.ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault @ParametersAreNonnullByDefault -public class BlockEntityDriveViewer extends BlockEntityMatteryPowered { - public static final Fraction MTE_PER_OPERATION = new Fraction("3.125"); +class BlockEntityDriveViewer(p_155229_: BlockPos, p_155230_: BlockState) : BlockEntityMatteryPowered(Registry.BlockEntities.DRIVE_VIEWER, p_155229_, p_155230_) { + override fun setChanged() { + super.setChanged() - public boolean canIOItems() { - return energy.getBatteryLevel().compareTo(MTE_PER_OPERATION) >= 0; - } + val level = level - private void updateState(Level level) { - if (isRemoved()) - return; + if (level != null) { + OverdriveThatMatters.tickOnceSelf(level) { + if (isRemoved) return@tickOnceSelf - var state = getBlockState(); + var state = blockState - if (drive_slot.getItem(0).getCapability(MatteryCapability.DRIVE).isPresent() && canIOItems()) { - state = state.setValue(WorkerState.SEMI_WORKER_STATE, WorkerState.WORKING); - } else { - state = state.setValue(WorkerState.SEMI_WORKER_STATE, WorkerState.IDLE); - } + if (drive_slot.getItem(0).getCapability(MatteryCapability.DRIVE).isPresent && energy.batteryLevel >= OverdriveThatMatters.ITEM_STORAGE.energyPerOperation()) { + state = state.setValue(WorkerState.SEMI_WORKER_STATE, WorkerState.WORKING) + } else { + state = state.setValue(WorkerState.SEMI_WORKER_STATE, WorkerState.IDLE) + } - if (state != getBlockState()) { - level.setBlock(getBlockPos(), state, Block.UPDATE_CLIENTS); + if (state !== blockState) { + it.setBlock(blockPos, state, Block.UPDATE_CLIENTS) + } + } } } - @Override - public void setChanged() { - super.setChanged(); + @JvmField + val drive_slot: MatteryContainer = object : MatteryContainer(this::setChanged, 1) { + override fun setChanged(slot: Int, new_state: ItemStack, old_state: ItemStack) { + super.setChanged(slot, new_state, old_state) - if (level != null) - OverdriveThatMatters.tickOnceSelf(level, this::updateState); - } + val level = level + if (level != null) { + OverdriveThatMatters.tickOnceSelf(level) { + if (!isRemoved) { + var state = blockState - public int getIOItemCount(int desired, boolean simulate) { - if (!canIOItems()) - return 0; - - var extracted = energy.extractEnergyInner(MTE_PER_OPERATION.times(desired), true); - var modulo = extracted.rem(MTE_PER_OPERATION); - - if (simulate) - return modulo.toInt(); - - energy.extractEnergyInner(modulo.times(MTE_PER_OPERATION), false); - - return modulo.toInt(); - } - - public BlockEntityDriveViewer(BlockPos p_155229_, BlockState p_155230_) { - super(Registry.BlockEntities.DRIVE_VIEWER, p_155229_, p_155230_); - energy = new MatteryMachineEnergyStorage(this, MatteryMachineEnergyStorage.MachineType.WORKER, new Fraction(30_000)); - } - - private static final TranslatableComponent NAME = new TranslatableComponent("block.overdrive_that_matters.drive_viewer"); - - public final MatteryContainer drive_slot = new MatteryContainer(this::setChanged, 1) { - @Override - public void setChanged(int slot, ItemStack new_state, ItemStack old_state) { - super.setChanged(slot, new_state, old_state); - - if (level != null) - OverdriveThatMatters.tickOnceSelf(level, (level) -> { - if (!isRemoved()) { - var state = getBlockState(); - - if (new_state.getCapability(MatteryCapability.DRIVE).isPresent()) { - state = state.setValue(BlockDriveViewer.DRIVE_PRESENT, true); + if (new_state.getCapability(MatteryCapability.DRIVE).isPresent) { + state = state.setValue(BlockDriveViewer.DRIVE_PRESENT, true) } else { - state = state.setValue(BlockDriveViewer.DRIVE_PRESENT, false); + state = state.setValue(BlockDriveViewer.DRIVE_PRESENT, false) } - if (state != getBlockState()) { - level.setBlock(getBlockPos(), state, Block.UPDATE_CLIENTS); + if (state !== blockState) { + level.setBlock(blockPos, state, Block.UPDATE_CLIENTS) } } - }); - } - }; - - @Override - protected Component getDefaultDisplayName() { - return NAME; - } - - @Nullable - @Override - public AbstractContainerMenu createMenu(int containerID, Inventory inventory, Player ply) { - return new DriveViewerMenu(containerID, inventory, this); - } - - @Override - public void saveAdditional(CompoundTag nbt) { - super.saveAdditional(nbt); - nbt.put("drive_slot", drive_slot.serializeNBT()); - } - - @Override - public void load(CompoundTag nbt) { - super.load(nbt); - drive_slot.deserializeNBT(nbt.get("drive_slot")); - } - - public static void ticker(Level level, BlockPos blockPos, BlockState blockState, T t) { - if (t instanceof BlockEntityDriveViewer tile) { - tile.batteryChargeLoop(); + } + } } } -} + + init { + energy = MatteryMachineEnergyStorage(this, MatteryMachineEnergyStorage.MachineType.WORKER, Fraction(30000)) + } + + override fun getDefaultDisplayName(): Component { + return NAME + } + + override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu? { + return DriveViewerMenu(containerID, inventory, this) + } + + override fun saveAdditional(nbt: CompoundTag) { + super.saveAdditional(nbt) + nbt["drive_slot"] = drive_slot.serializeNBT() + } + + override fun load(nbt: CompoundTag) { + super.load(nbt) + + nbt.ifHas("drive_slot") { + drive_slot.deserializeNBT(it) + } + } + + fun tick() { + batteryChargeLoop() + } + + companion object { + private val NAME = TranslatableComponent("block.overdrive_that_matters.drive_viewer") + } +} \ No newline at end of file diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/DriveViewerScreen.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/DriveViewerScreen.kt new file mode 100644 index 000000000..47dc5a097 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/DriveViewerScreen.kt @@ -0,0 +1,233 @@ +package ru.dbotthepony.mc.otm.client.screen + +import net.minecraft.network.chat.Component +import net.minecraft.network.chat.TranslatableComponent +import net.minecraft.world.entity.player.Inventory +import net.minecraft.world.item.ItemStack +import ru.dbotthepony.mc.otm.client.screen.panels.* +import ru.dbotthepony.mc.otm.client.screen.widget.PowerGaugePanel +import ru.dbotthepony.mc.otm.item.ItemPortableCondensationDrive.FilterSettings +import ru.dbotthepony.mc.otm.menu.DriveViewerMenu +import ru.dbotthepony.mc.otm.menu.DriveViewerMenu.FilterSetPacket +import ru.dbotthepony.mc.otm.menu.DriveViewerMenu.FilterSwitchPacket +import ru.dbotthepony.mc.otm.network.MatteryNetworking + +class DriveViewerScreen(menu: DriveViewerMenu, inventory: Inventory, title: Component) : + MatteryScreen(menu, inventory, title) { + + override fun makeMainFrame(): FramePanel { + val frame = FramePanel(this, null, 0f, 0f, FRAME_WIDTH, FRAME_HEIGHT, getTitle()) + + val views = ArrayList() + val settings = ArrayList() + val viewButton = frame.addTab(FramePanel.FrameTabPosition.TOP) + val settingsButton = frame.addTab(FramePanel.FrameTabPosition.TOP) + + viewButton.bindOnOpen { + for (panel in views) { + panel.visible = true + } + } + + viewButton.bindOnClose { + for (panel in views) { + panel.visible = false + } + } + + settingsButton.bindOnOpen { + for (panel in settings) { + panel.visible = true + } + } + + settingsButton.bindOnClose { + for (panel in settings) { + panel.visible = false + } + } + + views.add(PowerGaugePanel(this, frame, menu.battery_widget, 8f, 16f)) + views.add(SlotPanel(this, frame, menu.battery_slot, 8f, 67f)) + views.add(SlotPanel(this, frame, menu.driveSlot, 8f, 85f)) + + val grid = GridPanel(this, frame, 28f, 16f, GRID_WIDTH * 18f, GRID_HEIGHT * 18f, GRID_WIDTH, GRID_HEIGHT) + + val scroll_bar = ScrollBarPanel(this, frame, 192f, 14f, 92f) + scroll_bar.setupRowMultiplier { menu.view.getItemCount() / GRID_WIDTH } + views.add(grid) + views.add(scroll_bar) + + for (i in 0 until GRID_WIDTH * GRID_HEIGHT) { + object : AbstractSlotPanel(this@DriveViewerScreen, grid, 0f, 0f) { + override fun getItemStack(): ItemStack { + val index = i + scroll_bar.getScroll(menu.view.getItems().size / GRID_WIDTH) + val list = menu.view.getItems() + + return if (index >= list.size) { + ItemStack.EMPTY + } else list[index].stack + } + + override fun mouseScrolledInner(mouse_x: Double, mouse_y: Double, scroll: Double): Boolean { + return scroll_bar.mouseScrolledInner(mouse_x, mouse_y, scroll) + } + + override fun mouseClickedInner(mouse_x: Double, mouse_y: Double, mouse_click_type: Int): Boolean { + val index = i + scroll_bar.getScroll(GRID_WIDTH) + menu.view.mouseClick(index, mouse_click_type) + return true + } + } + } + + val dock_left = FlexGridPanel(this, frame, 0f, 0f, 90f, 0f) + dock_left.dock = Dock.LEFT + dock_left.setDockMargin(4f, 0f, 4f, 0f) + + val grid_filter = FlexGridPanel(this, frame) + grid_filter.dock = Dock.FILL + settings.add(dock_left) + settings.add(grid_filter) + + for (i in 0 until FilterSettings.MAX_FILTERS) { + object : AbstractSlotPanel(this@DriveViewerScreen, grid_filter, 0f, 0f) { + override fun getItemStack(): ItemStack { + val filter = menu.getFilter() ?: return ItemStack.EMPTY + return filter.items[i] + } + + private var clicking = false + + override fun mouseClickedInner(mouse_x: Double, mouse_y: Double, mouse_click_type: Int): Boolean { + clicking = true + return true + } + + override fun mouseReleasedInner(mouse_x: Double, mouse_y: Double, flag: Int): Boolean { + if (clicking) + MatteryNetworking.send(null, FilterSetPacket(menu.containerId, i, menu.carried)) + + clicking = false + return true + } + } + } + + val no = TranslatableComponent("otm.filter.no") + val yes = TranslatableComponent("otm.filter.yes") + + val matchNbt = + object : ButtonPanel(this@DriveViewerScreen, dock_left, 0f, 0f, 90f, 20f, TranslatableComponent("otm.filter.match_nbt", no)) { + override fun tick() { + super.tick() + + val filter = menu.getFilter() + if (filter != null) { + orCreateWidget.message = TranslatableComponent("otm.filter.match_nbt", if (filter.matchNbt) yes else no) + orCreateWidget.active = !isWidgetDisabled + } else { + orCreateWidget.active = false + } + } + + override fun onPress() { + super.onPress() + + val filter = menu.getFilter() + if (filter != null) { + MatteryNetworking.send( + null, + FilterSwitchPacket( + menu.containerId, + DriveViewerMenu.FilterSwitch.MATCH_NBT, + !filter.matchNbt + ) + ) + disableFor(20) + } + } + } + + val matchTag = + object : ButtonPanel(this@DriveViewerScreen, dock_left, 0f, 0f, 90f, 20f, TranslatableComponent("otm.filter.match_tag", no)) { + override fun tick() { + super.tick() + + val filter = menu.getFilter() + if (filter != null) { + orCreateWidget.message = + TranslatableComponent("otm.filter.match_tag", if (filter.matchTag) yes else no) + orCreateWidget.active = !isWidgetDisabled + } else { + orCreateWidget.active = false + } + } + + override fun onPress() { + super.onPress() + + val filter = menu.getFilter() + if (filter != null) { + MatteryNetworking.send( + null, + FilterSwitchPacket( + menu.containerId, + DriveViewerMenu.FilterSwitch.MATCH_TAG, + !filter.matchTag + ) + ) + disableFor(20) + } + } + } + + val blacklist = + object : ButtonPanel(this@DriveViewerScreen, dock_left, 0f, 0f, 90f, 20f, TranslatableComponent("otm.filter.blacklist", no)) { + override fun tick() { + super.tick() + + val filter = menu.getFilter() + if (filter != null) { + orCreateWidget.message = TranslatableComponent("otm.filter.blacklist", if (filter.isBlacklist) yes else no) + orCreateWidget.active = !isWidgetDisabled + } else { + orCreateWidget.active = false + } + } + + override fun onPress() { + super.onPress() + val filter = menu.getFilter() + if (filter != null) { + MatteryNetworking.send( + null, + FilterSwitchPacket( + menu.containerId, + DriveViewerMenu.FilterSwitch.BLACKLIST, + !filter.isBlacklist + ) + ) + disableFor(20) + } + } + } + + matchNbt.setDockMargin(0f, 4f, 0f, 0f) + matchTag.setDockMargin(0f, 4f, 0f, 0f) + blacklist.setDockMargin(0f, 4f, 0f, 0f) + + for (panel in settings) { + panel.visible = false + } + + return frame + } + + companion object { + const val FRAME_WIDTH = 210f + const val FRAME_HEIGHT = 110f + const val GRID_WIDTH = 9 + const val GRID_HEIGHT = 5 + } +} \ No newline at end of file diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/ItemMonitorScreen.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/ItemMonitorScreen.kt index a53a0c854..6dc016ef0 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/ItemMonitorScreen.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/ItemMonitorScreen.kt @@ -17,16 +17,16 @@ class ItemMonitorScreen(menu: ItemMonitorMenu, inventory: Inventory, title: Comp SlotPanel(this, frame, menu.battery_slot, 8f, 80f) val scrollBar = ScrollBarPanel(this, frame, 192f, 14f, 92f) - scrollBar.setupRowMultiplier { menu.view.items.size / GRID_WIDTH } + scrollBar.setupRowMultiplier { menu.view.getItemCount() / GRID_WIDTH } val gridPanel = GridPanel(this, frame, 28f, 16f, GRID_WIDTH * 18f, GRID_HEIGHT * 18f, GRID_WIDTH, GRID_HEIGHT) for (i in 0 until GRID_WIDTH * GRID_HEIGHT) { object : AbstractSlotPanel(this@ItemMonitorScreen, gridPanel) { override fun getItemStack(): ItemStack { - val index = i + scrollBar.getScroll(menu.view.items.size / GRID_WIDTH) - val list = menu.view.items - return if (index >= list.size) ItemStack.EMPTY else list[index].stack() + val index = i + scrollBar.getScroll(menu.view.getItemCount() / GRID_WIDTH) + val list = menu.view.getItems() + return if (index >= list.size) ItemStack.EMPTY else list[index].stack } override fun mouseScrolledInner(mouse_x: Double, mouse_y: Double, scroll: Double): Boolean { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/DriveViewerMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/DriveViewerMenu.kt new file mode 100644 index 000000000..e67e16f72 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/DriveViewerMenu.kt @@ -0,0 +1,241 @@ +package ru.dbotthepony.mc.otm.menu + +import net.minecraft.network.FriendlyByteBuf +import net.minecraft.world.SimpleContainer +import net.minecraft.world.entity.player.Inventory +import net.minecraft.world.entity.player.Player +import net.minecraft.world.item.ItemStack +import net.minecraftforge.energy.CapabilityEnergy +import net.minecraftforge.network.NetworkEvent +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.IMatteryDrive +import ru.dbotthepony.mc.otm.item.ItemPortableCondensationDrive +import ru.dbotthepony.mc.otm.item.ItemPortableCondensationDrive.FilterSettings +import ru.dbotthepony.mc.otm.menu.data.INetworkedItemViewSupplier +import ru.dbotthepony.mc.otm.menu.data.NetworkedItemView +import ru.dbotthepony.mc.otm.storage.ItemStackWrapper +import ru.dbotthepony.mc.otm.storage.PoweredVirtualComponent +import java.util.function.Supplier + +class DriveViewerMenu @JvmOverloads constructor( + containerID: Int, + inventory: Inventory, + tile: BlockEntityDriveViewer? = null +) : PoweredMatteryMenu( + Registry.Menus.DRIVE_VIEWER, containerID, inventory, tile +), INetworkedItemViewSupplier { + @JvmField val view: NetworkedItemView + private val powered: PoweredVirtualComponent? + @JvmField val driveSlot: MatterySlot + private var lastDrive: IMatteryDrive? = null + + override fun getNetworkedItemView() = view + + init { + val container = if (tile != null) tile.drive_slot else SimpleContainer(1) + + driveSlot = object : MatterySlot(container, 0) { + override fun mayPlace(stack: ItemStack): Boolean { + return stack.getCapability(MatteryCapability.DRIVE).isPresent + } + } + + view = NetworkedItemView(inventory.player, this, tile == null) + + if (tile != null) { + powered = PoweredVirtualComponent( + ItemStackWrapper::class.java, + tile.getCapability(MatteryCapability.ENERGY).resolve().get() + ) + + view.setComponent(powered) + } else { + powered = null + } + + addSlot(driveSlot) + addBatterySlot() + addInventorySlots() + } + + override fun broadcastChanges() { + super.broadcastChanges() + + if (tile != null) { + val itemStack = (tile as BlockEntityDriveViewer).drive_slot.getItem(0) + + val prev = lastDrive + lastDrive = null + + if (!itemStack.isEmpty) { + itemStack.getCapability(MatteryCapability.DRIVE).ifPresent { + if (it.storageIdentity() == ItemStackWrapper::class.java) { + lastDrive = it as IMatteryDrive + } + } + } + + if (prev != lastDrive) { + if (prev != null) + powered!!.remove(prev) + + view.clear() + + if (lastDrive != null) + powered!!.add(lastDrive!!) + } + + view.network() + } + } + + override fun getWorkingSlotStart(): Int { + return 0 + } + + override fun getWorkingSlotEnd(): Int { + return 2 + } + + override fun removed(p_38940_: Player) { + super.removed(p_38940_) + + if (powered != null) + lastDrive?.removeListener(powered) + + view.clear() + } + + override fun quickMoveStack(ply: Player, slot_index: Int): ItemStack { + val slot = slots[slot_index] + val item = slot.item + + if (item.isEmpty || item.getCapability(MatteryCapability.DRIVE).isPresent || item.getCapability(CapabilityEnergy.ENERGY).isPresent) + return super.quickMoveStack(ply, slot_index) + + val powered = powered + if (lastDrive == null || powered == null) + return ItemStack.EMPTY + + val remaining = powered.insertStack(ItemStackWrapper(item), false) + + if (remaining.count.toInt() == item.count) + return ItemStack.EMPTY + + if (remaining.isEmpty()) { + val copy = item.copy() + slot.set(ItemStack.EMPTY) + return copy + } + + val copy = item.copy() + item.shrink(remaining.count.toInt()) + slot.setChanged() + return copy + } + + enum class FilterSwitch { + MATCH_NBT, MATCH_TAG, BLACKLIST + } + + fun getFilter(): FilterSettings? { + if (driveSlot.item.isEmpty) + return null + + val item = driveSlot.item.item + return if (item is ItemPortableCondensationDrive) item.getFilterSettings(driveSlot.item) else null + } + + class FilterSetPacket(val id: Int, val slot: Int, val value: ItemStack) { + fun write(buffer: FriendlyByteBuf) { + buffer.writeInt(id) + buffer.writeInt(slot) + buffer.writeItem(value) + } + + fun play(context: Supplier) { + context.get().packetHandled = true + + if (slot < 0 || slot >= FilterSettings.MAX_FILTERS) + return + + if (value.count > 1) + value.count = 1 + + context.get().enqueueWork { + val ply = context.get().sender!! + val menu = ply.containerMenu + + if (menu is DriveViewerMenu && menu.containerId == id) { + if (menu.driveSlot.item.isEmpty) + return@enqueueWork + + val itemStack = menu.driveSlot.item + val item = itemStack.item + + if (item is ItemPortableCondensationDrive) { + val filter = item.getFilterSettings(itemStack) + filter.items[slot] = value + filter.serializeNBT(itemStack) + } + } + } + } + + companion object { + @JvmStatic + fun read(buffer: FriendlyByteBuf): FilterSetPacket { + return FilterSetPacket(buffer.readInt(), buffer.readInt(), buffer.readItem()) + } + } + } + + class FilterSwitchPacket(val id: Int, val type: FilterSwitch, val value: Boolean) { + fun write(buffer: FriendlyByteBuf) { + buffer.writeInt(id) + buffer.writeEnum(type) + buffer.writeBoolean(value) + } + + fun play(context: Supplier) { + context.get().packetHandled = true + context.get().enqueueWork { + val ply = context.get().sender!! + val menu = ply.containerMenu + + if (menu is DriveViewerMenu && menu.containerId == id) { + val settings = menu.getFilter() ?: return@enqueueWork + + when (type) { + FilterSwitch.MATCH_NBT -> { + settings.matchNbt = value + } + + FilterSwitch.MATCH_TAG -> { + settings.matchTag = value + } + + FilterSwitch.BLACKLIST -> { + settings.isBlacklist = value + } + } + + settings.serializeNBT(menu.driveSlot.item) + } + } + } + + companion object { + @JvmStatic + fun read(buffer: FriendlyByteBuf): FilterSwitchPacket { + return FilterSwitchPacket( + buffer.readInt(), + buffer.readEnum(FilterSwitch::class.java), + buffer.readBoolean() + ) + } + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/ItemMonitorMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/ItemMonitorMenu.kt index 4cc16b874..813a5a5f3 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/ItemMonitorMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/ItemMonitorMenu.kt @@ -2,6 +2,7 @@ package ru.dbotthepony.mc.otm.menu import net.minecraft.world.entity.player.Inventory import net.minecraft.world.entity.player.Player +import net.minecraft.world.item.ItemStack import ru.dbotthepony.mc.otm.Registry import ru.dbotthepony.mc.otm.block.entity.BlockEntityItemMonitor import ru.dbotthepony.mc.otm.capability.IMatteryEnergyStorage @@ -58,4 +59,12 @@ class ItemMonitorMenu @JvmOverloads constructor( override fun getWorkingSlotEnd(): Int { return 1 } + + override fun quickMoveStack(ply: Player, slot_index: Int): ItemStack { + if (slot_index in inventorySlotIndexStart..inventorySlotIndexEnd) { + + } + + return super.quickMoveStack(ply, slot_index) + } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/MatteryMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/MatteryMenu.kt index 7daee8f29..35b6b11f9 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/MatteryMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/MatteryMenu.kt @@ -9,32 +9,26 @@ import ru.dbotthepony.mc.otm.menu.widget.AbstractWidget import java.util.function.Consumer @JvmRecord -data class MoveResult(val merge_occured: Boolean, val remaining: ItemStack, val changed_slots: Set) +data class MoveResult(val mergeOccurred: Boolean, val remaining: ItemStack, val changed_slots: Set) abstract class MatteryMenu protected @JvmOverloads constructor( p_38851_: MenuType<*>?, p_38852_: Int, @JvmField val inventory: Inventory, - tile: BlockEntity? = null + @JvmField val tile: BlockEntity? = null ) : AbstractContainerMenu(p_38851_, p_38852_) { - @JvmField - val tile: BlockEntity? - @JvmField val ply: Player = inventory.player @JvmField - val mattery_widgets = ArrayList() + val matteryWidgets = ArrayList() @JvmField - val inventory_slots = ArrayList() + val inventorySlots = ArrayList() @JvmField - val main_slots = ArrayList() - - @JvmField - protected val locked_inventory_slots: MutableSet = HashSet() - protected fun isInventorySlotLocked(index: Int): Boolean = locked_inventory_slots.contains(index) + protected val lockedInventorySlots: MutableSet = HashSet() + protected open fun isInventorySlotLocked(index: Int): Boolean = lockedInventorySlots.contains(index) @JvmField protected var _synchronizer: ContainerSynchronizer? = null @@ -45,27 +39,17 @@ abstract class MatteryMenu protected @JvmOverloads constructor( } fun addWidget(widget: AbstractWidget, consumer: Consumer>) { - if (!mattery_widgets.contains(widget)) { - mattery_widgets.add(widget) + if (!matteryWidgets.contains(widget)) { + matteryWidgets.add(widget) consumer.accept(Consumer { p_38885_: ContainerData -> addDataSlots(p_38885_) }) } } - fun addMainSlot(slot: MatterySlot): MatterySlot { - addSlot(slot) - main_slots.add(slot) - return slot - } + @JvmField + protected var inventorySlotIndexStart = 0 @JvmField - protected var inventory_slot_index_start = 0 - - @JvmField - protected var inventory_slot_index_end = 0 - - init { - this.tile = tile - } + protected var inventorySlotIndexEnd = 0 @JvmOverloads protected fun addInventorySlots(offset: Int = 97) { @@ -83,12 +67,12 @@ abstract class MatteryMenu protected @JvmOverloads constructor( } } - inventory_slots.add(slot) + inventorySlots.add(slot) addSlot(slot) if (first) { first = false - inventory_slot_index_start = slot.index + inventorySlotIndexStart = slot.index } } } @@ -107,14 +91,14 @@ abstract class MatteryMenu protected @JvmOverloads constructor( } addSlot(last) - inventory_slots.add(last) + inventorySlots.add(last) } - inventory_slot_index_end = last!!.index + inventorySlotIndexEnd = last!!.index } override fun broadcastChanges() { - for (widget in mattery_widgets) { + for (widget in matteryWidgets) { widget.updateServer() } @@ -122,7 +106,7 @@ abstract class MatteryMenu protected @JvmOverloads constructor( } override fun broadcastFullState() { - for (widget in mattery_widgets) { + for (widget in matteryWidgets) { widget.updateServer() } @@ -148,7 +132,7 @@ abstract class MatteryMenu protected @JvmOverloads constructor( // It shall return item stack that got moved override fun quickMoveStack(ply: Player, slot_index: Int): ItemStack { // this.moveItemStackTo(ItemStack, int start_slot_index, int end_slot_index, boolean iteration_order) - // returns boolean, telling whenever ItemStack was modified (moved or sharnk) + // returns boolean, telling whenever ItemStack was modified (moved or shrank) // false means nothing happened // Last boolean determine order of slot iteration, where: // if TRUE, iteration order is end_slot_index -> start_slot_index @@ -161,26 +145,26 @@ abstract class MatteryMenu protected @JvmOverloads constructor( } var moved = ItemStack.EMPTY - val get_slot = slots[slot_index] + val initialSlot = slots[slot_index] - if (get_slot.hasItem()) { - val slot_item = get_slot.item - moved = slot_item.copy() + if (initialSlot.hasItem()) { + val initialItem = initialSlot.item + moved = initialItem.copy() - if (slot_index < inventory_slot_index_start) { + if (slot_index < inventorySlotIndexStart) { // Moving FROM machine TO inventory - if (!moveItemStackTo(slot_item, inventory_slot_index_start, inventory_slot_index_end + 1, false)) { + if (!moveItemStackTo(initialItem, inventorySlotIndexStart, inventorySlotIndexEnd + 1, false)) { return ItemStack.EMPTY } - } else if (!moveItemStackTo(slot_item, start, end, false)) { + } else if (!moveItemStackTo(initialItem, start, end, false)) { // Moving FROM inventory TO machine return ItemStack.EMPTY } - if (slot_item.isEmpty) { - get_slot.set(ItemStack.EMPTY) + if (initialItem.isEmpty) { + initialSlot.set(ItemStack.EMPTY) } else { - get_slot.setChanged() + initialSlot.setChanged() } } @@ -188,12 +172,12 @@ abstract class MatteryMenu protected @JvmOverloads constructor( } fun quickMoveToInventory(stack: ItemStack, simulate: Boolean): MoveResult { - return if (inventory_slot_index_start == 0 && inventory_slot_index_end == 0) { - MoveResult(false, stack, java.util.Set.of()) + return if (inventorySlotIndexStart == 0 && inventorySlotIndexEnd == 0) { + MoveResult(false, stack, setOf()) } else customMoveItemStackTo( stack, - inventory_slot_index_start, - inventory_slot_index_end + 1, + inventorySlotIndexStart, + inventorySlotIndexEnd + 1, false, simulate ) @@ -205,27 +189,27 @@ abstract class MatteryMenu protected @JvmOverloads constructor( final_slot: Int, reverse_direction: Boolean ): Boolean { - val move_result = customMoveItemStackTo(stack_to_move, initial_slot, final_slot, reverse_direction, false) - val remaining: ItemStack = move_result.remaining + val moveResult = customMoveItemStackTo(stack_to_move, initial_slot, final_slot, reverse_direction, false) + val remaining: ItemStack = moveResult.remaining if (remaining.count == stack_to_move.count) return false stack_to_move.count = remaining.count - return move_result.merge_occured + return moveResult.mergeOccurred } protected fun customMoveItemStackTo( - _stack_to_move: ItemStack, + stackToMove1: ItemStack, initial_slot: Int, final_slot: Int, reverse_direction: Boolean, simulate: Boolean ): MoveResult { - var merge_occured = false + var mergeOccurred = false var i = if (reverse_direction) final_slot - 1 else initial_slot val changed = HashSet() - val stack_to_move = _stack_to_move.copy() + val stackToMove = stackToMove1.copy() - if (stack_to_move.isStackable) { - while (!stack_to_move.isEmpty) { + if (stackToMove.isStackable) { + while (!stackToMove.isEmpty) { if (reverse_direction) { if (i < initial_slot) { break @@ -237,29 +221,29 @@ abstract class MatteryMenu protected @JvmOverloads constructor( val slot = slots[i] val slot_stack = slot.item - if (!slot_stack.isEmpty && ItemStack.isSameItemSameTags(stack_to_move, slot_stack)) { - val j = slot_stack.count + stack_to_move.count - val maxSize = slot.getMaxStackSize(stack_to_move) + if (!slot_stack.isEmpty && ItemStack.isSameItemSameTags(stackToMove, slot_stack)) { + val j = slot_stack.count + stackToMove.count + val maxSize = slot.getMaxStackSize(stackToMove) if (j <= maxSize) { - stack_to_move.count = 0 + stackToMove.count = 0 if (!simulate) { slot_stack.count = j slot.setChanged() } - merge_occured = true + mergeOccurred = true changed.add(slot) } else if (slot_stack.count < maxSize) { - stack_to_move.shrink(maxSize - slot_stack.count) + stackToMove.shrink(maxSize - slot_stack.count) if (!simulate) { slot_stack.count = maxSize slot.setChanged() } - merge_occured = true + mergeOccurred = true changed.add(slot) } } @@ -268,7 +252,7 @@ abstract class MatteryMenu protected @JvmOverloads constructor( } } - if (!stack_to_move.isEmpty) { + if (!stackToMove.isEmpty) { i = if (reverse_direction) final_slot - 1 else initial_slot while (true) { @@ -283,18 +267,18 @@ abstract class MatteryMenu protected @JvmOverloads constructor( val slot = slots[i] val slot_stack = slot.item - if (slot_stack.isEmpty && slot.mayPlace(stack_to_move)) { + if (slot_stack.isEmpty && slot.mayPlace(stackToMove)) { if (!simulate) { - if (stack_to_move.count > slot.maxStackSize) { - slot.set(stack_to_move.split(slot.maxStackSize)) + if (stackToMove.count > slot.maxStackSize) { + slot.set(stackToMove.split(slot.maxStackSize)) } else { - slot.set(stack_to_move.split(stack_to_move.count)) + slot.set(stackToMove.split(stackToMove.count)) } slot.setChanged() } - merge_occured = true + mergeOccurred = true changed.add(slot) break } @@ -302,6 +286,7 @@ abstract class MatteryMenu protected @JvmOverloads constructor( i += if (reverse_direction) -1 else 1 } } - return MoveResult(merge_occured, stack_to_move, changed) + + return MoveResult(mergeOccurred, stackToMove, changed) } } \ No newline at end of file diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/data/NetworkedItemView.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/data/NetworkedItemView.kt new file mode 100644 index 000000000..fcdefbbf0 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/data/NetworkedItemView.kt @@ -0,0 +1,213 @@ +package ru.dbotthepony.mc.otm.menu.data + +import com.mojang.blaze3d.platform.InputConstants +import net.minecraft.client.gui.screens.Screen +import net.minecraft.server.level.ServerPlayer +import net.minecraft.world.entity.player.Player +import net.minecraft.world.inventory.ClickAction +import net.minecraft.world.inventory.ClickType +import net.minecraft.world.item.ItemStack +import net.minecraftforge.network.PacketDistributor +import ru.dbotthepony.mc.otm.core.Fraction +import ru.dbotthepony.mc.otm.menu.MatteryMenu +import ru.dbotthepony.mc.otm.network.MatteryNetworking +import ru.dbotthepony.mc.otm.network.SetCarriedPacket +import ru.dbotthepony.mc.otm.storage.IStorageComponent +import ru.dbotthepony.mc.otm.storage.IStorageListener +import ru.dbotthepony.mc.otm.storage.IStorageView +import ru.dbotthepony.mc.otm.storage.ItemStackWrapper +import java.util.* + +/** + * Creates a virtual, slotless container for Player's interaction with. + */ +open class NetworkedItemView(val ply: Player, val menu: MatteryMenu, val remote: Boolean) : IStorageListener { + @JvmRecord + data class NetworkedItem @JvmOverloads constructor(val id: Int, val stack: ItemStack, val upstreamId: UUID? = null) + + @JvmField protected var next_stack_id = 0 + @JvmField val state = HashMap() + + @JvmField protected val upstream_state = HashMap() + @JvmField protected val backlog = ArrayList() + + operator fun get(id: Int): NetworkedItem? { + return state[id] + } + + private var cachedView: List? = null + @JvmField protected var provider: IStorageComponent? = null + + fun mouseClick(index: Int, mouse_click_type: Int) { + val list = getItems() + + val action = + if (mouse_click_type == InputConstants.MOUSE_BUTTON_LEFT) ClickAction.PRIMARY else ClickAction.SECONDARY + + val type = + if (mouse_click_type == InputConstants.MOUSE_BUTTON_MIDDLE) ClickType.CLONE else if (Screen.hasShiftDown()) ClickType.QUICK_MOVE else ClickType.PICKUP + + MatteryNetworking.send( + null, + InteractPacket(menu.containerId, if (index >= list.size) -1 else list[index].id, type, action) + ) + } + + fun setComponent(provider: IStorageComponent?) { + if (provider === this.provider) return + + this.provider?.removeListenerAuto(this) + this.provider = provider + provider?.addListenerAuto(this) + } + + fun removed() { + provider?.removeListenerAuto(this) + } + + fun clearCache() { + cachedView = null + } + + fun getItems(): List { + return if (cachedView != null) cachedView!! else java.util.List.copyOf(state.values).also { cachedView = it } + } + + fun getItemCount(): Int { + return state.values.size + } + + override fun addObject(stack: ItemStackWrapper, id: UUID, provider: IStorageView) = addObject(stack.stack, id) + override fun changeObject(id: UUID, newCount: Fraction) = changeObject(id, newCount.toInt()) + + protected fun network(fn: () -> Any) { + if (!remote) { + backlog.add(fn()) + } + } + + override fun removeObject(id: UUID) { + val get = upstream_state[id] ?: throw IllegalStateException("Unknown ItemStack with upstream id $id!") + upstream_state.remove(id) + state.remove(get.id) + network { StackRemovePacket(menu.containerId, get.id) } + clearCache() + } + + fun addObject(stack: ItemStack, id_upstream: UUID) { + check(!upstream_state.containsKey(id_upstream)) { "Already tracking ItemStack with upstream id $id_upstream!" } + + val state = NetworkedItem(next_stack_id++, stack.copy(), id_upstream) + + this.state[state.id] = state + upstream_state[id_upstream] = state + network { StackAddPacket(menu.containerId, state.id, stack) } + clearCache() + } + + fun changeObject(id_upstream: UUID, new_count: Int) { + val get = upstream_state[id_upstream] ?: throw IllegalStateException("Unknown ItemStack with upstream id $id_upstream!") + get.stack.count = new_count + network { StackChangePacket(menu.containerId, get.id, new_count) } + clearCache() + } + + fun clear() { + clearCache() + upstream_state.clear() + state.clear() + + if (!remote) { + backlog.clear() + backlog.add(ClearPacket(menu.containerId)) + } + } + + fun network() { + check(!remote) { "Not a server" } + val consumer = PacketDistributor.PLAYER.with { ply as ServerPlayer } + for (packet in backlog) MatteryNetworking.CHANNEL.send(consumer, packet) + backlog.clear() + } + + fun playerInteract(packet: InteractPacket) { + val provider = provider ?: return + + val click = packet.click() + val action = packet.action() + val stack_id = packet.stack_id() + + if (click == ClickType.CLONE) { + if (stack_id < 0 || !ply.abilities.instabuild) return + + val state = get(stack_id) ?: return + val copy: ItemStack = state.stack.copy() + + copy.count = Math.min(copy.count, copy.maxStackSize) + ply.containerMenu.carried = copy + MatteryNetworking.send(ply as ServerPlayer, SetCarriedPacket(ply.containerMenu.carried)) + ply.containerMenu.setRemoteCarried(ply.containerMenu.carried.copy()) + + return + } + + if (click == ClickType.QUICK_MOVE && stack_id > -1) { + val state = get(stack_id) ?: return + + val amount = + if (action == ClickAction.PRIMARY) + state.stack.maxStackSize + else + Math.max(1, state.stack.maxStackSize / 2) + + val extracted = provider.extractStack(state.upstreamId!!, amount, true) + + if (!extracted.isEmpty()) { + val (_, remaining) = menu.quickMoveToInventory(extracted.stack, false) + + if (remaining.count != extracted.stack.count) { + provider.extractStack(state.upstreamId, extracted.stack.count - remaining.count, false) + } + } + + return + } + + if (!menu.carried.isEmpty && click != ClickType.QUICK_MOVE) { + // try to put + if (action == ClickAction.PRIMARY) { + val carried = menu.carried + val amount = carried.count + + if (amount == carried.count) { + val (stack) = provider.insertStack(ItemStackWrapper(menu.carried), false) + menu.carried = stack + MatteryNetworking.send(ply as ServerPlayer, SetCarriedPacket(menu.carried)) + menu.setRemoteCarried(menu.carried.copy()) + } + } else { + val copy = menu.carried.copy() + copy.count = 1 + + if (provider.insertStack(ItemStackWrapper(copy), false).isEmpty()) { + menu.carried.shrink(1) + MatteryNetworking.send(ply as ServerPlayer, SetCarriedPacket(menu.carried)) + menu.setRemoteCarried(menu.carried.copy()) + } + } + } else if (stack_id > -1) { + val state = get(stack_id) ?: return + + val amount = + if (action == ClickAction.PRIMARY) + state.stack.maxStackSize + else + Math.max(1, state.stack.maxStackSize / 2) + + val extracted = provider.extractStack(state.upstreamId!!, amount, false) + menu.carried = extracted.stack + MatteryNetworking.send(ply as ServerPlayer, SetCarriedPacket(menu.carried)) + menu.setRemoteCarried(menu.carried.copy()) + } + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/storage/API.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/storage/API.kt index fb69e090b..ab2eef382 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/storage/API.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/storage/API.kt @@ -84,6 +84,8 @@ interface IStorageView : IStorageTrigger { * @return copy of object, with amount of units actually extracted */ fun extractStack(id: UUID, amount: Fraction, simulate: Boolean): T + fun extractStack(id: UUID, amount: Int, simulate: Boolean): T = extractStack(id, Fraction(amount), simulate) + fun extractStack(id: UUID, amount: Long, simulate: Boolean): T = extractStack(id, Fraction(amount), simulate) /** * Designed for views, for extraction with less computation overhead caused by @@ -98,6 +100,9 @@ interface IStorageView : IStorageTrigger { return extractStack(id, amount, simulate).count } + fun extractStackCount(id: UUID, amount: Int, simulate: Boolean): Fraction = extractStackCount(id, Fraction(amount), simulate) + fun extractStackCount(id: UUID, amount: Long, simulate: Boolean): Fraction = extractStackCount(id, Fraction(amount), simulate) + fun getStacks(): Collection> fun addListenerAuto(listener: IStorageListener): Boolean { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/storage/ItemStackWrapper.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/storage/ItemStackWrapper.kt index a89ece183..894149f28 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/storage/ItemStackWrapper.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/storage/ItemStackWrapper.kt @@ -15,7 +15,7 @@ data class ItemStackWrapper(val stack: ItemStack) : IStorageStack { } override var count: Fraction - get() = Fraction(stack.getCount()) + get() = Fraction(stack.count) set(value) = setCount(value.toInt()) fun getCountInt() = stack.count