diff --git a/src/main/kotlin/net/shadowfacts/extrahoppers/ExtraHoppers.kt b/src/main/kotlin/net/shadowfacts/extrahoppers/ExtraHoppers.kt index c27f883..82ec65a 100644 --- a/src/main/kotlin/net/shadowfacts/extrahoppers/ExtraHoppers.kt +++ b/src/main/kotlin/net/shadowfacts/extrahoppers/ExtraHoppers.kt @@ -1,6 +1,9 @@ package net.shadowfacts.extrahoppers import net.fabricmc.api.ModInitializer +import net.fabricmc.fabric.api.container.ContainerFactory +import net.fabricmc.fabric.api.container.ContainerProviderRegistry +import net.shadowfacts.extrahoppers.block.wood.WoodHopperContainer import net.shadowfacts.extrahoppers.init.EHBlockEntities import net.shadowfacts.extrahoppers.init.EHBlocks import net.shadowfacts.extrahoppers.init.EHItems @@ -8,13 +11,11 @@ import net.shadowfacts.extrahoppers.init.EHItems object ExtraHoppers: ModInitializer { override fun onInitialize() { - println("--------------------") - println("hello from extra hoppers") - println("--------------------") - EHBlocks.init() EHBlockEntities.init() EHItems.init() + + ContainerProviderRegistry.INSTANCE.registerFactory(WoodHopperContainer.ID, ContainerFactory(WoodHopperContainer.Companion::create)) } -} \ No newline at end of file +} diff --git a/src/main/kotlin/net/shadowfacts/extrahoppers/ExtraHoppersClient.kt b/src/main/kotlin/net/shadowfacts/extrahoppers/ExtraHoppersClient.kt new file mode 100644 index 0000000..64d2fc6 --- /dev/null +++ b/src/main/kotlin/net/shadowfacts/extrahoppers/ExtraHoppersClient.kt @@ -0,0 +1,15 @@ +package net.shadowfacts.extrahoppers + +import net.fabricmc.api.ClientModInitializer +import net.fabricmc.fabric.api.client.screen.ContainerScreenFactory +import net.fabricmc.fabric.api.client.screen.ScreenProviderRegistry +import net.shadowfacts.extrahoppers.block.wood.WoodHopperContainer +import net.shadowfacts.extrahoppers.block.wood.WoodHopperScreen + +object ExtraHoppersClient: ClientModInitializer { + + override fun onInitializeClient() { + ScreenProviderRegistry.INSTANCE.registerFactory(WoodHopperContainer.ID, ContainerScreenFactory(WoodHopperScreen.Companion::create)) + } + +} diff --git a/src/main/kotlin/net/shadowfacts/extrahoppers/block/wood/WoodHopperBlock.kt b/src/main/kotlin/net/shadowfacts/extrahoppers/block/wood/WoodHopperBlock.kt index 40fef83..bfcba06 100644 --- a/src/main/kotlin/net/shadowfacts/extrahoppers/block/wood/WoodHopperBlock.kt +++ b/src/main/kotlin/net/shadowfacts/extrahoppers/block/wood/WoodHopperBlock.kt @@ -1,13 +1,15 @@ package net.shadowfacts.extrahoppers.block.wood +import net.fabricmc.fabric.api.block.FabricBlockSettings +import net.fabricmc.fabric.api.container.ContainerProviderRegistry import net.minecraft.block.* import net.minecraft.block.entity.Hopper import net.minecraft.entity.Entity import net.minecraft.entity.EntityContext -import net.minecraft.entity.LivingEntity import net.minecraft.entity.player.PlayerEntity import net.minecraft.item.ItemPlacementContext -import net.minecraft.item.ItemStack +import net.minecraft.sound.BlockSoundGroup +import net.minecraft.stat.Stats import net.minecraft.state.StateManager import net.minecraft.state.property.Properties import net.minecraft.util.* @@ -23,7 +25,7 @@ import net.shadowfacts.extrahoppers.block.base.BlockWithEntity /** * @author shadowfacts */ -class WoodHopperBlock: BlockWithEntity(Settings.of(Material.WOOD)) { +class WoodHopperBlock: BlockWithEntity(FabricBlockSettings.of(Material.WOOD).strength(2f, 3f).sounds(BlockSoundGroup.WOOD).nonOpaque().build()) { companion object { val ID = Identifier("extrahoppers", "wood_hopper") @@ -83,28 +85,28 @@ class WoodHopperBlock: BlockWithEntity(Settings.of(Materi } override fun onUse(state: BlockState, world: World, pos: BlockPos, player: PlayerEntity, hand: Hand, hitResult: BlockHitResult): ActionResult { - // todo: container - return super.onUse(state, world, pos, player, hand, hitResult) + if (!world.isClient) { + player.incrementStat(Stats.INSPECT_HOPPER) + ContainerProviderRegistry.INSTANCE.openContainer(WoodHopperContainer.ID, player) { buf -> + buf.writeBlockPos(pos) + } + } + return ActionResult.SUCCESS } override fun onBlockRemoved(oldState: BlockState, world: World, pos: BlockPos, newState: BlockState, bl: Boolean) { if (oldState.block != newState.block) { getBlockEntity(world, pos)?.also { - // todo: spawn items -// ItemScatterer.spawn(world, pos, it) + ItemScatterer.spawn(world, pos, it) world.updateHorizontalAdjacent(pos, this) } + super.onBlockRemoved(oldState, world, pos, newState, bl) } - super.onBlockRemoved(oldState, world, pos, newState, bl) - } - - override fun getRenderType(blockState: BlockState?): BlockRenderType { - return BlockRenderType.MODEL } override fun onEntityCollision(state: BlockState, world: World, pos: BlockPos, entity: Entity) { getBlockEntity(world, pos)?.also { - // todo: handle entity collision + it.onEntityCollision(entity) } } diff --git a/src/main/kotlin/net/shadowfacts/extrahoppers/block/wood/WoodHopperBlockEntity.kt b/src/main/kotlin/net/shadowfacts/extrahoppers/block/wood/WoodHopperBlockEntity.kt index b25bc44..0e53179 100644 --- a/src/main/kotlin/net/shadowfacts/extrahoppers/block/wood/WoodHopperBlockEntity.kt +++ b/src/main/kotlin/net/shadowfacts/extrahoppers/block/wood/WoodHopperBlockEntity.kt @@ -3,15 +3,19 @@ package net.shadowfacts.extrahoppers.block.wood import net.minecraft.block.entity.BlockEntity import net.minecraft.block.entity.Hopper import net.minecraft.block.entity.HopperBlockEntity +import net.minecraft.entity.Entity +import net.minecraft.entity.ItemEntity import net.minecraft.entity.player.PlayerEntity import net.minecraft.inventory.Inventories import net.minecraft.inventory.Inventory import net.minecraft.inventory.SidedInventory import net.minecraft.item.ItemStack import net.minecraft.nbt.CompoundTag +import net.minecraft.util.BooleanBiFunction import net.minecraft.util.DefaultedList import net.minecraft.util.Tickable import net.minecraft.util.math.Direction +import net.minecraft.util.shape.VoxelShapes import net.shadowfacts.extrahoppers.init.EHBlockEntities import net.shadowfacts.extrahoppers.util.toVec3d @@ -50,7 +54,15 @@ class WoodHopperBlockEntity: BlockEntity(EHBlockEntities.WOOD_HOPPER), Inventory } } - fun insertAndExtract() { + fun onEntityCollision(entity: Entity) { + if (entity is ItemEntity) { + if (VoxelShapes.matchesAnywhere(VoxelShapes.cuboid(entity.boundingBox.offset(-pos.x.toDouble(), -pos.y.toDouble(), -pos.z.toDouble())), inputAreaShape, BooleanBiFunction.AND)) { + insertAndExtract() + } + } + } + + fun insertAndExtract(extractor: (() -> Boolean)? = null) { val world = world if (world == null || world.isClient) return @@ -58,7 +70,7 @@ class WoodHopperBlockEntity: BlockEntity(EHBlockEntities.WOOD_HOPPER), Inventory if (!isInvEmpty && insert()) { didWork = true } - if (!isFull() && HopperBlockEntity.extract(this)) { + if (!isFull() && ((extractor != null && extractor()) || HopperBlockEntity.extract(this))) { didWork = true } diff --git a/src/main/kotlin/net/shadowfacts/extrahoppers/block/wood/WoodHopperContainer.kt b/src/main/kotlin/net/shadowfacts/extrahoppers/block/wood/WoodHopperContainer.kt new file mode 100644 index 0000000..009284e --- /dev/null +++ b/src/main/kotlin/net/shadowfacts/extrahoppers/block/wood/WoodHopperContainer.kt @@ -0,0 +1,74 @@ +package net.shadowfacts.extrahoppers.block.wood + +import net.minecraft.container.Container +import net.minecraft.container.Slot +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.util.Identifier +import net.minecraft.util.PacketByteBuf +import net.shadowfacts.extrahoppers.init.EHBlocks + +class WoodHopperContainer(syncId: Int, playerInv: PlayerInventory, val hopperInv: Inventory): Container(null, syncId) { + + companion object { + val ID = Identifier("extrahoppers", "wood_hopper") + + fun create(syncId: Int, identifier: Identifier, player: PlayerEntity, buf: PacketByteBuf): WoodHopperContainer { + val pos = buf.readBlockPos() + val blockEntity = EHBlocks.WOOD_HOPPER.getBlockEntity(player.world, pos)!! + return WoodHopperContainer(syncId, player.inventory, blockEntity) + } + } + + init { + addSlot(Slot(hopperInv, 0, 80, 20)) + + // player inv + for (y in 0 until 3) { + for (x in 0 until 9) { + addSlot(Slot(playerInv, x + y * 9 + 9, 8 + x * 18, 51 + y * 18)) + } + } + // hotbar + for (x in 0 until 9) { + addSlot(Slot(playerInv, x, 8 + x * 18, 109)) + } + } + + override fun canUse(player: PlayerEntity): Boolean { + return true + } + + override fun close(player: PlayerEntity) { + super.close(player) + + hopperInv.onInvClose(player) + } + + override fun transferSlot(player: PlayerEntity, slotIndex: Int): ItemStack { + var remaining = ItemStack.EMPTY + val slot = slots[slotIndex] + if (slot != null && slot.hasStack()) { + val slotStack = slot.stack + remaining = slotStack.copy() + if (slotIndex < hopperInv.invSize) { + if (!insertItem(slotStack, hopperInv.invSize, slots.size, true)) { + return ItemStack.EMPTY; + } + } else if (!insertItem(slotStack, 0, hopperInv.invSize, false)) { + return ItemStack.EMPTY; + } + + if (slotStack.isEmpty) { + slot.stack = ItemStack.EMPTY; + } else { + slot.markDirty() + } + } + + return remaining + } + +} diff --git a/src/main/kotlin/net/shadowfacts/extrahoppers/block/wood/WoodHopperScreen.kt b/src/main/kotlin/net/shadowfacts/extrahoppers/block/wood/WoodHopperScreen.kt new file mode 100644 index 0000000..f59925d --- /dev/null +++ b/src/main/kotlin/net/shadowfacts/extrahoppers/block/wood/WoodHopperScreen.kt @@ -0,0 +1,37 @@ +package net.shadowfacts.extrahoppers.block.wood + +import com.mojang.blaze3d.platform.GlStateManager +import net.minecraft.client.MinecraftClient +import net.minecraft.client.gui.screen.ingame.ContainerScreen +import net.minecraft.entity.player.PlayerInventory +import net.minecraft.text.LiteralText +import net.minecraft.util.Identifier + +class WoodHopperScreen(container: WoodHopperContainer, playerInv: PlayerInventory): ContainerScreen(container, playerInv, LiteralText("Wooden Hopper")) { + + companion object { + val BACKGROUND = Identifier("extrahoppers", "textures/gui/wood_hopper.png") + + fun create(container: WoodHopperContainer): WoodHopperScreen { + return WoodHopperScreen(container, MinecraftClient.getInstance().player!!.inventory) + } + } + + init { + containerHeight = 133 + } + + override fun drawForeground(mouseX: Int, mouseY: Int) { + font.draw(title.asFormattedString(), 8f, 6f, 0x404040) + font.draw(playerInventory.displayName.asFormattedString(), 8f, containerHeight - 94f, 0x404040) + } + + override fun drawBackground(f: Float, i: Int, j: Int) { + GlStateManager.color4f(1f, 1f, 1f, 1f) + minecraft!!.textureManager.bindTexture(BACKGROUND) + val x = (width - containerWidth) / 2 + val y = (height - containerHeight) / 2 + blit(x, y, 0, 0, containerWidth, containerHeight) + } + +} diff --git a/src/main/resources/assets/extrahoppers/textures/gui/wood_hopper.png b/src/main/resources/assets/extrahoppers/textures/gui/wood_hopper.png new file mode 100644 index 0000000..43c21b9 Binary files /dev/null and b/src/main/resources/assets/extrahoppers/textures/gui/wood_hopper.png differ diff --git a/src/main/resources/data/extrahoppers/advancements/recipes/wood_hopper.json b/src/main/resources/data/extrahoppers/advancements/recipes/wood_hopper.json new file mode 100644 index 0000000..6306776 --- /dev/null +++ b/src/main/resources/data/extrahoppers/advancements/recipes/wood_hopper.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "rewards": { + "recipes": [ + "extrahoppers:wood_hopper" + ] + }, + "criteria": { + "has_logs_and_chest": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "tag": "minecraft:logs" + }, + { + "item": "minecraft:chest" + } + ] + } + }, + "has_the_recipe": { + "trigger": "minecraft:recipe_unlocked", + "conditions": { + "recipe": "extrahoppers:wood_hopper" + } + } + }, + "requirements": [ + [ + "has_logs_and_chest", + "has_the_recipe" + ] + ] +} diff --git a/src/main/resources/data/extrahoppers/loot_tables/blocks/wood_hopper.json b/src/main/resources/data/extrahoppers/loot_tables/blocks/wood_hopper.json new file mode 100644 index 0000000..b1d9f1e --- /dev/null +++ b/src/main/resources/data/extrahoppers/loot_tables/blocks/wood_hopper.json @@ -0,0 +1,19 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "rolls": 1, + "entries": [ + { + "type": "minecraft:item", + "name": "extrahoppers:wood_hopper" + } + ], + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ] + } + ] +} diff --git a/src/main/resources/data/extrahoppers/recipes/wood_hopper.json b/src/main/resources/data/extrahoppers/recipes/wood_hopper.json new file mode 100644 index 0000000..eea9f99 --- /dev/null +++ b/src/main/resources/data/extrahoppers/recipes/wood_hopper.json @@ -0,0 +1,19 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "L L", + "LCL", + " L " + ], + "key": { + "C": { + "item": "minecraft:chest" + }, + "L": { + "tag": "minecraft:logs" + } + }, + "result": { + "item": "extrahoppers:wood_hopper" + } +} diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 6790b4f..74efd05 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -9,6 +9,12 @@ "adapter": "kotlin", "value": "net.shadowfacts.extrahoppers.ExtraHoppers" } + ], + "client": [ + { + "adapter": "kotlin", + "value": "net.shadowfacts.extrahoppers.ExtraHoppersClient" + } ] }, "depends": {