Added energy counter in-world render
This commit is contained in:
parent
5ff3771f81
commit
6cd04682d7
@ -261,9 +261,9 @@ object DataGen {
|
|||||||
val mdl = if (dir === Direction.WEST) west else east
|
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).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(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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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.BlockEntityExplosionDebugger;
|
||||||
import ru.dbotthepony.mc.otm.block.entity.blackhole.BlockEntitySphereDebugger;
|
import ru.dbotthepony.mc.otm.block.entity.blackhole.BlockEntitySphereDebugger;
|
||||||
import ru.dbotthepony.mc.otm.client.render.BlackHoleRenderer;
|
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.GravitationStabilizerRenderer;
|
||||||
import ru.dbotthepony.mc.otm.client.render.SkinElement;
|
import ru.dbotthepony.mc.otm.client.render.SkinElement;
|
||||||
import ru.dbotthepony.mc.otm.core.Fraction;
|
import ru.dbotthepony.mc.otm.core.Fraction;
|
||||||
@ -1007,6 +1008,7 @@ public class Registry {
|
|||||||
public static void registerRenderers(final FMLClientSetupEvent event) {
|
public static void registerRenderers(final FMLClientSetupEvent event) {
|
||||||
BlockEntityRenderers.register(BLACK_HOLE, BlackHoleRenderer::new);
|
BlockEntityRenderers.register(BLACK_HOLE, BlackHoleRenderer::new);
|
||||||
BlockEntityRenderers.register(GRAVITATION_STABILIZER, GravitationStabilizerRenderer::new);
|
BlockEntityRenderers.register(GRAVITATION_STABILIZER, GravitationStabilizerRenderer::new);
|
||||||
|
BlockEntityRenderers.register(ENERGY_COUNTER, EnergyCounterRenderer::new);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,10 +12,83 @@ import javax.annotation.ParametersAreNonnullByDefault;
|
|||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.math.RoundingMode;
|
import java.math.RoundingMode;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@MethodsReturnNonnullByDefault
|
@MethodsReturnNonnullByDefault
|
||||||
@ParametersAreNonnullByDefault
|
@ParametersAreNonnullByDefault
|
||||||
public class FormattingHelper {
|
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<TranslatableComponent> 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<TranslatableComponent> 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<TranslatableComponent> BIG_SUFFIX_STRIPE_INV;
|
||||||
|
public static final List<TranslatableComponent> SMALL_SUFFIX_STRIPE_INV;
|
||||||
|
|
||||||
|
static {
|
||||||
|
var list = new ArrayList<TranslatableComponent>(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<TranslatableComponent>(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[] {
|
public static final String[] SUFFIX_COMPONENTS_ABOVE_ONE = new String[] {
|
||||||
"otm.suffix.kilo",
|
"otm.suffix.kilo",
|
||||||
"otm.suffix.mega",
|
"otm.suffix.mega",
|
||||||
|
@ -7,6 +7,7 @@ import net.minecraftforge.network.NetworkRegistry;
|
|||||||
import net.minecraftforge.network.PacketDistributor;
|
import net.minecraftforge.network.PacketDistributor;
|
||||||
import net.minecraftforge.network.simple.SimpleChannel;
|
import net.minecraftforge.network.simple.SimpleChannel;
|
||||||
import ru.dbotthepony.mc.otm.OverdriveThatMatters;
|
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.MenuDriveViewer;
|
||||||
import ru.dbotthepony.mc.otm.menu.data.*;
|
import ru.dbotthepony.mc.otm.menu.data.*;
|
||||||
import ru.dbotthepony.mc.otm.network.android.*;
|
import ru.dbotthepony.mc.otm.network.android.*;
|
||||||
@ -221,5 +222,14 @@ public class MatteryNetworking {
|
|||||||
MenuDriveViewer.FilterSetPacket::play,
|
MenuDriveViewer.FilterSetPacket::play,
|
||||||
Optional.of(NetworkDirection.PLAY_TO_SERVER)
|
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)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,9 +29,12 @@ class BlockEnergyCounter : BlockMattery(), EntityBlock {
|
|||||||
blockState: BlockState,
|
blockState: BlockState,
|
||||||
blockEntityType: BlockEntityType<T>
|
blockEntityType: BlockEntityType<T>
|
||||||
): BlockEntityTicker<T>? {
|
): BlockEntityTicker<T>? {
|
||||||
if (level.isClientSide || blockEntityType !== Registry.BlockEntities.ENERGY_COUNTER)
|
if (blockEntityType !== Registry.BlockEntities.ENERGY_COUNTER)
|
||||||
return null
|
return null
|
||||||
|
|
||||||
|
if (level.isClientSide)
|
||||||
|
return BlockEntityTicker { _, _, _, tile -> if (tile is BlockEntityEnergyCounter) tile.clientTick() }
|
||||||
|
|
||||||
return BlockEntityTicker { _, _, _, tile -> if (tile is BlockEntityEnergyCounter) tile.tick() }
|
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!!)
|
return defaultBlockState().setValue(INPUT_DIRECTION, inputDir).setValue(IF_DIRECTION, dir!!)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,8 +95,8 @@ class BlockEnergyCounter : BlockMattery(), EntityBlock {
|
|||||||
shape = shape.rotateInv(iface)
|
shape = shape.rotateInv(iface)
|
||||||
} else if (input === Direction.EAST || input === Direction.WEST) {
|
} else if (input === Direction.EAST || input === Direction.WEST) {
|
||||||
when (iface) {
|
when (iface) {
|
||||||
Direction.DOWN -> shape = shape.rotateAroundX(-Math.PI / 2)
|
Direction.DOWN -> shape = shape.rotateAroundX(Math.PI / 2)
|
||||||
Direction.UP -> shape = shape.rotateAroundX(Math.PI / 2)
|
Direction.UP -> shape = shape.rotateAroundX(-Math.PI / 2)
|
||||||
Direction.NORTH -> { /* уже в нужном положении */ }
|
Direction.NORTH -> { /* уже в нужном положении */ }
|
||||||
Direction.SOUTH -> shape = shape.rotateAroundX(Math.PI)
|
Direction.SOUTH -> shape = shape.rotateAroundX(Math.PI)
|
||||||
Direction.WEST -> { /* недостижимо */ }
|
Direction.WEST -> { /* недостижимо */ }
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
package ru.dbotthepony.mc.otm.block.entity
|
package ru.dbotthepony.mc.otm.block.entity
|
||||||
|
|
||||||
|
import net.minecraft.client.Minecraft
|
||||||
import net.minecraft.core.BlockPos
|
import net.minecraft.core.BlockPos
|
||||||
import net.minecraft.core.Direction
|
import net.minecraft.core.Direction
|
||||||
import net.minecraft.nbt.ByteArrayTag
|
import net.minecraft.nbt.ByteArrayTag
|
||||||
import net.minecraft.nbt.CompoundTag
|
import net.minecraft.nbt.CompoundTag
|
||||||
import net.minecraft.nbt.IntTag
|
import net.minecraft.nbt.IntTag
|
||||||
import net.minecraft.nbt.ListTag
|
import net.minecraft.nbt.ListTag
|
||||||
|
import net.minecraft.network.FriendlyByteBuf
|
||||||
import net.minecraft.network.chat.Component
|
import net.minecraft.network.chat.Component
|
||||||
import net.minecraft.network.chat.TranslatableComponent
|
import net.minecraft.network.chat.TranslatableComponent
|
||||||
import net.minecraft.server.level.ServerLevel
|
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.common.util.LazyOptional
|
||||||
import net.minecraftforge.energy.CapabilityEnergy
|
import net.minecraftforge.energy.CapabilityEnergy
|
||||||
import net.minecraftforge.energy.IEnergyStorage
|
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.*
|
||||||
import ru.dbotthepony.mc.otm.block.BlockEnergyCounter
|
import ru.dbotthepony.mc.otm.block.BlockEnergyCounter
|
||||||
import ru.dbotthepony.mc.otm.capability.IMatteryEnergyStorage
|
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.capability.receiveEnergy
|
||||||
import ru.dbotthepony.mc.otm.core.Fraction
|
import ru.dbotthepony.mc.otm.core.Fraction
|
||||||
import ru.dbotthepony.mc.otm.menu.MenuEnergyCounter
|
import ru.dbotthepony.mc.otm.menu.MenuEnergyCounter
|
||||||
|
import ru.dbotthepony.mc.otm.network.MatteryNetworking
|
||||||
import java.lang.ref.WeakReference
|
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<NetworkEvent.Context>) {
|
||||||
|
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_) {
|
class BlockEntityEnergyCounter(p_155229_: BlockPos, p_155230_: BlockState) : BlockEntityMattery(Registry.BlockEntities.ENERGY_COUNTER, p_155229_, p_155230_) {
|
||||||
var passed = Fraction.ZERO
|
var passed = Fraction.ZERO
|
||||||
private set
|
internal set
|
||||||
|
|
||||||
private val history = Array(10 * 20) { Fraction.ZERO }
|
private val history = Array(10 * 20) { Fraction.ZERO }
|
||||||
private var historyTick = 0
|
private var historyTick = 0
|
||||||
|
|
||||||
fun size() = history.size
|
fun size() = history.size
|
||||||
operator fun get(i: Int) = history[i]
|
operator fun get(i: Int) = history[i]
|
||||||
|
internal operator fun set(i: Int, value: Fraction) {
|
||||||
|
history[i] = value
|
||||||
|
}
|
||||||
|
|
||||||
var lastTick: Fraction = Fraction.ZERO
|
var lastTick: Fraction = Fraction.ZERO
|
||||||
private set
|
internal set
|
||||||
|
|
||||||
fun getHistory(ticks: Int): Array<Fraction> {
|
fun getHistory(ticks: Int): Array<Fraction> {
|
||||||
require(!(ticks < 1 || ticks >= history.size)) { "Invalid history length provided" }
|
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
|
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 canExtract() = !is_input
|
||||||
override fun canReceive() = 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)
|
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() {
|
fun tick() {
|
||||||
lastTick = history[historyTick]
|
lastTick = history[historyTick]
|
||||||
|
val index = historyTick
|
||||||
historyTick = (historyTick + 1) % history.size
|
historyTick = (historyTick + 1) % history.size
|
||||||
|
val accumulated = history[historyTick]
|
||||||
history[historyTick] = Fraction.ZERO
|
history[historyTick] = Fraction.ZERO
|
||||||
|
|
||||||
|
MatteryNetworking.CHANNEL.send(PacketDistributor.NEAR.with(this::distributor), EnergyCounterPacket(blockPos, lastTick, passed, index, accumulated))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun clientTick() {
|
||||||
|
passed += lastTick
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -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<BlockEntityEnergyCounter> {
|
||||||
|
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")
|
||||||
|
}
|
||||||
|
}
|
@ -5,6 +5,7 @@ import com.mojang.blaze3d.vertex.VertexConsumer
|
|||||||
import com.mojang.math.Matrix4f
|
import com.mojang.math.Matrix4f
|
||||||
import com.mojang.math.Vector3f
|
import com.mojang.math.Vector3f
|
||||||
import net.minecraft.client.gui.Font
|
import net.minecraft.client.gui.Font
|
||||||
|
import net.minecraft.core.Vec3i
|
||||||
import net.minecraft.network.chat.Component
|
import net.minecraft.network.chat.Component
|
||||||
import net.minecraft.util.FormattedCharSequence
|
import net.minecraft.util.FormattedCharSequence
|
||||||
import ru.dbotthepony.mc.otm.core.*
|
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 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: 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.translate(vector: Vector3f) = last().pose().multiplyWithTranslation(vector.x(), vector.y(), vector.z())
|
||||||
|
|
||||||
fun PoseStack.rotateAroundPoint(point: Vector, axis: Vector, rotation: Float, isDegrees: Boolean = false) {
|
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 {
|
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())
|
return drawAligned(poseStack, text, align, x, y, color.toInt())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Font.drawAlignedLines(poseStack: PoseStack, text: List<Any?>, 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<Any>, 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -24,6 +24,8 @@
|
|||||||
"otm.gui.progress_widget": "Progress: %s%%",
|
"otm.gui.progress_widget": "Progress: %s%%",
|
||||||
"otm.gui.progress_widget_stuck": "The machine can not work, check configuration",
|
"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.percentage_level": "Matter level: %s%%",
|
||||||
"otm.gui.matter.format": "Matter: %s",
|
"otm.gui.matter.format": "Matter: %s",
|
||||||
"otm.gui.matter.name": "MtU",
|
"otm.gui.matter.name": "MtU",
|
||||||
@ -142,6 +144,25 @@
|
|||||||
"otm.suffix.zepto": "%s z%s",
|
"otm.suffix.zepto": "%s z%s",
|
||||||
"otm.suffix.yocto": "%s y%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_android": "%1$s lost their humanity",
|
||||||
"death.attack.otm_become_humane": "%1$s regained their humanity",
|
"death.attack.otm_become_humane": "%1$s regained their humanity",
|
||||||
"death.attack.otm_event_horizon": "%1$s never crossed event horizon",
|
"death.attack.otm_event_horizon": "%1$s never crossed event horizon",
|
||||||
|
Loading…
Reference in New Issue
Block a user