diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/DataGen.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/DataGen.kt index fcdb05480..b865b5e10 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/DataGen.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/DataGen.kt @@ -261,9 +261,9 @@ object DataGen { val mdl = if (dir === Direction.WEST) west else east part().modelFile(mdl).addModel().condition(BlockEnergyCounter.INPUT_DIRECTION, dir).condition(BlockEnergyCounter.IF_DIRECTION, Direction.NORTH) - part().modelFile(mdl).rotationX(90).addModel().condition(BlockEnergyCounter.INPUT_DIRECTION, dir).condition(BlockEnergyCounter.IF_DIRECTION, Direction.UP) + part().modelFile(mdl).rotationX(-90).addModel().condition(BlockEnergyCounter.INPUT_DIRECTION, dir).condition(BlockEnergyCounter.IF_DIRECTION, Direction.UP) part().modelFile(mdl).rotationX(180).addModel().condition(BlockEnergyCounter.INPUT_DIRECTION, dir).condition(BlockEnergyCounter.IF_DIRECTION, Direction.SOUTH) - part().modelFile(mdl).rotationX(-90).addModel().condition(BlockEnergyCounter.INPUT_DIRECTION, dir).condition(BlockEnergyCounter.IF_DIRECTION, Direction.DOWN) + part().modelFile(mdl).rotationX(90).addModel().condition(BlockEnergyCounter.INPUT_DIRECTION, dir).condition(BlockEnergyCounter.IF_DIRECTION, Direction.DOWN) } } } diff --git a/src/main/java/ru/dbotthepony/mc/otm/Registry.java b/src/main/java/ru/dbotthepony/mc/otm/Registry.java index ab23a066e..7e5e4bab9 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/Registry.java +++ b/src/main/java/ru/dbotthepony/mc/otm/Registry.java @@ -48,6 +48,7 @@ import ru.dbotthepony.mc.otm.block.entity.blackhole.BlockEntityBlackHole; import ru.dbotthepony.mc.otm.block.entity.blackhole.BlockEntityExplosionDebugger; import ru.dbotthepony.mc.otm.block.entity.blackhole.BlockEntitySphereDebugger; import ru.dbotthepony.mc.otm.client.render.BlackHoleRenderer; +import ru.dbotthepony.mc.otm.client.render.EnergyCounterRenderer; import ru.dbotthepony.mc.otm.client.render.GravitationStabilizerRenderer; import ru.dbotthepony.mc.otm.client.render.SkinElement; import ru.dbotthepony.mc.otm.core.Fraction; @@ -1007,6 +1008,7 @@ public class Registry { public static void registerRenderers(final FMLClientSetupEvent event) { BlockEntityRenderers.register(BLACK_HOLE, BlackHoleRenderer::new); BlockEntityRenderers.register(GRAVITATION_STABILIZER, GravitationStabilizerRenderer::new); + BlockEntityRenderers.register(ENERGY_COUNTER, EnergyCounterRenderer::new); } } diff --git a/src/main/java/ru/dbotthepony/mc/otm/menu/FormattingHelper.java b/src/main/java/ru/dbotthepony/mc/otm/menu/FormattingHelper.java index 3f6570bfe..ca913c54b 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/menu/FormattingHelper.java +++ b/src/main/java/ru/dbotthepony/mc/otm/menu/FormattingHelper.java @@ -12,10 +12,83 @@ import javax.annotation.ParametersAreNonnullByDefault; import java.math.BigDecimal; import java.math.BigInteger; import java.math.RoundingMode; +import java.util.ArrayList; +import java.util.List; @MethodsReturnNonnullByDefault @ParametersAreNonnullByDefault public class FormattingHelper { + public static final TranslatableComponent SUFFIX_KILO = new TranslatableComponent("otm.suffix_raw.kilo"); + public static final TranslatableComponent SUFFIX_MEGA = new TranslatableComponent("otm.suffix_raw.mega"); + public static final TranslatableComponent SUFFIX_GIGA = new TranslatableComponent("otm.suffix_raw.giga"); + public static final TranslatableComponent SUFFIX_TERA = new TranslatableComponent("otm.suffix_raw.tera"); + public static final TranslatableComponent SUFFIX_PETA = new TranslatableComponent("otm.suffix_raw.peta"); + public static final TranslatableComponent SUFFIX_EXA = new TranslatableComponent("otm.suffix_raw.exa"); + public static final TranslatableComponent SUFFIX_ZETTA = new TranslatableComponent("otm.suffix_raw.zetta"); + public static final TranslatableComponent SUFFIX_YOTTA = new TranslatableComponent("otm.suffix_raw.yotta"); + + public static final TranslatableComponent SUFFIX_DECI = new TranslatableComponent("otm.suffix_raw.deci"); + public static final TranslatableComponent SUFFIX_CENTI = new TranslatableComponent("otm.suffix_raw.centi"); + public static final TranslatableComponent SUFFIX_MILLI = new TranslatableComponent("otm.suffix_raw.milli"); + public static final TranslatableComponent SUFFIX_MICRO = new TranslatableComponent("otm.suffix_raw.micro"); + public static final TranslatableComponent SUFFIX_NANO = new TranslatableComponent("otm.suffix_raw.nano"); + public static final TranslatableComponent SUFFIX_PICO = new TranslatableComponent("otm.suffix_raw.pico"); + public static final TranslatableComponent SUFFIX_FEMTO = new TranslatableComponent("otm.suffix_raw.femto"); + public static final TranslatableComponent SUFFIX_ATTO = new TranslatableComponent("otm.suffix_raw.atto"); + public static final TranslatableComponent SUFFIX_ZEPTO = new TranslatableComponent("otm.suffix_raw.zepto"); + public static final TranslatableComponent SUFFIX_YOCTO = new TranslatableComponent("otm.suffix_raw.yocto"); + + public static final List BIG_SUFFIX_STRIPE = List.of( + SUFFIX_KILO, + SUFFIX_MEGA, + SUFFIX_GIGA, + SUFFIX_TERA, + SUFFIX_PETA, + SUFFIX_EXA, + SUFFIX_ZETTA, + SUFFIX_YOTTA + ); + + public static final List SMALL_SUFFIX_STRIPE = List.of( + SUFFIX_DECI, + SUFFIX_CENTI, + SUFFIX_MILLI, + SUFFIX_MICRO, + SUFFIX_NANO, + SUFFIX_PICO, + SUFFIX_FEMTO, + SUFFIX_ATTO, + SUFFIX_ZEPTO, + SUFFIX_YOCTO + ); + + public static final List BIG_SUFFIX_STRIPE_INV; + public static final List SMALL_SUFFIX_STRIPE_INV; + + static { + var list = new ArrayList(BIG_SUFFIX_STRIPE.size()); + + int i2 = 0; + for (int i = BIG_SUFFIX_STRIPE.size() - 1; i >= 0; i--) { + list.add(BIG_SUFFIX_STRIPE.get(i2)); + i2++; + } + + BIG_SUFFIX_STRIPE_INV = List.copyOf(list); + } + + static { + var list = new ArrayList(BIG_SUFFIX_STRIPE.size()); + + int i2 = 0; + for (int i = BIG_SUFFIX_STRIPE.size() - 1; i >= 0; i--) { + list.add(BIG_SUFFIX_STRIPE.get(i2)); + i2++; + } + + SMALL_SUFFIX_STRIPE_INV = List.copyOf(list); + } + public static final String[] SUFFIX_COMPONENTS_ABOVE_ONE = new String[] { "otm.suffix.kilo", "otm.suffix.mega", diff --git a/src/main/java/ru/dbotthepony/mc/otm/network/MatteryNetworking.java b/src/main/java/ru/dbotthepony/mc/otm/network/MatteryNetworking.java index d81dac74d..b7fcd4421 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/network/MatteryNetworking.java +++ b/src/main/java/ru/dbotthepony/mc/otm/network/MatteryNetworking.java @@ -7,6 +7,7 @@ import net.minecraftforge.network.NetworkRegistry; import net.minecraftforge.network.PacketDistributor; import net.minecraftforge.network.simple.SimpleChannel; import ru.dbotthepony.mc.otm.OverdriveThatMatters; +import ru.dbotthepony.mc.otm.block.entity.EnergyCounterPacket; import ru.dbotthepony.mc.otm.menu.MenuDriveViewer; import ru.dbotthepony.mc.otm.menu.data.*; import ru.dbotthepony.mc.otm.network.android.*; @@ -221,5 +222,14 @@ public class MatteryNetworking { MenuDriveViewer.FilterSetPacket::play, Optional.of(NetworkDirection.PLAY_TO_SERVER) ); + + CHANNEL.registerMessage( + next_network_id++, + EnergyCounterPacket.class, + EnergyCounterPacket::write, + EnergyCounterPacket.Companion::read, + EnergyCounterPacket::play, + Optional.of(NetworkDirection.PLAY_TO_CLIENT) + ); } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/BlockEnergyCounter.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/BlockEnergyCounter.kt index e656388a0..0f9ece5de 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/BlockEnergyCounter.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/BlockEnergyCounter.kt @@ -29,9 +29,12 @@ class BlockEnergyCounter : BlockMattery(), EntityBlock { blockState: BlockState, blockEntityType: BlockEntityType ): BlockEntityTicker? { - if (level.isClientSide || blockEntityType !== Registry.BlockEntities.ENERGY_COUNTER) + if (blockEntityType !== Registry.BlockEntities.ENERGY_COUNTER) return null + if (level.isClientSide) + return BlockEntityTicker { _, _, _, tile -> if (tile is BlockEntityEnergyCounter) tile.clientTick() } + return BlockEntityTicker { _, _, _, tile -> if (tile is BlockEntityEnergyCounter) tile.tick() } } @@ -49,10 +52,6 @@ class BlockEnergyCounter : BlockMattery(), EntityBlock { } } - if ((inputDir === Direction.WEST || inputDir === Direction.EAST) && (dir === Direction.UP || dir === Direction.DOWN)) { - dir = dir.opposite - } - return defaultBlockState().setValue(INPUT_DIRECTION, inputDir).setValue(IF_DIRECTION, dir!!) } @@ -96,8 +95,8 @@ class BlockEnergyCounter : BlockMattery(), EntityBlock { shape = shape.rotateInv(iface) } else if (input === Direction.EAST || input === Direction.WEST) { when (iface) { - Direction.DOWN -> shape = shape.rotateAroundX(-Math.PI / 2) - Direction.UP -> shape = shape.rotateAroundX(Math.PI / 2) + Direction.DOWN -> shape = shape.rotateAroundX(Math.PI / 2) + Direction.UP -> shape = shape.rotateAroundX(-Math.PI / 2) Direction.NORTH -> { /* уже в нужном положении */ } Direction.SOUTH -> shape = shape.rotateAroundX(Math.PI) Direction.WEST -> { /* недостижимо */ } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BlockEntityEnergyCounter.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BlockEntityEnergyCounter.kt index 09503a360..de63a6613 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BlockEntityEnergyCounter.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BlockEntityEnergyCounter.kt @@ -1,11 +1,13 @@ package ru.dbotthepony.mc.otm.block.entity +import net.minecraft.client.Minecraft import net.minecraft.core.BlockPos import net.minecraft.core.Direction import net.minecraft.nbt.ByteArrayTag import net.minecraft.nbt.CompoundTag import net.minecraft.nbt.IntTag import net.minecraft.nbt.ListTag +import net.minecraft.network.FriendlyByteBuf import net.minecraft.network.chat.Component import net.minecraft.network.chat.TranslatableComponent import net.minecraft.server.level.ServerLevel @@ -18,6 +20,8 @@ import net.minecraftforge.common.capabilities.Capability import net.minecraftforge.common.util.LazyOptional import net.minecraftforge.energy.CapabilityEnergy import net.minecraftforge.energy.IEnergyStorage +import net.minecraftforge.network.NetworkEvent +import net.minecraftforge.network.PacketDistributor import ru.dbotthepony.mc.otm.* import ru.dbotthepony.mc.otm.block.BlockEnergyCounter import ru.dbotthepony.mc.otm.capability.IMatteryEnergyStorage @@ -26,19 +30,60 @@ import ru.dbotthepony.mc.otm.capability.extractEnergy import ru.dbotthepony.mc.otm.capability.receiveEnergy import ru.dbotthepony.mc.otm.core.Fraction import ru.dbotthepony.mc.otm.menu.MenuEnergyCounter +import ru.dbotthepony.mc.otm.network.MatteryNetworking import java.lang.ref.WeakReference +import java.util.function.Supplier + +data class EnergyCounterPacket(val pos: BlockPos, val thisTick: Fraction, val total: Fraction, val index: Int, val value: Fraction) { + fun write(buff: FriendlyByteBuf) { + buff.writeBlockPos(pos) + thisTick.write(buff) + total.write(buff) + buff.writeInt(index) + value.write(buff) + } + + fun play(context: Supplier) { + context.get().packetHandled = true + + context.get().enqueueWork { + val ply = Minecraft.getInstance().player ?: return@enqueueWork + val level = ply.level ?: return@enqueueWork + val tile = level.getBlockEntity(pos) as? BlockEntityEnergyCounter ?: return@enqueueWork + + tile.lastTick = thisTick + tile.passed = total + tile[index] = value + } + } + + companion object { + fun read(buff: FriendlyByteBuf): EnergyCounterPacket { + val pos = buff.readBlockPos() + val thisTick = Fraction.read(buff) + val total = Fraction.read(buff) + val index = buff.readInt() + val value = Fraction.read(buff) + return EnergyCounterPacket(pos, thisTick, total, index, value) + } + } +} class BlockEntityEnergyCounter(p_155229_: BlockPos, p_155230_: BlockState) : BlockEntityMattery(Registry.BlockEntities.ENERGY_COUNTER, p_155229_, p_155230_) { var passed = Fraction.ZERO - private set + internal set private val history = Array(10 * 20) { Fraction.ZERO } private var historyTick = 0 fun size() = history.size operator fun get(i: Int) = history[i] + internal operator fun set(i: Int, value: Fraction) { + history[i] = value + } + var lastTick: Fraction = Fraction.ZERO - private set + internal set fun getHistory(ticks: Int): Array { require(!(ticks < 1 || ticks >= history.size)) { "Invalid history length provided" } @@ -241,6 +286,33 @@ class BlockEntityEnergyCounter(p_155229_: BlockPos, p_155230_: BlockState) : Blo return Fraction.ZERO } + override val missingPower: Fraction + get() { + if (is_input) { + if (outputCapability.isPresent) { + val it = outputCapability.resolve().get() + + if (it is IMatteryEnergyStorage) { + return it.missingPower + } + + return Fraction((it.maxEnergyStored - it.energyStored).coerceAtLeast(0)) + } + } else { + if (inputCapability.isPresent) { + val it = inputCapability.resolve().get() + + if (it is IMatteryEnergyStorage) { + return it.missingPower + } + + return Fraction((it.maxEnergyStored - it.energyStored).coerceAtLeast(0)) + } + } + + return Fraction.ZERO + } + override fun canExtract() = !is_input override fun canReceive() = is_input } @@ -339,10 +411,25 @@ class BlockEntityEnergyCounter(p_155229_: BlockPos, p_155230_: BlockState) : Blo return super.getCapability(cap, side) } + private fun distributor(): PacketDistributor.TargetPoint { + val x = blockPos.x.toDouble() + val y = blockPos.y.toDouble() + val z = blockPos.z.toDouble() + return PacketDistributor.TargetPoint(x, y, z, 32.0, level!!.dimension()) + } + fun tick() { lastTick = history[historyTick] + val index = historyTick historyTick = (historyTick + 1) % history.size + val accumulated = history[historyTick] history[historyTick] = Fraction.ZERO + + MatteryNetworking.CHANNEL.send(PacketDistributor.NEAR.with(this::distributor), EnergyCounterPacket(blockPos, lastTick, passed, index, accumulated)) + } + + fun clientTick() { + passed += lastTick } companion object { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/EnergyCounterRenderer.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/EnergyCounterRenderer.kt new file mode 100644 index 000000000..cf123334d --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/EnergyCounterRenderer.kt @@ -0,0 +1,71 @@ +package ru.dbotthepony.mc.otm.client.render + +import com.mojang.blaze3d.vertex.PoseStack +import net.minecraft.client.Minecraft +import net.minecraft.client.renderer.MultiBufferSource +import net.minecraft.client.renderer.blockentity.BlockEntityRenderer +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider +import net.minecraft.core.Direction +import net.minecraft.network.chat.TranslatableComponent +import ru.dbotthepony.mc.otm.block.BlockEnergyCounter +import ru.dbotthepony.mc.otm.block.entity.BlockEntityEnergyCounter +import ru.dbotthepony.mc.otm.core.asAngle +import ru.dbotthepony.mc.otm.core.times +import ru.dbotthepony.mc.otm.menu.FormattingHelper +import kotlin.math.PI + +class EnergyCounterRenderer(private val context: BlockEntityRendererProvider.Context) : BlockEntityRenderer { + override fun render( + tile: BlockEntityEnergyCounter, + p_112308_: Float, + poseStack: PoseStack, + p_112310_: MultiBufferSource, + p_112311_: Int, + p_112312_: Int + ) { + val screenDir: Direction = tile.blockState.getValue(BlockEnergyCounter.IF_DIRECTION) + val inputDir: Direction = tile.blockState.getValue(BlockEnergyCounter.INPUT_DIRECTION) + + poseStack.pushPose() + poseStack.translate(0.5, 0.5, 0.5) + poseStack.translate(screenDir.normal * 0.44) + + val font = Minecraft.getInstance().font + + poseStack.scale(0.01f, 0.01f, 0.01f) + + if (screenDir === Direction.DOWN) { + poseStack.rotateAroundPoint(poseStack.translation(), inputDir.asAngle().copy(pitch = PI, roll = PI / 2)) + } else if (screenDir === Direction.UP) { + poseStack.rotateAroundPoint(poseStack.translation(), inputDir.asAngle().copy(pitch = 0.0, roll = PI / 2)) + } else { + poseStack.rotateAroundPoint(poseStack.translation(), screenDir.asAngle().copy(pitch = PI)) + } + + var y = -16f + + val finalX = font.drawAligned(poseStack, "00000000", TextAlign.CENTER_CENTER, -4f, y, 0x2C2C2C) + font.drawAligned(poseStack, "00000000", TextAlign.CENTER_CENTER, -4f, y + font.lineHeight, 0x2C2C2C) + font.drawAligned(poseStack, "/t", TextAlign.CENTER_LEFT, finalX.toFloat(), y, 0x2C2C2C) + font.drawAligned(poseStack, "/s", TextAlign.CENTER_LEFT, finalX.toFloat(), y + font.lineHeight, 0x2C2C2C) + + poseStack.pushPose() + poseStack.translate(-0.1, -0.1, -0.1) + font.drawAligned(poseStack, tile.lastTick.decimalString(0), TextAlign.CENTER_RIGHT, finalX.toFloat(), y, 0xFFFFFF) + font.drawAligned(poseStack, tile.sumHistory(20).decimalString(0), TextAlign.CENTER_RIGHT, finalX.toFloat(), y + font.lineHeight, 0xFFFFFF) + poseStack.popPose() + + y += font.lineHeight * 3 + + font.drawAligned(poseStack, TOTAL, TextAlign.CENTER_CENTER, 0f, y, 0xFFFFFF) + font.drawAligned(poseStack, FormattingHelper.formatPower(tile.passed), TextAlign.CENTER_CENTER, 0f, y + font.lineHeight, 0xFFFFFF) + + poseStack.popPose() + } + + override fun getViewDistance() = 32 + + companion object { + private val TOTAL = TranslatableComponent("otm.gui.total_raw") + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/Ext.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/Ext.kt index 977b3c5f9..7c9c211d4 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/Ext.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/Ext.kt @@ -5,6 +5,7 @@ import com.mojang.blaze3d.vertex.VertexConsumer import com.mojang.math.Matrix4f import com.mojang.math.Vector3f import net.minecraft.client.gui.Font +import net.minecraft.core.Vec3i import net.minecraft.network.chat.Component import net.minecraft.util.FormattedCharSequence import ru.dbotthepony.mc.otm.core.* @@ -14,6 +15,7 @@ fun VertexConsumer.vertex(matrix4f: Matrix4f, vector: Vector) = vertex(matrix4f, fun VertexConsumer.color(color: RGBAColor) = color(color.r, color.g, color.b, color.a) fun PoseStack.translate(vector: Vector) = translate(vector.x, vector.y, vector.z) +fun PoseStack.translate(vector: Vec3i) = translate(vector.x.toDouble(), vector.y.toDouble(), vector.z.toDouble()) fun PoseStack.translate(vector: Vector3f) = last().pose().multiplyWithTranslation(vector.x(), vector.y(), vector.z()) fun PoseStack.rotateAroundPoint(point: Vector, axis: Vector, rotation: Float, isDegrees: Boolean = false) { @@ -117,3 +119,362 @@ fun Font.drawAligned(poseStack: PoseStack, text: Component, align: TextAlign, x: fun Font.drawAligned(poseStack: PoseStack, text: FormattedCharSequence, align: TextAlign, x: Float, y: Float, color: RGBAColor): Int { return drawAligned(poseStack, text, align, x, y, color.toInt()) } + +fun Font.drawAlignedLines(poseStack: PoseStack, text: List, align: TextAlign, x: Float, y: Float, color: Int) { + var totalWidth = 0 + var height = 0 + + for (line in text) { + var accumulate = 0 + + when (line) { + is Component -> { + accumulate += width(line) + height += lineHeight + } + + is String -> { + accumulate += width(line) + height += lineHeight + } + + is FormattedCharSequence -> { + accumulate += width(line) + height += lineHeight + } + + else -> height += lineHeight + } + + totalWidth = totalWidth.coerceAtLeast(accumulate) + } + + if (height == 0 || totalWidth == 0) { + return + } + + var y = y + + when (align) { + TextAlign.TOP_LEFT -> { + for (line in text) { + when (line) { + is Component -> draw(poseStack, line, x, y, color) + is String -> draw(poseStack, line, x, y, color) + is FormattedCharSequence -> draw(poseStack, line, x, y, color) + } + + y += lineHeight + } + } + + TextAlign.TOP_CENTER -> { + for (line in text) { + when (line) { + is Component -> draw(poseStack, line, x - width(line) / 2f, y, color) + is String -> draw(poseStack, line, x - width(line) / 2f, y, color) + is FormattedCharSequence -> draw(poseStack, line, x - width(line) / 2f, y, color) + } + + y += lineHeight + } + } + + TextAlign.TOP_RIGHT -> { + for (line in text) { + when (line) { + is Component -> draw(poseStack, line, x - width(line), y, color) + is String -> draw(poseStack, line, x - width(line), y, color) + is FormattedCharSequence -> draw(poseStack, line, x - width(line), y, color) + } + + y += lineHeight + } + } + + TextAlign.CENTER_LEFT -> { + for (line in text) { + when (line) { + is Component -> draw(poseStack, line, x, y - height / 2f, color) + is String -> draw(poseStack, line, x, y - height / 2f, color) + is FormattedCharSequence -> draw(poseStack, line, x, y - height / 2f, color) + } + + y += lineHeight + } + } + + TextAlign.CENTER_CENTER -> { + for (line in text) { + when (line) { + is Component -> draw(poseStack, line, x - width(line) / 2f, y - height / 2f, color) + is String -> draw(poseStack, line, x - width(line) / 2f, y - height / 2f, color) + is FormattedCharSequence -> draw(poseStack, line, x - width(line) / 2f, y - height / 2f, color) + } + + y += lineHeight + } + } + + TextAlign.CENTER_RIGHT -> { + for (line in text) { + when (line) { + is Component -> draw(poseStack, line, x - width(line), y - height / 2f, color) + is String -> draw(poseStack, line, x - width(line), y - height / 2f, color) + is FormattedCharSequence -> draw(poseStack, line, x - width(line), y - height / 2f, color) + } + + y += lineHeight + } + } + + TextAlign.BOTTOM_LEFT -> { + for (line in text) { + when (line) { + is Component -> draw(poseStack, line, x, y - height, color) + is String -> draw(poseStack, line, x, y - height, color) + is FormattedCharSequence -> draw(poseStack, line, x, y - height, color) + } + + y += lineHeight + } + } + + TextAlign.BOTTOM_CENTER -> { + for (line in text) { + when (line) { + is Component -> draw(poseStack, line, x - width(line) / 2f, y - height, color) + is String -> draw(poseStack, line, x - width(line) / 2f, y - height, color) + is FormattedCharSequence -> draw(poseStack, line, x - width(line) / 2f, y - height, color) + } + + y += lineHeight + } + } + + TextAlign.BOTTOM_RIGHT -> { + for (line in text) { + when (line) { + is Component -> draw(poseStack, line, x - width(line), y - height, color) + is String -> draw(poseStack, line, x - width(line), y - height, color) + is FormattedCharSequence -> draw(poseStack, line, x - width(line), y - height, color) + } + + y += lineHeight + } + } + } +} + +fun Font.drawAlignedStripe(poseStack: PoseStack, text: List, align: TextAlign, x: Float, y: Float, color: Int) { + var totalWidth = 0 + + for (line in text) { + totalWidth += when (line) { + is Component -> { + width(line) + } + + is String -> { + width(line) + } + + is FormattedCharSequence -> { + width(line) + } + + else -> throw IllegalArgumentException("Invalid stripe value ${line}") + } + } + + if (totalWidth == 0) { + return + } + + var x = x + + when (align) { + TextAlign.TOP_LEFT -> { + for (line in text) { + when (line) { + is Component -> { + draw(poseStack, line, x, y, color) + x += width(line) + } + is String -> { + draw(poseStack, line, x, y, color) + x += width(line) + } + is FormattedCharSequence -> { + draw(poseStack, line, x, y, color) + x += width(line) + } + } + } + } + + TextAlign.TOP_CENTER -> { + x += totalWidth / 2f + + for (line in text) { + when (line) { + is Component -> { + draw(poseStack, line, x, y, color) + x -= width(line) + } + is String -> { + draw(poseStack, line, x, y, color) + x -= width(line) + } + is FormattedCharSequence -> { + draw(poseStack, line, x, y, color) + x -= width(line) + } + } + } + } + + TextAlign.TOP_RIGHT -> { + x += totalWidth + + for (line in text) { + when (line) { + is Component -> { + draw(poseStack, line, x, y, color) + x -= width(line) + } + is String -> { + draw(poseStack, line, x, y, color) + x -= width(line) + } + is FormattedCharSequence -> { + draw(poseStack, line, x, y, color) + x -= width(line) + } + } + } + } + + TextAlign.CENTER_LEFT -> { + for (line in text) { + when (line) { + is Component -> { + draw(poseStack, line, x, y - lineHeight / 2f, color) + x += width(line) + } + is String -> { + draw(poseStack, line, x, y - lineHeight / 2f, color) + x += width(line) + } + is FormattedCharSequence -> { + draw(poseStack, line, x, y - lineHeight / 2f, color) + x += width(line) + } + } + } + } + + TextAlign.CENTER_CENTER -> { + x += totalWidth / 2f + + for (line in text) { + when (line) { + is Component -> { + draw(poseStack, line, x, y - lineHeight / 2f, color) + x -= width(line) + } + is String -> { + draw(poseStack, line, x, y - lineHeight / 2f, color) + x -= width(line) + } + is FormattedCharSequence -> { + draw(poseStack, line, x, y - lineHeight / 2f, color) + x -= width(line) + } + } + } + } + + TextAlign.CENTER_RIGHT -> { + x += totalWidth + + for (line in text) { + when (line) { + is Component -> { + draw(poseStack, line, x, y - lineHeight / 2f, color) + x -= width(line) + } + is String -> { + draw(poseStack, line, x, y - lineHeight / 2f, color) + x -= width(line) + } + is FormattedCharSequence -> { + draw(poseStack, line, x, y - lineHeight / 2f, color) + x -= width(line) + } + } + } + } + + TextAlign.BOTTOM_LEFT -> { + for (line in text) { + when (line) { + is Component -> { + draw(poseStack, line, x, y - lineHeight, color) + x += width(line) + } + is String -> { + draw(poseStack, line, x, y - lineHeight, color) + x += width(line) + } + is FormattedCharSequence -> { + draw(poseStack, line, x, y - lineHeight, color) + x += width(line) + } + } + } + } + + TextAlign.BOTTOM_CENTER -> { + x += totalWidth / 2f + + for (line in text) { + when (line) { + is Component -> { + draw(poseStack, line, x, y - lineHeight, color) + x -= width(line) + } + is String -> { + draw(poseStack, line, x, y - lineHeight, color) + x -= width(line) + } + is FormattedCharSequence -> { + draw(poseStack, line, x, y - lineHeight, color) + x -= width(line) + } + } + } + } + + TextAlign.BOTTOM_RIGHT -> { + x += totalWidth + + for (line in text) { + when (line) { + is Component -> { + draw(poseStack, line, x, y - lineHeight, color) + x -= width(line) + } + is String -> { + draw(poseStack, line, x, y - lineHeight, color) + x -= width(line) + } + is FormattedCharSequence -> { + draw(poseStack, line, x, y - lineHeight, color) + x -= width(line) + } + } + } + } + } +} diff --git a/src/main/resources/assets/overdrive_that_matters/lang/en_us.json b/src/main/resources/assets/overdrive_that_matters/lang/en_us.json index e3d36c8f6..77aa69d9c 100644 --- a/src/main/resources/assets/overdrive_that_matters/lang/en_us.json +++ b/src/main/resources/assets/overdrive_that_matters/lang/en_us.json @@ -24,6 +24,8 @@ "otm.gui.progress_widget": "Progress: %s%%", "otm.gui.progress_widget_stuck": "The machine can not work, check configuration", + "otm.gui.total_raw": "Total:", + "otm.gui.matter.percentage_level": "Matter level: %s%%", "otm.gui.matter.format": "Matter: %s", "otm.gui.matter.name": "MtU", @@ -142,6 +144,25 @@ "otm.suffix.zepto": "%s z%s", "otm.suffix.yocto": "%s y%s", + "otm.suffix_raw.kilo": "k", + "otm.suffix_raw.mega": "M", + "otm.suffix_raw.giga": "G", + "otm.suffix_raw.tera": "T", + "otm.suffix_raw.peta": "P", + "otm.suffix_raw.exa": "E", + "otm.suffix_raw.zetta": "Z", + "otm.suffix_raw.yotta": "Y", + "otm.suffix_raw.deci": "d", + "otm.suffix_raw.centi": "c", + "otm.suffix_raw.milli": "m", + "otm.suffix_raw.micro": "μ", + "otm.suffix_raw.nano": "n", + "otm.suffix_raw.pico": "p", + "otm.suffix_raw.femto": "f", + "otm.suffix_raw.atto": "a", + "otm.suffix_raw.zepto": "z", + "otm.suffix_raw.yocto": "y", + "death.attack.otm_become_android": "%1$s lost their humanity", "death.attack.otm_become_humane": "%1$s regained their humanity", "death.attack.otm_event_horizon": "%1$s never crossed event horizon",