Add Golden Hopper

This commit is contained in:
Shadowfacts 2020-03-28 14:26:39 -04:00
parent 7b134f688d
commit e9e28f5625
Signed by: shadowfacts
GPG Key ID: 94A5AB95422746E5
22 changed files with 400 additions and 78 deletions

View File

@ -3,6 +3,7 @@ package net.shadowfacts.extrahoppers
import net.fabricmc.api.ModInitializer import net.fabricmc.api.ModInitializer
import net.fabricmc.fabric.api.container.ContainerFactory import net.fabricmc.fabric.api.container.ContainerFactory
import net.fabricmc.fabric.api.container.ContainerProviderRegistry import net.fabricmc.fabric.api.container.ContainerProviderRegistry
import net.shadowfacts.extrahoppers.block.gold.GoldHopperContainer
import net.shadowfacts.extrahoppers.block.wood.WoodHopperContainer import net.shadowfacts.extrahoppers.block.wood.WoodHopperContainer
import net.shadowfacts.extrahoppers.init.EHBlockEntities import net.shadowfacts.extrahoppers.init.EHBlockEntities
import net.shadowfacts.extrahoppers.init.EHBlocks import net.shadowfacts.extrahoppers.init.EHBlocks
@ -16,6 +17,7 @@ object ExtraHoppers: ModInitializer {
EHItems.init() EHItems.init()
ContainerProviderRegistry.INSTANCE.registerFactory(WoodHopperContainer.ID, ContainerFactory(WoodHopperContainer.Companion::create)) ContainerProviderRegistry.INSTANCE.registerFactory(WoodHopperContainer.ID, ContainerFactory(WoodHopperContainer.Companion::create))
ContainerProviderRegistry.INSTANCE.registerFactory(GoldHopperContainer.ID, ContainerFactory(GoldHopperContainer.Companion::create))
} }
} }

View File

@ -3,6 +3,8 @@ package net.shadowfacts.extrahoppers
import net.fabricmc.api.ClientModInitializer import net.fabricmc.api.ClientModInitializer
import net.fabricmc.fabric.api.client.screen.ContainerScreenFactory import net.fabricmc.fabric.api.client.screen.ContainerScreenFactory
import net.fabricmc.fabric.api.client.screen.ScreenProviderRegistry import net.fabricmc.fabric.api.client.screen.ScreenProviderRegistry
import net.shadowfacts.extrahoppers.block.gold.GoldHopperContainer
import net.shadowfacts.extrahoppers.block.gold.GoldHopperScreen
import net.shadowfacts.extrahoppers.block.wood.WoodHopperContainer import net.shadowfacts.extrahoppers.block.wood.WoodHopperContainer
import net.shadowfacts.extrahoppers.block.wood.WoodHopperScreen import net.shadowfacts.extrahoppers.block.wood.WoodHopperScreen
@ -10,6 +12,7 @@ object ExtraHoppersClient: ClientModInitializer {
override fun onInitializeClient() { override fun onInitializeClient() {
ScreenProviderRegistry.INSTANCE.registerFactory(WoodHopperContainer.ID, ContainerScreenFactory(WoodHopperScreen.Companion::create)) ScreenProviderRegistry.INSTANCE.registerFactory(WoodHopperContainer.ID, ContainerScreenFactory(WoodHopperScreen.Companion::create))
ScreenProviderRegistry.INSTANCE.registerFactory(GoldHopperContainer.ID, ContainerScreenFactory(GoldHopperScreen.Companion::create))
} }
} }

View File

