From ae8a9296f7034af3041cd6c9c506f59de0664296 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Sun, 4 Sep 2022 16:19:46 +0700 Subject: [PATCH] Power consumption by android station when doing stuff in it --- .../ru/dbotthepony/mc/otm/datagen/DataGen.kt | 2 +- .../mc/otm/datagen/lang/English.kt | 5 + .../block/entity/AndroidStationBlockEntity.kt | 10 +- .../otm/client/screen/AndroidStationScreen.kt | 42 ++++- .../mc/otm/menu/AndroidStationMenu.kt | 131 +++++++++++++--- ...station.json => android_station_idle.json} | 0 .../models/block/android_station_working.json | 147 ++++++++++++++++++ 7 files changed, 306 insertions(+), 31 deletions(-) rename src/main/resources/assets/overdrive_that_matters/models/block/{android_station.json => android_station_idle.json} (100%) create mode 100644 src/main/resources/assets/overdrive_that_matters/models/block/android_station_working.json diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/DataGen.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/DataGen.kt index 10e63ae72..4bf62acd4 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/DataGen.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/DataGen.kt @@ -363,7 +363,7 @@ object DataGen { } with(itemModelProvider) { - block(MItems.ANDROID_STATION) + block(MItems.ANDROID_STATION, "android_station_working") block(MItems.BATTERY_BANK) block(MItems.MATTER_CAPACITOR_BANK) block(MItems.PATTERN_STORAGE) diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/English.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/English.kt index 8c345bc12..2e9fc6261 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/English.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/English.kt @@ -200,6 +200,7 @@ private fun misc(provider: MatteryLanguageProvider) { misc("3d2d.gravitation_stabilizer.mass", "Singularity mass: %s") misc("3d2d.gravitation_stabilizer.strength", "Gravitation strength: %s") + misc("android_station.research.low_power", "Android Station is low on power! Can't research!") misc("android_station.research.researched", "Researched!") misc("android_station.research.can_be_researched", "Ready to research!") misc("android_station.research.can_not_be_researched", "Can't research!") @@ -207,6 +208,10 @@ private fun misc(provider: MatteryLanguageProvider) { misc("android_station.research.item", "Requires %s x%s") misc("android_station.research.missing_predecessors", "%s needs to be researched first") + misc("android_station.low_power_0", "Not enough power; Can't swap parts") + misc("android_station.low_power_1", "Low power; Can't research") + misc("android_station.power_ok", "Power OK") + misc("filter.yes", "Yes") misc("filter.no", "No") diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/AndroidStationBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/AndroidStationBlockEntity.kt index 7899b6a43..39874d3ac 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/AndroidStationBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/AndroidStationBlockEntity.kt @@ -29,7 +29,7 @@ class AndroidStationBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : override val defaultDisplayName: Component get() = MACHINE_NAME - override val energy = object : WorkerEnergyStorage(this@AndroidStationBlockEntity, STORAGE, MAX_IO) { + override val energy = object : WorkerEnergyStorage(this@AndroidStationBlockEntity, STORAGE, MAX_IO, null) { override fun extractEnergyInner(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction { return super.extractEnergyInner(howMuch, simulate).also { if (!simulate && this.batteryLevel.isZero) { @@ -93,7 +93,9 @@ class AndroidStationBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : companion object { private val MACHINE_NAME = TranslatableComponent("block.overdrive_that_matters.android_station") - private val STORAGE = ImpreciseFraction(100_000) - private val MAX_IO = ImpreciseFraction(250) + val STORAGE = ImpreciseFraction(100_000) + val MAX_IO = ImpreciseFraction.valueOf(250) + val ENERGY_PER_OPERATION = ImpreciseFraction.valueOf(2048) + val ENERGY_PER_RESEARCH = ImpreciseFraction.valueOf(16384) } -} \ No newline at end of file +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/AndroidStationScreen.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/AndroidStationScreen.kt index b4712fdea..8fb9b3e44 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/AndroidStationScreen.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/AndroidStationScreen.kt @@ -12,6 +12,7 @@ import net.minecraft.world.entity.player.Inventory import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.android.AndroidResearch import ru.dbotthepony.mc.otm.android.AndroidResearchType +import ru.dbotthepony.mc.otm.block.entity.AndroidStationBlockEntity import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.client.playGuiClickSound @@ -258,7 +259,6 @@ private class AndroidResearchButton( AndroidStationScreen.BUTTON_SIZE.toFloat(), AndroidStationScreen.BUTTON_SIZE.toFloat() ) { - init { setDockMargin(2f, 2f, 2f, 2f) } @@ -377,7 +377,7 @@ private class AndroidResearchButton( override fun mouseClickedInner(x: Double, y: Double, button: Int): Boolean { if (button == InputConstants.MOUSE_BUTTON_LEFT) { - if (node.canResearch && !node.isResearched) { + if (node.canResearch && !node.isResearched && (parent?.screen as AndroidStationScreen).menu.powerWidget.level >= AndroidStationBlockEntity.ENERGY_PER_RESEARCH) { MatteryPlayerNetworkChannel.sendToServer(AndroidResearchRequestPacket(node.type)) } @@ -391,12 +391,22 @@ private class AndroidResearchButton( if (isHovered) { val list = ArrayList().also { it.addAll(node.screenTooltipLines) } + val enoughPower = (parent?.screen as AndroidStationScreen).menu.powerWidget.level >= AndroidStationBlockEntity.ENERGY_PER_RESEARCH + if (node.isResearched) { list.add(TranslatableComponent("otm.android_station.research.researched").withStyle(ChatFormatting.DARK_AQUA)) } else if (node.canResearch) { list.add(TranslatableComponent("otm.android_station.research.can_be_researched").withStyle(ChatFormatting.DARK_GREEN)) + + if (!enoughPower) { + list.add(TranslatableComponent("otm.android_station.research.low_power").withStyle(ChatFormatting.DARK_RED)) + } } else { list.add(TranslatableComponent("otm.android_station.research.can_not_be_researched").withStyle(ChatFormatting.DARK_RED)) + + if (!enoughPower) { + list.add(TranslatableComponent("otm.android_station.research.low_power").withStyle(ChatFormatting.DARK_RED)) + } } screen.renderComponentTooltip(stack, list, mouse_x.toInt(), mouse_y.toInt()) @@ -599,7 +609,29 @@ class AndroidStationScreen constructor(p_97741_: AndroidStationMenu, p_97742_: I } override fun makeMainFrame(): FramePanel { - val frame = FramePanel(this, 200f, 100f, title) + val frame = FramePanel(this, 200f, 108f, title) + + object : Label(this@AndroidStationScreen, frame, height = 11f, shadow = true) { + init { + dock = Dock.BOTTOM + dockTop = 2f + } + + override fun innerRender(stack: PoseStack, mouseX: Float, mouseY: Float, partialTick: Float) { + if (menu.powerWidget.level >= AndroidStationBlockEntity.ENERGY_PER_RESEARCH) { + text = POWER_OK + color = RGBAColor.LIGHT_GREEN + } else if (menu.powerWidget.level >= AndroidStationBlockEntity.ENERGY_PER_OPERATION) { + text = LOW_POWER_1 + color = RGBAColor.DARK_RED + } else { + text = LOW_POWER_0 + color = RGBAColor.RED + } + + super.innerRender(stack, mouseX, mouseY, partialTick) + } + } val stripLeft = EditablePanel(this, frame, width = AbstractSlotPanel.SIZE) @@ -652,5 +684,9 @@ class AndroidStationScreen constructor(p_97741_: AndroidStationMenu, p_97742_: I val CAN_BE_RESEARCHED = RGBAColor(150, 200, 150) val CAN_NOT_BE_RESEARCHED = RGBAColor(200, 150, 150) val ALREADY_BLOCKED = RGBAColor(105, 79, 79) + + private val LOW_POWER_0 = TranslatableComponent("otm.android_station.low_power_0") + private val LOW_POWER_1 = TranslatableComponent("otm.android_station.low_power_1") + private val POWER_OK = TranslatableComponent("otm.android_station.power_ok") } } \ No newline at end of file diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/AndroidStationMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/AndroidStationMenu.kt index 5d57d8e08..411a675e6 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/AndroidStationMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/AndroidStationMenu.kt @@ -1,48 +1,133 @@ package ru.dbotthepony.mc.otm.menu import com.google.common.collect.ImmutableList +import net.minecraft.server.level.ServerPlayer +import net.minecraft.world.Container import net.minecraft.world.SimpleContainer import net.minecraft.world.entity.player.Inventory import net.minecraft.world.entity.player.Player +import net.minecraft.world.inventory.Slot import net.minecraft.world.item.ItemStack +import net.minecraftforge.common.capabilities.ForgeCapabilities import ru.dbotthepony.mc.otm.block.entity.AndroidStationBlockEntity import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability -import ru.dbotthepony.mc.otm.capability.MatteryCapability +import ru.dbotthepony.mc.otm.capability.energy +import ru.dbotthepony.mc.otm.capability.matteryEnergy +import ru.dbotthepony.mc.otm.capability.matteryPlayer import ru.dbotthepony.mc.otm.registry.MMenus - -private class AndroidStationContainer(player: Player) : SimpleContainer(1) { - var android: MatteryPlayerCapability? = null - - init { - player.getCapability(MatteryCapability.MATTERY_PLAYER).ifPresent { - android = it - setItem(0, it.batteryItemStack) - } - } -} - -private class AndroidBatterySlot(container: AndroidStationContainer, index: Int) : BatterySlot(container, index) { - val android: MatteryPlayerCapability? = container.android - - override fun set(stack: ItemStack) { - super.set(stack) - android?.batteryItemStack = stack - } -} +import java.util.* +import kotlin.reflect.KMutableProperty0 class AndroidStationMenu @JvmOverloads constructor( containerID: Int, inventory: Inventory, tile: AndroidStationBlockEntity? = null ) : MatteryPoweredMenu(MMenus.ANDROID_STATION, containerID, inventory, tile) { - val androidBattery: MatterySlot = AndroidBatterySlot(AndroidStationContainer(inventory.player), 0) + private fun container(target: (MatteryPlayerCapability) -> KMutableProperty0): Container { + if (ply is ServerPlayer) + return PartContainer(target.invoke(ply.matteryPlayer ?: throw NullPointerException("OTM player capability is missing"))) + else + return SimpleContainer(1) + } - override val storageSlots = listOf(addSlot(androidBattery)) + private inner class PartContainer(parent: KMutableProperty0) : Container { + private var item by parent + + override fun clearContent() { + setItem(0, ItemStack.EMPTY) + } + + override fun getContainerSize(): Int { + return 1 + } + + override fun isEmpty(): Boolean { + return item.isEmpty + } + + override fun getItem(p_18941_: Int): ItemStack { + if (p_18941_ != 0) + return ItemStack.EMPTY + + return item + } + + override fun removeItem(p_18942_: Int, p_18943_: Int): ItemStack { + if (p_18942_ != 0 || powerWidget.level < AndroidStationBlockEntity.ENERGY_PER_OPERATION || item.isEmpty) + return ItemStack.EMPTY + + (tile as AndroidStationBlockEntity).energy.extractEnergyInner(AndroidStationBlockEntity.ENERGY_PER_OPERATION, false) + return removeItemNoUpdate(p_18942_) + } + + override fun removeItemNoUpdate(p_18951_: Int): ItemStack { + if (p_18951_ != 0) + return ItemStack.EMPTY + + val old = item.copy() + item = ItemStack.EMPTY + return old + } + + override fun setItem(p_18944_: Int, p_18945_: ItemStack) { + if (p_18944_ != 0) + return + + item = p_18945_ + } + + override fun setChanged() { + // no op + } + + override fun stillValid(p_18946_: Player): Boolean { + return true + } + + override fun getMaxStackSize(): Int { + return 1 + } + } + + private inner class AndroidSlot(container: Container, private val condition: (ItemStack) -> Boolean) : MatterySlot(container, 0) { + override fun mayPickup(p_40228_: Player): Boolean { + if (tile is AndroidStationBlockEntity) { + return tile.energy.batteryLevel >= AndroidStationBlockEntity.ENERGY_PER_OPERATION + } + + return powerWidget.level >= AndroidStationBlockEntity.ENERGY_PER_OPERATION + } + + override fun mayPlace(p_40231_: ItemStack): Boolean { + if (tile is AndroidStationBlockEntity) { + return tile.energy.batteryLevel >= AndroidStationBlockEntity.ENERGY_PER_OPERATION && condition.invoke(p_40231_) + } + + return powerWidget.level >= AndroidStationBlockEntity.ENERGY_PER_OPERATION && condition.invoke(p_40231_) + } + } + + val androidBattery: MatterySlot = AndroidSlot(container { it::batteryItemStack }) { + it.getCapability(ForgeCapabilities.ENERGY).isPresent + } + + override val storageSlots: ImmutableList val armorSlots = makeArmorSlots() init { armorSlots.forEach(this::addSlot) addInventorySlots() + + addSlot(androidBattery) + + val builder = ImmutableList.builder() + builder.addAll(armorSlots) + builder.add(androidBattery) + storageSlots = builder.build() + } + + override fun stillValid(player: Player): Boolean { + return super.stillValid(player) && player.matteryPlayer?.isAndroid == true } } diff --git a/src/main/resources/assets/overdrive_that_matters/models/block/android_station.json b/src/main/resources/assets/overdrive_that_matters/models/block/android_station_idle.json similarity index 100% rename from src/main/resources/assets/overdrive_that_matters/models/block/android_station.json rename to src/main/resources/assets/overdrive_that_matters/models/block/android_station_idle.json diff --git a/src/main/resources/assets/overdrive_that_matters/models/block/android_station_working.json b/src/main/resources/assets/overdrive_that_matters/models/block/android_station_working.json new file mode 100644 index 000000000..fb047e55b --- /dev/null +++ b/src/main/resources/assets/overdrive_that_matters/models/block/android_station_working.json @@ -0,0 +1,147 @@ +{ + "parent": "block/cube_all", + "render_type": "translucent", + "textures": { + "0": "overdrive_that_matters:block/android_station", + "particle": "overdrive_that_matters:block/android_station" + }, + "elements": [ + { + "name": "platform", + "from": [0, 7, 0], + "to": [16, 9, 16], + "faces": { + "north": {"uv": [8, 4, 16, 4.5], "texture": "#0"}, + "east": {"uv": [0, 4, 8, 4.5], "texture": "#0"}, + "south": {"uv": [8, 4, 16, 4.5], "texture": "#0"}, + "west": {"uv": [0, 4, 8, 4.5], "texture": "#0"}, + "up": {"uv": [8, 0, 16, 4], "texture": "#0"}, + "down": {"uv": [8, 4.5, 16, 8.5], "texture": "#0"} + } + }, + { + "name": "base", + "from": [0, 0, 0], + "to": [16, 4, 16], + "faces": { + "north": {"uv": [0, 8.5, 8, 9.5], "texture": "#0"}, + "east": {"uv": [0, 8.5, 8, 9.5], "texture": "#0"}, + "south": {"uv": [8, 8.5, 16, 9.5], "texture": "#0"}, + "west": {"uv": [8, 8.5, 16, 9.5], "texture": "#0"}, + "up": {"uv": [8, 4.5, 16, 8.5], "texture": "#0"}, + "down": {"uv": [8, 9.5, 16, 13.5], "texture": "#0"} + } + }, + { + "name": "body", + "from": [2, 4, 2], + "to": [14, 7, 14], + "faces": { + "north": {"uv": [1, 0, 7, 0.75], "texture": "#0"}, + "east": {"uv": [1, 0, 7, 0.75], "texture": "#0"}, + "south": {"uv": [1, 0, 7, 0.75], "texture": "#0"}, + "west": {"uv": [1, 0, 7, 0.75], "texture": "#0"}, + "up": {"uv": [9, 5, 15, 8], "texture": "#0"}, + "down": {"uv": [9, 5, 15, 8], "texture": "#0"} + } + }, + { + "name": "frame", + "from": [1, 4, 13], + "to": [3, 7, 15], + "faces": { + "north": {"uv": [7, 0, 8, 0.75], "texture": "#0"}, + "east": {"uv": [0, 0, 1, 0.75], "texture": "#0"}, + "south": {"uv": [7, 0, 8, 0.75], "texture": "#0"}, + "west": {"uv": [0, 0, 1, 0.75], "texture": "#0"}, + "up": {"uv": [0, 0, 1, 0.58182], "texture": "#0"}, + "down": {"uv": [0, 0, 1, 0.58182], "texture": "#0"} + } + }, + { + "name": "frame", + "from": [13, 4, 13], + "to": [15, 7, 15], + "faces": { + "north": {"uv": [0, 0, 1, 0.75], "texture": "#0"}, + "east": {"uv": [7, 0, 8, 0.75], "texture": "#0"}, + "south": {"uv": [0, 0, 1, 0.75], "texture": "#0"}, + "west": {"uv": [0, 0, 1, 0.75], "texture": "#0"}, + "up": {"uv": [0, 0, 1, 0.58182], "texture": "#0"}, + "down": {"uv": [0, 0, 1, 0.58182], "texture": "#0"} + } + }, + { + "name": "frame", + "from": [13, 4, 1], + "to": [15, 7, 3], + "faces": { + "north": {"uv": [7, 0, 8, 0.75], "texture": "#0"}, + "east": {"uv": [0, 0, 1, 0.75], "texture": "#0"}, + "south": {"uv": [7, 0, 8, 0.75], "texture": "#0"}, + "west": {"uv": [0, 0, 1, 0.75], "texture": "#0"}, + "up": {"uv": [0, 0, 1, 0.58182], "texture": "#0"}, + "down": {"uv": [0, 0, 1, 0.58182], "texture": "#0"} + } + }, + { + "name": "frame", + "from": [1, 4, 1], + "to": [3, 7, 3], + "faces": { + "north": {"uv": [0, 0, 1, 0.75], "texture": "#0"}, + "east": {"uv": [0, 0, 1, 0.75], "texture": "#0"}, + "south": {"uv": [0, 0, 1, 0.75], "texture": "#0"}, + "west": {"uv": [7, 0, 8, 0.75], "texture": "#0"}, + "up": {"uv": [0, 0, 1, 0.58182], "texture": "#0"}, + "down": {"uv": [0, 0, 1, 0.58182], "texture": "#0"} + } + }, + { + "from": [-1, 10, -1], + "to": [17, 10, 17], + "faces": { + "north": {"uv": [0, 0, 8, 0], "texture": "#missing"}, + "east": {"uv": [0, 0, 8, 0], "texture": "#missing"}, + "south": {"uv": [0, 0, 8, 0], "texture": "#missing"}, + "west": {"uv": [0, 0, 8, 0], "texture": "#missing"}, + "up": {"uv": [0, 9.5, 8, 13.5], "texture": "#0"}, + "down": {"uv": [0, 9.5, 8, 13.5], "texture": "#0"} + } + } + ], + "display": { + "thirdperson_righthand": { + "rotation": [75, 45, 0], + "translation": [0, 2.5, 0], + "scale": [0.375, 0.375, 0.375] + }, + "thirdperson_lefthand": { + "rotation": [75, 45, 0], + "translation": [0, 2.5, 0], + "scale": [0.375, 0.375, 0.375] + }, + "firstperson_righthand": { + "rotation": [0, 45, 0], + "scale": [0.4, 0.4, 0.4] + }, + "firstperson_lefthand": { + "rotation": [0, 225, 0], + "scale": [0.4, 0.4, 0.4] + }, + "ground": { + "translation": [0, 3, 0], + "scale": [0.25, 0.25, 0.25] + }, + "gui": { + "rotation": [30, 225, 0], + "scale": [0.625, 0.625, 0.625] + }, + "head": { + "translation": [0, 13, 0] + }, + "fixed": { + "scale": [0.5, 0.5, 0.5] + } + } +} \ No newline at end of file