From 3301cf2d8b6a8543839432ea26c9974f648c5994 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bruno=20Ryb=C3=A1rsky?= Date: Fri, 24 May 2024 16:23:50 +0200 Subject: [PATCH] Get it to somehow work --- .../brn/server_storage/ServerStorage.java | 4 - .../blockEntities/StorageBlockEntity.java | 70 ------ .../server_storage/blocks/StorageBlock.java | 83 +------ .../items/StorageBlockItem.java | 4 +- .../brn/server_storage/lib/PagedGui.java | 204 ++++++++++++++++++ .../server_storage/lib/StorageOperations.java | 179 +++++++++++++++ .../server_storage/screens/StorageScreen.java | 97 +++++---- src/main/resources/fabric.mod.json | 3 - src/main/resources/server_storage.mixins.json | 11 - 9 files changed, 446 insertions(+), 209 deletions(-) delete mode 100644 src/main/java/systems/brn/server_storage/blockEntities/StorageBlockEntity.java create mode 100644 src/main/java/systems/brn/server_storage/lib/PagedGui.java create mode 100644 src/main/java/systems/brn/server_storage/lib/StorageOperations.java delete mode 100644 src/main/resources/server_storage.mixins.json diff --git a/src/main/java/systems/brn/server_storage/ServerStorage.java b/src/main/java/systems/brn/server_storage/ServerStorage.java index d922a9c..3922106 100644 --- a/src/main/java/systems/brn/server_storage/ServerStorage.java +++ b/src/main/java/systems/brn/server_storage/ServerStorage.java @@ -2,8 +2,6 @@ package systems.brn.server_storage; import eu.pb4.polymer.resourcepack.api.PolymerResourcePackUtils; import net.fabricmc.api.ModInitializer; -import net.minecraft.block.entity.BlockEntityType; -import systems.brn.server_storage.blockEntities.StorageBlockEntity; import systems.brn.server_storage.blocks.StorageBlock; import systems.brn.server_storage.items.StorageBlockItem; @@ -11,7 +9,6 @@ public class ServerStorage implements ModInitializer { public static final String MODID = "serverstorage"; public static final String MODELID = "storage"; public static StorageBlock STORAGE_BLOCK; - public static BlockEntityType CUSTOM_STORAGE_BLOCK_ENTITY; @Override public void onInitialize() @@ -21,7 +18,6 @@ public class ServerStorage implements ModInitializer { StorageBlock.register(); StorageBlockItem.register(); - StorageBlockEntity.register(); } } diff --git a/src/main/java/systems/brn/server_storage/blockEntities/StorageBlockEntity.java b/src/main/java/systems/brn/server_storage/blockEntities/StorageBlockEntity.java deleted file mode 100644 index 14bfd15..0000000 --- a/src/main/java/systems/brn/server_storage/blockEntities/StorageBlockEntity.java +++ /dev/null @@ -1,70 +0,0 @@ -package systems.brn.server_storage.blockEntities; - -import eu.pb4.polymer.core.api.block.PolymerBlockUtils; -import net.minecraft.block.BlockState; -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.block.entity.BlockEntityType; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.entity.player.PlayerInventory; -import net.minecraft.inventory.Inventory; -import net.minecraft.registry.Registries; -import net.minecraft.registry.Registry; -import net.minecraft.screen.NamedScreenHandlerFactory; -import net.minecraft.screen.ScreenHandler; -import net.minecraft.screen.ScreenHandlerContext; -import net.minecraft.text.Text; -import net.minecraft.util.Identifier; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; -import net.minecraft.world.World; -import org.jetbrains.annotations.Nullable; -import systems.brn.server_storage.screens.StorageScreen; - -import java.util.ArrayList; -import java.util.List; - -import static systems.brn.server_storage.ServerStorage.*; - -public class StorageBlockEntity extends BlockEntity implements NamedScreenHandlerFactory { - - public StorageBlockEntity(BlockPos pos, BlockState state) { - super(CUSTOM_STORAGE_BLOCK_ENTITY, pos, state); - } - - @Override - public Text getDisplayName() { - return Text.of("Custom Storage"); - } - - @Nullable - @Override - public ScreenHandler createMenu(int syncId, PlayerInventory playerInventory, PlayerEntity player) { - List connectedChests = getConnectedChests(world, pos); - return new StorageScreen(syncId, playerInventory, ScreenHandlerContext.create(world, pos), connectedChests.getFirst()); - } - - static List getConnectedChests(World world, BlockPos pos) { - List inventories = new ArrayList<>(); - - // Logic to find nearby chests and add them to the list - // Example logic: - for (Direction direction : Direction.values()) { - BlockPos chestPos = pos.offset(direction); - BlockEntity blockEntity = world.getBlockEntity(chestPos); - if (blockEntity instanceof Inventory) { - inventories.add((Inventory) blockEntity); - } - } - - return inventories; - } - - public static void register() { - Registry.register( - Registries.BLOCK_ENTITY_TYPE, - new Identifier(MODID, "custom_storage_block_entity"), - BlockEntityType.Builder.create(StorageBlockEntity::new, STORAGE_BLOCK).build() - ); - PolymerBlockUtils.registerBlockEntity(CUSTOM_STORAGE_BLOCK_ENTITY); - } -} diff --git a/src/main/java/systems/brn/server_storage/blocks/StorageBlock.java b/src/main/java/systems/brn/server_storage/blocks/StorageBlock.java index 92d6f2a..6568d3e 100644 --- a/src/main/java/systems/brn/server_storage/blocks/StorageBlock.java +++ b/src/main/java/systems/brn/server_storage/blocks/StorageBlock.java @@ -9,33 +9,19 @@ import net.minecraft.block.AbstractBlock; import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; -import net.minecraft.block.entity.BlockEntity; import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.inventory.Inventory; -import net.minecraft.inventory.SimpleInventory; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; import net.minecraft.registry.Registries; import net.minecraft.registry.Registry; -import net.minecraft.screen.NamedScreenHandlerFactory; -import net.minecraft.screen.ScreenHandlerContext; -import net.minecraft.screen.SimpleNamedScreenHandlerFactory; -import net.minecraft.text.Text; +import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.util.ActionResult; import net.minecraft.util.Hand; import net.minecraft.util.Identifier; import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; import net.minecraft.world.World; import systems.brn.server_storage.ServerStorage; import systems.brn.server_storage.screens.StorageScreen; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - import static systems.brn.server_storage.ServerStorage.STORAGE_BLOCK; public class StorageBlock extends Block implements PolymerTexturedBlock { @@ -59,22 +45,6 @@ public class StorageBlock extends Block implements PolymerTexturedBlock { UseBlockCallback.EVENT.register(StorageBlock::onUse); } - private static List getConnectedChests(World world, BlockPos pos) { - List inventories = new ArrayList<>(); - - // Logic to find nearby chests and add them to the list - // Example logic: - for (Direction direction : Direction.values()) { - BlockPos chestPos = pos.offset(direction); - BlockEntity blockEntity = world.getBlockEntity(chestPos); - if (blockEntity instanceof Inventory) { - inventories.add((Inventory) blockEntity); - } - } - - return inventories; - } - private static ActionResult onUse(PlayerEntity player, World world, Hand hand, BlockHitResult hitResult) { BlockPos pos = hitResult.getBlockPos(); BlockState state = world.getBlockState(pos); @@ -82,56 +52,7 @@ public class StorageBlock extends Block implements PolymerTexturedBlock { if (block instanceof StorageBlock) { if (!world.isClient) { - List inventories = getConnectedChests(world, pos); - int size = 0; - for (Inventory inventory : inventories) { - size += inventory.size(); - } - - // Create a map to keep track of item stacks and their counts - Map itemStackMap = new HashMap<>(); - - // Loop through inventories to add items to the inventory - for (Inventory inventory : inventories) { - int invsize = inventory.size(); - for (int i = 0; i < invsize; i++) { - ItemStack stack = inventory.getStack(i); - if (!stack.isEmpty()) { - Item item = stack.getItem(); - // Check if the item type already exists in the map - int count = stack.getCount(); - if (itemStackMap.containsKey(item)) { - // If yes, increment the count - count += itemStackMap.get(item); - itemStackMap.put(item, count); - } else { - // If not, add the item type to the map with count 1 - itemStackMap.put(item, count); - } - } - } - } - - // Populate the inventory with item stacks from the map - - SimpleInventory inv = new SimpleInventory(size); - int invpointer = 0; - for (Map.Entry entry : itemStackMap.entrySet()) { - Item item = entry.getKey(); - int count = entry.getValue(); - // Create a new ItemStack with the item type and the correct count - ItemStack stack = new ItemStack(item, count); - // Populate the inventory with the item stack - inv.heldStacks.set(invpointer, stack); - inv.markDirty(); - invpointer++; - } - if (!inv.isEmpty()) { - NamedScreenHandlerFactory screenHandlerFactory = new SimpleNamedScreenHandlerFactory( - (syncId, playerInventory, playerEntity) -> new StorageScreen(syncId, playerInventory, ScreenHandlerContext.create(world, pos), inv), - Text.of("Storage System")); - player.openHandledScreen(screenHandlerFactory); - } + new StorageScreen((ServerPlayerEntity) player, pos).open(); } return ActionResult.SUCCESS; } diff --git a/src/main/java/systems/brn/server_storage/items/StorageBlockItem.java b/src/main/java/systems/brn/server_storage/items/StorageBlockItem.java index 8ed689e..ebe4970 100644 --- a/src/main/java/systems/brn/server_storage/items/StorageBlockItem.java +++ b/src/main/java/systems/brn/server_storage/items/StorageBlockItem.java @@ -36,8 +36,6 @@ public class StorageBlockItem extends BlockItem implements PolymerItem { public static void register() { var modId = new Identifier(ServerStorage.MODID, ServerStorage.MODELID); Item item = Registry.register(Registries.ITEM, modId, new StorageBlockItem(new Item.Settings(), STORAGE_BLOCK, ServerStorage.MODELID)); - ItemGroupEvents.modifyEntriesEvent(ItemGroups.FUNCTIONAL).register(content -> { - content.add(item); - }); + ItemGroupEvents.modifyEntriesEvent(ItemGroups.FUNCTIONAL).register(content -> content.add(item)); } } \ No newline at end of file diff --git a/src/main/java/systems/brn/server_storage/lib/PagedGui.java b/src/main/java/systems/brn/server_storage/lib/PagedGui.java new file mode 100644 index 0000000..99575b0 --- /dev/null +++ b/src/main/java/systems/brn/server_storage/lib/PagedGui.java @@ -0,0 +1,204 @@ +package systems.brn.server_storage.lib; + +import eu.pb4.sgui.api.elements.GuiElement; +import eu.pb4.sgui.api.elements.GuiElementBuilder; +import eu.pb4.sgui.api.elements.GuiElementBuilderInterface; +import eu.pb4.sgui.api.elements.GuiElementInterface; +import eu.pb4.sgui.api.gui.SimpleGui; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.screen.ScreenHandlerType; +import net.minecraft.screen.slot.Slot; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.sound.SoundCategory; +import net.minecraft.sound.SoundEvents; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Nullable; + + +//from https://github.com/Patbox/get-off-my-lawn-reserved/blob/6c03c6b004f65616d1d8cb773c19da970eb8c1d1/src/main/java/draylar/goml/ui/PagedGui.java +@ApiStatus.Internal +public abstract class PagedGui extends SimpleGui { + + public static final String GUI_PREVIOUS_PAGE = "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzEwODI5OGZmMmIyNjk1MWQ2ODNlNWFkZTQ2YTQyZTkwYzJmN2M3ZGQ0MWJhYTkwOGJjNTg1MmY4YzMyZTU4MyJ9fX0"; + public static final String GUI_PREVIOUS_PAGE_BLOCKED = "ewogICJ0aW1lc3RhbXAiIDogMTY0MDYxNjE5MjE0MiwKICAicHJvZmlsZUlkIiA6ICJmMjc0YzRkNjI1MDQ0ZTQxOGVmYmYwNmM3NWIyMDIxMyIsCiAgInByb2ZpbGVOYW1lIiA6ICJIeXBpZ3NlbCIsCiAgInNpZ25hdHVyZVJlcXVpcmVkIiA6IHRydWUsCiAgInRleHR1cmVzIiA6IHsKICAgICJTS0lOIiA6IHsKICAgICAgInVybCIgOiAiaHR0cDovL3RleHR1cmVzLm1pbmVjcmFmdC5uZXQvdGV4dHVyZS81MDgyMGY3NmUzZTA0MWM3NWY3NmQwZjMwMTIzMmJkZjQ4MzIxYjUzNGZlNmE4NTljY2I4NzNkMjk4MWE5NjIzIiwKICAgICAgIm1ldGFkYXRhIiA6IHsKICAgICAgICAibW9kZWwiIDogInNsaW0iCiAgICAgIH0KICAgIH0KICB9Cn0="; + public static final String GUI_NEXT_PAGE = "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYzg2MTg1YjFkNTE5YWRlNTg1ZjE4NGMzNGYzZjNlMjBiYjY0MWRlYjg3OWU4MTM3OGU0ZWFmMjA5Mjg3In19fQ"; + public static final String GUI_NEXT_PAGE_BLOCKED = "ewogICJ0aW1lc3RhbXAiIDogMTY0MDYxNjExMDQ4OCwKICAicHJvZmlsZUlkIiA6ICIxZjEyNTNhYTVkYTQ0ZjU5YWU1YWI1NmFhZjRlNTYxNyIsCiAgInByb2ZpbGVOYW1lIiA6ICJOb3RNaUt5IiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzdlNTc3MjBhNDg3OGM4YmNhYjBlOWM5YzQ3ZDllNTUxMjhjY2Q3N2JhMzQ0NWE1NGE5MWUzZTFlMWEyNzM1NmUiLAogICAgICAibWV0YWRhdGEiIDogewogICAgICAgICJtb2RlbCIgOiAic2xpbSIKICAgICAgfQogICAgfQogIH0KfQ=="; + + public static final int PAGE_SIZE = 9 * 5; + protected final Runnable closeCallback; + protected int page = 0; + public boolean ignoreCloseCallback; + + public PagedGui(ServerPlayerEntity player, @Nullable Runnable closeCallback) { + super(ScreenHandlerType.GENERIC_9X6, player, false); + this.closeCallback = closeCallback; + } + + + public void refreshOpen() { + this.updateDisplay(); + this.open(); + } + + @Override + public void onClose() { + if (this.closeCallback != null && !ignoreCloseCallback) { + this.closeCallback.run(); + } + } + + protected void nextPage() { + this.page = Math.min(this.getPageAmount() - 1, this.page + 1); + this.updateDisplay(); + } + + protected boolean canNextPage() { + return this.getPageAmount() > this.page + 1; + } + + protected void previousPage() { + this.page = Math.max(0, this.page - 1); + this.updateDisplay(); + } + + protected boolean canPreviousPage() { + return this.page - 1 >= 0; + } + + protected void updateDisplay() { + var offset = this.page * PAGE_SIZE; + + for (int i = 0; i < PAGE_SIZE; i++) { + var element = this.getElement(offset + i); + + if (element == null) { + element = DisplayElement.empty(); + } + + if (element.element() != null) { + this.setSlot(i, element.element()); + } else if (element.slot() != null) { + this.setSlotRedirect(i, element.slot()); + } + } + + for (int i = 0; i < 9; i++) { + var navElement = this.getNavElement(i); + + if (navElement == null) { + navElement = DisplayElement.EMPTY; + } + + if (navElement.element != null) { + this.setSlot(i + PAGE_SIZE, navElement.element); + } else if (navElement.slot != null) { + this.setSlotRedirect(i + PAGE_SIZE, navElement.slot); + } + } + } + + protected int getPage() { + return this.page; + } + + protected abstract int getPageAmount(); + + protected abstract DisplayElement getElement(int id); + + protected DisplayElement getNavElement(int id) { + return switch (id) { + case 1 -> DisplayElement.previousPage(this); + case 3 -> DisplayElement.nextPage(this); + case 7 -> DisplayElement.of( + new GuiElementBuilder(Items.STRUCTURE_VOID) + .setName(Text.translatable(this.closeCallback != null ? "gui.back" : "mco.selectServer.close").formatted(Formatting.RED)) + .hideDefaultTooltip().noDefaults() + .setCallback((x, y, z) -> { + playClickSound(this.player); + this.close(this.closeCallback != null); + }) + ); + default -> DisplayElement.filler(); + }; + } + + public record DisplayElement(@Nullable GuiElementInterface element, @Nullable Slot slot) { + private static final DisplayElement EMPTY = DisplayElement.of(new GuiElement(ItemStack.EMPTY, GuiElementInterface.EMPTY_CALLBACK)); + private static final DisplayElement FILLER = DisplayElement.of( + new GuiElementBuilder(Items.WHITE_STAINED_GLASS_PANE) + .setName(Text.empty()) + .hideTooltip() + ); + + public static DisplayElement of(GuiElementInterface element) { + return new DisplayElement(element, null); + } + + public static DisplayElement of(GuiElementBuilderInterface element) { + return new DisplayElement(element.build(), null); + } + + public static DisplayElement of(Slot slot) { + return new DisplayElement(null, slot); + } + + public static DisplayElement nextPage(PagedGui gui) { + if (gui.canNextPage()) { + return DisplayElement.of( + new GuiElementBuilder(Items.PLAYER_HEAD) + .setName(Text.translatable("createWorld.customize.custom.next").formatted(Formatting.WHITE)) + .hideDefaultTooltip().noDefaults() + .setSkullOwner(GUI_NEXT_PAGE) + .setCallback((x, y, z) -> { + playClickSound(gui.player); + gui.nextPage(); + }) + ); + } else { + return DisplayElement.of( + new GuiElementBuilder(Items.PLAYER_HEAD) + .setName(Text.translatable("createWorld.customize.custom.next").formatted(Formatting.DARK_GRAY)) + .hideDefaultTooltip().noDefaults() + .setSkullOwner(GUI_NEXT_PAGE_BLOCKED) + ); + } + } + + public static DisplayElement previousPage(PagedGui gui) { + if (gui.canPreviousPage()) { + return DisplayElement.of( + new GuiElementBuilder(Items.PLAYER_HEAD) + .setName(Text.translatable("createWorld.customize.custom.prev").formatted(Formatting.WHITE)) + .hideDefaultTooltip().noDefaults() + .setSkullOwner(GUI_PREVIOUS_PAGE) + .setCallback((x, y, z) -> { + playClickSound(gui.player); + gui.previousPage(); + }) + ); + } else { + return DisplayElement.of( + new GuiElementBuilder(Items.PLAYER_HEAD) + .setName(Text.translatable("createWorld.customize.custom.prev").formatted(Formatting.DARK_GRAY)) + .hideDefaultTooltip().noDefaults() + .setSkullOwner(GUI_PREVIOUS_PAGE_BLOCKED) + ); + } + } + + public static DisplayElement filler() { + return FILLER; + } + + public static DisplayElement empty() { + return EMPTY; + } + } + + public static final void playClickSound(ServerPlayerEntity player) { + player.playSoundToPlayer(SoundEvents.UI_BUTTON_CLICK.value(), SoundCategory.MASTER, 1, 1); + } +} \ No newline at end of file diff --git a/src/main/java/systems/brn/server_storage/lib/StorageOperations.java b/src/main/java/systems/brn/server_storage/lib/StorageOperations.java new file mode 100644 index 0000000..b1c12b9 --- /dev/null +++ b/src/main/java/systems/brn/server_storage/lib/StorageOperations.java @@ -0,0 +1,179 @@ +package systems.brn.server_storage.lib; + +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.inventory.Inventory; +import net.minecraft.inventory.SimpleInventory; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; +import net.minecraft.world.World; +import org.jetbrains.annotations.NotNull; +import systems.brn.server_storage.blocks.StorageBlock; + +import java.util.*; + +public class StorageOperations { + public static List getConnectedChests(World world, BlockPos startPos) { + List inventories = new ArrayList<>(); + Set visited = new HashSet<>(); + + getConnectedChestsHelper(world, startPos, inventories, visited); + + return inventories; + } + + private static void getConnectedChestsHelper(World world, BlockPos pos, List inventories, Set visited) { + if (visited.contains(pos)) { + return; + } + visited.add(pos); + + BlockEntity blockEntity = world.getBlockEntity(pos); + if (blockEntity instanceof Inventory || world.getBlockState(pos).getBlock() instanceof StorageBlock) { + if (blockEntity instanceof Inventory) { + inventories.add((Inventory) blockEntity); + } + + for (Direction direction : Direction.values()) { + BlockPos nextPos = pos.offset(direction); + getConnectedChestsHelper(world, nextPos, inventories, visited); + } + } + } + + public static boolean tryPutItemStackIntoChests(World world, BlockPos startPos, ItemStack stack) { + List chests = getConnectedChests(world, startPos); + + // Iterate over each chest to try and insert the ItemStack + for (Inventory chest : chests) { + stack = insertStackIntoInventory(chest, stack); + if (stack.isEmpty()) { + return true; + } + } + + // If we still have remaining items, return false + return stack.isEmpty(); + } + + private static ItemStack insertStackIntoInventory(Inventory inventory, ItemStack stack) { + // First, try to merge with existing stacks + for (int i = 0; i < inventory.size(); i++) { + ItemStack slotStack = inventory.getStack(i); + if (canCombine(slotStack, stack)) { + int transferAmount = Math.min(stack.getCount(), slotStack.getMaxCount() - slotStack.getCount()); + if (transferAmount > 0) { + slotStack.increment(transferAmount); + stack.decrement(transferAmount); + inventory.markDirty(); + if (stack.isEmpty()) { + return ItemStack.EMPTY; + } + } + } + } + + // Next, try to find an empty slot + for (int i = 0; i < inventory.size(); i++) { + ItemStack slotStack = inventory.getStack(i); + if (slotStack.isEmpty()) { + inventory.setStack(i, stack.copy()); + stack.setCount(0); + inventory.markDirty(); + return ItemStack.EMPTY; + } + } + + return stack; + } + + public static boolean tryRemoveItemStackFromChests(World world, BlockPos startPos, ItemStack stackToRemove) { + List chests = getConnectedChests(world, startPos); + + int remainingToRemove = stackToRemove.getCount(); + + for (Inventory chest : chests) { + remainingToRemove = removeFromInventory(chest, stackToRemove, remainingToRemove); + if (remainingToRemove <= 0) { + return true; + } + } + + return remainingToRemove <= 0; + } + + public static int removeFromInventory(Inventory inventory, ItemStack stackToRemove, int remainingToRemove) { + for (int i = 0; i < inventory.size(); i++) { + ItemStack slotStack = inventory.getStack(i); + if (canCombine(slotStack, stackToRemove)) { + int removeAmount = Math.min(slotStack.getCount(), remainingToRemove); + slotStack.decrement(removeAmount); + remainingToRemove -= removeAmount; + inventory.markDirty(); + + if (slotStack.isEmpty()) { + inventory.setStack(i, ItemStack.EMPTY); + } + + if (remainingToRemove <= 0) { + return remainingToRemove; + } + } + } + return remainingToRemove; + } + + public static SimpleInventory getCombinedInventoryFromChests(World world, BlockPos startPos) { + List inventories = getConnectedChests(world, startPos); + int size = 0; + + // Create a map to keep track of item stacks and their counts + Map itemStackMap = new HashMap<>(); + + // Loop through inventories to add items to the inventory + for (Inventory inventory : inventories) { + int inventorySize = inventory.size(); + for (int i = 0; i < inventorySize; i++) { + ItemStack stack = inventory.getStack(i); + if (!stack.isEmpty()) { + Item item = stack.getItem(); + // Check if the item type already exists in the map + int count = stack.getCount(); + if (itemStackMap.containsKey(item)) { + // If yes, increment the count + count += itemStackMap.get(item); + itemStackMap.put(item, count); + } else { + // If not, add the item type to the map with count 1 + itemStackMap.put(item, count); + } + } + } + size += inventorySize; + } + + // Populate the inventory with item stacks from the map + + return getSimpleInventory(size, itemStackMap); + } + + private static @NotNull SimpleInventory getSimpleInventory(int size, Map itemStackMap) { + SimpleInventory inv = new SimpleInventory(size); + int invPointer = 0; + for (Map.Entry entry : itemStackMap.entrySet()) { + Item item = entry.getKey(); + int count = entry.getValue(); + // Create a new ItemStack with the item type and the correct count + ItemStack stack = new ItemStack(item, count); + // Populate the inventory with the item stack + inv.setStack(invPointer, stack); + invPointer++; + } + return inv; + } + + private static boolean canCombine(ItemStack stack1, ItemStack stack2) { + return !stack1.isEmpty() && stack1.getItem() == stack2.getItem() && ItemStack.areItemsAndComponentsEqual(stack1, stack2); + } +} diff --git a/src/main/java/systems/brn/server_storage/screens/StorageScreen.java b/src/main/java/systems/brn/server_storage/screens/StorageScreen.java index d24b63e..9b07416 100644 --- a/src/main/java/systems/brn/server_storage/screens/StorageScreen.java +++ b/src/main/java/systems/brn/server_storage/screens/StorageScreen.java @@ -1,55 +1,78 @@ package systems.brn.server_storage.screens; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.entity.player.PlayerInventory; +import eu.pb4.sgui.api.ClickType; +import eu.pb4.sgui.api.elements.GuiElementBuilder; +import eu.pb4.sgui.api.elements.GuiElementInterface; import net.minecraft.inventory.Inventory; import net.minecraft.item.ItemStack; -import net.minecraft.screen.ScreenHandler; -import net.minecraft.screen.ScreenHandlerContext; -import net.minecraft.screen.slot.Slot; +import net.minecraft.screen.slot.SlotActionType; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.text.Text; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import systems.brn.server_storage.lib.PagedGui; -import static net.minecraft.screen.ScreenHandlerType.GENERIC_9X6; +import static systems.brn.server_storage.lib.StorageOperations.*; -public class StorageScreen extends ScreenHandler { +public class StorageScreen extends PagedGui { private Inventory inventory; + private final BlockPos pos; + private final ServerPlayerEntity player; + private final World world; - public StorageScreen(int syncId, PlayerInventory playerInventory, ScreenHandlerContext context, Inventory inventory) { - super(GENERIC_9X6, syncId); - this.inventory = inventory; - - // Add custom storage inventory slots (9x6 grid for example) - for (int row = 0; row < 6; ++row) { - for (int col = 0; col < 9; ++col) { - this.addSlot(new Slot(this.inventory, row * 9 + col, col, row)); - } - } + public StorageScreen(ServerPlayerEntity player, BlockPos pos) { + super(player, null); + this.player = player; + this.pos = pos; + this.world = player.getWorld(); + + this.setTitle(Text.literal("Networked storage system")); + this.setLockPlayerInventory(false); + this.updateDisplay(); + } + + @Override + protected void updateDisplay() { + this.inventory = getCombinedInventoryFromChests(world, pos); + super.updateDisplay(); + } + + @Override + protected int getPageAmount() { + int sizeX = 9; + int sizeY = 6; + return Math.ceilDivExact(this.inventory.size(), sizeX * sizeY); } @Override - public boolean canUse(PlayerEntity player) { - return true; // Add appropriate checks here + protected DisplayElement getElement(int id) { + if (this.inventory.size() > id) { + ItemStack itemStack = this.inventory.getStack(id); + GuiElementBuilder guiElement = GuiElementBuilder.from(itemStack); + return DisplayElement.of(guiElement); + } + return DisplayElement.empty(); } @Override - public ItemStack quickMove(PlayerEntity player, int index) { - ItemStack newStack = ItemStack.EMPTY; - Slot slot = this.slots.get(index); - if (slot.hasStack()) { - ItemStack originalStack = slot.getStack(); - newStack = originalStack.copy(); - if (index < this.inventory.size()) { - if (!this.insertItem(originalStack, this.inventory.size(), this.slots.size(), true)) { - return ItemStack.EMPTY; - } - } else if (!this.insertItem(originalStack, 0, this.inventory.size(), false)) { - return ItemStack.EMPTY; - } - if (originalStack.isEmpty()) { - slot.setStack(ItemStack.EMPTY); - } else { - slot.markDirty(); + public boolean onClick(int index, ClickType type, SlotActionType action, GuiElementInterface element) { + GuiElementInterface clickedElement = this.getSlot(index); + if (clickedElement != null) { + ItemStack clickedItem = clickedElement.getItemStack(); + if (tryRemoveItemStackFromChests(world, pos, clickedItem)) { + this.player.getInventory().insertStack(clickedItem); } } - return newStack; + this.updateDisplay(); + return false; + } + + @Override + public boolean insertItem(ItemStack stack, int startIndex, int endIndex, boolean fromLast) { + if(tryPutItemStackIntoChests(world, pos, stack)){ + removeFromInventory(player.getInventory(), stack, stack.getCount()); + } + this.updateDisplay(); + return super.insertItem(stack, startIndex, endIndex, fromLast); } } diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 5b930cb..4bd896d 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -16,9 +16,6 @@ "systems.brn.server_storage.ServerStorage" ] }, - "mixins": [ - "server_storage.mixins.json" - ], "depends": { "fabricloader": ">=${loader_version}", "fabric": "*", diff --git a/src/main/resources/server_storage.mixins.json b/src/main/resources/server_storage.mixins.json deleted file mode 100644 index 8b1c9c1..0000000 --- a/src/main/resources/server_storage.mixins.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "required": true, - "minVersion": "0.8", - "package": "systems.brn.server_storage.mixin", - "compatibilityLevel": "JAVA_21", - "mixins": [ - ], - "injectors": { - "defaultRequire": 1 - } -}