diff --git a/build.gradle b/build.gradle index b4dff6d..9e3b95d 100644 --- a/build.gradle +++ b/build.gradle @@ -33,6 +33,7 @@ dependencies { modImplementation include("eu.pb4:polymer-autohost:${project.polymer_version}") modImplementation include("eu.pb4:polymer-blocks:${project.polymer_version}") include(modImplementation("xyz.nucleoid:server-translations-api:${project.server_translations_api_version}")) + modImplementation include("eu.pb4:sgui:${project.servergui_version}") } diff --git a/gradle.properties b/gradle.properties index 64031ff..2a9773a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -16,3 +16,4 @@ archives_base_name=Server_storage fabric_version=0.99.0+1.20.6 polymer_version=0.8.0+1.20.6 server_translations_api_version=2.3.0+1.20.5-rc2 +servergui_version=1.5.1+1.20.5 \ No newline at end of file diff --git a/src/main/java/systems/brn/server_storage/ServerStorage.java b/src/main/java/systems/brn/server_storage/ServerStorage.java index 66ff2b9..d922a9c 100644 --- a/src/main/java/systems/brn/server_storage/ServerStorage.java +++ b/src/main/java/systems/brn/server_storage/ServerStorage.java @@ -2,21 +2,26 @@ 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; 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() { - PolymerResourcePackUtils.addModAssets(MODID); PolymerResourcePackUtils.markAsRequired(); StorageBlock.register(); + StorageBlockItem.register(); + StorageBlockEntity.register(); } - public static StorageBlock JUMP_VADER_BLOCK; } diff --git a/src/main/java/systems/brn/server_storage/blockEntities/StorageBlockEntity.java b/src/main/java/systems/brn/server_storage/blockEntities/StorageBlockEntity.java new file mode 100644 index 0000000..14bfd15 --- /dev/null +++ b/src/main/java/systems/brn/server_storage/blockEntities/StorageBlockEntity.java @@ -0,0 +1,70 @@ +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 886625e..92d6f2a 100644 --- a/src/main/java/systems/brn/server_storage/blocks/StorageBlock.java +++ b/src/main/java/systems/brn/server_storage/blocks/StorageBlock.java @@ -4,16 +4,39 @@ import eu.pb4.polymer.blocks.api.BlockModelType; import eu.pb4.polymer.blocks.api.PolymerBlockModel; import eu.pb4.polymer.blocks.api.PolymerBlockResourceUtils; import eu.pb4.polymer.blocks.api.PolymerTexturedBlock; +import net.fabricmc.fabric.api.event.player.UseBlockCallback; 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.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.items.StorageBlockItem; +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 { @@ -31,9 +54,88 @@ public class StorageBlock extends Block implements PolymerTexturedBlock { public static void register() { var modId = new Identifier(ServerStorage.MODID, ServerStorage.MODELID); - var block = Registry.register(Registries.BLOCK, modId, + STORAGE_BLOCK = Registry.register(Registries.BLOCK, modId, new StorageBlock(AbstractBlock.Settings.copy(Blocks.WHITE_WOOL), BlockModelType.FULL_BLOCK, ServerStorage.MODELID)); - - Registry.register(Registries.ITEM, modId, new StorageBlockItem(new Item.Settings(), block, ServerStorage.MODELID)); + 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); + Block block = state.getBlock(); + + 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); + } + } + return ActionResult.SUCCESS; + } + return ActionResult.PASS; + } + } 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 5eaff71..8ed689e 100644 --- a/src/main/java/systems/brn/server_storage/items/StorageBlockItem.java +++ b/src/main/java/systems/brn/server_storage/items/StorageBlockItem.java @@ -3,16 +3,18 @@ package systems.brn.server_storage.items; import eu.pb4.polymer.core.api.item.PolymerItem; import eu.pb4.polymer.resourcepack.api.PolymerModelData; import eu.pb4.polymer.resourcepack.api.PolymerResourcePackUtils; +import net.fabricmc.fabric.api.itemgroup.v1.ItemGroupEvents; import net.minecraft.block.Block; -import net.minecraft.item.BlockItem; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.item.Items; +import net.minecraft.item.*; +import net.minecraft.registry.Registries; +import net.minecraft.registry.Registry; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.util.Identifier; import org.jetbrains.annotations.Nullable; import systems.brn.server_storage.ServerStorage; +import static systems.brn.server_storage.ServerStorage.STORAGE_BLOCK; + public class StorageBlockItem extends BlockItem implements PolymerItem { private final PolymerModelData polymerModel; @@ -30,4 +32,12 @@ public class StorageBlockItem extends BlockItem implements PolymerItem { public int getPolymerCustomModelData(ItemStack itemStack, @Nullable ServerPlayerEntity player) { return this.polymerModel.value(); } + + 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); + }); + } } \ No newline at end of file diff --git a/src/main/java/systems/brn/server_storage/screens/StorageScreen.java b/src/main/java/systems/brn/server_storage/screens/StorageScreen.java new file mode 100644 index 0000000..d24b63e --- /dev/null +++ b/src/main/java/systems/brn/server_storage/screens/StorageScreen.java @@ -0,0 +1,55 @@ +package systems.brn.server_storage.screens; + +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.player.PlayerInventory; +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 static net.minecraft.screen.ScreenHandlerType.GENERIC_9X6; + +public class StorageScreen extends ScreenHandler { + private Inventory inventory; + + 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)); + } + } + } + + @Override + public boolean canUse(PlayerEntity player) { + return true; // Add appropriate checks here + } + + @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(); + } + } + return newStack; + } +}