Skip to content

Commit

Permalink
feat: Chest upgrades
Browse files Browse the repository at this point in the history
  • Loading branch information
Zekromaster committed Aug 1, 2024
1 parent 69c94c2 commit 0ec4456
Show file tree
Hide file tree
Showing 17 changed files with 336 additions and 140 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Iron Chests (StationAPI)
<img src="https://i.imgur.com/c1DH9VL.png" height=50>
<img src="https://i.imgur.com/c1DH9VL.png" height=50 alt="Requires Fabric Kotlin">

Basic port of Iron Chests for b1.7.3 with Fabric and [StationAPI](https://github.com/ModificationStation/StationAPI).

Expand All @@ -13,4 +13,4 @@ unashamedly stole code
## Features
- [x] Iron, Gold and Diamond Chest
- [ ] Other modded metal chests (Silver, copper, dimando?)
- [ ] Chest upgrades
- [x] Chest upgrades
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ howmanyitems_version=5.2.1
modmenu_version=v1.8.5-beta.3

# Mod Properties
next_version=0.1.0
next_version=0.2.0

maven_group=net.zekromaster.minecraft
archives_base_name=IronChestsStationAPI
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package net.zekromaster.minecraft.ironchests.mixin;

import net.minecraft.block.ChestBlock;
import net.minecraft.block.entity.ChestBlockEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.world.World;
import net.zekromaster.minecraft.ironchests.ChestUpgrade;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

@Mixin(ChestBlock.class)
public class ChestMixin {

@Inject(method = "onUse", at=@At("HEAD"), cancellable = true)
void onUseMixin(World world, int x, int y, int z, PlayerEntity player, CallbackInfoReturnable<Boolean> cir) {
var chest = (ChestBlockEntity) world.getBlockEntity(x, y, z);
var hand = player.getHand();
if (hand != null) {
if (hand.getItem() instanceof ChestUpgrade upgrade) {
if (upgrade.upgrade(world, x, y, z, player, chest)) {
hand.count--;
}
cir.setReturnValue(true);
}
}
}

}
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
package net.zekromaster.minecraft.ironchests

import net.mine_diver.unsafeevents.listener.EventListener
import net.minecraft.block.Block
import net.minecraft.block.entity.BlockEntity
import net.minecraft.block.entity.ChestBlockEntity
import net.minecraft.block.material.Material
import net.minecraft.entity.ItemEntity
import net.minecraft.entity.player.PlayerEntity
import net.minecraft.item.Item
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NbtCompound
import net.minecraft.screen.GenericContainerScreenHandler
import net.minecraft.world.World
import net.modificationstation.stationapi.api.block.BlockState
import net.modificationstation.stationapi.api.event.block.entity.BlockEntityRegisterEvent
import net.modificationstation.stationapi.api.event.recipe.RecipeRegisterEvent
import net.modificationstation.stationapi.api.event.registry.BlockRegistryEvent
import net.modificationstation.stationapi.api.gui.screen.container.GuiHelper
import net.modificationstation.stationapi.api.item.ItemPlacementContext
import net.modificationstation.stationapi.api.recipe.CraftingRegistry
import net.modificationstation.stationapi.api.state.StateManager
import net.modificationstation.stationapi.api.state.property.EnumProperty
import net.modificationstation.stationapi.api.template.block.TemplateBlockWithEntity
Expand All @@ -21,13 +27,74 @@ import net.modificationstation.stationapi.api.util.math.Direction
import net.zekromaster.minecraft.ironchests.mixin.ChestInventoryAccessor
import java.util.*
import java.util.function.Predicate
import kotlin.math.floor


class IronChestBlockEntity(material: IronChestMaterial): ChestBlockEntity() {
constructor(): this(IronChestMaterial.IRON)
object IronChestsBlockEntrypoint {
@JvmStatic @get:JvmName("ironChest")
lateinit var IRON_CHEST: IronChestBlock
private set
@JvmStatic @get:JvmName("goldChest")
lateinit var GOLD_CHEST: IronChestBlock
private set
@JvmStatic @get:JvmName("diamondChest")
lateinit var DIAMOND_CHEST: IronChestBlock
private set

@EventListener
fun registerBlocks(event: BlockRegistryEvent) {
IRON_CHEST = IronChestBlock(Identifier.of("ironchests:iron_chest"), IronChestMaterial.IRON)
IRON_CHEST.setTranslationKey(Identifier.of("ironchests:iron_chest"))
GOLD_CHEST = IronChestBlock(Identifier.of("ironchests:gold_chest"), IronChestMaterial.GOLD)
GOLD_CHEST.setTranslationKey(Identifier.of("ironchests:gold_chest"))
DIAMOND_CHEST = IronChestBlock(Identifier.of("ironchests:diamond_chest"), IronChestMaterial.DIAMOND)
DIAMOND_CHEST.setTranslationKey(Identifier.of("ironchests:diamond_chest"))
}

@EventListener
internal fun registerTileEntities(event: BlockEntityRegisterEvent) {
event.register(
IronChestBlockEntity::class.java,
"ironchest"
)
}

private var material = material
@EventListener
internal fun registerRecipes(event: RecipeRegisterEvent) {
val type = RecipeRegisterEvent.Vanilla.fromType(event.recipeId)

if (type == RecipeRegisterEvent.Vanilla.CRAFTING_SHAPED) {
CraftingRegistry.addShapedRecipe(
ItemStack(IRON_CHEST),
"iii", "ici", "iii",
'i', ItemStack(Item.IRON_INGOT),
'c', ItemStack(Block.CHEST)
)
CraftingRegistry.addShapedRecipe(
ItemStack(GOLD_CHEST),
"iii", "ici", "iii",
'i', ItemStack(Item.GOLD_INGOT),
'c', ItemStack(IRON_CHEST)
)
CraftingRegistry.addShapedRecipe(
ItemStack(DIAMOND_CHEST),
"gig", "ici", "gig",
'i', ItemStack(Item.DIAMOND),
'c', ItemStack(GOLD_CHEST),
'g', ItemStack(Block.GLASS)
)
CraftingRegistry.addShapedRecipe(
ItemStack(DIAMOND_CHEST),
"igi", "gcg", "igi",
'i', ItemStack(Item.DIAMOND),
'c', ItemStack(GOLD_CHEST),
'g', ItemStack(Block.GLASS)
)
}
}
}

class IronChestBlockEntity @JvmOverloads constructor(material: IronChestMaterial = IronChestMaterial.IRON): ChestBlockEntity() {
var material = material
set(x) = run {
field = x
updateInventorySize()
Expand All @@ -37,6 +104,7 @@ class IronChestBlockEntity(material: IronChestMaterial): ChestBlockEntity() {
override fun getName(): String = material.chestName

init {
@Suppress("CAST_NEVER_SUCCEEDS")
(this as ChestInventoryAccessor).inventory = arrayOfNulls(material.size)
}

Expand All @@ -51,7 +119,8 @@ class IronChestBlockEntity(material: IronChestMaterial): ChestBlockEntity() {
}

private fun updateInventorySize() {
(this as ChestInventoryAccessor).inventory.copyOf(material.size)
@Suppress("CAST_NEVER_SUCCEEDS")
(this as ChestInventoryAccessor).inventory = inventory.copyOf(material.size)
}
}

Expand All @@ -75,16 +144,7 @@ class IronChestBlock(identifier: Identifier, private val chestMaterial: IronChes
super.appendProperties(builder)
}

override fun getPlacementState(context: ItemPlacementContext): BlockState {
val direction: Int = floor((context.player!!.yaw * 4.0f / 360.0f).toDouble() + 0.5).toInt() and 3
return when (direction) {
0 -> defaultState.with(FACING, Direction.NORTH)
1 -> defaultState.with(FACING, Direction.EAST)
2 -> defaultState.with(FACING, Direction.SOUTH)
3 -> defaultState.with(FACING, Direction.WEST)
else -> defaultState.with(FACING, Direction.NORTH)
}
}
override fun getPlacementState(context: ItemPlacementContext): BlockState = defaultState.with(FACING, context.player!!.placementFacing())

override fun createBlockEntity(): BlockEntity {
return IronChestBlockEntity(chestMaterial)
Expand Down Expand Up @@ -125,7 +185,20 @@ class IronChestBlock(identifier: Identifier, private val chestMaterial: IronChes

override fun onUse(world: World, x: Int, y: Int, z: Int, player: PlayerEntity): Boolean {
val entity = world.getBlockEntity(x, y, z) ?: return true
if (entity !is IronChestBlockEntity || world.shouldSuffocate(x, y+1, z) || world.isRemote) {

if (entity !is IronChestBlockEntity || world.isRemote) {
return true
}

val handheldItem = player.hand?.item
if (handheldItem is ChestUpgrade) {
if (handheldItem.upgrade(world, x, y, z, player, entity)) {
player.hand!!.count--
}
return true
}

if (world.shouldSuffocate(x, y+1, z)) {
return true
}

Expand Down
113 changes: 0 additions & 113 deletions src/main/kotlin/net/zekromaster/minecraft/ironchests/entrypoints.kt

This file was deleted.

41 changes: 37 additions & 4 deletions src/main/kotlin/net/zekromaster/minecraft/ironchests/gui.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,50 @@ package net.zekromaster.minecraft.ironchests

import net.fabricmc.api.EnvType
import net.fabricmc.api.Environment
import net.mine_diver.unsafeevents.listener.EventListener
import net.minecraft.client.gui.screen.Screen
import net.minecraft.client.gui.screen.ingame.HandledScreen
import net.minecraft.entity.player.PlayerEntity
import net.minecraft.inventory.Inventory
import net.minecraft.screen.ScreenHandler
import net.minecraft.screen.slot.Slot
import net.modificationstation.stationapi.api.event.registry.GuiHandlerRegistryEvent
import net.modificationstation.stationapi.api.util.Identifier
import org.lwjgl.opengl.GL11
import uk.co.benjiweber.expressions.tuple.BiTuple
import java.util.function.BiFunction
import java.util.function.Supplier

internal object RegisterGUIs {

private class OpenInventory(private val material: IronChestMaterial): BiFunction<PlayerEntity, Inventory, Screen> {
override fun apply(player: PlayerEntity, inventory: Inventory): Screen =
IronChestScreen(player.inventory, inventory, material)
}

private data class IronChestFactory(val material: IronChestMaterial): Supplier<Inventory> {
override fun get(): IronChestBlockEntity = IronChestBlockEntity(material)
}

@EventListener
fun registerGUIs(event: GuiHandlerRegistryEvent) {
event.registry.registerValueNoMessage(
Identifier.of("ironchests:gui_iron"), BiTuple.of(
OpenInventory(IronChestMaterial.IRON),
IronChestFactory(IronChestMaterial.IRON)
))
event.registry.registerValueNoMessage(
Identifier.of("ironchests:gui_gold"), BiTuple.of(
OpenInventory(IronChestMaterial.GOLD),
IronChestFactory(IronChestMaterial.GOLD)
))
event.registry.registerValueNoMessage(
Identifier.of("ironchests:gui_diamond"), BiTuple.of(
OpenInventory(IronChestMaterial.DIAMOND),
IronChestFactory(IronChestMaterial.DIAMOND)
))
}
}

private fun IronChestMaterial.gui() =
when (this) {
Expand All @@ -22,10 +59,6 @@ private enum class GUIType(val material: IronChestMaterial, val width: Int, val
IRON(IronChestMaterial.IRON, 184, 202, "ironchest.png"),
GOLD(IronChestMaterial.GOLD, 184, 256, "goldchest.png"),
DIAMOND(IronChestMaterial.DIAMOND, 238, 256, "diamondchest.png");

fun handler(playerInventory: Inventory, inventory: Inventory): ScreenHandler =
IronChestScreenHandler(this, playerInventory, inventory, width, height)

}

private class IronChestScreenHandler(
Expand Down
Loading

0 comments on commit 0ec4456

Please sign in to comment.