Exopack smelting, RenderGravity, IGUIRenderable

This commit is contained in:
DBotThePony 2023-07-08 00:51:37 +07:00
parent 311af4f8d9
commit 3cacf7f11f
Signed by: DBot
GPG Key ID: DCC23B5715498507
38 changed files with 804 additions and 326 deletions

View File

@ -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")

View File

@ -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", "Использует те же принципы, которыми обладают звёзды незера")

View File

@ -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);

View File

@ -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<CompoundTag> {
@ -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<MachineItemJob>() {
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<MachineItemJob> {
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<MatteryPlayerCapability, Boolean>) {
CRAFTING(MatteryPlayerCapability::isExoPackCraftingUpgraded),
SMELTING(MatteryPlayerCapability::isExoPackSmeltingInstalled);
}
@Suppress("unused")
companion object {
private fun setExoPack(players: Collection<Player>, 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<Player>): 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<Player>): 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<Player>, 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()

View File

@ -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<CompoundTag?> {
) : IMatteryEnergyStorage, INBTSerializable<CompoundTag?>, 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()

View File

@ -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
}

View File

@ -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))
}
}

View File

@ -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,

View File

@ -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())

View File

@ -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()
}
}
}

View File

@ -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()
}
}

View File

@ -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()
}

View File

@ -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()
}

View File

@ -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()
}

View File

@ -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
}

View File

@ -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()
}
}

View File

@ -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<ExoPack
val resultPanel = SlotPanel(this, craftingCanvas, menu.craftingResultSlot, x = craftingCanvas.width - 18f, y = topLine.height / 2f - 9f)
object : EditablePanel<ExoPackInventoryScreen>(
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)

View File

@ -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<out S : Screen> @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<out S : Screen> @JvmOverloads constructor(
}
if (child.isVisible() != isVisible()) {
updateVisible()
if (once)
updateVisible()
else
updateVisibility = true
}
}
@ -768,6 +783,8 @@ open class EditablePanel<out S : Screen> @JvmOverloads constructor(
}
fun render(graphics: GuiGraphics, mouseX: Float, mouseY: Float, partialTick: Float) {
once = true
if (!isVisible()) {
return
}
@ -1145,6 +1162,21 @@ open class EditablePanel<out S : Screen> @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<out S : Screen> @JvmOverloads constructor(
protected open fun tickInner() {}
fun tick() {
once = true
tickCount++
tickInner()
@ -1663,8 +1696,6 @@ open class EditablePanel<out S : Screen> @JvmOverloads constructor(
for (child in Array(visibleChildrenInternal.size) { visibleChildrenInternal[it] }) {
child.tick()
}
}
var isRemoved = false

View File

@ -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<out S : Screen> @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<out S : Screen> @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

View File

@ -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<out S : Screen>(
screen: S,
@ -29,8 +27,8 @@ open class FramePanel<out S : Screen>(
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<S>(this@FramePanel.screen, this@FramePanel, 0f, 0f, 28f, 28f) {
var isActive = tabs.isEmpty()
var initial = false
@ -54,7 +52,6 @@ open class FramePanel<out S : Screen>(
}
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<out S : Screen>(
)
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<out S : Screen>(
// 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)
}

View File

@ -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<out S : Screen> @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())
}
}

View File

@ -13,9 +13,14 @@ class SpritePanel<out S : Screen>(
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<S>(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)
}
}
}

View File

@ -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<out S : Screen>(
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() {

View File

@ -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<out S : Screen>(
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<out S : Screen>(
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<out S : Screen>(
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<out S : Screen>(
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<out S : Screen>(
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<out S : Screen>(
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<out S : Screen>(
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

View File

@ -21,7 +21,7 @@ abstract class AbstractSlotPanel<out S : MatteryScreen<*>> @JvmOverloads constru
y: Float = 0f,
width: Float = SIZE,
height: Float = SIZE,
open val noItemIcon: MatterySprite? = null
open val noItemIcon: IGUIRenderable? = null
) : EditablePanel<S>(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<out S : MatteryScreen<*>> @JvmOverloads constru
renderRegular(graphics, itemStack)
if (itemStack.isEmpty) {
noItemIcon?.render(graphics, width = width, height = height)
noItemIcon?.render(graphics, 0f, 0f, width, height)
}
}

View File

@ -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 S : MatteryScreen<*>, out T : Slot> @JvmOverloads const
y: Float = 0f,
width: Float = SIZE,
height: Float = SIZE,
noItemIcon: MatterySprite? = null
noItemIcon: IGUIRenderable? = null
) : AbstractSlotPanel<S>(screen, parent, x, y, width, height, noItemIcon), ISlotPanel<T> {
override fun mouseClickedInner(x: Double, y: Double, button: Int): Boolean {
screen.returnSlot = slot
@ -107,7 +108,7 @@ open class SlotPanel<out S : MatteryScreen<*>, 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)
}
}

View File

@ -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) {

View File

@ -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() {

View File

@ -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<PlatePressRecipe>, 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)
}
}

View File

@ -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)
}

View File

@ -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

View File

@ -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<D : WeaponDataTable>(val tables: KClass<D>, 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()
}

View File

@ -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<MatterySlot> = capability.smelters.map {
object : MatterySlot(it.input, 0) {
override fun mayPlace(itemStack: ItemStack): Boolean {
return super.mayPlace(itemStack) && capability.isExoPackSmeltingInstalled
}
}
}
val furnaceOutputs: List<MachineOutputSlot> = 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) {

View File

@ -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<Slot>, addMapping: Boolean = true) {
protected fun addStorageSlot(slot: Iterable<Slot>, 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<UpgradeType> = setOf()
override val speedBonus: Double by mSynchronizer.computedDouble(DoubleSupplier { container?.speedBonus ?: 0.0 }).property

View File

@ -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<Boolean>, 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)
}
}

View File

@ -345,7 +345,7 @@ class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCa
}
}
private val dirtyFields = ReferenceArraySet<AbstractField<*>>(fields.size)
private val dirtyFields = ReferenceArraySet<AbstractField<*>>(4)
// use LinkedList because it is ensured memory is freed on LinkedList#clear
private val mapBacklogs = Reference2ObjectOpenHashMap<Map<*, *>, LinkedList<Pair<Any?, (DataOutputStream) -> Unit>>>()

View File

@ -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)

View File

@ -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