Skip to content

Commit 1abe10b

Browse files
committed
feat(wire_basket): storage interface
1 parent 6d8d9a0 commit 1abe10b

5 files changed

Lines changed: 203 additions & 2 deletions

File tree

src/client/kotlin/dev/hybridlabs/albob/data/client/LanguageProvider.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ internal class LanguageProvider(output: FabricDataOutput) : FabricLanguageProvid
1212
registerBlocks(builder)
1313

1414
builder.add("${ALBOB.MOD_ID}.container.metal_drum", "Metal Drum")
15+
builder.add("${ALBOB.MOD_ID}.container.wire_basket", "Wire Basket")
1516
}
1617

1718
private fun registerBlocks(builder: TranslationBuilder) {

src/main/generated/assets/albob/lang/en_us.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{
22
"albob.container.metal_drum": "Metal Drum",
3+
"albob.container.wire_basket": "Wire Basket",
34
"block.albob.black_concrete_slab": "Black Concrete Slab",
45
"block.albob.black_concrete_stairs": "Black Concrete Stairs",
56
"block.albob.black_concrete_wall": "Black Concrete Wall",

src/main/kotlin/dev/hybridlabs/albob/block/WireBasketBlock.kt

Lines changed: 78 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,39 @@
1-
@file:Suppress("OVERRIDE_DEPRECATION")
1+
@file:Suppress("OVERRIDE_DEPRECATION", "DEPRECATION")
22

33
package dev.hybridlabs.albob.block
44

5+
import dev.hybridlabs.albob.block.entity.WireBasketBlockEntity
56
import net.minecraft.core.BlockPos
67
import net.minecraft.core.Direction
8+
import net.minecraft.server.level.ServerLevel
9+
import net.minecraft.util.RandomSource
10+
import net.minecraft.world.Container
11+
import net.minecraft.world.Containers
12+
import net.minecraft.world.InteractionHand
13+
import net.minecraft.world.InteractionResult
14+
import net.minecraft.world.entity.LivingEntity
15+
import net.minecraft.world.entity.monster.piglin.PiglinAi
16+
import net.minecraft.world.entity.player.Player
17+
import net.minecraft.world.inventory.AbstractContainerMenu
18+
import net.minecraft.world.item.ItemStack
719
import net.minecraft.world.item.context.BlockPlaceContext
820
import net.minecraft.world.level.BlockGetter
21+
import net.minecraft.world.level.Level
22+
import net.minecraft.world.level.block.BaseEntityBlock
923
import net.minecraft.world.level.block.Block
24+
import net.minecraft.world.level.block.RenderShape
1025
import net.minecraft.world.level.block.RotatedPillarBlock
1126
import net.minecraft.world.level.block.Rotation
27+
import net.minecraft.world.level.block.entity.BlockEntity
1228
import net.minecraft.world.level.block.state.BlockState
1329
import net.minecraft.world.level.block.state.StateDefinition
1430
import net.minecraft.world.level.block.state.properties.BlockStateProperties
1531
import net.minecraft.world.level.block.state.properties.EnumProperty
32+
import net.minecraft.world.phys.BlockHitResult
1633
import net.minecraft.world.phys.shapes.CollisionContext
1734
import net.minecraft.world.phys.shapes.VoxelShape
1835

19-
class WireBasketBlock(properties: Properties) : Block(properties) {
36+
class WireBasketBlock(properties: Properties) : BaseEntityBlock(properties) {
2037
init {
2138
registerDefaultState(
2239
stateDefinition.any()
@@ -44,6 +61,65 @@ class WireBasketBlock(properties: Properties) : Block(properties) {
4461
builder.add(HORIZONTAL_AXIS)
4562
}
4663

64+
override fun newBlockEntity(pos: BlockPos, state: BlockState): BlockEntity {
65+
return WireBasketBlockEntity(pos, state)
66+
}
67+
68+
override fun use(state: BlockState, level: Level, pos: BlockPos, player: Player, hand: InteractionHand, hit: BlockHitResult): InteractionResult {
69+
if (level.isClientSide) {
70+
return InteractionResult.SUCCESS
71+
} else {
72+
val blockEntity = level.getBlockEntity(pos)
73+
if (blockEntity is WireBasketBlockEntity) {
74+
player.openMenu(blockEntity)
75+
// player.awardStat(Stats.OPEN_BARREL) // TODO
76+
PiglinAi.angerNearbyPiglins(player, true)
77+
}
78+
79+
return InteractionResult.CONSUME
80+
}
81+
}
82+
83+
override fun onRemove(state: BlockState, level: Level, pos: BlockPos, otherState: BlockState, bl: Boolean) {
84+
if (!state.`is`(otherState.block)) {
85+
val blockEntity = level.getBlockEntity(pos)
86+
if (blockEntity is Container) {
87+
Containers.dropContents(level, pos, blockEntity as Container)
88+
level.updateNeighbourForOutputSignal(pos, this)
89+
}
90+
91+
super.onRemove(state, level, pos, otherState, bl)
92+
}
93+
}
94+
95+
override fun tick(state: BlockState, level: ServerLevel, pos: BlockPos, source: RandomSource) {
96+
val blockEntity = level.getBlockEntity(pos)
97+
if (blockEntity is WireBasketBlockEntity) {
98+
blockEntity.recheckOpen()
99+
}
100+
}
101+
102+
override fun getRenderShape(state: BlockState): RenderShape {
103+
return RenderShape.MODEL
104+
}
105+
106+
override fun setPlacedBy(level: Level, pos: BlockPos, state: BlockState, entity: LivingEntity?, stack: ItemStack) {
107+
if (stack.hasCustomHoverName()) {
108+
val blockEntity = level.getBlockEntity(pos)
109+
if (blockEntity is WireBasketBlockEntity) {
110+
blockEntity.customName = stack.getHoverName()
111+
}
112+
}
113+
}
114+
115+
override fun hasAnalogOutputSignal(state: BlockState): Boolean {
116+
return true
117+
}
118+
119+
override fun getAnalogOutputSignal(state: BlockState, level: Level, pos: BlockPos): Int {
120+
return AbstractContainerMenu.getRedstoneSignalFromBlockEntity(level.getBlockEntity(pos))
121+
}
122+
47123
companion object {
48124
val Z_SHAPE: VoxelShape = box(3.0, 0.0, 0.0, 13.0, 10.0, 16.0)
49125
val X_SHAPE: VoxelShape = box(0.0, 0.0, 3.0, 16.0, 10.0, 13.0)

src/main/kotlin/dev/hybridlabs/albob/block/entity/ALBOBlockEntityTypes.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ object ALBOBlockEntityTypes {
3131
ALBOBlocks.BLACK_OIL_DRUM,
3232
))
3333

34+
val WIRE_BASKET = register("wire_basket", BlockEntityType.Builder.of(::WireBasketBlockEntity,
35+
ALBOBlocks.WIRE_BASKET,
36+
))
37+
3438
@Suppress("NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS")
3539
private fun <T : BlockEntity> register(id: String, builder: BlockEntityType.Builder<T>): BlockEntityType<T> {
3640
val location = ResourceLocation(ALBOB.MOD_ID, id)
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
package dev.hybridlabs.albob.block.entity
2+
3+
import dev.hybridlabs.albob.ALBOB
4+
import net.minecraft.core.BlockPos
5+
import net.minecraft.core.NonNullList
6+
import net.minecraft.nbt.CompoundTag
7+
import net.minecraft.network.chat.Component
8+
import net.minecraft.sounds.SoundEvent
9+
import net.minecraft.sounds.SoundEvents
10+
import net.minecraft.sounds.SoundSource
11+
import net.minecraft.world.ContainerHelper
12+
import net.minecraft.world.entity.player.Inventory
13+
import net.minecraft.world.entity.player.Player
14+
import net.minecraft.world.inventory.AbstractContainerMenu
15+
import net.minecraft.world.inventory.ChestMenu
16+
import net.minecraft.world.inventory.MenuType
17+
import net.minecraft.world.item.ItemStack
18+
import net.minecraft.world.level.Level
19+
import net.minecraft.world.level.block.entity.ContainerOpenersCounter
20+
import net.minecraft.world.level.block.entity.RandomizableContainerBlockEntity
21+
import net.minecraft.world.level.block.state.BlockState
22+
23+
class WireBasketBlockEntity(pos: BlockPos, state: BlockState) : RandomizableContainerBlockEntity(ALBOBlockEntityTypes.WIRE_BASKET, pos, state) {
24+
private var inventory: NonNullList<ItemStack> = NonNullList.withSize(containerSize, ItemStack.EMPTY)
25+
26+
private val openersCounter: ContainerOpenersCounter = object : ContainerOpenersCounter() {
27+
private val blockEntity: WireBasketBlockEntity = this@WireBasketBlockEntity
28+
29+
override fun onOpen(level: Level, pos: BlockPos, state: BlockState) {
30+
blockEntity.playSound(SoundEvents.IRON_TRAPDOOR_OPEN)
31+
}
32+
33+
override fun onClose(level: Level, pos: BlockPos, state: BlockState) {
34+
blockEntity.playSound(SoundEvents.IRON_TRAPDOOR_CLOSE)
35+
}
36+
37+
override fun openerCountChanged(level: Level, pos: BlockPos, state: BlockState, previousOpenCount: Int, openCount: Int) {
38+
}
39+
40+
override fun isOwnContainer(player: Player): Boolean {
41+
val menu = player.containerMenu
42+
return menu is ChestMenu && menu.container == blockEntity
43+
}
44+
}
45+
46+
override fun getItems(): NonNullList<ItemStack> {
47+
return inventory
48+
}
49+
50+
override fun setItems(list: NonNullList<ItemStack>) {
51+
inventory = list
52+
}
53+
54+
override fun getDefaultName(): Component {
55+
return Component.translatable("${ALBOB.MOD_ID}.container.wire_basket")
56+
}
57+
58+
override fun createMenu(containerId: Int, inventory: Inventory): AbstractContainerMenu {
59+
return ChestMenu(MenuType.GENERIC_9x2, containerId, inventory, this, ROWS)
60+
}
61+
62+
override fun getContainerSize(): Int {
63+
return ROWS * 9
64+
}
65+
66+
override fun saveAdditional(tag: CompoundTag) {
67+
super.saveAdditional(tag)
68+
69+
if (!trySaveLootTable(tag)) {
70+
ContainerHelper.saveAllItems(tag, inventory)
71+
}
72+
}
73+
74+
override fun load(tag: CompoundTag) {
75+
super.load(tag)
76+
77+
inventory = NonNullList.withSize(containerSize, ItemStack.EMPTY)
78+
if (!tryLoadLootTable(tag)) {
79+
ContainerHelper.loadAllItems(tag, inventory)
80+
}
81+
}
82+
83+
override fun startOpen(player: Player) {
84+
if (!remove && !player.isSpectator) {
85+
openersCounter.incrementOpeners(player, level, blockPos, blockState)
86+
}
87+
}
88+
89+
override fun stopOpen(player: Player) {
90+
if (!remove && !player.isSpectator) {
91+
openersCounter.decrementOpeners(player, level, blockPos, blockState)
92+
}
93+
}
94+
95+
fun recheckOpen() {
96+
if (!remove) {
97+
openersCounter.recheckOpeners(level, blockPos, blockState)
98+
}
99+
}
100+
101+
fun playSound(soundEvent: SoundEvent) {
102+
level?.let { level ->
103+
level.playSound(
104+
null,
105+
worldPosition.x + 0.5,
106+
worldPosition.y + 0.5,
107+
worldPosition.z + 0.5,
108+
soundEvent,
109+
SoundSource.BLOCKS,
110+
0.5f,
111+
level.random.nextFloat() * 0.1f + 0.9f
112+
)
113+
}
114+
}
115+
116+
companion object {
117+
const val ROWS = 2
118+
}
119+
}

0 commit comments

Comments
 (0)