Updated energy counter, move energy API to kotlin

This commit is contained in:
DBotThePony 2022-01-03 21:06:21 +07:00
parent bb17f93a91
commit 6c029b98b7
Signed by: DBot
GPG Key ID: DCC23B5715498507
14 changed files with 578 additions and 724 deletions

View File

@ -4,6 +4,7 @@ import net.minecraft.core.BlockPos
import net.minecraft.core.Direction
import net.minecraft.core.Vec3i
import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.ListTag
import net.minecraft.nbt.Tag
import java.util.function.Consumer
@ -47,7 +48,7 @@ inline fun CompoundTag.ifHas(s: String, type: Byte, consumer: (Tag) -> Unit) {
}
}
inline fun <T : Tag> CompoundTag.ifHas(s: String, type: Class<T>, consumer: (T) -> Unit) {
inline fun <reified T : Tag> CompoundTag.ifHas(s: String, type: Class<T>, consumer: (T) -> Unit) {
val tag = get(s)
if (tag != null && tag::class.java == type) {

View File

@ -1,74 +1,75 @@
package ru.dbotthepony.mc.otm.block;
package ru.dbotthepony.mc.otm.block
import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.EntityBlock;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityTicker;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.EnumProperty;
import ru.dbotthepony.mc.otm.Registry;
import ru.dbotthepony.mc.otm.block.entity.BlockEntityEnergyCounter;
import ru.dbotthepony.mc.otm.block.entity.BlockEntityMatterBottler;
import net.minecraft.core.BlockPos
import net.minecraft.core.Direction
import net.minecraft.world.item.context.BlockPlaceContext
import net.minecraft.world.level.Level
import net.minecraft.world.level.block.Block
import net.minecraft.world.level.block.EntityBlock
import net.minecraft.world.level.block.entity.BlockEntity
import net.minecraft.world.level.block.entity.BlockEntityTicker
import net.minecraft.world.level.block.entity.BlockEntityType
import net.minecraft.world.level.block.state.BlockState
import net.minecraft.world.level.block.state.StateDefinition
import net.minecraft.world.level.block.state.properties.EnumProperty
import ru.dbotthepony.mc.otm.Registry
import ru.dbotthepony.mc.otm.block.entity.BlockEntityEnergyCounter
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
@ParametersAreNonnullByDefault
@MethodsReturnNonnullByDefault
public class BlockEnergyCounter extends BlockMattery implements EntityBlock {
public static final EnumProperty<Direction> INPUT_DIRECTION = EnumProperty.create("input", Direction.class);
public static final EnumProperty<Direction> IF_DIRECTION = EnumProperty.create("if", Direction.class);
@Nullable
@Override
public BlockEntity newBlockEntity(BlockPos blockPos, BlockState blockState) {
return new BlockEntityEnergyCounter(blockPos, blockState);
class BlockEnergyCounter : BlockMattery(), EntityBlock {
override fun newBlockEntity(blockPos: BlockPos, blockState: BlockState): BlockEntity {
return BlockEntityEnergyCounter(blockPos, blockState)
}
@Nullable
@Override
public <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level p_153212_, BlockState p_153213_, BlockEntityType<T> p_153214_) {
return p_153212_.isClientSide || p_153214_ != Registry.BlockEntities.ENERGY_COUNTER ? null : BlockEntityEnergyCounter::tick;
override fun <T : BlockEntity?> getTicker(
level: Level,
blockState: BlockState,
blockEntityType: BlockEntityType<T>
): BlockEntityTicker<T>? {
if (level.isClientSide || blockEntityType !== Registry.BlockEntities.ENERGY_COUNTER)
return null
return BlockEntityTicker { _, _, _, tile -> if (tile is BlockEntityEnergyCounter) tile.tick() }
}
@Nullable
@Override
public BlockState getStateForPlacement(BlockPlaceContext context) {
final var input_direction = context.getPlayer() != null && context.getPlayer().isCrouching() ? context.getClickedFace().getOpposite() : context.getClickedFace();
final var opposite = input_direction.getOpposite();
override fun getStateForPlacement(context: BlockPlaceContext): BlockState? {
val inputDir =
if (context.player != null && context.player!!.isCrouching) context.clickedFace.opposite else context.clickedFace
Direction dir = null;
val opposite = inputDir.opposite
var dir: Direction? = null
for (var _dir : context.getNearestLookingDirections()) {
if (_dir != input_direction && _dir != opposite) {
dir = _dir.getOpposite();
break;
for (_dir in context.nearestLookingDirections) {
if (_dir != inputDir && _dir != opposite) {
dir = _dir.opposite
break
}
}
assert dir != null;
return defaultBlockState().setValue(INPUT_DIRECTION, input_direction).setValue(IF_DIRECTION, dir);
return defaultBlockState().setValue(INPUT_DIRECTION, inputDir).setValue(IF_DIRECTION, dir!!)
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> p_49915_) {
super.createBlockStateDefinition(p_49915_);
p_49915_.add(INPUT_DIRECTION, IF_DIRECTION);
override fun createBlockStateDefinition(p_49915_: StateDefinition.Builder<Block, BlockState>) {
super.createBlockStateDefinition(p_49915_)
p_49915_.add(INPUT_DIRECTION, IF_DIRECTION)
}
@Override
public void neighborChanged(BlockState state, Level level, BlockPos pos, Block sender, BlockPos sender_pos, boolean flag) {
super.neighborChanged(state, level, pos, sender, sender_pos, flag);
override fun neighborChanged(
state: BlockState,
level: Level,
pos: BlockPos,
sender: Block,
sender_pos: BlockPos,
flag: Boolean
) {
super.neighborChanged(state, level, pos, sender, sender_pos, flag)
if (!level.isClientSide && level.getBlockEntity(pos) instanceof BlockEntityEnergyCounter tile) {
tile.checkSurroundings(level);
if (!level.isClientSide) {
(level.getBlockEntity(pos) as? BlockEntityEnergyCounter)?.checkSurroundings(level)
}
}
companion object {
@JvmField val INPUT_DIRECTION: EnumProperty<Direction> = EnumProperty.create("input", Direction::class.java)
@JvmField val IF_DIRECTION: EnumProperty<Direction> = EnumProperty.create("if", Direction::class.java)
}
}

View File

@ -188,7 +188,7 @@ class BlockEntityBatteryBank(p_155229_: BlockPos, p_155230_: BlockState) : Block
return distributeEnergy(true, howMuch, simulate)
}
override fun getBatteryLevel(): Fraction {
override val batteryLevel: Fraction get() {
var result = Fraction.ZERO
for (i in 0 until container.containerSize) {
@ -208,7 +208,7 @@ class BlockEntityBatteryBank(p_155229_: BlockPos, p_155230_: BlockState) : Block
return result
}
override fun getMaxBatteryLevel(): Fraction {
override val maxBatteryLevel: Fraction get() {
var result = Fraction.ZERO
for (i in 0 until container.containerSize) {

View File

@ -29,10 +29,11 @@ import ru.dbotthepony.mc.otm.menu.ChemicalGeneratorMenu
import ru.dbotthepony.mc.otm.*
import ru.dbotthepony.mc.otm.block.BlockMatteryRotatable
import ru.dbotthepony.mc.otm.block.entity.worker.WorkerState
import ru.dbotthepony.mc.otm.capability.MatteryMachineEnergyStorage
import ru.dbotthepony.mc.otm.capability.receiveEnergy
import java.lang.ref.WeakReference
class BlockEntityChemicalGenerator(pos: BlockPos, state: BlockState) : BlockEntityMattery(Registry.BlockEntities.CHEMICAL_GENERATOR, pos, state), IMatteryEnergyStorage {
class BlockEntityChemicalGenerator(pos: BlockPos, state: BlockState) : BlockEntityMattery(Registry.BlockEntities.CHEMICAL_GENERATOR, pos, state) {
override fun getDefaultDisplayName(): Component {
return NAME
}
@ -42,13 +43,14 @@ class BlockEntityChemicalGenerator(pos: BlockPos, state: BlockState) : BlockEnti
}
private var valid = true
private var resolver = LazyOptional.of {this}
private var resolver = LazyOptional.of {energy}
@JvmField val energy = MatteryMachineEnergyStorage(this::setChangedLight, MatteryMachineEnergyStorage.MachineType.GENERATOR, MAX_ENERGY, THROUGHPUT)
override fun <T> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> {
if (valid && (cap == MatteryCapability.ENERGY || cap == CapabilityEnergy.ENERGY) && side != blockState.getValue(BlockMatteryRotatable.FACING))
if (valid && (cap === MatteryCapability.ENERGY || cap === CapabilityEnergy.ENERGY) && side !== blockState.getValue(BlockMatteryRotatable.FACING))
return resolver.cast()
if (valid && cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY)
if (valid && cap === CapabilityItemHandler.ITEM_HANDLER_CAPABILITY)
return itemHandler.get().cast()
return super.getCapability(cap, side)
@ -65,7 +67,7 @@ class BlockEntityChemicalGenerator(pos: BlockPos, state: BlockState) : BlockEnti
super.reviveCaps()
itemHandler.revive()
valid = true
resolver = LazyOptional.of {this}
resolver = LazyOptional.of {energy}
}
override fun setLevel(level: Level) {
@ -87,7 +89,7 @@ class BlockEntityChemicalGenerator(pos: BlockPos, state: BlockState) : BlockEnti
override fun saveAdditional(nbt: CompoundTag) {
super.saveAdditional(nbt)
nbt["energy"] = power.serializeNBT()
nbt["energy"] = energy.serializeNBT()
nbt["slots"] = container.serializeNBT()
nbt["working_ticks"] = workingTicks
nbt["working_ticks_total"] = workingTicksTotal
@ -96,8 +98,8 @@ class BlockEntityChemicalGenerator(pos: BlockPos, state: BlockState) : BlockEnti
override fun load(nbt: CompoundTag) {
super.load(nbt)
nbt.ifHas("energy") {
power = Fraction.deserializeNBT(it)
nbt.ifHas("energy", CompoundTag::class.java) {
energy.deserializeNBT(it)
}
nbt.ifHas("slots") {
@ -169,44 +171,6 @@ class BlockEntityChemicalGenerator(pos: BlockPos, state: BlockState) : BlockEnti
}
}
private var power = Fraction.ZERO
override fun extractEnergyOuter(howMuch: Fraction, simulate: Boolean): Fraction {
return extractEnergyInner(howMuch, simulate)
}
override fun extractEnergyInner(howMuch: Fraction, simulate: Boolean): Fraction {
val extracted = howMuch.min(THROUGHPUT, power)
if (!simulate && !extracted.isZero()) {
power -= extracted
check = true
setChangedLight()
}
return extracted
}
override fun receiveEnergyOuter(howMuch: Fraction, simulate: Boolean): Fraction {
return Fraction.ZERO
}
override fun receiveEnergyInner(howMuch: Fraction, simulate: Boolean): Fraction {
val new = (howMuch + power).min(MAX_ENERGY)
val diff = new - power
if (!simulate) {
power = new
setChangedLight()
}
return diff
}
override fun getBatteryLevel(): Fraction = power
override fun getMaxBatteryLevel(): Fraction = MAX_ENERGY
override fun canExtract(): Boolean = true
var workingTicks = 0
private set
@ -218,19 +182,19 @@ class BlockEntityChemicalGenerator(pos: BlockPos, state: BlockState) : BlockEnti
private fun workWithPower(it: IEnergyStorage) {
if (it is IMatteryEnergyStorage) {
val demand = it.missingPower
val extracted = extractEnergyInner(demand, true)
val extracted = energy.extractEnergyInner(demand, true)
val received = it.receiveEnergyOuter(extracted, false)
if (!received.isZero()) {
extractEnergyInner(received, false)
energy.extractEnergyInner(received, false)
}
} else {
val demand = it.receiveEnergy(THROUGHPUT_INT, true)
val extracted = extractEnergyInner(demand, true)
val extracted = energy.extractEnergyInner(demand, true)
val received = it.receiveEnergy(extracted, false)
if (received != 0) {
extractEnergyInner(received, false)
energy.extractEnergyInner(received, false)
}
}
}
@ -238,7 +202,7 @@ class BlockEntityChemicalGenerator(pos: BlockPos, state: BlockState) : BlockEnti
fun tick() {
if (workingTicks > 0 && !isBlockedByRedstone) {
workingTicks--
receiveEnergyInner(GENERATION_SPEED, false)
energy.receiveEnergyInner(GENERATION_SPEED, false)
if (workingTicks == 0) {
workingTicksTotal = 0
@ -256,7 +220,7 @@ class BlockEntityChemicalGenerator(pos: BlockPos, state: BlockState) : BlockEnti
if (!container.getItem(0).isEmpty) {
val ticks = ForgeHooks.getBurnTime(container.getItem(0), null)
if (ticks >= 4 && (batteryLevel < Fraction.ONE || GENERATION_SPEED * (ticks / 4) + batteryLevel <= maxBatteryLevel)) {
if (ticks >= 4 && (energy.batteryLevel < Fraction.ONE || GENERATION_SPEED * (ticks / 4) + energy.batteryLevel <= energy.maxBatteryLevel)) {
workingTicksTotal = ticks / 4
workingTicks = ticks / 4
container.getItem(0).shrink(1)
@ -266,13 +230,13 @@ class BlockEntityChemicalGenerator(pos: BlockPos, state: BlockState) : BlockEnti
check = false
}
if (power.isZero()) return
if (energy.batteryLevel.isZero()) return
val item = container.getItem(1)
if (!item.isEmpty) {
item.getCapability(CapabilityEnergy.ENERGY).ifPresent(this::workWithPower)
if (power.isZero()) return
if (energy.batteryLevel.isZero()) return
}
for (consumer in consumers) {

View File

@ -1,410 +1,349 @@
package ru.dbotthepony.mc.otm.block.entity;
package ru.dbotthepony.mc.otm.block.entity
import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.nbt.*;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.energy.CapabilityEnergy;
import net.minecraftforge.energy.IEnergyStorage;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import ru.dbotthepony.mc.otm.OverdriveThatMatters;
import ru.dbotthepony.mc.otm.Registry;
import ru.dbotthepony.mc.otm.block.BlockEnergyCounter;
import ru.dbotthepony.mc.otm.capability.IMatteryEnergyStorage;
import ru.dbotthepony.mc.otm.capability.MatteryCapability;
import ru.dbotthepony.mc.otm.core.Fraction;
import ru.dbotthepony.mc.otm.menu.EnergyCounterMenu;
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.chat.Component
import net.minecraft.network.chat.TranslatableComponent
import net.minecraft.server.level.ServerLevel
import net.minecraft.world.entity.player.Inventory
import net.minecraft.world.entity.player.Player
import net.minecraft.world.inventory.AbstractContainerMenu
import net.minecraft.world.level.Level
import net.minecraft.world.level.block.state.BlockState
import net.minecraftforge.common.capabilities.Capability
import net.minecraftforge.common.util.LazyOptional
import net.minecraftforge.energy.CapabilityEnergy
import net.minecraftforge.energy.IEnergyStorage
import ru.dbotthepony.mc.otm.*
import ru.dbotthepony.mc.otm.block.BlockEnergyCounter
import ru.dbotthepony.mc.otm.capability.IMatteryEnergyStorage
import ru.dbotthepony.mc.otm.capability.MatteryCapability
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.EnergyCounterMenu
import java.lang.ref.WeakReference
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import java.lang.ref.WeakReference;
import java.util.Arrays;
class BlockEntityEnergyCounter(p_155229_: BlockPos, p_155230_: BlockState) : BlockEntityMattery(Registry.BlockEntities.ENERGY_COUNTER, p_155229_, p_155230_) {
var passed = Fraction.ZERO
private set
@MethodsReturnNonnullByDefault
@ParametersAreNonnullByDefault
public class BlockEntityEnergyCounter extends BlockEntityMattery {
protected Fraction passed = Fraction.ZERO;
protected final Fraction[] history = new Fraction[10 * 20];
protected int history_tick = 0;
private val history = Array(10 * 20) { Fraction.ZERO }
private var historyTick = 0
public static <T extends BlockEntity> void tick(Level level, BlockPos blockPos, BlockState blockState, T t) {
if (t instanceof BlockEntityEnergyCounter tile) {
tile.history_tick = (tile.history_tick + 1) % tile.history.length;
tile.history[tile.history_tick] = Fraction.ZERO;
}
}
fun size() = history.size
operator fun get(i: Int) = history[i]
val lastTick: Fraction get() = history[historyTick]
public Fraction[] getHistory(int ticks) {
if (ticks < 1 || ticks >= history.length) {
throw new IllegalArgumentException("Invalid history length provided");
fun getHistory(ticks: Int): Array<Fraction> {
require(!(ticks < 1 || ticks >= history.size)) { "Invalid history length provided" }
val history = Array(ticks) { Fraction.ZERO }
for (i in 0 until ticks) {
var index = (historyTick - i) % this.history.size
if (index < 0) index += this.history.size
history[i] = this.history[index]
}
final var history = new Fraction[ticks];
return history
}
for (int i = 0; i < ticks; i++) {
int index = (history_tick - i) % this.history.length;
fun calcAverage(ticks: Int): Fraction {
return sumHistory(ticks) / ticks
}
if (index < 0)
index += this.history.length;
fun sumHistory(ticks: Int): Fraction {
require(!(ticks < 1 || ticks >= history.size)) { "Invalid history length provided" }
history[i] = this.history[index];
var value = Fraction.ZERO
for (i in 0 until ticks) {
var index = (historyTick - i) % history.size
if (index < 0) index += history.size
value += history[index]
}
return history;
return value
}
public Fraction calcAverage(int ticks) {
return sumHistory(ticks).div(ticks);
override fun saveAdditional(nbt: CompoundTag) {
super.saveAdditional(nbt)
nbt["passed"] = passed.serializeNBT()
val list = ListTag()
nbt["history"] = list
nbt["history_tick"] = historyTick
for (num in history)
list.add(num.serializeNBT())
}
public Fraction sumHistory(int ticks) {
if (ticks < 1 || ticks >= history.length) {
throw new IllegalArgumentException("Invalid history length provided");
override fun load(nbt: CompoundTag) {
super.load(nbt)
nbt.ifHas(("passed")) {
passed = Fraction.deserializeNBT(it)
}
var value = Fraction.ZERO;
for (int i = 0; i < ticks; i++) {
int index = (history_tick - i) % this.history.length;
if (index < 0)
index += this.history.length;
value = value.plus(history[index]);
nbt.ifHas(("history_tick"), IntTag::class.java) {
historyTick = it.asInt
}
return value;
}
public Fraction getPassed() {
return passed;
}
public BlockEntityEnergyCounter(BlockPos p_155229_, BlockState p_155230_) {
super(Registry.BlockEntities.ENERGY_COUNTER, p_155229_, p_155230_);
Arrays.fill(history, Fraction.ZERO);
}
@Override
public void saveAdditional(CompoundTag nbt) {
super.saveAdditional(nbt);
nbt.put("passed", passed.serializeNBT());
var list = new ListTag();
nbt.put("history", list);
nbt.putInt("history_tick", history_tick);
for (var num : history)
list.add(StringTag.valueOf(num.toString()));
}
private static final Logger LOGGER = LogManager.getLogger();
@Override
public void load(CompoundTag nbt) {
super.load(nbt);
if (nbt.contains("passed"))
passed = Fraction.deserializeNBT(nbt.get("passed"));
if (nbt.get("history_tick") instanceof IntTag tag)
history_tick = tag.getAsInt();
// TODO: старый формат данных, удалить на релизе
var list = nbt.getList("history", Tag.TAG_STRING);
for (int i = 0; i < list.size(); i++) {
try {
history[i] = Fraction.fromString(list.getString(i));
} catch(Throwable err) {
LOGGER.error(err);
}
}
// новый формат данных
list = nbt.getList("history", Tag.TAG_BYTE_ARRAY);
for (int i = 0; i < list.size(); i++) {
try {
history[i] = Fraction.fromString(list.getString(i));
} catch(Throwable err) {
LOGGER.error(err);
nbt.ifHas("history", ListTag::class.java) {
for (i in it.indices) {
val bytes = it[i] as? ByteArrayTag
history[i] = if (bytes != null) Fraction.deserializeNBT(bytes) else Fraction.ZERO
}
}
}
private static final TranslatableComponent NAME = new TranslatableComponent("block.overdrive_that_matters.energy_counter");
@Override
protected Component getDefaultDisplayName() {
return NAME;
override fun getDefaultDisplayName(): Component {
return NAME
}
@Nullable
@Override
public AbstractContainerMenu createMenu(int containerID, Inventory inventory, Player ply) {
return new EnergyCounterMenu(containerID, inventory, this);
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu {
return EnergyCounterMenu(containerID, inventory, this)
}
public final EnergyCounterCap input = new EnergyCounterCap(true);
public final EnergyCounterCap output = new EnergyCounterCap(false);
private val energyInput = EnergyCounterCap(true)
private val energyOutput = EnergyCounterCap(false)
protected LazyOptional<IMatteryEnergyStorage> input_cap_mte = LazyOptional.empty();
protected LazyOptional<IEnergyStorage> input_cap_fe = LazyOptional.empty();
protected LazyOptional<IMatteryEnergyStorage> output_cap_mte = LazyOptional.empty();
protected LazyOptional<IEnergyStorage> output_cap_fe = LazyOptional.empty();
private var inputCapability = LazyOptional.empty<IEnergyStorage>()
private var outputCapability = LazyOptional.empty<IEnergyStorage>()
@Override
public void setLevel(Level p_155231_) {
super.setLevel(p_155231_);
override fun setLevel(p_155231_: Level) {
super.setLevel(p_155231_)
if (p_155231_ instanceof ServerLevel level) {
OverdriveThatMatters.tickOnceSelf(level, this::checkSurroundings);
val level = level
if (level is ServerLevel) {
OverdriveThatMatters.tickOnce(level) { checkSurroundings(level) }
}
}
public class EnergyCounterCap implements IMatteryEnergyStorage {
public final boolean is_input;
public EnergyCounterCap(boolean is_input) {
this.is_input = is_input;
private inner class EnergyCounterCap(val is_input: Boolean) : IMatteryEnergyStorage {
override fun extractEnergyOuter(howMuch: Fraction, simulate: Boolean): Fraction {
return extractEnergyInner(howMuch, simulate)
}
private EnergyCounterCap opposite() {
return is_input ? output : input;
}
@Override
public Fraction extractEnergyOuter(Fraction howMuch, boolean simulate) {
return extractEnergyInner(howMuch, simulate);
}
@Override
public Fraction extractEnergyInner(Fraction howMuch, boolean simulate) {
override fun extractEnergyInner(howMuch: Fraction, simulate: Boolean): Fraction {
if (is_input)
return Fraction.ZERO;
return Fraction.ZERO
if (input_cap_mte.isPresent()) {
final var value = input_cap_mte.resolve().get().extractEnergyOuter(howMuch, simulate);
if (inputCapability.isPresent) {
val it = inputCapability.resolve().get()
if (!simulate) {
passed = passed.plus(value);
history[history_tick] = history[history_tick].plus(value);
setChangedLight();
val diff: Fraction
if (it is IMatteryEnergyStorage) {
diff = it.extractEnergyOuter(howMuch, simulate)
} else {
diff = Fraction(it.extractEnergy(howMuch, simulate))
}
return value;
}
if (input_cap_fe.isPresent()) {
final var value = MatteryCapability.drainFE(input_cap_fe.resolve().get(), howMuch, simulate);
if (!simulate) {
passed = passed.plus(value);
history[history_tick] = history[history_tick].plus(value);
setChangedLight();
passed += diff
history[historyTick] += diff
}
return value;
return diff
}
return Fraction.ZERO;
return Fraction.ZERO
}
@Override
public Fraction receiveEnergyOuter(Fraction howMuch, boolean simulate) {
return receiveEnergyInner(howMuch, simulate);
override fun receiveEnergyOuter(howMuch: Fraction, simulate: Boolean): Fraction {
return receiveEnergyInner(howMuch, simulate)
}
@Override
public Fraction receiveEnergyInner(Fraction howMuch, boolean simulate) {
override fun receiveEnergyInner(howMuch: Fraction, simulate: Boolean): Fraction {
if (!is_input)
return Fraction.ZERO;
return Fraction.ZERO
if (output_cap_mte.isPresent()) {
final var value = output_cap_mte.resolve().get().receiveEnergyOuter(howMuch, simulate);
if (outputCapability.isPresent) {
val it = outputCapability.resolve().get()
val diff: Fraction
if (it is IMatteryEnergyStorage) {
diff = it.receiveEnergyOuter(howMuch, simulate)
} else {
diff = Fraction(it.receiveEnergy(howMuch, simulate))
}
if (!simulate) {
passed = passed.plus(value);
history[history_tick] = history[history_tick].plus(value);
setChangedLight();
passed += diff
history[historyTick] += diff
}
return value;
return diff
}
if (output_cap_fe.isPresent()) {
final var value = MatteryCapability.floodFE(output_cap_fe.resolve().get(), howMuch, simulate);
return Fraction.ZERO
}
if (!simulate) {
passed = passed.plus(value);
history[history_tick] = history[history_tick].plus(value);
setChangedLight();
override val batteryLevel: Fraction
get() {
if (is_input) {
if (outputCapability.isPresent) {
val it = outputCapability.resolve().get()
if (it is IMatteryEnergyStorage) {
return it.batteryLevel
}
return Fraction(it.energyStored)
}
} else {
if (inputCapability.isPresent) {
val it = inputCapability.resolve().get()
if (it is IMatteryEnergyStorage) {
return it.batteryLevel
}
return Fraction(it.energyStored)
}
}
return value;
return Fraction.ZERO
}
return Fraction.ZERO;
}
override val maxBatteryLevel: Fraction
get() {
if (is_input) {
if (outputCapability.isPresent) {
val it = outputCapability.resolve().get()
@Override
public Fraction getBatteryLevel() {
if (is_input) {
if (output_cap_mte.isPresent()) {
return output_cap_mte.resolve().get().getBatteryLevel();
if (it is IMatteryEnergyStorage) {
return it.maxBatteryLevel
}
return Fraction(it.maxEnergyStored)
}
} else {
if (inputCapability.isPresent) {
val it = inputCapability.resolve().get()
if (it is IMatteryEnergyStorage) {
return it.maxBatteryLevel
}
return Fraction(it.maxEnergyStored)
}
}
if (output_cap_fe.isPresent()) {
return new Fraction(output_cap_fe.resolve().get().getEnergyStored());
}
} else {
if (input_cap_mte.isPresent()) {
return input_cap_mte.resolve().get().getBatteryLevel();
}
if (input_cap_fe.isPresent()) {
return new Fraction(input_cap_fe.resolve().get().getEnergyStored());
}
return Fraction.ZERO
}
return Fraction.ZERO;
}
@Override
public Fraction getMaxBatteryLevel() {
if (is_input) {
if (output_cap_mte.isPresent()) {
return output_cap_mte.resolve().get().getMaxBatteryLevel();
}
if (output_cap_fe.isPresent()) {
return new Fraction(output_cap_fe.resolve().get().getMaxEnergyStored());
}
} else {
if (input_cap_mte.isPresent()) {
return input_cap_mte.resolve().get().getMaxBatteryLevel();
}
if (input_cap_fe.isPresent()) {
return new Fraction(input_cap_fe.resolve().get().getMaxEnergyStored());
}
}
return Fraction.ZERO;
}
@Override
public boolean canExtract() {
return !is_input;
}
@Override
public boolean canReceive() {
return is_input;
}
override fun canExtract() = !is_input
override fun canReceive() = is_input
}
protected LazyOptional<IMatteryEnergyStorage> input_resolver = LazyOptional.of(() -> input);
protected LazyOptional<IMatteryEnergyStorage> output_resolver = LazyOptional.of(() -> output);
private var resolverInput = LazyOptional.of<IMatteryEnergyStorage> { energyInput }
private var resolverOutput = LazyOptional.of<IMatteryEnergyStorage> { energyOutput }
private var valid = true
@Override
public void invalidateCaps() {
super.invalidateCaps();
input_resolver.invalidate();
output_resolver.invalidate();
override fun invalidateCaps() {
super.invalidateCaps()
valid = false
resolverInput.invalidate()
resolverOutput.invalidate()
}
@Override
public void reviveCaps() {
super.reviveCaps();
input_resolver = LazyOptional.of(() -> input);
output_resolver = LazyOptional.of(() -> output);
override fun reviveCaps() {
super.reviveCaps()
valid = true
resolverInput = LazyOptional.of { energyInput }
resolverOutput = LazyOptional.of { energyOutput }
}
@Override
@SuppressWarnings("deprecation")
public void setBlockState(BlockState p_155251_) {
final var old = getBlockState();
@Suppress("deprecation")
override fun setBlockState(new: BlockState) {
val old = blockState
super.setBlockState(new)
super.setBlockState(p_155251_);
if (p_155251_ != old && p_155251_.getValue(BlockEnergyCounter.INPUT_DIRECTION) != old.getValue(BlockEnergyCounter.INPUT_DIRECTION)) {
input_resolver.invalidate();
output_resolver.invalidate();
input_resolver = LazyOptional.of(() -> input);
output_resolver = LazyOptional.of(() -> output);
if (new !== old && new.getValue(BlockEnergyCounter.INPUT_DIRECTION) != old.getValue(BlockEnergyCounter.INPUT_DIRECTION)) {
resolverInput.invalidate()
resolverOutput.invalidate()
resolverInput = LazyOptional.of { energyInput }
resolverOutput = LazyOptional.of { energyOutput }
if (level != null)
checkSurroundings(level);
checkSurroundings(level)
}
}
private <T> LazyOptional<T> getAndBind(Level level, LazyOptional<T> old, Capability<T> cap, Direction side) {
final var ent = level.getBlockEntity(getBlockPos().offset(side.getNormal()));
private fun getAndBind(
level: Level,
old: LazyOptional<IEnergyStorage>,
side: Direction
): LazyOptional<IEnergyStorage> {
val ent = level.getBlockEntity(blockPos.offset(side.normal)) ?: return LazyOptional.empty()
val resolve = ent.getCapability(CapabilityEnergy.ENERGY, side.opposite)
if (ent == null)
return LazyOptional.empty();
if (resolve !== old) {
val weak = WeakReference(this)
final var resolve = ent.getCapability(cap, side.getOpposite());
resolve.addListener {
val get = weak.get()
if (resolve != old) {
final var weak = new WeakReference<>(this);
resolve.addListener((l) -> {
final var get = weak.get();
if (get != null && get.level != null) {
get.checkSurroundings(get.level);
if (get?.level != null) {
get.checkSurroundings(get.level)
}
});
}
return resolve;
return resolve
}
return old;
return old
}
public void checkSurroundings(Level level) {
if (isRemoved() || !(level instanceof ServerLevel))
return;
fun checkSurroundings(level: Level?) {
if (isRemoved || level !is ServerLevel) return
input_cap_mte = getAndBind(level, input_cap_mte, MatteryCapability.ENERGY, getBlockState().getValue(BlockEnergyCounter.INPUT_DIRECTION));
input_cap_fe = getAndBind(level, input_cap_fe, CapabilityEnergy.ENERGY, getBlockState().getValue(BlockEnergyCounter.INPUT_DIRECTION));
inputCapability = getAndBind(
level,
inputCapability,
blockState.getValue(BlockEnergyCounter.INPUT_DIRECTION)
)
output_cap_mte = getAndBind(level, output_cap_mte, MatteryCapability.ENERGY, getBlockState().getValue(BlockEnergyCounter.INPUT_DIRECTION).getOpposite());
output_cap_fe = getAndBind(level, output_cap_fe, CapabilityEnergy.ENERGY, getBlockState().getValue(BlockEnergyCounter.INPUT_DIRECTION).getOpposite());
outputCapability = getAndBind(
level,
outputCapability,
-blockState.getValue(BlockEnergyCounter.INPUT_DIRECTION)
)
}
@Nonnull
@Override
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable Direction side) {
if (side == null || isRemoved())
return super.getCapability(cap, side);
override fun <T> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> {
if (side == null || isRemoved)
return super.getCapability(cap, side)
if (side == getBlockState().getValue(BlockEnergyCounter.INPUT_DIRECTION)) {
if (cap == MatteryCapability.ENERGY || cap == CapabilityEnergy.ENERGY) {
return input_resolver.cast();
}
} else if (side == getBlockState().getValue(BlockEnergyCounter.INPUT_DIRECTION).getOpposite()) {
if (cap == MatteryCapability.ENERGY || cap == CapabilityEnergy.ENERGY) {
return output_resolver.cast();
if (valid) {
if (side == blockState.getValue(BlockEnergyCounter.INPUT_DIRECTION)) {
if (cap === MatteryCapability.ENERGY || cap === CapabilityEnergy.ENERGY) {
return resolverInput.cast()
}
} else if (side == blockState.getValue(BlockEnergyCounter.INPUT_DIRECTION).opposite) {
if (cap === MatteryCapability.ENERGY || cap === CapabilityEnergy.ENERGY) {
return resolverOutput.cast()
}
}
}
return super.getCapability(cap, side);
return super.getCapability(cap, side)
}
}
fun tick() {
historyTick = (historyTick + 1) % history.size
history[historyTick] = Fraction.ZERO
}
companion object {
private val NAME = TranslatableComponent("block.overdrive_that_matters.energy_counter")
}
}

View File

@ -1,123 +1,104 @@
package ru.dbotthepony.mc.otm.capability;
package ru.dbotthepony.mc.otm.capability
import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraftforge.energy.IEnergyStorage;
import ru.dbotthepony.mc.otm.core.Fraction;
import javax.annotation.ParametersAreNonnullByDefault;
import net.minecraftforge.energy.IEnergyStorage
import ru.dbotthepony.mc.otm.core.Fraction
// IEnergyStorage for direct compat with Forge Energy
@MethodsReturnNonnullByDefault
@ParametersAreNonnullByDefault
@SuppressWarnings("unused")
public interface IMatteryEnergyStorage extends IEnergyStorage {
interface IMatteryEnergyStorage : IEnergyStorage {
// such as cables. This is something that would work only with energy storage
Fraction extractEnergyOuter(Fraction howMuch, boolean simulate);
fun extractEnergyOuter(howMuch: Fraction, simulate: Boolean): Fraction
// for internal needs, e.g. for work
// CAN also be used by something that does evil
// e.g. sucking out energy anomaly should use this
Fraction extractEnergyInner(Fraction howMuch, boolean simulate);
fun extractEnergyInner(howMuch: Fraction, simulate: Boolean): Fraction
// energy is received from outside, e.g. cables
Fraction receiveEnergyOuter(Fraction howMuch, boolean simulate);
fun receiveEnergyOuter(howMuch: Fraction, simulate: Boolean): Fraction
// energy is received from inside, e.g. generator generates power
Fraction receiveEnergyInner(Fraction howMuch, boolean simulate);
fun receiveEnergyInner(howMuch: Fraction, simulate: Boolean): Fraction
default Fraction extractEnergyOuter(long howMuch, boolean simulate) {
return extractEnergyOuter(new Fraction(howMuch), simulate);
fun extractEnergyOuter(howMuch: Long, simulate: Boolean): Fraction {
return extractEnergyOuter(Fraction(howMuch), simulate)
}
default Fraction extractEnergyOuter(int howMuch, boolean simulate) {
return extractEnergyOuter(new Fraction(howMuch), simulate);
fun extractEnergyOuter(howMuch: Int, simulate: Boolean): Fraction {
return extractEnergyOuter(Fraction(howMuch), simulate)
}
default Fraction receiveEnergyOuter(long howMuch, boolean simulate) {
return receiveEnergyOuter(new Fraction(howMuch), simulate);
fun receiveEnergyOuter(howMuch: Long, simulate: Boolean): Fraction {
return receiveEnergyOuter(Fraction(howMuch), simulate)
}
default Fraction receiveEnergyOuter(int howMuch, boolean simulate) {
return receiveEnergyOuter(new Fraction(howMuch), simulate);
fun receiveEnergyOuter(howMuch: Int, simulate: Boolean): Fraction {
return receiveEnergyOuter(Fraction(howMuch), simulate)
}
default Fraction extractEnergyInner(long howMuch, boolean simulate) {
return extractEnergyInner(new Fraction(howMuch), simulate);
fun extractEnergyInner(howMuch: Long, simulate: Boolean): Fraction {
return extractEnergyInner(Fraction(howMuch), simulate)
}
default Fraction extractEnergyInner(int howMuch, boolean simulate) {
return extractEnergyInner(new Fraction(howMuch), simulate);
fun extractEnergyInner(howMuch: Int, simulate: Boolean): Fraction {
return extractEnergyInner(Fraction(howMuch), simulate)
}
default Fraction receiveEnergyInner(long howMuch, boolean simulate) {
return receiveEnergyInner(new Fraction(howMuch), simulate);
fun receiveEnergyInner(howMuch: Long, simulate: Boolean): Fraction {
return receiveEnergyInner(Fraction(howMuch), simulate)
}
default Fraction receiveEnergyInner(int howMuch, boolean simulate) {
return receiveEnergyInner(new Fraction(howMuch), simulate);
fun receiveEnergyInner(howMuch: Int, simulate: Boolean): Fraction {
return receiveEnergyInner(Fraction(howMuch), simulate)
}
Fraction getBatteryLevel();
val batteryLevel: Fraction
val maxBatteryLevel: Fraction
val missingPower: Fraction
get() = maxBatteryLevel - batteryLevel
Fraction getMaxBatteryLevel();
override fun receiveEnergy(maxReceive: Int, simulate: Boolean): Int {
val received = receiveEnergyOuter(maxReceive, true).toInt()
default Fraction getMissingPower() {
return getMaxBatteryLevel().minus(getBatteryLevel());
// Receiving only a fraction
if (received == 0)
return 0
return receiveEnergyOuter(Fraction(received), simulate).toInt()
}
@Override
default int receiveEnergy(int maxReceive, boolean simulate) {
int received = receiveEnergyOuter(maxReceive, true).toInt();
override fun extractEnergy(maxReceive: Int, simulate: Boolean): Int {
val extracted = extractEnergyOuter(maxReceive, true).toInt()
if (received == 0) {
// Receiving only a fraction
return 0;
}
// Extracting only a fraction
if (extracted == 0)
return 0
return receiveEnergyOuter(new Fraction(received), simulate).toInt();
return extractEnergyOuter(Fraction(extracted), simulate).toInt()
}
@Override
default int extractEnergy(int maxReceive, boolean simulate) {
int extracted = extractEnergyOuter(maxReceive, true).toInt();
override fun getEnergyStored(): Int {
val level = batteryLevel
if (extracted == 0) {
// Extracting only a fraction
return 0;
}
if (level < MatteryCapability.INT_MAX_VALUE)
return level.toInt()
return extractEnergyOuter(new Fraction(extracted), simulate).toInt();
return Int.MAX_VALUE
}
@Override
default int getEnergyStored() {
Fraction level = getBatteryLevel();
override fun getMaxEnergyStored(): Int {
val level = maxBatteryLevel
if (level.compareTo(MatteryCapability.INT_MAX_VALUE) < 0) {
return level.toInt();
}
if (level < MatteryCapability.INT_MAX_VALUE)
return level.toInt()
return Integer.MAX_VALUE;
return Int.MAX_VALUE
}
@Override
default int getMaxEnergyStored() {
Fraction level = getMaxBatteryLevel();
if (level.compareTo(MatteryCapability.INT_MAX_VALUE) < 0) {
return level.toInt();
}
return Integer.MAX_VALUE;
override fun canExtract(): Boolean {
return extractEnergyOuter(Fraction.ONE, true) > Fraction.ZERO
}
@Override
default boolean canExtract() {
return extractEnergyOuter(Fraction.ONE, true).compareTo(Fraction.ZERO) > 0;
override fun canReceive(): Boolean {
return receiveEnergyOuter(Fraction.ONE, true) > Fraction.ZERO
}
@Override
default boolean canReceive() {
return receiveEnergyOuter(Fraction.ONE, true).compareTo(Fraction.ZERO) > 0;
}
}
}

View File

@ -1,144 +1,103 @@
package ru.dbotthepony.mc.otm.capability;
package ru.dbotthepony.mc.otm.capability
import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraftforge.common.util.INBTSerializable;
import ru.dbotthepony.mc.otm.core.Fraction;
import net.minecraft.nbt.CompoundTag
import net.minecraft.world.level.block.entity.BlockEntity
import net.minecraftforge.common.util.INBTSerializable
import ru.dbotthepony.mc.otm.core.Fraction
import ru.dbotthepony.mc.otm.core.Fraction.Companion.deserializeNBT
import ru.dbotthepony.mc.otm.ifHas
import ru.dbotthepony.mc.otm.set
import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
import java.math.BigDecimal;
open class MatteryMachineEnergyStorage @JvmOverloads constructor(
protected val listener: () -> Unit,
val type: MachineType,
override var maxBatteryLevel: Fraction = DEFAULT_MAX_CAPACITY,
protected var maxInput: Fraction = DEFAULT_MAX_RECEIVE,
protected var maxOutput: Fraction = maxInput
) : IMatteryEnergyStorage, INBTSerializable<CompoundTag> {
@JvmOverloads
constructor(
listener: BlockEntity,
type: MachineType,
maxBatteryLevel: Fraction = DEFAULT_MAX_CAPACITY,
maxInput: Fraction = DEFAULT_MAX_RECEIVE,
maxOutput: Fraction = maxInput) : this({listener.setChanged()}, type, maxBatteryLevel, maxInput, maxOutput)
@MethodsReturnNonnullByDefault
@ParametersAreNonnullByDefault
public class MatteryMachineEnergyStorage implements IMatteryEnergyStorage, INBTSerializable<CompoundTag> {
public enum MachineType {
WORKER,
GENERATOR,
CAPACITOR,
enum class MachineType {
WORKER, GENERATOR, CAPACITOR
}
public static final Fraction DEFAULT_MAX_RECEIVE = new Fraction(200);
public static final Fraction DEFAULT_MAX_EXTRACT = new Fraction(200);
public static final Fraction DEFAULT_MAX_CAPACITY = new Fraction(60000);
override var batteryLevel = Fraction.ZERO
protected set
protected Fraction energy_stored = Fraction.ZERO;
protected Fraction energy_stored_max;
protected Fraction max_input;
protected Fraction max_output;
protected final MachineType machine_type;
protected final BlockEntity listener;
override fun extractEnergyOuter(howMuch: Fraction, simulate: Boolean): Fraction {
if (type == MachineType.WORKER)
return Fraction.ZERO
public MatteryMachineEnergyStorage(BlockEntity listener, MachineType type, Fraction capacity) {
this(listener, type, capacity, DEFAULT_MAX_RECEIVE, DEFAULT_MAX_EXTRACT);
return extractEnergyInner(howMuch, simulate)
}
public MatteryMachineEnergyStorage(BlockEntity listener, MachineType type) {
this(listener, type, DEFAULT_MAX_CAPACITY);
}
override fun extractEnergyInner(howMuch: Fraction, simulate: Boolean): Fraction {
val new = batteryLevel.minus(howMuch.min(maxOutput)).moreThanZero()
val diff = batteryLevel.minus(new)
public MatteryMachineEnergyStorage(BlockEntity listener, MachineType type, Fraction capacity, Fraction maxReceive, Fraction maxExtract) {
this.listener = listener;
energy_stored_max = capacity;
max_input = maxReceive;
max_output = maxExtract;
machine_type = type;
}
@Nonnull
@Override
public Fraction extractEnergyOuter(Fraction howMuch, boolean simulate) {
if (machine_type == MachineType.WORKER) {
return Fraction.ZERO;
if (!simulate && batteryLevel != new) {
batteryLevel = new
listener()
}
return extractEnergyInner(howMuch, simulate);
return diff
}
@Nonnull
@Override
public Fraction extractEnergyInner(Fraction howMuch, boolean simulate) {
Fraction new_energy = energy_stored.minus(howMuch.min(max_output)).moreThanZero();
Fraction diff = energy_stored.minus(new_energy);
override fun receiveEnergyOuter(howMuch: Fraction, simulate: Boolean): Fraction {
if (type == MachineType.GENERATOR)
return Fraction.ZERO
if (!simulate && !energy_stored.equalsCompact(new_energy)) {
energy_stored = new_energy;
listener.setChanged();
return receiveEnergyInner(howMuch, simulate)
}
override fun receiveEnergyInner(howMuch: Fraction, simulate: Boolean): Fraction {
val new = batteryLevel.plus(howMuch.min(maxInput)).min(maxBatteryLevel)
val diff = new.minus(batteryLevel)
if (!simulate && batteryLevel != new) {
batteryLevel = new
listener()
}
return diff;
return diff
}
@Nonnull
@Override
public Fraction receiveEnergyOuter(Fraction howMuch, boolean simulate) {
if (machine_type == MachineType.GENERATOR) {
return Fraction.ZERO;
}
return receiveEnergyInner(howMuch, simulate);
override fun canExtract(): Boolean {
return type != MachineType.WORKER
}
@Nonnull
@Override
public Fraction receiveEnergyInner(Fraction howMuch, boolean simulate) {
Fraction new_energy = energy_stored.plus(howMuch.min(max_input)).min(energy_stored_max);
Fraction diff = new_energy.minus(energy_stored);
if (!simulate && !energy_stored.equalsCompact(new_energy)) {
energy_stored = new_energy;
listener.setChanged();
}
return diff;
override fun canReceive(): Boolean {
return type != MachineType.GENERATOR
}
@Nonnull
@Override
public Fraction getBatteryLevel() {
return energy_stored;
override fun serializeNBT(): CompoundTag {
val tag = CompoundTag()
// TODO: А это вообще надо?
tag["energy_stored"] = batteryLevel.serializeNBT()
// tag["energy_stored_max"] = maxBatteryLevel.serializeNBT()
// tag["max_input"] = maxInput.serializeNBT()
// tag["max_output"] = maxOutput.serializeNBT()
return tag
}
@Nonnull
@Override
public Fraction getMaxBatteryLevel() {
return energy_stored_max;
override fun deserializeNBT(nbt: CompoundTag) {
nbt.ifHas("energy_stored") { batteryLevel = deserializeNBT(it) }
// nbt.ifHas("energy_stored_max") { maxBatteryLevel = deserializeNBT(it) }
// nbt.ifHas("max_input") { maxInput = deserializeNBT(it) }
// nbt.ifHas("max_output") { maxOutput = deserializeNBT(it) }
}
@Override
public boolean canExtract() {
return machine_type != MachineType.WORKER;
companion object {
val DEFAULT_MAX_RECEIVE = Fraction(200)
val DEFAULT_MAX_EXTRACT = Fraction(200)
val DEFAULT_MAX_CAPACITY = Fraction(60000)
}
@Override
public boolean canReceive() {
return machine_type != MachineType.GENERATOR;
}
@Override
@Nonnull
public CompoundTag serializeNBT() {
CompoundTag tag = new CompoundTag();
tag.put("energy_stored", energy_stored.serializeNBT());
tag.put("energy_stored_max", energy_stored_max.serializeNBT());
tag.put("max_input", max_input.serializeNBT());
tag.put("max_output", max_output.serializeNBT());
return tag;
}
@Override
public void deserializeNBT(CompoundTag nbt) {
if (nbt.contains("energy_stored"))
energy_stored = Fraction.deserializeNBT(nbt.get("energy_stored"));
if (nbt.contains("energy_stored_max"))
energy_stored_max = Fraction.deserializeNBT(nbt.get("energy_stored_max"));
if (nbt.contains("max_input"))
max_input = Fraction.deserializeNBT(nbt.get("max_input"));
if (nbt.contains("max_output"))
max_output = Fraction.deserializeNBT(nbt.get("max_output"));
}
}
}

View File

@ -386,7 +386,7 @@ open class AndroidCapability(@JvmField protected val ent: LivingEntity) : ICapab
return ent
}
override fun getBatteryLevel(): Fraction {
override val batteryLevel: Fraction get() {
if (!batteryItemStack.isEmpty) {
val resolver = batteryItemStack.getCapability(CapabilityEnergy.ENERGY).resolve()
@ -404,7 +404,7 @@ open class AndroidCapability(@JvmField protected val ent: LivingEntity) : ICapab
return battery
}
override fun getMaxBatteryLevel(): Fraction {
override val maxBatteryLevel: Fraction get() {
if (batteryItemStack != ItemStack.EMPTY) {
val resolver = batteryItemStack.getCapability(CapabilityEnergy.ENERGY).resolve()

View File

@ -1,63 +1,78 @@
package ru.dbotthepony.mc.otm.client.screen;
package ru.dbotthepony.mc.otm.client.screen
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.world.entity.player.Inventory;
import ru.dbotthepony.mc.otm.client.screen.panels.Dock;
import ru.dbotthepony.mc.otm.client.screen.panels.FramePanel;
import ru.dbotthepony.mc.otm.client.screen.panels.Label;
import ru.dbotthepony.mc.otm.menu.EnergyCounterMenu;
import ru.dbotthepony.mc.otm.menu.FormattingHelper;
import net.minecraft.network.chat.Component
import net.minecraft.network.chat.TranslatableComponent
import net.minecraft.world.entity.player.Inventory
import ru.dbotthepony.mc.otm.client.screen.panels.Dock
import ru.dbotthepony.mc.otm.client.screen.panels.FramePanel
import ru.dbotthepony.mc.otm.client.screen.panels.Label
import ru.dbotthepony.mc.otm.menu.EnergyCounterMenu
import ru.dbotthepony.mc.otm.menu.FormattingHelper
import javax.annotation.Nullable;
class EnergyCounterScreen(menu: EnergyCounterMenu, inventory: Inventory, title: Component) : MatteryScreen<EnergyCounterMenu>(menu, inventory, title) {
override fun makeMainFrame(): FramePanel {
val frame = super.makeMainFrame()!!
public class EnergyCounterScreen extends MatteryScreen<EnergyCounterMenu> {
public EnergyCounterScreen(EnergyCounterMenu menu, Inventory inventory, Component title) {
super(menu, inventory, title);
var label: Label = object : Label(this@EnergyCounterScreen, frame) {
override fun tick() {
super.tick()
setText(
TranslatableComponent(
"otm.item.power.passed",
FormattingHelper.formatPower(menu.passed.value)
)
)
}
}
label.dock = Dock.TOP
label.setDockMargin(4f, 0f, 0f, 0f)
label = object : Label(this@EnergyCounterScreen, frame) {
override fun tick() {
super.tick()
setText(
TranslatableComponent(
"otm.item.power.average",
FormattingHelper.formatPower(menu.average.value)
)
)
}
}
label.dock = Dock.TOP
label.setDockMargin(4f, 0f, 0f, 0f)
label = object : Label(this@EnergyCounterScreen, frame) {
override fun tick() {
super.tick()
setText(
TranslatableComponent(
"otm.item.power.last_20_ticks",
FormattingHelper.formatPower(menu.last20Ticks.value)
)
)
}
}
label.dock = Dock.TOP
label.setDockMargin(4f, 0f, 0f, 0f)
label = object : Label(this@EnergyCounterScreen, frame) {
override fun tick() {
super.tick()
setText(
TranslatableComponent(
"otm.item.power.last_tick",
FormattingHelper.formatPower(menu.lastTick.value)
)
)
}
}
label.dock = Dock.TOP
label.setDockMargin(4f, 0f, 0f, 0f)
return frame
}
@Nullable
@Override
protected FramePanel makeMainFrame() {
var frame = super.makeMainFrame();
var label = (Label) new Label(this, frame) {
@Override
public void tick() {
super.tick();
setText(new TranslatableComponent("otm.item.power.passed", FormattingHelper.formatPower(menu.passed.getValue())));
}
};
label.setDock(Dock.TOP);
label.setDockMargin(4, 0, 0, 0);
label = new Label(this, frame) {
@Override
public void tick() {
super.tick();
setText(new TranslatableComponent("otm.item.power.average", FormattingHelper.formatPower(menu.average.getValue())));
}
};
label.setDock(Dock.TOP);
label.setDockMargin(4, 0, 0, 0);
label = new Label(this, frame) {
@Override
public void tick() {
super.tick();
setText(new TranslatableComponent("otm.item.power.last_20_ticks", FormattingHelper.formatPower(menu.last_20_ticks.getValue())));
}
};
label.setDock(Dock.TOP);
label.setDockMargin(4, 0, 0, 0);
return frame;
}
}
}

View File

@ -66,15 +66,15 @@ class ItemBattery : Item {
return diff
}
override fun getMissingPower(): Fraction {
return if (isCreative) MatteryCapability.LONG_MAX_VALUE else super.getMissingPower()
override val missingPower: Fraction get() {
return if (isCreative) MatteryCapability.LONG_MAX_VALUE else super.missingPower
}
override fun getBatteryLevel(): Fraction {
override val batteryLevel: Fraction get() {
return if (isCreative) MatteryCapability.LONG_MAX_VALUE else energy()
}
override fun getMaxBatteryLevel(): Fraction {
override val maxBatteryLevel: Fraction get() {
return storage
}

View File

@ -29,7 +29,7 @@ class ChemicalGeneratorMenu @JvmOverloads constructor(id: Int, inv: Inventory, t
}
val progress = ProgressGaugeWidget(this) { 1f - tile!!.workingTicks.toFloat() / tile.workingTicksTotal }
val energy = LevelGaugeWidget(this, tile)
val energy = LevelGaugeWidget(this, tile?.energy)
val burnTime = IntDataContainer()
init {

View File

@ -1,59 +1,52 @@
package ru.dbotthepony.mc.otm.menu;
package ru.dbotthepony.mc.otm.menu
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.inventory.MenuType;
import net.minecraft.world.level.block.entity.BlockEntity;
import ru.dbotthepony.mc.otm.Registry;
import ru.dbotthepony.mc.otm.block.entity.BlockEntityEnergyCounter;
import ru.dbotthepony.mc.otm.menu.data.BigDecimalDataContainer;
import ru.dbotthepony.mc.otm.menu.data.FractionDataContainer;
import kotlin.jvm.JvmOverloads
import net.minecraft.world.entity.player.Inventory
import ru.dbotthepony.mc.otm.Registry
import ru.dbotthepony.mc.otm.block.entity.BlockEntityEnergyCounter
import ru.dbotthepony.mc.otm.menu.data.FractionDataContainer
import javax.annotation.Nullable;
class EnergyCounterMenu @JvmOverloads constructor(
p_38852_: Int,
inventory: Inventory,
tile: BlockEntityEnergyCounter? = null
) : MatteryMenu(Registry.Menus.ENERGY_COUNTER, p_38852_, inventory, tile) {
@JvmField val passed = FractionDataContainer()
@JvmField val average = FractionDataContainer()
@JvmField val last20Ticks = FractionDataContainer()
@JvmField val lastTick = FractionDataContainer()
public class EnergyCounterMenu extends MatteryMenu {
public final FractionDataContainer passed = new FractionDataContainer();
public final FractionDataContainer average = new FractionDataContainer();
public final FractionDataContainer last_20_ticks = new FractionDataContainer();
// TODO: Graph and proper networking for it
private int ticks_passed = 0;
private var ticksPassed = 0
public EnergyCounterMenu(int p_38852_, Inventory inventory) {
this(p_38852_, inventory, null);
init {
addDataSlots(passed)
addDataSlots(average)
addDataSlots(last20Ticks)
addDataSlots(lastTick)
}
public EnergyCounterMenu(int p_38852_, Inventory inventory, BlockEntityEnergyCounter tile) {
super(Registry.Menus.ENERGY_COUNTER, p_38852_, inventory, tile);
override fun broadcastChanges() {
if (tile is BlockEntityEnergyCounter) {
passed.value = tile.passed
average.value = tile.calcAverage(20)
lastTick.value = tile.lastTick
addDataSlots(passed);
addDataSlots(average);
addDataSlots(last_20_ticks);
}
@Override
public void broadcastChanges() {
if (tile != null) {
BlockEntityEnergyCounter tile = (BlockEntityEnergyCounter) this.tile;
passed.setValue(tile.getPassed());
average.setValue(tile.calcAverage(20));
if (ticks_passed == 0) {
last_20_ticks.setValue(tile.sumHistory(20));
if (ticksPassed == 0) {
last20Ticks.value = tile.sumHistory(20)
}
ticks_passed = (ticks_passed + 1) % 20;
ticksPassed = (ticksPassed + 1) % 20
}
super.broadcastChanges();
super.broadcastChanges()
}
@Override
protected int getWorkingSlotStart() {
return 0;
override fun getWorkingSlotStart(): Int {
return 0
}
@Override
protected int getWorkingSlotEnd() {
return 0;
override fun getWorkingSlotEnd(): Int {
return 0
}
}
}

View File

@ -23,8 +23,8 @@ class LevelGaugeWidget(menu: MatteryMenu) : AbstractWidget(menu) {
) : this(menu) {
if (power == null) return
this.level = power::getBatteryLevel
this.maxLevel = power::getMaxBatteryLevel
this.level = power::batteryLevel
this.maxLevel = power::maxBatteryLevel
}
constructor(

View File

@ -40,6 +40,7 @@
"otm.item.power.passed": "Passed energy: %s",
"otm.item.power.average": "Average throughput: %s/t",
"otm.item.power.last_20_ticks": "Last second: %s",
"otm.item.power.last_tick": "Last tick: %s",
"otm.item.power.normal.storage": "Stored energy: %s / %s",
"otm.item.power.normal.throughput": "Max I/O %s / %s",