From 3cacf7f11f7cf3abd5564f2536e5a2e3a9c1b9df Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Sat, 8 Jul 2023 00:51:37 +0700 Subject: [PATCH] Exopack smelting, RenderGravity, IGUIRenderable --- .../mc/otm/datagen/lang/English.kt | 3 + .../mc/otm/datagen/lang/Russian.kt | 9 +- .../mc/otm/OverdriveThatMatters.java | 4 +- .../otm/capability/MatteryPlayerCapability.kt | 190 ++++++++++++++---- ...ource.kt => BatteryBackedEnergyStorage.kt} | 30 ++- .../mc/otm/client/AndroidMenuKeyMapping.kt | 10 +- .../dbotthepony/mc/otm/client/MatteryGUI.kt | 16 +- .../client/render/AbstractMatterySprite.kt | 11 +- .../dbotthepony/mc/otm/client/render/Ext.kt | 187 +++++------------ .../mc/otm/client/render/IGUIRenderable.kt | 64 ++++++ .../mc/otm/client/render/RenderGravity.kt | 184 +++++++++++++++++ .../render/blockentity/BlackHoleRenderer.kt | 8 +- .../blockentity/EnergyCounterRenderer.kt | 16 +- .../GravitationStabilizerRenderer.kt | 9 +- .../render/blockentity/HoloSignRenderer.kt | 4 +- .../render/entity/PlasmaProjectileRenderer.kt | 4 +- .../client/screen/ExoPackInventoryScreen.kt | 86 +++++++- .../otm/client/screen/panels/EditablePanel.kt | 39 +++- .../client/screen/panels/EffectListPanel.kt | 9 +- .../mc/otm/client/screen/panels/FramePanel.kt | 13 +- .../mc/otm/client/screen/panels/Label.kt | 40 ++-- .../otm/client/screen/panels/SpritePanel.kt | 9 +- .../screen/panels/button/ButtonPanel.kt | 6 +- .../screen/panels/input/TextInputPanel.kt | 17 +- .../screen/panels/slot/AbstractSlotPanel.kt | 4 +- .../client/screen/panels/slot/SlotPanel.kt | 5 +- .../screen/tech/AndroidStationScreen.kt | 8 +- .../screen/tech/EssenceStorageScreen.kt | 5 +- .../compat/jei/PlatePressRecipeCategory.kt | 6 +- .../mc/otm/config/ExopackConfig.kt | 15 ++ ...ngUpgradeItem.kt => ExopackUpgradeItem.kt} | 27 ++- .../mc/otm/item/weapon/AbstractWeaponItem.kt | 5 +- .../mc/otm/menu/ExoPackInventoryMenu.kt | 41 ++++ .../ru/dbotthepony/mc/otm/menu/MatteryMenu.kt | 12 +- .../mc/otm/menu/input/InstantBooleanInput.kt | 25 +++ .../network/synchronizer/FieldSynchronizer.kt | 2 +- .../mc/otm/registry/MCreativeTabs.kt | 1 + .../ru/dbotthepony/mc/otm/registry/MItems.kt | 6 +- 38 files changed, 804 insertions(+), 326 deletions(-) rename src/main/kotlin/ru/dbotthepony/mc/otm/capability/energy/{AndroidPowerSource.kt => BatteryBackedEnergyStorage.kt} (86%) create mode 100644 src/main/kotlin/ru/dbotthepony/mc/otm/client/render/IGUIRenderable.kt create mode 100644 src/main/kotlin/ru/dbotthepony/mc/otm/client/render/RenderGravity.kt create mode 100644 src/main/kotlin/ru/dbotthepony/mc/otm/config/ExopackConfig.kt rename src/main/kotlin/ru/dbotthepony/mc/otm/item/exopack/{ExoPackCraftingUpgradeItem.kt => ExopackUpgradeItem.kt} (74%) create mode 100644 src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/InstantBooleanInput.kt 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 e76ae4983..ac240e091 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 @@ -148,6 +148,7 @@ private fun misc(provider: MatteryLanguageProvider) { gui("exopack_upgrades.already_activated", "Upgrade is already active!") gui("exopack_upgrades.slots_upgrade", "Using this will permanently grant %s slots in your Exopack inventory.") gui("exopack_upgrades.crafting_upgrade", "Using this will permanently grant 3x3 crafting grid in your Exopack inventory.") + gui("exopack_upgrades.smelting_upgrade", "Using this will permanently grant smelter in your Exopack inventory.") gui("crude_battery.replace_in_world", "Simplistic nature of this battery allows to replace your energy source in the field without using Android Station.") gui("crude_battery.replace_in_world_warning", "This operation is very unstable and can cause extreme damage to your systems!") @@ -158,6 +159,7 @@ private fun misc(provider: MatteryLanguageProvider) { misc("exopack_upgrades.slots_upgraded", "Your Exopack has permanently gained %s slots") misc("exopack_upgrades.crafting_upgraded", "Your Exopack has permanently gained 3x3 crafting grid") + misc("exopack_upgrades.smelting_installed", "Your Exopack has permanently gained smelting module") misc("exopack.granted1", "As you keep pressing on the fingerprint reader, probe disappears.") misc("exopack.granted2", "After a moment, you are getting pierced into back multiple times...") @@ -474,6 +476,7 @@ private fun items(provider: MatteryLanguageProvider) { add(MItems.EXOPACK_PROBE, "Exopack Probe") add(MItems.ExopackUpgrades.INVENTORY_UPGRADE_CREATIVE, "Creative Exopack Inventory Upgrade") add(MItems.ExopackUpgrades.CRAFTING_UPGRADE, "Exopack Crafting Upgrade") + add(MItems.ExopackUpgrades.SMELTING_UPGRADE, "Exopack Smelting Module") add(MItems.ExopackUpgrades.INVENTORY_UPGRADE_WITHER, "Superdense Packing Upgrade") add(MItems.ExopackUpgrades.INVENTORY_UPGRADE_WITHER, "description", "Utilizes similar principle that exhibit Nether Stars") diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/Russian.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/Russian.kt index 291b4ff5a..4faf716dd 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/Russian.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/Russian.kt @@ -155,7 +155,8 @@ private fun misc(provider: MatteryLanguageProvider) { gui("exopack_upgrades.already_activated", "Улучшение уже активно!") gui("exopack_upgrades.slots_upgrade", "Активируя данное улучшение даст %s слотов в вашем экзопаке.") - gui("exopack_upgrades.crafting_upgrade", "Активируя данное улучшение даст 3x3 сетку создания в вашем экзопаке.") + gui("exopack_upgrades.crafting_upgrade", "Активация данного улучшения даст 3x3 сетку создания в вашем экзопаке.") + gui("exopack_upgrades.smelting_upgrade", "Активация данного улучшения даст плавильню в вашем экзопаке.") gui("crude_battery.replace_in_world", "Простота устройства данного аккумулятора позволяет вам заменить .") gui("crude_battery.replace_in_world_warning", "Данная операция крайне рискованная и может нанести огромный урон вашим системам!") @@ -164,8 +165,9 @@ private fun misc(provider: MatteryLanguageProvider) { misc("battery.single_use", "Единоразовая батарейка, не может быть перезаряжена.") - misc("exopack_upgrades.slots_upgraded", "Ваш Экзопак был расширен на %s слотов") - misc("exopack_upgrades.crafting_upgraded", "Ваш Экзопак получил 3x3 сетку создания") + misc("exopack_upgrades.slots_upgraded", "Ваш экзопак был расширен на %s слотов") + misc("exopack_upgrades.crafting_upgraded", "Ваш экзопак получил 3x3 сетку создания") + misc("exopack_upgrades.smelting_upgraded", "Ваш экзопак получил плавильню") misc("exopack.granted1", "После некоторого времени нажатия на сканер отпечатка, маяк исчезает.") misc("exopack.granted2", "Через мгновение, вашу спину пронзают множество раз...") @@ -478,6 +480,7 @@ private fun items(provider: MatteryLanguageProvider) { add(MItems.EXOPACK_PROBE, "Маяк экзопака") add(MItems.ExopackUpgrades.INVENTORY_UPGRADE_CREATIVE, "Творческое обновление инвентаря экзопака") add(MItems.ExopackUpgrades.CRAFTING_UPGRADE, "Обновление сетки крафта экзопака") + add(MItems.ExopackUpgrades.SMELTING_UPGRADE, "Модуль плавильни экзопака") add(MItems.ExopackUpgrades.INVENTORY_UPGRADE_WITHER, "Обновление сверхмассивной упаковки") add(MItems.ExopackUpgrades.INVENTORY_UPGRADE_WITHER, "description", "Использует те же принципы, которыми обладают звёзды незера") diff --git a/src/main/java/ru/dbotthepony/mc/otm/OverdriveThatMatters.java b/src/main/java/ru/dbotthepony/mc/otm/OverdriveThatMatters.java index 4b410adfc..c03666bbd 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/OverdriveThatMatters.java +++ b/src/main/java/ru/dbotthepony/mc/otm/OverdriveThatMatters.java @@ -40,6 +40,7 @@ import ru.dbotthepony.mc.otm.compat.mekanism.MekanismHooks; import ru.dbotthepony.mc.otm.compat.mekanism.QIOKt; import ru.dbotthepony.mc.otm.config.AndroidConfig; import ru.dbotthepony.mc.otm.config.ClientConfig; +import ru.dbotthepony.mc.otm.config.ExopackConfig; import ru.dbotthepony.mc.otm.config.ItemsConfig; import ru.dbotthepony.mc.otm.config.MachinesConfig; import ru.dbotthepony.mc.otm.config.ServerCompatConfig; @@ -140,6 +141,7 @@ public final class OverdriveThatMatters { ServerConfig.INSTANCE.register(); ServerCompatConfig.INSTANCE.register(); AndroidConfig.INSTANCE.register(); + ExopackConfig.INSTANCE.register(); ItemsConfig.INSTANCE.register(); MachinesConfig.INSTANCE.register(); ToolsConfig.INSTANCE.register(); @@ -167,7 +169,7 @@ public final class OverdriveThatMatters { EVENT_BUS.addListener(EventPriority.NORMAL, MatteryPlayerCapability.Companion::onPlayerCloneEvent); EVENT_BUS.addListener(EventPriority.NORMAL, MatteryPlayerCapability.Companion::onStartTracking); EVENT_BUS.addListener(EventPriority.NORMAL, MatteryPlayerCapability.Companion::onStopTracking); - EVENT_BUS.addListener(EventPriority.NORMAL, MatteryPlayerCapability.MPCommands::addCommands); + EVENT_BUS.addListener(EventPriority.NORMAL, MatteryPlayerCapability.Companion::addCommands); EVENT_BUS.addListener(EventPriority.NORMAL, ExplosionQueue.Companion::onWorldTick); EVENT_BUS.addListener(EventPriority.NORMAL, AbstractWeaponItem.Companion::tick); diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/MatteryPlayerCapability.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/MatteryPlayerCapability.kt index 5341a58b4..d1737afff 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/MatteryPlayerCapability.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/MatteryPlayerCapability.kt @@ -10,6 +10,7 @@ import net.minecraft.nbt.ListTag import net.minecraft.nbt.StringTag import net.minecraft.network.chat.Component import net.minecraft.resources.ResourceLocation +import net.minecraft.server.level.ServerLevel import net.minecraft.server.level.ServerPlayer import net.minecraft.tags.TagKey import net.minecraft.world.Difficulty @@ -19,15 +20,14 @@ import net.minecraft.world.effect.MobEffectInstance import net.minecraft.world.effect.MobEffects import net.minecraft.world.entity.Entity import net.minecraft.world.entity.LivingEntity -import net.minecraft.world.entity.MobSpawnType import net.minecraft.world.entity.boss.wither.WitherBoss -import net.minecraft.world.entity.monster.Phantom import net.minecraft.world.entity.player.Inventory import net.minecraft.world.entity.player.Player -import net.minecraft.world.inventory.InventoryMenu import net.minecraft.world.item.ItemStack import net.minecraft.world.item.Items import net.minecraft.world.item.ProjectileWeaponItem +import net.minecraft.world.item.crafting.RecipeManager +import net.minecraft.world.item.crafting.RecipeType import net.minecraft.world.item.enchantment.EnchantmentHelper.hasVanishingCurse import net.minecraft.world.level.GameRules import net.minecraft.world.level.Level @@ -47,8 +47,10 @@ import net.minecraftforge.event.entity.living.LivingDeathEvent import net.minecraftforge.event.entity.living.LivingHurtEvent import net.minecraftforge.event.entity.living.MobEffectEvent import net.minecraftforge.event.entity.player.PlayerEvent +import net.minecraftforge.eventbus.api.Cancelable import net.minecraftforge.eventbus.api.Event import net.minecraftforge.registries.ForgeRegistries +import net.minecraftforge.server.command.EnumArgument import org.apache.logging.log4j.LogManager import ru.dbotthepony.mc.otm.* import ru.dbotthepony.mc.otm.android.AndroidFeature @@ -56,12 +58,18 @@ import ru.dbotthepony.mc.otm.android.AndroidFeatureType import ru.dbotthepony.mc.otm.android.AndroidResearch import ru.dbotthepony.mc.otm.android.AndroidResearchManager import ru.dbotthepony.mc.otm.android.AndroidResearchType -import ru.dbotthepony.mc.otm.android.AndroidSwitchableFeature -import ru.dbotthepony.mc.otm.capability.energy.AndroidPowerSource +import ru.dbotthepony.mc.otm.block.entity.JobContainer +import ru.dbotthepony.mc.otm.block.entity.JobStatus +import ru.dbotthepony.mc.otm.block.entity.MachineItemJob +import ru.dbotthepony.mc.otm.block.entity.MachineJobEventLoop +import ru.dbotthepony.mc.otm.capability.energy.BatteryBackedEnergyStorage +import ru.dbotthepony.mc.otm.capability.energy.IMatteryEnergyStorage +import ru.dbotthepony.mc.otm.capability.energy.ProfiledEnergyStorage import ru.dbotthepony.mc.otm.capability.energy.extractEnergyExact import ru.dbotthepony.mc.otm.capability.energy.receiveEnergyExact import ru.dbotthepony.mc.otm.client.minecraft import ru.dbotthepony.mc.otm.config.AndroidConfig +import ru.dbotthepony.mc.otm.config.ExopackConfig import ru.dbotthepony.mc.otm.container.MatteryContainer import ru.dbotthepony.mc.otm.container.stream import ru.dbotthepony.mc.otm.core.* @@ -95,6 +103,7 @@ import java.util.stream.Stream import kotlin.collections.ArrayDeque import kotlin.collections.ArrayList import kotlin.collections.HashMap +import kotlin.reflect.KMutableProperty1 @Suppress("unused") class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerializable { @@ -103,10 +112,8 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial * * Cancelling it is probably not a good idea, but you can do it anyway. */ + @Cancelable data class PreTick(val capability: MatteryPlayerCapability) : Event() { - override fun isCancelable() = true - override fun hasResult() = false - val player get() = capability.ply val level: Level get() = capability.ply.level() } @@ -115,9 +122,6 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial * This event is fired on main event bus after ticking logic took place. */ data class PostTick(val capability: MatteryPlayerCapability) : Event() { - override fun isCancelable() = false - override fun hasResult() = false - val player get() = capability.ply val level: Level get() = capability.ply.level() } @@ -127,10 +131,6 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial * (both in [Inventory] and [MatteryPlayerCapability] exopack due to inventory filters or no free space). */ data class ItemStackLeftoverEvent(val stack: ItemStack, val capability: MatteryPlayerCapability) : Event() { - override fun isCancelable() = false - override fun hasResult() = false - override fun setResult(value: Result) {} - val player get() = capability.ply val level: Level get() = capability.ply.level() } @@ -149,25 +149,26 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial /** * For fields that need to be synchronized only to owning player * - * Please mind if you really need to use this in your mod; - * any differences in field order/types/etc will break *everything* - * + * Please mind when you use this in your mod; + * any differences in field order/types/etc between client and server + * will break *everything* */ val synchronizer = FieldSynchronizer() - /** - * For data to be stored and loaded from NBT automatically - */ - val savetables = Savetables() - /** * For fields that need to be synchronized to everyone * - * Please mind if you really need to use this in your mod; - * any differences in field order/types/etc will break *everything* + * Please mind when you use this in your mod; + * any differences in field order/types/etc between client and server + * will break *everything* */ val publicSynchronizer = FieldSynchronizer() + /** + * For data to be stored to and loaded from NBT automatically + */ + val savetables = Savetables() + /** * Whenever player has Exopack */ @@ -238,7 +239,7 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial * Whenever Exopack has 3x3 crafting grid upgrade installed */ var isExoPackCraftingUpgraded by publicSynchronizer.bool(setter = setter@{ value, access, _ -> - if (value != access.read()) { + if (value != access.readBoolean()) { access.write(value) _exoPackMenu = null } @@ -324,16 +325,91 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial * * But they can be harmed using harm potion * * Can't be poisoned (with default datapack) * * CAN be withered (with default datapack) + * * Ignored by the Wither but not by Wither Skeletons + * * Can't drown * * etc * * Android-immune (de)buffs are specified in `data/overdrive_that_matters/tags/mob_effect/android_immune_effects.json` */ var isAndroid by publicSynchronizer.bool().property + /** + * Whenever player has exosuit smelting upgrade + */ + var isExoPackSmeltingInstalled by synchronizer.bool(setter = { value, access, _ -> + if (value != access.readBoolean()) { + access.write(value) + _exoPackMenu = null + } + }).property + + inner class SmelterBelt(index: Int) : MachineJobEventLoop() { + override val energy: IMatteryEnergyStorage + get() = exoPackEnergy + override val isBlockedByRedstone: Boolean + get() = false + + override fun deserializeJob(nbt: CompoundTag): MachineItemJob { + return MachineItemJob(nbt) + } + + override val upgrades: IMatteryUpgrade? + get() = null + + override fun jobUpdated(new: MachineItemJob?, old: MachineItemJob?) {} + + override fun onJobFinish(job: MachineItemJob): JobStatus { + if (output.fullyAddItem(job.itemStack)) { + exoPackSmelterExperience += job.experience + return JobStatus.SUCCESS + } else { + return JobStatus.FAILURE_ITEM + } + } + + private val cache = RecipeManager.createCheck(RecipeType.SMELTING) + + override fun computeNextJob(): JobContainer { + val level = ply.level() as? ServerLevel ?: return JobContainer.failure() + val recipe = cache.getRecipeFor(input, level) + + if (recipe.isEmpty) { + return JobContainer.noItem() + } else { + val actual = recipe.get() + val item = actual.assemble(input, level.registryAccess()) + input[0].shrink(1) + input.setChanged(0) + return JobContainer.success(MachineItemJob(item, actual.cookingTime.toDouble(), ExopackConfig.FURNACE_POWER_CONSUMPTION, actual.experience)) + } + } + + val input = MatteryContainer({ notify(IdleReason.ITEM) }, 1) + val output = MatteryContainer({ notify(IdleReason.ITEM) }, 1) + + init { + savetables.stateful(::input, "exopack_smelter_input_$index") + savetables.stateful(::output, "exopack_smelter_output_$index") + savetables.stateful(this, "exopack_smelter_worker_$index") + } + } + + val smelter0 = SmelterBelt(0) + val smelter1 = SmelterBelt(1) + val smelter2 = SmelterBelt(2) + val smelters = listOf(smelter0, smelter1, smelter2) + + var exoPackSmelterExperience = 0f + /** * [IMatteryEnergyStorage] instance, representing Android' battery charge */ - val androidEnergy = AndroidPowerSource(ply, synchronizer, AndroidConfig.ANDROID_MAX_ENERGY, AndroidConfig.ANDROID_MAX_ENERGY) + val androidEnergy = BatteryBackedEnergyStorage(ply, synchronizer, AndroidConfig.ANDROID_MAX_ENERGY, AndroidConfig.ANDROID_MAX_ENERGY) + + /** + * [IMatteryEnergyStorage] instance, representing Exopack battery charge + */ + val exoPackEnergy = ProfiledEnergyStorage(BatteryBackedEnergyStorage(ply, synchronizer, Decimal.ZERO, ExopackConfig.ENERGY_CAPACITY)) init { savetables.int(::ticksIExist) @@ -355,6 +431,9 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial savetables.stateful(::exoPackSlotModifier, "exoSuitSlotCountModifiers") savetables.stateful(::exoPackContainer, "exoSuitContainer") savetables.stateful(::androidEnergy) + savetables.stateful(::exoPackEnergy) + savetables.float(::exoPackSmelterExperience) + savetables.bool(::isExoPackSmeltingInstalled) } fun invalidateNetworkState() { @@ -642,7 +721,7 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial return featureMap[feature] as T? } - internal fun onHurt(event: LivingHurtEvent) { + private fun onHurt(event: LivingHurtEvent) { if (isAndroid) { for (feature in featureMap.values) { feature.onHurt(event) @@ -654,7 +733,7 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial } } - internal fun onAttack(event: LivingAttackEvent) { + private fun onAttack(event: LivingAttackEvent) { if (isAndroid) { for (feature in featureMap.values) { feature.onAttack(event) @@ -862,6 +941,14 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial } } + if (hasExoPack) { + exoPackEnergy.parent.tick() + + if (!ply.isSpectator && isExoPackSmeltingInstalled) { + smelters.forEach { it.think() } + } + } + if (isAndroid) { androidEnergy.tick() @@ -1194,19 +1281,22 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial return stack.isEmpty } - object MPCommands { - @JvmStatic + enum class UpgradeType(val prop: KMutableProperty1) { + CRAFTING(MatteryPlayerCapability::isExoPackCraftingUpgraded), + SMELTING(MatteryPlayerCapability::isExoPackSmeltingInstalled); + } + + @Suppress("unused") + companion object { private fun setExoPack(players: Collection, hasExoPack: Boolean): Int { for (player in players) { - if (player.containerMenu is InventoryMenu || player.containerMenu is ExoPackInventoryMenu) player.closeContainer() - player.matteryPlayer?.hasExoPack = hasExoPack + player.matteryPlayer?._exoPackMenu = null } return players.size } - @JvmStatic private fun makeAndroid(players: Collection): Int { for (player in players) { player.matteryPlayer?.becomeAndroid() @@ -1215,7 +1305,6 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial return players.size } - @JvmStatic private fun makeHuman(players: Collection): Int { for (player in players) { player.matteryPlayer?.becomeHumane() @@ -1224,38 +1313,51 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial return players.size } - @JvmStatic + private fun setUpgrade(players: Collection, type: UpgradeType, state: Boolean): Int { + for (player in players) { + player.matteryPlayer?.let { type.prop.set(it, state) } + } + + return players.size + } + fun addCommands(event: RegisterCommandsEvent) { event.dispatcher.register( Commands.literal("exopack") .requires { it.hasPermission(Commands.LEVEL_GAMEMASTERS) } .then(Commands.literal("add") - .executes { setExoPack(Collections.singleton(it.source.playerOrException), true) } + .executes { setExoPack(listOf(it.source.playerOrException), true) } .then(Commands.argument("targets", EntityArgument.players()).executes { setExoPack(EntityArgument.getPlayers(it, "targets"), true) }) ) .then(Commands.literal("remove") - .executes { setExoPack(Collections.singleton(it.source.playerOrException), false) } + .executes { setExoPack(listOf(it.source.playerOrException), false) } .then(Commands.argument("targets", EntityArgument.players()).executes { setExoPack(EntityArgument.getPlayers(it, "targets"), false) }) ) + .then(Commands.literal("upgrade") + .then(Commands.argument("type", EnumArgument.enumArgument(UpgradeType::class.java)) + .then(Commands.literal("add") + .executes { setUpgrade(listOf(it.source.playerOrException), it.getArgument("type", UpgradeType::class.java), true) } + .then(Commands.argument("targets", EntityArgument.players()).executes { setUpgrade(EntityArgument.getPlayers(it, "targets"), it.getArgument("type", UpgradeType::class.java), true) })) + .then(Commands.literal("remove") + .executes { setUpgrade(listOf(it.source.playerOrException), it.getArgument("type", UpgradeType::class.java), false) } + .then(Commands.argument("targets", EntityArgument.players()).executes { setUpgrade(EntityArgument.getPlayers(it, "targets"), it.getArgument("type", UpgradeType::class.java), false) }))) + ) ) event.dispatcher.register( Commands.literal("android") .requires { it.hasPermission(Commands.LEVEL_GAMEMASTERS) } .then(Commands.literal("on") - .executes { makeAndroid(Collections.singleton(it.source.playerOrException)) } + .executes { makeAndroid(listOf(it.source.playerOrException)) } .then(Commands.argument("targets", EntityArgument.players()).executes { makeAndroid(EntityArgument.getPlayers(it, "targets")) }) ) .then(Commands.literal("off") - .executes { makeHuman(Collections.singleton(it.source.playerOrException)) } + .executes { makeHuman(listOf(it.source.playerOrException)) } .then(Commands.argument("targets", EntityArgument.players()).executes { makeHuman(EntityArgument.getPlayers(it, "targets")) }) ) ) } - } - @Suppress("unused") - companion object { private fun stackStacks(it: ItemStack, stack: ItemStack): Boolean { if ( !it.isEmpty && @@ -1353,7 +1455,7 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial mattery.iteration++ mattery.shouldSendIteration = true mattery.deathLog.addLast(ply.tickCount to ply.combatTracker.deathMessage) - mattery.androidEnergy.batteryLevel = mattery.androidEnergy.batteryLevel.coerceAtLeast(Decimal(20_000)) // если смерть была от разряда батареи, то предотвращаем софтлок + mattery.androidEnergy.batteryLevel = mattery.androidEnergy.batteryLevel.coerceAtLeast(AndroidConfig.ANDROID_MAX_ENERGY * Decimal("0.2")) // если смерть была от разряда батареи, то предотвращаем софтлок while (mattery.deathLog.size > 6) { mattery.deathLog.removeFirst() diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/energy/AndroidPowerSource.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/energy/BatteryBackedEnergyStorage.kt similarity index 86% rename from src/main/kotlin/ru/dbotthepony/mc/otm/capability/energy/AndroidPowerSource.kt rename to src/main/kotlin/ru/dbotthepony/mc/otm/capability/energy/BatteryBackedEnergyStorage.kt index c5aeff61e..5d9e30922 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/energy/AndroidPowerSource.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/energy/BatteryBackedEnergyStorage.kt @@ -4,6 +4,7 @@ import net.minecraft.nbt.CompoundTag import net.minecraft.server.level.ServerPlayer import net.minecraft.world.entity.player.Player import net.minecraft.world.item.ItemStack +import net.minecraft.world.ticks.ContainerSingleItem import net.minecraftforge.common.capabilities.ForgeCapabilities import net.minecraftforge.common.util.INBTSerializable import ru.dbotthepony.mc.otm.capability.FlowDirection @@ -18,19 +19,19 @@ import ru.dbotthepony.mc.otm.network.synchronizer.FieldSynchronizer import ru.dbotthepony.mc.otm.registry.StatNames import ru.dbotthepony.mc.otm.triggers.AndroidBatteryTrigger -class AndroidPowerSource( +class BatteryBackedEnergyStorage( private val ply: Player, synchronizer: FieldSynchronizer, initialCharge: Decimal, maxCharge: Decimal -) : IMatteryEnergyStorage, INBTSerializable { +) : IMatteryEnergyStorage, INBTSerializable, ContainerSingleItem { override val energyFlow: FlowDirection get() = FlowDirection.INPUT private var battery by synchronizer.decimal(initialCharge) private var maxBattery by synchronizer.decimal(maxCharge) - var item by synchronizer.item(setter = setter@{ value, access, setByRemote -> + var item by synchronizer.item(setter = setter@{ value, access, _ -> access.write(value) if (ply is ServerPlayer) { @@ -38,6 +39,29 @@ class AndroidPowerSource( } }) + override fun getItem(slot: Int): ItemStack { + require(slot == 0) { "Invalid slot $slot" } + return item + } + + override fun removeItem(slot: Int, count: Int): ItemStack { + require(slot == 0) { "Invalid slot $slot" } + return item.split(count) + } + + override fun setItem(slot: Int, stack: ItemStack) { + require(slot == 0) { "Invalid slot $slot" } + item = stack + } + + override fun setChanged() { + + } + + override fun stillValid(p_18946_: Player): Boolean { + return true + } + override fun serializeNBT(): CompoundTag { return CompoundTag().also { it["battery"] = battery.serializeNBT() diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/AndroidMenuKeyMapping.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/AndroidMenuKeyMapping.kt index 3aac27d2d..8c1ca9854 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/AndroidMenuKeyMapping.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/AndroidMenuKeyMapping.kt @@ -13,7 +13,7 @@ import ru.dbotthepony.mc.otm.OverdriveThatMatters import ru.dbotthepony.mc.otm.android.AndroidFeature import ru.dbotthepony.mc.otm.android.AndroidSwitchableFeature import ru.dbotthepony.mc.otm.capability.matteryPlayer -import ru.dbotthepony.mc.otm.client.render.TextAlign +import ru.dbotthepony.mc.otm.client.render.RenderGravity import ru.dbotthepony.mc.otm.client.render.drawAligned import ru.dbotthepony.mc.otm.client.render.drawArc import ru.dbotthepony.mc.otm.core.math.RGBAColor @@ -257,15 +257,15 @@ object AndroidMenuKeyMapping : KeyMapping("key.otm.android_menu", KeyConflictCon val shift = size * 0.6f feature.renderIcon(event.guiGraphics, -iconSize / 2f + shift * cos, -shift * sin - iconSize / 2f, iconSize, iconSize) - event.guiGraphics.drawAligned(minecraft.font, feature.type.displayName, TextAlign.CENTER_CENTER, shift * cos + 1f, -shift * sin - iconSize / 1.5f + 1f, 0) - event.guiGraphics.drawAligned(minecraft.font, feature.type.displayName, TextAlign.CENTER_CENTER, shift * cos, -shift * sin - iconSize / 1.5f, if (feature.isActive) RGBAColor.DARK_GREEN else RGBAColor.DARK_RED) + event.guiGraphics.drawAligned(minecraft.font, feature.type.displayName, RenderGravity.CENTER_CENTER, shift * cos + 1f, -shift * sin - iconSize / 1.5f + 1f, 0) + event.guiGraphics.drawAligned(minecraft.font, feature.type.displayName, RenderGravity.CENTER_CENTER, shift * cos, -shift * sin - iconSize / 1.5f, if (feature.isActive) RGBAColor.DARK_GREEN else RGBAColor.DARK_RED) if (feature.isOnCooldown && feature.cooldownPercent > 0.0f) { RenderSystem.setShaderColor(1f, 1f, 1f, 0.5f) drawArc(event.guiGraphics, shift * cos, -shift * sin, iconSize / 2f, 0f, PI / 2.0, PI / 2.0 + PI * 2.0 * feature.cooldownPercent.toDouble()) RenderSystem.setShaderColor(1f, 1f, 1f, 1f) - event.guiGraphics.drawAligned(minecraft.font, formatTickDuration(feature.cooldown), TextAlign.CENTER_CENTER, shift * cos, -shift * sin + iconSize / 1.5f, RGBAColor.WHITE) + event.guiGraphics.drawAligned(minecraft.font, formatTickDuration(feature.cooldown), RenderGravity.CENTER_CENTER, shift * cos, -shift * sin + iconSize / 1.5f, RGBAColor.WHITE) } } @@ -302,7 +302,7 @@ object AndroidMenuKeyMapping : KeyMapping("key.otm.android_menu", KeyConflictCon drawArc(event.guiGraphics, x, y, COOLDOWN_ICON_SIZE / 2f, 0f, PI / 2.0, PI / 2.0 + PI * 2.0 * feature.cooldownPercent, alignAtCenter = false) RenderSystem.setShaderColor(1f, 1f, 1f, 1f) - event.guiGraphics.drawAligned(font, formatTickDuration(feature.cooldown), TextAlign.TOP_CENTER, x + COOLDOWN_ICON_SIZE / 2f, y + COOLDOWN_ICON_SIZE + 1f, RGBAColor.WHITE) + event.guiGraphics.drawAligned(font, formatTickDuration(feature.cooldown), RenderGravity.TOP_CENTER, x + COOLDOWN_ICON_SIZE / 2f, y + COOLDOWN_ICON_SIZE + 1f, RGBAColor.WHITE) x += COOLDOWN_ICON_SIZE + COOLDOWN_ICON_MARGIN } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/MatteryGUI.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/MatteryGUI.kt index 6e9372b08..53a4fc24d 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/MatteryGUI.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/MatteryGUI.kt @@ -160,8 +160,8 @@ object MatteryGUI { val text = TranslatableComponent("otm.iteration", iteration) - minecraft.font.drawAligned(stack, text, TextAlign.CENTER_CENTER, x + 1f, y + 1f, RGBAColor.BLACK) - minecraft.font.drawAligned(stack, text, TextAlign.CENTER_CENTER, x, y, RGBAColor.WHITE) + minecraft.font.drawAligned(stack, text, RenderGravity.CENTER_CENTER, x + 1f, y + 1f, RGBAColor.BLACK) + minecraft.font.drawAligned(stack, text, RenderGravity.CENTER_CENTER, x, y, RGBAColor.WHITE) stack.scale(0.35f, 0.35f, 0.35f) @@ -177,8 +177,8 @@ object MatteryGUI { for (i in deathLog.indices.reversed()) { val component = deathLog[i] - minecraft.font.drawAligned(stack, component.second, TextAlign.CENTER_CENTER, x + 1f, y + 1f, RGBAColor.BLACK) - minecraft.font.drawAligned(stack, component.second, TextAlign.CENTER_CENTER, x, y, RGBAColor(color, color, color)) + minecraft.font.drawAligned(stack, component.second, RenderGravity.CENTER_CENTER, x + 1f, y + 1f, RGBAColor.BLACK) + minecraft.font.drawAligned(stack, component.second, RenderGravity.CENTER_CENTER, x, y, RGBAColor(color, color, color)) y += minecraft.font.lineHeight color = (color - 0x20).coerceAtLeast(0x0) @@ -249,8 +249,8 @@ object MatteryGUI { val formattedPower = mattery.androidEnergy.batteryLevel.formatPower() - event.guiGraphics.drawScaledAligned(gui.font, formattedPower, 0.5f, TextAlign.CENTER_LEFT, left + 83f, top + 4f, RGBAColor.BLACK.toInt()) - event.guiGraphics.drawScaledAligned(gui.font, formattedPower, 0.5f, TextAlign.CENTER_LEFT, left + 82f, top + 3f, RGBAColor.YELLOW.toInt()) + event.guiGraphics.drawScaledAligned(gui.font, formattedPower, 0.5f, RenderGravity.CENTER_LEFT, left + 83f, top + 4f, RGBAColor.BLACK.toInt()) + event.guiGraphics.drawScaledAligned(gui.font, formattedPower, 0.5f, RenderGravity.CENTER_LEFT, left + 82f, top + 3f, RGBAColor.YELLOW.toInt()) } } @@ -325,8 +325,8 @@ object MatteryGUI { if (ply.absorptionAmount > 0) formattedHealth = "%d+%d/%d".format(ply.health.toInt(), ply.absorptionAmount.toInt(), ply.maxHealth.toInt()) - event.guiGraphics.drawScaledAligned(minecraft.font, formattedHealth, 0.5f, TextAlign.CENTER_RIGHT, left - 4f, top + 4f, RGBAColor.BLACK.toInt()) - event.guiGraphics.drawScaledAligned(minecraft.font, formattedHealth, 0.5f, TextAlign.CENTER_RIGHT, left - 5f, top + 3f, getHealthColorForPlayer(ply)) + event.guiGraphics.drawScaledAligned(minecraft.font, formattedHealth, 0.5f, RenderGravity.CENTER_RIGHT, left - 4f, top + 4f, RGBAColor.BLACK.toInt()) + event.guiGraphics.drawScaledAligned(minecraft.font, formattedHealth, 0.5f, RenderGravity.CENTER_RIGHT, left - 5f, top + 3f, getHealthColorForPlayer(ply)) } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/AbstractMatterySprite.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/AbstractMatterySprite.kt index e82597258..3b331de9c 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/AbstractMatterySprite.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/AbstractMatterySprite.kt @@ -17,7 +17,7 @@ import ru.dbotthepony.mc.otm.core.math.RGBAColor import ru.dbotthepony.mc.otm.core.math.linearInterpolation import java.util.concurrent.ConcurrentHashMap -sealed class AbstractMatterySprite { +sealed class AbstractMatterySprite : IGUIRenderable { /** * Expected image width in pixels, used in calculations * and as default width argument in render methods @@ -76,7 +76,6 @@ sealed class AbstractMatterySprite { renderRaw(stack, x, y, width, height, winding) } - @JvmOverloads fun render( graphics: GuiGraphics, x: Float = 0f, @@ -88,6 +87,14 @@ sealed class AbstractMatterySprite { render(graphics.pose(), x, y, width, height, winding) } + override fun render(guiGraphics: GuiGraphics, x: Float, y: Float, width: Float, height: Float) { + return render(guiGraphics, x, y, width, height, winding) + } + + override fun render(guiGraphics: GuiGraphics, x: Float, y: Float, gravity: RenderGravity) { + return render(guiGraphics, gravity.x(x, width), gravity.y(y, height), width, height, winding) + } + @JvmOverloads fun render( stack: PoseStack, diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/Ext.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/Ext.kt index 4cc6ba666..fad69667b 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/Ext.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/Ext.kt @@ -20,7 +20,6 @@ import ru.dbotthepony.mc.otm.core.math.rotateAroundThis import ru.dbotthepony.mc.otm.core.math.times import ru.dbotthepony.mc.otm.core.math.translation import ru.dbotthepony.mc.otm.core.math.unaryMinus -import kotlin.math.roundToInt val tesselator: Tesselator get() = Tesselator.getInstance() @@ -63,20 +62,6 @@ fun PoseStack.translation(): Vector3f { inline val PoseStack.last: PoseStack.Pose get() = last() inline val PoseStack.Pose.pose: Matrix4f get() = pose() -enum class TextAlign { - TOP_LEFT, - TOP_CENTER, - TOP_RIGHT, - - CENTER_LEFT, - CENTER_CENTER, - CENTER_RIGHT, - - BOTTOM_LEFT, - BOTTOM_CENTER, - BOTTOM_RIGHT, -} - private fun Font.drawScaledDuckTyped(poseStack: PoseStack, text: Any, scale: Float, x: Float, y: Float, color: Int): Int { val translation = poseStack.translation() @@ -152,27 +137,15 @@ private fun Font.widthDuckTyped(text: Any): Int { } } -private fun Font.drawAlignedDuckTyped(poseStack: PoseStack, text: Any, align: TextAlign, x: Float, y: Float, color: Int): Int { - return when (align) { - TextAlign.TOP_LEFT -> drawDuckTyped(poseStack, text, x, y, color) - TextAlign.TOP_CENTER -> drawDuckTyped(poseStack, text, (x - widthDuckTyped(text) / 2f), y, color) - TextAlign.TOP_RIGHT -> drawDuckTyped(poseStack, text, (x - widthDuckTyped(text)), y, color) - - TextAlign.CENTER_LEFT -> drawDuckTyped(poseStack, text, x, (y - lineHeight / 2f), color) - TextAlign.CENTER_CENTER -> drawDuckTyped(poseStack, text, (x - widthDuckTyped(text) / 2f), (y - lineHeight / 2f), color) - TextAlign.CENTER_RIGHT -> drawDuckTyped(poseStack, text, (x - widthDuckTyped(text)), (y - lineHeight / 2f), color) - - TextAlign.BOTTOM_LEFT -> drawDuckTyped(poseStack, text, x, (y - lineHeight), color) - TextAlign.BOTTOM_CENTER -> drawDuckTyped(poseStack, text, (x - widthDuckTyped(text) / 2f), (y - lineHeight), color) - TextAlign.BOTTOM_RIGHT -> drawDuckTyped(poseStack, text, (x - widthDuckTyped(text)), (y - lineHeight), color) - } +private fun Font.drawAlignedDuckTyped(poseStack: PoseStack, text: Any, align: RenderGravity, x: Float, y: Float, color: Int): Int { + return drawDuckTyped(poseStack, text, align.x(x, widthDuckTyped(text)), align.y(y, lineHeight), color) } private fun Font.drawAlignedDuckTyped( poseStack: PoseStack, buffer: MultiBufferSource, text: Any, - align: TextAlign, + align: RenderGravity, x: Float, y: Float, color: Int, @@ -181,25 +154,13 @@ private fun Font.drawAlignedDuckTyped( packedLightCoords: Int = 15728880, effectColor: Int = 0 ): Int { - return when (align) { - TextAlign.TOP_LEFT -> drawDuckTyped(poseStack, buffer, text, x, y, color, drawShadow, displayMode, packedLightCoords, effectColor) - TextAlign.TOP_CENTER -> drawDuckTyped(poseStack, buffer, text, (x - widthDuckTyped(text) / 2f), y, color, drawShadow, displayMode, packedLightCoords, effectColor) - TextAlign.TOP_RIGHT -> drawDuckTyped(poseStack, buffer, text, (x - widthDuckTyped(text)), y, color, drawShadow, displayMode, packedLightCoords, effectColor) - - TextAlign.CENTER_LEFT -> drawDuckTyped(poseStack, buffer, text, x, (y - lineHeight / 2f), color, drawShadow, displayMode, packedLightCoords, effectColor) - TextAlign.CENTER_CENTER -> drawDuckTyped(poseStack, buffer, text, (x - widthDuckTyped(text) / 2f), (y - lineHeight / 2f), color, drawShadow, displayMode, packedLightCoords, effectColor) - TextAlign.CENTER_RIGHT -> drawDuckTyped(poseStack, buffer, text, (x - widthDuckTyped(text)), (y - lineHeight / 2f), color, drawShadow, displayMode, packedLightCoords, effectColor) - - TextAlign.BOTTOM_LEFT -> drawDuckTyped(poseStack, buffer, text, x, (y - lineHeight), color, drawShadow, displayMode, packedLightCoords, effectColor) - TextAlign.BOTTOM_CENTER -> drawDuckTyped(poseStack, buffer, text, (x - widthDuckTyped(text) / 2f), (y - lineHeight), color, drawShadow, displayMode, packedLightCoords, effectColor) - TextAlign.BOTTOM_RIGHT -> drawDuckTyped(poseStack, buffer, text, (x - widthDuckTyped(text)), (y - lineHeight), color, drawShadow, displayMode, packedLightCoords, effectColor) - } + return drawDuckTyped(poseStack, buffer, text, align.x(x, widthDuckTyped(text)), align.y(y, lineHeight), color, drawShadow, displayMode, packedLightCoords, effectColor) } private fun GuiGraphics.drawAlignedDuckTyped( font: Font, text: Any, - align: TextAlign, + align: RenderGravity, x: Float, y: Float, color: Int, @@ -208,39 +169,13 @@ private fun GuiGraphics.drawAlignedDuckTyped( packedLightCoords: Int = 15728880, effectColor: Int = 0 ): Int { - val width = when (align) { - TextAlign.TOP_LEFT -> font.drawDuckTyped(pose(), bufferSource(), text, x, y, color, drawShadow, displayMode, packedLightCoords, effectColor) - TextAlign.TOP_CENTER -> font.drawDuckTyped(pose(), bufferSource(), text, (x - font.widthDuckTyped(text) / 2f), y, color, drawShadow, displayMode, packedLightCoords, effectColor) - TextAlign.TOP_RIGHT -> font.drawDuckTyped(pose(), bufferSource(), text, (x - font.widthDuckTyped(text)), y, color, drawShadow, displayMode, packedLightCoords, effectColor) - - TextAlign.CENTER_LEFT -> font.drawDuckTyped(pose(), bufferSource(), text, x, (y - font.lineHeight / 2f), color, drawShadow, displayMode, packedLightCoords, effectColor) - TextAlign.CENTER_CENTER -> font.drawDuckTyped(pose(), bufferSource(), text, (x - font.widthDuckTyped(text) / 2f), (y - font.lineHeight / 2f), color, drawShadow, displayMode, packedLightCoords, effectColor) - TextAlign.CENTER_RIGHT -> font.drawDuckTyped(pose(), bufferSource(), text, (x - font.widthDuckTyped(text)), (y - font.lineHeight / 2f), color, drawShadow, displayMode, packedLightCoords, effectColor) - - TextAlign.BOTTOM_LEFT -> font.drawDuckTyped(pose(), bufferSource(), text, x, (y - font.lineHeight), color, drawShadow, displayMode, packedLightCoords, effectColor) - TextAlign.BOTTOM_CENTER -> font.drawDuckTyped(pose(), bufferSource(), text, (x - font.widthDuckTyped(text) / 2f), (y - font.lineHeight), color, drawShadow, displayMode, packedLightCoords, effectColor) - TextAlign.BOTTOM_RIGHT -> font.drawDuckTyped(pose(), bufferSource(), text, (x - font.widthDuckTyped(text)), (y - font.lineHeight), color, drawShadow, displayMode, packedLightCoords, effectColor) - } - + val width = font.drawDuckTyped(pose(), bufferSource(), text, align.x(x, font.widthDuckTyped(text)), align.y(y, font.lineHeight), color, drawShadow, displayMode, packedLightCoords, effectColor) flush() - return width } -private fun Font.drawScaledAlignedDuckTyped(poseStack: PoseStack, text: Any, scale: Float, align: TextAlign, x: Float, y: Float, color: Int): Int { - return when (align) { - TextAlign.TOP_LEFT -> drawScaledDuckTyped(poseStack, text, scale, x, y, color) - TextAlign.TOP_CENTER -> drawScaledDuckTyped(poseStack, text, scale, (x - widthDuckTyped(text) * scale / 2f), y, color) - TextAlign.TOP_RIGHT -> drawScaledDuckTyped(poseStack, text, scale, (x - widthDuckTyped(text) * scale), y, color) - - TextAlign.CENTER_LEFT -> drawScaledDuckTyped(poseStack, text, scale, x, (y - lineHeight / 2f * scale), color) - TextAlign.CENTER_CENTER -> drawScaledDuckTyped(poseStack, text, scale, (x - widthDuckTyped(text) * scale / 2f), (y - lineHeight * scale / 2f), color) - TextAlign.CENTER_RIGHT -> drawScaledDuckTyped(poseStack, text, scale, (x - widthDuckTyped(text) * scale), (y - lineHeight * scale / 2f), color) - - TextAlign.BOTTOM_LEFT -> drawScaledDuckTyped(poseStack, text, scale, x, (y - lineHeight * scale), color) - TextAlign.BOTTOM_CENTER -> drawScaledDuckTyped(poseStack, text, scale, (x - widthDuckTyped(text) * scale / 2f), (y - lineHeight * scale), color) - TextAlign.BOTTOM_RIGHT -> drawScaledDuckTyped(poseStack, text, scale, (x - widthDuckTyped(text) * scale), (y - lineHeight * scale), color) - } +private fun Font.drawScaledAlignedDuckTyped(poseStack: PoseStack, text: Any, scale: Float, align: RenderGravity, x: Float, y: Float, color: Int): Int { + return drawScaledDuckTyped(poseStack, text, scale, align.x(x, widthDuckTyped(text)), align.y(y, lineHeight * scale), color) } private fun Font.drawScaledAlignedDuckTyped( @@ -248,7 +183,7 @@ private fun Font.drawScaledAlignedDuckTyped( buffer: MultiBufferSource, text: Any, scale: Float, - align: TextAlign, + align: RenderGravity, x: Float, y: Float, color: Int, @@ -257,26 +192,14 @@ private fun Font.drawScaledAlignedDuckTyped( packedLightCoords: Int = 15728880, effectColor: Int = 0 ): Int { - return when (align) { - TextAlign.TOP_LEFT -> drawScaledDuckTyped(poseStack, buffer, text, scale, x, y, color, drawShadow, displayMode, packedLightCoords, effectColor) - TextAlign.TOP_CENTER -> drawScaledDuckTyped(poseStack, buffer, text, scale, (x - widthDuckTyped(text) * scale / 2f), y, color, drawShadow, displayMode, packedLightCoords, effectColor) - TextAlign.TOP_RIGHT -> drawScaledDuckTyped(poseStack, buffer, text, scale, (x - widthDuckTyped(text) * scale), y, color, drawShadow, displayMode, packedLightCoords, effectColor) - - TextAlign.CENTER_LEFT -> drawScaledDuckTyped(poseStack, buffer, text, scale, x, (y - lineHeight / 2f * scale), color, drawShadow, displayMode, packedLightCoords, effectColor) - TextAlign.CENTER_CENTER -> drawScaledDuckTyped(poseStack, buffer, text, scale, (x - widthDuckTyped(text) * scale / 2f), (y - lineHeight * scale / 2f), color, drawShadow, displayMode, packedLightCoords, effectColor) - TextAlign.CENTER_RIGHT -> drawScaledDuckTyped(poseStack, buffer, text, scale, (x - widthDuckTyped(text) * scale), (y - lineHeight * scale / 2f), color, drawShadow, displayMode, packedLightCoords, effectColor) - - TextAlign.BOTTOM_LEFT -> drawScaledDuckTyped(poseStack, buffer, text, scale, x, (y - lineHeight * scale), color, drawShadow, displayMode, packedLightCoords, effectColor) - TextAlign.BOTTOM_CENTER -> drawScaledDuckTyped(poseStack, buffer, text, scale, (x - widthDuckTyped(text) * scale / 2f), (y - lineHeight * scale), color, drawShadow, displayMode, packedLightCoords, effectColor) - TextAlign.BOTTOM_RIGHT -> drawScaledDuckTyped(poseStack, buffer, text, scale, (x - widthDuckTyped(text) * scale), (y - lineHeight * scale), color, drawShadow, displayMode, packedLightCoords, effectColor) - } + return drawScaledDuckTyped(poseStack, buffer, text, scale, align.x(x, widthDuckTyped(text) * scale), align.y(y, lineHeight * scale), color, drawShadow, displayMode, packedLightCoords, effectColor) } private fun GuiGraphics.drawScaledAlignedDuckTyped( font: Font, text: Any, scale: Float, - align: TextAlign, + align: RenderGravity, x: Float, y: Float, color: Int, @@ -285,69 +208,55 @@ private fun GuiGraphics.drawScaledAlignedDuckTyped( packedLightCoords: Int = 15728880, effectColor: Int = 0 ): Int { - val width = when (align) { - TextAlign.TOP_LEFT -> font.drawScaledDuckTyped(pose(), bufferSource(), text, scale, x, y, color, drawShadow, displayMode, packedLightCoords, effectColor) - TextAlign.TOP_CENTER -> font.drawScaledDuckTyped(pose(), bufferSource(), text, scale, (x - font.widthDuckTyped(text) * scale / 2f), y, color, drawShadow, displayMode, packedLightCoords, effectColor) - TextAlign.TOP_RIGHT -> font.drawScaledDuckTyped(pose(), bufferSource(), text, scale, (x - font.widthDuckTyped(text) * scale), y, color, drawShadow, displayMode, packedLightCoords, effectColor) - - TextAlign.CENTER_LEFT -> font.drawScaledDuckTyped(pose(), bufferSource(), text, scale, x, (y - font.lineHeight / 2f * scale), color, drawShadow, displayMode, packedLightCoords, effectColor) - TextAlign.CENTER_CENTER -> font.drawScaledDuckTyped(pose(), bufferSource(), text, scale, (x - font.widthDuckTyped(text) * scale / 2f), (y - font.lineHeight * scale / 2f), color, drawShadow, displayMode, packedLightCoords, effectColor) - TextAlign.CENTER_RIGHT -> font.drawScaledDuckTyped(pose(), bufferSource(), text, scale, (x - font.widthDuckTyped(text) * scale), (y - font.lineHeight * scale / 2f), color, drawShadow, displayMode, packedLightCoords, effectColor) - - TextAlign.BOTTOM_LEFT -> font.drawScaledDuckTyped(pose(), bufferSource(), text, scale, x, (y - font.lineHeight * scale), color, drawShadow, displayMode, packedLightCoords, effectColor) - TextAlign.BOTTOM_CENTER -> font.drawScaledDuckTyped(pose(), bufferSource(), text, scale, (x - font.widthDuckTyped(text) * scale / 2f), (y - font.lineHeight * scale), color, drawShadow, displayMode, packedLightCoords, effectColor) - TextAlign.BOTTOM_RIGHT -> font.drawScaledDuckTyped(pose(), bufferSource(), text, scale, (x - font.widthDuckTyped(text) * scale), (y - font.lineHeight * scale), color, drawShadow, displayMode, packedLightCoords, effectColor) - } - + val width = font.drawScaledDuckTyped(pose(), bufferSource(), text, scale, align.x(x, font.widthDuckTyped(text) * scale), align.y(y, font.lineHeight * scale), color, drawShadow, displayMode, packedLightCoords, effectColor) flush() - return width } -fun Font.drawAligned(poseStack: PoseStack, text: String, align: TextAlign, x: Float, y: Float, color: Int) = drawAlignedDuckTyped(poseStack, text, align, x, y, color) -fun Font.drawAligned(poseStack: PoseStack, text: Component, align: TextAlign, x: Float, y: Float, color: Int) = drawAlignedDuckTyped(poseStack, text, align, x, y, color) -fun Font.drawAligned(poseStack: PoseStack, text: FormattedCharSequence, align: TextAlign, x: Float, y: Float, color: Int) = drawAlignedDuckTyped(poseStack, text, align, x, y, color) +fun Font.drawAligned(poseStack: PoseStack, text: String, align: RenderGravity, x: Float, y: Float, color: Int) = drawAlignedDuckTyped(poseStack, text, align, x, y, color) +fun Font.drawAligned(poseStack: PoseStack, text: Component, align: RenderGravity, x: Float, y: Float, color: Int) = drawAlignedDuckTyped(poseStack, text, align, x, y, color) +fun Font.drawAligned(poseStack: PoseStack, text: FormattedCharSequence, align: RenderGravity, x: Float, y: Float, color: Int) = drawAlignedDuckTyped(poseStack, text, align, x, y, color) -fun Font.drawAligned(poseStack: PoseStack, text: String, align: TextAlign, x: Float, y: Float, color: RGBAColor) = drawAligned(poseStack, text, align, x, y, color.toInt()) -fun Font.drawAligned(poseStack: PoseStack, text: Component, align: TextAlign, x: Float, y: Float, color: RGBAColor) = drawAligned(poseStack, text, align, x, y, color.toInt()) -fun Font.drawAligned(poseStack: PoseStack, text: FormattedCharSequence, align: TextAlign, x: Float, y: Float, color: RGBAColor) = drawAligned(poseStack, text, align, x, y, color.toInt()) +fun Font.drawAligned(poseStack: PoseStack, text: String, align: RenderGravity, x: Float, y: Float, color: RGBAColor) = drawAligned(poseStack, text, align, x, y, color.toInt()) +fun Font.drawAligned(poseStack: PoseStack, text: Component, align: RenderGravity, x: Float, y: Float, color: RGBAColor) = drawAligned(poseStack, text, align, x, y, color.toInt()) +fun Font.drawAligned(poseStack: PoseStack, text: FormattedCharSequence, align: RenderGravity, x: Float, y: Float, color: RGBAColor) = drawAligned(poseStack, text, align, x, y, color.toInt()) -fun Font.drawScaledAligned(poseStack: PoseStack, text: String, scale: Float, align: TextAlign, x: Float, y: Float, color: Int) = drawScaledAlignedDuckTyped(poseStack, text, scale, align, x, y, color) -fun Font.drawScaledAligned(poseStack: PoseStack, text: Component, scale: Float, align: TextAlign, x: Float, y: Float, color: Int) = drawScaledAlignedDuckTyped(poseStack, text, scale, align, x, y, color) -fun Font.drawScaledAligned(poseStack: PoseStack, text: FormattedCharSequence, scale: Float, align: TextAlign, x: Float, y: Float, color: Int) = drawScaledAlignedDuckTyped(poseStack, text, scale, align, x, y, color) +fun Font.drawScaledAligned(poseStack: PoseStack, text: String, scale: Float, align: RenderGravity, x: Float, y: Float, color: Int) = drawScaledAlignedDuckTyped(poseStack, text, scale, align, x, y, color) +fun Font.drawScaledAligned(poseStack: PoseStack, text: Component, scale: Float, align: RenderGravity, x: Float, y: Float, color: Int) = drawScaledAlignedDuckTyped(poseStack, text, scale, align, x, y, color) +fun Font.drawScaledAligned(poseStack: PoseStack, text: FormattedCharSequence, scale: Float, align: RenderGravity, x: Float, y: Float, color: Int) = drawScaledAlignedDuckTyped(poseStack, text, scale, align, x, y, color) -fun Font.drawScaledAligned(poseStack: PoseStack, text: String, scale: Float, align: TextAlign, x: Float, y: Float, color: RGBAColor) = drawScaledAligned(poseStack, text, scale, align, x, y, color.toInt()) -fun Font.drawScaledAligned(poseStack: PoseStack, text: Component, scale: Float, align: TextAlign, x: Float, y: Float, color: RGBAColor) = drawScaledAligned(poseStack, text, scale, align, x, y, color.toInt()) -fun Font.drawScaledAligned(poseStack: PoseStack, text: FormattedCharSequence, scale: Float, align: TextAlign, x: Float, y: Float, color: RGBAColor) = drawScaledAligned(poseStack, text, scale, align, x, y, color.toInt()) +fun Font.drawScaledAligned(poseStack: PoseStack, text: String, scale: Float, align: RenderGravity, x: Float, y: Float, color: RGBAColor) = drawScaledAligned(poseStack, text, scale, align, x, y, color.toInt()) +fun Font.drawScaledAligned(poseStack: PoseStack, text: Component, scale: Float, align: RenderGravity, x: Float, y: Float, color: RGBAColor) = drawScaledAligned(poseStack, text, scale, align, x, y, color.toInt()) +fun Font.drawScaledAligned(poseStack: PoseStack, text: FormattedCharSequence, scale: Float, align: RenderGravity, x: Float, y: Float, color: RGBAColor) = drawScaledAligned(poseStack, text, scale, align, x, y, color.toInt()) -fun Font.drawAligned(poseStack: PoseStack, buffer: MultiBufferSource, text: String, align: TextAlign, x: Float, y: Float, color: Int, drawShadow: Boolean = false, displayMode: Font.DisplayMode = Font.DisplayMode.NORMAL, packedLightCoords: Int = 15728880, effectColor: Int = 0) = drawAlignedDuckTyped(poseStack, buffer, text, align, x, y, color, drawShadow, displayMode, packedLightCoords, effectColor) -fun Font.drawAligned(poseStack: PoseStack, buffer: MultiBufferSource, text: Component, align: TextAlign, x: Float, y: Float, color: Int, drawShadow: Boolean = false, displayMode: Font.DisplayMode = Font.DisplayMode.NORMAL, packedLightCoords: Int = 15728880, effectColor: Int = 0) = drawAlignedDuckTyped(poseStack, buffer, text, align, x, y, color, drawShadow, displayMode, packedLightCoords, effectColor) -fun Font.drawAligned(poseStack: PoseStack, buffer: MultiBufferSource, text: FormattedCharSequence, align: TextAlign, x: Float, y: Float, color: Int, drawShadow: Boolean = false, displayMode: Font.DisplayMode = Font.DisplayMode.NORMAL, packedLightCoords: Int = 15728880, effectColor: Int = 0) = drawAlignedDuckTyped(poseStack, buffer, text, align, x, y, color, drawShadow, displayMode, packedLightCoords, effectColor) +fun Font.drawAligned(poseStack: PoseStack, buffer: MultiBufferSource, text: String, align: RenderGravity, x: Float, y: Float, color: Int, drawShadow: Boolean = false, displayMode: Font.DisplayMode = Font.DisplayMode.NORMAL, packedLightCoords: Int = 15728880, effectColor: Int = 0) = drawAlignedDuckTyped(poseStack, buffer, text, align, x, y, color, drawShadow, displayMode, packedLightCoords, effectColor) +fun Font.drawAligned(poseStack: PoseStack, buffer: MultiBufferSource, text: Component, align: RenderGravity, x: Float, y: Float, color: Int, drawShadow: Boolean = false, displayMode: Font.DisplayMode = Font.DisplayMode.NORMAL, packedLightCoords: Int = 15728880, effectColor: Int = 0) = drawAlignedDuckTyped(poseStack, buffer, text, align, x, y, color, drawShadow, displayMode, packedLightCoords, effectColor) +fun Font.drawAligned(poseStack: PoseStack, buffer: MultiBufferSource, text: FormattedCharSequence, align: RenderGravity, x: Float, y: Float, color: Int, drawShadow: Boolean = false, displayMode: Font.DisplayMode = Font.DisplayMode.NORMAL, packedLightCoords: Int = 15728880, effectColor: Int = 0) = drawAlignedDuckTyped(poseStack, buffer, text, align, x, y, color, drawShadow, displayMode, packedLightCoords, effectColor) -fun Font.drawAligned(poseStack: PoseStack, buffer: MultiBufferSource, text: String, align: TextAlign, x: Float, y: Float, color: RGBAColor, drawShadow: Boolean = false, displayMode: Font.DisplayMode = Font.DisplayMode.NORMAL, packedLightCoords: Int = 15728880, effectColor: Int = 0) = drawAligned(poseStack, buffer, text, align, x, y, color.toInt(), drawShadow, displayMode, packedLightCoords, effectColor) -fun Font.drawAligned(poseStack: PoseStack, buffer: MultiBufferSource, text: Component, align: TextAlign, x: Float, y: Float, color: RGBAColor, drawShadow: Boolean = false, displayMode: Font.DisplayMode = Font.DisplayMode.NORMAL, packedLightCoords: Int = 15728880, effectColor: Int = 0) = drawAligned(poseStack, buffer, text, align, x, y, color.toInt(), drawShadow, displayMode, packedLightCoords, effectColor) -fun Font.drawAligned(poseStack: PoseStack, buffer: MultiBufferSource, text: FormattedCharSequence, align: TextAlign, x: Float, y: Float, color: RGBAColor, drawShadow: Boolean = false, displayMode: Font.DisplayMode = Font.DisplayMode.NORMAL, packedLightCoords: Int = 15728880, effectColor: Int = 0) = drawAligned(poseStack, buffer, text, align, x, y, color.toInt(), drawShadow, displayMode, packedLightCoords, effectColor) +fun Font.drawAligned(poseStack: PoseStack, buffer: MultiBufferSource, text: String, align: RenderGravity, x: Float, y: Float, color: RGBAColor, drawShadow: Boolean = false, displayMode: Font.DisplayMode = Font.DisplayMode.NORMAL, packedLightCoords: Int = 15728880, effectColor: Int = 0) = drawAligned(poseStack, buffer, text, align, x, y, color.toInt(), drawShadow, displayMode, packedLightCoords, effectColor) +fun Font.drawAligned(poseStack: PoseStack, buffer: MultiBufferSource, text: Component, align: RenderGravity, x: Float, y: Float, color: RGBAColor, drawShadow: Boolean = false, displayMode: Font.DisplayMode = Font.DisplayMode.NORMAL, packedLightCoords: Int = 15728880, effectColor: Int = 0) = drawAligned(poseStack, buffer, text, align, x, y, color.toInt(), drawShadow, displayMode, packedLightCoords, effectColor) +fun Font.drawAligned(poseStack: PoseStack, buffer: MultiBufferSource, text: FormattedCharSequence, align: RenderGravity, x: Float, y: Float, color: RGBAColor, drawShadow: Boolean = false, displayMode: Font.DisplayMode = Font.DisplayMode.NORMAL, packedLightCoords: Int = 15728880, effectColor: Int = 0) = drawAligned(poseStack, buffer, text, align, x, y, color.toInt(), drawShadow, displayMode, packedLightCoords, effectColor) -fun Font.drawScaledAligned(poseStack: PoseStack, buffer: MultiBufferSource, text: String, scale: Float, align: TextAlign, x: Float, y: Float, color: Int, drawShadow: Boolean = false, displayMode: Font.DisplayMode = Font.DisplayMode.NORMAL, packedLightCoords: Int = 15728880, effectColor: Int = 0,) = drawScaledAlignedDuckTyped(poseStack, buffer, text, scale, align, x, y, color, drawShadow, displayMode, packedLightCoords, effectColor) -fun Font.drawScaledAligned(poseStack: PoseStack, buffer: MultiBufferSource, text: Component, scale: Float, align: TextAlign, x: Float, y: Float, color: Int, drawShadow: Boolean = false, displayMode: Font.DisplayMode = Font.DisplayMode.NORMAL, packedLightCoords: Int = 15728880, effectColor: Int = 0,) = drawScaledAlignedDuckTyped(poseStack, buffer, text, scale, align, x, y, color, drawShadow, displayMode, packedLightCoords, effectColor) -fun Font.drawScaledAligned(poseStack: PoseStack, buffer: MultiBufferSource, text: FormattedCharSequence, scale: Float, align: TextAlign, x: Float, y: Float, color: Int, drawShadow: Boolean = false, displayMode: Font.DisplayMode = Font.DisplayMode.NORMAL, packedLightCoords: Int = 15728880, effectColor: Int = 0,) = drawScaledAlignedDuckTyped(poseStack, buffer, text, scale, align, x, y, color, drawShadow, displayMode, packedLightCoords, effectColor) +fun Font.drawScaledAligned(poseStack: PoseStack, buffer: MultiBufferSource, text: String, scale: Float, align: RenderGravity, x: Float, y: Float, color: Int, drawShadow: Boolean = false, displayMode: Font.DisplayMode = Font.DisplayMode.NORMAL, packedLightCoords: Int = 15728880, effectColor: Int = 0,) = drawScaledAlignedDuckTyped(poseStack, buffer, text, scale, align, x, y, color, drawShadow, displayMode, packedLightCoords, effectColor) +fun Font.drawScaledAligned(poseStack: PoseStack, buffer: MultiBufferSource, text: Component, scale: Float, align: RenderGravity, x: Float, y: Float, color: Int, drawShadow: Boolean = false, displayMode: Font.DisplayMode = Font.DisplayMode.NORMAL, packedLightCoords: Int = 15728880, effectColor: Int = 0,) = drawScaledAlignedDuckTyped(poseStack, buffer, text, scale, align, x, y, color, drawShadow, displayMode, packedLightCoords, effectColor) +fun Font.drawScaledAligned(poseStack: PoseStack, buffer: MultiBufferSource, text: FormattedCharSequence, scale: Float, align: RenderGravity, x: Float, y: Float, color: Int, drawShadow: Boolean = false, displayMode: Font.DisplayMode = Font.DisplayMode.NORMAL, packedLightCoords: Int = 15728880, effectColor: Int = 0,) = drawScaledAlignedDuckTyped(poseStack, buffer, text, scale, align, x, y, color, drawShadow, displayMode, packedLightCoords, effectColor) -fun Font.drawScaledAligned(poseStack: PoseStack, buffer: MultiBufferSource, text: String, scale: Float, align: TextAlign, x: Float, y: Float, drawShadow: Boolean = false, displayMode: Font.DisplayMode = Font.DisplayMode.NORMAL, packedLightCoords: Int = 15728880, effectColor: Int = 0, color: RGBAColor) = drawScaledAligned(poseStack, buffer, text, scale, align, x, y, color.toInt(), drawShadow, displayMode, packedLightCoords, effectColor) -fun Font.drawScaledAligned(poseStack: PoseStack, buffer: MultiBufferSource, text: Component, scale: Float, align: TextAlign, x: Float, y: Float, drawShadow: Boolean = false, displayMode: Font.DisplayMode = Font.DisplayMode.NORMAL, packedLightCoords: Int = 15728880, effectColor: Int = 0, color: RGBAColor) = drawScaledAligned(poseStack, buffer, text, scale, align, x, y, color.toInt(), drawShadow, displayMode, packedLightCoords, effectColor) -fun Font.drawScaledAligned(poseStack: PoseStack, buffer: MultiBufferSource, text: FormattedCharSequence, scale: Float, align: TextAlign, x: Float, y: Float, drawShadow: Boolean = false, displayMode: Font.DisplayMode = Font.DisplayMode.NORMAL, packedLightCoords: Int = 15728880, effectColor: Int = 0, color: RGBAColor) = drawScaledAligned(poseStack, buffer, text, scale, align, x, y, color.toInt(), drawShadow, displayMode, packedLightCoords, effectColor) +fun Font.drawScaledAligned(poseStack: PoseStack, buffer: MultiBufferSource, text: String, scale: Float, align: RenderGravity, x: Float, y: Float, drawShadow: Boolean = false, displayMode: Font.DisplayMode = Font.DisplayMode.NORMAL, packedLightCoords: Int = 15728880, effectColor: Int = 0, color: RGBAColor) = drawScaledAligned(poseStack, buffer, text, scale, align, x, y, color.toInt(), drawShadow, displayMode, packedLightCoords, effectColor) +fun Font.drawScaledAligned(poseStack: PoseStack, buffer: MultiBufferSource, text: Component, scale: Float, align: RenderGravity, x: Float, y: Float, drawShadow: Boolean = false, displayMode: Font.DisplayMode = Font.DisplayMode.NORMAL, packedLightCoords: Int = 15728880, effectColor: Int = 0, color: RGBAColor) = drawScaledAligned(poseStack, buffer, text, scale, align, x, y, color.toInt(), drawShadow, displayMode, packedLightCoords, effectColor) +fun Font.drawScaledAligned(poseStack: PoseStack, buffer: MultiBufferSource, text: FormattedCharSequence, scale: Float, align: RenderGravity, x: Float, y: Float, drawShadow: Boolean = false, displayMode: Font.DisplayMode = Font.DisplayMode.NORMAL, packedLightCoords: Int = 15728880, effectColor: Int = 0, color: RGBAColor) = drawScaledAligned(poseStack, buffer, text, scale, align, x, y, color.toInt(), drawShadow, displayMode, packedLightCoords, effectColor) -fun GuiGraphics.drawAligned(font: Font, text: String, align: TextAlign, x: Float, y: Float, color: Int) = drawAlignedDuckTyped(font, text, align, x, y, color) -fun GuiGraphics.drawAligned(font: Font, text: Component, align: TextAlign, x: Float, y: Float, color: Int) = drawAlignedDuckTyped(font, text, align, x, y, color) -fun GuiGraphics.drawAligned(font: Font, text: FormattedCharSequence, align: TextAlign, x: Float, y: Float, color: Int) = drawAlignedDuckTyped(font, text, align, x, y, color) +fun GuiGraphics.drawAligned(font: Font, text: String, align: RenderGravity, x: Float, y: Float, color: Int) = drawAlignedDuckTyped(font, text, align, x, y, color) +fun GuiGraphics.drawAligned(font: Font, text: Component, align: RenderGravity, x: Float, y: Float, color: Int) = drawAlignedDuckTyped(font, text, align, x, y, color) +fun GuiGraphics.drawAligned(font: Font, text: FormattedCharSequence, align: RenderGravity, x: Float, y: Float, color: Int) = drawAlignedDuckTyped(font, text, align, x, y, color) -fun GuiGraphics.drawAligned(font: Font, text: String, align: TextAlign, x: Float, y: Float, color: RGBAColor) = drawAligned(font, text, align, x, y, color.toInt()) -fun GuiGraphics.drawAligned(font: Font, text: Component, align: TextAlign, x: Float, y: Float, color: RGBAColor) = drawAligned(font, text, align, x, y, color.toInt()) -fun GuiGraphics.drawAligned(font: Font, text: FormattedCharSequence, align: TextAlign, x: Float, y: Float, color: RGBAColor) = drawAligned(font, text, align, x, y, color.toInt()) +fun GuiGraphics.drawAligned(font: Font, text: String, align: RenderGravity, x: Float, y: Float, color: RGBAColor) = drawAligned(font, text, align, x, y, color.toInt()) +fun GuiGraphics.drawAligned(font: Font, text: Component, align: RenderGravity, x: Float, y: Float, color: RGBAColor) = drawAligned(font, text, align, x, y, color.toInt()) +fun GuiGraphics.drawAligned(font: Font, text: FormattedCharSequence, align: RenderGravity, x: Float, y: Float, color: RGBAColor) = drawAligned(font, text, align, x, y, color.toInt()) -fun GuiGraphics.drawScaledAligned(font: Font, text: String, scale: Float, align: TextAlign, x: Float, y: Float, color: Int) = drawScaledAlignedDuckTyped(font, text, scale, align, x, y, color) -fun GuiGraphics.drawScaledAligned(font: Font, text: Component, scale: Float, align: TextAlign, x: Float, y: Float, color: Int) = drawScaledAlignedDuckTyped(font, text, scale, align, x, y, color) -fun GuiGraphics.drawScaledAligned(font: Font, text: FormattedCharSequence, scale: Float, align: TextAlign, x: Float, y: Float, color: Int) = drawScaledAlignedDuckTyped(font, text, scale, align, x, y, color) +fun GuiGraphics.drawScaledAligned(font: Font, text: String, scale: Float, align: RenderGravity, x: Float, y: Float, color: Int) = drawScaledAlignedDuckTyped(font, text, scale, align, x, y, color) +fun GuiGraphics.drawScaledAligned(font: Font, text: Component, scale: Float, align: RenderGravity, x: Float, y: Float, color: Int) = drawScaledAlignedDuckTyped(font, text, scale, align, x, y, color) +fun GuiGraphics.drawScaledAligned(font: Font, text: FormattedCharSequence, scale: Float, align: RenderGravity, x: Float, y: Float, color: Int) = drawScaledAlignedDuckTyped(font, text, scale, align, x, y, color) -fun GuiGraphics.drawScaledAligned(font: Font, text: String, scale: Float, align: TextAlign, x: Float, y: Float, color: RGBAColor) = drawScaledAligned(font, text, scale, align, x, y, color.toInt()) -fun GuiGraphics.drawScaledAligned(font: Font, text: Component, scale: Float, align: TextAlign, x: Float, y: Float, color: RGBAColor) = drawScaledAligned(font, text, scale, align, x, y, color.toInt()) -fun GuiGraphics.drawScaledAligned(font: Font, text: FormattedCharSequence, scale: Float, align: TextAlign, x: Float, y: Float, color: RGBAColor) = drawScaledAligned(font, text, scale, align, x, y, color.toInt()) +fun GuiGraphics.drawScaledAligned(font: Font, text: String, scale: Float, align: RenderGravity, x: Float, y: Float, color: RGBAColor) = drawScaledAligned(font, text, scale, align, x, y, color.toInt()) +fun GuiGraphics.drawScaledAligned(font: Font, text: Component, scale: Float, align: RenderGravity, x: Float, y: Float, color: RGBAColor) = drawScaledAligned(font, text, scale, align, x, y, color.toInt()) +fun GuiGraphics.drawScaledAligned(font: Font, text: FormattedCharSequence, scale: Float, align: RenderGravity, x: Float, y: Float, color: RGBAColor) = drawScaledAligned(font, text, scale, align, x, y, color.toInt()) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/IGUIRenderable.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/IGUIRenderable.kt new file mode 100644 index 000000000..716d9a1c2 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/IGUIRenderable.kt @@ -0,0 +1,64 @@ +package ru.dbotthepony.mc.otm.client.render + +import net.minecraft.client.gui.GuiGraphics +import net.minecraft.world.item.ItemStack + +interface IGUIRenderable { + fun render(guiGraphics: GuiGraphics, x: Float, y: Float, gravity: RenderGravity = RenderGravity.TOP_LEFT) + + /** + * Render at specified [x], [y] with fixed [width] x [height] + */ + fun render(guiGraphics: GuiGraphics, x: Float, y: Float, width: Float, height: Float) + + fun composeBefore(other: IGUIRenderable): IGUIRenderable { + return object : IGUIRenderable { + override fun render(guiGraphics: GuiGraphics, x: Float, y: Float, gravity: RenderGravity) { + this@IGUIRenderable.render(guiGraphics, x, y, gravity) + other.render(guiGraphics, x, y, gravity) + } + + override fun render(guiGraphics: GuiGraphics, x: Float, y: Float, width: Float, height: Float) { + this@IGUIRenderable.render(guiGraphics, x, y, width, height) + other.render(guiGraphics, x, y, width, height) + } + } + } + + fun composeAfter(other: IGUIRenderable): IGUIRenderable { + return other.composeBefore(this) + } + + companion object { + fun of(value: ItemStack, width: Float = 16f, height: Float = 16f): IGUIRenderable { + return ItemStackIcon(value, width, height) + } + + fun of(value: IGUIRenderable): IGUIRenderable { + return value + } + } +} + +data class ItemStackIcon(private val itemStack: ItemStack, val width: Float = 16f, val height: Float = 16f) : IGUIRenderable { + override fun render(guiGraphics: GuiGraphics, x: Float, y: Float, gravity: RenderGravity) { + return render(guiGraphics, gravity.x(x, width), gravity.y(y, height), width, height) + } + + override fun render(guiGraphics: GuiGraphics, x: Float, y: Float, width: Float, height: Float) { + if (x % 1f == 0f && y % 1f == 0f && width == 16f && height == 16f) { + guiGraphics.renderFakeItem(itemStack, x.toInt(), y.toInt()) + } else { + val pose = guiGraphics.pose() + + pose.pushPose() + pose.translate(x % 1f, y % 1f, 0f) + + if (width != 16f || height != 16f) + pose.scale(width / 16f, height / 16f, 1f) + + guiGraphics.renderFakeItem(itemStack, x.toInt(), y.toInt()) + pose.popPose() + } + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/RenderGravity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/RenderGravity.kt new file mode 100644 index 000000000..e3fbf8d71 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/RenderGravity.kt @@ -0,0 +1,184 @@ +package ru.dbotthepony.mc.otm.client.render + +import ru.dbotthepony.mc.otm.core.FloatSupplier +import kotlin.math.roundToInt + +private operator fun FloatSupplier.div(other: Float): Float { + return getAsFloat() / other +} + +private operator fun Float.minus(other: FloatSupplier): Float { + return this - other.getAsFloat() +} + +enum class RenderGravity { + TOP_LEFT { + override fun x(x: Float, width: FloatSupplier): Float { + return x + } + + override fun y(y: Float, height: FloatSupplier): Float { + return y + } + + override fun x(x: Float, width: Float): Float { + return x + } + + override fun y(y: Float, height: Float): Float { + return y + } + }, + TOP_CENTER { + override fun x(x: Float, width: FloatSupplier): Float { + return x - width / 2f + } + + override fun y(y: Float, height: FloatSupplier): Float { + return y + } + + override fun x(x: Float, width: Float): Float { + return x - width / 2f + } + + override fun y(y: Float, height: Float): Float { + return y + } + }, + TOP_RIGHT { + override fun x(x: Float, width: FloatSupplier): Float { + return x - width + } + + override fun y(y: Float, height: FloatSupplier): Float { + return y + } + + override fun x(x: Float, width: Float): Float { + return x - width + } + + override fun y(y: Float, height: Float): Float { + return y + } + }, + + CENTER_LEFT { + override fun x(x: Float, width: FloatSupplier): Float { + return x + } + + override fun y(y: Float, height: FloatSupplier): Float { + return y - height / 2f + } + + override fun x(x: Float, width: Float): Float { + return x + } + + override fun y(y: Float, height: Float): Float { + return y - height / 2f + } + }, + CENTER_CENTER { + override fun x(x: Float, width: FloatSupplier): Float { + return x - width / 2f + } + + override fun y(y: Float, height: FloatSupplier): Float { + return y - height / 2f + } + + override fun x(x: Float, width: Float): Float { + return x - width / 2f + } + + override fun y(y: Float, height: Float): Float { + return y - height / 2f + } + }, + CENTER_RIGHT { + override fun x(x: Float, width: FloatSupplier): Float { + return x - width + } + + override fun y(y: Float, height: FloatSupplier): Float { + return y - height / 2f + } + + override fun x(x: Float, width: Float): Float { + return x - width + } + + override fun y(y: Float, height: Float): Float { + return y - height / 2f + } + }, + + BOTTOM_LEFT { + override fun x(x: Float, width: FloatSupplier): Float { + return x + } + + override fun y(y: Float, height: FloatSupplier): Float { + return y - height + } + + override fun x(x: Float, width: Float): Float { + return x + } + + override fun y(y: Float, height: Float): Float { + return y - height + } + }, + BOTTOM_CENTER { + override fun x(x: Float, width: FloatSupplier): Float { + return x - width / 2f + } + + override fun y(y: Float, height: FloatSupplier): Float { + return y - height + } + + override fun x(x: Float, width: Float): Float { + return x - width / 2f + } + + override fun y(y: Float, height: Float): Float { + return y - height + } + }, + BOTTOM_RIGHT { + override fun x(x: Float, width: FloatSupplier): Float { + return x - width + } + + override fun y(y: Float, height: FloatSupplier): Float { + return y - height + } + + override fun x(x: Float, width: Float): Float { + return x - width + } + + override fun y(y: Float, height: Float): Float { + return y - height + } + }; + + abstract fun x(x: Float, width: FloatSupplier): Float + abstract fun y(y: Float, height: FloatSupplier): Float + + abstract fun x(x: Float, width: Float): Float + abstract fun y(y: Float, height: Float): Float + + fun x(x: Float, width: Int): Float { + return x(x, width.toFloat()).roundToInt().toFloat() + } + + fun y(y: Float, height: Int): Float { + return y(y, height.toFloat()).roundToInt().toFloat() + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/blockentity/BlackHoleRenderer.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/blockentity/BlackHoleRenderer.kt index 09da620e7..a5ad2be22 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/blockentity/BlackHoleRenderer.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/blockentity/BlackHoleRenderer.kt @@ -185,11 +185,11 @@ class BlackHoleRenderer(private val context: BlockEntityRendererProvider.Context val sorse = DynamicBufferSource.WORLD - font.drawAligned(poseStack, sorse, text1, TextAlign.TOP_LEFT, 0.8f, 0.8f - font.lineHeight.toFloat() / 2f, 0x0) - font.drawAligned(poseStack, sorse, text2, TextAlign.TOP_LEFT, 0.8f, 0.8f + font.lineHeight.toFloat() / 2f, 0x0) + font.drawAligned(poseStack, sorse, text1, RenderGravity.TOP_LEFT, 0.8f, 0.8f - font.lineHeight.toFloat() / 2f, 0x0) + font.drawAligned(poseStack, sorse, text2, RenderGravity.TOP_LEFT, 0.8f, 0.8f + font.lineHeight.toFloat() / 2f, 0x0) poseStack.translate(0.0, 0.0, -1.0) - font.drawAligned(poseStack, sorse, text1, TextAlign.TOP_LEFT, 0f, -font.lineHeight.toFloat() / 2f, 0xFFFFFF) - font.drawAligned(poseStack, sorse, text2, TextAlign.TOP_LEFT, 0f, font.lineHeight.toFloat() / 2f, 0xFFFFFF) + font.drawAligned(poseStack, sorse, text1, RenderGravity.TOP_LEFT, 0f, -font.lineHeight.toFloat() / 2f, 0xFFFFFF) + font.drawAligned(poseStack, sorse, text2, RenderGravity.TOP_LEFT, 0f, font.lineHeight.toFloat() / 2f, 0xFFFFFF) poseStack.popPose() } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/blockentity/EnergyCounterRenderer.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/blockentity/EnergyCounterRenderer.kt index fccd11b5c..378c3c998 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/blockentity/EnergyCounterRenderer.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/blockentity/EnergyCounterRenderer.kt @@ -48,21 +48,21 @@ class EnergyCounterRenderer(private val context: BlockEntityRendererProvider.Con var y = -16f - val finalX = font.drawAligned(poseStack, sorse, "00000000", TextAlign.CENTER_CENTER, -4f, y, RGBAColor.GRAY) - font.drawAligned(poseStack, sorse, "00000000", TextAlign.CENTER_CENTER, -4f, y + font.lineHeight, RGBAColor.GRAY) - font.drawAligned(poseStack, sorse, "/t", TextAlign.CENTER_LEFT, finalX.toFloat(), y, RGBAColor.GRAY) - font.drawAligned(poseStack, sorse, "/s", TextAlign.CENTER_LEFT, finalX.toFloat(), y + font.lineHeight, RGBAColor.GRAY) + val finalX = font.drawAligned(poseStack, sorse, "00000000", RenderGravity.CENTER_CENTER, -4f, y, RGBAColor.GRAY) + font.drawAligned(poseStack, sorse, "00000000", RenderGravity.CENTER_CENTER, -4f, y + font.lineHeight, RGBAColor.GRAY) + font.drawAligned(poseStack, sorse, "/t", RenderGravity.CENTER_LEFT, finalX.toFloat(), y, RGBAColor.GRAY) + font.drawAligned(poseStack, sorse, "/s", RenderGravity.CENTER_LEFT, finalX.toFloat(), y + font.lineHeight, RGBAColor.GRAY) poseStack.pushPose() poseStack.translate(-0.1, -0.1, -0.1) - font.drawAligned(poseStack, sorse, tile.lastTick.toString(0), TextAlign.CENTER_RIGHT, finalX.toFloat(), y, RGBAColor.WHITE) - font.drawAligned(poseStack, sorse, tile.sumHistory(20).toString(0), TextAlign.CENTER_RIGHT, finalX.toFloat(), y + font.lineHeight, RGBAColor.WHITE) + font.drawAligned(poseStack, sorse, tile.lastTick.toString(0), RenderGravity.CENTER_RIGHT, finalX.toFloat(), y, RGBAColor.WHITE) + font.drawAligned(poseStack, sorse, tile.sumHistory(20).toString(0), RenderGravity.CENTER_RIGHT, finalX.toFloat(), y + font.lineHeight, RGBAColor.WHITE) poseStack.popPose() y += font.lineHeight * 3 - font.drawAligned(poseStack, sorse, TOTAL, TextAlign.CENTER_CENTER, 0f, y, RGBAColor.WHITE) - font.drawAligned(poseStack, sorse, tile.passed.formatPower(), TextAlign.CENTER_CENTER, 0f, y + font.lineHeight, RGBAColor.WHITE) + font.drawAligned(poseStack, sorse, TOTAL, RenderGravity.CENTER_CENTER, 0f, y, RGBAColor.WHITE) + font.drawAligned(poseStack, sorse, tile.passed.formatPower(), RenderGravity.CENTER_CENTER, 0f, y + font.lineHeight, RGBAColor.WHITE) poseStack.popPose() } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/blockentity/GravitationStabilizerRenderer.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/blockentity/GravitationStabilizerRenderer.kt index 1d58c78ca..f3031ecfa 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/blockentity/GravitationStabilizerRenderer.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/blockentity/GravitationStabilizerRenderer.kt @@ -12,7 +12,6 @@ import net.minecraft.core.Direction import org.joml.Matrix4f import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.block.BlackHoleBlock -import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock import ru.dbotthepony.mc.otm.block.entity.tech.GravitationStabilizerBlockEntity import ru.dbotthepony.mc.otm.block.entity.blackhole.BlackHoleBlockEntity import ru.dbotthepony.mc.otm.block.entity.WorkerState @@ -157,12 +156,12 @@ class GravitationStabilizerRenderer(private val context: BlockEntityRendererProv val sorse = DynamicBufferSource.WORLD val font = minecraft.font - font.drawAligned(poseStack, sorse, TranslatableComponent("otm.3d2d.gravitation_stabilizer.mass", bhTile.mass.formatMatter(formatAsReadable = ShiftPressedCond)), TextAlign.TOP_CENTER, 1f, -font.lineHeight.toFloat() / 2f + 1f, 0) - font.drawAligned(poseStack, sorse, TranslatableComponent("otm.3d2d.gravitation_stabilizer.strength", "%.2f".format(bhTile.gravitationStrength)), TextAlign.TOP_CENTER, 1f, font.lineHeight.toFloat() / 2f + 1f, 0) + font.drawAligned(poseStack, sorse, TranslatableComponent("otm.3d2d.gravitation_stabilizer.mass", bhTile.mass.formatMatter(formatAsReadable = ShiftPressedCond)), RenderGravity.TOP_CENTER, 1f, -font.lineHeight.toFloat() / 2f + 1f, 0) + font.drawAligned(poseStack, sorse, TranslatableComponent("otm.3d2d.gravitation_stabilizer.strength", "%.2f".format(bhTile.gravitationStrength)), RenderGravity.TOP_CENTER, 1f, font.lineHeight.toFloat() / 2f + 1f, 0) poseStack.translate(0.2f, 0f, -0.5f) - font.drawAligned(poseStack, sorse, TranslatableComponent("otm.3d2d.gravitation_stabilizer.mass", bhTile.mass.formatMatter(formatAsReadable = ShiftPressedCond)), TextAlign.TOP_CENTER, 0f, -font.lineHeight.toFloat() / 2f, 0xFFFFFF) - font.drawAligned(poseStack, sorse, TranslatableComponent("otm.3d2d.gravitation_stabilizer.strength", "%.2f".format(bhTile.gravitationStrength)), TextAlign.TOP_CENTER, 0f, font.lineHeight.toFloat() / 2f, 0xFFFFFF) + font.drawAligned(poseStack, sorse, TranslatableComponent("otm.3d2d.gravitation_stabilizer.mass", bhTile.mass.formatMatter(formatAsReadable = ShiftPressedCond)), RenderGravity.TOP_CENTER, 0f, -font.lineHeight.toFloat() / 2f, 0xFFFFFF) + font.drawAligned(poseStack, sorse, TranslatableComponent("otm.3d2d.gravitation_stabilizer.strength", "%.2f".format(bhTile.gravitationStrength)), RenderGravity.TOP_CENTER, 0f, font.lineHeight.toFloat() / 2f, 0xFFFFFF) poseStack.popPose() } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/blockentity/HoloSignRenderer.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/blockentity/HoloSignRenderer.kt index a482b3641..32994e002 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/blockentity/HoloSignRenderer.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/blockentity/HoloSignRenderer.kt @@ -7,7 +7,7 @@ import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider import ru.dbotthepony.mc.otm.block.entity.decorative.HoloSignBlockEntity import ru.dbotthepony.mc.otm.client.font import ru.dbotthepony.mc.otm.client.render.DynamicBufferSource -import ru.dbotthepony.mc.otm.client.render.TextAlign +import ru.dbotthepony.mc.otm.client.render.RenderGravity import ru.dbotthepony.mc.otm.client.render.drawAligned import ru.dbotthepony.mc.otm.core.math.RGBAColor import ru.dbotthepony.mc.otm.core.math.rotateWithBlockFacing @@ -37,7 +37,7 @@ class HoloSignRenderer(private val context: BlockEntityRendererProvider.Context) var y = -totalHeight / 2f for (line in lines) { - font.drawAligned(poseStack = poseStack, buffer = sorse, text = line, align = TextAlign.TOP_CENTER, x = 0f, y = y, color = RGBAColor.YELLOW.toInt()) + font.drawAligned(poseStack = poseStack, buffer = sorse, text = line, align = RenderGravity.TOP_CENTER, x = 0f, y = y, color = RGBAColor.YELLOW.toInt()) y += font.lineHeight + 2f } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/entity/PlasmaProjectileRenderer.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/entity/PlasmaProjectileRenderer.kt index b13fb7963..583e1d519 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/entity/PlasmaProjectileRenderer.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/entity/PlasmaProjectileRenderer.kt @@ -5,7 +5,7 @@ import net.minecraft.client.renderer.MultiBufferSource import net.minecraft.client.renderer.entity.EntityRenderer import net.minecraft.client.renderer.entity.EntityRendererProvider import net.minecraft.resources.ResourceLocation -import ru.dbotthepony.mc.otm.client.render.TextAlign +import ru.dbotthepony.mc.otm.client.render.RenderGravity import ru.dbotthepony.mc.otm.client.render.drawAligned import ru.dbotthepony.mc.otm.client.render.rotateAroundPoint import ru.dbotthepony.mc.otm.client.render.translation @@ -30,7 +30,7 @@ class PlasmaProjectileRenderer(context: EntityRendererProvider.Context) : Entity pose.pushPose() pose.scale(0.03f, 0.03f, 0.03f) pose.rotateAroundPoint(pose.translation(), Angle.deg(roll = entity.xRot.toDouble(), yaw = entity.yRot.toDouble(), pitch = 180.0)) - font.drawAligned(pose, "PLASMA", TextAlign.CENTER_CENTER, 0f, 0f, 0xFFFFFF) + font.drawAligned(pose, "PLASMA", RenderGravity.CENTER_CENTER, 0f, 0f, 0xFFFFFF) pose.popPose() } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/ExoPackInventoryScreen.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/ExoPackInventoryScreen.kt index 43447b8da..ae6778d90 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/ExoPackInventoryScreen.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/ExoPackInventoryScreen.kt @@ -1,23 +1,33 @@ package ru.dbotthepony.mc.otm.client.screen -import com.mojang.blaze3d.vertex.PoseStack import net.minecraft.client.gui.GuiGraphics import net.minecraft.client.gui.screens.inventory.InventoryScreen +import net.minecraft.world.item.ItemStack +import net.minecraft.world.item.Items import ru.dbotthepony.mc.otm.client.mousePos import ru.dbotthepony.mc.otm.client.moveMousePosScaled +import ru.dbotthepony.mc.otm.client.render.ItemStackIcon import ru.dbotthepony.mc.otm.client.render.Widgets18 import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.client.render.sprite import ru.dbotthepony.mc.otm.client.screen.panels.* import ru.dbotthepony.mc.otm.client.screen.panels.button.LargeRectangleButtonPanel import ru.dbotthepony.mc.otm.client.screen.panels.slot.AbstractSlotPanel +import ru.dbotthepony.mc.otm.client.screen.panels.slot.BatterySlotPanel import ru.dbotthepony.mc.otm.client.screen.panels.slot.UserFilteredSlotPanel import ru.dbotthepony.mc.otm.client.screen.panels.slot.SlotPanel +import ru.dbotthepony.mc.otm.client.screen.panels.util.BackgroundPanel import ru.dbotthepony.mc.otm.client.screen.panels.util.DiscreteScrollBarPanel +import ru.dbotthepony.mc.otm.client.screen.widget.HorizontalPowerGaugePanel +import ru.dbotthepony.mc.otm.client.screen.widget.PowerGaugePanel +import ru.dbotthepony.mc.otm.client.screen.widget.ProgressGaugePanel +import ru.dbotthepony.mc.otm.client.screen.widget.TallHorizontalProfiledPowerGaugePanel +import ru.dbotthepony.mc.otm.client.screen.widget.WideProfiledPowerGaugePanel import ru.dbotthepony.mc.otm.client.setMousePos import ru.dbotthepony.mc.otm.client.shouldOpenVanillaInventory import ru.dbotthepony.mc.otm.core.math.integerDivisionDown import ru.dbotthepony.mc.otm.menu.ExoPackInventoryMenu +import ru.dbotthepony.mc.otm.menu.widget.ProgressGaugeWidget import ru.dbotthepony.mc.otm.network.ExoPackMenuOpen import ru.dbotthepony.mc.otm.network.MatteryPlayerNetworkChannel import yalter.mousetweaks.api.MouseTweaksDisableWheelTweak @@ -133,18 +143,74 @@ class ExoPackInventoryScreen(menu: ExoPackInventoryMenu) : MatteryScreen( - this@ExoPackInventoryScreen, - craftingCanvas, - x = craftingSlotsCanvas.width, - width = craftingCanvas.width - resultPanel.width - craftingSlotsCanvas.width, - height = topLine.height - ) { - override fun innerRender(graphics: GuiGraphics, mouseX: Float, mouseY: Float, partialTick: Float) { - CRAFT_ARROW.render(graphics, x = width / 2f - CRAFT_ARROW.width / 2f, y = height / 2f - CRAFT_ARROW.height / 2f) + SpritePanel(this, craftingCanvas, CRAFT_ARROW, x = craftingSlotsCanvas.width, + width = craftingCanvas.width - resultPanel.width - craftingSlotsCanvas.width, + height = topLine.height, centerSprite = true) + + if (menu.capability.isExoPackSmeltingInstalled) { + val craftingTab = frame.Tab() + val furnaceTab = frame.Tab() + + craftingTab.activeIcon = ItemStackIcon(ItemStack(Items.CRAFTING_TABLE)) + craftingTab.inactiveIcon = craftingTab.activeIcon + furnaceTab.activeIcon = ItemStackIcon(ItemStack(Items.FURNACE)) + furnaceTab.inactiveIcon = furnaceTab.activeIcon + + craftingTab.onOpen = Runnable { craftingCanvas.visible = true } + craftingTab.onClose = Runnable { craftingCanvas.visible = false } + + val furnaceCanvas = EditablePanel(this, topLine, width = 90f) + furnaceCanvas.dock = Dock.LEFT + furnaceCanvas.visible = false + + furnaceTab.onOpen = Runnable { furnaceCanvas.visible = true; menu.furnaceMenuOpenState.accept(true) } + furnaceTab.onClose = Runnable { furnaceCanvas.visible = false; menu.furnaceMenuOpenState.accept(false) } + + for (i in menu.capability.smelters.indices) { + val row = EditablePanel(this, furnaceCanvas, height = AbstractSlotPanel.SIZE) + row.dock = Dock.TOP + row.dockTop = 4f + + SlotPanel(this, row, menu.furnaceInputs[i]).also { + it.dock = Dock.LEFT + it.dockLeft = 12f + it.dockResize = DockResizeMode.NONE + } + + ProgressGaugePanel(this, row, menu.furnaceProgress[i]).also { + it.dock = Dock.LEFT + it.dockLeft = 9f + it.dockResize = DockResizeMode.NONE + } + + SlotPanel(this, row, menu.furnaceOutputs[i]).also { + it.dock = Dock.LEFT + it.dockLeft = 10f + it.dockResize = DockResizeMode.NONE + } } } + val chargeWidth = HorizontalPowerGaugePanel.GAUGE_BACKGROUND_TALL.width + AbstractSlotPanel.SIZE + 4f + ProgressGaugePanel.GAUGE_BACKGROUND.width + val chargeStrip = BackgroundPanel.paddedCenter(this, frame, frame.width / 2f - chargeWidth / 2f, frame.height + 2f, chargeWidth, AbstractSlotPanel.SIZE) + + chargeStrip.customDock { chargeStrip.setPos(frame.width / 2f - chargeWidth / 2f, frame.height + 2f) } + + BatterySlotPanel(this, chargeStrip, menu.exoPackPowerSlot).also { + it.dock = Dock.LEFT + } + + SpritePanel(this, chargeStrip, ProgressGaugePanel.GAUGE_BACKGROUND).also { + it.dock = Dock.LEFT + it.dockLeft = 2f + it.dockResize = DockResizeMode.NONE + } + + TallHorizontalProfiledPowerGaugePanel(this, chargeStrip, menu.exoPackPower).also { + it.dock = Dock.LEFT + it.dockLeft = 2f + } + scrollPanel.dock = Dock.RIGHT scrollPanel.setDockMargin(right = 3f) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/EditablePanel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/EditablePanel.kt index c188af33e..add7aa7cb 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/EditablePanel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/EditablePanel.kt @@ -3,7 +3,6 @@ package ru.dbotthepony.mc.otm.client.screen.panels import com.google.common.collect.ImmutableList import com.mojang.blaze3d.platform.InputConstants import com.mojang.blaze3d.systems.RenderSystem -import com.mojang.blaze3d.vertex.PoseStack import it.unimi.dsi.fastutil.ints.IntAVLTreeSet import it.unimi.dsi.fastutil.objects.ReferenceArraySet import net.minecraft.client.gui.ComponentPath @@ -550,6 +549,19 @@ open class EditablePanel @JvmOverloads constructor( return x < 0 || y < 0 || x + width > parent.width || y + height > parent.height } + private var once = false + set(value) { + if (value && field != value) { + if (updateVisibility) { + updateVisible() + } + + field = value + } + } + + private var updateVisibility = false + fun calculateAbsoluteRectangle(): Rect2f { if (scissor) { return Rect2f(absoluteX, absoluteY, width, height) @@ -703,7 +715,10 @@ open class EditablePanel @JvmOverloads constructor( } if (child.isVisible() != isVisible()) { - updateVisible() + if (once) + updateVisible() + else + updateVisibility = true } } @@ -768,6 +783,8 @@ open class EditablePanel @JvmOverloads constructor( } fun render(graphics: GuiGraphics, mouseX: Float, mouseY: Float, partialTick: Float) { + once = true + if (!isVisible()) { return } @@ -1145,6 +1162,21 @@ open class EditablePanel @JvmOverloads constructor( } updateBounds() + + for (child in visibleChildrenInternal) { + child.parentLayoutPerformed() + } + } + + private var repositioningCallback: Runnable? = null + + fun customDock(callback: Runnable?) { + if (callback != null) dock = Dock.NONE + repositioningCallback = callback + } + + open fun parentLayoutPerformed() { + repositioningCallback?.run() } fun updateBounds() { @@ -1656,6 +1688,7 @@ open class EditablePanel @JvmOverloads constructor( protected open fun tickInner() {} fun tick() { + once = true tickCount++ tickInner() @@ -1663,8 +1696,6 @@ open class EditablePanel @JvmOverloads constructor( for (child in Array(visibleChildrenInternal.size) { visibleChildrenInternal[it] }) { child.tick() } - - } var isRemoved = false diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/EffectListPanel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/EffectListPanel.kt index bd84d5141..3cf406d10 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/EffectListPanel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/EffectListPanel.kt @@ -1,7 +1,6 @@ package ru.dbotthepony.mc.otm.client.screen.panels import com.mojang.blaze3d.systems.RenderSystem -import com.mojang.blaze3d.vertex.PoseStack import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap import it.unimi.dsi.fastutil.objects.Object2ObjectFunction import net.minecraft.client.gui.GuiGraphics @@ -11,7 +10,7 @@ import net.minecraft.world.effect.MobEffect import net.minecraft.world.effect.MobEffectInstance import net.minecraft.world.entity.LivingEntity import ru.dbotthepony.mc.otm.client.minecraft -import ru.dbotthepony.mc.otm.client.render.TextAlign +import ru.dbotthepony.mc.otm.client.render.RenderGravity import ru.dbotthepony.mc.otm.client.render.determineTooltipPosition import ru.dbotthepony.mc.otm.client.render.drawAligned import ru.dbotthepony.mc.otm.client.render.drawScaledAligned @@ -118,7 +117,7 @@ open class EffectListPanel @JvmOverloads constructor( minecraft.mobEffectTextures.get(effect.effect).render(graphics, x = 3f, y = 3f, width = width - 6f, height = height - 6f) RenderSystem.setShaderColor(1f, 1f, 1f, 1f) - graphics.drawScaledAligned(font, formatTickDuration(effect.duration), 0.75f, TextAlign.CENTER_CENTER, width / 2f - 1f, height / 2f, RGBAColor.WHITE) + graphics.drawScaledAligned(font, formatTickDuration(effect.duration), 0.75f, RenderGravity.CENTER_CENTER, width / 2f - 1f, height / 2f, RGBAColor.WHITE) } override fun innerRenderTooltips(graphics: GuiGraphics, mouseX: Float, mouseY: Float, partialTick: Float): Boolean { @@ -146,8 +145,8 @@ open class EffectListPanel @JvmOverloads constructor( name.append(" ${effect.amplifier + 1}") } - graphics.drawAligned(font, name, TextAlign.TOP_LEFT, x + renderWidth + 12f, y + 7f, RGBAColor.WHITE) - graphics.drawAligned(font, formatTickDuration(effect.duration, true), TextAlign.TOP_LEFT, x + renderWidth + 12f, y + 7f + font.lineHeight + 2f, 8355711) + graphics.drawAligned(font, name, RenderGravity.TOP_LEFT, x + renderWidth + 12f, y + 7f, RGBAColor.WHITE) + graphics.drawAligned(font, formatTickDuration(effect.duration, true), RenderGravity.TOP_LEFT, x + renderWidth + 12f, y + 7f + font.lineHeight + 2f, 8355711) } return isHovered diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/FramePanel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/FramePanel.kt index ace546c82..cb35b2580 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/FramePanel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/FramePanel.kt @@ -2,7 +2,6 @@ package ru.dbotthepony.mc.otm.client.screen.panels import com.mojang.blaze3d.platform.InputConstants import com.mojang.blaze3d.systems.RenderSystem -import com.mojang.blaze3d.vertex.PoseStack import net.minecraft.client.gui.GuiGraphics import net.minecraft.client.gui.narration.NarratableEntry import net.minecraft.client.gui.narration.NarratableEntry.NarrationPriority @@ -13,7 +12,6 @@ import org.lwjgl.opengl.GL30 import ru.dbotthepony.mc.otm.client.playGuiClickSound import ru.dbotthepony.mc.otm.client.render.* import ru.dbotthepony.mc.otm.client.screen.panels.button.AbstractButtonPanel -import ru.dbotthepony.mc.otm.client.screen.panels.button.ButtonPanel open class FramePanel( screen: S, @@ -29,8 +27,8 @@ open class FramePanel( open inner class Tab( var onOpen: Runnable? = null, var onClose: Runnable? = null, - var activeIcon: AbstractMatterySprite? = null, - var inactiveIcon: AbstractMatterySprite? = null, + var activeIcon: IGUIRenderable? = null, + var inactiveIcon: IGUIRenderable? = null, ) : EditablePanel(this@FramePanel.screen, this@FramePanel, 0f, 0f, 28f, 28f) { var isActive = tabs.isEmpty() var initial = false @@ -54,7 +52,6 @@ open class FramePanel( } override fun innerRender(graphics: GuiGraphics, mouseX: Float, mouseY: Float, partialTick: Float) { - val stack = graphics.pose() val width: Float val height: Float @@ -88,10 +85,10 @@ open class FramePanel( ) val skinActive = activeIcon ?: return - skinActive.render(graphics, TAB_WIDTH_ACTIVE / 2f - skinActive.width / 2f, TAB_HEIGHT_ACTIVE / 2f - skinActive.height / 2f) + skinActive.render(graphics, TAB_WIDTH_ACTIVE / 2f, TAB_HEIGHT_ACTIVE / 2f, gravity = RenderGravity.CENTER_CENTER) } else { val skinInactive = inactiveIcon ?: return - skinInactive.render(graphics, width / 2f - skinInactive.width / 2f, TAB_HEIGHT_ACTIVE / 2f - skinInactive.height / 2f) + skinInactive.render(graphics, width / 2f, TAB_HEIGHT_ACTIVE / 2f, gravity = RenderGravity.CENTER_CENTER) } } @@ -259,7 +256,7 @@ open class FramePanel( // title val title = title ?: return RenderSystem.depthFunc(GL30.GL_ALWAYS) - graphics.drawAligned(font, title, TextAlign.TOP_LEFT, 8f, 5f, 4210752) + graphics.drawAligned(font, title, RenderGravity.TOP_LEFT, 8f, 5f, 4210752) RenderSystem.depthFunc(GL30.GL_ALWAYS) } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/Label.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/Label.kt index a67574e2d..b21085fd3 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/Label.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/Label.kt @@ -3,7 +3,7 @@ package ru.dbotthepony.mc.otm.client.screen.panels import net.minecraft.client.gui.GuiGraphics import net.minecraft.client.gui.screens.Screen import net.minecraft.network.chat.Component -import ru.dbotthepony.mc.otm.client.render.TextAlign +import ru.dbotthepony.mc.otm.client.render.RenderGravity import ru.dbotthepony.mc.otm.client.render.drawAligned import ru.dbotthepony.mc.otm.core.TextComponent import ru.dbotthepony.mc.otm.core.math.RGBAColor @@ -29,35 +29,35 @@ open class Label @JvmOverloads constructor( } var color = RGBAColor.SLATE_GRAY - var align = TextAlign.TOP_LEFT + var align = RenderGravity.TOP_LEFT override fun innerRender(graphics: GuiGraphics, mouseX: Float, mouseY: Float, partialTick: Float) { clearDepth(graphics) if (shadow) { when (align) { - TextAlign.TOP_LEFT -> graphics.drawAligned(font, text, align, shadowX, shadowY, shadowColor.toInt()) - TextAlign.TOP_CENTER -> graphics.drawAligned(font, text, align, shadowX + width / 2f, shadowY, shadowColor.toInt()) - TextAlign.TOP_RIGHT -> graphics.drawAligned(font, text, align, shadowX + width, shadowY, shadowColor.toInt()) - TextAlign.CENTER_LEFT -> graphics.drawAligned(font, text, align, shadowX, height / 2f + shadowY, shadowColor.toInt()) - TextAlign.CENTER_CENTER -> graphics.drawAligned(font, text, align, shadowX + width / 2f, height / 2f + shadowY, shadowColor.toInt()) - TextAlign.CENTER_RIGHT -> graphics.drawAligned(font, text, align, shadowX + width, height / 2f + shadowY, shadowColor.toInt()) - TextAlign.BOTTOM_LEFT -> graphics.drawAligned(font, text, align, shadowX, height + shadowY, shadowColor.toInt()) - TextAlign.BOTTOM_CENTER -> graphics.drawAligned(font, text, align, shadowX + width / 2f, height + shadowY, shadowColor.toInt()) - TextAlign.BOTTOM_RIGHT -> graphics.drawAligned(font, text, align, shadowX + width, height + shadowY, shadowColor.toInt()) + RenderGravity.TOP_LEFT -> graphics.drawAligned(font, text, align, shadowX, shadowY, shadowColor.toInt()) + RenderGravity.TOP_CENTER -> graphics.drawAligned(font, text, align, shadowX + width / 2f, shadowY, shadowColor.toInt()) + RenderGravity.TOP_RIGHT -> graphics.drawAligned(font, text, align, shadowX + width, shadowY, shadowColor.toInt()) + RenderGravity.CENTER_LEFT -> graphics.drawAligned(font, text, align, shadowX, height / 2f + shadowY, shadowColor.toInt()) + RenderGravity.CENTER_CENTER -> graphics.drawAligned(font, text, align, shadowX + width / 2f, height / 2f + shadowY, shadowColor.toInt()) + RenderGravity.CENTER_RIGHT -> graphics.drawAligned(font, text, align, shadowX + width, height / 2f + shadowY, shadowColor.toInt()) + RenderGravity.BOTTOM_LEFT -> graphics.drawAligned(font, text, align, shadowX, height + shadowY, shadowColor.toInt()) + RenderGravity.BOTTOM_CENTER -> graphics.drawAligned(font, text, align, shadowX + width / 2f, height + shadowY, shadowColor.toInt()) + RenderGravity.BOTTOM_RIGHT -> graphics.drawAligned(font, text, align, shadowX + width, height + shadowY, shadowColor.toInt()) } } when (align) { - TextAlign.TOP_LEFT -> font.drawAligned(graphics.pose(), text, align, 0f, 0f, color.toInt()) - TextAlign.TOP_CENTER -> font.drawAligned(graphics.pose(), text, align, width / 2f, 0f, color.toInt()) - TextAlign.TOP_RIGHT -> font.drawAligned(graphics.pose(), text, align, width - (if (shadow) shadowX else 0f), 0f, color.toInt()) - TextAlign.CENTER_LEFT -> font.drawAligned(graphics.pose(), text, align, 0f, height / 2f, color.toInt()) - TextAlign.CENTER_CENTER -> font.drawAligned(graphics.pose(), text, align, width / 2f, height / 2f, color.toInt()) - TextAlign.CENTER_RIGHT -> font.drawAligned(graphics.pose(), text, align, width - (if (shadow) shadowX else 0f), height / 2f, color.toInt()) - TextAlign.BOTTOM_LEFT -> font.drawAligned(graphics.pose(), text, align, 0f, height, color.toInt()) - TextAlign.BOTTOM_CENTER -> font.drawAligned(graphics.pose(), text, align, width / 2f, height, color.toInt()) - TextAlign.BOTTOM_RIGHT -> font.drawAligned(graphics.pose(), text, align, width - (if (shadow) shadowX else 0f), height, color.toInt()) + RenderGravity.TOP_LEFT -> font.drawAligned(graphics.pose(), text, align, 0f, 0f, color.toInt()) + RenderGravity.TOP_CENTER -> font.drawAligned(graphics.pose(), text, align, width / 2f, 0f, color.toInt()) + RenderGravity.TOP_RIGHT -> font.drawAligned(graphics.pose(), text, align, width - (if (shadow) shadowX else 0f), 0f, color.toInt()) + RenderGravity.CENTER_LEFT -> font.drawAligned(graphics.pose(), text, align, 0f, height / 2f, color.toInt()) + RenderGravity.CENTER_CENTER -> font.drawAligned(graphics.pose(), text, align, width / 2f, height / 2f, color.toInt()) + RenderGravity.CENTER_RIGHT -> font.drawAligned(graphics.pose(), text, align, width - (if (shadow) shadowX else 0f), height / 2f, color.toInt()) + RenderGravity.BOTTOM_LEFT -> font.drawAligned(graphics.pose(), text, align, 0f, height, color.toInt()) + RenderGravity.BOTTOM_CENTER -> font.drawAligned(graphics.pose(), text, align, width / 2f, height, color.toInt()) + RenderGravity.BOTTOM_RIGHT -> font.drawAligned(graphics.pose(), text, align, width - (if (shadow) shadowX else 0f), height, color.toInt()) } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/SpritePanel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/SpritePanel.kt index ba04c9a63..836444940 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/SpritePanel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/SpritePanel.kt @@ -13,9 +13,14 @@ class SpritePanel( y: Float = 0f, width: Float = sprite.width, height: Float = sprite.height, - val winding: UVWindingOrder = sprite.winding + var winding: UVWindingOrder = sprite.winding, + var centerSprite: Boolean = false ) : EditablePanel(screen, parent, x, y, width, height) { override fun innerRender(graphics: GuiGraphics, mouseX: Float, mouseY: Float, partialTick: Float) { - sprite.render(graphics, 0f, 0f, width, height, winding) + if (centerSprite) { + sprite.render(graphics, width / 2f - sprite.width / 2f, height / 2f - sprite.height / 2f, sprite.width, sprite.height, winding) + } else { + sprite.render(graphics, 0f, 0f, width, height, winding) + } } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/ButtonPanel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/ButtonPanel.kt index 43d4485e0..94e07f8d9 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/ButtonPanel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/ButtonPanel.kt @@ -1,11 +1,9 @@ package ru.dbotthepony.mc.otm.client.screen.panels.button -import com.mojang.blaze3d.vertex.PoseStack import net.minecraft.client.gui.GuiGraphics import net.minecraft.client.gui.screens.Screen import net.minecraft.network.chat.Component -import ru.dbotthepony.mc.otm.client.playGuiClickSound -import ru.dbotthepony.mc.otm.client.render.TextAlign +import ru.dbotthepony.mc.otm.client.render.RenderGravity import ru.dbotthepony.mc.otm.client.render.Widgets18 import ru.dbotthepony.mc.otm.client.render.drawAligned import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel @@ -55,7 +53,7 @@ open class ButtonPanel( override fun innerRender(graphics: GuiGraphics, mouseX: Float, mouseY: Float, partialTick: Float) { renderStretchableBackground(graphics, mouseX, mouseY, partialTick) - graphics.drawAligned(font, label, TextAlign.CENTER_CENTER, width / 2f, height / 2f, textColor.toInt()) + graphics.drawAligned(font, label, RenderGravity.CENTER_CENTER, width / 2f, height / 2f, textColor.toInt()) } override fun sizeToContents() { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/input/TextInputPanel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/input/TextInputPanel.kt index 7fccf017b..c4372fe51 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/input/TextInputPanel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/input/TextInputPanel.kt @@ -3,7 +3,6 @@ package ru.dbotthepony.mc.otm.client.screen.panels.input import com.mojang.blaze3d.platform.InputConstants import com.mojang.blaze3d.systems.RenderSystem import com.mojang.blaze3d.vertex.DefaultVertexFormat -import com.mojang.blaze3d.vertex.PoseStack import com.mojang.blaze3d.vertex.VertexFormat import it.unimi.dsi.fastutil.chars.Char2IntFunction import it.unimi.dsi.fastutil.chars.Char2IntOpenHashMap @@ -20,7 +19,7 @@ import ru.dbotthepony.mc.otm.client.isShiftDown import ru.dbotthepony.mc.otm.client.minecraft import ru.dbotthepony.mc.otm.client.playGuiClickSound import ru.dbotthepony.mc.otm.client.render.DynamicBufferSource -import ru.dbotthepony.mc.otm.client.render.TextAlign +import ru.dbotthepony.mc.otm.client.render.RenderGravity import ru.dbotthepony.mc.otm.client.render.drawAligned import ru.dbotthepony.mc.otm.client.render.drawRect import ru.dbotthepony.mc.otm.client.render.tesselator @@ -1119,7 +1118,7 @@ open class TextInputPanel( graphics.drawAligned( font = font, text = placeholder, - align = TextAlign.TOP_LEFT, + align = RenderGravity.TOP_LEFT, x = dockPadding.left, y = y, color = placeholderColor @@ -1133,7 +1132,7 @@ open class TextInputPanel( graphics.drawAligned( font = font, text = line, - align = TextAlign.TOP_LEFT, + align = RenderGravity.TOP_LEFT, x = dockPadding.left, y = y, color = textColor @@ -1187,7 +1186,7 @@ open class TextInputPanel( graphics.drawAligned( font = font, text = "_", - align = TextAlign.TOP_LEFT, + align = RenderGravity.TOP_LEFT, x = dockPadding.left + (if (activeLine == null) 0f else font.width(activeLine).toFloat()), y = topPadding + (cursorLine - scrollLines) * (font.lineHeight + rowSpacing), color = cursorColor @@ -1196,7 +1195,7 @@ open class TextInputPanel( graphics.drawAligned( font = font, text = "|", - align = TextAlign.TOP_LEFT, + align = RenderGravity.TOP_LEFT, x = dockPadding.left + font.width(activeLine.substring(0, cursorRow)).toFloat() - 1f, y = topPadding + (cursorLine - scrollLines) * (font.lineHeight + rowSpacing), color = cursorColor @@ -1210,7 +1209,7 @@ open class TextInputPanel( graphics.drawAligned( font = font, text = cursorLine.toString(), - align = TextAlign.TOP_RIGHT, + align = RenderGravity.TOP_RIGHT, x = width, y = topPadding, color = cursorColor @@ -1219,7 +1218,7 @@ open class TextInputPanel( graphics.drawAligned( font = font, text = cursorRow.toString(), - align = TextAlign.TOP_RIGHT, + align = RenderGravity.TOP_RIGHT, x = width - dockPadding.right, y = topPadding + font.lineHeight + rowSpacing, color = cursorColor @@ -1228,7 +1227,7 @@ open class TextInputPanel( graphics.drawAligned( font = font, text = lines.size.toString(), - align = TextAlign.TOP_RIGHT, + align = RenderGravity.TOP_RIGHT, x = width - dockPadding.right, y = topPadding + font.lineHeight * 2f + rowSpacing * 2f, color = cursorColor diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/slot/AbstractSlotPanel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/slot/AbstractSlotPanel.kt index e90c7aef0..f4b84dd1e 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/slot/AbstractSlotPanel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/slot/AbstractSlotPanel.kt @@ -21,7 +21,7 @@ abstract class AbstractSlotPanel> @JvmOverloads constru y: Float = 0f, width: Float = SIZE, height: Float = SIZE, - open val noItemIcon: MatterySprite? = null + open val noItemIcon: IGUIRenderable? = null ) : EditablePanel(screen, parent, x, y, width, height), IItemStackPanel { protected open fun renderSlotBackground(graphics: GuiGraphics, mouseX: Float, mouseY: Float, partialTick: Float) { SLOT_BACKGROUND.render(graphics, width = width, height = height) @@ -51,7 +51,7 @@ abstract class AbstractSlotPanel> @JvmOverloads constru renderRegular(graphics, itemStack) if (itemStack.isEmpty) { - noItemIcon?.render(graphics, width = width, height = height) + noItemIcon?.render(graphics, 0f, 0f, width, height) } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/slot/SlotPanel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/slot/SlotPanel.kt index ab5ca2056..98fe73aac 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/slot/SlotPanel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/slot/SlotPanel.kt @@ -11,6 +11,7 @@ import net.minecraft.world.inventory.AbstractContainerMenu import net.minecraft.world.inventory.Slot import net.minecraft.world.item.ItemStack import ru.dbotthepony.mc.otm.client.minecraft +import ru.dbotthepony.mc.otm.client.render.IGUIRenderable import ru.dbotthepony.mc.otm.client.render.MatterySprite import ru.dbotthepony.mc.otm.client.render.Widgets18 import ru.dbotthepony.mc.otm.client.render.drawRect @@ -29,7 +30,7 @@ open class SlotPanel, out T : Slot> @JvmOverloads const y: Float = 0f, width: Float = SIZE, height: Float = SIZE, - noItemIcon: MatterySprite? = null + noItemIcon: IGUIRenderable? = null ) : AbstractSlotPanel(screen, parent, x, y, width, height, noItemIcon), ISlotPanel { override fun mouseClickedInner(x: Double, y: Double, button: Int): Boolean { screen.returnSlot = slot @@ -107,7 +108,7 @@ open class SlotPanel, out T : Slot> @JvmOverloads const RenderSystem.setShaderTexture(0, texture.atlasLocation()) graphics.blit(1, 1, 0, 16, 16, texture) } else { - noItemIcon?.render(graphics, width = width, height = height) + noItemIcon?.render(graphics, 0f, 0f, width = width, height = height) } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/tech/AndroidStationScreen.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/tech/AndroidStationScreen.kt index a937153ab..7d51e8a86 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/tech/AndroidStationScreen.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/tech/AndroidStationScreen.kt @@ -1,8 +1,6 @@ package ru.dbotthepony.mc.otm.client.screen.tech import com.mojang.blaze3d.platform.InputConstants -import com.mojang.blaze3d.systems.RenderSystem -import com.mojang.blaze3d.vertex.PoseStack import it.unimi.dsi.fastutil.ints.Int2FloatAVLTreeMap import it.unimi.dsi.fastutil.ints.Int2ObjectFunction import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap @@ -12,7 +10,6 @@ import net.minecraft.client.gui.GuiGraphics import net.minecraft.network.chat.Component import net.minecraft.world.entity.player.Inventory import net.minecraft.world.item.ItemStack -import org.lwjgl.opengl.GL11 import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.android.AndroidResearch import ru.dbotthepony.mc.otm.android.AndroidResearchManager @@ -22,7 +19,7 @@ import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.client.minecraft import ru.dbotthepony.mc.otm.client.playGuiClickSound -import ru.dbotthepony.mc.otm.client.render.TextAlign +import ru.dbotthepony.mc.otm.client.render.RenderGravity import ru.dbotthepony.mc.otm.client.render.Widgets18 import ru.dbotthepony.mc.otm.client.render.drawColor import ru.dbotthepony.mc.otm.client.render.drawLine @@ -35,7 +32,6 @@ import ru.dbotthepony.mc.otm.client.screen.panels.slot.AbstractSlotPanel import ru.dbotthepony.mc.otm.client.screen.panels.slot.BatterySlotPanel import ru.dbotthepony.mc.otm.client.screen.panels.slot.EquipmentBatterySlotPanel import ru.dbotthepony.mc.otm.client.screen.panels.util.DraggableCanvasPanel -import ru.dbotthepony.mc.otm.client.screen.widget.WidePowerGaugePanel import ru.dbotthepony.mc.otm.client.screen.widget.WideProfiledPowerGaugePanel import ru.dbotthepony.mc.otm.core.math.RGBAColor import ru.dbotthepony.mc.otm.core.ifPresentK @@ -663,7 +659,7 @@ class AndroidStationScreen constructor(p_97741_: AndroidStationMenu, p_97742_: I init { dock = Dock.BOTTOM dockTop = 2f - align = TextAlign.TOP_RIGHT + align = RenderGravity.TOP_RIGHT } override fun innerRender(graphics: GuiGraphics, mouseX: Float, mouseY: Float, partialTick: Float) { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/tech/EssenceStorageScreen.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/tech/EssenceStorageScreen.kt index 2ae976f46..896c8513d 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/tech/EssenceStorageScreen.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/tech/EssenceStorageScreen.kt @@ -1,6 +1,5 @@ package ru.dbotthepony.mc.otm.client.screen.tech -import com.mojang.blaze3d.vertex.PoseStack import net.minecraft.ChatFormatting import net.minecraft.client.gui.GuiGraphics import net.minecraft.network.chat.Component @@ -9,7 +8,7 @@ import net.minecraft.world.entity.player.Inventory import ru.dbotthepony.mc.otm.OverdriveThatMatters import ru.dbotthepony.mc.otm.client.isShiftDown import ru.dbotthepony.mc.otm.client.render.MatteryAtlas -import ru.dbotthepony.mc.otm.client.render.TextAlign +import ru.dbotthepony.mc.otm.client.render.RenderGravity import ru.dbotthepony.mc.otm.client.screen.MatteryScreen import ru.dbotthepony.mc.otm.client.screen.panels.Dock import ru.dbotthepony.mc.otm.client.screen.panels.DockProperty @@ -74,7 +73,7 @@ class EssenceStorageScreen(menu: EssenceStorageMenu, inventory: Inventory, title init { dock = Dock.TOP dockMargin = DockProperty(bottom = 3f) - align = TextAlign.TOP_CENTER + align = RenderGravity.TOP_CENTER } override fun tickInner() { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/compat/jei/PlatePressRecipeCategory.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/compat/jei/PlatePressRecipeCategory.kt index 2e46da76f..ceed77e88 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/compat/jei/PlatePressRecipeCategory.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/compat/jei/PlatePressRecipeCategory.kt @@ -14,7 +14,7 @@ import net.minecraft.world.item.ItemStack import net.minecraft.world.item.crafting.Ingredient import ru.dbotthepony.mc.otm.OverdriveThatMatters import ru.dbotthepony.mc.otm.client.minecraft -import ru.dbotthepony.mc.otm.client.render.TextAlign +import ru.dbotthepony.mc.otm.client.render.RenderGravity import ru.dbotthepony.mc.otm.client.render.drawAligned import ru.dbotthepony.mc.otm.client.screen.panels.slot.AbstractSlotPanel import ru.dbotthepony.mc.otm.client.screen.widget.ProgressGaugePanel @@ -70,12 +70,12 @@ object PlatePressRecipeCategory : IRecipeCategory, IDrawable { mouseX: Double, mouseY: Double ) { - graphics.drawAligned(minecraft.font, TranslatableComponent("otm.gui.recipe.ticks", recipe.workTime), TextAlign.TOP_CENTER, 40f, 30f, RGBAColor.BLACK) + graphics.drawAligned(minecraft.font, TranslatableComponent("otm.gui.recipe.ticks", recipe.workTime), RenderGravity.TOP_CENTER, 40f, 30f, RGBAColor.BLACK) val average = recipe.experience.toString() if (average != "0.0") { - graphics.drawAligned(minecraft.font, TranslatableComponent("gui.jei.category.smelting.experience", average), TextAlign.TOP_CENTER, 40f, 1f, RGBAColor.BLACK) + graphics.drawAligned(minecraft.font, TranslatableComponent("gui.jei.category.smelting.experience", average), RenderGravity.TOP_CENTER, 40f, 1f, RGBAColor.BLACK) } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/config/ExopackConfig.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/config/ExopackConfig.kt new file mode 100644 index 000000000..ab652e63d --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/config/ExopackConfig.kt @@ -0,0 +1,15 @@ +package ru.dbotthepony.mc.otm.config + +import ru.dbotthepony.mc.otm.core.math.Decimal +import ru.dbotthepony.mc.otm.core.math.defineDecimal + +object ExopackConfig : AbstractConfig("exopack") { + val ENERGY_CAPACITY by builder + .comment("Internal battery capacity of Exopack") + .defineDecimal("ENERGY_CAPACITY", Decimal(400_000), Decimal.ZERO) + + val FURNACE_POWER_CONSUMPTION by builder + .comment("Power consumed per tick by built in furnace") + .comment("Vanilla furnace consumes 10 MtU/t (1 tick = 10 MtU, 1 Coal = 16 000 MtU,", "this ratio is utilized by almost all mods)") + .defineDecimal("FURNACE_POWER_CONSUMPTION", Decimal(20), Decimal.ZERO) +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/item/exopack/ExoPackCraftingUpgradeItem.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/item/exopack/ExopackUpgradeItem.kt similarity index 74% rename from src/main/kotlin/ru/dbotthepony/mc/otm/item/exopack/ExoPackCraftingUpgradeItem.kt rename to src/main/kotlin/ru/dbotthepony/mc/otm/item/exopack/ExopackUpgradeItem.kt index 86f904785..2c393c725 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/item/exopack/ExoPackCraftingUpgradeItem.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/item/exopack/ExopackUpgradeItem.kt @@ -7,15 +7,23 @@ import net.minecraft.world.InteractionHand import net.minecraft.world.InteractionResultHolder import net.minecraft.world.entity.LivingEntity import net.minecraft.world.entity.player.Player -import net.minecraft.world.item.* +import net.minecraft.world.item.Item +import net.minecraft.world.item.ItemStack +import net.minecraft.world.item.Rarity +import net.minecraft.world.item.TooltipFlag +import net.minecraft.world.item.UseAnim import net.minecraft.world.level.Level -import ru.dbotthepony.mc.otm.OverdriveThatMatters -import ru.dbotthepony.mc.otm.core.TranslatableComponent +import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability import ru.dbotthepony.mc.otm.capability.matteryPlayer import ru.dbotthepony.mc.otm.client.minecraft +import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.runIfClient -class ExoPackCraftingUpgradeItem : Item(Properties().stacksTo(1).rarity(Rarity.RARE)) { +class ExopackUpgradeItem( + val type: MatteryPlayerCapability.UpgradeType, + val upgradeName: String, + val upgradedName: String, +) : Item(Properties().stacksTo(1).rarity(Rarity.RARE)) { override fun getUseDuration(p_41454_: ItemStack): Int { return 30 } @@ -36,13 +44,13 @@ class ExoPackCraftingUpgradeItem : Item(Properties().stacksTo(1).rarity(Rarity.R } val alreadyHas = runIfClient(true) { - minecraft.player?.matteryPlayer?.isExoPackCraftingUpgraded == true + type.prop.get(minecraft.player?.matteryPlayer ?: return@runIfClient false) } if (alreadyHas) { tooltip.add(TranslatableComponent("otm.gui.exopack_upgrades.already_activated").withStyle(ChatFormatting.DARK_RED)) } else { - tooltip.add(TranslatableComponent("otm.gui.exopack_upgrades.crafting_upgrade").withStyle(ChatFormatting.DARK_GREEN)) + tooltip.add(TranslatableComponent("otm.gui.exopack_upgrades.$upgradeName").withStyle(ChatFormatting.DARK_GREEN)) } } @@ -59,7 +67,7 @@ class ExoPackCraftingUpgradeItem : Item(Properties().stacksTo(1).rarity(Rarity.R if (player !is Player) return super.finishUsingItem(itemStack, level, player) val mattery = player.matteryPlayer ?: return super.finishUsingItem(itemStack, level, player) - if (!mattery.hasExoPack || mattery.isExoPackCraftingUpgraded) { + if (!mattery.hasExoPack || type.prop.get(mattery)) { return super.finishUsingItem(itemStack, level, player) } @@ -67,9 +75,8 @@ class ExoPackCraftingUpgradeItem : Item(Properties().stacksTo(1).rarity(Rarity.R itemStack.shrink(1) if (player is ServerPlayer) { - mattery.isExoPackCraftingUpgraded = true - - player.displayClientMessage(TranslatableComponent("otm.exopack_upgrades.crafting_upgraded").withStyle(ChatFormatting.DARK_GREEN), false) + type.prop.set(mattery, true) + player.displayClientMessage(TranslatableComponent("otm.exopack_upgrades.$upgradedName").withStyle(ChatFormatting.DARK_GREEN), false) } return itemStack diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/item/weapon/AbstractWeaponItem.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/item/weapon/AbstractWeaponItem.kt index 7c67f68e7..19c2c5f02 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/item/weapon/AbstractWeaponItem.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/item/weapon/AbstractWeaponItem.kt @@ -3,7 +3,6 @@ package ru.dbotthepony.mc.otm.item.weapon import com.mojang.blaze3d.systems.RenderSystem import net.minecraft.client.Minecraft import net.minecraft.client.model.HumanoidModel -import net.minecraft.client.renderer.block.model.ItemTransforms import net.minecraft.nbt.CompoundTag import net.minecraft.network.FriendlyByteBuf import net.minecraft.server.level.ServerPlayer @@ -24,7 +23,7 @@ import net.minecraftforge.network.NetworkEvent import ru.dbotthepony.mc.otm.* import ru.dbotthepony.mc.otm.capability.matteryEnergy import ru.dbotthepony.mc.otm.client.font -import ru.dbotthepony.mc.otm.client.render.TextAlign +import ru.dbotthepony.mc.otm.client.render.RenderGravity import ru.dbotthepony.mc.otm.client.render.drawAligned import ru.dbotthepony.mc.otm.client.render.drawRect import ru.dbotthepony.mc.otm.client.render.setDrawColor @@ -468,7 +467,7 @@ abstract class AbstractWeaponItem(val tables: KClass, pr pose.translate(0.0, 0.0, -1.0) pose.scale(0.7f, 0.7f, 0.7f) val text = it.batteryLevel.formatPower() - font.drawAligned(pose, text, TextAlign.TOP_LEFT, 2f, 2f, RGBAColor.WHITE.toInt()) + font.drawAligned(pose, text, RenderGravity.TOP_LEFT, 2f, 2f, RGBAColor.WHITE.toInt()) pose.popPose() } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/ExoPackInventoryMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/ExoPackInventoryMenu.kt index 8e3c13dc0..4fd40ba70 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/ExoPackInventoryMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/ExoPackInventoryMenu.kt @@ -4,14 +4,19 @@ import com.google.common.collect.ImmutableList import com.mojang.datafixers.util.Pair import net.minecraft.core.NonNullList import net.minecraft.resources.ResourceLocation +import net.minecraft.server.level.ServerLevel import net.minecraft.server.level.ServerPlayer import net.minecraft.world.Container +import net.minecraft.world.entity.ExperienceOrb import net.minecraft.world.entity.player.Player import net.minecraft.world.inventory.* import net.minecraft.world.item.ItemStack import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability import ru.dbotthepony.mc.otm.compat.curios.curiosSlots import ru.dbotthepony.mc.otm.container.iterator +import ru.dbotthepony.mc.otm.menu.input.InstantBooleanInput +import ru.dbotthepony.mc.otm.menu.widget.ProfiledLevelGaugeWidget +import ru.dbotthepony.mc.otm.menu.widget.ProgressGaugeWidget import ru.dbotthepony.mc.otm.network.ExoSuitCarriedPacket import ru.dbotthepony.mc.otm.network.ExoSuitMenuInitPacket import ru.dbotthepony.mc.otm.network.ExoSuitSlotPacket @@ -102,6 +107,42 @@ class ExoPackInventoryMenu(val capability: MatteryPlayerCapability) : MatteryMen } } + private fun popFurnaceExp() { + if (capability.isExoPackSmeltingInstalled && capability.exoPackSmelterExperience >= 1f && !ply.level().isClientSide) { + val whole = capability.exoPackSmelterExperience.toInt() + capability.exoPackSmelterExperience -= whole + ExperienceOrb.award(ply.level() as ServerLevel, ply.position(), whole) + } + } + + val furnaceInputs: List = capability.smelters.map { + object : MatterySlot(it.input, 0) { + override fun mayPlace(itemStack: ItemStack): Boolean { + return super.mayPlace(itemStack) && capability.isExoPackSmeltingInstalled + } + } + } + + val furnaceOutputs: List = capability.smelters.map { + object : MachineOutputSlot(it.output, 0, onTake = ::popFurnaceExp) { + override fun mayPickup(player: Player): Boolean { + return super.mayPickup(player) && capability.isExoPackSmeltingInstalled + } + } + } + + val furnaceProgress = capability.smelters.map { ProgressGaugeWidget(mSynchronizer, it) } + val exoPackPowerSlot = BatterySlot(capability.exoPackEnergy.parent, 0) + val exoPackPower = ProfiledLevelGaugeWidget(mSynchronizer, capability.exoPackEnergy) + + val furnaceMenuOpenState = InstantBooleanInput(this) + + init { + addStorageSlot(furnaceInputs, condition = furnaceMenuOpenState) + addStorageSlot(furnaceOutputs, condition = furnaceMenuOpenState) + addSlot(exoPackPowerSlot) + } + private var isRemoved = false override fun slotsChanged(container: Container) { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/MatteryMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/MatteryMenu.kt index 0e4260970..cf4523b61 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/MatteryMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/MatteryMenu.kt @@ -48,6 +48,7 @@ import ru.dbotthepony.mc.otm.core.util.IStreamCodec import ru.dbotthepony.mc.otm.core.util.ItemValueCodec import ru.dbotthepony.mc.otm.core.util.NullValueCodec import ru.dbotthepony.mc.otm.core.util.VarIntValueCodec +import ru.dbotthepony.mc.otm.menu.input.InstantBooleanInput import ru.dbotthepony.mc.otm.network.MatteryPacket import ru.dbotthepony.mc.otm.network.MatteryPlayerNetworkChannel import ru.dbotthepony.mc.otm.network.MenuFieldPacket @@ -457,9 +458,9 @@ abstract class MatteryMenu @JvmOverloads protected constructor( return slot } - protected fun addStorageSlot(slot: Iterable, addMapping: Boolean = true) { + protected fun addStorageSlot(slot: Iterable, addMapping: Boolean = true, prepend: Boolean = false, condition: BooleanSupplier = BooleanSupplier { true }) { for (value in slot) - addStorageSlot(value, addMapping) + addStorageSlot(value, addMapping, prepend, condition) } /** @@ -762,8 +763,7 @@ abstract class MatteryMenu @JvmOverloads protected constructor( val syncContainer = container ?: SimpleContainer(count) - var isOpen = false - val input = PlayerInput(BooleanValueCodec, allowSpectators = true, handler = { isOpen = it }) + val isOpen = InstantBooleanInput(this) return UpgradeSlots( slots = immutableList(count) { @@ -776,10 +776,10 @@ abstract class MatteryMenu @JvmOverloads protected constructor( return super.mayPlace(itemStack) && itemStack.getCapability(MatteryCapability.UPGRADE).map { it.upgradeTypes.any { allowedTypes[it]!!.boolean } }.orElse(false) } } - }.also { for (i in it.indices.reversed()) addStorageSlot(it[i], prepend = true, condition = { isOpen }) }, + }.also { for (i in it.indices.reversed()) addStorageSlot(it[i], prepend = true, condition = isOpen) }, allowedTypes = ConditionalEnumSet(allowedTypes), - openState = GetterSetter.of({ isOpen }, { input.input(it); isOpen = it }), + openState = isOpen, currentStats = object : IMatteryUpgrade { override val upgradeTypes: Set = setOf() override val speedBonus: Double by mSynchronizer.computedDouble(DoubleSupplier { container?.speedBonus ?: 0.0 }).property diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/InstantBooleanInput.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/InstantBooleanInput.kt new file mode 100644 index 000000000..49204ce6b --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/InstantBooleanInput.kt @@ -0,0 +1,25 @@ +package ru.dbotthepony.mc.otm.menu.input + +import ru.dbotthepony.mc.otm.core.GetterSetter +import ru.dbotthepony.mc.otm.menu.MatteryMenu +import java.util.function.BooleanSupplier + +class InstantBooleanInput(menu: MatteryMenu) : GetterSetter, BooleanSupplier { + var value = false + private set + + val input = menu.booleanInput(true) { value = it } + + override fun get(): Boolean { + return value + } + + override fun getAsBoolean(): Boolean { + return value + } + + override fun accept(t: Boolean) { + value = t + input.input(t) + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/network/synchronizer/FieldSynchronizer.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/network/synchronizer/FieldSynchronizer.kt index 2cc385b8b..a86c4e5f4 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/network/synchronizer/FieldSynchronizer.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/network/synchronizer/FieldSynchronizer.kt @@ -345,7 +345,7 @@ class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCa } } - private val dirtyFields = ReferenceArraySet>(fields.size) + private val dirtyFields = ReferenceArraySet>(4) // use LinkedList because it is ensured memory is freed on LinkedList#clear private val mapBacklogs = Reference2ObjectOpenHashMap, LinkedList Unit>>>() diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MCreativeTabs.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MCreativeTabs.kt index 44a35bf41..dcbc6ac30 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MCreativeTabs.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MCreativeTabs.kt @@ -187,6 +187,7 @@ private fun addMainCreativeTabItems(consumer: CreativeModeTab.Output) { accept(MItems.EXOPACK_PROBE) accept(MItems.ExopackUpgrades.INVENTORY_UPGRADE_CREATIVE) accept(MItems.ExopackUpgrades.CRAFTING_UPGRADE) + accept(MItems.ExopackUpgrades.SMELTING_UPGRADE) accept(MItems.ExopackUpgrades.INVENTORY_UPGRADE_BIG) accept(MItems.ExopackUpgrades.INVENTORY_UPGRADE_HUGE) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MItems.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MItems.kt index ea6697944..4a5be5b0f 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MItems.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MItems.kt @@ -14,13 +14,13 @@ import net.minecraftforge.eventbus.api.IEventBus import net.minecraftforge.registries.DeferredRegister import net.minecraftforge.registries.ForgeRegistries import ru.dbotthepony.mc.otm.OverdriveThatMatters +import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability import ru.dbotthepony.mc.otm.capability.UpgradeType import ru.dbotthepony.mc.otm.config.ItemsConfig import ru.dbotthepony.mc.otm.core.collect.SupplierList import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.core.math.Decimal import ru.dbotthepony.mc.otm.item.* -import ru.dbotthepony.mc.otm.item.exopack.ExoPackCraftingUpgradeItem import ru.dbotthepony.mc.otm.item.exopack.ExoPackProbeItem import ru.dbotthepony.mc.otm.item.exopack.ExoPackSlotUpgradeItem import ru.dbotthepony.mc.otm.item.matter.CreativePatternItem @@ -33,6 +33,7 @@ import ru.dbotthepony.mc.otm.item.tool.MatteryAxeItem import ru.dbotthepony.mc.otm.item.armor.PortableGravitationStabilizerItem import ru.dbotthepony.mc.otm.item.armor.SimpleTritaniumArmorItem import ru.dbotthepony.mc.otm.item.armor.TritaniumArmorItem +import ru.dbotthepony.mc.otm.item.exopack.ExopackUpgradeItem import ru.dbotthepony.mc.otm.item.exopack.ProceduralExoPackSlotUpgradeItem import ru.dbotthepony.mc.otm.item.weapon.PlasmaRifleItem @@ -500,7 +501,8 @@ object MItems { object ExopackUpgrades { val INVENTORY_UPGRADE_CREATIVE: Item by registry.register("exosuit_inventory_upgrade_creative") { ExoPackSlotUpgradeItem(null, 27, Rarity.EPIC) } - val CRAFTING_UPGRADE: Item by registry.register("exosuit_crafting_upgrade", ::ExoPackCraftingUpgradeItem) + val CRAFTING_UPGRADE: Item by registry.register("exosuit_crafting_upgrade") { ExopackUpgradeItem(MatteryPlayerCapability.UpgradeType.CRAFTING, "crafting_upgrade", "crafting_upgraded") } + val SMELTING_UPGRADE: Item by registry.register("exopack_smelting_upgrade") { ExopackUpgradeItem(MatteryPlayerCapability.UpgradeType.SMELTING, "smelting_upgrade", "smelting_installed") } val INVENTORY_UPGRADES = SupplierList(8) { registry.register("exosuit_inventory_upgrade_$it") { ExoPackSlotUpgradeItem(18, Rarity.COMMON) }::get