diff --git a/gradle.properties b/gradle.properties index 943936d002..0677f5394d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -19,4 +19,4 @@ kotlin.code.style=official loom_version=0.5-SNAPSHOT # Kotlin kotlin_version=1.4.0 - fabric_kotlin_version=1.4.0+build.1 \ No newline at end of file + fabric_kotlin_version=1.4.21+build.1 \ No newline at end of file diff --git a/src/main/kotlin/li/cli/oc/Components.kt b/src/main/kotlin/li/cli/oc/Components.kt index dc8d6cd0d8..60bc5601d3 100644 --- a/src/main/kotlin/li/cli/oc/Components.kt +++ b/src/main/kotlin/li/cli/oc/Components.kt @@ -2,12 +2,16 @@ package li.cli.oc import li.cli.oc.blocks.* import li.cli.oc.components.BlockEntitiesComponent +import li.cli.oc.client.gui.blocks.CaseScreen +import li.cli.oc.client.gui.blocks.CaseScreenHandler import li.cli.oc.items.Analyzer import li.cli.oc.items.Debugger import li.cli.oc.items.commons.ComponentBlockItem import li.cli.oc.items.commons.ComponentItem import net.minecraft.block.Block import net.minecraft.item.Item +import net.fabricmc.fabric.api.screenhandler.v1.ScreenHandlerRegistry +import net.minecraft.screen.ScreenHandlerType import net.minecraft.util.Identifier import net.minecraft.util.registry.Registry @@ -178,4 +182,7 @@ object Components { Registry.register(Registry.ITEM, Identifier(OpenComputers.modId, x.id), x.item) } } + + val CASE1 = Case(1) + val CASE_SCREEN_HANDLER: ScreenHandlerType = ScreenHandlerRegistry.registerExtended(Identifier(OpenComputers.modId), ::CaseScreenHandler) } diff --git a/src/main/kotlin/li/cli/oc/blockentity/Case.kt b/src/main/kotlin/li/cli/oc/blockentity/Case.kt index 1ad4dfee15..b6b9fe4981 100644 --- a/src/main/kotlin/li/cli/oc/blockentity/Case.kt +++ b/src/main/kotlin/li/cli/oc/blockentity/Case.kt @@ -1,6 +1,43 @@ package li.cli.oc.blockentity import li.cli.oc.blocks.commons.RedstoneAwareEntity +import li.cli.oc.client.gui.blocks.CaseScreenHandler import li.cli.oc.components.BlockEntitiesComponent +import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory +import net.minecraft.block.BlockState +import net.minecraft.entity.player.PlayerEntity +import net.minecraft.entity.player.PlayerInventory +import net.minecraft.nbt.CompoundTag +import net.minecraft.network.PacketByteBuf +import net.minecraft.screen.ScreenHandler +import net.minecraft.server.network.ServerPlayerEntity +import net.minecraft.text.Text -class CaseEntity : RedstoneAwareEntity(BlockEntitiesComponent.Case) \ No newline at end of file +class CaseEntity(var Tier: Int) : RedstoneAwareEntity(BlockEntitiesComponent.Case), ExtendedScreenHandlerFactory { + init { + markDirty() + } + + override fun createMenu(syncId: Int, inv: PlayerInventory, player: PlayerEntity): ScreenHandler { + return CaseScreenHandler(syncId, inv, Tier) + } + + override fun getDisplayName(): Text { + return Text.of("Computer") + } + + override fun writeScreenOpeningData(playerEntity: ServerPlayerEntity?, buf: PacketByteBuf?) { + buf?.writeInt(Tier) + } + + override fun toTag(tag: CompoundTag): CompoundTag { + super.toTag(tag) + tag.putInt("tier", Tier) + return tag + } + + override fun fromTag(state: BlockState?, tag: CompoundTag?) { + super.fromTag(state, tag) + Tier = tag?.getInt("tier")!! + } +} \ No newline at end of file diff --git a/src/main/kotlin/li/cli/oc/blocks/Case.kt b/src/main/kotlin/li/cli/oc/blocks/Case.kt index b93bb2fb4c..c249f4aa73 100644 --- a/src/main/kotlin/li/cli/oc/blocks/Case.kt +++ b/src/main/kotlin/li/cli/oc/blocks/Case.kt @@ -1,4 +1,4 @@ -package li.cli.oc.blocks +package li.cli.oc.blocks; import li.cli.oc.blockentity.CaseEntity import li.cli.oc.blocks.commons.TecBlock @@ -6,11 +6,17 @@ import li.cli.oc.render.Color import net.fabricmc.fabric.api.`object`.builder.v1.block.FabricBlockSettings import net.minecraft.block.* import net.minecraft.block.entity.BlockEntity +import net.minecraft.entity.player.PlayerEntity import net.minecraft.item.ItemPlacementContext import net.minecraft.state.StateManager import net.minecraft.state.property.BooleanProperty +import net.minecraft.util.ActionResult +import net.minecraft.util.Hand +import net.minecraft.util.hit.BlockHitResult +import net.minecraft.util.math.BlockPos import net.minecraft.util.math.Direction import net.minecraft.world.BlockView +import net.minecraft.world.World class Case(var Tier: Int) : TecBlock(FabricBlockSettings.of(Material.METAL)) { @@ -35,11 +41,22 @@ class Case(var Tier: Int) : TecBlock(FabricBlockSettings.of(Material.METAL)) { return this.defaultState.with(facing, ctx?.playerFacing?.opposite) } - override fun createBlockEntity(world: BlockView?): BlockEntity { - return CaseEntity() + override fun createBlockEntity(world: BlockView?): BlockEntity? { + return CaseEntity(Tier); } override fun getRenderType(state: BlockState?): BlockRenderType { - return BlockRenderType.MODEL + return BlockRenderType.MODEL; + } + + override fun onUse(state: BlockState, world: World, pos: BlockPos?, player: PlayerEntity, hand: Hand?, hit: BlockHitResult?): ActionResult? { + // Open the case screen if we can + if (!world.isClient) { + val screenHandlerFactory = state.createScreenHandlerFactory(world, pos) + if (screenHandlerFactory != null) { + player.openHandledScreen(screenHandlerFactory) + } + } + return ActionResult.SUCCESS } } diff --git a/src/main/kotlin/li/cli/oc/client/ClientInit.kt b/src/main/kotlin/li/cli/oc/client/ClientInit.kt index 0f5ce4d818..d1bbc2e1f7 100644 --- a/src/main/kotlin/li/cli/oc/client/ClientInit.kt +++ b/src/main/kotlin/li/cli/oc/client/ClientInit.kt @@ -4,14 +4,16 @@ import li.cli.oc.Components import li.cli.oc.OpenComputers import li.cli.oc.blocks.Case import li.cli.oc.blocks.Screen +import li.cli.oc.client.gui.blocks.CaseScreen import li.cli.oc.items.commons.ComponentBlockItem import li.cli.oc.render.BaseModelProvider -import li.cli.oc.render.block.CableModel import li.cli.oc.render.block.ScreenModel +import li.cli.oc.render.block.CableModel import net.fabricmc.api.ClientModInitializer import net.fabricmc.fabric.api.blockrenderlayer.v1.BlockRenderLayerMap import net.fabricmc.fabric.api.client.model.ModelLoadingRegistry import net.fabricmc.fabric.api.client.rendering.v1.ColorProviderRegistry +import net.fabricmc.fabric.api.client.screenhandler.v1.ScreenRegistry import net.minecraft.block.BlockState import net.minecraft.client.render.RenderLayer import net.minecraft.item.ItemStack @@ -25,6 +27,7 @@ object ClientInit : ClientModInitializer { ModelLoadingRegistry.INSTANCE.registerResourceProvider { BaseModelProvider(Identifier(OpenComputers.modId, "block/cable"), CableModel()) } ModelLoadingRegistry.INSTANCE.registerResourceProvider { BaseModelProvider(Identifier(OpenComputers.modId, "block/screen"), ScreenModel()) } + ColorProviderRegistry.BLOCK.register(handleBlockColor, Components.Blocks.CaseOne.block, Components.Blocks.CaseTwo.block, @@ -46,6 +49,8 @@ object ClientInit : ClientModInitializer { ) BlockRenderLayerMap.INSTANCE.putBlock(Components.Blocks.Assembler.block, RenderLayer.getTranslucent()); + + ScreenRegistry.register(Components.CASE_SCREEN_HANDLER, ::CaseScreen) } private val handleItemColor = fun (item: ItemStack, tintIndex: Int): Int { diff --git a/src/main/kotlin/li/cli/oc/client/gui/blocks/CaseScreen.kt b/src/main/kotlin/li/cli/oc/client/gui/blocks/CaseScreen.kt new file mode 100644 index 0000000000..6f47651cc6 --- /dev/null +++ b/src/main/kotlin/li/cli/oc/client/gui/blocks/CaseScreen.kt @@ -0,0 +1,97 @@ +package li.cli.oc.client.gui.blocks + +import com.mojang.blaze3d.systems.RenderSystem +import li.cli.oc.OpenComputers +import net.minecraft.client.gui.screen.ingame.HandledScreen +import net.minecraft.client.gui.widget.TexturedButtonWidget +import net.minecraft.client.util.math.MatrixStack +import net.minecraft.entity.player.PlayerInventory +import net.minecraft.screen.ScreenHandler +import net.minecraft.text.Text +import net.minecraft.util.Identifier + +class CaseScreen(handler: ScreenHandler?, inventory: PlayerInventory?, title: Text?) : HandledScreen( + handler, + inventory, + title +) { + + override fun drawBackground(matrices: MatrixStack?, delta: Float, mouseX: Int, mouseY: Int) { + RenderSystem.color4f(1.0f, 1.0f, 1.0f, 1.0f) + assert(client != null) + client!!.textureManager.bindTexture(TEXTURE) + val x = (width - backgroundWidth) / 2 + val y = (height - backgroundHeight) / 2 + drawTexture(matrices, x, y, 0, 0, backgroundWidth, backgroundHeight) + + client!!.textureManager.bindTexture(COMP_TEXTURE) + drawTexture(matrices, x, y + 1, 0, 0, 256, 256) + + client!!.textureManager.bindTexture(SLOT_TEXTURE) + val tier = (handler as CaseScreenHandler).tier + + drawTexture(matrices, x + 42, y + 34, 0, 0, 18, 18) + + drawInvSlots(tier!!, x, y) // Tier should almost certainly be set by the time we are drawing the background + } + + + override fun render(matrices: MatrixStack, mouseX: Int, mouseY: Int, delta: Float) { + renderBackground(matrices) + super.render(matrices, mouseX, mouseY, delta) + drawMouseoverTooltip(matrices, mouseX, mouseY) + } + + override fun init() { + super.init() + val x = (width - backgroundWidth) / 2 + val y = (height - backgroundHeight) / 2 + // Center the title + titleX = 7 + val powerButton = TexturedButtonWidget( + x + (backgroundWidth / 2) - 18, + y + 34, + 18, + 18, + 0, + 0, + 0, + BUTTON_TEXTURE, + 36, + 36 + ) { button -> + TODO( + "Computer start/stop here" + ) + } + addButton(powerButton) + } + + private fun drawInvSlots(tier: Int, x: Int, y: Int) { + var invSlotMatrix = MatrixStack() + + client!!.textureManager.bindTexture(SLOT_TEXTURE) + + val xOffset = 93 + val yOffset = 12 + + //drawTexture(invSlotMatrix, x + xOffset, y + yOffset, 0, 0, 18, 18) + + drawTexture(invSlotMatrix, x + xOffset + 3, y + yOffset + 3, 0, 0, 18, 18) + drawTexture(invSlotMatrix, x + xOffset + 3, y + yOffset + 21, 0, 0, 18, 18) + + drawTexture(invSlotMatrix, x + xOffset + 3 + 18 + 5, y + yOffset + 3, 0, 0, 18, 18) + drawTexture(invSlotMatrix, x + xOffset + 3 + 18 + 5, y + yOffset + 21, 0, 0, 18, 18) + drawTexture(invSlotMatrix, x + xOffset + 3 + 18 + 5, y + yOffset + 39, 0, 0, 18, 18) + + drawTexture(invSlotMatrix, x + xOffset + 3 + 36 + 10, y + yOffset + 3, 0, 0, 18, 18) + } + + companion object { + private val TEXTURE = Identifier(OpenComputers.modId, "textures/gui/background.png") + private val COMP_TEXTURE = Identifier(OpenComputers.modId, "textures/gui/computer.png") + private val BUTTON_TEXTURE = Identifier(OpenComputers.modId, "textures/gui/button_power.png") + private val SLOT_TEXTURE = Identifier(OpenComputers.modId, "textures/gui/slot.png") + } + +} \ No newline at end of file diff --git a/src/main/kotlin/li/cli/oc/client/gui/blocks/CaseScreenHandler.kt b/src/main/kotlin/li/cli/oc/client/gui/blocks/CaseScreenHandler.kt new file mode 100644 index 0000000000..064385bd9a --- /dev/null +++ b/src/main/kotlin/li/cli/oc/client/gui/blocks/CaseScreenHandler.kt @@ -0,0 +1,60 @@ +package li.cli.oc.client.gui.blocks + +import li.cli.oc.Components +import li.cli.oc.client.gui.blocks.slots.* +import net.minecraft.entity.player.PlayerEntity +import net.minecraft.entity.player.PlayerInventory +import net.minecraft.inventory.SimpleInventory +import net.minecraft.network.PacketByteBuf +import net.minecraft.screen.ScreenHandler +import net.minecraft.screen.slot.Slot + +class CaseScreenHandler : ScreenHandler { + private val inventory = SimpleInventory(10) + var tier: Int? = null + + constructor(syncId: Int, playerInventory: PlayerInventory, buf: PacketByteBuf) : this(syncId, playerInventory, buf.readInt()) { + } + + constructor(syncId: Int, playerInventory: PlayerInventory, _tier: Int?) : super(Components.CASE_SCREEN_HANDLER, syncId) { + if (_tier != null) { + this.tier = _tier + } + addSlot(Slot(inventory, 0, 43, 35)) // EEPROM Slot + if (this.tier == 1) { + // Two Expansion Slot Cards to the left of the component grid + addSlot(Slot(inventory, 1, 97, 16)) + addSlot(Slot(inventory, 2, 97, 34)) + + // One CPU Slot in the center top of the component grid + addSlot(Slot(inventory, 3, 120, 16)) + + // Two RAM Slots in the direct middle and bottom middle of the component grid + addSlot(Slot(inventory, 4, 120, 34)) + addSlot(Slot(inventory, 5, 120, 52)) + + // One HDD Slot in the top right of the component grid + addSlot(Slot(inventory, 6, 143, 16)) + } + if (this.tier == 2) { + // Two Expansion Slot Cards to the left of the component grid + addSlot(Slot(inventory, 1, 97, 16)) + addSlot(Slot(inventory, 2, 97, 34)) + + // One CPU Slot in the center top of the component grid + addSlot(Slot(inventory, 3, 120, 16)) + + // Two RAM Slots in the direct middle and bottom middle of the component grid + addSlot(Slot(inventory, 4, 120, 34)) + addSlot(Slot(inventory, 5, 120, 52)) + + // Two HDD Slots in the top right and middle right of the component grid + addSlot(Slot(inventory, 6, 143, 16)) + addSlot(Slot(inventory, 7, 143, 34)) + } + } + + override fun canUse(player: PlayerEntity?): Boolean { + return inventory.canPlayerUse(player) + } +} diff --git a/src/main/kotlin/li/cli/oc/client/gui/blocks/slots/CPUSlot.kt b/src/main/kotlin/li/cli/oc/client/gui/blocks/slots/CPUSlot.kt new file mode 100644 index 0000000000..8fa131b8f9 --- /dev/null +++ b/src/main/kotlin/li/cli/oc/client/gui/blocks/slots/CPUSlot.kt @@ -0,0 +1,18 @@ +package li.cli.oc.client.gui.blocks.slots + +import li.cli.oc.items.CPU +import net.minecraft.inventory.Inventory +import net.minecraft.item.ItemStack +import net.minecraft.screen.slot.Slot + +class CPUSlot(inventory: Inventory, index: Int, x: Int, y: Int, level: Int) : Slot(inventory, index, x, y) { + private val tier: Int = 0 + +/* override fun canInsert(stack: ItemStack?): Boolean { + if (stack != null) { + return stack.item is CPU && CPU.tier <= tier + } + + return false + }*/ +} \ No newline at end of file diff --git a/src/main/kotlin/li/cli/oc/client/gui/blocks/slots/EEPROMSlot.kt b/src/main/kotlin/li/cli/oc/client/gui/blocks/slots/EEPROMSlot.kt new file mode 100644 index 0000000000..5fbde4a600 --- /dev/null +++ b/src/main/kotlin/li/cli/oc/client/gui/blocks/slots/EEPROMSlot.kt @@ -0,0 +1,16 @@ +package li.cli.oc.client.gui.blocks.slots + +import net.minecraft.inventory.Inventory +import net.minecraft.item.ItemStack +import net.minecraft.screen.slot.Slot + +class EEPROMSlot(inventory: Inventory, index: Int, x: Int, y: Int) : Slot(inventory, index, x, y) { + +/* override fun canInsert(stack: ItemStack?): Boolean { + if (stack != null) { + return stack.item is EEPROM // TODO: Rename once BIOS Card item class is created + } + + return false + }*/ +} \ No newline at end of file diff --git a/src/main/kotlin/li/cli/oc/client/gui/blocks/slots/ExpSlot.kt b/src/main/kotlin/li/cli/oc/client/gui/blocks/slots/ExpSlot.kt new file mode 100644 index 0000000000..e68d480bf8 --- /dev/null +++ b/src/main/kotlin/li/cli/oc/client/gui/blocks/slots/ExpSlot.kt @@ -0,0 +1,17 @@ +package li.cli.oc.client.gui.blocks.slots + +import net.minecraft.inventory.Inventory +import net.minecraft.item.ItemStack +import net.minecraft.screen.slot.Slot + +class ExpSlot(inventory: Inventory, index: Int, x: Int, y: Int, level: Int) : Slot(inventory, index, x, y) { + private val level: Int = 0 + +/* override fun canInsert(stack: ItemStack?): Boolean { + if (stack != null) { + return stack.item is ExpansionCard && ExpansionCard.level <= level// TODO: Rename once Expansion Card item class is created + } + + return false + }*/ +} \ No newline at end of file diff --git a/src/main/kotlin/li/cli/oc/client/gui/blocks/slots/HDSlot.kt b/src/main/kotlin/li/cli/oc/client/gui/blocks/slots/HDSlot.kt new file mode 100644 index 0000000000..b210da3bce --- /dev/null +++ b/src/main/kotlin/li/cli/oc/client/gui/blocks/slots/HDSlot.kt @@ -0,0 +1,17 @@ +package li.cli.oc.client.gui.blocks.slots + +import net.minecraft.inventory.Inventory +import net.minecraft.item.ItemStack +import net.minecraft.screen.slot.Slot + +class HDSlot(inventory: Inventory, index: Int, x: Int, y: Int, level: Int) : Slot(inventory, index, x, y) { + private val level: Int = 0 + +/* override fun canInsert(stack: ItemStack?): Boolean { + if (stack != null) { + return stack.item is HardDrive && HardDrive.level <= level// TODO: Rename once Expansion Card item class is created + } + + return false + }*/ +} \ No newline at end of file diff --git a/src/main/kotlin/li/cli/oc/client/gui/blocks/slots/RAMSlot.kt b/src/main/kotlin/li/cli/oc/client/gui/blocks/slots/RAMSlot.kt new file mode 100644 index 0000000000..f3de09ac61 --- /dev/null +++ b/src/main/kotlin/li/cli/oc/client/gui/blocks/slots/RAMSlot.kt @@ -0,0 +1,17 @@ +package li.cli.oc.client.gui.blocks.slots + +import net.minecraft.inventory.Inventory +import net.minecraft.item.ItemStack +import net.minecraft.screen.slot.Slot + +class RAMSlot(inventory: Inventory, index: Int, x: Int, y: Int, level: Int) : Slot(inventory, index, x, y) { + private val level: Int = 0 + +/* override fun canInsert(stack: ItemStack?): Boolean { + if (stack != null) { + return stack.item is RAMCard && RAMCard.level <= level// TODO: Rename once RAM Card item class is created + } + + return false + }*/ +} \ No newline at end of file diff --git a/src/main/kotlin/li/cli/oc/components/BlockEntitiesComponent.kt b/src/main/kotlin/li/cli/oc/components/BlockEntitiesComponent.kt index c676de4e6d..7dba86e541 100644 --- a/src/main/kotlin/li/cli/oc/components/BlockEntitiesComponent.kt +++ b/src/main/kotlin/li/cli/oc/components/BlockEntitiesComponent.kt @@ -14,7 +14,7 @@ enum class BlockEntitiesComponent(val id: String, val entityType: BlockEntityTyp Cable ("cable", makeType({ Cable() }, Blocks.Cable)), Capacitor ("capacitor", makeType({ Capacitor() }, Blocks.Capacitor)), CarpatedCapacitor ("carpetedcapacitor", makeType({ CarpetedCapacitor() }, Blocks.CarpetedCapacitor)), - Case ("case", makeType({ CaseEntity()}, Case(4))), + Case ("case", makeType({ CaseEntity(4)}, Case(4))), Charger ("charger", makeType({ Charger()}, Blocks.Charger)), Disassembler ("disassembler", makeType({ Disassembler() }, Blocks.Disassembler)), DiskDrive ("diskdrive", makeType({ DiskDrive() }, Blocks.DiskDrive)), diff --git a/src/main/kotlin/li/cli/oc/items/CPU.kt b/src/main/kotlin/li/cli/oc/items/CPU.kt new file mode 100644 index 0000000000..04be5971bb --- /dev/null +++ b/src/main/kotlin/li/cli/oc/items/CPU.kt @@ -0,0 +1,9 @@ +package li.cli.oc.items + +import li.cli.oc.OpenComputers +import net.minecraft.item.Item + +class CPU(tier: Int) : Item(Settings().group(OpenComputers.ITEM_GROUP)) { + + +} \ No newline at end of file diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index bbea7345e7..2957380cc1 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -36,7 +36,7 @@ "fabric": "*", "minecraft": "1.16.x" }, - "requires": { + "depends": { "fabric-language-kotlin": ">=1.4.0" }, "suggests": {