@ -24,9 +24,9 @@ import net.shadowfacts.extrahoppers.util.toVec3d
*/ */
abstract class BaseHopperBlockEntity(type: BlockEntityType<*>): BlockEntity(type), Inventory, Hopper, Tickable { abstract class BaseHopperBlockEntity(type: BlockEntityType<*>): BlockEntity(type), Inventory, Hopper, Tickable {
protected open val inventorySize = 5 abstract val inventorySize: Int
protected open val maxTransferCooldown = 8 abstract val maxTransferCooldown: Int
var inventory: DefaultedList<ItemStack> = DefaultedList.ofSize(inventorySize, ItemStack.EMPTY) val inventory: DefaultedList<ItemStack> by lazy { DefaultedList.ofSize(inventorySize, ItemStack.EMPTY) }
protected var transferCooldown = -1 protected var transferCooldown = -1
override fun toTag(tag: CompoundTag): CompoundTag { override fun toTag(tag: CompoundTag): CompoundTag {

View File

@ -0,0 +1,70 @@
package net.shadowfacts.extrahoppers.block.base
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
/**
* @author shadowfacts
*/
abstract class BaseHopperContainer(
syncId: Int,
playerInv: PlayerInventory,
val hopperInv: Inventory
): Container(null, syncId) {
init {
addHopperSlots()
// 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))
}
}
abstract fun addHopperSlots()
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
}
}

View File

@ -0,0 +1,37 @@
package net.shadowfacts.extrahoppers.block.base
import com.mojang.blaze3d.platform.GlStateManager
import net.minecraft.client.gui.screen.ingame.ContainerScreen
import net.minecraft.entity.player.PlayerInventory
import net.minecraft.text.Text
import net.minecraft.util.Identifier
/**
* @author shadowfacts
*/
abstract class BaseHopperScreen<T: BaseHopperContainer>(
container: T,
playerInv: PlayerInventory,
title: Text
): ContainerScreen<T>(container, playerInv, title) {
abstract val background: Identifier
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(delta: Float, mouseX: Int, mouseY: 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)
}
}

View File

@ -0,0 +1,46 @@
package net.shadowfacts.extrahoppers.block.gold
import net.fabricmc.fabric.api.block.FabricBlockSettings
import net.fabricmc.fabric.api.container.ContainerProviderRegistry
import net.minecraft.block.BlockState
import net.minecraft.block.Material
import net.minecraft.entity.player.PlayerEntity
import net.minecraft.sound.BlockSoundGroup
import net.minecraft.stat.Stats
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.world.BlockView
import net.minecraft.world.World
import net.shadowfacts.extrahoppers.block.base.BaseHopperBlock
/**
* @author shadowfacts
*/
class GoldHopperBlock: BaseHopperBlock<GoldHopperBlockEntity>(
FabricBlockSettings.of(Material.METAL)
.strength(3f, 6f)
.sounds(BlockSoundGroup.METAL)
.nonOpaque()
.build()
) {
companion object {
val ID = Identifier("extrahoppers", "gold_hopper")
}
override fun createBlockEntity(world: BlockView) = GoldHopperBlockEntity()
override fun onUse(state: BlockState, world: World, pos: BlockPos, player: PlayerEntity, hand: Hand, hitResult: BlockHitResult): ActionResult {
if (!world.isClient) {
player.incrementStat(Stats.INSPECT_HOPPER)
ContainerProviderRegistry.INSTANCE.openContainer(GoldHopperContainer.ID, player) { buf ->
buf.writeBlockPos(pos)
}
}
return ActionResult.SUCCESS
}
}

View File

@ -0,0 +1,14 @@
package net.shadowfacts.extrahoppers.block.gold
import net.shadowfacts.extrahoppers.block.base.BaseHopperBlockEntity
import net.shadowfacts.extrahoppers.init.EHBlockEntities
/**
* @author shadowfacts
*/
class GoldHopperBlockEntity: BaseHopperBlockEntity(EHBlockEntities.GOLD_HOPPER) {
override val inventorySize = 5
override val maxTransferCooldown = 4
}

View File

@ -0,0 +1,37 @@
package net.shadowfacts.extrahoppers.block.gold
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.util.Identifier
import net.minecraft.util.PacketByteBuf
import net.shadowfacts.extrahoppers.block.base.BaseHopperContainer
import net.shadowfacts.extrahoppers.init.EHBlocks
/**
* @author shadowfacts
*/
class GoldHopperContainer(
syncId: Int,
playerInv: PlayerInventory,
hopperInv: Inventory
): BaseHopperContainer(syncId, playerInv, hopperInv) {
companion object {
val ID = Identifier("extrahoppers", "gold_hopper")
fun create(syncId: Int, identifier: Identifier, player: PlayerEntity, buf: PacketByteBuf): GoldHopperContainer {
val pos = buf.readBlockPos()
val blockEntity = EHBlocks.GOLD_HOPPER.getBlockEntity(player.world, pos)!!
return GoldHopperContainer(syncId, player.inventory, blockEntity)
}
}
override fun addHopperSlots() {
for (i in 0 until 5) {
addSlot(Slot(hopperInv, i, 44 + i * 18, 20))
}
}
}

View File

@ -0,0 +1,24 @@
package net.shadowfacts.extrahoppers.block.gold
import net.minecraft.client.MinecraftClient
import net.minecraft.entity.player.PlayerInventory
import net.minecraft.text.TranslatableText
import net.minecraft.util.Identifier
import net.shadowfacts.extrahoppers.block.base.BaseHopperScreen
/**
* @author shadowfacts
*/
class GoldHopperScreen(
container: GoldHopperContainer,
playerInv: PlayerInventory
): BaseHopperScreen<GoldHopperContainer>(container, playerInv, TranslatableText("block.extrahoppers.gold_hopper")) {
companion object {
fun create(container: GoldHopperContainer): GoldHopperScreen {
return GoldHopperScreen(container, MinecraftClient.getInstance().player!!.inventory)
}
}
override val background = Identifier("minecraft", "textures/gui/container/hopper.png")
}

View File

@ -1,16 +1,19 @@
package net.shadowfacts.extrahoppers.block.wood package net.shadowfacts.extrahoppers.block.wood
import net.minecraft.container.Container
import net.minecraft.container.Slot import net.minecraft.container.Slot
import net.minecraft.entity.player.PlayerEntity import net.minecraft.entity.player.PlayerEntity
import net.minecraft.entity.player.PlayerInventory import net.minecraft.entity.player.PlayerInventory
import net.minecraft.inventory.Inventory import net.minecraft.inventory.Inventory
import net.minecraft.item.ItemStack
import net.minecraft.util.Identifier import net.minecraft.util.Identifier
import net.minecraft.util.PacketByteBuf import net.minecraft.util.PacketByteBuf
import net.shadowfacts.extrahoppers.block.base.BaseHopperContainer
import net.shadowfacts.extrahoppers.init.EHBlocks import net.shadowfacts.extrahoppers.init.EHBlocks
class WoodHopperContainer(syncId: Int, playerInv: PlayerInventory, val hopperInv: Inventory): Container(null, syncId) { class WoodHopperContainer(
syncId: Int,
playerInv: PlayerInventory,
hopperInv: Inventory
): BaseHopperContainer(syncId, playerInv, hopperInv) {
companion object { companion object {
val ID = Identifier("extrahoppers", "wood_hopper") val ID = Identifier("extrahoppers", "wood_hopper")
@ -22,53 +25,8 @@ class WoodHopperContainer(syncId: Int, playerInv: PlayerInventory, val hopperInv
} }
} }
init { override fun addHopperSlots() {
addSlot(Slot(hopperInv, 0, 80, 20)) 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
} }
} }

