Move energy, matter and storage ImpreciseFraction

those imprecisions will haut me in my dreams
This commit is contained in:
DBotThePony 2022-01-26 09:00:47 +07:00
parent dab5cd6a2b
commit a5e5b928bc
Signed by: DBot
GPG Key ID: DCC23B5715498507
60 changed files with 1054 additions and 663 deletions

View File

@ -30,6 +30,7 @@ import ru.dbotthepony.mc.otm.client.EventHandler;
import ru.dbotthepony.mc.otm.client.model.GravitationStabilizerModel;
import ru.dbotthepony.mc.otm.client.model.TritaniumArmorModel;
import ru.dbotthepony.mc.otm.core.Fraction;
import ru.dbotthepony.mc.otm.core.ImpreciseFraction;
import ru.dbotthepony.mc.otm.item.ItemPortableCondensationDrive;
import ru.dbotthepony.mc.otm.matter.MatterRegistry;
import ru.dbotthepony.mc.otm.network.MatteryNetworking;
@ -171,7 +172,7 @@ public class OverdriveThatMatters {
MatterRegistry.registerInitialItems();
ITEM_STORAGE = StorageObjectRegistry.register(ItemStackWrapper.class, ItemStackWrapper.EMPTY, new Fraction("3.125"));
ITEM_STORAGE = StorageObjectRegistry.register(ItemStackWrapper.class, ItemStackWrapper.EMPTY, new ImpreciseFraction("3.125"));
TritaniumArmorModel.register();
GravitationStabilizerModel.register();

View File

@ -52,6 +52,7 @@ 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;
import ru.dbotthepony.mc.otm.core.ImpreciseFraction;
import ru.dbotthepony.mc.otm.item.*;
import ru.dbotthepony.mc.otm.menu.*;
import ru.dbotthepony.mc.otm.client.screen.*;
@ -673,11 +674,11 @@ public class Registry {
public static final ItemPill PILL_OBLIVION = new ItemPill(PillType.OBLIVION);
public static final ItemPillHeal PILL_HEAL = new ItemPillHeal();
public static final ItemBattery BATTERY_CRUDE = new ItemBattery(new Fraction(30_000), new Fraction(150), new Fraction(150));
public static final ItemBattery BATTERY_BASIC = new ItemBattery(new Fraction(60_000), new Fraction(300), new Fraction(300));
public static final ItemBattery BATTERY_NORMAL = new ItemBattery(new Fraction(250_000), new Fraction(1000), new Fraction(1000));
public static final ItemBattery BATTERY_DENSE = new ItemBattery(new Fraction(1_000_000), new Fraction(2000), new Fraction(2000));
public static final ItemBattery BATTERY_CAPACITOR = new ItemBattery(new Fraction(150_000), new Fraction(15000), new Fraction(15000));
public static final ItemBattery BATTERY_CRUDE = new ItemBattery(new ImpreciseFraction(30_000), new ImpreciseFraction(150), new ImpreciseFraction(150));
public static final ItemBattery BATTERY_BASIC = new ItemBattery(new ImpreciseFraction(60_000), new ImpreciseFraction(300), new ImpreciseFraction(300));
public static final ItemBattery BATTERY_NORMAL = new ItemBattery(new ImpreciseFraction(250_000), new ImpreciseFraction(1000), new ImpreciseFraction(1000));
public static final ItemBattery BATTERY_DENSE = new ItemBattery(new ImpreciseFraction(1_000_000), new ImpreciseFraction(2000), new ImpreciseFraction(2000));
public static final ItemBattery BATTERY_CAPACITOR = new ItemBattery(new ImpreciseFraction(150_000), new ImpreciseFraction(15000), new ImpreciseFraction(15000));
public static final ItemBattery BATTERY_CREATIVE = new ItemBattery();
public static final ItemBattery[] BATTERIES = {
@ -705,9 +706,9 @@ public class Registry {
MATTER_TRANSFORM_MATRIX,
};
public static final ItemMatterCapacitor MATTER_CAPACITOR_BASIC = new ItemMatterCapacitor(new Fraction("4"));
public static final ItemMatterCapacitor MATTER_CAPACITOR_NORMAL = new ItemMatterCapacitor(new Fraction("10"));
public static final ItemMatterCapacitor MATTER_CAPACITOR_DENSE = new ItemMatterCapacitor(new Fraction("40"));
public static final ItemMatterCapacitor MATTER_CAPACITOR_BASIC = new ItemMatterCapacitor(new ImpreciseFraction("4"));
public static final ItemMatterCapacitor MATTER_CAPACITOR_NORMAL = new ItemMatterCapacitor(new ImpreciseFraction("10"));
public static final ItemMatterCapacitor MATTER_CAPACITOR_DENSE = new ItemMatterCapacitor(new ImpreciseFraction("40"));
public static final ItemMatterCapacitor MATTER_CAPACITOR_CREATIVE = new ItemMatterCapacitor();
public static final ItemPatternStorage PATTERN_DRIVE_NORMAL = new ItemPatternStorage(4);

View File

@ -9,6 +9,7 @@ import ru.dbotthepony.mc.otm.android.AndroidFeatureType;
import ru.dbotthepony.mc.otm.capability.android.IAndroidCapability;
import ru.dbotthepony.mc.otm.capability.MatteryCapability;
import ru.dbotthepony.mc.otm.core.Fraction;
import ru.dbotthepony.mc.otm.core.ImpreciseFraction;
import java.math.BigDecimal;
@ -39,8 +40,8 @@ public class AndroidNanobotsArmor extends AndroidFeature {
protected int ticks_passed = 0;
protected int layers = 0;
protected static final Fraction ENERGY_PER_BUILT = new Fraction(200);
protected static final Fraction ENERGY_PER_HITPOINT = new Fraction(500);
protected static final ImpreciseFraction ENERGY_PER_BUILT = new ImpreciseFraction(200);
protected static final ImpreciseFraction ENERGY_PER_HITPOINT = new ImpreciseFraction(500);
public static final int[] TICKS = new int[] {
80, // 4 seconds to build a layer

View File

@ -9,6 +9,7 @@ import ru.dbotthepony.mc.otm.android.AndroidFeatureType;
import ru.dbotthepony.mc.otm.capability.android.IAndroidCapability;
import ru.dbotthepony.mc.otm.capability.MatteryCapability;
import ru.dbotthepony.mc.otm.core.Fraction;
import ru.dbotthepony.mc.otm.core.ImpreciseFraction;
import java.math.BigDecimal;
@ -20,7 +21,7 @@ public class AndroidNanobotsRegeneration extends AndroidFeature {
protected int ticks_passed = 0;
protected int heal_ticks = 0;
protected static final Fraction ENERGY_PER_HITPOINT = new Fraction(800);
protected static final ImpreciseFraction ENERGY_PER_HITPOINT = new ImpreciseFraction(800);
protected static final int[] TICKS_BETWEEN_HEAL = new int[] {
100, // 5 seconds
@ -42,7 +43,7 @@ public class AndroidNanobotsRegeneration extends AndroidFeature {
var missing = Math.min(1, ent.getMaxHealth() - ent.getHealth());
var extract = capability.extractEnergyInner(ENERGY_PER_HITPOINT.times(missing), false);
if (extract.compareTo(Fraction.ZERO) > 0) {
if (extract.compareTo(ImpreciseFraction.ZERO) > 0) {
heal_ticks = Math.min(heal_ticks + 1, level);
var heal = missing * extract.div(ENERGY_PER_HITPOINT).toFloat();
ent.heal(heal);

View File

@ -6,19 +6,20 @@ import net.minecraft.nbt.DoubleTag;
import net.minecraft.nbt.Tag;
import net.minecraft.world.item.ItemStack;
import ru.dbotthepony.mc.otm.core.Fraction;
import ru.dbotthepony.mc.otm.core.ImpreciseFraction;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
@MethodsReturnNonnullByDefault
@ParametersAreNonnullByDefault
public record MachineJob(ItemStack stack, double ticks, Fraction power, CompoundTag data) {
public MachineJob(ItemStack stack, double ticks, Fraction power) {
public record MachineJob(ItemStack stack, double ticks, ImpreciseFraction power, CompoundTag data) {
public MachineJob(ItemStack stack, double ticks, ImpreciseFraction power) {
this(stack, ticks, power, new CompoundTag());
}
public MachineJob(ItemStack stack, double ticks) {
this(stack, ticks, Fraction.ZERO);
this(stack, ticks, ImpreciseFraction.ZERO);
}
public CompoundTag serializeNBT() {
@ -42,7 +43,7 @@ public record MachineJob(ItemStack stack, double ticks, Fraction power, Compound
ItemStack stack = ItemStack.of(stack_tag);
if (!stack.isEmpty()) {
return new MachineJob(stack, ticks_processing_time.getAsDouble(), Fraction.deserializeNBT(tag.get("power")), tag.getCompound("data"));
return new MachineJob(stack, ticks_processing_time.getAsDouble(), ImpreciseFraction.deserializeNBT(tag.get("power")), tag.getCompound("data"));
}
}
}

View File

@ -2,11 +2,12 @@ package ru.dbotthepony.mc.otm.block.entity.worker;
import net.minecraft.MethodsReturnNonnullByDefault;
import ru.dbotthepony.mc.otm.core.Fraction;
import ru.dbotthepony.mc.otm.core.ImpreciseFraction;
import javax.annotation.ParametersAreNonnullByDefault;
@MethodsReturnNonnullByDefault
@ParametersAreNonnullByDefault
public record WorkTickContext(MachineJob job, Fraction requiredPower, Fraction extractedPower, Fraction workSpeed) {
public record WorkTickContext(MachineJob job, ImpreciseFraction requiredPower, ImpreciseFraction extractedPower, ImpreciseFraction workSpeed) {
}

View File

@ -35,26 +35,4 @@ public class MatteryCapability {
event.register(IStorageGraphNode.class);
event.register(IMatterGraphNode.class);
}
public static final MathContext ROUND_RULES = new MathContext(32, RoundingMode.HALF_DOWN);
public static final Fraction INT_MAX_VALUE = new Fraction(Integer.MAX_VALUE);
public static final Fraction INT_MIN_VALUE = new Fraction(Integer.MIN_VALUE);
public static final Fraction LONG_MAX_VALUE = new Fraction(Long.MAX_VALUE);
public static final Fraction LONG_MIN_VALUE = new Fraction(Long.MIN_VALUE);
public static Fraction drainFE(IEnergyStorage capability, Fraction howMuch, boolean simulate) {
if (howMuch.compareTo(Fraction.ONE) < 0)
return Fraction.ZERO;
return new Fraction(capability.extractEnergy(howMuch.compareTo(INT_MAX_VALUE) > 0 ? Integer.MAX_VALUE : howMuch.toInt(), simulate));
}
public static Fraction floodFE(IEnergyStorage capability, Fraction howMuch, boolean simulate) {
if (howMuch.compareTo(Fraction.ONE) < 0)
return Fraction.ZERO;
return new Fraction(capability.receiveEnergy(howMuch.compareTo(INT_MAX_VALUE) > 0 ? Integer.MAX_VALUE : howMuch.toInt(), simulate));
}
}

View File

@ -1,11 +1,9 @@
package ru.dbotthepony.mc.otm.capability.matter;
import net.minecraft.MethodsReturnNonnullByDefault;
import ru.dbotthepony.mc.otm.core.Fraction;
import ru.dbotthepony.mc.otm.core.ImpreciseFraction;
import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
import java.math.BigDecimal;
@MethodsReturnNonnullByDefault
@ParametersAreNonnullByDefault
@ -16,18 +14,18 @@ public interface IMatterHandler {
BIDIRECTIONAL // storage
}
Fraction getStoredMatter();
Fraction getMaxStoredMatter();
ImpreciseFraction getStoredMatter();
ImpreciseFraction getMaxStoredMatter();
Fraction receiveMatterOuter(Fraction howMuch, boolean simulate);
Fraction receiveMatterInner(Fraction howMuch, boolean simulate);
ImpreciseFraction receiveMatterOuter(ImpreciseFraction howMuch, boolean simulate);
ImpreciseFraction receiveMatterInner(ImpreciseFraction howMuch, boolean simulate);
Fraction extractMatterOuter(Fraction howMuch, boolean simulate);
Fraction extractMatterInner(Fraction howMuch, boolean simulate);
ImpreciseFraction extractMatterOuter(ImpreciseFraction howMuch, boolean simulate);
ImpreciseFraction extractMatterInner(ImpreciseFraction howMuch, boolean simulate);
MatterDirection getDirection();
default Fraction getMissingMatter() {
default ImpreciseFraction getMissingMatter() {
return getMaxStoredMatter().minus(getStoredMatter());
}
}

View File

@ -4,30 +4,28 @@ import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.nbt.CompoundTag;
import net.minecraftforge.common.util.INBTSerializable;
import net.minecraftforge.common.util.LazyOptional;
import ru.dbotthepony.mc.otm.capability.matter.IMatterHandler;
import ru.dbotthepony.mc.otm.core.Fraction;
import ru.dbotthepony.mc.otm.matter.MatterRegistry;
import ru.dbotthepony.mc.otm.core.ImpreciseFraction;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import java.math.BigDecimal;
@MethodsReturnNonnullByDefault
@ParametersAreNonnullByDefault
public class MatterHandlerCapability implements IMatterHandler, INBTSerializable<CompoundTag> {
protected final Runnable listener;
protected Fraction stored = Fraction.ZERO;
protected ImpreciseFraction stored = ImpreciseFraction.ZERO;
protected MatterDirection direction;
protected Fraction max_storage;
protected ImpreciseFraction max_storage;
protected Fraction max_receive;
protected Fraction max_extract;
protected ImpreciseFraction max_receive;
protected ImpreciseFraction max_extract;
public MatterHandlerCapability(
@Nullable Runnable listener,
MatterDirection direction,
Fraction max_storage
ImpreciseFraction max_storage
) {
this.listener = listener;
this.direction = direction;
@ -37,9 +35,9 @@ public class MatterHandlerCapability implements IMatterHandler, INBTSerializable
public MatterHandlerCapability(
@Nullable Runnable listener,
MatterDirection direction,
Fraction max_storage,
Fraction max_receive,
Fraction max_extract
ImpreciseFraction max_storage,
ImpreciseFraction max_receive,
ImpreciseFraction max_extract
) {
this(listener, direction, max_storage);
@ -63,33 +61,33 @@ public class MatterHandlerCapability implements IMatterHandler, INBTSerializable
@Nonnull
@Override
public Fraction getStoredMatter() {
public ImpreciseFraction getStoredMatter() {
return stored;
}
@Nonnull
@Override
public Fraction getMaxStoredMatter() {
public ImpreciseFraction getMaxStoredMatter() {
return max_storage;
}
public boolean canReceiveAll(Fraction value) {
public boolean canReceiveAll(ImpreciseFraction value) {
return max_storage.compareTo(value) >= 0 && stored.plus(value).compareTo(max_storage) <= 0;
}
@Nonnull
@Override
public Fraction receiveMatterOuter(Fraction howMuch, boolean simulate) {
public ImpreciseFraction receiveMatterOuter(ImpreciseFraction howMuch, boolean simulate) {
if (getDirection() == MatterDirection.EXTRACT)
return Fraction.ZERO;
return ImpreciseFraction.ZERO;
return receiveMatterInner(howMuch, simulate);
}
@Nonnull
@Override
public Fraction receiveMatterInner(Fraction howMuch, boolean simulate) {
Fraction new_matter;
public ImpreciseFraction receiveMatterInner(ImpreciseFraction howMuch, boolean simulate) {
ImpreciseFraction new_matter;
if (max_receive == null) {
new_matter = stored.plus(howMuch).min(max_storage);
@ -97,7 +95,7 @@ public class MatterHandlerCapability implements IMatterHandler, INBTSerializable
new_matter = stored.plus(howMuch.min(max_receive)).min(max_storage);
}
Fraction diff = new_matter.minus(stored);
ImpreciseFraction diff = new_matter.minus(stored);
if (!simulate && new_matter.compareTo(stored) != 0) {
stored = new_matter;
@ -112,17 +110,17 @@ public class MatterHandlerCapability implements IMatterHandler, INBTSerializable
@Nonnull
@Override
public Fraction extractMatterOuter(Fraction howMuch, boolean simulate) {
public ImpreciseFraction extractMatterOuter(ImpreciseFraction howMuch, boolean simulate) {
if (getDirection() == MatterDirection.RECEIVE)
return Fraction.ZERO;
return ImpreciseFraction.ZERO;
return extractMatterInner(howMuch, simulate);
}
@Nonnull
@Override
public Fraction extractMatterInner(Fraction howMuch, boolean simulate) {
Fraction new_matter;
public ImpreciseFraction extractMatterInner(ImpreciseFraction howMuch, boolean simulate) {
ImpreciseFraction new_matter;
if (max_receive == null) {
new_matter = stored.minus(howMuch).moreThanZero();
@ -130,7 +128,7 @@ public class MatterHandlerCapability implements IMatterHandler, INBTSerializable
new_matter = stored.minus(howMuch.min(max_receive)).moreThanZero();
}
Fraction diff = stored.minus(new_matter);
ImpreciseFraction diff = stored.minus(new_matter);
if (!simulate && new_matter.compareTo(stored) != 0) {
stored = new_matter;
@ -167,18 +165,18 @@ public class MatterHandlerCapability implements IMatterHandler, INBTSerializable
@Override
public void deserializeNBT(CompoundTag tag) {
if (tag.contains("stored"))
stored = Fraction.deserializeNBT(tag.get("stored"));
stored = ImpreciseFraction.deserializeNBT(tag.get("stored"));
if (tag.contains("max_storage"))
max_storage = Fraction.deserializeNBT(tag.get("max_storage"));
max_storage = ImpreciseFraction.deserializeNBT(tag.get("max_storage"));
if (tag.contains("max_receive"))
max_receive = Fraction.deserializeNBT(tag.get("max_receive"));
max_receive = ImpreciseFraction.deserializeNBT(tag.get("max_receive"));
else
max_receive = null;
if (tag.contains("max_extract"))
max_extract = Fraction.deserializeNBT(tag.get("max_extract"));
max_extract = ImpreciseFraction.deserializeNBT(tag.get("max_extract"));
else
max_extract = null;
}

View File

@ -24,6 +24,7 @@ import ru.dbotthepony.mc.otm.capability.android.AndroidCapabilityPlayer;
import ru.dbotthepony.mc.otm.capability.android.IAndroidCapability;
import ru.dbotthepony.mc.otm.capability.MatteryCapability;
import ru.dbotthepony.mc.otm.core.Fraction;
import ru.dbotthepony.mc.otm.core.ImpreciseFraction;
import java.util.Optional;
import java.util.Random;
@ -160,7 +161,7 @@ public class AndroidGui {
float level;
if (android.getMaxBatteryLevel().compareTo(Fraction.ZERO) == 0) {
if (android.getMaxBatteryLevel().isZero()) {
level = 0f;
} else {
level = android.getBatteryLevel().div(android.getMaxBatteryLevel()).toFloat();

View File

@ -20,6 +20,7 @@ import ru.dbotthepony.mc.otm.OverdriveThatMatters;
import ru.dbotthepony.mc.otm.capability.MatteryCapability;
import ru.dbotthepony.mc.otm.capability.drive.IMatteryDrive;
import ru.dbotthepony.mc.otm.core.Fraction;
import ru.dbotthepony.mc.otm.core.ImpreciseFraction;
import ru.dbotthepony.mc.otm.menu.FormattingHelper;
import ru.dbotthepony.mc.otm.network.MatterRegistryPacket;
import ru.dbotthepony.mc.otm.network.MatteryNetworking;
@ -30,11 +31,11 @@ import java.math.MathContext;
import java.util.*;
public class MatterRegistry {
public static final Map<Item, Fraction> INITIAL_ITEMS = new HashMap<>();
public static final Map<Item, Fraction> ITEMS = new HashMap<>();
public static final Map<Item, ImpreciseFraction> INITIAL_ITEMS = new HashMap<>();
public static final Map<Item, ImpreciseFraction> ITEMS = new HashMap<>();
public static Fraction getMatterValue(Item item) {
return ITEMS.getOrDefault(item, INITIAL_ITEMS.getOrDefault(item, Fraction.ZERO));
public static ImpreciseFraction getMatterValue(Item item) {
return ITEMS.getOrDefault(item, INITIAL_ITEMS.getOrDefault(item, ImpreciseFraction.ZERO));
}
public static boolean hasMatterValue(Item item) {
@ -49,25 +50,25 @@ public class MatterRegistry {
}
public static boolean canDecompose(ItemStack stack) {
if (stack.getCapability(MatteryCapability.DRIVE).isPresent() && stack.getCapability(MatteryCapability.DRIVE).resolve().get().getStoredCount().compareTo(Fraction.ZERO) > 0)
if (stack.getCapability(MatteryCapability.DRIVE).isPresent() && stack.getCapability(MatteryCapability.DRIVE).resolve().get().getStoredCount().compareTo(ImpreciseFraction.ZERO) > 0)
return false;
if (stack.getCapability(MatteryCapability.MATTER).isPresent() && stack.getCapability(MatteryCapability.MATTER).resolve().get().getStoredMatter().compareTo(Fraction.ZERO) > 0)
if (stack.getCapability(MatteryCapability.MATTER).isPresent() && stack.getCapability(MatteryCapability.MATTER).resolve().get().getStoredMatter().compareTo(ImpreciseFraction.ZERO) > 0)
return false;
return hasMatterValue(stack.getItem());
}
private static Fraction getMatterValue(ItemStack stack, int level) {
private static ImpreciseFraction getMatterValue(ItemStack stack, int level) {
if (level >= 100) {
return Fraction.ZERO;
return ImpreciseFraction.ZERO;
}
Item item = stack.getItem();
var matter = getMatterValue(item);
if (item.isDamageable(stack)) {
matter = matter.times(Fraction.ONE.minus(new Fraction(item.getDamage(stack)).div(new Fraction(item.getMaxDamage(stack)))));
matter = matter.times(ImpreciseFraction.ONE.minus(new ImpreciseFraction(item.getDamage(stack)).div(new ImpreciseFraction(item.getMaxDamage(stack)))));
}
var cap1 = stack.getCapability(MatteryCapability.DRIVE).resolve();
@ -86,104 +87,104 @@ public class MatterRegistry {
return matter;
}
public static Fraction getMatterValue(ItemStack stack) {
public static ImpreciseFraction getMatterValue(ItemStack stack) {
return getMatterValue(stack, 0);
}
public static void registerInitialItems() {
// basic things
INITIAL_ITEMS.put(Items.DIRT, new Fraction("0.0013"));
INITIAL_ITEMS.put(Items.DIRT_PATH, new Fraction("0.0013"));
INITIAL_ITEMS.put(Items.GRASS_BLOCK, new Fraction("0.0016"));
INITIAL_ITEMS.put(Items.DIRT, new ImpreciseFraction("0.0013"));
INITIAL_ITEMS.put(Items.DIRT_PATH, new ImpreciseFraction("0.0013"));
INITIAL_ITEMS.put(Items.GRASS_BLOCK, new ImpreciseFraction("0.0016"));
INITIAL_ITEMS.put(Items.POINTED_DRIPSTONE, new Fraction("0.0007"));
INITIAL_ITEMS.put(Items.POINTED_DRIPSTONE, new ImpreciseFraction("0.0007"));
INITIAL_ITEMS.put(Items.STONE, new Fraction("0.001"));
INITIAL_ITEMS.put(Items.COBBLESTONE, new Fraction("0.001"));
INITIAL_ITEMS.put(Items.MOSSY_COBBLESTONE, new Fraction("0.001"));
INITIAL_ITEMS.put(Items.NETHERRACK, new Fraction("0.00027"));
INITIAL_ITEMS.put(Items.GRANITE, new Fraction("0.0011"));
INITIAL_ITEMS.put(Items.DIORITE, new Fraction("0.0013"));
INITIAL_ITEMS.put(Items.ANDESITE, new Fraction("0.0012"));
INITIAL_ITEMS.put(Items.BASALT, new Fraction("0.0013"));
INITIAL_ITEMS.put(Items.STONE, new ImpreciseFraction("0.001"));
INITIAL_ITEMS.put(Items.COBBLESTONE, new ImpreciseFraction("0.001"));
INITIAL_ITEMS.put(Items.MOSSY_COBBLESTONE, new ImpreciseFraction("0.001"));
INITIAL_ITEMS.put(Items.NETHERRACK, new ImpreciseFraction("0.00027"));
INITIAL_ITEMS.put(Items.GRANITE, new ImpreciseFraction("0.0011"));
INITIAL_ITEMS.put(Items.DIORITE, new ImpreciseFraction("0.0013"));
INITIAL_ITEMS.put(Items.ANDESITE, new ImpreciseFraction("0.0012"));
INITIAL_ITEMS.put(Items.BASALT, new ImpreciseFraction("0.0013"));
INITIAL_ITEMS.put(Items.SOUL_SAND, new Fraction("0.00087"));
INITIAL_ITEMS.put(Items.SOUL_SOIL, new Fraction("0.00087"));
INITIAL_ITEMS.put(Items.SOUL_SAND, new ImpreciseFraction("0.00087"));
INITIAL_ITEMS.put(Items.SOUL_SOIL, new ImpreciseFraction("0.00087"));
INITIAL_ITEMS.put(Items.ICE, new Fraction("0.0002"));
INITIAL_ITEMS.put(Items.ICE, new ImpreciseFraction("0.0002"));
INITIAL_ITEMS.put(Items.GRAVEL, new Fraction("0.001"));
INITIAL_ITEMS.put(Items.FLINT, new Fraction("0.001"));
INITIAL_ITEMS.put(Items.GRAVEL, new ImpreciseFraction("0.001"));
INITIAL_ITEMS.put(Items.FLINT, new ImpreciseFraction("0.001"));
INITIAL_ITEMS.put(Items.SAND, new Fraction("0.0005"));
INITIAL_ITEMS.put(Items.RED_SAND, new Fraction("0.0005"));
INITIAL_ITEMS.put(Items.SAND, new ImpreciseFraction("0.0005"));
INITIAL_ITEMS.put(Items.RED_SAND, new ImpreciseFraction("0.0005"));
INITIAL_ITEMS.put(Items.TUFF, new Fraction("0.0007"));
INITIAL_ITEMS.put(Items.DEEPSLATE, new Fraction("0.0014"));
INITIAL_ITEMS.put(Items.COBBLED_DEEPSLATE, new Fraction("0.0014"));
INITIAL_ITEMS.put(Items.TUFF, new ImpreciseFraction("0.0007"));
INITIAL_ITEMS.put(Items.DEEPSLATE, new ImpreciseFraction("0.0014"));
INITIAL_ITEMS.put(Items.COBBLED_DEEPSLATE, new ImpreciseFraction("0.0014"));
INITIAL_ITEMS.put(Items.BLACKSTONE, new Fraction("0.0015"));
INITIAL_ITEMS.put(Items.BLACKSTONE, new ImpreciseFraction("0.0015"));
INITIAL_ITEMS.put(Items.INFESTED_STONE, new Fraction("0.063"));
INITIAL_ITEMS.put(Items.INFESTED_COBBLESTONE, new Fraction("0.063"));
INITIAL_ITEMS.put(Items.INFESTED_STONE_BRICKS, new Fraction("0.063"));
INITIAL_ITEMS.put(Items.INFESTED_MOSSY_STONE_BRICKS, new Fraction("0.063"));
INITIAL_ITEMS.put(Items.INFESTED_CRACKED_STONE_BRICKS, new Fraction("0.063"));
INITIAL_ITEMS.put(Items.INFESTED_CHISELED_STONE_BRICKS, new Fraction("0.063"));
INITIAL_ITEMS.put(Items.INFESTED_DEEPSLATE, new Fraction("0.067"));
INITIAL_ITEMS.put(Items.INFESTED_STONE, new ImpreciseFraction("0.063"));
INITIAL_ITEMS.put(Items.INFESTED_COBBLESTONE, new ImpreciseFraction("0.063"));
INITIAL_ITEMS.put(Items.INFESTED_STONE_BRICKS, new ImpreciseFraction("0.063"));
INITIAL_ITEMS.put(Items.INFESTED_MOSSY_STONE_BRICKS, new ImpreciseFraction("0.063"));
INITIAL_ITEMS.put(Items.INFESTED_CRACKED_STONE_BRICKS, new ImpreciseFraction("0.063"));
INITIAL_ITEMS.put(Items.INFESTED_CHISELED_STONE_BRICKS, new ImpreciseFraction("0.063"));
INITIAL_ITEMS.put(Items.INFESTED_DEEPSLATE, new ImpreciseFraction("0.067"));
// affected by luck enchantment, thus can be duped
// INITIAL_ITEMS.put(Items.GILDED_BLACKSTONE, new Fraction("0.037"));
INITIAL_ITEMS.put(Items.GILDED_BLACKSTONE, new Fraction("0.34"));
// INITIAL_ITEMS.put(Items.GILDED_BLACKSTONE, new ImpreciseFraction("0.037"));
INITIAL_ITEMS.put(Items.GILDED_BLACKSTONE, new ImpreciseFraction("0.34"));
// assuming it is very light since it is floating
INITIAL_ITEMS.put(Items.END_STONE, new Fraction("0.0004"));
INITIAL_ITEMS.put(Items.END_STONE, new ImpreciseFraction("0.0004"));
INITIAL_ITEMS.put(Items.OBSIDIAN, new Fraction("0.038"));
INITIAL_ITEMS.put(Items.OBSIDIAN, new ImpreciseFraction("0.038"));
// metallic / chemical things
INITIAL_ITEMS.put(Items.COAL, new Fraction("0.005"));
INITIAL_ITEMS.put(Items.LAPIS_LAZULI, new Fraction("0.0042"));
INITIAL_ITEMS.put(Items.REDSTONE, new Fraction("0.004"));
INITIAL_ITEMS.put(Items.CHARCOAL, new Fraction("0.005"));
INITIAL_ITEMS.put(Items.DIAMOND, new Fraction("0.5"));
INITIAL_ITEMS.put(Items.EMERALD, new Fraction("0.46"));
INITIAL_ITEMS.put(Items.IRON_INGOT, new Fraction("0.03"));
INITIAL_ITEMS.put(Items.COPPER_INGOT, new Fraction("0.014"));
INITIAL_ITEMS.put(Items.GOLD_INGOT, new Fraction("0.32"));
INITIAL_ITEMS.put(Items.NETHERITE_SCRAP, new Fraction("1.2"));
INITIAL_ITEMS.put(Items.QUARTZ, new Fraction("0.008"));
INITIAL_ITEMS.put(Items.GLOWSTONE_DUST, new Fraction("0.007"));
INITIAL_ITEMS.put(Items.AMETHYST_SHARD, new Fraction("0.034"));
INITIAL_ITEMS.put(Items.COAL, new ImpreciseFraction("0.005"));
INITIAL_ITEMS.put(Items.LAPIS_LAZULI, new ImpreciseFraction("0.0042"));
INITIAL_ITEMS.put(Items.REDSTONE, new ImpreciseFraction("0.004"));
INITIAL_ITEMS.put(Items.CHARCOAL, new ImpreciseFraction("0.005"));
INITIAL_ITEMS.put(Items.DIAMOND, new ImpreciseFraction("0.5"));
INITIAL_ITEMS.put(Items.EMERALD, new ImpreciseFraction("0.46"));
INITIAL_ITEMS.put(Items.IRON_INGOT, new ImpreciseFraction("0.03"));
INITIAL_ITEMS.put(Items.COPPER_INGOT, new ImpreciseFraction("0.014"));
INITIAL_ITEMS.put(Items.GOLD_INGOT, new ImpreciseFraction("0.32"));
INITIAL_ITEMS.put(Items.NETHERITE_SCRAP, new ImpreciseFraction("1.2"));
INITIAL_ITEMS.put(Items.QUARTZ, new ImpreciseFraction("0.008"));
INITIAL_ITEMS.put(Items.GLOWSTONE_DUST, new ImpreciseFraction("0.007"));
INITIAL_ITEMS.put(Items.AMETHYST_SHARD, new ImpreciseFraction("0.034"));
// living things
INITIAL_ITEMS.put(Items.MOSS_BLOCK, new Fraction("0.0012"));
INITIAL_ITEMS.put(Items.MOSS_BLOCK, new ImpreciseFraction("0.0012"));
INITIAL_ITEMS.put(Items.OAK_LOG, new Fraction("0.005"));
INITIAL_ITEMS.put(Items.SPRUCE_LOG, new Fraction("0.005"));
INITIAL_ITEMS.put(Items.BIRCH_LOG, new Fraction("0.005"));
INITIAL_ITEMS.put(Items.JUNGLE_LOG, new Fraction("0.005"));
INITIAL_ITEMS.put(Items.ACACIA_LOG, new Fraction("0.005"));
INITIAL_ITEMS.put(Items.DARK_OAK_LOG, new Fraction("0.005"));
INITIAL_ITEMS.put(Items.OAK_LOG, new ImpreciseFraction("0.005"));
INITIAL_ITEMS.put(Items.SPRUCE_LOG, new ImpreciseFraction("0.005"));
INITIAL_ITEMS.put(Items.BIRCH_LOG, new ImpreciseFraction("0.005"));
INITIAL_ITEMS.put(Items.JUNGLE_LOG, new ImpreciseFraction("0.005"));
INITIAL_ITEMS.put(Items.ACACIA_LOG, new ImpreciseFraction("0.005"));
INITIAL_ITEMS.put(Items.DARK_OAK_LOG, new ImpreciseFraction("0.005"));
INITIAL_ITEMS.put(Items.BAMBOO, new Fraction("0.00085"));
INITIAL_ITEMS.put(Items.BAMBOO, new ImpreciseFraction("0.00085"));
INITIAL_ITEMS.put(Items.CRIMSON_PLANKS, new Fraction("0.003"));
INITIAL_ITEMS.put(Items.WARPED_PLANKS, new Fraction("0.003"));
INITIAL_ITEMS.put(Items.CRIMSON_PLANKS, new ImpreciseFraction("0.003"));
INITIAL_ITEMS.put(Items.WARPED_PLANKS, new ImpreciseFraction("0.003"));
INITIAL_ITEMS.put(Items.STRIPPED_OAK_LOG, new Fraction("0.005"));
INITIAL_ITEMS.put(Items.STRIPPED_SPRUCE_LOG, new Fraction("0.005"));
INITIAL_ITEMS.put(Items.STRIPPED_BIRCH_LOG, new Fraction("0.005"));
INITIAL_ITEMS.put(Items.STRIPPED_JUNGLE_LOG, new Fraction("0.005"));
INITIAL_ITEMS.put(Items.STRIPPED_ACACIA_LOG, new Fraction("0.005"));
INITIAL_ITEMS.put(Items.STRIPPED_DARK_OAK_LOG, new Fraction("0.005"));
INITIAL_ITEMS.put(Items.STRIPPED_OAK_LOG, new ImpreciseFraction("0.005"));
INITIAL_ITEMS.put(Items.STRIPPED_SPRUCE_LOG, new ImpreciseFraction("0.005"));
INITIAL_ITEMS.put(Items.STRIPPED_BIRCH_LOG, new ImpreciseFraction("0.005"));
INITIAL_ITEMS.put(Items.STRIPPED_JUNGLE_LOG, new ImpreciseFraction("0.005"));
INITIAL_ITEMS.put(Items.STRIPPED_ACACIA_LOG, new ImpreciseFraction("0.005"));
INITIAL_ITEMS.put(Items.STRIPPED_DARK_OAK_LOG, new ImpreciseFraction("0.005"));
INITIAL_ITEMS.put(Items.CACTUS, new Fraction("0.0039"));
INITIAL_ITEMS.put(Items.PUMPKIN, new Fraction("0.005"));
INITIAL_ITEMS.put(Items.MELON, new Fraction("0.005"));
INITIAL_ITEMS.put(Items.CACTUS, new ImpreciseFraction("0.0039"));
INITIAL_ITEMS.put(Items.PUMPKIN, new ImpreciseFraction("0.005"));
INITIAL_ITEMS.put(Items.MELON, new ImpreciseFraction("0.005"));
// flowers!
final Fraction flower_value = new Fraction("0.0031");
final ImpreciseFraction flower_value = new ImpreciseFraction("0.0031");
INITIAL_ITEMS.put(Items.DANDELION, flower_value);
INITIAL_ITEMS.put(Items.POPPY, flower_value);
INITIAL_ITEMS.put(Items.BLUE_ORCHID, flower_value);
@ -197,28 +198,28 @@ public class MatterRegistry {
INITIAL_ITEMS.put(Items.CORNFLOWER, flower_value);
INITIAL_ITEMS.put(Items.LILY_OF_THE_VALLEY, flower_value);
final Fraction big_flower_value = new Fraction("0.0042");
final ImpreciseFraction big_flower_value = new ImpreciseFraction("0.0042");
INITIAL_ITEMS.put(Items.SUNFLOWER, big_flower_value);
INITIAL_ITEMS.put(Items.LILAC, big_flower_value);
INITIAL_ITEMS.put(Items.ROSE_BUSH, big_flower_value);
INITIAL_ITEMS.put(Items.PEONY, big_flower_value);
INITIAL_ITEMS.put(Items.SPORE_BLOSSOM, new Fraction("0.0067"));
INITIAL_ITEMS.put(Items.BROWN_MUSHROOM, new Fraction("0.0034"));
INITIAL_ITEMS.put(Items.RED_MUSHROOM, new Fraction("0.0034"));
INITIAL_ITEMS.put(Items.CRIMSON_FUNGUS, new Fraction("0.004"));
INITIAL_ITEMS.put(Items.WARPED_FUNGUS, new Fraction("0.004"));
INITIAL_ITEMS.put(Items.SPORE_BLOSSOM, new ImpreciseFraction("0.0067"));
INITIAL_ITEMS.put(Items.BROWN_MUSHROOM, new ImpreciseFraction("0.0034"));
INITIAL_ITEMS.put(Items.RED_MUSHROOM, new ImpreciseFraction("0.0034"));
INITIAL_ITEMS.put(Items.CRIMSON_FUNGUS, new ImpreciseFraction("0.004"));
INITIAL_ITEMS.put(Items.WARPED_FUNGUS, new ImpreciseFraction("0.004"));
// grass
final Fraction grass_value = new Fraction("0.0024");
final ImpreciseFraction grass_value = new ImpreciseFraction("0.0024");
INITIAL_ITEMS.put(Items.CRIMSON_ROOTS, grass_value);
INITIAL_ITEMS.put(Items.WARPED_ROOTS, grass_value);
INITIAL_ITEMS.put(Items.NETHER_SPROUTS, new Fraction("0.002"));
INITIAL_ITEMS.put(Items.NETHER_SPROUTS, new ImpreciseFraction("0.002"));
INITIAL_ITEMS.put(Items.WEEPING_VINES, grass_value);
INITIAL_ITEMS.put(Items.TWISTING_VINES, grass_value);
INITIAL_ITEMS.put(Items.HANGING_ROOTS, grass_value);
INITIAL_ITEMS.put(Items.TALL_GRASS, new Fraction("0.0035"));
INITIAL_ITEMS.put(Items.LARGE_FERN, new Fraction("0.0035"));
INITIAL_ITEMS.put(Items.TALL_GRASS, new ImpreciseFraction("0.0035"));
INITIAL_ITEMS.put(Items.LARGE_FERN, new ImpreciseFraction("0.0035"));
INITIAL_ITEMS.put(Items.GRASS, grass_value);
INITIAL_ITEMS.put(Items.VINE, grass_value);
INITIAL_ITEMS.put(Items.LILY_PAD, grass_value);
@ -227,95 +228,95 @@ public class MatterRegistry {
INITIAL_ITEMS.put(Items.SEA_PICKLE, grass_value);
INITIAL_ITEMS.put(Items.SEAGRASS, grass_value);
INITIAL_ITEMS.put(Items.FERN, grass_value);
INITIAL_ITEMS.put(Items.DEAD_BUSH, new Fraction("0.0017"));
INITIAL_ITEMS.put(Items.GLOW_LICHEN, new Fraction("0.0026"));
INITIAL_ITEMS.put(Items.AZALEA, new Fraction("0.0018"));
INITIAL_ITEMS.put(Items.DEAD_BUSH, new ImpreciseFraction("0.0017"));
INITIAL_ITEMS.put(Items.GLOW_LICHEN, new ImpreciseFraction("0.0026"));
INITIAL_ITEMS.put(Items.AZALEA, new ImpreciseFraction("0.0018"));
INITIAL_ITEMS.put(Items.FLOWERING_AZALEA, grass_value);
// living plant (not very blocky) things
// saplings
INITIAL_ITEMS.put(Items.OAK_SAPLING, new Fraction("0.0035"));
INITIAL_ITEMS.put(Items.SPRUCE_SAPLING, new Fraction("0.0045"));
INITIAL_ITEMS.put(Items.BIRCH_SAPLING, new Fraction("0.0035"));
INITIAL_ITEMS.put(Items.JUNGLE_SAPLING, new Fraction("0.0048"));
INITIAL_ITEMS.put(Items.ACACIA_SAPLING, new Fraction("0.0033"));
INITIAL_ITEMS.put(Items.DARK_OAK_SAPLING, new Fraction("0.005"));
INITIAL_ITEMS.put(Items.OAK_SAPLING, new ImpreciseFraction("0.0035"));
INITIAL_ITEMS.put(Items.SPRUCE_SAPLING, new ImpreciseFraction("0.0045"));
INITIAL_ITEMS.put(Items.BIRCH_SAPLING, new ImpreciseFraction("0.0035"));
INITIAL_ITEMS.put(Items.JUNGLE_SAPLING, new ImpreciseFraction("0.0048"));
INITIAL_ITEMS.put(Items.ACACIA_SAPLING, new ImpreciseFraction("0.0033"));
INITIAL_ITEMS.put(Items.DARK_OAK_SAPLING, new ImpreciseFraction("0.005"));
INITIAL_ITEMS.put(Items.WHEAT_SEEDS, new Fraction("0.0007"));
INITIAL_ITEMS.put(Items.BEETROOT_SEEDS, new Fraction("0.0007"));
// INITIAL_ITEMS.put(Items.MELON_SEEDS, new Fraction("0.0013"));
INITIAL_ITEMS.put(Items.WHEAT, new Fraction("0.0016"));
INITIAL_ITEMS.put(Items.NETHER_WART, new Fraction("0.0017"));
INITIAL_ITEMS.put(Items.CARROT, new Fraction("0.0019"));
INITIAL_ITEMS.put(Items.POTATO, new Fraction("0.0021"));
INITIAL_ITEMS.put(Items.BEETROOT, new Fraction("0.0021"));
INITIAL_ITEMS.put(Items.MELON_SLICE, new Fraction("0.0008"));
INITIAL_ITEMS.put(Items.WHEAT_SEEDS, new ImpreciseFraction("0.0007"));
INITIAL_ITEMS.put(Items.BEETROOT_SEEDS, new ImpreciseFraction("0.0007"));
// INITIAL_ITEMS.put(Items.MELON_SEEDS, new ImpreciseFraction("0.0013"));
INITIAL_ITEMS.put(Items.WHEAT, new ImpreciseFraction("0.0016"));
INITIAL_ITEMS.put(Items.NETHER_WART, new ImpreciseFraction("0.0017"));
INITIAL_ITEMS.put(Items.CARROT, new ImpreciseFraction("0.0019"));
INITIAL_ITEMS.put(Items.POTATO, new ImpreciseFraction("0.0021"));
INITIAL_ITEMS.put(Items.BEETROOT, new ImpreciseFraction("0.0021"));
INITIAL_ITEMS.put(Items.MELON_SLICE, new ImpreciseFraction("0.0008"));
INITIAL_ITEMS.put(Items.COCOA_BEANS, new Fraction("0.00035"));
INITIAL_ITEMS.put(Items.HONEYCOMB, new Fraction("0.0014"));
INITIAL_ITEMS.put(Items.SUGAR_CANE, new Fraction("0.004"));
INITIAL_ITEMS.put(Items.APPLE, new Fraction("0.0061"));
INITIAL_ITEMS.put(Items.SWEET_BERRIES, new Fraction("0.0035"));
INITIAL_ITEMS.put(Items.GLOW_BERRIES, new Fraction("0.0041"));
INITIAL_ITEMS.put(Items.KELP, new Fraction("0.0009"));
INITIAL_ITEMS.put(Items.COCOA_BEANS, new ImpreciseFraction("0.00035"));
INITIAL_ITEMS.put(Items.HONEYCOMB, new ImpreciseFraction("0.0014"));
INITIAL_ITEMS.put(Items.SUGAR_CANE, new ImpreciseFraction("0.004"));
INITIAL_ITEMS.put(Items.APPLE, new ImpreciseFraction("0.0061"));
INITIAL_ITEMS.put(Items.SWEET_BERRIES, new ImpreciseFraction("0.0035"));
INITIAL_ITEMS.put(Items.GLOW_BERRIES, new ImpreciseFraction("0.0041"));
INITIAL_ITEMS.put(Items.KELP, new ImpreciseFraction("0.0009"));
// living animal things
INITIAL_ITEMS.put(Items.STRING, new Fraction("0.0006"));
INITIAL_ITEMS.put(Items.COBWEB, new Fraction("0.0006"));
INITIAL_ITEMS.put(Items.INK_SAC, new Fraction("0.0009"));
INITIAL_ITEMS.put(Items.SPIDER_EYE, new Fraction("0.001"));
INITIAL_ITEMS.put(Items.FEATHER, new Fraction("0.0007"));
INITIAL_ITEMS.put(Items.GUNPOWDER, new Fraction("0.003"));
INITIAL_ITEMS.put(Items.LEATHER, new Fraction("0.0065"));
INITIAL_ITEMS.put(Items.BONE, new Fraction("0.004"));
INITIAL_ITEMS.put(Items.ENDER_PEARL, new Fraction("0.041"));
INITIAL_ITEMS.put(Items.GHAST_TEAR, new Fraction("0.023"));
INITIAL_ITEMS.put(Items.BLAZE_ROD, new Fraction("0.02"));
INITIAL_ITEMS.put(Items.SLIME_BALL, new Fraction("0.0015"));
INITIAL_ITEMS.put(Items.EGG, new Fraction("0.0011"));
INITIAL_ITEMS.put(Items.STRING, new ImpreciseFraction("0.0006"));
INITIAL_ITEMS.put(Items.COBWEB, new ImpreciseFraction("0.0006"));
INITIAL_ITEMS.put(Items.INK_SAC, new ImpreciseFraction("0.0009"));
INITIAL_ITEMS.put(Items.SPIDER_EYE, new ImpreciseFraction("0.001"));
INITIAL_ITEMS.put(Items.FEATHER, new ImpreciseFraction("0.0007"));
INITIAL_ITEMS.put(Items.GUNPOWDER, new ImpreciseFraction("0.003"));
INITIAL_ITEMS.put(Items.LEATHER, new ImpreciseFraction("0.0065"));
INITIAL_ITEMS.put(Items.BONE, new ImpreciseFraction("0.004"));
INITIAL_ITEMS.put(Items.ENDER_PEARL, new ImpreciseFraction("0.041"));
INITIAL_ITEMS.put(Items.GHAST_TEAR, new ImpreciseFraction("0.023"));
INITIAL_ITEMS.put(Items.BLAZE_ROD, new ImpreciseFraction("0.02"));
INITIAL_ITEMS.put(Items.SLIME_BALL, new ImpreciseFraction("0.0015"));
INITIAL_ITEMS.put(Items.EGG, new ImpreciseFraction("0.0011"));
INITIAL_ITEMS.put(Items.PORKCHOP, new Fraction("0.0047"));
INITIAL_ITEMS.put(Items.BEEF, new Fraction("0.0047"));
INITIAL_ITEMS.put(Items.MUTTON, new Fraction("0.004"));
INITIAL_ITEMS.put(Items.PORKCHOP, new ImpreciseFraction("0.0047"));
INITIAL_ITEMS.put(Items.BEEF, new ImpreciseFraction("0.0047"));
INITIAL_ITEMS.put(Items.MUTTON, new ImpreciseFraction("0.004"));
INITIAL_ITEMS.put(Items.PUFFERFISH, new Fraction("0.013"));
INITIAL_ITEMS.put(Items.COD, new Fraction("0.013"));
INITIAL_ITEMS.put(Items.SALMON, new Fraction("0.013"));
INITIAL_ITEMS.put(Items.TROPICAL_FISH, new Fraction("0.013"));
INITIAL_ITEMS.put(Items.PUFFERFISH, new ImpreciseFraction("0.013"));
INITIAL_ITEMS.put(Items.COD, new ImpreciseFraction("0.013"));
INITIAL_ITEMS.put(Items.SALMON, new ImpreciseFraction("0.013"));
INITIAL_ITEMS.put(Items.TROPICAL_FISH, new ImpreciseFraction("0.013"));
// building items
INITIAL_ITEMS.put(Items.CLAY_BALL, new Fraction("0.0006"));
INITIAL_ITEMS.put(Items.SNOWBALL, new Fraction("0.00041"));
INITIAL_ITEMS.put(Items.CLAY_BALL, new ImpreciseFraction("0.0006"));
INITIAL_ITEMS.put(Items.SNOWBALL, new ImpreciseFraction("0.00041"));
// loot
INITIAL_ITEMS.put(Items.TOTEM_OF_UNDYING, new Fraction("1.47"));
INITIAL_ITEMS.put(Items.TRIDENT, new Fraction("1.35"));
INITIAL_ITEMS.put(Items.TOTEM_OF_UNDYING, new ImpreciseFraction("1.47"));
INITIAL_ITEMS.put(Items.TRIDENT, new ImpreciseFraction("1.35"));
/*
INITIAL_ITEMS.put(Items.WHITE_WOOL, new Fraction("0.004"));
INITIAL_ITEMS.put(Items.ORANGE_WOOL, new Fraction("0.004"));
INITIAL_ITEMS.put(Items.MAGENTA_WOOL, new Fraction("0.004"));
INITIAL_ITEMS.put(Items.LIGHT_BLUE_WOOL, new Fraction("0.004"));
INITIAL_ITEMS.put(Items.YELLOW_WOOL, new Fraction("0.004"));
INITIAL_ITEMS.put(Items.LIME_WOOL, new Fraction("0.004"));
INITIAL_ITEMS.put(Items.PINK_WOOL, new Fraction("0.004"));
INITIAL_ITEMS.put(Items.GRAY_WOOL, new Fraction("0.004"));
INITIAL_ITEMS.put(Items.LIGHT_GRAY_WOOL, new Fraction("0.004"));
INITIAL_ITEMS.put(Items.CYAN_WOOL, new Fraction("0.004"));
INITIAL_ITEMS.put(Items.PURPLE_WOOL, new Fraction("0.004"));
INITIAL_ITEMS.put(Items.BLUE_WOOL, new Fraction("0.004"));
INITIAL_ITEMS.put(Items.BROWN_WOOL, new Fraction("0.004"));
INITIAL_ITEMS.put(Items.GREEN_WOOL, new Fraction("0.004"));
INITIAL_ITEMS.put(Items.RED_WOOL, new Fraction("0.004"));
INITIAL_ITEMS.put(Items.BLACK_WOOL, new Fraction("0.004"));
INITIAL_ITEMS.put(Items.WHITE_WOOL, new ImpreciseFraction("0.004"));
INITIAL_ITEMS.put(Items.ORANGE_WOOL, new ImpreciseFraction("0.004"));
INITIAL_ITEMS.put(Items.MAGENTA_WOOL, new ImpreciseFraction("0.004"));
INITIAL_ITEMS.put(Items.LIGHT_BLUE_WOOL, new ImpreciseFraction("0.004"));
INITIAL_ITEMS.put(Items.YELLOW_WOOL, new ImpreciseFraction("0.004"));
INITIAL_ITEMS.put(Items.LIME_WOOL, new ImpreciseFraction("0.004"));
INITIAL_ITEMS.put(Items.PINK_WOOL, new ImpreciseFraction("0.004"));
INITIAL_ITEMS.put(Items.GRAY_WOOL, new ImpreciseFraction("0.004"));
INITIAL_ITEMS.put(Items.LIGHT_GRAY_WOOL, new ImpreciseFraction("0.004"));
INITIAL_ITEMS.put(Items.CYAN_WOOL, new ImpreciseFraction("0.004"));
INITIAL_ITEMS.put(Items.PURPLE_WOOL, new ImpreciseFraction("0.004"));
INITIAL_ITEMS.put(Items.BLUE_WOOL, new ImpreciseFraction("0.004"));
INITIAL_ITEMS.put(Items.BROWN_WOOL, new ImpreciseFraction("0.004"));
INITIAL_ITEMS.put(Items.GREEN_WOOL, new ImpreciseFraction("0.004"));
INITIAL_ITEMS.put(Items.RED_WOOL, new ImpreciseFraction("0.004"));
INITIAL_ITEMS.put(Items.BLACK_WOOL, new ImpreciseFraction("0.004"));
*/
// INITIAL_ITEMS.put(Items.CRIMSON_LOG, new Fraction("0.005"));
// INITIAL_ITEMS.put(Items.WARPED_LOG, new Fraction("0.005"));
// INITIAL_ITEMS.put(Items.CRIMSON_LOG, new ImpreciseFraction("0.005"));
// INITIAL_ITEMS.put(Items.WARPED_LOG, new ImpreciseFraction("0.005"));
}
private static void registerPostItem(Item item, Item base, Fraction multiplier) {
Fraction value = getMatterValue(base);
private static void registerPostItem(Item item, Item base, ImpreciseFraction multiplier) {
ImpreciseFraction value = getMatterValue(base);
if (!value.equals(Fraction.ZERO)) {
ITEMS.put(item, value.times(multiplier));
@ -323,12 +324,10 @@ public class MatterRegistry {
}
public static void registerPostItems() {
registerPostItem(Items.CHIPPED_ANVIL, Items.ANVIL, new Fraction("0.8"));
registerPostItem(Items.DAMAGED_ANVIL, Items.ANVIL, new Fraction("0.5"));
registerPostItem(Items.CHIPPED_ANVIL, Items.ANVIL, new ImpreciseFraction("0.8"));
registerPostItem(Items.DAMAGED_ANVIL, Items.ANVIL, new ImpreciseFraction("0.5"));
}
public static final MathContext ROUND_RULES = MatteryCapability.ROUND_RULES;
private static final HashMap<Item, ArrayList<Recipe<?>>> usages = new HashMap<>();
private static final HashMap<Item, ArrayList<Recipe<?>>> results = new HashMap<>();
private static final HashMap<Item, Integer> seen_items = new HashMap<>();
@ -341,8 +340,8 @@ public class MatterRegistry {
private static final Item[] scan_stack = new Item[1000];
@Nullable
private static Fraction determineValue(Item item) {
Fraction _get = ITEMS.get(item);
private static ImpreciseFraction determineValue(Item item) {
ImpreciseFraction _get = ITEMS.get(item);
if (_get != null) {
return _get;
@ -379,13 +378,13 @@ public class MatterRegistry {
}
}
return Fraction.ZERO;
return ImpreciseFraction.ZERO;
}
seen_items.put(item, 0);
if (!results.containsKey(item)) {
return Fraction.ZERO;
return ImpreciseFraction.ZERO;
}
scan_stack[stack_index] = item;
@ -393,32 +392,32 @@ public class MatterRegistry {
boolean defer_occured = false;
Fraction smallest_possible_total = null;
ImpreciseFraction smallest_possible_total = null;
for (Recipe<?> recipe : results.get(item)) {
ItemStack self = recipe.getResultItem();
Fraction recipe_summ = Fraction.ZERO;
ImpreciseFraction recipe_summ = ImpreciseFraction.ZERO;
boolean this_defered = false;
for (Ingredient ingredient : recipe.getIngredients()) {
ItemStack[] items = ingredient.getItems();
Fraction smallest_possible = null;
ImpreciseFraction smallest_possible = null;
for (ItemStack stack : items) {
if (!stack.isEmpty()) {
Fraction determine = determineValue(stack.getItem());
ImpreciseFraction determine = determineValue(stack.getItem());
// if we hit an recursive recipe, defer it
if (determine != null) {
if (determine.compareTo(Fraction.ZERO) == 0) {
if (determine.isZero()) {
// farewell
OverdriveThatMatters.LOGGER.debug("Cannot determine matter value for {} because value of {} is unknown", item, stack.getItem());
seen_items_child.put(item, stack.getItem());
scan_stack[stack_index] = null;
stack_index--;
return Fraction.ZERO;
return ImpreciseFraction.ZERO;
}
if (smallest_possible == null || smallest_possible.compareTo(determine) > 0)
@ -444,7 +443,7 @@ public class MatterRegistry {
if (this_defered)
continue;
recipe_summ = recipe_summ.div(new Fraction(self.getCount()));
recipe_summ = recipe_summ.div(self.getCount());
if (smallest_possible_total == null || smallest_possible_total.compareTo(recipe_summ) > 0)
smallest_possible_total = recipe_summ;
@ -469,7 +468,7 @@ public class MatterRegistry {
scan_stack[stack_index] = null;
stack_index--;
return Fraction.ZERO;
return ImpreciseFraction.ZERO;
}
private static void flood(List<? extends Recipe<?>> recipe_type) {
@ -564,9 +563,9 @@ public class MatterRegistry {
@SubscribeEvent
public static void attachItemStackTextEvent(ItemTooltipEvent event) {
if (InputConstants.isKeyDown(Minecraft.getInstance().getWindow().getWindow(), 340) || InputConstants.isKeyDown(Minecraft.getInstance().getWindow().getWindow(), 344)) {
Fraction matter_value = getMatterValue(event.getItemStack());
ImpreciseFraction matter_value = getMatterValue(event.getItemStack());
if (!matter_value.equals(Fraction.ZERO)) {
if (!matter_value.isZero()) {
event.getToolTip().add(FormattingHelper.formatMatterValue(matter_value).withStyle(ChatFormatting.AQUA));
}
}

View File

@ -7,6 +7,7 @@ import net.minecraft.network.chat.TextComponent;
import net.minecraft.network.chat.TranslatableComponent;
import ru.dbotthepony.mc.otm.OverdriveThatMatters;
import ru.dbotthepony.mc.otm.core.Fraction;
import ru.dbotthepony.mc.otm.core.ImpreciseFraction;
import javax.annotation.ParametersAreNonnullByDefault;
import java.math.BigDecimal;
@ -122,6 +123,17 @@ public class FormattingHelper {
Fraction.fromString("1000000000000000000000000"), // "otm.suffix.yotta": "Y%s",
};
public static final ImpreciseFraction[] SUFFIX_ABOVE_ONE_IM_FRAC = new ImpreciseFraction[] {
new ImpreciseFraction("1000"), // "otm.suffix.kilo": "k%s",
new ImpreciseFraction("1000000"), // "otm.suffix.mega": "M%s",
new ImpreciseFraction("1000000000"), // "otm.suffix.giga": "G%s",
new ImpreciseFraction("1000000000000"), // "otm.suffix.tera": "T%s",
new ImpreciseFraction("1000000000000000"), // "otm.suffix.peta": "P%s",
new ImpreciseFraction("1000000000000000000"), // "otm.suffix.exa": "E%s",
new ImpreciseFraction("1000000000000000000000"), // "otm.suffix.zetta": "Z%s",
new ImpreciseFraction("1000000000000000000000000"), // "otm.suffix.yotta": "Y%s",
};
public static final String[] SUFFIX_COMPONENTS_BELOW_ONE = new String[] {
"otm.suffix.deci",
"otm.suffix.centi",
@ -161,6 +173,19 @@ public class FormattingHelper {
Fraction.fromString("0.000000000000000000000001"), // "otm.suffix.yocto": "y%s",
};
public static final ImpreciseFraction[] SUFFIX_BELOW_ONE_IM_FRAC = new ImpreciseFraction[] {
new ImpreciseFraction("0.1"), // "otm.suffix.milli": "d%s",
new ImpreciseFraction("0.01"), // "otm.suffix.milli": "c%s",
new ImpreciseFraction("0.001"), // "otm.suffix.milli": "m%s",
new ImpreciseFraction("0.000001"), // "otm.suffix.micro": "μ%s",
new ImpreciseFraction("0.000000001"), // "otm.suffix.nano": "n%s",
new ImpreciseFraction("0.000000000001"), // "otm.suffix.pico": "p%s",
new ImpreciseFraction("0.000000000000001"), // "otm.suffix.femto": "f%s",
new ImpreciseFraction("0.000000000000000001"), // "otm.suffix.atto": "a%s",
new ImpreciseFraction("0.000000000000000000001"), // "otm.suffix.zepto": "z%s",
new ImpreciseFraction("0.000000000000000000000001"), // "otm.suffix.yocto": "y%s",
};
public static String formatDecimal(BigDecimal value, int decimals) {
return value.setScale(decimals, RoundingMode.HALF_UP).toString();
}
@ -176,6 +201,10 @@ public class FormattingHelper {
return new TranslatableComponent("otm.gui.level", formatSI(power, POWER_NAME), formatSI(max_power, POWER_NAME));
}
public static Component formatPowerLevel(ImpreciseFraction power, ImpreciseFraction max_power) {
return new TranslatableComponent("otm.gui.level", formatSI(power, POWER_NAME), formatSI(max_power, POWER_NAME));
}
public static Component formatMatterLevel(BigDecimal power, BigDecimal max_power) {
return new TranslatableComponent("otm.gui.level", formatMatterValuePlain(power), formatMatterValuePlain(max_power));
}
@ -184,6 +213,10 @@ public class FormattingHelper {
return new TranslatableComponent("otm.gui.level", formatMatterValuePlain(power), formatMatterValuePlain(max_power));
}
public static Component formatMatterLevel(ImpreciseFraction power, ImpreciseFraction max_power) {
return new TranslatableComponent("otm.gui.level", formatMatterValuePlain(power), formatMatterValuePlain(max_power));
}
public static TranslatableComponent formatMatterValue(BigDecimal matter) {
return new TranslatableComponent("otm.gui.matter.format", formatSI(matter, MATTER_NAME));
}
@ -192,6 +225,10 @@ public class FormattingHelper {
return new TranslatableComponent("otm.gui.matter.format", formatSI(matter, MATTER_NAME));
}
public static TranslatableComponent formatMatterValue(ImpreciseFraction matter) {
return new TranslatableComponent("otm.gui.matter.format", formatSI(matter, MATTER_NAME));
}
public static Component formatMatterValuePlain(BigDecimal matter) {
return formatSI(matter, MATTER_NAME);
}
@ -200,6 +237,10 @@ public class FormattingHelper {
return formatSI(matter, MATTER_NAME);
}
public static Component formatMatterValuePlain(ImpreciseFraction matter) {
return formatSI(matter, MATTER_NAME);
}
public static Component formatPower(BigDecimal power) {
return formatSI(power, POWER_NAME);
}
@ -208,6 +249,10 @@ public class FormattingHelper {
return formatSI(power, POWER_NAME);
}
public static Component formatPower(ImpreciseFraction power) {
return formatSI(power, POWER_NAME);
}
public static Component formatSI(BigDecimal value) {
return formatSI(value, "");
}
@ -303,4 +348,48 @@ public class FormattingHelper {
return new TranslatableComponent("otm.suffix.merge", value.decimalString(2, true), end_suffix);
}
}
public static Component formatSI(ImpreciseFraction value, Object end_suffix) {
if (value.compareTo(ImpreciseFraction.ZERO) == 0) {
if ("".equals(end_suffix)) {
return new TextComponent("0.00");
} else {
return new TranslatableComponent("otm.suffix.merge", "0.00", end_suffix);
}
}
int compare = value.compareTo(ImpreciseFraction.ONE);
if (compare == 0) {
if ("".equals(end_suffix)) {
return new TextComponent("1.00");
} else {
return new TranslatableComponent("otm.suffix.merge", "1.00", end_suffix);
}
} else if (compare > 0) {
for (int i = SUFFIX_ABOVE_ONE_IM_FRAC.length - 1; i >= 0; i--) {
if (value.compareTo(SUFFIX_ABOVE_ONE_IM_FRAC[i]) >= 0) {
return new TranslatableComponent(SUFFIX_COMPONENTS_ABOVE_ONE[i], value.div(SUFFIX_ABOVE_ONE_IM_FRAC[i]).toString(2), end_suffix);
}
}
if ("".equals(end_suffix)) {
return new TextComponent(value.toString(2));
} else {
return new TranslatableComponent("otm.suffix.merge", value.toString(2), end_suffix);
}
}
for (int i = SUFFIX_BELOW_ONE_IM_FRAC.length - 1; i >= 0; i--) {
if (value.compareTo(SUFFIX_BELOW_ONE_IM_FRAC[i]) < 0) {
return new TranslatableComponent(SUFFIX_COMPONENTS_BELOW_ONE[i], value.div(SUFFIX_BELOW_ONE_IM_FRAC[i]).toString(2), end_suffix);
}
}
if ("".equals(end_suffix)) {
return new TextComponent(value.toString(2));
} else {
return new TranslatableComponent("otm.suffix.merge", value.toString(2), end_suffix);
}
}
}

View File

@ -8,6 +8,7 @@ import net.minecraftforge.network.NetworkEvent;
import net.minecraftforge.registries.ForgeRegistry;
import net.minecraftforge.registries.RegistryManager;
import ru.dbotthepony.mc.otm.core.Fraction;
import ru.dbotthepony.mc.otm.core.ImpreciseFraction;
import ru.dbotthepony.mc.otm.matter.MatterRegistry;
import java.math.BigDecimal;
@ -15,7 +16,7 @@ import java.util.HashMap;
import java.util.Map;
import java.util.function.Supplier;
public record MatterRegistryPacket(Map<Item, Fraction> list) {
public record MatterRegistryPacket(Map<Item, ImpreciseFraction> list) {
public void write(FriendlyByteBuf buffer) {
buffer.writeInt(list.size());
var registry = (ForgeRegistry<Item>) RegistryManager.ACTIVE.getRegistry(Item.class);
@ -30,10 +31,10 @@ public record MatterRegistryPacket(Map<Item, Fraction> list) {
var size = buffer.readInt();
var registry = (ForgeRegistry<Item>) RegistryManager.ACTIVE.getRegistry(Item.class);
var map = new HashMap<Item, Fraction>();
var map = new HashMap<Item, ImpreciseFraction>();
for (int i = 0; i < size; i++) {
map.put(registry.getValue(buffer.readInt()), Fraction.read(buffer));
map.put(registry.getValue(buffer.readInt()), ImpreciseFraction.read(buffer));
}
return new MatterRegistryPacket(map);

View File

@ -7,12 +7,13 @@ import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.network.NetworkEvent;
import ru.dbotthepony.mc.otm.capability.MatteryCapability;
import ru.dbotthepony.mc.otm.core.Fraction;
import ru.dbotthepony.mc.otm.core.ImpreciseFraction;
import ru.dbotthepony.mc.otm.network.NetworkHelper;
import java.math.BigDecimal;
import java.util.function.Supplier;
public record AndroidEnergyPacket(boolean is_maximal, Fraction energy) {
public record AndroidEnergyPacket(boolean is_maximal, ImpreciseFraction energy) {
public void write(FriendlyByteBuf buffer) {
buffer.writeBoolean(is_maximal);
energy.write(buffer);
@ -40,6 +41,6 @@ public record AndroidEnergyPacket(boolean is_maximal, Fraction energy) {
}
public static AndroidEnergyPacket read(FriendlyByteBuf buffer) {
return new AndroidEnergyPacket(buffer.readBoolean(), Fraction.read(buffer));
return new AndroidEnergyPacket(buffer.readBoolean(), ImpreciseFraction.read(buffer));
}
}

View File

@ -2,6 +2,7 @@ package ru.dbotthepony.mc.otm.storage;
import net.minecraft.MethodsReturnNonnullByDefault;
import ru.dbotthepony.mc.otm.core.Fraction;
import ru.dbotthepony.mc.otm.core.ImpreciseFraction;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@ -14,7 +15,7 @@ import java.util.Objects;
public class StorageObjectRegistry {
private static final HashMap<Class<? extends IStorageStack>, StorageObjectTuple<? extends IStorageStack>> REGISTRY = new HashMap<>();
public static <T extends IStorageStack> StorageObjectTuple<T> register(Class<T> identity, T empty, Fraction energyPerOperation) {
public static <T extends IStorageStack> StorageObjectTuple<T> register(Class<T> identity, T empty, ImpreciseFraction energyPerOperation) {
final var tuple = new StorageObjectTuple<>(identity, empty, energyPerOperation);
REGISTRY.put(identity, tuple);
return tuple;

View File

@ -1,10 +1,11 @@
package ru.dbotthepony.mc.otm.storage;
import ru.dbotthepony.mc.otm.core.Fraction;
import ru.dbotthepony.mc.otm.core.ImpreciseFraction;
import javax.annotation.Nonnull;
public record StorageObjectTuple<T extends IStorageStack>(@Nonnull Class<T> identity, @Nonnull T empty, @Nonnull Fraction energyPerOperation) {
public record StorageObjectTuple<T extends IStorageStack>(@Nonnull Class<T> identity, @Nonnull T empty, @Nonnull ImpreciseFraction energyPerOperation) {
@Override
public boolean equals(Object obj) {
if (obj instanceof StorageObjectTuple tuple)

View File

@ -14,6 +14,7 @@ import ru.dbotthepony.mc.otm.Registry
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.MatteryMachineEnergyStorage
import ru.dbotthepony.mc.otm.core.Fraction
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.menu.AndroidStationMenu
class BlockEntityAndroidStation(p_155229_: BlockPos, p_155230_: BlockState) :
@ -31,9 +32,9 @@ class BlockEntityAndroidStation(p_155229_: BlockPos, p_155230_: BlockState) :
energy = MatteryMachineEnergyStorage(
this,
MatteryMachineEnergyStorage.MachineType.WORKER,
Fraction(100000),
Fraction(250),
Fraction(250)
ImpreciseFraction(100000),
ImpreciseFraction(250),
ImpreciseFraction(250)
)
}
@ -53,10 +54,10 @@ class BlockEntityAndroidStation(p_155229_: BlockPos, p_155230_: BlockState) :
val missing = it.missingPower
if (missing > Fraction.ZERO) {
if (missing > ImpreciseFraction.ZERO) {
val extract = energy.extractEnergyInner(missing, true)
if (extract > Fraction.ZERO) {
if (extract > ImpreciseFraction.ZERO) {
val received = it.receiveEnergyOuter(extract, false)
energy.extractEnergyInner(received, false)
}

View File

@ -28,6 +28,7 @@ import ru.dbotthepony.mc.otm.capability.extractEnergy
import ru.dbotthepony.mc.otm.capability.receiveEnergy
import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.core.Fraction
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.menu.MenuBatteryBank
import ru.dbotthepony.mc.otm.set
import ru.dbotthepony.mc.otm.unaryMinus
@ -61,16 +62,16 @@ class BlockEntityBatteryBank(p_155229_: BlockPos, p_155230_: BlockState) : Block
{ slot: Int, amount: Int, stack: ItemStack? -> true }
)
private data class BatteryBankDistribution(val distribution: Array<Fraction>, val maxThroughput: Fraction)
private data class BatteryBankDistribution(val distribution: Array<ImpreciseFraction>, val maxThroughput: ImpreciseFraction)
private enum class BankMode { RECEIVE, EXTRACT, BIDIRECTIONAL }
private inner class BatteryBankEnergy(private val mode: BankMode) : IMatteryEnergyStorage {
override fun canExtract() = mode != BankMode.RECEIVE
override fun canReceive() = mode != BankMode.EXTRACT
override fun extractEnergyOuter(howMuch: Fraction, simulate: Boolean): Fraction {
override fun extractEnergyOuter(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
if (mode == BankMode.RECEIVE)
return Fraction.ZERO
return ImpreciseFraction.ZERO
return extractEnergyInner(howMuch, simulate)
}
@ -79,8 +80,8 @@ class BlockEntityBatteryBank(p_155229_: BlockPos, p_155230_: BlockState) : Block
* [mode] = true на приём, false на отдачу
*/
fun getDistribution(mode: Boolean): BatteryBankDistribution {
val distribution = Array(container.containerSize) { Fraction.ZERO }
var summ = Fraction.ZERO
val distribution = Array(container.containerSize) { ImpreciseFraction.ZERO }
var summ = ImpreciseFraction.ZERO
for (i in 0 until container.containerSize) {
val stack = container.getItem(i)
@ -88,12 +89,12 @@ class BlockEntityBatteryBank(p_155229_: BlockPos, p_155230_: BlockState) : Block
if (!stack.isEmpty) {
stack.getCapability(CapabilityEnergy.ENERGY).ifPresent {
if (it is IMatteryEnergyStorage) {
val diff: Fraction
val diff: ImpreciseFraction
if (mode) {
diff = it.receiveEnergyOuter(MatteryCapability.LONG_MAX_VALUE, true)
diff = it.receiveEnergyOuter(ImpreciseFraction.LONG_MAX_VALUE, true)
} else {
diff = it.extractEnergyOuter(MatteryCapability.LONG_MAX_VALUE, true)
diff = it.extractEnergyOuter(ImpreciseFraction.LONG_MAX_VALUE, true)
}
distribution[i] = diff
@ -102,19 +103,19 @@ class BlockEntityBatteryBank(p_155229_: BlockPos, p_155230_: BlockState) : Block
val diff: Int
if (mode) {
diff = it.receiveEnergy(MatteryCapability.LONG_MAX_VALUE, true)
diff = it.receiveEnergy(ImpreciseFraction.LONG_MAX_VALUE, true)
} else {
diff = it.extractEnergy(MatteryCapability.LONG_MAX_VALUE, true)
diff = it.extractEnergy(ImpreciseFraction.LONG_MAX_VALUE, true)
}
distribution[i] = Fraction(diff)
distribution[i] = ImpreciseFraction(diff)
summ += distribution[i]
}
}
}
}
if (!summ.isZero()) {
if (!summ.isZero) {
for (i in 0 until container.containerSize) {
distribution[i] = distribution[i] / summ
}
@ -123,23 +124,23 @@ class BlockEntityBatteryBank(p_155229_: BlockPos, p_155230_: BlockState) : Block
return BatteryBankDistribution(distribution, summ)
}
private fun distributeEnergy(mode: Boolean, howMuch: Fraction, simulate: Boolean): Fraction {
private fun distributeEnergy(mode: Boolean, howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
val distribution = getDistribution(mode)
if (distribution.maxThroughput.isZero())
return Fraction.ZERO
if (distribution.maxThroughput.isZero)
return ImpreciseFraction.ZERO
val distList: Array<Fraction> = distribution.distribution
var summ = Fraction.ZERO
val distList = distribution.distribution
var summ = ImpreciseFraction.ZERO
for (i in 0 until container.containerSize) {
if (!distList[i].isZero()) {
if (!distList[i].isZero) {
val stack = container.getItem(i)
if (!stack.isEmpty) {
stack.getCapability(CapabilityEnergy.ENERGY).ifPresent {
if (it is IMatteryEnergyStorage) {
val diff: Fraction
val diff: ImpreciseFraction
if (mode) {
diff = it.receiveEnergyOuter(howMuch * distList[i], simulate)
@ -157,37 +158,37 @@ class BlockEntityBatteryBank(p_155229_: BlockPos, p_155230_: BlockState) : Block
diff = it.extractEnergy(howMuch * distList[i], simulate)
}
summ += Fraction(diff)
summ += ImpreciseFraction(diff)
}
}
}
}
}
if (!simulate && !summ.isZero()) {
if (!simulate && !summ.isZero) {
setChangedLight()
}
return summ
}
override fun extractEnergyInner(howMuch: Fraction, simulate: Boolean): Fraction {
override fun extractEnergyInner(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
return distributeEnergy(false, howMuch, simulate)
}
override fun receiveEnergyOuter(howMuch: Fraction, simulate: Boolean): Fraction {
override fun receiveEnergyOuter(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
if (mode == BankMode.EXTRACT)
return Fraction.ZERO
return ImpreciseFraction.ZERO
return receiveEnergyInner(howMuch, simulate)
}
override fun receiveEnergyInner(howMuch: Fraction, simulate: Boolean): Fraction {
override fun receiveEnergyInner(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
return distributeEnergy(true, howMuch, simulate)
}
override val batteryLevel: Fraction get() {
var result = Fraction.ZERO
override val batteryLevel: ImpreciseFraction get() {
var result = ImpreciseFraction.ZERO
for (i in 0 until container.containerSize) {
val stack = container.getItem(i)
@ -206,8 +207,8 @@ class BlockEntityBatteryBank(p_155229_: BlockPos, p_155230_: BlockState) : Block
return result
}
override val maxBatteryLevel: Fraction get() {
var result = Fraction.ZERO
override val maxBatteryLevel: ImpreciseFraction get() {
var result = ImpreciseFraction.ZERO
for (i in 0 until container.containerSize) {
val stack = container.getItem(i)
@ -329,13 +330,13 @@ class BlockEntityBatteryBank(p_155229_: BlockPos, p_155230_: BlockState) : Block
outputCapability.ifPresent {
val (_, maxThroughput) = energy.getDistribution(false)
if (maxThroughput.isZero())
if (maxThroughput.isZero)
return@ifPresent
if (it is IMatteryEnergyStorage) {
val diff = it.receiveEnergyOuter(maxThroughput, false)
if (!diff.isZero()) {
if (!diff.isZero) {
energy.extractEnergyInner(diff, false)
}
} else {

View File

@ -29,6 +29,7 @@ import ru.dbotthepony.mc.otm.capability.MatteryMachineEnergyStorage
import ru.dbotthepony.mc.otm.capability.receiveEnergy
import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.core.Fraction
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.core.plus
import ru.dbotthepony.mc.otm.menu.MenuChemicalGenerator
import java.lang.ref.WeakReference
@ -181,7 +182,7 @@ class BlockEntityChemicalGenerator(pos: BlockPos, state: BlockState) : BlockEnti
val extracted = energy.extractEnergyInner(demand, true)
val received = it.receiveEnergyOuter(extracted, false)
if (!received.isZero()) {
if (!received.isZero) {
energy.extractEnergyInner(received, false)
}
} else {
@ -218,7 +219,7 @@ class BlockEntityChemicalGenerator(pos: BlockPos, state: BlockState) : BlockEnti
val residue = container[SLOT_INPUT].item.getContainerItem(container[SLOT_INPUT].copy().also { it.count = 1 })
val canPutResidue = residue.isEmpty || container[SLOT_RESIDUE].isEmpty || ItemStack.isSameItemSameTags(container[SLOT_RESIDUE], residue) && container[SLOT_RESIDUE].count < container[2].maxStackSize
if (canPutResidue && ticks >= 4 && (energy.batteryLevel < Fraction.ONE || GENERATION_SPEED * (ticks / 4) + energy.batteryLevel <= energy.maxBatteryLevel)) {
if (canPutResidue && ticks >= 4 && (energy.batteryLevel < ImpreciseFraction.ONE || GENERATION_SPEED * (ticks / 4) + energy.batteryLevel <= energy.maxBatteryLevel)) {
workingTicksTotal = ticks / 4
workingTicks = ticks / 4
container[SLOT_INPUT].shrink(1)
@ -238,13 +239,13 @@ class BlockEntityChemicalGenerator(pos: BlockPos, state: BlockState) : BlockEnti
check = false
}
if (energy.batteryLevel.isZero()) return
if (energy.batteryLevel.isZero) return
val item = container[SLOT_BATTERY]
if (!item.isEmpty) {
item.getCapability(CapabilityEnergy.ENERGY).ifPresent(this::workWithPower)
if (energy.batteryLevel.isZero()) return
if (energy.batteryLevel.isZero) return
}
for (consumer in consumers) {
@ -253,10 +254,10 @@ class BlockEntityChemicalGenerator(pos: BlockPos, state: BlockState) : BlockEnti
}
companion object {
private val THROUGHPUT = Fraction(160)
private val THROUGHPUT = ImpreciseFraction(160)
private const val THROUGHPUT_INT = 160
private val GENERATION_SPEED = Fraction(40)
private val MAX_ENERGY = Fraction(24_000)
private val GENERATION_SPEED = ImpreciseFraction(40)
private val MAX_ENERGY = ImpreciseFraction(24_000)
private val NAME = TranslatableComponent("block.overdrive_that_matters.chemical_generator")
const val SLOT_INPUT = 0

View File

@ -20,6 +20,7 @@ import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.MatteryMachineEnergyStorage
import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.core.Fraction
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.ifHas
import ru.dbotthepony.mc.otm.menu.MenuDriveRack
import ru.dbotthepony.mc.otm.set
@ -67,7 +68,7 @@ class BlockEntityDriveRack(p_155229_: BlockPos, p_155230_: BlockState) :
}
init {
energy = MatteryMachineEnergyStorage(this, MatteryMachineEnergyStorage.MachineType.WORKER, Fraction(80000))
energy = MatteryMachineEnergyStorage(this, MatteryMachineEnergyStorage.MachineType.WORKER, ImpreciseFraction(80000))
}
fun tick() {

View File

@ -19,6 +19,7 @@ import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.MatteryMachineEnergyStorage
import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.core.Fraction
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.menu.MenuDriveViewer
import ru.dbotthepony.mc.otm.set
import javax.annotation.ParametersAreNonnullByDefault
@ -77,7 +78,7 @@ class BlockEntityDriveViewer(p_155229_: BlockPos, p_155230_: BlockState) : Block
}
init {
energy = MatteryMachineEnergyStorage(this, MatteryMachineEnergyStorage.MachineType.WORKER, Fraction(30000))
energy = MatteryMachineEnergyStorage(this, MatteryMachineEnergyStorage.MachineType.WORKER, ImpreciseFraction(30000))
}
override fun getDefaultDisplayName(): Component {

View File

@ -29,12 +29,13 @@ 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.core.ImpreciseFraction
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) {
data class EnergyCounterPacket(val pos: BlockPos, val thisTick: ImpreciseFraction, val total: ImpreciseFraction, val index: Int, val value: ImpreciseFraction) {
fun write(buff: FriendlyByteBuf) {
buff.writeBlockPos(pos)
thisTick.write(buff)
@ -60,35 +61,35 @@ data class EnergyCounterPacket(val pos: BlockPos, val thisTick: Fraction, val to
companion object {
fun read(buff: FriendlyByteBuf): EnergyCounterPacket {
val pos = buff.readBlockPos()
val thisTick = Fraction.read(buff)
val total = Fraction.read(buff)
val thisTick = ImpreciseFraction.read(buff)
val total = ImpreciseFraction.read(buff)
val index = buff.readInt()
val value = Fraction.read(buff)
val value = ImpreciseFraction.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
var passed = ImpreciseFraction.ZERO
internal set
private val history = Array(10 * 20) { Fraction.ZERO }
private val history = Array(10 * 20) { ImpreciseFraction.ZERO }
private var historyTick = 0
fun size() = history.size
operator fun get(i: Int) = history[i]
internal operator fun set(i: Int, value: Fraction) {
internal operator fun set(i: Int, value: ImpreciseFraction) {
history[i] = value
}
var lastTick: Fraction = Fraction.ZERO
var lastTick = ImpreciseFraction.ZERO
internal set
fun getHistory(ticks: Int): Array<Fraction> {
fun getHistory(ticks: Int): Array<ImpreciseFraction> {
require(!(ticks < 1 || ticks >= history.size)) { "Invalid history length provided" }
val history = Array(ticks) { Fraction.ZERO }
val history = Array(ticks) { ImpreciseFraction.ZERO }
for (i in 0 until ticks) {
var index = (historyTick - i) % this.history.size
@ -99,14 +100,14 @@ class BlockEntityEnergyCounter(p_155229_: BlockPos, p_155230_: BlockState) : Blo
return history
}
fun calcAverage(ticks: Int): Fraction {
fun calcAverage(ticks: Int): ImpreciseFraction {
return sumHistory(ticks) / ticks
}
fun sumHistory(ticks: Int): Fraction {
fun sumHistory(ticks: Int): ImpreciseFraction {
require(!(ticks < 1 || ticks >= history.size)) { "Invalid history length provided" }
var value = Fraction.ZERO
var value = ImpreciseFraction.ZERO
for (i in 0 until ticks) {
var index = (historyTick - i) % history.size
@ -133,7 +134,7 @@ class BlockEntityEnergyCounter(p_155229_: BlockPos, p_155230_: BlockState) : Blo
super.load(nbt)
nbt.ifHas(("passed")) {
passed = Fraction.deserializeNBT(it)
passed = ImpreciseFraction.deserializeNBT(it)
}
nbt.ifHas(("history_tick"), IntTag::class.java) {
@ -143,7 +144,7 @@ class BlockEntityEnergyCounter(p_155229_: BlockPos, p_155230_: BlockState) : Blo
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
history[i] = if (bytes != null) ImpreciseFraction.deserializeNBT(bytes) else ImpreciseFraction.ZERO
}
}
}
@ -172,23 +173,23 @@ class BlockEntityEnergyCounter(p_155229_: BlockPos, p_155230_: BlockState) : Blo
}
private inner class EnergyCounterCap(val is_input: Boolean) : IMatteryEnergyStorage {
override fun extractEnergyOuter(howMuch: Fraction, simulate: Boolean): Fraction {
override fun extractEnergyOuter(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
return extractEnergyInner(howMuch, simulate)
}
override fun extractEnergyInner(howMuch: Fraction, simulate: Boolean): Fraction {
override fun extractEnergyInner(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
if (is_input)
return Fraction.ZERO
return ImpreciseFraction.ZERO
if (inputCapability.isPresent) {
val it = inputCapability.resolve().get()
val diff: Fraction
val diff: ImpreciseFraction
if (it is IMatteryEnergyStorage) {
diff = it.extractEnergyOuter(howMuch, simulate)
} else {
diff = Fraction(it.extractEnergy(howMuch, simulate))
diff = ImpreciseFraction(it.extractEnergy(howMuch, simulate))
}
if (!simulate) {
@ -199,26 +200,26 @@ class BlockEntityEnergyCounter(p_155229_: BlockPos, p_155230_: BlockState) : Blo
return diff
}
return Fraction.ZERO
return ImpreciseFraction.ZERO
}
override fun receiveEnergyOuter(howMuch: Fraction, simulate: Boolean): Fraction {
override fun receiveEnergyOuter(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
return receiveEnergyInner(howMuch, simulate)
}
override fun receiveEnergyInner(howMuch: Fraction, simulate: Boolean): Fraction {
override fun receiveEnergyInner(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
if (!is_input)
return Fraction.ZERO
return ImpreciseFraction.ZERO
if (outputCapability.isPresent) {
val it = outputCapability.resolve().get()
val diff: Fraction
val diff: ImpreciseFraction
if (it is IMatteryEnergyStorage) {
diff = it.receiveEnergyOuter(howMuch, simulate)
} else {
diff = Fraction(it.receiveEnergy(howMuch, simulate))
diff = ImpreciseFraction(it.receiveEnergy(howMuch, simulate))
}
if (!simulate) {
@ -229,10 +230,10 @@ class BlockEntityEnergyCounter(p_155229_: BlockPos, p_155230_: BlockState) : Blo
return diff
}
return Fraction.ZERO
return ImpreciseFraction.ZERO
}
override val batteryLevel: Fraction
override val batteryLevel: ImpreciseFraction
get() {
if (is_input) {
if (outputCapability.isPresent) {
@ -242,7 +243,7 @@ class BlockEntityEnergyCounter(p_155229_: BlockPos, p_155230_: BlockState) : Blo
return it.batteryLevel
}
return Fraction(it.energyStored)
return ImpreciseFraction(it.energyStored)
}
} else {
if (inputCapability.isPresent) {
@ -252,14 +253,14 @@ class BlockEntityEnergyCounter(p_155229_: BlockPos, p_155230_: BlockState) : Blo
return it.batteryLevel
}
return Fraction(it.energyStored)
return ImpreciseFraction(it.energyStored)
}
}
return Fraction.ZERO
return ImpreciseFraction.ZERO
}
override val maxBatteryLevel: Fraction
override val maxBatteryLevel: ImpreciseFraction
get() {
if (is_input) {
if (outputCapability.isPresent) {
@ -269,7 +270,7 @@ class BlockEntityEnergyCounter(p_155229_: BlockPos, p_155230_: BlockState) : Blo
return it.maxBatteryLevel
}
return Fraction(it.maxEnergyStored)
return ImpreciseFraction(it.maxEnergyStored)
}
} else {
if (inputCapability.isPresent) {
@ -279,14 +280,14 @@ class BlockEntityEnergyCounter(p_155229_: BlockPos, p_155230_: BlockState) : Blo
return it.maxBatteryLevel
}
return Fraction(it.maxEnergyStored)
return ImpreciseFraction(it.maxEnergyStored)
}
}
return Fraction.ZERO
return ImpreciseFraction.ZERO
}
override val missingPower: Fraction
override val missingPower: ImpreciseFraction
get() {
if (is_input) {
if (outputCapability.isPresent) {
@ -296,7 +297,7 @@ class BlockEntityEnergyCounter(p_155229_: BlockPos, p_155230_: BlockState) : Blo
return it.missingPower
}
return Fraction((it.maxEnergyStored - it.energyStored).coerceAtLeast(0))
return ImpreciseFraction((it.maxEnergyStored - it.energyStored).coerceAtLeast(0))
}
} else {
if (inputCapability.isPresent) {
@ -306,11 +307,11 @@ class BlockEntityEnergyCounter(p_155229_: BlockPos, p_155230_: BlockState) : Blo
return it.missingPower
}
return Fraction((it.maxEnergyStored - it.energyStored).coerceAtLeast(0))
return ImpreciseFraction((it.maxEnergyStored - it.energyStored).coerceAtLeast(0))
}
}
return Fraction.ZERO
return ImpreciseFraction.ZERO
}
override fun canExtract() = !is_input
@ -423,7 +424,7 @@ class BlockEntityEnergyCounter(p_155229_: BlockPos, p_155230_: BlockState) : Blo
val index = historyTick
historyTick = (historyTick + 1) % history.size
val accumulated = history[historyTick]
history[historyTick] = Fraction.ZERO
history[historyTick] = ImpreciseFraction.ZERO
MatteryNetworking.CHANNEL.send(PacketDistributor.NEAR.with(this::distributor), EnergyCounterPacket(blockPos, lastTick, passed, index, accumulated))
}

View File

@ -17,6 +17,7 @@ import ru.dbotthepony.mc.otm.graph.storage.BasicStorageGraphNode
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.MatteryMachineEnergyStorage
import ru.dbotthepony.mc.otm.core.Fraction
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.menu.MenuItemMonitor
import ru.dbotthepony.mc.otm.graph.storage.StorageNetworkGraph
@ -27,7 +28,7 @@ class BlockEntityItemMonitor(p_155229_: BlockPos, p_155230_: BlockState) :
val cell = BasicStorageGraphNode()
init {
energy = MatteryMachineEnergyStorage(this, MatteryMachineEnergyStorage.MachineType.WORKER, Fraction(80_000))
energy = MatteryMachineEnergyStorage(this, MatteryMachineEnergyStorage.MachineType.WORKER, ImpreciseFraction(80_000))
}
fun tick() {

View File

@ -26,6 +26,7 @@ import ru.dbotthepony.mc.otm.capability.matter.IMatterHandler.MatterDirection
import ru.dbotthepony.mc.otm.capability.matter.MatterHandlerCapability
import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.core.Fraction
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.graph.Graph6Node
import ru.dbotthepony.mc.otm.graph.matter.IMatterGraphNode
import ru.dbotthepony.mc.otm.graph.matter.MatterNetworkGraph
@ -106,13 +107,13 @@ class BlockEntityMatterBottler(p_155229_: BlockPos, p_155230_: BlockState) :
@JvmField
val matter: MatterHandlerCapability =
object : MatterHandlerCapability(this::setChangedLight, MatterDirection.BIDIRECTIONAL, Fraction(4)) {
object : MatterHandlerCapability(this::setChangedLight, MatterDirection.BIDIRECTIONAL, CAPACITY) {
override fun getDirection(): MatterDirection {
return if (this@BlockEntityMatterBottler.workFlow) MatterDirection.RECEIVE else MatterDirection.EXTRACT
}
}
private var initialCapacity: Fraction? = null
private var initialCapacity: ImpreciseFraction? = null
private var lastWorkStack: ItemStack? = null
override fun getMatterHandler(): IMatterHandler {
@ -200,18 +201,18 @@ class BlockEntityMatterBottler(p_155229_: BlockPos, p_155230_: BlockState) :
val cap = resolver.get()
if (this.workFlow) {
if (cap.maxStoredMatter - initialCapacity!! <= Fraction.ZERO) {
if (cap.maxStoredMatter - initialCapacity!! <= ImpreciseFraction.ZERO) {
return 0f
}
return ((cap.storedMatter - initialCapacity!!) / (cap.maxStoredMatter - initialCapacity!!)).toFloat()
}
if (initialCapacity!! <= Fraction.ZERO) {
if (initialCapacity!! <= ImpreciseFraction.ZERO) {
return 0f
}
return (Fraction.ONE - cap.storedMatter / initialCapacity!!).toFloat()
return (ImpreciseFraction.ONE - cap.storedMatter / initialCapacity!!).toFloat()
}
override fun setRemoved() {
@ -224,7 +225,7 @@ class BlockEntityMatterBottler(p_155229_: BlockPos, p_155230_: BlockState) :
if (isBlockedByRedstone) {
if (blockState.getValue(WorkerState.SEMI_WORKER_STATE) !== WorkerState.IDLE) {
level!!.setBlock(
level?.setBlock(
blockPos,
blockState.setValue(WorkerState.SEMI_WORKER_STATE, WorkerState.IDLE),
Block.UPDATE_CLIENTS
@ -247,7 +248,7 @@ class BlockEntityMatterBottler(p_155229_: BlockPos, p_155230_: BlockState) :
val cap = itemStack.getCapability(MatteryCapability.MATTER).resolve()
if (cap.isPresent && cap.get().direction !== unexpectedDirection) {
if (this.workFlow && cap.get().missingMatter > Fraction.ZERO || !this.workFlow && cap.get().storedMatter > Fraction.ZERO) {
if (this.workFlow && cap.get().missingMatter > ImpreciseFraction.ZERO || !this.workFlow && cap.get().storedMatter > ImpreciseFraction.ZERO) {
work_stack = itemStack
capability = cap.get()
work_slot = i
@ -269,7 +270,7 @@ class BlockEntityMatterBottler(p_155229_: BlockPos, p_155230_: BlockState) :
if (capability != null) {
if (blockState.getValue(WorkerState.SEMI_WORKER_STATE) !== WorkerState.WORKING) {
level!!.setBlock(blockPos, blockState.setValue(WorkerState.SEMI_WORKER_STATE, WorkerState.WORKING), Block.UPDATE_CLIENTS)
level?.setBlock(blockPos, blockState.setValue(WorkerState.SEMI_WORKER_STATE, WorkerState.WORKING), Block.UPDATE_CLIENTS)
}
if (workFlow) {
@ -278,25 +279,25 @@ class BlockEntityMatterBottler(p_155229_: BlockPos, p_155230_: BlockState) :
matter.missingMatter.min(MATTER_EXCHANGE_RATE * EXTRACTION_TICKS, capability.missingMatter - matter.storedMatter), true
)
if (extracted > Fraction.ZERO) {
if (extracted > ImpreciseFraction.ZERO) {
val received = matter.receiveMatterOuter(extracted, false)
graph.extractMatter(received, false)
}
}
if (matter.storedMatter > Fraction.ZERO) {
if (matter.storedMatter > ImpreciseFraction.ZERO) {
val energyExtracted = energy.extractEnergyInner(ENERGY_CONSUMPTION, true)
if (!energyExtracted.isZero()) {
val matter = capability.receiveMatterOuter(MATTER_EXCHANGE_RATE.min(matter.storedMatter) * (energyExtracted / ENERGY_CONSUMPTION), true)
if (!energyExtracted.isZero) {
val matter = capability.receiveMatterOuter(MATTER_EXCHANGE_RATE.min(matter.storedMatter) * energyExtracted / ENERGY_CONSUMPTION, true)
if (!matter.isZero()) {
energy.extractEnergyInner(ENERGY_CONSUMPTION * matter / MATTER_EXCHANGE_RATE,false)
if (!matter.isZero) {
energy.extractEnergyInner(ENERGY_CONSUMPTION * matter / MATTER_EXCHANGE_RATE, false)
capability.receiveMatterOuter(matter, false)
this.matter.extractMatterInner(matter, false)
if (capability.missingMatter.isZero()) {
if (capability.missingMatter.isZero) {
for (i in 3..5) {
if (container.getItem(i).isEmpty) {
container.setItem(work_slot, ItemStack.EMPTY)
@ -311,16 +312,16 @@ class BlockEntityMatterBottler(p_155229_: BlockPos, p_155230_: BlockState) :
} else {
val energyExtracted = energy.extractEnergyInner(ENERGY_CONSUMPTION, true)
if (!energyExtracted.isZero()) {
if (!energyExtracted.isZero) {
val matter = capability.extractMatterOuter(MATTER_EXCHANGE_RATE.min(matter.missingMatter) * energyExtracted / ENERGY_CONSUMPTION, true)
if (!matter.isZero()) {
this.energy.extractEnergyInner(ENERGY_CONSUMPTION * matter / MATTER_EXCHANGE_RATE,false)
if (!matter.isZero) {
this.energy.extractEnergyInner(ENERGY_CONSUMPTION * (matter / MATTER_EXCHANGE_RATE).toDouble(),false)
capability.extractMatterOuter(matter, false)
this.matter.receiveMatterInner(matter, false)
if (capability.storedMatter.isZero()) {
if (capability.storedMatter.isZero) {
for (i in 2 downTo 0) {
if (container.getItem(i).isEmpty) {
container.setItem(work_slot, ItemStack.EMPTY)
@ -336,7 +337,7 @@ class BlockEntityMatterBottler(p_155229_: BlockPos, p_155230_: BlockState) :
level!!.setBlock(blockPos, blockState.setValue(WorkerState.SEMI_WORKER_STATE, WorkerState.IDLE), Block.UPDATE_CLIENTS)
}
if (!workFlow && !matter.storedMatter.isZero() && graph != null) {
if (!workFlow && !matter.storedMatter.isZero && graph != null) {
val diff = matter.extractMatterInner(matter.storedMatter, true)
val diff2 = graph.receiveMatter(diff, true)
matter.extractMatterInner(diff2, false)
@ -346,8 +347,9 @@ class BlockEntityMatterBottler(p_155229_: BlockPos, p_155230_: BlockState) :
companion object {
private val MACHINE_NAME = TranslatableComponent("block.overdrive_that_matters.matter_bottler")
private val MATTER_EXCHANGE_RATE = Fraction("0.04")
private val ENERGY_CONSUMPTION = Fraction(20)
private val EXTRACTION_TICKS = Fraction(200)
private val MATTER_EXCHANGE_RATE = ImpreciseFraction("0.04")
private val ENERGY_CONSUMPTION = ImpreciseFraction(20)
private val EXTRACTION_TICKS = ImpreciseFraction(200)
private val CAPACITY = ImpreciseFraction(4)
}
}

View File

@ -23,6 +23,7 @@ import ru.dbotthepony.mc.otm.capability.matter.IMatterHandler
import ru.dbotthepony.mc.otm.capability.matter.IMatterHandler.MatterDirection
import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.core.Fraction
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.graph.Graph6Node
import ru.dbotthepony.mc.otm.graph.matter.IMatterGraphNode
import ru.dbotthepony.mc.otm.graph.matter.MatterNetworkGraph
@ -42,8 +43,8 @@ class BlockEntityMatterCapacitorBank(p_155229_: BlockPos, p_155230_: BlockState)
return node
}
override fun getStoredMatter(): Fraction {
var summ = Fraction.ZERO
override fun getStoredMatter(): ImpreciseFraction {
var summ = ImpreciseFraction.ZERO
for (stack in container)
if (!stack.isEmpty)
@ -54,8 +55,8 @@ class BlockEntityMatterCapacitorBank(p_155229_: BlockPos, p_155230_: BlockState)
return summ
}
override fun getMaxStoredMatter(): Fraction {
var summ = Fraction.ZERO
override fun getMaxStoredMatter(): ImpreciseFraction {
var summ = ImpreciseFraction.ZERO
for (stack in container)
if (!stack.isEmpty)
@ -66,13 +67,13 @@ class BlockEntityMatterCapacitorBank(p_155229_: BlockPos, p_155230_: BlockState)
return summ
}
override fun receiveMatterOuter(howMuch: Fraction, simulate: Boolean): Fraction {
override fun receiveMatterOuter(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
return receiveMatterInner(howMuch, simulate)
}
override fun receiveMatterInner(howMuch: Fraction, simulate: Boolean): Fraction {
override fun receiveMatterInner(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
var howMuch = howMuch
var summ = Fraction.ZERO
var summ = ImpreciseFraction.ZERO
for (stack in container) {
if (!stack.isEmpty) {
@ -82,7 +83,7 @@ class BlockEntityMatterCapacitorBank(p_155229_: BlockPos, p_155230_: BlockState)
howMuch -= diff
}
if (howMuch.isZero()) {
if (howMuch.isZero) {
break
}
}
@ -91,13 +92,13 @@ class BlockEntityMatterCapacitorBank(p_155229_: BlockPos, p_155230_: BlockState)
return summ
}
override fun extractMatterOuter(howMuch: Fraction, simulate: Boolean): Fraction {
override fun extractMatterOuter(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
return extractMatterInner(howMuch, simulate)
}
override fun extractMatterInner(howMuch: Fraction, simulate: Boolean): Fraction {
override fun extractMatterInner(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
var howMuch = howMuch
var summ = Fraction.ZERO
var summ = ImpreciseFraction.ZERO
for (stack in container) {
if (!stack.isEmpty) {
@ -107,7 +108,7 @@ class BlockEntityMatterCapacitorBank(p_155229_: BlockPos, p_155230_: BlockState)
howMuch -= diff
}
if (howMuch.isZero()) {
if (howMuch.isZero) {
break
}
}

View File

@ -26,6 +26,7 @@ import ru.dbotthepony.mc.otm.capability.matter.IMatterHandler
import ru.dbotthepony.mc.otm.capability.matter.MatterHandlerCapability
import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.core.Fraction
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.graph.Graph6Node
import ru.dbotthepony.mc.otm.graph.matter.IMatterGraphNode
import ru.dbotthepony.mc.otm.graph.matter.MatterNetworkGraph
@ -37,18 +38,13 @@ import ru.dbotthepony.mc.otm.set
class BlockEntityMatterDecomposer(pos: BlockPos, state: BlockState)
: BlockEntityMatteryWorker(Registry.BlockEntities.MATTER_DECOMPOSER, pos, state), IMatterGraphNode {
companion object {
private val MACHINE_NAME = TranslatableComponent("block.overdrive_that_matters.matter_decomposer")
private val BASE_CONSUMPTION = Fraction(240)
}
init {
energy = MatteryMachineEnergyStorage(
this,
MatteryMachineEnergyStorage.MachineType.WORKER,
Fraction(400000),
Fraction(2000),
Fraction(2000)
ImpreciseFraction(400000),
ImpreciseFraction(2000),
ImpreciseFraction(2000)
)
}
@ -60,7 +56,7 @@ class BlockEntityMatterDecomposer(pos: BlockPos, state: BlockState)
}
@JvmField
val matter = MatterHandlerCapability(this::setChangedLight, IMatterHandler.MatterDirection.EXTRACT, Fraction("20"))
val matter = MatterHandlerCapability(this::setChangedLight, IMatterHandler.MatterDirection.EXTRACT, CAPACITY)
private var resolverMatter = LazyOptional.of { matter }
private var resolverNode = LazyOptional.of { this }
@ -136,7 +132,7 @@ class BlockEntityMatterDecomposer(pos: BlockPos, state: BlockState)
if (MatterRegistry.canDecompose(copy)) {
val value = MatterRegistry.getMatterValue(copy)
if (value != Fraction.ZERO && matter.canReceiveAll(value)) {
if (!value.isZero && matter.canReceiveAll(value)) {
stack.shrink(1)
return MachineJob(copy, value.toDouble() * 12500.0, BASE_CONSUMPTION)
}
@ -168,7 +164,7 @@ class BlockEntityMatterDecomposer(pos: BlockPos, state: BlockState)
val grid = node.graph as MatterNetworkGraph?
if (!matter.storedMatter.isZero() && grid != null) {
if (!matter.storedMatter.isZero && grid != null) {
val diff = matter.extractMatterInner(matter.getStoredMatter(), true)
val diff2 = grid.receiveMatter(diff, true)
@ -176,4 +172,10 @@ class BlockEntityMatterDecomposer(pos: BlockPos, state: BlockState)
grid.receiveMatter(diff2, false)
}
}
companion object {
private val CAPACITY = ImpreciseFraction("20")
private val MACHINE_NAME = TranslatableComponent("block.overdrive_that_matters.matter_decomposer")
private val BASE_CONSUMPTION = ImpreciseFraction(240)
}
}

View File

@ -29,6 +29,7 @@ import ru.dbotthepony.mc.otm.capability.matter.MatterTask
import ru.dbotthepony.mc.otm.capability.matter.PatternState
import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.core.Fraction
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.graph.Graph6Node
import ru.dbotthepony.mc.otm.graph.matter.IMatterGraphNode
import ru.dbotthepony.mc.otm.graph.matter.MatterNetworkGraph
@ -51,7 +52,7 @@ class BlockEntityMatterReplicator(p_155229_: BlockPos, p_155230_: BlockState) :
}
@JvmField
val matter = MatterHandlerCapability(this::setChangedLight, IMatterHandler.MatterDirection.RECEIVE, Fraction(2))
val matter = MatterHandlerCapability(this::setChangedLight, IMatterHandler.MatterDirection.RECEIVE, ImpreciseFraction(2))
// обычные запросы
@JvmField
@ -144,7 +145,7 @@ class BlockEntityMatterReplicator(p_155229_: BlockPos, p_155230_: BlockState) :
val drain = graph.extractMatter(toExtract, true)
if (drain.isZero()) {
if (drain.isZero) {
// в сети нет материи
return MachineJobStatus(false, 200)
}
@ -209,19 +210,19 @@ class BlockEntityMatterReplicator(p_155229_: BlockPos, p_155230_: BlockState) :
energy = MatteryMachineEnergyStorage(
this,
MatteryMachineEnergyStorage.MachineType.WORKER,
Fraction(200000),
Fraction(4000),
Fraction(4000)
ImpreciseFraction(200000),
ImpreciseFraction(4000),
ImpreciseFraction(4000)
)
}
companion object {
private val NAME = TranslatableComponent("block.overdrive_that_matters.matter_replicator")
private val BASE_CONSUMPTION = Fraction(400)
private val BASE_CONSUMPTION = ImpreciseFraction(400)
private const val TICKS_PER_MTU = 20000.0
private val TICKS_PER_MTU_BD = Fraction(20000)
private val TICKS_PER_MTU_BD = ImpreciseFraction(20000)
private const val MTU_PER_TICK = 1.0 / 20000.0
private val MTU_PER_TICK_BD = Fraction.ONE.div(TICKS_PER_MTU_BD)
private val DRAIN_MULT = Fraction(200)
private val MTU_PER_TICK_BD = ImpreciseFraction.ONE.div(TICKS_PER_MTU_BD)
private val DRAIN_MULT = ImpreciseFraction(200)
}
}
}

View File

@ -25,6 +25,7 @@ import ru.dbotthepony.mc.otm.capability.matter.PatternInsertStatus
import ru.dbotthepony.mc.otm.capability.matter.PatternState
import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.core.Fraction
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.graph.Graph6Node
import ru.dbotthepony.mc.otm.graph.matter.IMatterGraphNode
import ru.dbotthepony.mc.otm.graph.matter.MatterNetworkGraph
@ -184,9 +185,9 @@ class BlockEntityMatterScanner(p_155229_: BlockPos, p_155230_: BlockState) :
energy = MatteryMachineEnergyStorage(
this,
MatteryMachineEnergyStorage.MachineType.WORKER,
Fraction(40000),
Fraction(400),
Fraction(400)
ImpreciseFraction(40000),
ImpreciseFraction(400),
ImpreciseFraction(400)
)
}
@ -200,6 +201,6 @@ class BlockEntityMatterScanner(p_155229_: BlockPos, p_155230_: BlockState) :
companion object {
private val NAME = TranslatableComponent("block.overdrive_that_matters.matter_scanner")
private val BASE_CONSUMPTION = Fraction("40")
private val BASE_CONSUMPTION = ImpreciseFraction("40")
}
}

View File

@ -14,6 +14,7 @@ import ru.dbotthepony.mc.otm.capability.MatteryMachineEnergyStorage
import ru.dbotthepony.mc.otm.capability.extractEnergy
import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.core.Fraction
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.ifHas
import ru.dbotthepony.mc.otm.set
@ -25,7 +26,7 @@ abstract class BlockEntityMatteryPowered(p_155228_: BlockEntityType<*>, p_155229
protected fun batteryChargeLoop() {
var demand = energy.receiveEnergyOuter(energy.missingPower, true)
if (demand.isZero()) return
if (demand.isZero) return
for (stack in batteryContainer) {
if (!stack.isEmpty) {
@ -41,7 +42,7 @@ abstract class BlockEntityMatteryPowered(p_155228_: BlockEntityType<*>, p_155229
}
}
if (demand <= Fraction.ZERO)
if (demand <= ImpreciseFraction.ZERO)
return
}
}

View File

@ -16,6 +16,7 @@ import ru.dbotthepony.mc.otm.capability.MatteryMachineEnergyStorage
import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.container.MatteryContainerFilter
import ru.dbotthepony.mc.otm.core.Fraction
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.menu.MenuPlatePress
import ru.dbotthepony.mc.otm.set
@ -81,7 +82,7 @@ class BlockEntityPlatePress(p_155229_: BlockPos, p_155230_: BlockState) : BlockE
}
companion object {
private val BASELINE_CONSUMPTION = Fraction(15)
private val BASELINE_CONSUMPTION = ImpreciseFraction(15)
private val NAME = TranslatableComponent("block.overdrive_that_matters.plate_press")
const val SLOT_INPUT = 0
const val SLOT_OUTPUT = 1

View File

@ -26,6 +26,7 @@ import ru.dbotthepony.mc.otm.block.BlockBlackHole
import ru.dbotthepony.mc.otm.block.entity.BlockEntityGravitationStabilizer
import ru.dbotthepony.mc.otm.block.entity.blackhole.ExplosionQueue.Companion.queueForLevel
import ru.dbotthepony.mc.otm.core.Fraction
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.core.plus
import ru.dbotthepony.mc.otm.matter.MatterRegistry
import ru.dbotthepony.mc.otm.set
@ -35,7 +36,7 @@ import kotlin.math.sqrt
class BlockEntityBlackHole(p_155229_: BlockPos, p_155230_: BlockState) : BlockEntity(Registry.BlockEntities.BLACK_HOLE, p_155229_, p_155230_) {
var mass = BASELINE_MASS
set(mass) {
if (mass <= Fraction.ZERO) {
if (mass <= ImpreciseFraction.ZERO) {
collapse()
return
}
@ -156,7 +157,7 @@ class BlockEntityBlackHole(p_155229_: BlockPos, p_155230_: BlockState) : BlockEn
fun readBlackHoleData(tag: CompoundTag) {
tag["mass"]?.let {
mass = Fraction.deserializeNBT(it)
mass = ImpreciseFraction.deserializeNBT(it)
}
spin_direction = tag.getBoolean("spin_direction")
@ -280,7 +281,7 @@ class BlockEntityBlackHole(p_155229_: BlockPos, p_155230_: BlockState) : BlockEn
} else {
val mass = MatterRegistry.getMatterValue(item.item)
if (mass > Fraction.ZERO)
if (mass > ImpreciseFraction.ZERO)
this.mass += mass * item.item.count
}
}
@ -351,8 +352,8 @@ class BlockEntityBlackHole(p_155229_: BlockPos, p_155230_: BlockState) : BlockEn
companion object {
const val ITERATIONS = 30_000
val BASELINE_MASS = Fraction(1_000)
val HAWKING_MASS_LOSE_STEP = Fraction("-0.1")
val BASELINE_MASS = ImpreciseFraction(1_000)
val HAWKING_MASS_LOSE_STEP = ImpreciseFraction("-0.1")
private val blockShapeCache = HashMap<Int, Array<BlockPos>>()

View File

@ -8,6 +8,7 @@ import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.DoubleTag
import net.minecraft.world.level.block.Block
import ru.dbotthepony.mc.otm.core.Fraction
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.ifHas
import ru.dbotthepony.mc.otm.set
@ -139,7 +140,7 @@ abstract class BlockEntityMatteryWorker(p_155228_: BlockEntityType<*>, p_155229_
return
}
if (!currentJob.power.isZero() && energy.batteryLevel.isZero()) {
if (!currentJob.power.isZero && energy.batteryLevel.isZero) {
idleTicksAnim++
if (idleTicksAnim > 20 && blockState.hasProperty(WorkerState.WORKER_STATE) && blockState.getValue(WorkerState.WORKER_STATE) != WorkerState.IDLE) {
@ -152,7 +153,7 @@ abstract class BlockEntityMatteryWorker(p_155228_: BlockEntityType<*>, p_155229_
idleTicksAnim = 0
if (workTicks < currentJob.ticks) {
if (!currentJob.power.isZero()) {
if (!currentJob.power.isZero) {
val extractedPower = energy.extractEnergyInner(currentJob.power, true)
val workSpeed = extractedPower.div(currentJob.power)
@ -191,7 +192,7 @@ abstract class BlockEntityMatteryWorker(p_155228_: BlockEntityType<*>, p_155229_
}
}
} else {
val status = onWorkTick(WorkTickContext(currentJob, Fraction.ZERO, Fraction.ZERO, Fraction.ONE))
val status = onWorkTick(WorkTickContext(currentJob, ImpreciseFraction.ZERO, ImpreciseFraction.ZERO, ImpreciseFraction.ONE))
if (!status.valid) {
throttleTicks += status.throttle()

View File

@ -2,6 +2,7 @@ package ru.dbotthepony.mc.otm.capability
import net.minecraftforge.energy.IEnergyStorage
import ru.dbotthepony.mc.otm.core.Fraction
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
fun IEnergyStorage.receiveEnergy(amount: Fraction, simulate: Boolean): Int {
if (amount.isZero())
@ -22,3 +23,23 @@ fun IEnergyStorage.extractEnergy(amount: Fraction, simulate: Boolean): Int {
return extractEnergy(amount.wholePart().toInt(), simulate)
}
fun IEnergyStorage.receiveEnergy(amount: ImpreciseFraction, simulate: Boolean): Int {
if (amount.isZero)
return 0
if (amount > ImpreciseFraction.INT_MAX_VALUE)
return receiveEnergy(Int.MAX_VALUE, simulate)
return receiveEnergy(amount.toInt(), simulate)
}
fun IEnergyStorage.extractEnergy(amount: ImpreciseFraction, simulate: Boolean): Int {
if (amount.isZero)
return 0
if (amount > ImpreciseFraction.INT_MAX_VALUE)
return extractEnergy(Int.MAX_VALUE, simulate)
return extractEnergy(amount.toInt(), simulate)
}

View File

@ -2,58 +2,59 @@ package ru.dbotthepony.mc.otm.capability
import net.minecraftforge.energy.IEnergyStorage
import ru.dbotthepony.mc.otm.core.Fraction
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
// IEnergyStorage for direct compat with Forge Energy
interface IMatteryEnergyStorage : IEnergyStorage {
// such as cables. This is something that would work only with energy storage
fun extractEnergyOuter(howMuch: Fraction, simulate: Boolean): Fraction
fun extractEnergyOuter(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction
// 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
fun extractEnergyInner(howMuch: Fraction, simulate: Boolean): Fraction
fun extractEnergyInner(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction
// energy is received from outside, e.g. cables
fun receiveEnergyOuter(howMuch: Fraction, simulate: Boolean): Fraction
fun receiveEnergyOuter(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction
// energy is received from inside, e.g. generator generates power
fun receiveEnergyInner(howMuch: Fraction, simulate: Boolean): Fraction
fun receiveEnergyInner(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction
fun extractEnergyOuter(howMuch: Long, simulate: Boolean): Fraction {
return extractEnergyOuter(Fraction(howMuch), simulate)
fun extractEnergyOuter(howMuch: Long, simulate: Boolean): ImpreciseFraction {
return extractEnergyOuter(ImpreciseFraction(howMuch), simulate)
}
fun extractEnergyOuter(howMuch: Int, simulate: Boolean): Fraction {
return extractEnergyOuter(Fraction(howMuch), simulate)
fun extractEnergyOuter(howMuch: Int, simulate: Boolean): ImpreciseFraction {
return extractEnergyOuter(ImpreciseFraction(howMuch), simulate)
}
fun receiveEnergyOuter(howMuch: Long, simulate: Boolean): Fraction {
return receiveEnergyOuter(Fraction(howMuch), simulate)
fun receiveEnergyOuter(howMuch: Long, simulate: Boolean): ImpreciseFraction {
return receiveEnergyOuter(ImpreciseFraction(howMuch), simulate)
}
fun receiveEnergyOuter(howMuch: Int, simulate: Boolean): Fraction {
return receiveEnergyOuter(Fraction(howMuch), simulate)
fun receiveEnergyOuter(howMuch: Int, simulate: Boolean): ImpreciseFraction {
return receiveEnergyOuter(ImpreciseFraction(howMuch), simulate)
}
fun extractEnergyInner(howMuch: Long, simulate: Boolean): Fraction {
return extractEnergyInner(Fraction(howMuch), simulate)
fun extractEnergyInner(howMuch: Long, simulate: Boolean): ImpreciseFraction {
return extractEnergyInner(ImpreciseFraction(howMuch), simulate)
}
fun extractEnergyInner(howMuch: Int, simulate: Boolean): Fraction {
return extractEnergyInner(Fraction(howMuch), simulate)
fun extractEnergyInner(howMuch: Int, simulate: Boolean): ImpreciseFraction {
return extractEnergyInner(ImpreciseFraction(howMuch), simulate)
}
fun receiveEnergyInner(howMuch: Long, simulate: Boolean): Fraction {
return receiveEnergyInner(Fraction(howMuch), simulate)
fun receiveEnergyInner(howMuch: Long, simulate: Boolean): ImpreciseFraction {
return receiveEnergyInner(ImpreciseFraction(howMuch), simulate)
}
fun receiveEnergyInner(howMuch: Int, simulate: Boolean): Fraction {
return receiveEnergyInner(Fraction(howMuch), simulate)
fun receiveEnergyInner(howMuch: Int, simulate: Boolean): ImpreciseFraction {
return receiveEnergyInner(ImpreciseFraction(howMuch), simulate)
}
val batteryLevel: Fraction
val maxBatteryLevel: Fraction
val missingPower: Fraction
val batteryLevel: ImpreciseFraction
val maxBatteryLevel: ImpreciseFraction
val missingPower: ImpreciseFraction
get() = (maxBatteryLevel - batteryLevel).moreThanZero()
override fun receiveEnergy(maxReceive: Int, simulate: Boolean): Int {
@ -63,7 +64,7 @@ interface IMatteryEnergyStorage : IEnergyStorage {
if (received == 0)
return 0
return receiveEnergyOuter(Fraction(received), simulate).toInt()
return receiveEnergyOuter(ImpreciseFraction(received), simulate).toInt()
}
override fun extractEnergy(maxReceive: Int, simulate: Boolean): Int {
@ -73,32 +74,22 @@ interface IMatteryEnergyStorage : IEnergyStorage {
if (extracted == 0)
return 0
return extractEnergyOuter(Fraction(extracted), simulate).toInt()
return extractEnergyOuter(ImpreciseFraction(extracted), simulate).toInt()
}
override fun getEnergyStored(): Int {
val level = batteryLevel
if (level < MatteryCapability.INT_MAX_VALUE)
return level.toInt()
return Int.MAX_VALUE
return batteryLevel.toInt()
}
override fun getMaxEnergyStored(): Int {
val level = maxBatteryLevel
if (level < MatteryCapability.INT_MAX_VALUE)
return level.toInt()
return Int.MAX_VALUE
return maxBatteryLevel.toInt()
}
override fun canExtract(): Boolean {
return extractEnergyOuter(Fraction.ONE, true) > Fraction.ZERO
return extractEnergyOuter(ImpreciseFraction.ONE, true) > ImpreciseFraction.ZERO
}
override fun canReceive(): Boolean {
return receiveEnergyOuter(Fraction.ONE, true) > Fraction.ZERO
return receiveEnergyOuter(ImpreciseFraction.ONE, true) > ImpreciseFraction.ZERO
}
}

View File

@ -3,41 +3,40 @@ package ru.dbotthepony.mc.otm.capability
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.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.ifHas
import ru.dbotthepony.mc.otm.set
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
override var maxBatteryLevel: ImpreciseFraction = DEFAULT_MAX_CAPACITY,
protected var maxInput: ImpreciseFraction = DEFAULT_MAX_RECEIVE,
protected var maxOutput: ImpreciseFraction = maxInput
) : IMatteryEnergyStorage, INBTSerializable<CompoundTag> {
@JvmOverloads
constructor(
listener: BlockEntity,
type: MachineType,
maxBatteryLevel: Fraction = DEFAULT_MAX_CAPACITY,
maxInput: Fraction = DEFAULT_MAX_RECEIVE,
maxOutput: Fraction = DEFAULT_MAX_EXTRACT) : this({listener.setChanged()}, type, maxBatteryLevel, maxInput, maxOutput)
maxBatteryLevel: ImpreciseFraction = DEFAULT_MAX_CAPACITY,
maxInput: ImpreciseFraction = DEFAULT_MAX_RECEIVE,
maxOutput: ImpreciseFraction = DEFAULT_MAX_EXTRACT) : this({listener.setChanged()}, type, maxBatteryLevel, maxInput, maxOutput)
enum class MachineType {
WORKER, GENERATOR, CAPACITOR
}
override var batteryLevel = Fraction.ZERO
override var batteryLevel = ImpreciseFraction.ZERO
protected set
override fun extractEnergyOuter(howMuch: Fraction, simulate: Boolean): Fraction {
override fun extractEnergyOuter(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
if (type == MachineType.WORKER)
return Fraction.ZERO
return ImpreciseFraction.ZERO
return extractEnergyInner(howMuch, simulate)
}
override fun extractEnergyInner(howMuch: Fraction, simulate: Boolean): Fraction {
override fun extractEnergyInner(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
val new = batteryLevel.minus(howMuch.min(maxOutput)).moreThanZero()
val diff = batteryLevel.minus(new)
@ -49,14 +48,14 @@ open class MatteryMachineEnergyStorage @JvmOverloads constructor(
return diff
}
override fun receiveEnergyOuter(howMuch: Fraction, simulate: Boolean): Fraction {
override fun receiveEnergyOuter(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
if (type == MachineType.GENERATOR)
return Fraction.ZERO
return ImpreciseFraction.ZERO
return receiveEnergyInner(howMuch, simulate)
}
override fun receiveEnergyInner(howMuch: Fraction, simulate: Boolean): Fraction {
override fun receiveEnergyInner(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
val new = batteryLevel.plus(howMuch.min(maxInput)).min(maxBatteryLevel)
val diff = new.minus(batteryLevel)
@ -89,15 +88,15 @@ open class MatteryMachineEnergyStorage @JvmOverloads constructor(
}
override fun deserializeNBT(nbt: CompoundTag) {
nbt.ifHas("energy_stored") { batteryLevel = deserializeNBT(it) }
nbt.ifHas("energy_stored") { batteryLevel = ImpreciseFraction.deserializeNBT(it) }
// nbt.ifHas("energy_stored_max") { maxBatteryLevel = deserializeNBT(it) }
// nbt.ifHas("max_input") { maxInput = deserializeNBT(it) }
// nbt.ifHas("max_output") { maxOutput = deserializeNBT(it) }
}
companion object {
val DEFAULT_MAX_RECEIVE = Fraction(200)
val DEFAULT_MAX_RECEIVE = ImpreciseFraction(200)
val DEFAULT_MAX_EXTRACT = DEFAULT_MAX_RECEIVE
val DEFAULT_MAX_CAPACITY = Fraction(60000)
val DEFAULT_MAX_CAPACITY = ImpreciseFraction(60000)
}
}

View File

@ -36,6 +36,7 @@ import ru.dbotthepony.mc.otm.capability.IMatteryEnergyStorage
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.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.ifHas
import ru.dbotthepony.mc.otm.set
import java.util.*
@ -43,13 +44,13 @@ import java.util.*
@MethodsReturnNonnullByDefault
@ParametersAreNonnullByDefault
open class AndroidCapability(@JvmField protected val ent: LivingEntity) : ICapabilityProvider, IAndroidCapability, INBTSerializable<CompoundTag?> {
@JvmField protected var battery = Fraction.ZERO
@JvmField protected var maxBattery = Fraction(60000)
@JvmField protected var battery = ImpreciseFraction.ZERO
@JvmField protected var maxBattery = ImpreciseFraction(60000)
override var batteryItemStack = ItemStack.EMPTY
private var remoteBattery = Fraction(-1)
private var remoteMaxBattery = Fraction(-1)
private var remoteBattery = ImpreciseFraction(-1)
private var remoteMaxBattery = ImpreciseFraction(-1)
private var remoteBatteryStack = ItemStack.EMPTY
@JvmField protected val features: MutableMap<AndroidFeatureType<*>, AndroidFeature> = HashMap()
@ -119,8 +120,8 @@ open class AndroidCapability(@JvmField protected val ent: LivingEntity) : ICapab
}
override fun invalidateNetworkState() {
remoteBattery = Fraction.MINUS_ONE
remoteMaxBattery = Fraction.MINUS_ONE
remoteBattery = ImpreciseFraction.MINUS_ONE
remoteMaxBattery = ImpreciseFraction.MINUS_ONE
remoteBatteryStack = ItemStack.EMPTY
if (ent is ServerPlayer) {
@ -131,11 +132,11 @@ open class AndroidCapability(@JvmField protected val ent: LivingEntity) : ICapab
}
}
override fun setEnergy(value: Fraction) {
override fun setEnergy(value: ImpreciseFraction) {
battery = value
}
override fun setMaxEnergy(value: Fraction) {
override fun setMaxEnergy(value: ImpreciseFraction) {
maxBattery = value
}
@ -170,11 +171,11 @@ open class AndroidCapability(@JvmField protected val ent: LivingEntity) : ICapab
compound!!
compound.ifHas("energy_stored") {
battery = Fraction.deserializeNBT(it)
battery = ImpreciseFraction.deserializeNBT(it)
}
compound.ifHas("energy_stored_max") {
maxBattery = Fraction.deserializeNBT(it)
maxBattery = ImpreciseFraction.deserializeNBT(it)
}
compound.ifHas("battery", CompoundTag::class.java) {
@ -300,13 +301,13 @@ open class AndroidCapability(@JvmField protected val ent: LivingEntity) : ICapab
}
}
override fun extractEnergyOuter(howMuch: Fraction, simulate: Boolean): Fraction {
return Fraction.ZERO
override fun extractEnergyOuter(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
return ImpreciseFraction.ZERO
}
override fun extractEnergyInner(howMuch: Fraction, simulate: Boolean): Fraction {
override fun extractEnergyInner(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
var howMuch = howMuch
var drained = Fraction.ZERO
var drained = ImpreciseFraction.ZERO
if (!batteryItemStack.isEmpty) {
batteryItemStack.getCapability(CapabilityEnergy.ENERGY).ifPresent {
@ -321,7 +322,7 @@ open class AndroidCapability(@JvmField protected val ent: LivingEntity) : ICapab
}
}
if (howMuch.isZero()) {
if (howMuch.isZero) {
if (!simulate && ent is ServerPlayer) {
ent.awardStat(Registry.Names.POWER_CONSUMED, drained.toInt() * 10)
}
@ -344,9 +345,9 @@ open class AndroidCapability(@JvmField protected val ent: LivingEntity) : ICapab
return drained
}
override fun receiveEnergyOuter(howMuch: Fraction, simulate: Boolean): Fraction {
override fun receiveEnergyOuter(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
var howMuch = howMuch
var received = Fraction.ZERO
var received = ImpreciseFraction.ZERO
if (!batteryItemStack.isEmpty) {
batteryItemStack.getCapability(CapabilityEnergy.ENERGY).ifPresent {
@ -361,7 +362,7 @@ open class AndroidCapability(@JvmField protected val ent: LivingEntity) : ICapab
}
}
if (howMuch.isZero()) {
if (howMuch.isZero) {
return received
}
}
@ -376,7 +377,7 @@ open class AndroidCapability(@JvmField protected val ent: LivingEntity) : ICapab
return received
}
override fun receiveEnergyInner(howMuch: Fraction, simulate: Boolean): Fraction {
override fun receiveEnergyInner(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
return receiveEnergyOuter(howMuch, simulate)
}
@ -384,7 +385,7 @@ open class AndroidCapability(@JvmField protected val ent: LivingEntity) : ICapab
return ent
}
override val batteryLevel: Fraction get() {
override val batteryLevel: ImpreciseFraction get() {
if (!batteryItemStack.isEmpty) {
val resolver = batteryItemStack.getCapability(CapabilityEnergy.ENERGY).resolve()
@ -402,7 +403,7 @@ open class AndroidCapability(@JvmField protected val ent: LivingEntity) : ICapab
return battery
}
override val maxBatteryLevel: Fraction get() {
override val maxBatteryLevel: ImpreciseFraction get() {
if (batteryItemStack != ItemStack.EMPTY) {
val resolver = batteryItemStack.getCapability(CapabilityEnergy.ENERGY).resolve()

View File

@ -18,6 +18,7 @@ import ru.dbotthepony.mc.otm.android.AndroidResearch
import ru.dbotthepony.mc.otm.android.AndroidResearchType
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.core.Fraction
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.network.android.AndroidResearchPacket
import ru.dbotthepony.mc.otm.network.android.AndroidStatusPacket
import ru.dbotthepony.mc.otm.set
@ -58,8 +59,8 @@ class AndroidCapabilityPlayer(@JvmField val ply: Player) : AndroidCapability(ply
isAndroid = true
willBecomeAndroid = false
battery = Fraction(60000)
maxBattery = Fraction(60000)
battery = ImpreciseFraction(60000)
maxBattery = ImpreciseFraction(60000)
}
fun becomeAndroidAndKill() {
@ -74,8 +75,8 @@ class AndroidCapabilityPlayer(@JvmField val ply: Player) : AndroidCapability(ply
if (!isAndroid) return
isAndroid = false
battery = Fraction(0)
maxBattery = Fraction(60000)
battery = ImpreciseFraction(0)
maxBattery = ImpreciseFraction(60000)
dropBattery()
}
@ -296,7 +297,7 @@ class AndroidCapabilityPlayer(@JvmField val ply: Player) : AndroidCapability(ply
}
}
val ENERGY_FOR_HUNGER_POINT = Fraction(1000)
val ENERGY_FOR_HUNGER_POINT = ImpreciseFraction(1000)
const val SLEEP_TICKS_LIMIT = 80
}
}

View File

@ -8,7 +8,7 @@ import net.minecraftforge.event.entity.living.LivingHurtEvent
import ru.dbotthepony.mc.otm.android.AndroidFeature
import ru.dbotthepony.mc.otm.android.AndroidFeatureType
import ru.dbotthepony.mc.otm.capability.IMatteryEnergyStorage
import ru.dbotthepony.mc.otm.core.Fraction
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import java.util.*
interface IAndroidCapability : IMatteryEnergyStorage, INBTSerializable<CompoundTag?> {
@ -40,6 +40,6 @@ interface IAndroidCapability : IMatteryEnergyStorage, INBTSerializable<CompoundT
fun onHurt(event: LivingHurtEvent) {}
var batteryItemStack: ItemStack
fun invalidateNetworkState() // tell capability that player forgot everything, and everything needs to be re-networked
fun setEnergy(value: Fraction)
fun setMaxEnergy(value: Fraction)
fun setEnergy(value: ImpreciseFraction)
fun setMaxEnergy(value: ImpreciseFraction)
}

View File

@ -4,6 +4,7 @@ import net.minecraft.nbt.CompoundTag
import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack
import ru.dbotthepony.mc.otm.core.Fraction
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.storage.IStorageComponent
import ru.dbotthepony.mc.otm.storage.IStorageStack
import ru.dbotthepony.mc.otm.storage.IStorageTuple
@ -35,8 +36,8 @@ interface IMatteryDrive<T : IStorageStack> : IStorageComponent<T> {
var isDirty: Boolean
val storedCount: Fraction
val driveCapacity: Fraction
val storedCount: ImpreciseFraction
val driveCapacity: ImpreciseFraction
// not extending INBTSerializable to avoid serializing it as forgecaps
fun serializeNBT(): CompoundTag

View File

@ -13,6 +13,7 @@ import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.ListTag
import net.minecraft.nbt.Tag
import ru.dbotthepony.mc.otm.core.Fraction
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.ifHas
import ru.dbotthepony.mc.otm.set
import java.util.ArrayList
@ -20,7 +21,7 @@ import java.util.HashSet
abstract class AbstractMatteryDrive<T : IStorageStack> @JvmOverloads constructor(
override var driveCapacity: Fraction,
override var driveCapacity: ImpreciseFraction,
override val uuid: UUID = UUID.randomUUID(),
var maxDifferentStacks: Int = 0xFFFF
) : IMatteryDrive<T> {
@ -42,12 +43,12 @@ abstract class AbstractMatteryDrive<T : IStorageStack> @JvmOverloads constructor
var storedDifferentStacks = 0
override var storedCount = Fraction.ZERO
override var storedCount = ImpreciseFraction.ZERO
protected set
override fun insertStack(stack: T, simulate: Boolean): T {
val maxInsert = driveCapacity.minus(storedCount).min(stack.count)
if (maxInsert <= Fraction.ZERO) return stack
if (maxInsert <= ImpreciseFraction.ZERO) return stack
val listing = storedStacks.computeIfAbsent(stack.partitionKey()) { ArrayList() }
@ -97,16 +98,16 @@ abstract class AbstractMatteryDrive<T : IStorageStack> @JvmOverloads constructor
return copy
}
override fun extractStack(id: UUID, amount: Fraction, simulate: Boolean): T {
override fun extractStack(id: UUID, amount: ImpreciseFraction, simulate: Boolean): T {
var amount = amount
val get = storedByID[id] ?: return identity().empty()
if (amount <= Fraction.ZERO)
if (amount <= ImpreciseFraction.ZERO)
amount = get.stack.getMaxStackSize().orElse(get.stack.count)
amount = amount.min(get.stack.count)
if (amount <= Fraction.ZERO)
if (amount <= ImpreciseFraction.ZERO)
return identity().empty()
val copy = get.stack.copy() as T
@ -130,7 +131,7 @@ abstract class AbstractMatteryDrive<T : IStorageStack> @JvmOverloads constructor
storedCount = storedCount.minus(amount)
get.stack.shrink(amount)
if (get.stack.count.compareTo(Fraction.ZERO) != 0) {
if (!get.stack.count.isZero) {
for (listener in listeners) {
listener.changeObject(get.id(), get.stack.count)
}
@ -170,11 +171,11 @@ abstract class AbstractMatteryDrive<T : IStorageStack> @JvmOverloads constructor
override fun deserializeNBT(nbt: CompoundTag) {
storedStacks.clear()
storedByID.clear()
storedCount = Fraction.ZERO
storedCount = ImpreciseFraction.ZERO
storedDifferentStacks = 0
nbt.ifHas("capacity") {
driveCapacity = deserializeNBT(it)
driveCapacity = ImpreciseFraction.deserializeNBT(it)
}
maxDifferentStacks = nbt.getInt("max_different_stacks")

View File

@ -7,6 +7,7 @@ import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Items
import net.minecraftforge.registries.RegistryManager
import ru.dbotthepony.mc.otm.core.Fraction
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.set
import ru.dbotthepony.mc.otm.storage.IStorageTuple
import ru.dbotthepony.mc.otm.storage.ItemStackWrapper
@ -14,10 +15,10 @@ import ru.dbotthepony.mc.otm.storage.StorageObjectRegistry
import java.util.*
class ItemMatteryDrive : AbstractMatteryDrive<ItemStackWrapper>, IItemMatteryDrive {
constructor(capacity: Fraction, max_different_stacks: Int) : super(capacity, maxDifferentStacks = max_different_stacks)
constructor(capacity: Fraction, uuid: UUID, max_different_stacks: Int) : super(capacity, uuid, max_different_stacks)
constructor(capacity: Fraction, uuid: UUID) : super(capacity, uuid)
constructor(capacity: Fraction) : super(capacity)
constructor(capacity: ImpreciseFraction, max_different_stacks: Int) : super(capacity, maxDifferentStacks = max_different_stacks)
constructor(capacity: ImpreciseFraction, uuid: UUID, max_different_stacks: Int) : super(capacity, uuid, max_different_stacks)
constructor(capacity: ImpreciseFraction, uuid: UUID) : super(capacity, uuid)
constructor(capacity: ImpreciseFraction) : super(capacity)
private val identity = StorageObjectRegistry.getOrError(ItemStackWrapper::class.java)
override fun identity() = identity
@ -86,6 +87,6 @@ class ItemMatteryDrive : AbstractMatteryDrive<ItemStackWrapper>, IItemMatteryDri
companion object {
@JvmField
val DUMMY = ItemMatteryDrive(Fraction(0), UUID(0L, 0L), 0)
val DUMMY = ItemMatteryDrive(ImpreciseFraction(0), UUID(0L, 0L), 0)
}
}
}

View File

@ -51,8 +51,8 @@ class EnergyCounterRenderer(private val context: BlockEntityRendererProvider.Con
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)
font.drawAligned(poseStack, tile.lastTick.toString(0), TextAlign.CENTER_RIGHT, finalX.toFloat(), y, 0xFFFFFF)
font.drawAligned(poseStack, tile.sumHistory(20).toString(0), TextAlign.CENTER_RIGHT, finalX.toFloat(), y + font.lineHeight, 0xFFFFFF)
poseStack.popPose()
y += font.lineHeight * 3

View File

@ -105,7 +105,7 @@ open class PatternGaugePanel @JvmOverloads constructor(
protected open fun makeTooltip(): MutableList<Component> {
return mutableListOf(
TranslatableComponent("otm.gui.pattern.percentage_level", String.format("%.2f", widget.percentage() * 100.0)),
TranslatableComponent("otm.gui.pattern.format", widget.level().decimalString(), widget.maxLevel().decimalString())
TranslatableComponent("otm.gui.pattern.format", widget.level().toString(2), widget.maxLevel().toString(2))
)
}

View File

@ -10,6 +10,8 @@ import java.math.BigInteger
import java.math.MathContext
import java.math.RoundingMode
private val IMPRECISE_CONTEXT = MathContext(17)
private fun powScale(int: Int): BigInteger {
if (int <= 0)
return BigInteger.ONE
@ -597,6 +599,27 @@ data class Fraction @JvmOverloads constructor(@JvmField val value: BigInteger, @
return (value / divisor).toDouble() + ((value % divisor).toDouble() / divisor.toDouble())
}
fun toImpreciseFraction(): ImpreciseFraction {
if (isNaN())
return ImpreciseFraction.NaN
val div = value.divideAndRemainder(divisor)
val a = divisor.toDouble()
val b = div[1].toDouble()
if (b == 0.0 || b == -0.0 || !a.isFinite() || !b.isFinite()) {
return ImpreciseFraction(div[0])
}
val div2 = a / b
if (div2.isFinite() && !div2.isNaN()) {
return ImpreciseFraction(div[0], div2)
}
return ImpreciseFraction(div[0])
}
fun toByteArray(): ByteArray {
if (isNaN()) {
return byteArrayOf(1, 0, 0, 0, 0, 1, 0, 0, 0, 0)

View File

@ -3,6 +3,7 @@ package ru.dbotthepony.mc.otm.core
import net.minecraft.nbt.ByteArrayTag
import net.minecraft.nbt.StringTag
import net.minecraft.nbt.Tag
import net.minecraft.network.FriendlyByteBuf
import java.math.BigDecimal
import java.math.BigInteger
import java.math.MathContext
@ -13,6 +14,14 @@ private fun isZero(value: BigInteger) = value == BigInteger.ZERO
private val LONG_BUFF = ByteBuffer.allocate(8)
private fun byteToInt(value: Byte): Int {
if (value < 0) {
return 256 + value
}
return value.toInt()
}
private fun longToBytes(value: Long): ByteArray {
LONG_BUFF.position(0)
LONG_BUFF.putLong(value)
@ -33,6 +42,29 @@ private fun bytesToLong(value: ByteArray, from: Int = 0): Long {
return LONG_BUFF.long
}
private fun bytesToLong(
value0: Byte,
value1: Byte,
value2: Byte,
value3: Byte,
value4: Byte,
value5: Byte,
value6: Byte,
value7: Byte,
): Long {
val arr = LONG_BUFF.array()
arr[0] = value0
arr[1] = value1
arr[2] = value2
arr[3] = value3
arr[4] = value4
arr[5] = value5
arr[6] = value6
arr[7] = value7
LONG_BUFF.position(0)
return LONG_BUFF.long
}
const val EPSILON = 0.0000001
private fun cmpDouble(a: Double, b: Double): Boolean {
@ -42,6 +74,18 @@ private fun cmpDouble(a: Double, b: Double): Boolean {
return (a - b).absoluteValue <= EPSILON
}
private val BI_INT_MAX = BigInteger.valueOf(Int.MAX_VALUE.toLong())
private val BI_INT_MIN = BigInteger.valueOf(Int.MIN_VALUE.toLong())
private val BI_LONG_MAX = BigInteger.valueOf(Long.MAX_VALUE)
private val BI_LONG_MIN = BigInteger.valueOf(Long.MIN_VALUE)
private val BI_FLOAT_MAX = BigDecimal(Float.MAX_VALUE.toString()).toBigInteger()
private val BI_FLOAT_MIN = BigDecimal(Float.MIN_VALUE.toString()).toBigInteger()
private val BI_DOUBLE_MAX = BigDecimal(Double.MAX_VALUE.toString()).toBigInteger()
private val BI_DOUBLE_MIN = BigDecimal(Double.MIN_VALUE.toString()).toBigInteger()
private val PERCENTAGE_CONTEXT = MathContext(6)
@Suppress("unused")
class ImpreciseFraction @JvmOverloads constructor(whole: BigInteger, decimal: Double = 0.0) : Comparable<ImpreciseFraction> {
@JvmOverloads constructor(whole: Byte, decimal: Double = 0.0) : this(BigInteger.valueOf(whole.toLong()), decimal)
@ -49,8 +93,8 @@ class ImpreciseFraction @JvmOverloads constructor(whole: BigInteger, decimal: Do
@JvmOverloads constructor(whole: Int, decimal: Double = 0.0) : this(BigInteger.valueOf(whole.toLong()), decimal)
@JvmOverloads constructor(whole: Long, decimal: Double = 0.0) : this(BigInteger.valueOf(whole), decimal)
constructor(value: BigDecimal) : this(value.toBigInteger(), value.remainder(BigDecimal.ONE).toDouble()) // TODO
constructor(value: Float) : this(BigDecimal(value.toString()))
constructor(value: Double) : this(BigDecimal(value.toString()))
constructor(value: Float) : this(BigInteger.valueOf((value - value % 1.0).toLong()), value % 1.0)
constructor(value: Double) : this(BigInteger.valueOf((value - value % 1.0).toLong()), value % 1.0)
constructor(value: String) : this(BigDecimal(value))
val decimal: Double
@ -95,7 +139,7 @@ class ImpreciseFraction @JvmOverloads constructor(whole: BigInteger, decimal: Do
}
}
fun isNaN() = decimal.isNaN()
val isNaN get() = decimal.isNaN()
operator fun plus(other: ImpreciseFraction) = ImpreciseFraction(whole + other.whole, decimal + other.decimal)
operator fun minus(other: ImpreciseFraction) = ImpreciseFraction(whole - other.whole, decimal - other.decimal)
@ -133,12 +177,32 @@ class ImpreciseFraction @JvmOverloads constructor(whole: BigInteger, decimal: Do
return ImpreciseFraction(div[0].toBigInteger(), div[1].toDouble() / bD)
}
operator fun plus(other: Float): ImpreciseFraction = plus(ImpreciseFraction(other))
operator fun minus(other: Float): ImpreciseFraction = minus(ImpreciseFraction(other))
operator fun times(other: Float): ImpreciseFraction = times(ImpreciseFraction(other))
operator fun div(other: Float): ImpreciseFraction = div(ImpreciseFraction(other))
operator fun plus(other: Double): ImpreciseFraction = plus(ImpreciseFraction(other))
operator fun minus(other: Double): ImpreciseFraction = minus(ImpreciseFraction(other))
operator fun times(other: Double): ImpreciseFraction = times(ImpreciseFraction(other))
operator fun div(other: Double): ImpreciseFraction = div(ImpreciseFraction(other))
operator fun plus(other: Int): ImpreciseFraction = plus(ImpreciseFraction(other))
operator fun minus(other: Int): ImpreciseFraction = minus(ImpreciseFraction(other))
operator fun times(other: Int): ImpreciseFraction = times(ImpreciseFraction(other))
operator fun div(other: Int): ImpreciseFraction = div(ImpreciseFraction(other))
operator fun plus(other: Long): ImpreciseFraction = plus(ImpreciseFraction(other))
operator fun minus(other: Long): ImpreciseFraction = minus(ImpreciseFraction(other))
operator fun times(other: Long): ImpreciseFraction = times(ImpreciseFraction(other))
operator fun div(other: Long): ImpreciseFraction = div(ImpreciseFraction(other))
operator fun unaryMinus(): ImpreciseFraction {
return ImpreciseFraction(-whole, decimal)
}
override fun equals(other: Any?): Boolean {
if (isNaN())
if (isNaN)
return false
if (other is ImpreciseFraction) {
@ -149,7 +213,7 @@ class ImpreciseFraction @JvmOverloads constructor(whole: BigInteger, decimal: Do
}
fun equalsStrict(other: Any?): Boolean {
if (isNaN())
if (isNaN)
return false
if (other is ImpreciseFraction) {
@ -160,16 +224,36 @@ class ImpreciseFraction @JvmOverloads constructor(whole: BigInteger, decimal: Do
}
override fun hashCode(): Int {
if (isNaN())
if (isNaN)
return Double.NaN.hashCode()
return 31 * decimal.hashCode() + whole.hashCode()
}
override fun toString(): String {
if (isNaN())
fun toString(decimals: Int): String {
if (isNaN)
return "NaN"
if (decimals == 0) {
return whole.toString()
} else if (decimals > 0) {
val strDecimal = if (decimal == 0.0 || decimal == -0.0) {
"0"
} else if (decimal > 0.0) {
decimal.toString().substring(2)
} else {
decimal.toString().substring(3)
}
if (strDecimal.length < decimals) {
return "$whole.${strDecimal + "0".repeat(decimals - strDecimal.length)}"
} else if (strDecimal.length > decimals) {
return "$whole.${strDecimal.substring(0, decimals)}"
} else {
return "$whole.$strDecimal"
}
}
return when (signum()) {
1 -> "$whole.${decimal.toString().substring(2)}"
0 -> "0.0"
@ -178,9 +262,7 @@ class ImpreciseFraction @JvmOverloads constructor(whole: BigInteger, decimal: Do
}
}
fun toDouble(): Double {
return java.lang.Double.parseDouble(toString())
}
override fun toString() = toString(-1)
fun toBigDecmial(): BigDecimal {
return BigDecimal(whole) + BigDecimal(decimal)
@ -197,9 +279,9 @@ class ImpreciseFraction @JvmOverloads constructor(whole: BigInteger, decimal: Do
}
override fun compareTo(other: ImpreciseFraction): Int {
if (isNaN())
if (isNaN)
return 1
else if (other.isNaN())
else if (other.isNaN)
return -1
val a = signum()
@ -222,9 +304,9 @@ class ImpreciseFraction @JvmOverloads constructor(whole: BigInteger, decimal: Do
}
fun compareToStrict(other: ImpreciseFraction): Int {
if (isNaN())
if (isNaN)
return 1
else if (other.isNaN())
else if (other.isNaN)
return -1
val a = signum()
@ -246,16 +328,16 @@ class ImpreciseFraction @JvmOverloads constructor(whole: BigInteger, decimal: Do
return whole.compareTo(other.whole)
}
fun toBytesArray(): ByteArray {
fun toByteArray(): ByteArray {
val whole = whole.toByteArray()
return byteArrayOf(whole.size.toByte(), *whole, *longToBytes(decimal.toBits()))
}
fun serializeNBT(): Tag {
return ByteArrayTag(toBytesArray())
return ByteArrayTag(toByteArray())
}
fun isZero() = cmpDouble(decimal, 0.0) && isZero(whole)
val isZero get() = cmpDouble(decimal, 0.0) && isZero(whole)
fun moreThanZero(): ImpreciseFraction {
if (signum() >= 0)
@ -295,28 +377,105 @@ class ImpreciseFraction @JvmOverloads constructor(whole: BigInteger, decimal: Do
return min
}
fun toInt(): Int {
if (whole > BI_INT_MAX) {
return Int.MAX_VALUE
} else if (whole < BI_INT_MIN) {
return Int.MIN_VALUE
}
return whole.toInt()
}
fun write(buff: FriendlyByteBuf) {
buff.writeBytes(toByteArray())
}
fun toFloat(): Float {
return whole.toFloat() + decimal.toFloat()
}
fun toDouble(): Double {
return whole.toDouble() + decimal
}
fun toFraction(): Fraction {
if (isZero) {
return Fraction.ZERO
}
if (cmpDouble(decimal, 0.0)) {
return Fraction(whole)
}
return Fraction(toBigDecmial())
}
fun percentage(divisor: ImpreciseFraction, zeroing: Boolean = true): Float {
if ((isZero || divisor.isZero) && zeroing) return 0f
if (isNaN || divisor.isNaN || divisor.isZero) return Float.NaN
if (this >= divisor)
return 1f
if (this <= FLOAT_MAX_VALUE && divisor <= FLOAT_MAX_VALUE)
return (toDouble() / divisor.toDouble()).toFloat()
return toBigDecmial().divide(divisor.toBigDecmial(), PERCENTAGE_CONTEXT).toFloat()
}
companion object {
@JvmField val MINUS_ZERO = ImpreciseFraction(0, -0.0)
@JvmField val ZERO = ImpreciseFraction(BigInteger.ZERO)
@JvmField val ONE = ImpreciseFraction(BigInteger.ONE)
@JvmField val MINUS_ONE = ImpreciseFraction(-BigInteger.ONE)
@JvmField val TWO = ImpreciseFraction(BigInteger.TWO)
@JvmField val TEN = ImpreciseFraction(BigInteger.TEN)
fun fromBytesArray(input: ByteArray): ImpreciseFraction {
val size = if (input[0] < 0) input[0].toInt() + 256 else input[0].toInt()
@JvmField val INT_MAX_VALUE = ImpreciseFraction(BI_INT_MAX)
@JvmField val INT_MIN_VALUE = ImpreciseFraction(BI_INT_MIN)
@JvmField val LONG_MAX_VALUE = ImpreciseFraction(BI_LONG_MAX)
@JvmField val LONG_MIN_VALUE = ImpreciseFraction(BI_LONG_MIN)
@JvmField val FLOAT_MAX_VALUE = ImpreciseFraction(BI_FLOAT_MAX)
@JvmField val FLOAT_MIN_VALUE = ImpreciseFraction(BI_FLOAT_MIN)
@JvmField val DOUBLE_MAX_VALUE = ImpreciseFraction(BI_DOUBLE_MAX)
@JvmField val DOUBLE_MIN_VALUE = ImpreciseFraction(BI_DOUBLE_MIN)
@JvmField val NaN = ImpreciseFraction(0, Double.NaN)
@JvmStatic
fun fromByteArray(input: ByteArray): ImpreciseFraction {
val size = byteToInt(input[0])
val slice = input.copyOfRange(1, 1 + size)
val bits = bytesToLong(input, 1 + size)
return ImpreciseFraction(BigInteger(slice), Double.fromBits(bits))
}
@JvmStatic
fun deserializeNBT(input: Tag?): ImpreciseFraction {
if (input is ByteArrayTag) {
return fromBytesArray(input.asByteArray)
return fromByteArray(input.asByteArray)
} else if (input is StringTag) {
return ImpreciseFraction(input.asString)
}
return ZERO
}
@JvmStatic
fun read(buff: FriendlyByteBuf): ImpreciseFraction {
val len = byteToInt(buff.readByte())
val slice = ByteArray(len)
for (i in 0 until len)
slice[i] = buff.readByte()
val bits = bytesToLong(buff.readByte(), buff.readByte(), buff.readByte(), buff.readByte(), buff.readByte(), buff.readByte(), buff.readByte(), buff.readByte())
return ImpreciseFraction(BigInteger(slice), Double.fromBits(bits))
}
}
}
fun FriendlyByteBuf.readImpreciseFraction() = ImpreciseFraction.read(this)
fun FriendlyByteBuf.writeImpreciseFraction(value: ImpreciseFraction) = value.write(this)

View File

@ -6,6 +6,7 @@ import net.minecraft.world.level.block.entity.BlockEntity
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.matter.*
import ru.dbotthepony.mc.otm.core.Fraction
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.graph.Abstract6Graph
import ru.dbotthepony.mc.otm.graph.Graph6Node
import java.util.*
@ -71,8 +72,8 @@ class MatterNetworkGraph : Abstract6Graph<IMatterGraphNode>(), IMatterGraphListe
}
}
fun getMatterStorageLevel(): Fraction {
var level = Fraction.ZERO
fun getMatterStorageLevel(): ImpreciseFraction {
var level = ImpreciseFraction.ZERO
for (node in _nodes) {
val matter = node.value.getMatterHandler()
@ -85,8 +86,8 @@ class MatterNetworkGraph : Abstract6Graph<IMatterGraphNode>(), IMatterGraphListe
return level
}
fun getMatterStorageMaxLevel(): Fraction {
var level = Fraction.ZERO
fun getMatterStorageMaxLevel(): ImpreciseFraction {
var level = ImpreciseFraction.ZERO
for (node in _nodes) {
val matter = node.value.getMatterHandler()
@ -99,12 +100,12 @@ class MatterNetworkGraph : Abstract6Graph<IMatterGraphNode>(), IMatterGraphListe
return level
}
fun extractMatter(howMuch: Fraction, simulate: Boolean): Fraction {
if (howMuch <= Fraction.ZERO)
return Fraction.ZERO
fun extractMatter(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
if (howMuch <= ImpreciseFraction.ZERO)
return ImpreciseFraction.ZERO
var howMuch = howMuch
var extracted = Fraction.ZERO
var extracted = ImpreciseFraction.ZERO
for (node in _nodes) {
val matter = node.value.getMatterHandler()
@ -114,7 +115,7 @@ class MatterNetworkGraph : Abstract6Graph<IMatterGraphNode>(), IMatterGraphListe
howMuch -= value
extracted += value
if (howMuch <= Fraction.ZERO)
if (howMuch <= ImpreciseFraction.ZERO)
return extracted
}
}
@ -122,12 +123,12 @@ class MatterNetworkGraph : Abstract6Graph<IMatterGraphNode>(), IMatterGraphListe
return extracted
}
fun receiveMatter(howMuch: Fraction, simulate: Boolean): Fraction {
if (howMuch <= Fraction.ZERO)
return Fraction.ZERO
fun receiveMatter(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
if (howMuch <= ImpreciseFraction.ZERO)
return ImpreciseFraction.ZERO
var howMuch = howMuch
var received = Fraction.ZERO
var received = ImpreciseFraction.ZERO
for (node in _nodes) {
val matter = node.value.getMatterHandler()
@ -137,7 +138,7 @@ class MatterNetworkGraph : Abstract6Graph<IMatterGraphNode>(), IMatterGraphListe
howMuch -= value
received += value
if (howMuch <= Fraction.ZERO)
if (howMuch <= ImpreciseFraction.ZERO)
return received
}
}
@ -145,12 +146,12 @@ class MatterNetworkGraph : Abstract6Graph<IMatterGraphNode>(), IMatterGraphListe
return received
}
fun receiveMatterForce(howMuch: Fraction, simulate: Boolean): Fraction {
if (howMuch <= Fraction.ZERO)
return Fraction.ZERO
fun receiveMatterForce(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
if (howMuch <= ImpreciseFraction.ZERO)
return ImpreciseFraction.ZERO
var howMuch = howMuch
var received = Fraction.ZERO
var received = ImpreciseFraction.ZERO
for (node in _nodes) {
val matter = node.value.getMatterHandler()
@ -160,7 +161,7 @@ class MatterNetworkGraph : Abstract6Graph<IMatterGraphNode>(), IMatterGraphListe
howMuch -= value
received += value
if (howMuch <= Fraction.ZERO)
if (howMuch <= ImpreciseFraction.ZERO)
return received
}
}

View File

@ -20,25 +20,26 @@ import net.minecraft.world.item.TooltipFlag
import net.minecraft.world.level.Level
import net.minecraftforge.common.capabilities.Capability
import ru.dbotthepony.mc.otm.core.Fraction
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
class ItemBattery : Item {
private inner class BatteryMatteryCapability(private val stack: ItemStack) : IMatteryEnergyStorage, ICapabilityProvider {
private fun energy(): Fraction {
private fun energy(): ImpreciseFraction {
val tag = stack.orCreateTag
return if (tag.contains("otm_energy")) {
deserializeNBT(tag["otm_energy"])
} else Fraction.ZERO
ImpreciseFraction.deserializeNBT(tag["otm_energy"])
} else ImpreciseFraction.ZERO
}
private fun energy(value: Fraction) {
private fun energy(value: ImpreciseFraction) {
stack.getOrCreateTag().put("otm_energy", value.serializeNBT())
}
override fun extractEnergyOuter(howMuch: Fraction, simulate: Boolean): Fraction {
override fun extractEnergyOuter(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
return extractEnergyInner(howMuch, simulate)
}
override fun extractEnergyInner(howMuch: Fraction, simulate: Boolean): Fraction {
override fun extractEnergyInner(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
if (isCreative) return howMuch
val new = energy().minus(howMuch.min(extract)).moreThanZero()
val diff = energy().minus(new)
@ -50,11 +51,11 @@ class ItemBattery : Item {
return diff
}
override fun receiveEnergyOuter(howMuch: Fraction, simulate: Boolean): Fraction {
override fun receiveEnergyOuter(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
return receiveEnergyInner(howMuch, simulate)
}
override fun receiveEnergyInner(howMuch: Fraction, simulate: Boolean): Fraction {
override fun receiveEnergyInner(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
if (isCreative) return howMuch
val new = energy().plus(howMuch.min(receive)).min(storage)
val diff = new.minus(energy())
@ -66,15 +67,15 @@ class ItemBattery : Item {
return diff
}
override val missingPower: Fraction get() {
return if (isCreative) MatteryCapability.LONG_MAX_VALUE else super.missingPower
override val missingPower: ImpreciseFraction get() {
return if (isCreative) ImpreciseFraction.LONG_MAX_VALUE else super.missingPower
}
override val batteryLevel: Fraction get() {
return if (isCreative) MatteryCapability.LONG_MAX_VALUE else energy()
override val batteryLevel: ImpreciseFraction get() {
return if (isCreative) ImpreciseFraction.LONG_MAX_VALUE else energy()
}
override val maxBatteryLevel: Fraction get() {
override val maxBatteryLevel: ImpreciseFraction get() {
return storage
}
@ -94,12 +95,12 @@ class ItemBattery : Item {
}
private val isCreative: Boolean
val storage: Fraction
val receive: Fraction
val extract: Fraction
val storage: ImpreciseFraction
val receive: ImpreciseFraction
val extract: ImpreciseFraction
private val throughputText: Component
constructor(storage: Fraction, receive: Fraction, extract: Fraction) : super(
constructor(storage: ImpreciseFraction, receive: ImpreciseFraction, extract: ImpreciseFraction) : super(
Properties().stacksTo(1).tab(OverdriveThatMatters.CREATIVE_TAB)
) {
isCreative = false
@ -115,9 +116,9 @@ class ItemBattery : Item {
constructor() : super(Properties().stacksTo(1).rarity(Rarity.EPIC).tab(OverdriveThatMatters.CREATIVE_TAB)) {
isCreative = true
storage = MatteryCapability.LONG_MAX_VALUE
receive = MatteryCapability.LONG_MAX_VALUE
extract = MatteryCapability.LONG_MAX_VALUE
storage = ImpreciseFraction.LONG_MAX_VALUE
receive = ImpreciseFraction.LONG_MAX_VALUE
extract = ImpreciseFraction.LONG_MAX_VALUE
throughputText = TranslatableComponent("otm.item.power.infinite.throughput").withStyle(ChatFormatting.GRAY)
}

View File

@ -20,6 +20,7 @@ import ru.dbotthepony.mc.otm.capability.matter.IMatterHandler
import ru.dbotthepony.mc.otm.capability.matter.IMatterHandler.MatterDirection
import ru.dbotthepony.mc.otm.core.Fraction
import ru.dbotthepony.mc.otm.core.Fraction.Companion.deserializeNBT
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.menu.FormattingHelper
import javax.annotation.ParametersAreNonnullByDefault
@ -33,34 +34,34 @@ class ItemMatterCapacitor : Item {
return if (cap === MatteryCapability.MATTER) resolver.cast() else LazyOptional.empty()
}
private fun matter(): Fraction {
private fun matter(): ImpreciseFraction {
val tag = stack.orCreateTag
return if (tag.contains("otm_matter")) {
deserializeNBT(tag["otm_matter"])
} else Fraction.ZERO
return if (tag.contains("matter")) {
ImpreciseFraction.deserializeNBT(tag["matter"])
} else ImpreciseFraction.ZERO
}
private fun matter(value: Fraction) {
stack.getOrCreateTag().put("otm_matter", value.serializeNBT())
private fun matter(value: ImpreciseFraction) {
stack.getOrCreateTag().put("matter", value.serializeNBT())
}
override fun getStoredMatter(): Fraction {
return if (isCreative) Fraction.LONG_MAX_VALUE else matter()
override fun getStoredMatter(): ImpreciseFraction {
return if (isCreative) ImpreciseFraction.LONG_MAX_VALUE else matter()
}
override fun getMaxStoredMatter(): Fraction {
override fun getMaxStoredMatter(): ImpreciseFraction {
return storage
}
override fun getMissingMatter(): Fraction {
return if (isCreative) Fraction.LONG_MAX_VALUE else super.getMissingMatter()
override fun getMissingMatter(): ImpreciseFraction {
return if (isCreative) ImpreciseFraction.LONG_MAX_VALUE else super.getMissingMatter()
}
override fun receiveMatterOuter(howMuch: Fraction, simulate: Boolean): Fraction {
override fun receiveMatterOuter(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
return receiveMatterInner(howMuch, simulate)
}
override fun receiveMatterInner(howMuch: Fraction, simulate: Boolean): Fraction {
override fun receiveMatterInner(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
if (isCreative) return howMuch
val new = matter().plus(howMuch.min(maxInput)).min(storage)
val diff = new.minus(matter())
@ -72,11 +73,11 @@ class ItemMatterCapacitor : Item {
return diff
}
override fun extractMatterOuter(howMuch: Fraction, simulate: Boolean): Fraction {
override fun extractMatterOuter(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
return extractMatterInner(howMuch, simulate)
}
override fun extractMatterInner(howMuch: Fraction, simulate: Boolean): Fraction {
override fun extractMatterInner(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
if (isCreative) return howMuch
val new = matter().minus(howMuch.min(maxOutput)).moreThanZero()
val diff = matter().minus(new)
@ -93,17 +94,17 @@ class ItemMatterCapacitor : Item {
}
}
val storage: Fraction
val storage: ImpreciseFraction
private val isCreative: Boolean
constructor(storage: Fraction) : super(Properties().stacksTo(1).tab(OverdriveThatMatters.CREATIVE_TAB)) {
constructor(storage: ImpreciseFraction) : super(Properties().stacksTo(1).tab(OverdriveThatMatters.CREATIVE_TAB)) {
isCreative = false
this.storage = storage
}
constructor() : super(Properties().stacksTo(1).tab(OverdriveThatMatters.CREATIVE_TAB).rarity(Rarity.EPIC)) {
isCreative = true
storage = MatteryCapability.LONG_MAX_VALUE
storage = ImpreciseFraction.LONG_MAX_VALUE
}
override fun appendHoverText(
@ -133,8 +134,8 @@ class ItemMatterCapacitor : Item {
}
companion object {
private val maxInput = MatteryCapability.LONG_MAX_VALUE
private val maxOutput = MatteryCapability.LONG_MAX_VALUE
private val maxInput = ImpreciseFraction.LONG_MAX_VALUE
private val maxOutput = ImpreciseFraction.LONG_MAX_VALUE
private val INFINITE_STORAGE: Component =
TranslatableComponent("otm.item.matter.infinite").withStyle(ChatFormatting.GRAY)

View File

@ -25,15 +25,16 @@ import net.minecraftforge.eventbus.api.SubscribeEvent
import net.minecraftforge.event.entity.player.EntityItemPickupEvent
import ru.dbotthepony.mc.otm.capability.drive.DrivePool
import ru.dbotthepony.mc.otm.core.Fraction
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.set
import java.util.*
class ItemPortableCondensationDrive(capacity: Int) :
Item(Properties().stacksTo(1).tab(OverdriveThatMatters.CREATIVE_TAB)) {
val capacity: Fraction
val capacity: ImpreciseFraction
init {
this.capacity = Fraction(capacity)
this.capacity = ImpreciseFraction(capacity)
}
private inner class DriveCapability(private val stack: ItemStack) : ICapabilityProvider {

View File

@ -5,16 +5,17 @@ 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 ru.dbotthepony.mc.otm.menu.data.ImpreciseFractionDataContainer
class MenuEnergyCounter @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()
@JvmField val passed = ImpreciseFractionDataContainer()
@JvmField val average = ImpreciseFractionDataContainer()
@JvmField val last20Ticks = ImpreciseFractionDataContainer()
@JvmField val lastTick = ImpreciseFractionDataContainer()
// TODO: Graph and proper networking for it
private var ticksPassed = 0

View File

@ -5,6 +5,7 @@ import net.minecraft.world.entity.player.Inventory
import ru.dbotthepony.mc.otm.Registry
import ru.dbotthepony.mc.otm.block.entity.BlockEntityMatterCapacitorBank
import ru.dbotthepony.mc.otm.core.Fraction
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.graph.matter.MatterNetworkGraph
import ru.dbotthepony.mc.otm.menu.widget.LevelGaugeWidget
@ -26,9 +27,9 @@ class MenuMatterCapacitor @JvmOverloads constructor(
} else {
matterGauge = LevelGaugeWidget(this, tile)
totalMatterGauge = LevelGaugeWidget(this, {
(tile.getAsMatterNode().graph as MatterNetworkGraph?)?.getMatterStorageLevel() ?: Fraction.ZERO
(tile.getAsMatterNode().graph as MatterNetworkGraph?)?.getMatterStorageLevel() ?: ImpreciseFraction.ZERO
}, {
(tile.getAsMatterNode().graph as MatterNetworkGraph?)?.getMatterStorageMaxLevel() ?: Fraction.ZERO
(tile.getAsMatterNode().graph as MatterNetworkGraph?)?.getMatterStorageMaxLevel() ?: ImpreciseFraction.ZERO
})
}

View File

@ -9,6 +9,7 @@ import net.minecraft.world.SimpleContainer
import net.minecraft.world.item.ItemStack
import ru.dbotthepony.mc.otm.Registry
import ru.dbotthepony.mc.otm.core.Fraction
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.matter.MatterRegistry
import java.math.BigInteger
@ -37,8 +38,8 @@ class MenuMatterScanner @JvmOverloads constructor(
if (tile != null) {
progress = ProgressGaugeWidget(this, { tile.workProgress.toFloat() }, tile::isUnableToProcess)
patterns = LevelGaugeWidget(this,
{ Fraction(tile.getAsMatterGraph()?.getPatternCount()?.toBigInteger() ?: BigInteger.ZERO) },
{ Fraction(tile.getAsMatterGraph()?.getPatternCapacity()?.toBigInteger() ?: BigInteger.ZERO) })
{ ImpreciseFraction(tile.getAsMatterGraph()?.getPatternCount()?.toBigInteger() ?: BigInteger.ZERO) },
{ ImpreciseFraction(tile.getAsMatterGraph()?.getPatternCapacity()?.toBigInteger() ?: BigInteger.ZERO) })
} else {
progress = ProgressGaugeWidget(this)
patterns = LevelGaugeWidget(this)

View File

@ -5,6 +5,7 @@ import net.minecraft.world.entity.player.Inventory
import ru.dbotthepony.mc.otm.Registry
import ru.dbotthepony.mc.otm.block.entity.BlockEntityPatternStorage
import ru.dbotthepony.mc.otm.core.Fraction
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.graph.matter.MatterNetworkGraph
import ru.dbotthepony.mc.otm.menu.widget.LevelGaugeWidget
@ -26,9 +27,9 @@ class MenuPatternStorage @JvmOverloads constructor(
} else {
stored_this = LevelGaugeWidget(this, tile)
stored_grid = LevelGaugeWidget(this, {
Fraction((tile.getAsMatterNode().graph as MatterNetworkGraph?)?.getPatternCount() ?: 0)
ImpreciseFraction((tile.getAsMatterNode().graph as MatterNetworkGraph?)?.getPatternCount() ?: 0)
}, {
Fraction((tile.getAsMatterNode().graph as MatterNetworkGraph?)?.getPatternCapacity() ?: 0)
ImpreciseFraction((tile.getAsMatterNode().graph as MatterNetworkGraph?)?.getPatternCapacity() ?: 0)
})
}

View File

@ -3,6 +3,7 @@ package ru.dbotthepony.mc.otm.menu.data
import net.minecraft.world.inventory.ContainerData
import org.apache.logging.log4j.LogManager
import ru.dbotthepony.mc.otm.core.Fraction
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.network.NetworkHelper
import java.util.zip.CRC32
@ -47,6 +48,7 @@ class FractionDataContainer : ContainerData {
set(value) {
_value = value
val _value = _value
if (_value == null) {
buffer.fill(0)
return
@ -54,7 +56,95 @@ class FractionDataContainer : ContainerData {
try {
val bytes = ByteArray(128) {0}
_value!!.toByteArray().copyInto(bytes)
_value.toByteArray().copyInto(bytes)
val crc = CRC32()
crc.update(bytes)
val crcValue = crc.value
val a = (crcValue and 0xFFFF).toShort()
val b = ((crcValue and 0xFFFF0000) ushr 16).toShort()
buffer[0] = a
buffer[1] = b
NetworkHelper.bytesToShorts(bytes).copyInto(buffer, destinationOffset = 2)
} catch(err: Throwable) {
if (!mute) {
LOGGER.error("Unable to serialize value $value for network transportation", err)
mute = true
}
buffer.fill(0)
}
}
val buffer = ShortArray(NETWORK_PAYLOAD_SIZE)
override operator fun get(p_39284_: Int): Int {
return buffer[p_39284_].toInt()
}
override operator fun set(p_39285_: Int, p_39286_: Int) {
buffer[p_39285_] = p_39286_.toShort()
if (_value != null) _value2 = _value
_value = null
}
override fun getCount(): Int {
return buffer.size
}
}
class ImpreciseFractionDataContainer : ContainerData {
companion object {
// CRC32 + Данные
const val NETWORK_PAYLOAD_SIZE = 64 + 2
private val LOGGER = LogManager.getLogger()
}
private var _value: ImpreciseFraction? = ImpreciseFraction.ZERO
private var _value2: ImpreciseFraction? = ImpreciseFraction.ZERO
fun hasComputedValue(): Boolean {
return _value != null
}
private var mute = false
var value: ImpreciseFraction
get() {
if (_value != null)
return _value!!
val bytes = NetworkHelper.shortsToBytes(buffer, 2)
val crc = CRC32()
crc.update(bytes)
val crcValue = crc.value
val a = (crcValue and 0xFFFF).toShort()
val b = ((crcValue and 0xFFFF0000) ushr 16).toShort()
if (a == buffer[0] && b == buffer[1]) {
_value = ImpreciseFraction.fromByteArray(bytes)
} else {
_value = _value2
}
return _value!!
}
set(value) {
_value = value
val _value = _value
if (_value == null) {
buffer.fill(0)
return
}
try {
val bytes = ByteArray(128) {0}
_value.toByteArray().copyInto(bytes)
val crc = CRC32()
crc.update(bytes)

View File

@ -8,7 +8,7 @@ import net.minecraft.world.inventory.ClickAction
import net.minecraft.world.inventory.ClickType
import net.minecraft.world.item.ItemStack
import net.minecraftforge.network.PacketDistributor
import ru.dbotthepony.mc.otm.core.Fraction
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.menu.MatteryMenu
import ru.dbotthepony.mc.otm.network.MatteryNetworking
import ru.dbotthepony.mc.otm.network.SetCarriedPacket
@ -78,7 +78,7 @@ open class NetworkedItemView(val ply: Player, val menu: MatteryMenu, val remote:
}
override fun addObject(stack: ItemStackWrapper, id: UUID, provider: IStorageView<ItemStackWrapper>) = addObject(stack.stack, id)
override fun changeObject(id: UUID, newCount: Fraction) = changeObject(id, newCount.toInt())
override fun changeObject(id: UUID, newCount: ImpreciseFraction) = changeObject(id, newCount.toInt())
protected fun network(fn: () -> Any) {
if (!remote) {

View File

@ -4,16 +4,18 @@ import ru.dbotthepony.mc.otm.capability.IMatteryEnergyStorage
import ru.dbotthepony.mc.otm.capability.matter.IMatterHandler
import ru.dbotthepony.mc.otm.capability.matter.IPatternStorage
import ru.dbotthepony.mc.otm.core.Fraction
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.menu.MatteryMenu
import ru.dbotthepony.mc.otm.menu.data.FractionDataContainer
import ru.dbotthepony.mc.otm.menu.data.ImpreciseFractionDataContainer
@Suppress("unused")
class LevelGaugeWidget(menu: MatteryMenu) : AbstractWidget(menu) {
@JvmField var level = {Fraction.ONE}
@JvmField var maxLevel = {Fraction.ONE}
@JvmField var level = { ImpreciseFraction.ONE}
@JvmField var maxLevel = {ImpreciseFraction.ONE}
@JvmField val levelContainer = FractionDataContainer()
@JvmField val maxLevelContainer = FractionDataContainer()
@JvmField val levelContainer = ImpreciseFractionDataContainer()
@JvmField val maxLevelContainer = ImpreciseFractionDataContainer()
constructor(
menu: MatteryMenu,
@ -41,14 +43,14 @@ class LevelGaugeWidget(menu: MatteryMenu) : AbstractWidget(menu) {
) : this(menu) {
if (patterns == null) return
this.level = {Fraction(patterns.stored)}
this.maxLevel = {Fraction(patterns.capacity)}
this.level = {ImpreciseFraction(patterns.stored)}
this.maxLevel = {ImpreciseFraction(patterns.capacity)}
}
constructor(
menu: MatteryMenu,
level: () -> Fraction,
maxLevel: () -> Fraction,
level: () -> ImpreciseFraction,
maxLevel: () -> ImpreciseFraction,
) : this(menu) {
this.level = level
this.maxLevel = maxLevel
@ -64,7 +66,7 @@ class LevelGaugeWidget(menu: MatteryMenu) : AbstractWidget(menu) {
maxLevelContainer.value = maxLevel.invoke()
}
fun level(): Fraction = levelContainer.value
fun maxLevel(): Fraction = maxLevelContainer.value
fun level(): ImpreciseFraction = levelContainer.value
fun maxLevel(): ImpreciseFraction = maxLevelContainer.value
fun percentage(): Float = levelContainer.value.percentage(maxLevelContainer.value)
}

View File

@ -1,19 +1,19 @@
package ru.dbotthepony.mc.otm.storage
import ru.dbotthepony.mc.otm.core.Fraction
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import java.util.*
interface IStorageStack {
fun copy(): IStorageStack
var count: Fraction
var count: ImpreciseFraction
fun isEmpty(): Boolean
/**
* @return max stack size for this stack object
* [Optional.empty()] if unlimited (default)
*/
fun getMaxStackSize(): Optional<Fraction> = Optional.empty()
fun getMaxStackSize(): Optional<ImpreciseFraction> = Optional.empty()
/**
* Returns Identity utilized to partition view table (if it has any).
@ -38,11 +38,11 @@ interface IStorageStack {
*/
fun sameItem(other: IStorageStack): Boolean
fun grow(amount: Fraction) {
fun grow(amount: ImpreciseFraction) {
count += amount
}
fun shrink(amount: Fraction) {
fun shrink(amount: ImpreciseFraction) {
count -= amount
}
}
@ -83,9 +83,9 @@ interface IStorageView<T : IStorageStack> : IStorageTrigger<T> {
* @param simulate whenever to simulate the action or not
* @return copy of object, with amount of units actually extracted
*/
fun extractStack(id: UUID, amount: Fraction, simulate: Boolean): T
fun extractStack(id: UUID, amount: Int, simulate: Boolean): T = extractStack(id, Fraction(amount), simulate)
fun extractStack(id: UUID, amount: Long, simulate: Boolean): T = extractStack(id, Fraction(amount), simulate)
fun extractStack(id: UUID, amount: ImpreciseFraction, simulate: Boolean): T
fun extractStack(id: UUID, amount: Int, simulate: Boolean): T = extractStack(id, ImpreciseFraction(amount), simulate)
fun extractStack(id: UUID, amount: Long, simulate: Boolean): T = extractStack(id, ImpreciseFraction(amount), simulate)
/**
* Designed for views, for extraction with less computation overhead caused by
@ -96,12 +96,12 @@ interface IStorageView<T : IStorageStack> : IStorageTrigger<T> {
* @param simulate whenever to simulate the action or not
* @return amount extracted
*/
fun extractStackCount(id: UUID, amount: Fraction, simulate: Boolean): Fraction {
fun extractStackCount(id: UUID, amount: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
return extractStack(id, amount, simulate).count
}
fun extractStackCount(id: UUID, amount: Int, simulate: Boolean): Fraction = extractStackCount(id, Fraction(amount), simulate)
fun extractStackCount(id: UUID, amount: Long, simulate: Boolean): Fraction = extractStackCount(id, Fraction(amount), simulate)
fun extractStackCount(id: UUID, amount: Int, simulate: Boolean): ImpreciseFraction = extractStackCount(id, ImpreciseFraction(amount), simulate)
fun extractStackCount(id: UUID, amount: Long, simulate: Boolean): ImpreciseFraction = extractStackCount(id, ImpreciseFraction(amount), simulate)
fun getStacks(): Collection<IStorageTuple<T>>
@ -139,7 +139,7 @@ interface IStorageListener<T : IStorageStack> {
/**
* Fired on whenever an object is changes on listener we subscribed to
*/
fun changeObject(id: UUID, newCount: Fraction)
fun changeObject(id: UUID, newCount: ImpreciseFraction)
/**
* Fired on whenever an object is removed from listener we subscribed to

View File

@ -2,6 +2,7 @@ package ru.dbotthepony.mc.otm.storage
import net.minecraft.world.item.ItemStack
import ru.dbotthepony.mc.otm.core.Fraction
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import java.util.*
@JvmRecord
@ -14,14 +15,14 @@ data class ItemStackWrapper(val stack: ItemStack) : IStorageStack {
stack.count = Math.max(value, 0)
}
override var count: Fraction
get() = Fraction(stack.count)
override var count: ImpreciseFraction
get() = ImpreciseFraction(stack.count)
set(value) = setCount(value.toInt())
fun getCountInt() = stack.count
override fun getMaxStackSize(): Optional<Fraction> {
return Optional.of(Fraction(stack.maxStackSize))
override fun getMaxStackSize(): Optional<ImpreciseFraction> {
return Optional.of(ImpreciseFraction(stack.maxStackSize))
}
override fun isEmpty(): Boolean = stack.isEmpty

View File

@ -2,14 +2,15 @@ package ru.dbotthepony.mc.otm.storage
import ru.dbotthepony.mc.otm.capability.IMatteryEnergyStorage
import ru.dbotthepony.mc.otm.core.Fraction
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import java.util.*
class RemoteTuple<T : IStorageStack>(val obj: T, val remote_id: UUID, val provider: IStorageView<T>, val local: LocalTuple<T>) {
fun extract(amount: Fraction, simulate: Boolean): T {
fun extract(amount: ImpreciseFraction, simulate: Boolean): T {
return provider.extractStack(remote_id, amount, simulate)
}
fun extractCount(amount: Fraction, simulate: Boolean): Fraction {
fun extractCount(amount: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
return provider.extractStackCount(remote_id, amount, simulate)
}
@ -145,8 +146,8 @@ open class VirtualComponent<T : IStorageStack>(identity: Class<T>) : IStorageCom
}
}
override fun changeObject(id: UUID, newCount: Fraction) {
assert(newCount > Fraction.ZERO)
override fun changeObject(id: UUID, newCount: ImpreciseFraction) {
assert(newCount > ImpreciseFraction.ZERO)
val tuple = remoteByUUID[id] ?: throw IllegalStateException("No such tuple with id $id")
val diff = newCount - tuple.obj.count
@ -167,7 +168,7 @@ open class VirtualComponent<T : IStorageStack>(identity: Class<T>) : IStorageCom
remoteByUUID.remove(id)
val a = tuple.local.stack.count <= Fraction.ZERO
val a = tuple.local.stack.count <= ImpreciseFraction.ZERO
val b = tuple.local.tuples.size == 0
if (a || b) {
@ -195,21 +196,21 @@ open class VirtualComponent<T : IStorageStack>(identity: Class<T>) : IStorageCom
return leftover
}
override fun extractStack(id: UUID, amount: Fraction, simulate: Boolean): T {
if (amount.isZero())
override fun extractStack(id: UUID, amount: ImpreciseFraction, simulate: Boolean): T {
if (amount.isZero)
return identity.empty
var amount = amount
val tuple: LocalTuple<T>? = localByUUID[id]
if (tuple == null || amount.isZero())
if (tuple == null || amount.isZero)
return identity.empty
if (amount <= Fraction.MINUS_ONE)
if (amount <= ImpreciseFraction.MINUS_ONE)
amount = tuple.stack.getMaxStackSize().orElse(tuple.stack.count)
val toExtract = tuple.stack.count.min(amount)
var extracted = Fraction.ZERO
var extracted = ImpreciseFraction.ZERO
val copy = tuple.stack.copy() as T
for (remote_tuple in tuple.tuples) {
@ -219,7 +220,7 @@ open class VirtualComponent<T : IStorageStack>(identity: Class<T>) : IStorageCom
break
}
if (extracted > Fraction.ZERO) {
if (extracted > ImpreciseFraction.ZERO) {
copy.count = extracted
return copy
}
@ -235,11 +236,11 @@ open class PoweredVirtualComponent<T : IStorageStack>(identity: Class<T>, @JvmFi
}
override fun insertStack(stack: T, simulate: Boolean): T {
val required = stack.count * identity.energyPerOperation
val required = identity.energyPerOperation * stack.count
val energy = energyProvider()
val extracted = energy.extractEnergyInner(required, true)
if (extracted.isZero()) {
if (extracted.isZero) {
return stack.copy() as T
}
@ -255,7 +256,7 @@ open class PoweredVirtualComponent<T : IStorageStack>(identity: Class<T>, @JvmFi
}
if (!simulate) {
val requiredNew = (stack.count - leftover.count) * identity.energyPerOperation
val requiredNew = identity.energyPerOperation * stack.count - leftover.count
energy.extractEnergyInner(requiredNew, false)
}
@ -266,7 +267,7 @@ open class PoweredVirtualComponent<T : IStorageStack>(identity: Class<T>, @JvmFi
val oldCount = stack.count
stack.count = extracted / identity.energyPerOperation
val diff = oldCount - stack.count
val newRequired = stack.count * identity.energyPerOperation
val newRequired = identity.energyPerOperation * stack.count
val newExtracted = energy.extractEnergyInner(newRequired, true)
if (newExtracted == newRequired) {
@ -293,12 +294,12 @@ open class PoweredVirtualComponent<T : IStorageStack>(identity: Class<T>, @JvmFi
return stack
}
override fun extractStack(id: UUID, amount: Fraction, simulate: Boolean): T {
val required = amount * identity.energyPerOperation
override fun extractStack(id: UUID, amount: ImpreciseFraction, simulate: Boolean): T {
val required = identity.energyPerOperation * amount
val energy = energyProvider()
val extracted = energy.extractEnergyInner(required, true)
if (extracted.isZero()) {
if (extracted.isZero) {
return identity.empty
}

View File

@ -37,7 +37,7 @@ object ImpreciseFractionTests {
@DisplayName("ImpreciseFraction store/load")
fun storeLoad() {
val f = ImpreciseFraction(4, 0.28)
val loaded = ImpreciseFraction.fromBytesArray(f.toBytesArray())
val loaded = ImpreciseFraction.fromByteArray(f.toByteArray())
check(f == loaded) { "$f != $loaded" }
}
}