View File

@ -1,37 +1,22 @@
package net.shadowfacts.extrahoppers.block.wood package net.shadowfacts.extrahoppers.block.wood
import com.mojang.blaze3d.platform.GlStateManager
import net.minecraft.client.MinecraftClient import net.minecraft.client.MinecraftClient
import net.minecraft.client.gui.screen.ingame.ContainerScreen
import net.minecraft.entity.player.PlayerInventory import net.minecraft.entity.player.PlayerInventory
import net.minecraft.text.LiteralText import net.minecraft.text.TranslatableText
import net.minecraft.util.Identifier import net.minecraft.util.Identifier
import net.shadowfacts.extrahoppers.block.base.BaseHopperScreen
class WoodHopperScreen(container: WoodHopperContainer, playerInv: PlayerInventory): ContainerScreen<WoodHopperContainer>(container, playerInv, LiteralText("Wooden Hopper")) { class WoodHopperScreen(
container: WoodHopperContainer,
playerInv: PlayerInventory
): BaseHopperScreen<WoodHopperContainer>(container, playerInv, TranslatableText("block.extrahoppers.gold_hopper")) {
companion object { companion object {
val BACKGROUND = Identifier("extrahoppers", "textures/gui/wood_hopper.png")
fun create(container: WoodHopperContainer): WoodHopperScreen { fun create(container: WoodHopperContainer): WoodHopperScreen {
return WoodHopperScreen(container, MinecraftClient.getInstance().player!!.inventory) return WoodHopperScreen(container, MinecraftClient.getInstance().player!!.inventory)
} }
} }
init { override val background = Identifier("extrahoppers", "textures/gui/wood_hopper.png")
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)
}
} }

View File

@ -5,15 +5,19 @@ import net.minecraft.block.entity.BlockEntity
import net.minecraft.block.entity.BlockEntityType import net.minecraft.block.entity.BlockEntityType
import net.minecraft.util.Identifier import net.minecraft.util.Identifier
import net.minecraft.util.registry.Registry import net.minecraft.util.registry.Registry
import net.shadowfacts.extrahoppers.block.gold.GoldHopperBlock
import net.shadowfacts.extrahoppers.block.gold.GoldHopperBlockEntity
import net.shadowfacts.extrahoppers.block.wood.WoodHopperBlock import net.shadowfacts.extrahoppers.block.wood.WoodHopperBlock
import net.shadowfacts.extrahoppers.block.wood.WoodHopperBlockEntity import net.shadowfacts.extrahoppers.block.wood.WoodHopperBlockEntity
object EHBlockEntities { object EHBlockEntities {
val WOOD_HOPPER = create(::WoodHopperBlockEntity, EHBlocks.WOOD_HOPPER) val WOOD_HOPPER = create(::WoodHopperBlockEntity, EHBlocks.WOOD_HOPPER)
val GOLD_HOPPER = create(::GoldHopperBlockEntity, EHBlocks.GOLD_HOPPER)
fun init() { fun init() {
register(WoodHopperBlock.ID, WOOD_HOPPER) register(WoodHopperBlock.ID, WOOD_HOPPER)
register(GoldHopperBlock.ID, GOLD_HOPPER)
} }
private fun <T: BlockEntity> create(builder: () -> T, block: Block): BlockEntityType<T> { private fun <T: BlockEntity> create(builder: () -> T, block: Block): BlockEntityType<T> {

View File

@ -3,14 +3,17 @@ package net.shadowfacts.extrahoppers.init
import net.minecraft.block.Block import net.minecraft.block.Block
import net.minecraft.util.Identifier import net.minecraft.util.Identifier
import net.minecraft.util.registry.Registry import net.minecraft.util.registry.Registry
import net.shadowfacts.extrahoppers.block.gold.GoldHopperBlock
import net.shadowfacts.extrahoppers.block.wood.WoodHopperBlock import net.shadowfacts.extrahoppers.block.wood.WoodHopperBlock
object EHBlocks { object EHBlocks {
val WOOD_HOPPER = WoodHopperBlock() val WOOD_HOPPER = WoodHopperBlock()
val GOLD_HOPPER = GoldHopperBlock()
fun init() { fun init() {
register(WoodHopperBlock.ID, WOOD_HOPPER) register(WoodHopperBlock.ID, WOOD_HOPPER)
register(GoldHopperBlock.ID, GOLD_HOPPER)
} }
private fun register(id: Identifier, block: Block) { private fun register(id: Identifier, block: Block) {

View File

@ -4,14 +4,17 @@ import net.minecraft.item.BlockItem
import net.minecraft.item.Item import net.minecraft.item.Item
import net.minecraft.util.Identifier import net.minecraft.util.Identifier
import net.minecraft.util.registry.Registry import net.minecraft.util.registry.Registry
import net.shadowfacts.extrahoppers.block.gold.GoldHopperBlock
import net.shadowfacts.extrahoppers.block.wood.WoodHopperBlock import net.shadowfacts.extrahoppers.block.wood.WoodHopperBlock
object EHItems { object EHItems {
val WOOD_HOPPER = BlockItem(EHBlocks.WOOD_HOPPER, Item.Settings()) val WOOD_HOPPER = BlockItem(EHBlocks.WOOD_HOPPER, Item.Settings())
val GOLD_HOPPER = BlockItem(EHBlocks.GOLD_HOPPER, Item.Settings())
fun init() { fun init() {
register(WoodHopperBlock.ID, WOOD_HOPPER) register(WoodHopperBlock.ID, WOOD_HOPPER)
register(GoldHopperBlock.ID, GOLD_HOPPER)
} }
private fun register(id: Identifier, item: Item) { private fun register(id: Identifier, item: Item) {

View File

@ -0,0 +1,9 @@
{
"variants": {
"facing=down": { "model": "extrahoppers:block/gold_hopper" },
"facing=north": { "model": "extrahoppers:block/gold_hopper_side" },
"facing=south": { "model": "extrahoppers:block/gold_hopper_side", "y": 180 },
"facing=west": { "model": "extrahoppers:block/gold_hopper_side", "y": 270 },
"facing=east": { "model": "extrahoppers:block/gold_hopper_side", "y": 90 }
}
}

View File

@ -1,3 +1,4 @@
{ {
"block.extrahoppers.wood_hopper": "Wooden Hopper" "block.extrahoppers.wood_hopper": "Wooden Hopper",
"block.extrahoppers.gold_hopper": "Golden Hopper"
} }

View File

@ -0,0 +1,41 @@
{
"parent": "block/hopper",
"textures": {
"particle": "block/gold_block",
"top": "block/gold_block",
"side": "block/gold_block",
"inside": "block/gold_block"
},
"display": {
"gui": {
"rotation": [ 30, 225, 0 ],
"translation": [ 0, 0, 0],
"scale":[ 0.625, 0.625, 0.625 ]
},
"ground": {
"rotation": [ 0, 0, 0 ],
"translation": [ 0, 3, 0],
"scale":[ 0.25, 0.25, 0.25 ]
},
"fixed": {
"rotation": [ 0, 0, 0 ],
"translation": [ 0, 0, 0],
"scale":[ 0.5, 0.5, 0.5 ]
},
"thirdperson_righthand": {
"rotation": [ 75, 45, 0 ],
"translation": [ 0, 2.5, 0],
"scale": [ 0.375, 0.375, 0.375 ]
},
"firstperson_righthand": {
"rotation": [ 0, 45, 0 ],
"translation": [ 0, 0, 0 ],
"scale": [ 0.40, 0.40, 0.40 ]
},
"firstperson_lefthand": {
"rotation": [ 0, 225, 0 ],
"translation": [ 0, 0, 0 ],
"scale": [ 0.40, 0.40, 0.40 ]
}
}
}

View File

@ -0,0 +1,9 @@
{
"parent": "block/hopper_side",
"textures": {
"particle": "block/gold_block",
"top": "block/gold_block",
"side": "block/gold_block",
"inside": "block/gold_block"
}
}

View File

@ -0,0 +1,3 @@
{
"parent": "extrahoppers:block/gold_hopper"
}

View File

@ -0,0 +1,35 @@
{
"parent": "minecraft:recipes/root",
"rewards": {
"recipes": [
"extrahoppers:gold_hopper"
]
},
"criteria": {
"has_hopper_and_gold": {
"trigger": "minecraft:inventory_changed",
"conditions": {
"items": [
{
"item": "minecraft:hopper"
},
{
"item": "minecraft:gold_ingot"
}
]
}
},
"has_the_recipe": {
"trigger": "minecraft:recipe_unlocked",
"conditions": {
"recipe": "extrahoppers:gold_hopper"
}
}
},
"requirements": [
[
"has_hopper_and_gold",
"has_the_recipe"
]
]
}

View File

@ -0,0 +1,19 @@
{
"type": "minecraft:block",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "extrahoppers:gold_hopper"
}
],
"conditions": [
{
"condition": "minecraft:survives_explosion"
}
]
}
]
}

View File

@ -0,0 +1,19 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
"G G",
"GCG",
" G "
],
"key": {
"C": {
"item": "minecraft:chest"
},
"G": {
"item": "minecraft:gold_ingot"
}
},
"result": {
"item": "extrahoppers:gold_hopper"
}
}