Kotlin, Unit tests, Fraction instead of BigDecimal

This commit is contained in:
DBotThePony 2021-12-23 22:46:25 +07:00
parent 69defb2e62
commit 6d78029af2
Signed by: DBot
GPG Key ID: DCC23B5715498507
59 changed files with 1752 additions and 801 deletions

View File

@ -5,8 +5,11 @@ buildscript {
maven { url = 'https://maven.minecraftforge.net' }
mavenCentral()
}
dependencies {
classpath group: 'net.minecraftforge.gradle', name: 'ForgeGradle', version: '5.1.+', changing: true
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.0"
}
}
@ -14,6 +17,9 @@ apply plugin: 'net.minecraftforge.gradle'
// Only edit below this line, the above code adds and enables the necessary things for Forge to be setup.
apply plugin: 'eclipse'
apply plugin: 'maven-publish'
apply plugin: 'kotlin'
apply from: 'https://raw.githubusercontent.com/thedarkcolour/KotlinForForge/site/thedarkcolour/kotlinforforge/gradle/kff-3.0.0.gradle'
version = '1.0'
group = 'ru.dbotthepony.mc' // http://maven.apache.org/guides/mini/guide-naming-conventions.html
@ -29,6 +35,10 @@ exec {
args 'shapenator.js'
}
test {
useJUnitPlatform()
}
minecraft {
// The mappings can be changed at any time and must be in the following format.
// Channel: Version:
@ -140,6 +150,8 @@ dependencies {
// The userdev artifact is a special name and will get all sorts of transformations applied to it.
minecraft 'net.minecraftforge:forge:1.18.1-39.0.7'
testImplementation 'org.junit.jupiter:junit-jupiter:5.8.2'
// Real mod deobf dependency examples - these get remapped to your current mappings
// compileOnly fg.deobf("mezz.jei:jei-${mc_version}:${jei_version}:api") // Adds JEI API as a compile dependency
// runtimeOnly fg.deobf("mezz.jei:jei-${mc_version}:${jei_version}") // Adds the full JEI mod as a runtime dependency

View File

@ -6,6 +6,8 @@ import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.TickEvent;
import net.minecraftforge.event.server.ServerAboutToStartEvent;
import net.minecraftforge.event.server.ServerStoppingEvent;
import net.minecraftforge.eventbus.api.EventPriority;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.InterModComms;
@ -16,14 +18,12 @@ import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.event.lifecycle.InterModEnqueueEvent;
import net.minecraftforge.fml.event.lifecycle.InterModProcessEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.event.server.ServerAboutToStartEvent;
import net.minecraftforge.event.server.ServerStoppingEvent;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import ru.dbotthepony.mc.otm.block.entity.BlockEntityBlackHole;
import ru.dbotthepony.mc.otm.capability.MatteryCapability;
import ru.dbotthepony.mc.otm.capability.android.AndroidCapability;
import ru.dbotthepony.mc.otm.capability.android.AndroidCapabilityPlayer;
import ru.dbotthepony.mc.otm.capability.MatteryCapability;
import ru.dbotthepony.mc.otm.capability.drive.DrivePool;
import ru.dbotthepony.mc.otm.client.AndroidGui;
import ru.dbotthepony.mc.otm.client.EventHandler;

View File

@ -37,6 +37,7 @@ import ru.dbotthepony.mc.otm.block.entity.*;
import ru.dbotthepony.mc.otm.android.AndroidFeatureType;
import ru.dbotthepony.mc.otm.client.render.BlackHoleRenderer;
import ru.dbotthepony.mc.otm.client.render.SkinElement;
import ru.dbotthepony.mc.otm.core.Fraction;
import ru.dbotthepony.mc.otm.item.*;
import ru.dbotthepony.mc.otm.menu.*;
import ru.dbotthepony.mc.otm.client.screen.*;
@ -410,17 +411,17 @@ public class Registry {
public static final ItemPill PILL_ANDROID = new ItemPill(ItemPill.PillType.BECOME_ANDROID);
public static final ItemPill PILL_HUMANE = new ItemPill(ItemPill.PillType.BECOME_HUMANE);
public static final ItemBattery BATTERY_CRUDE = new ItemBattery(new BigDecimal(30_000), new BigDecimal(150), new BigDecimal(150));
public static final ItemBattery BATTERY_BASIC = new ItemBattery(new BigDecimal(60_000), new BigDecimal(300), new BigDecimal(300));
public static final ItemBattery BATTERY_NORMAL = new ItemBattery(new BigDecimal(250_000), new BigDecimal(1000), new BigDecimal(1000));
public static final ItemBattery BATTERY_DENSE = new ItemBattery(new BigDecimal(1_000_000), new BigDecimal(2000), new BigDecimal(2000));
public static final ItemBattery BATTERY_CAPACITOR = new ItemBattery(new BigDecimal(150_000), new BigDecimal(15000), new BigDecimal(15000));
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_CREATIVE = new ItemBattery();
public static final Item MATTER_CAPACITOR_PARTS = new Item(new Item.Properties().stacksTo(64).tab(OverdriveThatMatters.CREATIVE_TAB));
public static final ItemMatterCapacitor MATTER_CAPACITOR_BASIC = new ItemMatterCapacitor(new BigDecimal("4"));
public static final ItemMatterCapacitor MATTER_CAPACITOR_NORMAL = new ItemMatterCapacitor(new BigDecimal("10"));
public static final ItemMatterCapacitor MATTER_CAPACITOR_DENSE = new ItemMatterCapacitor(new BigDecimal("40"));
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_CREATIVE = new ItemMatterCapacitor();
public static final ItemPatternStorage PATTERN_DRIVE_NORMAL = new ItemPatternStorage(4);

View File

@ -8,6 +8,7 @@ import ru.dbotthepony.mc.otm.android.AndroidFeature;
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 java.math.BigDecimal;
@ -38,8 +39,8 @@ public class AndroidNanobotsArmor extends AndroidFeature {
protected int ticks_passed = 0;
protected int layers = 0;
protected static final BigDecimal ENERGY_PER_BUILT = new BigDecimal(200);
protected static final BigDecimal ENERGY_PER_HITPOINT = new BigDecimal(500);
protected static final Fraction ENERGY_PER_BUILT = new Fraction(200);
protected static final Fraction ENERGY_PER_HITPOINT = new Fraction(500);
public static final int[] TICKS = new int[] {
80, // 4 seconds to build a layer
@ -77,9 +78,9 @@ public class AndroidNanobotsArmor extends AndroidFeature {
var absorbed = event.getAmount() * SHIELD_STRENGTH[layers];
if (absorbed > 0.1f) {
var required = ENERGY_PER_HITPOINT.multiply(new BigDecimal(Float.toString(absorbed)));
var required = ENERGY_PER_HITPOINT.times(absorbed);
var extracted = capability.extractEnergyInner(required, false);
var real_absorbed = absorbed * extracted.divide(required, MatteryCapability.ROUND_RULES).floatValue();
var real_absorbed = absorbed * extracted.div(required).toFloat();
event.setAmount(event.getAmount() - real_absorbed);
if (capability.getEntity() instanceof ServerPlayer ply) {

View File

@ -8,6 +8,7 @@ import ru.dbotthepony.mc.otm.android.AndroidFeature;
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 java.math.BigDecimal;
@ -19,7 +20,7 @@ public class AndroidNanobotsRegeneration extends AndroidFeature {
protected int ticks_passed = 0;
protected int heal_ticks = 0;
protected static final BigDecimal ENERGY_PER_HITPOINT = new BigDecimal(800);
protected static final Fraction ENERGY_PER_HITPOINT = new Fraction(800);
protected static final int[] TICKS_BETWEEN_HEAL = new int[] {
100, // 5 seconds
@ -39,11 +40,11 @@ public class AndroidNanobotsRegeneration extends AndroidFeature {
if (ticks_passed > wait_time) {
var missing = Math.min(1, ent.getMaxHealth() - ent.getHealth());
var extract = capability.extractEnergyInner(ENERGY_PER_HITPOINT.multiply(new BigDecimal(Float.toString(missing))), false);
var extract = capability.extractEnergyInner(ENERGY_PER_HITPOINT.times(missing), false);
if (extract.compareTo(BigDecimal.ZERO) > 0) {
if (extract.compareTo(Fraction.ZERO) > 0) {
heal_ticks = Math.min(heal_ticks + 1, level);
var heal = missing * extract.divide(ENERGY_PER_HITPOINT, MatteryCapability.ROUND_RULES).floatValue();
var heal = missing * extract.div(ENERGY_PER_HITPOINT).toFloat();
ent.heal(heal);
if (capability.getEntity() instanceof ServerPlayer ply) {

View File

@ -17,6 +17,7 @@ import ru.dbotthepony.mc.otm.Registry;
import ru.dbotthepony.mc.otm.capability.android.IAndroidCapability;
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.menu.AndroidStationMenu;
import javax.annotation.Nullable;
@ -43,7 +44,7 @@ public class BlockEntityAndroidStation extends BlockEntityMatteryPowered impleme
public BlockEntityAndroidStation(BlockPos p_155229_, BlockState p_155230_) {
super(Registry.BlockEntities.ANDROID_STATION, p_155229_, p_155230_);
energy = new MatteryMachineEnergyStorage(this, MatteryMachineEnergyStorage.MachineType.WORKER, new BigDecimal(100_000), new BigDecimal(250), new BigDecimal(250));
energy = new MatteryMachineEnergyStorage(this, MatteryMachineEnergyStorage.MachineType.WORKER, new Fraction(100_000), new Fraction(250), new Fraction(250));
}
public static <T extends BlockEntity> void tick(Level level, BlockPos blockPos, BlockState blockState, T t) {
@ -69,13 +70,13 @@ public class BlockEntityAndroidStation extends BlockEntityMatteryPowered impleme
final var missing = capability.getMissingPower();
if (missing.compareTo(BigDecimal.ZERO) > 0) {
if (missing.compareTo(Fraction.ZERO) > 0) {
final var extract = tile.energy.extractEnergyInner(missing, true);
if (extract.compareTo(BigDecimal.ZERO) > 0) {
if (extract.compareTo(Fraction.ZERO) > 0) {
final var received = capability.receiveEnergyOuter(extract, true);
if (received.compareTo(BigDecimal.ZERO) > 0) {
if (received.compareTo(Fraction.ZERO) > 0) {
tile.energy.extractEnergyInner(extract, false);
capability.receiveEnergyOuter(extract, false);
}

View File

@ -27,6 +27,7 @@ import ru.dbotthepony.mc.otm.block.BlockMatteryRotatable;
import ru.dbotthepony.mc.otm.capability.IMatteryEnergyStorage;
import ru.dbotthepony.mc.otm.capability.MatteryCapability;
import ru.dbotthepony.mc.otm.container.MatteryContainer;
import ru.dbotthepony.mc.otm.core.Fraction;
import ru.dbotthepony.mc.otm.menu.BatteryBankMenu;
import javax.annotation.Nonnull;
@ -63,7 +64,7 @@ public class BlockEntityBatteryBank extends BlockEntityMattery {
(slot, amount, stack) -> true
));
public record BatteryBankDistribution(BigDecimal[] distribution, BigDecimal max_throughput) {
public record BatteryBankDistribution(Fraction[] distribution, Fraction max_throughput) {
}
@ -86,16 +87,16 @@ public class BlockEntityBatteryBank extends BlockEntityMattery {
@Nonnull
@Override
public BigDecimal extractEnergyOuter(BigDecimal howMuch, boolean simulate) {
public Fraction extractEnergyOuter(Fraction howMuch, boolean simulate) {
if (mode == BankMode.RECEIVE)
return BigDecimal.ZERO;
return Fraction.ZERO;
return extractEnergyInner(howMuch, simulate);
}
BatteryBankDistribution getDistribution(boolean mode) {
BigDecimal[] distribution = new BigDecimal[tile.battery_container.getContainerSize()];
BigDecimal summ = BigDecimal.ZERO;
Fraction[] distribution = new Fraction[tile.battery_container.getContainerSize()];
Fraction summ = Fraction.ZERO;
for (int i = 0; i < tile.battery_container.getContainerSize(); i++) {
ItemStack stack = tile.battery_container.getItem(i);
@ -104,57 +105,57 @@ public class BlockEntityBatteryBank extends BlockEntityMattery {
Optional<IMatteryEnergyStorage> cap = stack.getCapability(MatteryCapability.ENERGY).resolve();
if (cap.isPresent()) {
BigDecimal diff = mode ? cap.get().receiveEnergyOuter(MatteryCapability.LONG_MAX_VALUE, true) : cap.get().extractEnergyOuter(MatteryCapability.LONG_MAX_VALUE, true);
Fraction diff = mode ? cap.get().receiveEnergyOuter(MatteryCapability.LONG_MAX_VALUE, true) : cap.get().extractEnergyOuter(MatteryCapability.LONG_MAX_VALUE, true);
distribution[i] = diff;
summ = summ.add(diff);
summ = summ.plus(diff);
} else {
Optional<IEnergyStorage> cap2 = stack.getCapability(CapabilityEnergy.ENERGY).resolve();
if (cap2.isPresent()) {
BigDecimal diff = new BigDecimal(mode ? cap2.get().receiveEnergy(Integer.MAX_VALUE, true) : cap2.get().extractEnergy(Integer.MAX_VALUE, true));
Fraction diff = new Fraction(mode ? cap2.get().receiveEnergy(Integer.MAX_VALUE, true) : cap2.get().extractEnergy(Integer.MAX_VALUE, true));
distribution[i] = diff;
summ = summ.add(diff);
summ = summ.plus(diff);
}
}
} else {
distribution[i] = BigDecimal.ZERO;
distribution[i] = Fraction.ZERO;
}
}
if (summ.compareTo(BigDecimal.ZERO) != 0) {
if (summ.compareTo(Fraction.ZERO) != 0) {
for (int i = 0; i < tile.battery_container.getContainerSize(); i++) {
distribution[i] = distribution[i].divide(summ, MatteryCapability.ROUND_RULES);
distribution[i] = distribution[i].div(summ);
}
}
return new BatteryBankDistribution(distribution, summ);
}
private BigDecimal distributeEnergy(boolean mode, BigDecimal howMuch, boolean simulate) {
private Fraction distributeEnergy(boolean mode, Fraction howMuch, boolean simulate) {
BatteryBankDistribution distribution = getDistribution(mode);
if (distribution.max_throughput.compareTo(BigDecimal.ZERO) == 0)
return BigDecimal.ZERO;
if (distribution.max_throughput.compareTo(Fraction.ZERO) == 0)
return Fraction.ZERO;
BigDecimal[] distList = distribution.distribution;
BigDecimal summ = BigDecimal.ZERO;
Fraction[] distList = distribution.distribution;
Fraction summ = Fraction.ZERO;
for (int i = 0; i < tile.battery_container.getContainerSize(); i++) {
if (!distList[i].equals(BigDecimal.ZERO)) {
if (!distList[i].equals(Fraction.ZERO)) {
ItemStack stack = tile.battery_container.getItem(i);
if (!stack.isEmpty()) {
Optional<IMatteryEnergyStorage> cap = stack.getCapability(MatteryCapability.ENERGY).resolve();
if (cap.isPresent()) {
BigDecimal diff = mode ? cap.get().receiveEnergyOuter(howMuch.multiply(distList[i], MatteryCapability.ROUND_RULES), simulate) : cap.get().extractEnergyOuter(howMuch.multiply(distList[i], MatteryCapability.ROUND_RULES), simulate);
summ = summ.add(diff);
Fraction diff = mode ? cap.get().receiveEnergyOuter(howMuch.times(distList[i]), simulate) : cap.get().extractEnergyOuter(howMuch.times(distList[i]), simulate);
summ = summ.plus(diff);
} else {
Optional<IEnergyStorage> cap2 = stack.getCapability(CapabilityEnergy.ENERGY).resolve();
if (cap2.isPresent()) {
BigDecimal diff = mode ? MatteryCapability.floodFE(cap2.get(), howMuch.multiply(distList[i], MatteryCapability.ROUND_RULES), simulate) : MatteryCapability.drainFE(cap2.get(), howMuch.multiply(distList[i], MatteryCapability.ROUND_RULES), simulate);
summ = summ.add(diff);
Fraction diff = mode ? MatteryCapability.floodFE(cap2.get(), howMuch.times(distList[i]), simulate) : MatteryCapability.drainFE(cap2.get(), howMuch.times(distList[i]), simulate);
summ = summ.plus(diff);
}
}
}
@ -166,29 +167,29 @@ public class BlockEntityBatteryBank extends BlockEntityMattery {
@Nonnull
@Override
public BigDecimal extractEnergyInner(BigDecimal howMuch, boolean simulate) {
public Fraction extractEnergyInner(Fraction howMuch, boolean simulate) {
return distributeEnergy(false, howMuch, simulate);
}
@Nonnull
@Override
public BigDecimal receiveEnergyOuter(BigDecimal howMuch, boolean simulate) {
public Fraction receiveEnergyOuter(Fraction howMuch, boolean simulate) {
if (mode == BankMode.EXTRACT)
return BigDecimal.ZERO;
return Fraction.ZERO;
return receiveEnergyInner(howMuch, simulate);
}
@Nonnull
@Override
public BigDecimal receiveEnergyInner(BigDecimal howMuch, boolean simulate) {
public Fraction receiveEnergyInner(Fraction howMuch, boolean simulate) {
return distributeEnergy(true, howMuch, simulate);
}
@Nonnull
@Override
public BigDecimal getBatteryLevel() {
BigDecimal result = BigDecimal.ZERO;
public Fraction getBatteryLevel() {
Fraction result = Fraction.ZERO;
for (int i = 0; i < tile.battery_container.getContainerSize(); i++) {
ItemStack stack = tile.battery_container.getItem(i);
@ -197,12 +198,12 @@ public class BlockEntityBatteryBank extends BlockEntityMattery {
Optional<IMatteryEnergyStorage> cap = stack.getCapability(MatteryCapability.ENERGY).resolve();
if (cap.isPresent()) {
result = result.add(cap.get().getBatteryLevel(), MatteryCapability.ROUND_RULES);
result = result.plus(cap.get().getBatteryLevel());
} else {
Optional<IEnergyStorage> cap2 = stack.getCapability(CapabilityEnergy.ENERGY).resolve();
if (cap2.isPresent()) {
result = result.add(new BigDecimal(cap2.get().getEnergyStored()), MatteryCapability.ROUND_RULES);
result = result.plus(cap2.get().getEnergyStored());
}
}
}
@ -213,8 +214,8 @@ public class BlockEntityBatteryBank extends BlockEntityMattery {
@Nonnull
@Override
public BigDecimal getMaxBatteryLevel() {
BigDecimal result = BigDecimal.ZERO;
public Fraction getMaxBatteryLevel() {
Fraction result = Fraction.ZERO;
for (int i = 0; i < tile.battery_container.getContainerSize(); i++) {
ItemStack stack = tile.battery_container.getItem(i);
@ -223,12 +224,12 @@ public class BlockEntityBatteryBank extends BlockEntityMattery {
Optional<IMatteryEnergyStorage> cap = stack.getCapability(MatteryCapability.ENERGY).resolve();
if (cap.isPresent()) {
result = result.add(cap.get().getMaxBatteryLevel(), MatteryCapability.ROUND_RULES);
result = result.plus(cap.get().getMaxBatteryLevel());
} else {
Optional<IEnergyStorage> cap2 = stack.getCapability(CapabilityEnergy.ENERGY).resolve();
if (cap2.isPresent()) {
result = result.add(new BigDecimal(cap2.get().getMaxEnergyStored()), MatteryCapability.ROUND_RULES);
result = result.plus(cap2.get().getMaxEnergyStored());
}
}
}
@ -354,7 +355,7 @@ public class BlockEntityBatteryBank extends BlockEntityMattery {
if (cap.canReceive()) {
BatteryBankDistribution distribution = tile.energy.getDistribution(false);
BigDecimal diff = cap.receiveEnergyOuter(distribution.max_throughput, true);
Fraction diff = cap.receiveEnergyOuter(distribution.max_throughput, true);
diff = tile.energy.extractEnergyOuter(diff, false);
cap.receiveEnergyOuter(diff, false);
}
@ -363,7 +364,7 @@ public class BlockEntityBatteryBank extends BlockEntityMattery {
if (cap.canReceive()) {
BatteryBankDistribution distribution = tile.energy.getDistribution(false);
BigDecimal diff = MatteryCapability.floodFE(cap, distribution.max_throughput, true);
Fraction diff = MatteryCapability.floodFE(cap, distribution.max_throughput, true);
diff = tile.energy.extractEnergyOuter(diff, false);
MatteryCapability.floodFE(cap, diff, false);
}

View File

@ -33,6 +33,7 @@ import net.minecraftforge.eventbus.api.SubscribeEvent;
import ru.dbotthepony.mc.otm.OverdriveThatMatters;
import ru.dbotthepony.mc.otm.Registry;
import ru.dbotthepony.mc.otm.capability.MatteryCapability;
import ru.dbotthepony.mc.otm.core.Fraction;
import ru.dbotthepony.mc.otm.matter.MatterRegistry;
import javax.annotation.Nullable;
@ -49,8 +50,8 @@ public class BlockEntityBlackHole extends BlockEntity {
setMass(mass);
}
public static final BigDecimal NORMAL_MASS = new BigDecimal(1_000);
private BigDecimal mass = NORMAL_MASS;
public static final Fraction NORMAL_MASS = new Fraction(1_000);
private Fraction mass = NORMAL_MASS;
private double gravitation_strength = 1;
private boolean suppress_updates = true;
public boolean spin_direction = false;
@ -284,19 +285,19 @@ public class BlockEntityBlackHole extends BlockEntity {
}
}
public void addMass(BigDecimal mass) {
setMass(this.mass.add(mass));
public void addMass(Fraction mass) {
setMass(this.mass.plus(mass));
}
public void setMass(BigDecimal mass) {
if (mass.compareTo(BigDecimal.ZERO) <= 0) {
public void setMass(Fraction mass) {
if (mass.compareTo(Fraction.ZERO) <= 0) {
collapse();
return;
}
this.mass = mass;
setChanged();
gravitation_strength = mass.divide(NORMAL_MASS, MatteryCapability.ROUND_RULES).doubleValue();
gravitation_strength = mass.div(NORMAL_MASS).toDouble();
if (gravitation_strength > 1) {
gravitation_strength = Math.min(20, Math.sqrt(gravitation_strength));
@ -327,8 +328,8 @@ public class BlockEntityBlackHole extends BlockEntity {
}
public void readBlackHoleData(CompoundTag tag) {
if (tag.get("mass") instanceof StringTag str)
setMass(new BigDecimal(str.getAsString()));
if (tag.contains("mass"))
setMass(Fraction.deserializeNBT(tag.get("mass")));
spin_direction = tag.getBoolean("spin_direction");
}
@ -426,7 +427,7 @@ public class BlockEntityBlackHole extends BlockEntity {
}
}
public static final BigDecimal HAWKING_MASS_LOSE_STEP = new BigDecimal("-0.1");
public static final Fraction HAWKING_MASS_LOSE_STEP = new Fraction("-0.1");
public static <T extends BlockEntity> void ticker(Level level, BlockPos blockPos, BlockState blockState, T t) {
if (t instanceof BlockEntityBlackHole tile) {
@ -457,7 +458,7 @@ public class BlockEntityBlackHole extends BlockEntity {
} else {
var mass = MatterRegistry.getMatterValue(item.getItem());
if (mass.compareTo(BigDecimal.ZERO) > 0)
if (mass.compareTo(Fraction.ZERO) > 0)
tile.addMass(mass);
}
}

View File

@ -20,6 +20,7 @@ import ru.dbotthepony.mc.otm.capability.AbstractStorageGridCell;
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.menu.DriveRackMenu;
import ru.dbotthepony.mc.otm.storage.ItemStackWrapper;
import ru.dbotthepony.mc.otm.storage.VirtualComponent;
@ -34,7 +35,7 @@ import java.math.BigDecimal;
public class BlockEntityDriveRack extends BlockEntityMatteryPowered {
public BlockEntityDriveRack(BlockPos p_155229_, BlockState p_155230_) {
super(Registry.BlockEntities.DRIVE_RACK, p_155229_, p_155230_);
energy = new MatteryMachineEnergyStorage(this, MatteryMachineEnergyStorage.MachineType.WORKER, new BigDecimal(80_000));
energy = new MatteryMachineEnergyStorage(this, MatteryMachineEnergyStorage.MachineType.WORKER, new Fraction(80_000));
}
public final MatteryContainer drives = new MatteryContainer(this::setChanged, 4) {

View File

@ -21,6 +21,7 @@ import ru.dbotthepony.mc.otm.block.entity.worker.WorkerState;
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.menu.DriveViewerMenu;
import javax.annotation.Nullable;
@ -30,7 +31,7 @@ import java.math.BigDecimal;
@MethodsReturnNonnullByDefault
@ParametersAreNonnullByDefault
public class BlockEntityDriveViewer extends BlockEntityMatteryPowered {
public static final BigDecimal MTE_PER_OPERATION = new BigDecimal("3.125");
public static final Fraction MTE_PER_OPERATION = new Fraction("3.125");
public boolean canIOItems() {
return energy.getBatteryLevel().compareTo(MTE_PER_OPERATION) >= 0;
@ -65,20 +66,20 @@ public class BlockEntityDriveViewer extends BlockEntityMatteryPowered {
if (!canIOItems())
return 0;
var extracted = energy.extractEnergyInner(MTE_PER_OPERATION.multiply(new BigDecimal(desired)), true);
var modulo = extracted.divideToIntegralValue(MTE_PER_OPERATION);
var extracted = energy.extractEnergyInner(MTE_PER_OPERATION.times(desired), true);
var modulo = extracted.rem(MTE_PER_OPERATION);
if (simulate)
return modulo.intValue();
return modulo.toInt();
energy.extractEnergyInner(modulo.multiply(MTE_PER_OPERATION), false);
energy.extractEnergyInner(modulo.times(MTE_PER_OPERATION), false);
return modulo.intValue();
return modulo.toInt();
}
public BlockEntityDriveViewer(BlockPos p_155229_, BlockState p_155230_) {
super(Registry.BlockEntities.DRIVE_VIEWER, p_155229_, p_155230_);
energy = new MatteryMachineEnergyStorage(this, MatteryMachineEnergyStorage.MachineType.WORKER, new BigDecimal(30_000));
energy = new MatteryMachineEnergyStorage(this, MatteryMachineEnergyStorage.MachineType.WORKER, new Fraction(30_000));
}
private static final TranslatableComponent NAME = new TranslatableComponent("block.overdrive_that_matters.drive_viewer");

View File

@ -24,6 +24,7 @@ import ru.dbotthepony.mc.otm.Registry;
import ru.dbotthepony.mc.otm.block.BlockEnergyCounter;
import ru.dbotthepony.mc.otm.capability.IMatteryEnergyStorage;
import ru.dbotthepony.mc.otm.capability.MatteryCapability;
import ru.dbotthepony.mc.otm.core.Fraction;
import ru.dbotthepony.mc.otm.menu.EnergyCounterMenu;
import javax.annotation.Nonnull;
@ -36,23 +37,23 @@ import java.util.Arrays;
@MethodsReturnNonnullByDefault
@ParametersAreNonnullByDefault
public class BlockEntityEnergyCounter extends BlockEntityMattery {
protected BigDecimal passed = BigDecimal.ZERO;
protected final BigDecimal[] history = new BigDecimal[10 * 20];
protected Fraction passed = Fraction.ZERO;
protected final Fraction[] history = new Fraction[10 * 20];
protected int history_tick = 0;
public static <T extends BlockEntity> void tick(Level level, BlockPos blockPos, BlockState blockState, T t) {
if (t instanceof BlockEntityEnergyCounter tile) {
tile.history_tick = (tile.history_tick + 1) % tile.history.length;
tile.history[tile.history_tick] = BigDecimal.ZERO;
tile.history[tile.history_tick] = Fraction.ZERO;
}
}
public BigDecimal[] getHistory(int ticks) {
public Fraction[] getHistory(int ticks) {
if (ticks < 1 || ticks >= history.length) {
throw new IllegalArgumentException("Invalid history length provided");
}
final var history = new BigDecimal[ticks];
final var history = new Fraction[ticks];
for (int i = 0; i < ticks; i++) {
int index = (history_tick - i) % this.history.length;
@ -66,16 +67,16 @@ public class BlockEntityEnergyCounter extends BlockEntityMattery {
return history;
}
public BigDecimal calcAverage(int ticks) {
return sumHistory(ticks).divide(new BigDecimal(ticks), MatteryCapability.ROUND_RULES);
public Fraction calcAverage(int ticks) {
return sumHistory(ticks).div(ticks);
}
public BigDecimal sumHistory(int ticks) {
public Fraction sumHistory(int ticks) {
if (ticks < 1 || ticks >= history.length) {
throw new IllegalArgumentException("Invalid history length provided");
}
var value = BigDecimal.ZERO;
var value = Fraction.ZERO;
for (int i = 0; i < ticks; i++) {
int index = (history_tick - i) % this.history.length;
@ -83,19 +84,19 @@ public class BlockEntityEnergyCounter extends BlockEntityMattery {
if (index < 0)
index += this.history.length;
value = value.add(history[index]);
value = value.plus(history[index]);
}
return value;
}
public BigDecimal getPassed() {
public Fraction getPassed() {
return passed;
}
public BlockEntityEnergyCounter(BlockPos p_155229_, BlockState p_155230_) {
super(Registry.BlockEntities.ENERGY_COUNTER, p_155229_, p_155230_);
Arrays.fill(history, BigDecimal.ZERO);
Arrays.fill(history, Fraction.ZERO);
}
@Override
@ -117,17 +118,29 @@ public class BlockEntityEnergyCounter extends BlockEntityMattery {
public void load(CompoundTag nbt) {
super.load(nbt);
if (nbt.get("passed") instanceof StringTag tag)
passed = new BigDecimal(tag.getAsString());
if (nbt.contains("passed"))
passed = Fraction.deserializeNBT(nbt.get("passed"));
if (nbt.get("history_tick") instanceof IntTag tag)
history_tick = tag.getAsInt();
// TODO: старый формат данных, удалить на релизе
var list = nbt.getList("history", Tag.TAG_STRING);
for (int i = 0; i < list.size(); i++) {
try {
history[i] = new BigDecimal(list.getString(i));
history[i] = Fraction.fromString(list.getString(i));
} catch(Throwable err) {
LOGGER.error(err);
}
}
// новый формат данных
list = nbt.getList("history", Tag.TAG_BYTE_ARRAY);
for (int i = 0; i < list.size(); i++) {
try {
history[i] = Fraction.fromString(list.getString(i));
} catch(Throwable err) {
LOGGER.error(err);
}
@ -176,21 +189,21 @@ public class BlockEntityEnergyCounter extends BlockEntityMattery {
}
@Override
public BigDecimal extractEnergyOuter(BigDecimal howMuch, boolean simulate) {
public Fraction extractEnergyOuter(Fraction howMuch, boolean simulate) {
return extractEnergyInner(howMuch, simulate);
}
@Override
public BigDecimal extractEnergyInner(BigDecimal howMuch, boolean simulate) {
public Fraction extractEnergyInner(Fraction howMuch, boolean simulate) {
if (is_input)
return BigDecimal.ZERO;
return Fraction.ZERO;
if (input_cap_mte.isPresent()) {
final var value = input_cap_mte.resolve().get().extractEnergyOuter(howMuch, simulate);
if (!simulate) {
passed = passed.add(value);
history[history_tick] = history[history_tick].add(value);
passed = passed.plus(value);
history[history_tick] = history[history_tick].plus(value);
setChangedLight();
}
@ -201,33 +214,33 @@ public class BlockEntityEnergyCounter extends BlockEntityMattery {
final var value = MatteryCapability.drainFE(input_cap_fe.resolve().get(), howMuch, simulate);
if (!simulate) {
passed = passed.add(value);
history[history_tick] = history[history_tick].add(value);
passed = passed.plus(value);
history[history_tick] = history[history_tick].plus(value);
setChangedLight();
}
return value;
}
return BigDecimal.ZERO;
return Fraction.ZERO;
}
@Override
public BigDecimal receiveEnergyOuter(BigDecimal howMuch, boolean simulate) {
public Fraction receiveEnergyOuter(Fraction howMuch, boolean simulate) {
return receiveEnergyInner(howMuch, simulate);
}
@Override
public BigDecimal receiveEnergyInner(BigDecimal howMuch, boolean simulate) {
public Fraction receiveEnergyInner(Fraction howMuch, boolean simulate) {
if (!is_input)
return BigDecimal.ZERO;
return Fraction.ZERO;
if (output_cap_mte.isPresent()) {
final var value = output_cap_mte.resolve().get().receiveEnergyOuter(howMuch, simulate);
if (!simulate) {
passed = passed.add(value);
history[history_tick] = history[history_tick].add(value);
passed = passed.plus(value);
history[history_tick] = history[history_tick].plus(value);
setChangedLight();
}
@ -238,26 +251,26 @@ public class BlockEntityEnergyCounter extends BlockEntityMattery {
final var value = MatteryCapability.floodFE(output_cap_fe.resolve().get(), howMuch, simulate);
if (!simulate) {
passed = passed.add(value);
history[history_tick] = history[history_tick].add(value);
passed = passed.plus(value);
history[history_tick] = history[history_tick].plus(value);
setChangedLight();
}
return value;
}
return BigDecimal.ZERO;
return Fraction.ZERO;
}
@Override
public BigDecimal getBatteryLevel() {
public Fraction getBatteryLevel() {
if (is_input) {
if (output_cap_mte.isPresent()) {
return output_cap_mte.resolve().get().getBatteryLevel();
}
if (output_cap_fe.isPresent()) {
return new BigDecimal(output_cap_fe.resolve().get().getEnergyStored());
return new Fraction(output_cap_fe.resolve().get().getEnergyStored());
}
} else {
if (input_cap_mte.isPresent()) {
@ -265,22 +278,22 @@ public class BlockEntityEnergyCounter extends BlockEntityMattery {
}
if (input_cap_fe.isPresent()) {
return new BigDecimal(input_cap_fe.resolve().get().getEnergyStored());
return new Fraction(input_cap_fe.resolve().get().getEnergyStored());
}
}
return BigDecimal.ZERO;
return Fraction.ZERO;
}
@Override
public BigDecimal getMaxBatteryLevel() {
public Fraction getMaxBatteryLevel() {
if (is_input) {
if (output_cap_mte.isPresent()) {
return output_cap_mte.resolve().get().getMaxBatteryLevel();
}
if (output_cap_fe.isPresent()) {
return new BigDecimal(output_cap_fe.resolve().get().getMaxEnergyStored());
return new Fraction(output_cap_fe.resolve().get().getMaxEnergyStored());
}
} else {
if (input_cap_mte.isPresent()) {
@ -288,11 +301,11 @@ public class BlockEntityEnergyCounter extends BlockEntityMattery {
}
if (input_cap_fe.isPresent()) {
return new BigDecimal(input_cap_fe.resolve().get().getMaxEnergyStored());
return new Fraction(input_cap_fe.resolve().get().getMaxEnergyStored());
}
}
return BigDecimal.ZERO;
return Fraction.ZERO;
}
@Override

View File

@ -17,6 +17,7 @@ import ru.dbotthepony.mc.otm.Registry;
import ru.dbotthepony.mc.otm.capability.AbstractStorageGridCell;
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.menu.ItemMonitorMenu;
import javax.annotation.Nonnull;
@ -29,7 +30,7 @@ import java.math.BigDecimal;
public class BlockEntityItemMonitor extends BlockEntityMatteryPowered {
public BlockEntityItemMonitor(BlockPos p_155229_, BlockState p_155230_) {
super(Registry.BlockEntities.ITEM_MONITOR, p_155229_, p_155230_);
energy = new MatteryMachineEnergyStorage(this, MatteryMachineEnergyStorage.MachineType.WORKER, new BigDecimal(80_000));
energy = new MatteryMachineEnergyStorage(this, MatteryMachineEnergyStorage.MachineType.WORKER, new Fraction(80_000));
}
public final AbstractStorageGridCell cell = new AbstractStorageGridCell();

View File

@ -25,6 +25,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.container.MatteryContainerHandler;
import ru.dbotthepony.mc.otm.core.Fraction;
import ru.dbotthepony.mc.otm.matter.MatterGrid;
import ru.dbotthepony.mc.otm.menu.MatterBottlerMenu;
@ -85,7 +86,7 @@ public class BlockEntityMatterBottler extends BlockEntityMatteryPowered implemen
return slot < 3;
});
public final MatterHandlerCapability matter = new MatterHandlerCapability(this::setChanged, IMatterHandler.MatterDirection.BIDIRECTIONAL, new BigDecimal(4)) {
public final MatterHandlerCapability matter = new MatterHandlerCapability(this::setChanged, IMatterHandler.MatterDirection.BIDIRECTIONAL, new Fraction(4)) {
@Nonnull
@Override
public MatterDirection getDirection() {
@ -93,12 +94,12 @@ public class BlockEntityMatterBottler extends BlockEntityMatteryPowered implemen
}
};
private static final BigDecimal MATTER_EXCHANGE_RATE = new BigDecimal("0.04");
private static final BigDecimal ENERGY_CONSUMPTION = new BigDecimal(20);
private static final Fraction MATTER_EXCHANGE_RATE = new Fraction("0.04");
private static final Fraction ENERGY_CONSUMPTION = new Fraction(20);
private LazyOptional<IMatterGridCell> cell_resolver = LazyOptional.of(() -> this);
protected BigDecimal initial_capacity;
protected Fraction initial_capacity;
protected ItemStack last_work_stack;
private MatterGrid grid;
@ -202,7 +203,7 @@ public class BlockEntityMatterBottler extends BlockEntityMatteryPowered implemen
matter.deserializeNBT(_matter);
}
private static final BigDecimal EXTRACTION_TICKS = new BigDecimal(200);
private static final Fraction EXTRACTION_TICKS = new Fraction(200);
public float getWorkProgress() {
if (last_work_stack == null) {
@ -216,18 +217,18 @@ public class BlockEntityMatterBottler extends BlockEntityMatteryPowered implemen
}
if (work_flow) {
if (cap.get().getMaxStoredMatter().subtract(initial_capacity).compareTo(BigDecimal.ZERO) <= 0) {
if (cap.get().getMaxStoredMatter().minus(initial_capacity).compareTo(Fraction.ZERO) <= 0) {
return 0;
}
return cap.get().getStoredMatter().subtract(initial_capacity).divide(cap.get().getMaxStoredMatter().subtract(initial_capacity), MatteryCapability.ROUND_RULES).floatValue();
return cap.get().getStoredMatter().minus(initial_capacity).div(cap.get().getMaxStoredMatter().minus(initial_capacity)).toFloat();
}
if (initial_capacity.compareTo(BigDecimal.ZERO) <= 0) {
if (initial_capacity.compareTo(Fraction.ZERO) <= 0) {
return 0;
}
return BigDecimal.ONE.subtract(cap.get().getStoredMatter().divide(initial_capacity, MatteryCapability.ROUND_RULES)).floatValue();
return Fraction.ONE.minus(cap.get().getStoredMatter().div(initial_capacity)).toFloat();
}
public static <T extends BlockEntity> void tick(Level level, BlockPos blockPos, BlockState blockState, T t) {
@ -253,7 +254,7 @@ public class BlockEntityMatterBottler extends BlockEntityMatteryPowered implemen
if (!get.isEmpty()) {
var cap = get.getCapability(MatteryCapability.MATTER).resolve();
if (cap.isPresent() && cap.get().getDirection() != (tile.work_flow ? IMatterHandler.MatterDirection.EXTRACT : IMatterHandler.MatterDirection.RECEIVE) && (tile.work_flow ? cap.get().getMissingMatter().compareTo(BigDecimal.ZERO) > 0 : cap.get().getStoredMatter().compareTo(BigDecimal.ZERO) > 0)) {
if (cap.isPresent() && cap.get().getDirection() != (tile.work_flow ? IMatterHandler.MatterDirection.EXTRACT : IMatterHandler.MatterDirection.RECEIVE) && (tile.work_flow ? cap.get().getMissingMatter().compareTo(Fraction.ZERO) > 0 : cap.get().getStoredMatter().compareTo(Fraction.ZERO) > 0)) {
work_stack = get;
capability = cap.get();
work_slot = i;
@ -280,29 +281,29 @@ public class BlockEntityMatterBottler extends BlockEntityMatteryPowered implemen
if (tile.grid != null) {
var extracted = tile.grid.extractMatter(
tile.matter.getMissingMatter()
.min(MATTER_EXCHANGE_RATE.multiply(EXTRACTION_TICKS))
.min(capability.getMissingMatter().subtract(tile.matter.getStoredMatter()))
.min(MATTER_EXCHANGE_RATE.times(EXTRACTION_TICKS))
.min(capability.getMissingMatter().minus(tile.matter.getStoredMatter()))
, true);
if (extracted.compareTo(BigDecimal.ZERO) > 0) {
if (extracted.compareTo(Fraction.ZERO) > 0) {
var received = tile.matter.receiveMatterOuter(extracted, false);
tile.grid.extractMatter(received, false);
}
}
}
if (tile.matter.getStoredMatter().compareTo(BigDecimal.ZERO) > 0) {
if (tile.matter.getStoredMatter().compareTo(Fraction.ZERO) > 0) {
var energy = tile.energy.extractEnergyInner(ENERGY_CONSUMPTION, true);
if (energy.compareTo(BigDecimal.ZERO) > 0) {
var matter = capability.receiveMatterOuter(MATTER_EXCHANGE_RATE.min(tile.matter.getStoredMatter()).multiply(energy.divide(ENERGY_CONSUMPTION, MatteryCapability.ROUND_RULES)), true);
if (energy.compareTo(Fraction.ZERO) > 0) {
var matter = capability.receiveMatterOuter(MATTER_EXCHANGE_RATE.min(tile.matter.getStoredMatter()).times(energy.div(ENERGY_CONSUMPTION)), true);
if (matter.compareTo(BigDecimal.ZERO) > 0) {
tile.energy.extractEnergyInner(ENERGY_CONSUMPTION.multiply(matter.divide(MATTER_EXCHANGE_RATE, MatteryCapability.ROUND_RULES)), false);
if (matter.compareTo(Fraction.ZERO) > 0) {
tile.energy.extractEnergyInner(ENERGY_CONSUMPTION.times(matter.div(MATTER_EXCHANGE_RATE)), false);
capability.receiveMatterOuter(matter, false);
tile.matter.extractMatterInner(matter, false);
if (capability.getMissingMatter().compareTo(BigDecimal.ZERO) == 0) {
if (capability.getMissingMatter().compareTo(Fraction.ZERO) == 0) {
for (int i = 3; i < 6; i++) {
if (tile.work_slots.getItem(i).isEmpty()) {
tile.work_slots.setItem(work_slot, ItemStack.EMPTY);
@ -327,15 +328,15 @@ public class BlockEntityMatterBottler extends BlockEntityMatteryPowered implemen
var energy = tile.energy.extractEnergyInner(ENERGY_CONSUMPTION, true);
if (energy.compareTo(BigDecimal.ZERO) > 0) {
var matter = capability.extractMatterOuter(MATTER_EXCHANGE_RATE.min(tile.matter.getMissingMatter()).multiply(energy.divide(ENERGY_CONSUMPTION, MatteryCapability.ROUND_RULES)), true);
if (energy.compareTo(Fraction.ZERO) > 0) {
var matter = capability.extractMatterOuter(MATTER_EXCHANGE_RATE.min(tile.matter.getMissingMatter()).times(energy.div(ENERGY_CONSUMPTION)), true);
if (matter.compareTo(BigDecimal.ZERO) > 0) {
tile.energy.extractEnergyInner(ENERGY_CONSUMPTION.multiply(matter.divide(MATTER_EXCHANGE_RATE, MatteryCapability.ROUND_RULES)), false);
if (matter.compareTo(Fraction.ZERO) > 0) {
tile.energy.extractEnergyInner(ENERGY_CONSUMPTION.times(matter.div(MATTER_EXCHANGE_RATE)), false);
capability.extractMatterOuter(matter, false);
tile.matter.receiveMatterInner(matter, false);
if (capability.getStoredMatter().compareTo(BigDecimal.ZERO) == 0) {
if (capability.getStoredMatter().compareTo(Fraction.ZERO) == 0) {
for (int i = 2; i >= 0; i--) {
if (tile.work_slots.getItem(i).isEmpty()) {
tile.work_slots.setItem(work_slot, ItemStack.EMPTY);
@ -352,9 +353,9 @@ public class BlockEntityMatterBottler extends BlockEntityMatteryPowered implemen
}
}
if (tile.matter.getStoredMatter().compareTo(BigDecimal.ZERO) > 0 && tile.grid != null) {
BigDecimal diff = tile.matter.extractMatterInner(tile.matter.getStoredMatter(), true);
BigDecimal diff2 = tile.grid.softPushMatter(diff, true);
if (tile.matter.getStoredMatter().compareTo(Fraction.ZERO) > 0 && tile.grid != null) {
var diff = tile.matter.extractMatterInner(tile.matter.getStoredMatter(), true);
var diff2 = tile.grid.softPushMatter(diff, true);
tile.matter.extractMatterInner(diff2, false);
tile.grid.softPushMatter(diff2, false);

View File

@ -17,6 +17,7 @@ import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.util.LazyOptional;
import ru.dbotthepony.mc.otm.block.BlockBatteryBank;
import ru.dbotthepony.mc.otm.capability.matter.IMatterGridCell;
import ru.dbotthepony.mc.otm.core.Fraction;
import ru.dbotthepony.mc.otm.matter.MatterGrid;
import ru.dbotthepony.mc.otm.Registry;
import ru.dbotthepony.mc.otm.capability.matter.IMatterHandler;
@ -37,8 +38,8 @@ public class BlockEntityMatterCapacitorBank extends BlockEntityMattery implement
public final IMatterHandler matter = new IMatterHandler() {
@Nonnull
@Override
public BigDecimal getStoredMatter() {
BigDecimal summ = BigDecimal.ZERO;
public Fraction getStoredMatter() {
Fraction summ = Fraction.ZERO;
for (int i = 0; i < matter_container.getContainerSize(); i++) {
ItemStack stack = matter_container.getItem(i);
@ -47,7 +48,7 @@ public class BlockEntityMatterCapacitorBank extends BlockEntityMattery implement
Optional<IMatterHandler> handler = stack.getCapability(MatteryCapability.MATTER).resolve();
if (handler.isPresent()) {
summ = summ.add(handler.get().getStoredMatter());
summ = summ.plus(handler.get().getStoredMatter());
}
}
}
@ -57,8 +58,8 @@ public class BlockEntityMatterCapacitorBank extends BlockEntityMattery implement
@Nonnull
@Override
public BigDecimal getMaxStoredMatter() {
BigDecimal summ = BigDecimal.ZERO;
public Fraction getMaxStoredMatter() {
Fraction summ = Fraction.ZERO;
for (int i = 0; i < matter_container.getContainerSize(); i++) {
ItemStack stack = matter_container.getItem(i);
@ -67,7 +68,7 @@ public class BlockEntityMatterCapacitorBank extends BlockEntityMattery implement
Optional<IMatterHandler> handler = stack.getCapability(MatteryCapability.MATTER).resolve();
if (handler.isPresent()) {
summ = summ.add(handler.get().getMaxStoredMatter());
summ = summ.plus(handler.get().getMaxStoredMatter());
}
}
}
@ -77,14 +78,14 @@ public class BlockEntityMatterCapacitorBank extends BlockEntityMattery implement
@Nonnull
@Override
public BigDecimal receiveMatterOuter(BigDecimal howMuch, boolean simulate) {
public Fraction receiveMatterOuter(Fraction howMuch, boolean simulate) {
return receiveMatterInner(howMuch, simulate);
}
@Nonnull
@Override
public BigDecimal receiveMatterInner(BigDecimal howMuch, boolean simulate) {
BigDecimal summ = BigDecimal.ZERO;
public Fraction receiveMatterInner(Fraction howMuch, boolean simulate) {
Fraction summ = Fraction.ZERO;
for (int i = 0; i < matter_container.getContainerSize(); i++) {
ItemStack stack = matter_container.getItem(i);
@ -93,11 +94,11 @@ public class BlockEntityMatterCapacitorBank extends BlockEntityMattery implement
Optional<IMatterHandler> handler = stack.getCapability(MatteryCapability.MATTER).resolve();
if (handler.isPresent()) {
BigDecimal diff = handler.get().receiveMatterOuter(howMuch, simulate);
summ = summ.add(diff);
howMuch = howMuch.subtract(diff);
var diff = handler.get().receiveMatterOuter(howMuch, simulate);
summ = summ.plus(diff);
howMuch = howMuch.minus(diff);
if (howMuch.compareTo(BigDecimal.ZERO) == 0) {
if (howMuch.compareTo(Fraction.ZERO) == 0) {
break;
}
}
@ -109,14 +110,14 @@ public class BlockEntityMatterCapacitorBank extends BlockEntityMattery implement
@Nonnull
@Override
public BigDecimal extractMatterOuter(BigDecimal howMuch, boolean simulate) {
public Fraction extractMatterOuter(Fraction howMuch, boolean simulate) {
return extractMatterInner(howMuch, simulate);
}
@Nonnull
@Override
public BigDecimal extractMatterInner(BigDecimal howMuch, boolean simulate) {
BigDecimal summ = BigDecimal.ZERO;
public Fraction extractMatterInner(Fraction howMuch, boolean simulate) {
Fraction summ = Fraction.ZERO;
for (int i = 0; i < matter_container.getContainerSize(); i++) {
ItemStack stack = matter_container.getItem(i);
@ -125,11 +126,11 @@ public class BlockEntityMatterCapacitorBank extends BlockEntityMattery implement
Optional<IMatterHandler> handler = stack.getCapability(MatteryCapability.MATTER).resolve();
if (handler.isPresent()) {
BigDecimal diff = handler.get().extractMatterOuter(howMuch, simulate);
summ = summ.add(diff);
howMuch = howMuch.subtract(diff);
var diff = handler.get().extractMatterOuter(howMuch, simulate);
summ = summ.plus(diff);
howMuch = howMuch.minus(diff);
if (howMuch.compareTo(BigDecimal.ZERO) == 0) {
if (howMuch.compareTo(Fraction.ZERO) == 0) {
break;
}
}

View File

@ -27,6 +27,7 @@ import ru.dbotthepony.mc.otm.capability.matter.IPatternStorage;
import ru.dbotthepony.mc.otm.capability.matter.MatterHandlerCapability;
import ru.dbotthepony.mc.otm.container.MatteryContainer;
import ru.dbotthepony.mc.otm.capability.matter.IMatterGridCell;
import ru.dbotthepony.mc.otm.core.Fraction;
import ru.dbotthepony.mc.otm.matter.MatterGrid;
import ru.dbotthepony.mc.otm.matter.MatterRegistry;
import ru.dbotthepony.mc.otm.menu.MatterDecomposerMenu;
@ -41,7 +42,7 @@ import java.math.BigDecimal;
public class BlockEntityMatterDecomposer extends BlockEntityMatteryWorker implements IMatterGridCell {
private static final TranslatableComponent MACHINE_NAME = new TranslatableComponent("block.overdrive_that_matters.matter_decomposer");
private boolean valid = true;
public final MatterHandlerCapability matter = new MatterHandlerCapability(this::setChanged, IMatterHandler.MatterDirection.EXTRACT, new BigDecimal("20"));
public final MatterHandlerCapability matter = new MatterHandlerCapability(this::setChanged, IMatterHandler.MatterDirection.EXTRACT, new Fraction("20"));
private LazyOptional<IMatterHandler> matter_resolver = LazyOptional.of(() -> matter);
// вход, выход
@ -54,7 +55,7 @@ public class BlockEntityMatterDecomposer extends BlockEntityMatteryWorker implem
public BlockEntityMatterDecomposer(BlockPos p_155229_, BlockState p_155230_) {
super(Registry.BlockEntities.MATTER_DECOMPOSER, p_155229_, p_155230_);
energy = new MatteryMachineEnergyStorage(this, MatteryMachineEnergyStorage.MachineType.WORKER, new BigDecimal(400_000), new BigDecimal(2000), new BigDecimal(2000));
energy = new MatteryMachineEnergyStorage(this, MatteryMachineEnergyStorage.MachineType.WORKER, new Fraction(400_000), new Fraction(2000), new Fraction(2000));
}
@Override
@ -130,7 +131,7 @@ public class BlockEntityMatterDecomposer extends BlockEntityMatteryWorker implem
@Nonnull
@Override
protected MachineJobStatus onJobFinish(MachineJob job) {
BigDecimal matter_value = MatterRegistry.getMatterValue(job.stack());
var matter_value = MatterRegistry.getMatterValue(job.stack());
matter.receiveMatterInner(matter_value, false);
return new MachineJobStatus();
}
@ -145,11 +146,11 @@ public class BlockEntityMatterDecomposer extends BlockEntityMatteryWorker implem
copy.setCount(1);
if (MatterRegistry.canDecompose(copy)) {
BigDecimal matter_value = MatterRegistry.getMatterValue(copy);
var matter_value = MatterRegistry.getMatterValue(copy);
if (!matter_value.equals(BigDecimal.ZERO) && matter.canReceiveAll(matter_value)) {
stack.shrink(1);
return new MachineJob(copy, matter_value.doubleValue() * 12_500d);
return new MachineJob(copy, matter_value.toDouble() * 12_500d);
}
}
}
@ -162,9 +163,9 @@ public class BlockEntityMatterDecomposer extends BlockEntityMatteryWorker implem
tile.batteryChargeLoop();
tile.workerLoop();
if (tile.matter.getStoredMatter().compareTo(BigDecimal.ZERO) > 0 && tile.grid != null) {
BigDecimal diff = tile.matter.extractMatterInner(tile.matter.getStoredMatter(), true);
BigDecimal diff2 = tile.grid.softPushMatter(diff, true);
if (tile.matter.getStoredMatter().compareTo(Fraction.ZERO) > 0 && tile.grid != null) {
var diff = tile.matter.extractMatterInner(tile.matter.getStoredMatter(), true);
var diff2 = tile.grid.softPushMatter(diff, true);
tile.matter.extractMatterInner(diff2, false);
tile.grid.softPushMatter(diff2, false);
@ -212,10 +213,10 @@ public class BlockEntityMatterDecomposer extends BlockEntityMatteryWorker implem
this.grid = grid;
}
private static final BigDecimal BASE_CONSUMPTION = new BigDecimal(240);
private static final Fraction BASE_CONSUMPTION = new Fraction(240);
@Override
protected BigDecimal getBaseConsumption() {
protected Fraction getBaseConsumption() {
return BASE_CONSUMPTION;
}
}

View File

@ -24,6 +24,7 @@ import ru.dbotthepony.mc.otm.capability.*;
import ru.dbotthepony.mc.otm.capability.matter.*;
import ru.dbotthepony.mc.otm.container.MatteryContainer;
import ru.dbotthepony.mc.otm.container.MatteryContainerHandler;
import ru.dbotthepony.mc.otm.core.Fraction;
import ru.dbotthepony.mc.otm.matter.MatterGrid;
import ru.dbotthepony.mc.otm.matter.MatterRegistry;
import ru.dbotthepony.mc.otm.menu.MatterReplicatorMenu;
@ -38,10 +39,10 @@ import java.math.BigDecimal;
public class BlockEntityMatterReplicator extends BlockEntityMatteryWorker implements IMatterGridCell {
public BlockEntityMatterReplicator(BlockPos p_155229_, BlockState p_155230_) {
super(Registry.BlockEntities.MATTER_REPLICATOR, p_155229_, p_155230_);
energy = new MatteryMachineEnergyStorage(this, MatteryMachineEnergyStorage.MachineType.WORKER, new BigDecimal(200_000), new BigDecimal(4000), new BigDecimal(4000));
energy = new MatteryMachineEnergyStorage(this, MatteryMachineEnergyStorage.MachineType.WORKER, new Fraction(200_000), new Fraction(4000), new Fraction(4000));
}
public final MatterHandlerCapability matter = new MatterHandlerCapability(this::setChanged, IMatterHandler.MatterDirection.RECEIVE, new BigDecimal(2));
public final MatterHandlerCapability matter = new MatterHandlerCapability(this::setChanged, IMatterHandler.MatterDirection.RECEIVE, new Fraction(2));
// обычные запросы
public final MatteryContainer regular_slots = new MatteryContainer(this::setChanged, 3);
@ -53,7 +54,7 @@ public class BlockEntityMatterReplicator extends BlockEntityMatteryWorker implem
private static final TranslatableComponent NAME = new TranslatableComponent("block.overdrive_that_matters.matter_replicator");
private static final BigDecimal BASE_CONSUMPTION = new BigDecimal(400);
private static final Fraction BASE_CONSUMPTION = new Fraction(400);
@Override
protected Component getDefaultDisplayName() {
@ -68,7 +69,7 @@ public class BlockEntityMatterReplicator extends BlockEntityMatteryWorker implem
@Nonnull
@Override
protected BigDecimal getBaseConsumption() {
protected Fraction getBaseConsumption() {
return BASE_CONSUMPTION;
}
@ -110,9 +111,9 @@ public class BlockEntityMatterReplicator extends BlockEntityMatteryWorker implem
}
private static final double TICKS_PER_MTU = 20_000d;
private static final BigDecimal TICKS_PER_MTU_BD = new BigDecimal(20_000);
private static final Fraction TICKS_PER_MTU_BD = new Fraction(20_000);
private static final double MTU_PER_TICK = 1d / 20_000d;
private static final BigDecimal MTU_PER_TICK_BD = BigDecimal.ONE.divide(TICKS_PER_MTU_BD, MatteryCapability.ROUND_RULES);
private static final Fraction MTU_PER_TICK_BD = Fraction.ONE.div(TICKS_PER_MTU_BD);
@Override
public void setLevel(Level p_155231_) {
@ -139,7 +140,7 @@ public class BlockEntityMatterReplicator extends BlockEntityMatteryWorker implem
if (!MatterRegistry.hasMatterValue(stack))
return null;
MachineJob job = new MachineJob(stack, MatterRegistry.getMatterValue(stack).doubleValue() * TICKS_PER_MTU);
MachineJob job = new MachineJob(stack, MatterRegistry.getMatterValue(stack).toDouble() * TICKS_PER_MTU);
job.data().put("task", allocation.task().serializeNBT());
@ -149,11 +150,11 @@ public class BlockEntityMatterReplicator extends BlockEntityMatteryWorker implem
return job;
}
private static final BigDecimal DRAIN_MULT = new BigDecimal(200);
private static final Fraction DRAIN_MULT = new Fraction(200);
@Override
protected MachineJobStatus onWorkTick(WorkTickContext context) {
BigDecimal drain_per_tick = MTU_PER_TICK_BD.multiply(context.work_speed(), MatteryCapability.ROUND_RULES);
var drain_per_tick = MTU_PER_TICK_BD.times(context.work_speed());
if (matter.extractMatterInner(drain_per_tick, true).compareTo(drain_per_tick) < 0) {
// в машине недостаточно материи
@ -162,8 +163,8 @@ public class BlockEntityMatterReplicator extends BlockEntityMatteryWorker implem
if (drain_per_tick.compareTo(matter.getMaxStoredMatter()) > 0) {
// в тик требуется больше материи, чем её может хранить репликатор
BigDecimal to_extract = drain_per_tick.subtract(matter.extractMatterInner(drain_per_tick, true));
BigDecimal drain = grid.extractMatter(to_extract, true);
var to_extract = drain_per_tick.minus(matter.extractMatterInner(drain_per_tick, true));
var drain = grid.extractMatter(to_extract, true);
if (drain.compareTo(to_extract) < 0) {
// недостаточно материи в сети
@ -178,15 +179,15 @@ public class BlockEntityMatterReplicator extends BlockEntityMatteryWorker implem
} else {
// в тик требуется меньше материи, чем её может хранить репликатор
// примем из сети недостающее количество бака материи, или 200 тиков репликации, что меньше
BigDecimal to_extract = matter.getMissingMatter().min(drain_per_tick.multiply(DRAIN_MULT));
BigDecimal drain = grid.extractMatter(to_extract, true);
var to_extract = matter.getMissingMatter().min(drain_per_tick.times(DRAIN_MULT));
var drain = grid.extractMatter(to_extract, true);
if (drain.compareTo(BigDecimal.ZERO) == 0) {
if (drain.compareTo(Fraction.ZERO) == 0) {
// в сети нет материи
return new MachineJobStatus(false, 200);
}
BigDecimal received = matter.receiveMatterOuter(drain, false);
var received = matter.receiveMatterOuter(drain, false);
grid.extractMatter(received, false);
// получили материю, проверяем возможность работы

View File

@ -22,6 +22,7 @@ import ru.dbotthepony.mc.otm.block.entity.worker.MachineJobStatus;
import ru.dbotthepony.mc.otm.capability.*;
import ru.dbotthepony.mc.otm.capability.matter.*;
import ru.dbotthepony.mc.otm.container.MatteryContainerHandler;
import ru.dbotthepony.mc.otm.core.Fraction;
import ru.dbotthepony.mc.otm.matter.MatterGrid;
import ru.dbotthepony.mc.otm.matter.MatterRegistry;
import ru.dbotthepony.mc.otm.Registry;
@ -49,7 +50,7 @@ public class BlockEntityMatterScanner extends BlockEntityMatteryWorker implement
public BlockEntityMatterScanner(BlockPos p_155229_, BlockState p_155230_) {
super(Registry.BlockEntities.MATTER_SCANNER, p_155229_, p_155230_);
energy = new MatteryMachineEnergyStorage(this, MatteryMachineEnergyStorage.MachineType.WORKER, new BigDecimal(40000), new BigDecimal(400), new BigDecimal(400));
energy = new MatteryMachineEnergyStorage(this, MatteryMachineEnergyStorage.MachineType.WORKER, new Fraction(40000), new Fraction(400), new Fraction(400));
}
private boolean valid = true;
@ -137,11 +138,11 @@ public class BlockEntityMatterScanner extends BlockEntityMatteryWorker implement
super.load(nbt);
}
private static final BigDecimal BASE_CONSUMPTION = new BigDecimal("40");
private static final Fraction BASE_CONSUMPTION = new Fraction("40");
@Override
@Nonnull
protected BigDecimal getBaseConsumption() {
protected Fraction getBaseConsumption() {
return BASE_CONSUMPTION;
}
@ -220,7 +221,7 @@ public class BlockEntityMatterScanner extends BlockEntityMatteryWorker implement
copy.setCount(1);
stack.shrink(1);
input_slot.setChanged();
return new MachineJob(copy, MatterRegistry.getMatterValue(copy).doubleValue() * 35_000d);
return new MachineJob(copy, MatterRegistry.getMatterValue(copy).toDouble() * 35_000d);
}
return null;

View File

@ -15,6 +15,7 @@ import ru.dbotthepony.mc.otm.capability.IMatteryEnergyStorage;
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 javax.annotation.Nonnull;
import javax.annotation.Nullable;
@ -35,17 +36,17 @@ abstract public class BlockEntityMatteryPowered extends BlockEntityMattery {
if (energy == null)
return;
if (energy.getMissingPower().compareTo(BigDecimal.ZERO) <= 0)
if (energy.getMissingPower().compareTo(Fraction.ZERO) <= 0)
return;
var demand = energy.getMissingPower();
if (demand.compareTo(BigDecimal.ZERO) == 0)
if (demand.compareTo(Fraction.ZERO) == 0)
return;
demand = demand.min(energy.receiveEnergyOuter(demand, true));
for (int i = 0; i < battery_container.getContainerSize() && demand.compareTo(BigDecimal.ZERO) > 0; i++) {
for (int i = 0; i < battery_container.getContainerSize() && demand.compareTo(Fraction.ZERO) > 0; i++) {
final var stack = battery_container.getItem(i);
if (!stack.isEmpty()) {
@ -54,13 +55,13 @@ abstract public class BlockEntityMatteryPowered extends BlockEntityMattery {
if (mattery_storage.isPresent()) {
final var drain = mattery_storage.get().extractEnergyOuter(demand, true);
if (drain.compareTo(BigDecimal.ZERO) != 0) {
if (drain.compareTo(Fraction.ZERO) != 0) {
final var receive = energy.receiveEnergyOuter(drain, true);
mattery_storage.get().extractEnergyOuter(receive, false);
energy.receiveEnergyOuter(receive, false);
demand = demand.subtract(receive, MatteryCapability.ROUND_RULES);
demand = demand.minus(receive);
}
} else {
final var storage = stack.getCapability(CapabilityEnergy.ENERGY).resolve();
@ -68,13 +69,13 @@ abstract public class BlockEntityMatteryPowered extends BlockEntityMattery {
if (storage.isPresent()) {
final var drain = MatteryCapability.drainFE(storage.get(), demand, true);
if (drain.compareTo(BigDecimal.ZERO) != 0) {
if (drain.compareTo(Fraction.ZERO) != 0) {
final var receive = energy.receiveEnergyOuter(drain, true);
MatteryCapability.drainFE(storage.get(), receive, false);
energy.receiveEnergyOuter(receive, false);
demand = demand.subtract(receive, MatteryCapability.ROUND_RULES);
demand = demand.minus(receive);
}
}
}

View File

@ -11,6 +11,7 @@ import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import ru.dbotthepony.mc.otm.block.entity.BlockEntityMatteryPowered;
import ru.dbotthepony.mc.otm.capability.MatteryCapability;
import ru.dbotthepony.mc.otm.core.Fraction;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@ -24,9 +25,9 @@ abstract public class BlockEntityMatteryWorker extends BlockEntityMatteryPowered
super(p_155228_, p_155229_, p_155230_);
}
protected abstract BigDecimal getBaseConsumption();
protected abstract Fraction getBaseConsumption();
protected BigDecimal consumptionPerWork() {
protected Fraction consumptionPerWork() {
return getBaseConsumption();
}
@ -150,7 +151,7 @@ abstract public class BlockEntityMatteryWorker extends BlockEntityMatteryPowered
return;
}
if (current_job.power_consumption_multiplier().compareTo(BigDecimal.ZERO) != 0 && energy.getBatteryLevel().compareTo(BigDecimal.ZERO) == 0) {
if (current_job.power_consumption_multiplier().compareTo(Fraction.ZERO) != 0 && energy.getBatteryLevel().compareTo(Fraction.ZERO) == 0) {
idle_ticks_anim++;
if (level != null && idle_ticks_anim > 20 && getBlockState().hasProperty(WorkerState.WORKER_STATE) && getBlockState().getValue(WorkerState.WORKER_STATE) != WorkerState.IDLE) {
@ -163,11 +164,10 @@ abstract public class BlockEntityMatteryWorker extends BlockEntityMatteryPowered
idle_ticks_anim = 0;
if (work_ticks < current_job.ticks_processing_time()) {
if (current_job.power_consumption_multiplier().compareTo(BigDecimal.ZERO) != 0) {
BigDecimal required_power = consumptionPerWork().multiply(current_job.power_consumption_multiplier());
BigDecimal extracted_power = energy.extractEnergyInner(required_power, true);
BigDecimal work_speed = extracted_power.divide(required_power, MatteryCapability.ROUND_RULES);
if (current_job.power_consumption_multiplier().compareTo(Fraction.ZERO) != 0) {
var required_power = consumptionPerWork().times(current_job.power_consumption_multiplier());
var extracted_power = energy.extractEnergyInner(required_power, true);
var work_speed = extracted_power.div(required_power);
MachineJobStatus status = onWorkTick(new WorkTickContext(current_job, required_power, extracted_power, work_speed));
@ -179,11 +179,11 @@ abstract public class BlockEntityMatteryWorker extends BlockEntityMatteryPowered
working_ticks_anim++;
error_ticks_anim = 0;
double new_work_ticks = work_speed.doubleValue() + work_ticks;
double new_work_ticks = work_speed.toDouble() + work_ticks;
if (new_work_ticks > current_job.ticks_processing_time()) {
work_ticks = current_job.ticks_processing_time();
energy.extractEnergyInner(extracted_power.multiply(new BigDecimal(1d - (new_work_ticks - current_job.ticks_processing_time()), MatteryCapability.ROUND_RULES)), false);
energy.extractEnergyInner(extracted_power.times(1d - (new_work_ticks - current_job.ticks_processing_time())), false);
} else {
work_ticks = new_work_ticks;
energy.extractEnergyInner(extracted_power, false);
@ -200,7 +200,7 @@ abstract public class BlockEntityMatteryWorker extends BlockEntityMatteryPowered
}
}
} else {
MachineJobStatus status = onWorkTick(new WorkTickContext(current_job, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ONE));
MachineJobStatus status = onWorkTick(new WorkTickContext(current_job, Fraction.ZERO, Fraction.ZERO, Fraction.ONE));
if (!status.valid()) {
throttle_ticks += status.throttle();

View File

@ -6,6 +6,7 @@ import net.minecraft.nbt.DoubleTag;
import net.minecraft.nbt.StringTag;
import net.minecraft.nbt.Tag;
import net.minecraft.world.item.ItemStack;
import ru.dbotthepony.mc.otm.core.Fraction;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
@ -13,14 +14,14 @@ import java.math.BigDecimal;
@MethodsReturnNonnullByDefault
@ParametersAreNonnullByDefault
public record MachineJob(ItemStack stack, double ticks_processing_time, BigDecimal power_consumption_multiplier,
public record MachineJob(ItemStack stack, double ticks_processing_time, Fraction power_consumption_multiplier,
CompoundTag data) {
public MachineJob(ItemStack stack, double ticks_processing_time, BigDecimal power_consumption_multiplier) {
public MachineJob(ItemStack stack, double ticks_processing_time, Fraction power_consumption_multiplier) {
this(stack, ticks_processing_time, power_consumption_multiplier, new CompoundTag());
}
public MachineJob(ItemStack stack, double ticks_processing_time) {
this(stack, ticks_processing_time, BigDecimal.ONE);
this(stack, ticks_processing_time, Fraction.ONE);
}
public CompoundTag serializeNBT() {
@ -40,11 +41,11 @@ public record MachineJob(ItemStack stack, double ticks_processing_time, BigDecim
return null;
if (nbt instanceof CompoundTag tag) {
if (tag.get("stack") instanceof CompoundTag stack_tag && tag.get("ticks_processing_time") instanceof DoubleTag ticks_processing_time && tag.get("power_consumption_multiplier") instanceof StringTag power_consumption_multiplier) {
if (tag.get("stack") instanceof CompoundTag stack_tag && tag.get("ticks_processing_time") instanceof DoubleTag ticks_processing_time && tag.contains("power_consumption_multiplier")) {
ItemStack stack = ItemStack.of(stack_tag);
if (!stack.isEmpty()) {
return new MachineJob(stack, ticks_processing_time.getAsDouble(), new BigDecimal(power_consumption_multiplier.getAsString()), tag.getCompound("data"));
return new MachineJob(stack, ticks_processing_time.getAsDouble(), Fraction.deserializeNBT(tag.get("power_consumption_multiplier")), tag.getCompound("data"));
}
}
}

View File

@ -1,13 +1,14 @@
package ru.dbotthepony.mc.otm.block.entity.worker;
import net.minecraft.MethodsReturnNonnullByDefault;
import ru.dbotthepony.mc.otm.core.Fraction;
import javax.annotation.ParametersAreNonnullByDefault;
import java.math.BigDecimal;
@MethodsReturnNonnullByDefault
@ParametersAreNonnullByDefault
public record WorkTickContext(MachineJob job, BigDecimal required_power, BigDecimal extracted_power,
BigDecimal work_speed) {
public record WorkTickContext(MachineJob job, Fraction required_power, Fraction extracted_power,
Fraction work_speed) {
}

View File

@ -2,8 +2,8 @@ package ru.dbotthepony.mc.otm.capability;
import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraftforge.energy.IEnergyStorage;
import ru.dbotthepony.mc.otm.core.Fraction;
import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
import java.math.BigDecimal;
@ -12,114 +12,112 @@ import java.math.BigDecimal;
@ParametersAreNonnullByDefault
public interface IMatteryEnergyStorage extends IEnergyStorage {
// such as cables. This is something that would work only with energy storage
BigDecimal extractEnergyOuter(BigDecimal howMuch, boolean simulate);
Fraction extractEnergyOuter(Fraction howMuch, boolean simulate);
// 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
BigDecimal extractEnergyInner(BigDecimal howMuch, boolean simulate);
Fraction extractEnergyInner(Fraction howMuch, boolean simulate);
// energy is received from outside, e.g. cables
BigDecimal receiveEnergyOuter(BigDecimal howMuch, boolean simulate);
Fraction receiveEnergyOuter(Fraction howMuch, boolean simulate);
// energy is received from inside, e.g. generator generates power
BigDecimal receiveEnergyInner(BigDecimal howMuch, boolean simulate);
Fraction receiveEnergyInner(Fraction howMuch, boolean simulate);
default BigDecimal extractEnergyOuter(long howMuch, boolean simulate) {
return extractEnergyOuter(new BigDecimal(howMuch, MatteryCapability.ROUND_RULES), simulate);
default Fraction extractEnergyOuter(long howMuch, boolean simulate) {
return extractEnergyOuter(new Fraction(howMuch), simulate);
}
default BigDecimal extractEnergyOuter(int howMuch, boolean simulate) {
return extractEnergyOuter(new BigDecimal(howMuch, MatteryCapability.ROUND_RULES), simulate);
default Fraction extractEnergyOuter(int howMuch, boolean simulate) {
return extractEnergyOuter(new Fraction(howMuch), simulate);
}
default BigDecimal receiveEnergyOuter(long howMuch, boolean simulate) {
return receiveEnergyOuter(new BigDecimal(howMuch, MatteryCapability.ROUND_RULES), simulate);
default Fraction receiveEnergyOuter(long howMuch, boolean simulate) {
return receiveEnergyOuter(new Fraction(howMuch), simulate);
}
default BigDecimal receiveEnergyOuter(int howMuch, boolean simulate) {
return receiveEnergyOuter(new BigDecimal(howMuch, MatteryCapability.ROUND_RULES), simulate);
default Fraction receiveEnergyOuter(int howMuch, boolean simulate) {
return receiveEnergyOuter(new Fraction(howMuch), simulate);
}
default BigDecimal extractEnergyInner(long howMuch, boolean simulate) {
return receiveEnergyOuter(new BigDecimal(howMuch, MatteryCapability.ROUND_RULES), simulate);
default Fraction extractEnergyInner(long howMuch, boolean simulate) {
return receiveEnergyOuter(new Fraction(howMuch), simulate);
}
default BigDecimal extractEnergyInner(int howMuch, boolean simulate) {
return receiveEnergyOuter(new BigDecimal(howMuch, MatteryCapability.ROUND_RULES), simulate);
default Fraction extractEnergyInner(int howMuch, boolean simulate) {
return receiveEnergyOuter(new Fraction(howMuch), simulate);
}
default BigDecimal receiveEnergyInner(long howMuch, boolean simulate) {
return receiveEnergyOuter(new BigDecimal(howMuch, MatteryCapability.ROUND_RULES), simulate);
default Fraction receiveEnergyInner(long howMuch, boolean simulate) {
return receiveEnergyOuter(new Fraction(howMuch), simulate);
}
default BigDecimal receiveEnergyInner(int howMuch, boolean simulate) {
return receiveEnergyOuter(new BigDecimal(howMuch, MatteryCapability.ROUND_RULES), simulate);
default Fraction receiveEnergyInner(int howMuch, boolean simulate) {
return receiveEnergyOuter(new Fraction(howMuch), simulate);
}
BigDecimal getBatteryLevel();
Fraction getBatteryLevel();
BigDecimal getMaxBatteryLevel();
Fraction getMaxBatteryLevel();
default BigDecimal getMissingPower() {
return getMaxBatteryLevel().subtract(getBatteryLevel(), MatteryCapability.ROUND_RULES);
default Fraction getMissingPower() {
return getMaxBatteryLevel().minus(getBatteryLevel());
}
@Override
default int receiveEnergy(int maxReceive, boolean simulate) {
BigDecimal toReceive = new BigDecimal(maxReceive, MatteryCapability.ROUND_RULES);
int received = receiveEnergyOuter(toReceive, true).intValue();
int received = receiveEnergyOuter(maxReceive, true).toInt();
if (received == 0) {
// Receiving only a fraction
return 0;
}
return receiveEnergyOuter(new BigDecimal(received, MatteryCapability.ROUND_RULES), simulate).intValue();
return receiveEnergyOuter(new Fraction(received), simulate).toInt();
}
@Override
default int extractEnergy(int maxReceive, boolean simulate) {
BigDecimal toReceive = new BigDecimal(maxReceive, MatteryCapability.ROUND_RULES);
int extracted = extractEnergyOuter(toReceive, true).intValue();
int extracted = extractEnergyOuter(maxReceive, true).toInt();
if (extracted == 0) {
// Extracting only a fraction
return 0;
}
return extractEnergyOuter(new BigDecimal(extracted, MatteryCapability.ROUND_RULES), simulate).intValue();
return extractEnergyOuter(new Fraction(extracted), simulate).toInt();
}
@Override
default int getEnergyStored() {
BigDecimal level = getBatteryLevel();
Fraction level = getBatteryLevel();
if (level.compareTo(MatteryCapability.INT_MAX_VALUE) == -1) {
return level.intValue();
if (level.compareTo(MatteryCapability.INT_MAX_VALUE) < 0) {
return level.toInt();
}
return Integer.MAX_VALUE;
};
}
@Override
default int getMaxEnergyStored() {
BigDecimal level = getMaxBatteryLevel();
Fraction level = getMaxBatteryLevel();
if (level.compareTo(MatteryCapability.INT_MAX_VALUE) == -1) {
return level.intValue();
if (level.compareTo(MatteryCapability.INT_MAX_VALUE) < 0) {
return level.toInt();
}
return Integer.MAX_VALUE;
};
}
@Override
default boolean canExtract() {
return extractEnergyOuter(BigDecimal.ONE, true).compareTo(BigDecimal.ZERO) > 0;
};
return extractEnergyOuter(Fraction.ONE, true).compareTo(Fraction.ZERO) > 0;
}
@Override
default boolean canReceive() {
return receiveEnergyOuter(BigDecimal.ONE, true).compareTo(BigDecimal.ZERO) > 0;
return receiveEnergyOuter(Fraction.ONE, true).compareTo(Fraction.ZERO) > 0;
};
}

View File

@ -8,6 +8,7 @@ import ru.dbotthepony.mc.otm.capability.matter.IMatterGridCell;
import ru.dbotthepony.mc.otm.capability.matter.IMatterHandler;
import ru.dbotthepony.mc.otm.capability.matter.IMatterTaskProvider;
import ru.dbotthepony.mc.otm.capability.matter.IPatternStorage;
import ru.dbotthepony.mc.otm.core.Fraction;
import java.math.BigDecimal;
import java.math.MathContext;
@ -37,23 +38,23 @@ public class MatteryCapability {
public static final MathContext ROUND_RULES = new MathContext(32, RoundingMode.HALF_DOWN);
public static final BigDecimal INT_MAX_VALUE = new BigDecimal(Integer.MAX_VALUE);
public static final BigDecimal INT_MIN_VALUE = new BigDecimal(Integer.MIN_VALUE);
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 BigDecimal LONG_MAX_VALUE = new BigDecimal(Long.MAX_VALUE);
public static final BigDecimal LONG_MIN_VALUE = new BigDecimal(Long.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 BigDecimal drainFE(IEnergyStorage capability, BigDecimal howMuch, boolean simulate) {
if (howMuch.compareTo(BigDecimal.ONE) < 0)
return BigDecimal.ZERO;
public static Fraction drainFE(IEnergyStorage capability, Fraction howMuch, boolean simulate) {
if (howMuch.compareTo(Fraction.ONE) < 0)
return Fraction.ZERO;
return new BigDecimal(capability.extractEnergy(howMuch.compareTo(INT_MAX_VALUE) > 0 ? Integer.MAX_VALUE : howMuch.intValue(), simulate));
return new Fraction(capability.extractEnergy(howMuch.compareTo(INT_MAX_VALUE) > 0 ? Integer.MAX_VALUE : howMuch.toInt(), simulate));
}
public static BigDecimal floodFE(IEnergyStorage capability, BigDecimal howMuch, boolean simulate) {
if (howMuch.compareTo(BigDecimal.ONE) < 0)
return BigDecimal.ZERO;
public static Fraction floodFE(IEnergyStorage capability, Fraction howMuch, boolean simulate) {
if (howMuch.compareTo(Fraction.ONE) < 0)
return Fraction.ZERO;
return new BigDecimal(capability.receiveEnergy(howMuch.compareTo(INT_MAX_VALUE) > 0 ? Integer.MAX_VALUE : howMuch.intValue(), simulate));
return new Fraction(capability.receiveEnergy(howMuch.compareTo(INT_MAX_VALUE) > 0 ? Integer.MAX_VALUE : howMuch.toInt(), simulate));
}
}

View File

@ -4,6 +4,7 @@ import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraftforge.common.util.INBTSerializable;
import ru.dbotthepony.mc.otm.core.Fraction;
import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
@ -18,18 +19,18 @@ public class MatteryMachineEnergyStorage implements IMatteryEnergyStorage, INBTS
CAPACITOR,
}
public static final BigDecimal DEFAULT_MAX_RECEIVE = new BigDecimal(200);
public static final BigDecimal DEFAULT_MAX_EXTRACT = new BigDecimal(200);
public static final BigDecimal DEFAULT_MAX_CAPACITY = new BigDecimal(60000);
public static final Fraction DEFAULT_MAX_RECEIVE = new Fraction(200);
public static final Fraction DEFAULT_MAX_EXTRACT = new Fraction(200);
public static final Fraction DEFAULT_MAX_CAPACITY = new Fraction(60000);
protected BigDecimal energy_stored = BigDecimal.ZERO;
protected BigDecimal energy_stored_max;
protected BigDecimal max_input;
protected BigDecimal max_output;
protected Fraction energy_stored = Fraction.ZERO;
protected Fraction energy_stored_max;
protected Fraction max_input;
protected Fraction max_output;
protected final MachineType machine_type;
protected final BlockEntity listener;
public MatteryMachineEnergyStorage(BlockEntity listener, MachineType type, BigDecimal capacity) {
public MatteryMachineEnergyStorage(BlockEntity listener, MachineType type, Fraction capacity) {
this(listener, type, capacity, DEFAULT_MAX_RECEIVE, DEFAULT_MAX_EXTRACT);
}
@ -37,7 +38,7 @@ public class MatteryMachineEnergyStorage implements IMatteryEnergyStorage, INBTS
this(listener, type, DEFAULT_MAX_CAPACITY);
}
public MatteryMachineEnergyStorage(BlockEntity listener, MachineType type, BigDecimal capacity, BigDecimal maxReceive, BigDecimal maxExtract) {
public MatteryMachineEnergyStorage(BlockEntity listener, MachineType type, Fraction capacity, Fraction maxReceive, Fraction maxExtract) {
this.listener = listener;
energy_stored_max = capacity;
max_input = maxReceive;
@ -47,9 +48,9 @@ public class MatteryMachineEnergyStorage implements IMatteryEnergyStorage, INBTS
@Nonnull
@Override
public BigDecimal extractEnergyOuter(BigDecimal howMuch, boolean simulate) {
public Fraction extractEnergyOuter(Fraction howMuch, boolean simulate) {
if (machine_type == MachineType.WORKER) {
return BigDecimal.ZERO;
return Fraction.ZERO;
}
return extractEnergyInner(howMuch, simulate);
@ -57,11 +58,11 @@ public class MatteryMachineEnergyStorage implements IMatteryEnergyStorage, INBTS
@Nonnull
@Override
public BigDecimal extractEnergyInner(BigDecimal howMuch, boolean simulate) {
BigDecimal new_energy = energy_stored.subtract(howMuch.min(max_output), MatteryCapability.ROUND_RULES).max(BigDecimal.ZERO);
BigDecimal diff = energy_stored.subtract(new_energy);
public Fraction extractEnergyInner(Fraction howMuch, boolean simulate) {
Fraction new_energy = energy_stored.minus(howMuch.min(max_output)).moreThanZero();
Fraction diff = energy_stored.minus(new_energy);
if (!simulate && !energy_stored.equals(new_energy)) {
if (!simulate && !energy_stored.equalsCompact(new_energy)) {
energy_stored = new_energy;
listener.setChanged();
}
@ -71,9 +72,9 @@ public class MatteryMachineEnergyStorage implements IMatteryEnergyStorage, INBTS
@Nonnull
@Override
public BigDecimal receiveEnergyOuter(BigDecimal howMuch, boolean simulate) {
public Fraction receiveEnergyOuter(Fraction howMuch, boolean simulate) {
if (machine_type == MachineType.GENERATOR) {
return BigDecimal.ZERO;
return Fraction.ZERO;
}
return receiveEnergyInner(howMuch, simulate);
@ -81,11 +82,11 @@ public class MatteryMachineEnergyStorage implements IMatteryEnergyStorage, INBTS
@Nonnull
@Override
public BigDecimal receiveEnergyInner(BigDecimal howMuch, boolean simulate) {
BigDecimal new_energy = energy_stored.add(howMuch.min(max_input), MatteryCapability.ROUND_RULES).min(energy_stored_max);
BigDecimal diff = new_energy.subtract(energy_stored);
public Fraction receiveEnergyInner(Fraction howMuch, boolean simulate) {
Fraction new_energy = energy_stored.plus(howMuch.min(max_input)).min(energy_stored_max);
Fraction diff = new_energy.minus(energy_stored);
if (!simulate && !energy_stored.equals(new_energy)) {
if (!simulate && !energy_stored.equalsCompact(new_energy)) {
energy_stored = new_energy;
listener.setChanged();
}
@ -95,13 +96,13 @@ public class MatteryMachineEnergyStorage implements IMatteryEnergyStorage, INBTS
@Nonnull
@Override
public BigDecimal getBatteryLevel() {
public Fraction getBatteryLevel() {
return energy_stored;
}
@Nonnull
@Override
public BigDecimal getMaxBatteryLevel() {
public Fraction getMaxBatteryLevel() {
return energy_stored_max;
}
@ -119,25 +120,25 @@ public class MatteryMachineEnergyStorage implements IMatteryEnergyStorage, INBTS
@Nonnull
public CompoundTag serializeNBT() {
CompoundTag tag = new CompoundTag();
tag.putString("energy_stored", energy_stored.toString());
tag.putString("energy_stored_max", energy_stored_max.toString());
tag.putString("max_input", max_input.toString());
tag.putString("max_output", max_output.toString());
tag.put("energy_stored", energy_stored.serializeNBT());
tag.put("energy_stored_max", energy_stored_max.serializeNBT());
tag.put("max_input", max_input.serializeNBT());
tag.put("max_output", max_output.serializeNBT());
return tag;
}
@Override
public void deserializeNBT(CompoundTag nbt) {
if (nbt.contains("energy_stored"))
energy_stored = new BigDecimal(nbt.getString("energy_stored"));
energy_stored = Fraction.deserializeNBT(nbt.get("energy_stored"));
if (nbt.contains("energy_stored_max"))
energy_stored_max = new BigDecimal(nbt.getString("energy_stored_max"));
energy_stored_max = Fraction.deserializeNBT(nbt.get("energy_stored_max"));
if (nbt.contains("max_input"))
max_input = new BigDecimal(nbt.getString("max_input"));
max_input = Fraction.deserializeNBT(nbt.get("max_input"));
if (nbt.contains("max_output"))
max_output = new BigDecimal(nbt.getString("max_output"));
max_output = Fraction.deserializeNBT(nbt.get("max_output"));
}
}

View File

@ -28,6 +28,7 @@ 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.capability.MatteryCapability;
import ru.dbotthepony.mc.otm.core.Fraction;
import ru.dbotthepony.mc.otm.network.MatteryNetworking;
import ru.dbotthepony.mc.otm.network.android.AndroidBatteryPacket;
import ru.dbotthepony.mc.otm.network.android.AndroidEnergyPacket;
@ -43,12 +44,12 @@ import java.util.*;
@ParametersAreNonnullByDefault
public class AndroidCapability implements ICapabilityProvider, IAndroidCapability, INBTSerializable<CompoundTag> {
protected final LivingEntity ent;
protected BigDecimal energy_stored = new BigDecimal(0);
protected BigDecimal energy_stored_max = new BigDecimal(60_000);
protected Fraction energy_stored = Fraction.ZERO;
protected Fraction energy_stored_max = new Fraction(60_000);
protected ItemStack battery = ItemStack.EMPTY;
private BigDecimal network_energy = new BigDecimal(-1);
private BigDecimal network_energy_max = new BigDecimal(-1);
private Fraction network_energy = new Fraction(-1);
private Fraction network_energy_max = new Fraction(-1);
private ItemStack network_battery = ItemStack.EMPTY;
protected final Map<AndroidFeatureType<?>, AndroidFeature> features = new HashMap<>();
@ -158,8 +159,8 @@ public class AndroidCapability implements ICapabilityProvider, IAndroidCapabilit
@Override
public void invalidateNetworkState() {
network_energy = new BigDecimal(-1);
network_energy_max = new BigDecimal(-1);
network_energy = Fraction.MINUS_ONE;
network_energy_max = Fraction.MINUS_ONE;
network_battery = ItemStack.EMPTY;
if (ent instanceof ServerPlayer ply) {
@ -171,12 +172,12 @@ public class AndroidCapability implements ICapabilityProvider, IAndroidCapabilit
}
@Override
public void setEnergy(BigDecimal value) {
public void setEnergy(Fraction value) {
energy_stored = value;
}
@Override
public void setMaxEnergy(BigDecimal value) {
public void setMaxEnergy(Fraction value) {
energy_stored_max = value;
}
@ -232,10 +233,10 @@ public class AndroidCapability implements ICapabilityProvider, IAndroidCapabilit
@Override
public void deserializeNBT(CompoundTag compound) {
if (compound.contains("energy_stored"))
energy_stored = new BigDecimal(compound.getString("energy_stored"));
energy_stored = Fraction.deserializeNBT(compound.get("energy_stored"));
if (compound.contains("energy_stored_max"))
energy_stored_max = new BigDecimal(compound.getString("energy_stored_max"));
energy_stored_max = Fraction.deserializeNBT(compound.get("energy_stored_max"));
if (compound.contains("battery"))
battery = ItemStack.of(compound.getCompound("battery"));
@ -371,52 +372,52 @@ public class AndroidCapability implements ICapabilityProvider, IAndroidCapabilit
ent.removeEffect(effect);
if (!battery.isEmpty()) {
BigDecimal demand = energy_stored_max.subtract(energy_stored, MatteryCapability.ROUND_RULES);
Fraction demand = energy_stored_max.minus(energy_stored);
if (demand.compareTo(BigDecimal.ZERO) > 0) {
if (demand.compareTo(Fraction.ZERO) > 0) {
Optional<IMatteryEnergyStorage> get_mattery = battery.getCapability(MatteryCapability.ENERGY).resolve();
if (get_mattery.isPresent()) {
demand = demand.subtract(get_mattery.get().extractEnergyInner(demand, false), MatteryCapability.ROUND_RULES);
demand = demand.minus(get_mattery.get().extractEnergyInner(demand, false));
}
if (demand.compareTo(BigDecimal.ONE) >= 0) {
if (demand.compareTo(Fraction.ONE) >= 0) {
Optional<IEnergyStorage> get_energy = battery.getCapability(CapabilityEnergy.ENERGY).resolve();
if (get_energy.isPresent()) {
demand = demand.subtract(MatteryCapability.drainFE(get_energy.get(), demand, false), MatteryCapability.ROUND_RULES);
demand = demand.minus(MatteryCapability.drainFE(get_energy.get(), demand, false));
}
}
energy_stored = energy_stored_max.subtract(demand);
energy_stored = energy_stored_max.minus(demand);
}
}
}
@Nonnull
@Override
public BigDecimal extractEnergyOuter(BigDecimal howMuch, boolean simulate) {
return BigDecimal.ZERO;
public Fraction extractEnergyOuter(Fraction howMuch, boolean simulate) {
return Fraction.ZERO;
}
@Nonnull
@Override
public BigDecimal extractEnergyInner(BigDecimal howMuch, boolean simulate) {
BigDecimal drained = BigDecimal.ZERO;
public Fraction extractEnergyInner(Fraction howMuch, boolean simulate) {
Fraction drained = Fraction.ZERO;
if (battery != ItemStack.EMPTY) {
Optional<IMatteryEnergyStorage> get_mattery = battery.getCapability(MatteryCapability.ENERGY).resolve();
if (get_mattery.isPresent()) {
BigDecimal changed = get_mattery.get().extractEnergyOuter(howMuch, simulate);
Fraction changed = get_mattery.get().extractEnergyOuter(howMuch, simulate);
if (changed.compareTo(BigDecimal.ZERO) > 0) {
drained = drained.add(changed, MatteryCapability.ROUND_RULES);
howMuch = howMuch.subtract(changed, MatteryCapability.ROUND_RULES);
if (changed.compareTo(Fraction.ZERO) > 0) {
drained = drained.plus(changed);
howMuch = howMuch.minus(changed);
if (howMuch.compareTo(BigDecimal.ZERO) <= 0) {
if (howMuch.compareTo(Fraction.ZERO) <= 0) {
if (!simulate && ent instanceof ServerPlayer ply) {
ply.awardStat(Registry.Names.POWER_CONSUMED, drained.intValue() * 10);
ply.awardStat(Registry.Names.POWER_CONSUMED, drained.toInt() * 10);
}
return drained;
@ -424,19 +425,19 @@ public class AndroidCapability implements ICapabilityProvider, IAndroidCapabilit
}
}
if (howMuch.compareTo(BigDecimal.ONE) >= 0) {
if (howMuch.compareTo(Fraction.ONE) >= 0) {
Optional<IEnergyStorage> get_energy = battery.getCapability(CapabilityEnergy.ENERGY).resolve();
if (get_energy.isPresent()) {
BigDecimal changed = MatteryCapability.drainFE(get_energy.get(), howMuch, simulate);
Fraction changed = MatteryCapability.drainFE(get_energy.get(), howMuch, simulate);
if (changed.compareTo(BigDecimal.ZERO) > 0) {
drained = drained.add(changed, MatteryCapability.ROUND_RULES);
howMuch = howMuch.subtract(changed, MatteryCapability.ROUND_RULES);
if (changed.compareTo(Fraction.ZERO) > 0) {
drained = drained.plus(changed);
howMuch = howMuch.minus(changed);
if (howMuch.compareTo(BigDecimal.ZERO) <= 0) {
if (howMuch.compareTo(Fraction.ZERO) <= 0) {
if (!simulate && ent instanceof ServerPlayer ply) {
ply.awardStat(Registry.Names.POWER_CONSUMED, drained.intValue() * 10);
ply.awardStat(Registry.Names.POWER_CONSUMED, drained.toInt() * 10);
}
return drained;
@ -446,14 +447,14 @@ public class AndroidCapability implements ICapabilityProvider, IAndroidCapabilit
}
}
BigDecimal new_energy = energy_stored.subtract(howMuch, MatteryCapability.ROUND_RULES).max(BigDecimal.ZERO);
drained = drained.add(energy_stored.subtract(new_energy, MatteryCapability.ROUND_RULES));
Fraction new_energy = energy_stored.minus(howMuch).max(Fraction.ZERO);
drained = drained.plus(energy_stored.minus(new_energy));
if (!simulate) {
energy_stored = new_energy;
if (ent instanceof ServerPlayer ply) {
ply.awardStat(Registry.Names.POWER_CONSUMED, drained.intValue() * 10);
ply.awardStat(Registry.Names.POWER_CONSUMED, drained.toInt() * 10);
}
}
@ -462,36 +463,36 @@ public class AndroidCapability implements ICapabilityProvider, IAndroidCapabilit
@Nonnull
@Override
public BigDecimal receiveEnergyOuter(BigDecimal howMuch, boolean simulate) {
BigDecimal received = BigDecimal.ZERO;
public Fraction receiveEnergyOuter(Fraction howMuch, boolean simulate) {
Fraction received = Fraction.ZERO;
if (battery != ItemStack.EMPTY) {
Optional<IMatteryEnergyStorage> get_mattery = battery.getCapability(MatteryCapability.ENERGY).resolve();
if (get_mattery.isPresent()) {
BigDecimal changed = get_mattery.get().receiveEnergyOuter(howMuch, simulate);
Fraction changed = get_mattery.get().receiveEnergyOuter(howMuch, simulate);
if (changed.compareTo(BigDecimal.ZERO) > 0) {
received = received.add(changed, MatteryCapability.ROUND_RULES);
howMuch = howMuch.subtract(changed, MatteryCapability.ROUND_RULES);
if (changed.compareTo(Fraction.ZERO) > 0) {
received = received.plus(changed);
howMuch = howMuch.minus(changed);
if (howMuch.compareTo(BigDecimal.ZERO) <= 0) {
if (howMuch.compareTo(Fraction.ZERO) <= 0) {
return received;
}
}
}
if (howMuch.compareTo(BigDecimal.ONE) >= 0) {
if (howMuch.compareTo(Fraction.ONE) >= 0) {
Optional<IEnergyStorage> get_energy = battery.getCapability(CapabilityEnergy.ENERGY).resolve();
if (get_energy.isPresent()) {
BigDecimal changed = MatteryCapability.floodFE(get_energy.get(), howMuch, simulate);
Fraction changed = MatteryCapability.floodFE(get_energy.get(), howMuch, simulate);
if (changed.compareTo(BigDecimal.ZERO) > 0) {
received = received.add(changed, MatteryCapability.ROUND_RULES);
howMuch = howMuch.subtract(changed, MatteryCapability.ROUND_RULES);
if (changed.compareTo(Fraction.ZERO) > 0) {
received = received.plus(changed);
howMuch = howMuch.minus(changed);
if (howMuch.compareTo(BigDecimal.ZERO) <= 0) {
if (howMuch.compareTo(Fraction.ZERO) <= 0) {
return received;
}
}
@ -499,8 +500,8 @@ public class AndroidCapability implements ICapabilityProvider, IAndroidCapabilit
}
}
BigDecimal new_energy = energy_stored.add(howMuch, MatteryCapability.ROUND_RULES).min(energy_stored_max);
received = received.add(new_energy.subtract(energy_stored, MatteryCapability.ROUND_RULES), MatteryCapability.ROUND_RULES);
Fraction new_energy = energy_stored.plus(howMuch).min(energy_stored_max);
received = received.plus(new_energy.minus(energy_stored));
if (!simulate) {
energy_stored = new_energy;
@ -511,7 +512,7 @@ public class AndroidCapability implements ICapabilityProvider, IAndroidCapabilit
@Nonnull
@Override
public BigDecimal receiveEnergyInner(BigDecimal howMuch, boolean simulate) {
public Fraction receiveEnergyInner(Fraction howMuch, boolean simulate) {
return receiveEnergyOuter(howMuch, simulate);
}
@ -533,18 +534,18 @@ public class AndroidCapability implements ICapabilityProvider, IAndroidCapabilit
@Override
@Nonnull
public BigDecimal getBatteryLevel() {
public Fraction getBatteryLevel() {
if (battery != ItemStack.EMPTY) {
Optional<IMatteryEnergyStorage> get_mattery = battery.getCapability(MatteryCapability.ENERGY).resolve();
if (get_mattery.isPresent()) {
return get_mattery.get().getBatteryLevel().add(energy_stored, MatteryCapability.ROUND_RULES);
return get_mattery.get().getBatteryLevel().plus(energy_stored);
}
Optional<IEnergyStorage> get_energy = battery.getCapability(CapabilityEnergy.ENERGY).resolve();
if (get_energy.isPresent()) {
return new BigDecimal(get_energy.get().getEnergyStored()).add(energy_stored, MatteryCapability.ROUND_RULES);
return energy_stored.plus(get_energy.get().getEnergyStored());
}
}
@ -553,18 +554,18 @@ public class AndroidCapability implements ICapabilityProvider, IAndroidCapabilit
@Override
@Nonnull
public BigDecimal getMaxBatteryLevel() {
public Fraction getMaxBatteryLevel() {
if (battery != ItemStack.EMPTY) {
Optional<IMatteryEnergyStorage> get_mattery = battery.getCapability(MatteryCapability.ENERGY).resolve();
if (get_mattery.isPresent()) {
return get_mattery.get().getMaxBatteryLevel().add(energy_stored_max, MatteryCapability.ROUND_RULES);
return get_mattery.get().getMaxBatteryLevel().plus(energy_stored_max);
}
Optional<IEnergyStorage> get_energy = battery.getCapability(CapabilityEnergy.ENERGY).resolve();
if (get_energy.isPresent()) {
return new BigDecimal(get_energy.get().getMaxEnergyStored()).add(energy_stored_max, MatteryCapability.ROUND_RULES);
return energy_stored_max.plus(get_energy.get().getMaxEnergyStored());
}
}

View File

@ -18,6 +18,7 @@ import ru.dbotthepony.mc.otm.Registry;
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.network.android.AndroidResearchPacket;
import ru.dbotthepony.mc.otm.network.android.AndroidStatusPacket;
@ -75,8 +76,8 @@ public class AndroidCapabilityPlayer extends AndroidCapability {
is_android = true;
will_become_android = false;
energy_stored = new BigDecimal(60_000);
energy_stored_max = new BigDecimal(60_000);
energy_stored = new Fraction(60_000);
energy_stored_max = new Fraction(60_000);
}
public void becomeAndroidAndKill() {
@ -96,8 +97,8 @@ public class AndroidCapabilityPlayer extends AndroidCapability {
is_android = false;
energy_stored = new BigDecimal(0);
energy_stored_max = new BigDecimal(60_000);
energy_stored = new Fraction(0);
energy_stored_max = new Fraction(60_000);
dropBattery();
}
@ -247,7 +248,7 @@ public class AndroidCapabilityPlayer extends AndroidCapability {
}
}
public static final BigDecimal ENERGY_FOR_HUNGER_POINT = new BigDecimal(1000);
public static final Fraction ENERGY_FOR_HUNGER_POINT = new Fraction(1000);
public int sleep_ticks = 0;
public static final int SLEEP_TICKS_LIMIT = 80;
@ -315,13 +316,13 @@ public class AndroidCapabilityPlayer extends AndroidCapability {
var food_level = (float) stats.getFoodLevel();
if (stats.getSaturationLevel() < food_level) {
BigDecimal extracted = this.extractEnergyInner(ENERGY_FOR_HUNGER_POINT.multiply(new BigDecimal(Float.toString(food_level - stats.getSaturationLevel()))), false);
stats.setSaturation(stats.getSaturationLevel() + extracted.divide(ENERGY_FOR_HUNGER_POINT, MatteryCapability.ROUND_RULES).floatValue());
Fraction extracted = this.extractEnergyInner(ENERGY_FOR_HUNGER_POINT.times(food_level - stats.getSaturationLevel()), false);
stats.setSaturation(stats.getSaturationLevel() + extracted.div(ENERGY_FOR_HUNGER_POINT).toFloat());
}
if (stats.getExhaustionLevel() > 0f) {
BigDecimal extracted = this.extractEnergyInner(ENERGY_FOR_HUNGER_POINT.multiply(new BigDecimal(Float.toString(stats.getExhaustionLevel() / 4f))), false);
stats.setExhaustion(stats.getExhaustionLevel() - extracted.divide(ENERGY_FOR_HUNGER_POINT, MatteryCapability.ROUND_RULES).floatValue() * 4f);
Fraction extracted = this.extractEnergyInner(ENERGY_FOR_HUNGER_POINT.times(stats.getExhaustionLevel() / 4f), false);
stats.setExhaustion(stats.getExhaustionLevel() - extracted.div(ENERGY_FOR_HUNGER_POINT).toFloat() * 4f);
}
}
}

View File

@ -9,6 +9,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 javax.annotation.Nonnull;
import javax.annotation.Nullable;
@ -45,6 +46,6 @@ public interface IAndroidCapability extends IMatteryEnergyStorage, INBTSerializa
void invalidateNetworkState(); // tell capability that player forgot everything, and everything needs to be re-networked
void setEnergy(BigDecimal value);
void setMaxEnergy(BigDecimal value);
void setEnergy(Fraction value);
void setMaxEnergy(Fraction value);
}

View File

@ -4,6 +4,7 @@ import net.minecraft.MethodsReturnNonnullByDefault;
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.storage.*;
import javax.annotation.Nonnull;
@ -22,16 +23,16 @@ abstract public class AbstractMatteryDrive<T extends IStorageStack> implements I
protected boolean dirty = false;
protected int different_stacks = 0;
protected BigDecimal stored = BigDecimal.ZERO;
protected Fraction stored = Fraction.ZERO;
protected int max_different_stacks;
protected BigDecimal capacity;
protected Fraction capacity;
public AbstractMatteryDrive(BigDecimal capacity, int max_different_stacks) {
public AbstractMatteryDrive(Fraction capacity, int max_different_stacks) {
this.capacity = capacity;
this.max_different_stacks = max_different_stacks;
}
public AbstractMatteryDrive(BigDecimal capacity) {
public AbstractMatteryDrive(Fraction capacity) {
this(capacity, 0xFFFF);
}
@ -51,12 +52,12 @@ abstract public class AbstractMatteryDrive<T extends IStorageStack> implements I
}
@Override
public BigDecimal getStoredCount() {
public Fraction getStoredCount() {
return stored;
}
@Override
public BigDecimal getCapacity() {
public Fraction getCapacity() {
return capacity;
}
@ -64,9 +65,9 @@ abstract public class AbstractMatteryDrive<T extends IStorageStack> implements I
@Override
@SuppressWarnings("unchecked")
public T insertStack(T stack, boolean simulate) {
BigDecimal max_insert = getCapacity().subtract(getStoredCount()).min(stack.getCount());
var max_insert = getCapacity().minus(getStoredCount()).min(stack.getCount());
if (max_insert.compareTo(BigDecimal.ZERO) <= 0)
if (max_insert.compareTo(Fraction.ZERO) <= 0)
return stack;
final var listing = items.computeIfAbsent(stack.partitionKey(), (key) -> new ArrayList<>());
@ -75,7 +76,7 @@ abstract public class AbstractMatteryDrive<T extends IStorageStack> implements I
if (state.stack().sameItem(stack)) {
if (!simulate) {
state.stack().grow(max_insert);
stored = stored.add(max_insert);
stored = stored.plus(max_insert);
for (var listener : listeners2) {
listener.changeObject(state.id(), state.stack().getCount());
@ -96,7 +97,7 @@ abstract public class AbstractMatteryDrive<T extends IStorageStack> implements I
if (!simulate) {
different_stacks++;
stored = stored.add(max_insert);
stored = stored.plus(max_insert);
final var copy = (T) stack.copy();
copy.setCount(max_insert);
@ -119,18 +120,18 @@ abstract public class AbstractMatteryDrive<T extends IStorageStack> implements I
@Nonnull
@Override
@SuppressWarnings("unchecked")
public T extractStack(UUID id, BigDecimal amount, boolean simulate) {
public T extractStack(UUID id, Fraction amount, boolean simulate) {
var get = items_by_id.get(id);
if (get == null)
return identity().empty();
if (amount.compareTo(BigDecimal.ZERO) <= 0)
if (amount.compareTo(Fraction.ZERO) <= 0)
amount = get.stack().getMaxStackSize().orElse(get.stack().getCount());
amount = amount.min(get.stack().getCount());
if (amount.compareTo(BigDecimal.ZERO) <= 0)
if (amount.compareTo(Fraction.ZERO) <= 0)
return identity().empty();
final var copy = (T) get.stack().copy();
@ -151,10 +152,10 @@ abstract public class AbstractMatteryDrive<T extends IStorageStack> implements I
}
}
stored = stored.subtract(amount);
stored = stored.minus(amount);
get.stack().shrink(amount);
if (get.stack().getCount().compareTo(BigDecimal.ZERO) != 0) {
if (get.stack().getCount().compareTo(Fraction.ZERO) != 0) {
for (var listener : listeners2) {
listener.changeObject(get.id(), get.stack().getCount());
}
@ -200,10 +201,12 @@ abstract public class AbstractMatteryDrive<T extends IStorageStack> implements I
public void deserializeNBT(CompoundTag nbt) {
items.clear();
items_by_id.clear();
stored = BigDecimal.ZERO;
stored = Fraction.ZERO;
different_stacks = 0;
capacity = new BigDecimal(nbt.getString("capacity"));
if (nbt.contains("capacity"))
capacity = Fraction.deserializeNBT(nbt.get("capacity"));
max_different_stacks = nbt.getInt("max_different_stacks");
for (var _entry : nbt.getList("items", Tag.TAG_COMPOUND)) {
@ -211,7 +214,7 @@ abstract public class AbstractMatteryDrive<T extends IStorageStack> implements I
final var stack = deserializeStack(entry);
if (stack != null) {
stored = stored.add(stack.getCount());
stored = stored.plus(stack.getCount());
different_stacks++;
final var id = entry.getLongArray("id");

View File

@ -4,6 +4,7 @@ import net.minecraft.MethodsReturnNonnullByDefault;
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.storage.*;
import javax.annotation.ParametersAreNonnullByDefault;
@ -18,8 +19,8 @@ public interface IMatteryDrive<T extends IStorageStack> extends IStorageComponen
void markDirty();
void markClean();
BigDecimal getStoredCount();
BigDecimal getCapacity();
Fraction getStoredCount();
Fraction getCapacity();
// not extending INBTSerializable to avoid serializing it as forgecaps
CompoundTag serializeNBT();

View File

@ -7,6 +7,7 @@ import net.minecraft.world.item.Item;
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.storage.IStorageTuple;
import ru.dbotthepony.mc.otm.storage.ItemStackWrapper;
import ru.dbotthepony.mc.otm.storage.StorageObjectRegistry;
@ -24,11 +25,11 @@ import java.util.Objects;
public class ItemMatteryDrive extends AbstractMatteryDrive<ItemStackWrapper> implements IItemMatteryDrive {
private static StorageObjectTuple<ItemStackWrapper> identity;
public ItemMatteryDrive(BigDecimal capacity, int max_different_stacks) {
public ItemMatteryDrive(Fraction capacity, int max_different_stacks) {
super(capacity, max_different_stacks);
}
public ItemMatteryDrive(BigDecimal capacity) {
public ItemMatteryDrive(Fraction capacity) {
super(capacity);
}

View File

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

View File

@ -5,6 +5,7 @@ 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 javax.annotation.Nonnull;
@ -16,17 +17,17 @@ import java.math.BigDecimal;
@ParametersAreNonnullByDefault
public class MatterHandlerCapability implements IMatterHandler, INBTSerializable<CompoundTag> {
protected final Runnable listener;
protected BigDecimal stored = BigDecimal.ZERO;
protected Fraction stored = Fraction.ZERO;
protected MatterDirection direction;
protected BigDecimal max_storage;
protected Fraction max_storage;
protected BigDecimal max_receive;
protected BigDecimal max_extract;
protected Fraction max_receive;
protected Fraction max_extract;
public MatterHandlerCapability(
@Nullable Runnable listener,
MatterDirection direction,
BigDecimal max_storage
Fraction max_storage
) {
this.listener = listener;
this.direction = direction;
@ -36,9 +37,9 @@ public class MatterHandlerCapability implements IMatterHandler, INBTSerializable
public MatterHandlerCapability(
@Nullable Runnable listener,
MatterDirection direction,
BigDecimal max_storage,
BigDecimal max_receive,
BigDecimal max_extract
Fraction max_storage,
Fraction max_receive,
Fraction max_extract
) {
this(listener, direction, max_storage);
@ -62,41 +63,41 @@ public class MatterHandlerCapability implements IMatterHandler, INBTSerializable
@Nonnull
@Override
public BigDecimal getStoredMatter() {
public Fraction getStoredMatter() {
return stored;
}
@Nonnull
@Override
public BigDecimal getMaxStoredMatter() {
public Fraction getMaxStoredMatter() {
return max_storage;
}
public boolean canReceiveAll(BigDecimal value) {
return max_storage.compareTo(value) >= 0 && stored.add(value).compareTo(max_storage) <= 0;
public boolean canReceiveAll(Fraction value) {
return max_storage.compareTo(value) >= 0 && stored.plus(value).compareTo(max_storage) <= 0;
}
@Nonnull
@Override
public BigDecimal receiveMatterOuter(BigDecimal howMuch, boolean simulate) {
public Fraction receiveMatterOuter(Fraction howMuch, boolean simulate) {
if (getDirection() == MatterDirection.EXTRACT)
return BigDecimal.ZERO;
return Fraction.ZERO;
return receiveMatterInner(howMuch, simulate);
}
@Nonnull
@Override
public BigDecimal receiveMatterInner(BigDecimal howMuch, boolean simulate) {
BigDecimal new_matter;
public Fraction receiveMatterInner(Fraction howMuch, boolean simulate) {
Fraction new_matter;
if (max_receive == null) {
new_matter = stored.add(howMuch, MatterRegistry.ROUND_RULES).min(max_storage);
new_matter = stored.plus(howMuch).min(max_storage);
} else {
new_matter = stored.add(howMuch.min(max_receive), MatterRegistry.ROUND_RULES).min(max_storage);
new_matter = stored.plus(howMuch.min(max_receive)).min(max_storage);
}
BigDecimal diff = new_matter.subtract(stored);
Fraction diff = new_matter.minus(stored);
if (!simulate && new_matter.compareTo(stored) != 0) {
stored = new_matter;
@ -111,25 +112,25 @@ public class MatterHandlerCapability implements IMatterHandler, INBTSerializable
@Nonnull
@Override
public BigDecimal extractMatterOuter(BigDecimal howMuch, boolean simulate) {
public Fraction extractMatterOuter(Fraction howMuch, boolean simulate) {
if (getDirection() == MatterDirection.RECEIVE)
return BigDecimal.ZERO;
return Fraction.ZERO;
return extractMatterInner(howMuch, simulate);
}
@Nonnull
@Override
public BigDecimal extractMatterInner(BigDecimal howMuch, boolean simulate) {
BigDecimal new_matter;
public Fraction extractMatterInner(Fraction howMuch, boolean simulate) {
Fraction new_matter;
if (max_receive == null) {
new_matter = stored.subtract(howMuch, MatterRegistry.ROUND_RULES).max(BigDecimal.ZERO);
new_matter = stored.minus(howMuch).moreThanZero();
} else {
new_matter = stored.subtract(howMuch.min(max_receive), MatterRegistry.ROUND_RULES).max(BigDecimal.ZERO);
new_matter = stored.minus(howMuch.min(max_receive)).moreThanZero();
}
BigDecimal diff = stored.subtract(new_matter);
Fraction diff = stored.minus(new_matter);
if (!simulate && new_matter.compareTo(stored) != 0) {
stored = new_matter;
@ -166,18 +167,18 @@ public class MatterHandlerCapability implements IMatterHandler, INBTSerializable
@Override
public void deserializeNBT(CompoundTag tag) {
if (tag.contains("stored"))
stored = new BigDecimal(tag.getString("stored"));
stored = Fraction.deserializeNBT(tag.get("stored"));
if (tag.contains("max_storage"))
max_storage = new BigDecimal(tag.getString("max_storage"));
max_storage = Fraction.deserializeNBT(tag.get("max_storage"));
if (tag.contains("max_receive"))
max_receive = new BigDecimal(tag.getString("max_receive"));
max_receive = Fraction.deserializeNBT(tag.get("max_receive"));
else
max_receive = null;
if (tag.contains("max_extract"))
max_extract = new BigDecimal(tag.getString("max_extract"));
max_extract = Fraction.deserializeNBT(tag.get("max_extract"));
else
max_extract = null;
}

View File

@ -25,6 +25,7 @@ import ru.dbotthepony.mc.otm.OverdriveThatMatters;
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 java.math.BigDecimal;
import java.util.Optional;
@ -162,10 +163,10 @@ public class AndroidGui {
float level;
if (android.getMaxBatteryLevel().compareTo(BigDecimal.ZERO) == 0) {
if (android.getMaxBatteryLevel().compareTo(Fraction.ZERO) == 0) {
level = 0f;
} else {
level = android.getBatteryLevel().divide(android.getMaxBatteryLevel(), MatteryCapability.ROUND_RULES).floatValue();
level = android.getBatteryLevel().div(android.getMaxBatteryLevel()).toFloat();
if (level >= 0.98f)
level = 1f;

View File

@ -27,7 +27,7 @@ public class EnergyCounterScreen extends MatteryScreen<EnergyCounterMenu> {
public void tick() {
super.tick();
setText(new TranslatableComponent("otm.item.power.passed", FormattingHelper.formatPower(menu.passed.getDecimal())));
setText(new TranslatableComponent("otm.item.power.passed", FormattingHelper.formatPower(menu.passed.getValue())));
}
};
@ -39,7 +39,7 @@ public class EnergyCounterScreen extends MatteryScreen<EnergyCounterMenu> {
public void tick() {
super.tick();
setText(new TranslatableComponent("otm.item.power.average", FormattingHelper.formatPower(menu.average.getDecimal())));
setText(new TranslatableComponent("otm.item.power.average", FormattingHelper.formatPower(menu.average.getValue())));
}
};
@ -51,7 +51,7 @@ public class EnergyCounterScreen extends MatteryScreen<EnergyCounterMenu> {
public void tick() {
super.tick();
setText(new TranslatableComponent("otm.item.power.last_20_ticks", FormattingHelper.formatPower(menu.last_20_ticks.getDecimal())));
setText(new TranslatableComponent("otm.item.power.last_20_ticks", FormattingHelper.formatPower(menu.last_20_ticks.getValue())));
}
};

View File

@ -7,59 +7,44 @@ import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.world.item.*;
import net.minecraft.world.level.Level;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.ICapabilityProvider;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.energy.CapabilityEnergy;
import net.minecraftforge.fml.loading.FMLEnvironment;
import ru.dbotthepony.mc.otm.OverdriveThatMatters;
import ru.dbotthepony.mc.otm.capability.IMatteryEnergyStorage;
import ru.dbotthepony.mc.otm.capability.MatteryCapability;
import ru.dbotthepony.mc.otm.core.Fraction;
import ru.dbotthepony.mc.otm.menu.FormattingHelper;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.math.BigDecimal;
import java.util.List;
import java.util.Objects;
public class ItemBattery extends Item {
public class BatteryMatteryCapability implements IMatteryEnergyStorage, ICapabilityProvider {
private final BigDecimal storage;
private final BigDecimal max_input;
private final BigDecimal max_output;
private final Fraction storage;
private final Fraction max_input;
private final Fraction max_output;
private final boolean is_creative;
private BigDecimal energy;
private String _energy;
private final ItemStack stack;
private BigDecimal energy() {
private Fraction energy() {
CompoundTag tag = stack.getOrCreateTag();
if (tag.contains("otm_energy")) {
String get_energy = tag.getString("otm_energy");
if (Objects.equals(_energy, get_energy)) {
return energy;
}
energy = new BigDecimal(tag.getString("otm_energy"));
_energy = get_energy;
return energy;
return Fraction.deserializeNBT(tag.get("otm_energy"));
}
return BigDecimal.ZERO;
return Fraction.ZERO;
}
private void energy(BigDecimal value) {
energy = value;
stack.getOrCreateTag().putString("otm_energy", value.toString());
private void energy(Fraction value) {
stack.getOrCreateTag().put("otm_energy", value.serializeNBT());
}
public BatteryMatteryCapability(ItemStack stack, BigDecimal storage, BigDecimal max_input, BigDecimal max_output) {
public BatteryMatteryCapability(ItemStack stack, Fraction storage, Fraction max_input, Fraction max_output) {
this.stack = stack;
is_creative = false;
this.storage = storage;
@ -77,18 +62,18 @@ public class ItemBattery extends Item {
@Nonnull
@Override
public BigDecimal extractEnergyOuter(BigDecimal howMuch, boolean simulate) {
public Fraction extractEnergyOuter(@Nonnull Fraction howMuch, boolean simulate) {
return extractEnergyInner(howMuch, simulate);
}
@Nonnull
@Override
public BigDecimal extractEnergyInner(BigDecimal howMuch, boolean simulate) {
public Fraction extractEnergyInner(@Nonnull Fraction howMuch, boolean simulate) {
if (is_creative)
return howMuch;
BigDecimal new_energy = energy().subtract(howMuch.min(max_output), MatteryCapability.ROUND_RULES).max(BigDecimal.ZERO);
BigDecimal diff = energy().subtract(new_energy);
Fraction new_energy = energy().minus(howMuch.min(max_output)).moreThanZero();
Fraction diff = energy().minus(new_energy);
if (!simulate) {
energy(new_energy);
@ -99,18 +84,18 @@ public class ItemBattery extends Item {
@Nonnull
@Override
public BigDecimal receiveEnergyOuter(BigDecimal howMuch, boolean simulate) {
public Fraction receiveEnergyOuter(@Nonnull Fraction howMuch, boolean simulate) {
return receiveEnergyInner(howMuch, simulate);
}
@Nonnull
@Override
public BigDecimal receiveEnergyInner(BigDecimal howMuch, boolean simulate) {
public Fraction receiveEnergyInner(@Nonnull Fraction howMuch, boolean simulate) {
if (is_creative)
return howMuch;
BigDecimal new_energy = energy().add(howMuch.min(max_input), MatteryCapability.ROUND_RULES).min(storage);
BigDecimal diff = new_energy.subtract(energy());
Fraction new_energy = energy().plus(howMuch.min(max_input)).min(storage);
Fraction diff = new_energy.minus(energy());
if (!simulate) {
energy(new_energy);
@ -119,8 +104,9 @@ public class ItemBattery extends Item {
return diff;
}
@Nonnull
@Override
public BigDecimal getMissingPower() {
public Fraction getMissingPower() {
if (is_creative)
return MatteryCapability.LONG_MAX_VALUE;
@ -129,7 +115,7 @@ public class ItemBattery extends Item {
@Nonnull
@Override
public BigDecimal getBatteryLevel() {
public Fraction getBatteryLevel() {
if (is_creative)
return MatteryCapability.LONG_MAX_VALUE;
@ -138,7 +124,7 @@ public class ItemBattery extends Item {
@Nonnull
@Override
public BigDecimal getMaxBatteryLevel() {
public Fraction getMaxBatteryLevel() {
if (is_creative)
return MatteryCapability.LONG_MAX_VALUE;
@ -169,14 +155,14 @@ public class ItemBattery extends Item {
private final boolean is_creative;
public final BigDecimal storage;
public final BigDecimal receive;
public final BigDecimal extract;
public final Fraction storage;
public final Fraction receive;
public final Fraction extract;
private final Component THROUGHPUT;
private static final Component INFINITE_STORAGE = new TranslatableComponent("otm.item.power.infinite.storage").withStyle(ChatFormatting.GRAY);
public ItemBattery(BigDecimal storage, BigDecimal receive, BigDecimal extract) {
public ItemBattery(Fraction storage, Fraction receive, Fraction extract) {
super(new Properties().stacksTo(1).tab(OverdriveThatMatters.CREATIVE_TAB));
is_creative = false;
this.storage = storage;

View File

@ -1,6 +1,7 @@
package ru.dbotthepony.mc.otm.item;
import net.minecraft.ChatFormatting;
import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.core.Direction;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
@ -13,14 +14,18 @@ import net.minecraftforge.common.util.LazyOptional;
import ru.dbotthepony.mc.otm.OverdriveThatMatters;
import ru.dbotthepony.mc.otm.capability.matter.IMatterHandler;
import ru.dbotthepony.mc.otm.capability.MatteryCapability;
import ru.dbotthepony.mc.otm.core.Fraction;
import ru.dbotthepony.mc.otm.menu.FormattingHelper;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import java.math.BigDecimal;
import java.util.List;
import java.util.Objects;
@ParametersAreNonnullByDefault
@MethodsReturnNonnullByDefault
public class ItemMatterCapacitor extends Item {
public static class ItemMatterCapacitorCapability implements ICapabilityProvider, IMatterHandler {
private final LazyOptional<IMatterHandler> resolver = LazyOptional.of(() -> this);
@ -33,40 +38,31 @@ public class ItemMatterCapacitor extends Item {
return LazyOptional.empty();
}
private final BigDecimal storage;
private final BigDecimal max_input;
private final BigDecimal max_output;
private final Fraction storage;
private final Fraction max_input;
private final Fraction max_output;
private final boolean is_creative;
private BigDecimal energy;
private Fraction energy;
private String _energy;
private final ItemStack stack;
private BigDecimal matter() {
private Fraction matter() {
CompoundTag tag = stack.getOrCreateTag();
if (tag.contains("otm_matter")) {
String get_energy = tag.getString("otm_matter");
if (Objects.equals(_energy, get_energy)) {
return energy;
}
energy = new BigDecimal(tag.getString("otm_matter"));
_energy = get_energy;
return energy;
return Fraction.deserializeNBT(tag.get("otm_matter"));
}
return BigDecimal.ZERO;
return Fraction.ZERO;
}
private void matter(BigDecimal value) {
energy = value;
stack.getOrCreateTag().putString("otm_matter", value.toString());
private void matter(Fraction value) {
stack.getOrCreateTag().put("otm_matter", value.serializeNBT());
}
public ItemMatterCapacitorCapability(ItemStack stack, BigDecimal storage, BigDecimal max_input, BigDecimal max_output) {
public ItemMatterCapacitorCapability(ItemStack stack, Fraction storage, Fraction max_input, Fraction max_output) {
this.stack = stack;
is_creative = false;
this.storage = storage;
@ -82,7 +78,7 @@ public class ItemMatterCapacitor extends Item {
max_output = MatteryCapability.LONG_MAX_VALUE;
}
public ItemMatterCapacitorCapability(ItemStack stack, BigDecimal storage) {
public ItemMatterCapacitorCapability(ItemStack stack, Fraction storage) {
this.stack = stack;
is_creative = false;
this.storage = storage;
@ -92,7 +88,7 @@ public class ItemMatterCapacitor extends Item {
@Nonnull
@Override
public BigDecimal getStoredMatter() {
public Fraction getStoredMatter() {
if (is_creative)
return MatteryCapability.LONG_MAX_VALUE;
@ -101,7 +97,7 @@ public class ItemMatterCapacitor extends Item {
@Nonnull
@Override
public BigDecimal getMaxStoredMatter() {
public Fraction getMaxStoredMatter() {
if (is_creative)
return MatteryCapability.LONG_MAX_VALUE;
@ -110,7 +106,7 @@ public class ItemMatterCapacitor extends Item {
@Nonnull
@Override
public BigDecimal getMissingMatter() {
public Fraction getMissingMatter() {
if (is_creative)
return MatteryCapability.LONG_MAX_VALUE;
@ -119,18 +115,18 @@ public class ItemMatterCapacitor extends Item {
@Nonnull
@Override
public BigDecimal receiveMatterOuter(BigDecimal howMuch, boolean simulate) {
public Fraction receiveMatterOuter(Fraction howMuch, boolean simulate) {
return receiveMatterInner(howMuch, simulate);
}
@Nonnull
@Override
public BigDecimal receiveMatterInner(BigDecimal howMuch, boolean simulate) {
public Fraction receiveMatterInner(Fraction howMuch, boolean simulate) {
if (is_creative)
return howMuch;
BigDecimal new_matter = matter().add(howMuch.min(max_input), MatteryCapability.ROUND_RULES).min(storage);
BigDecimal diff = new_matter.subtract(matter());
Fraction new_matter = matter().plus(howMuch.min(max_input)).min(storage);
Fraction diff = new_matter.minus(matter());
if (!simulate) {
matter(new_matter);
@ -141,19 +137,19 @@ public class ItemMatterCapacitor extends Item {
@Nonnull
@Override
public BigDecimal extractMatterOuter(BigDecimal howMuch, boolean simulate) {
public Fraction extractMatterOuter(Fraction howMuch, boolean simulate) {
return extractMatterInner(howMuch, simulate);
}
@Nonnull
@Override
public BigDecimal extractMatterInner(BigDecimal howMuch, boolean simulate) {
public Fraction extractMatterInner(Fraction howMuch, boolean simulate) {
if (is_creative)
return howMuch;
BigDecimal new_matter = matter().subtract(howMuch.min(max_output), MatteryCapability.ROUND_RULES).max(BigDecimal.ZERO);
BigDecimal diff = matter().subtract(new_matter);
Fraction new_matter = matter().minus(howMuch.min(max_output)).moreThanZero();
Fraction diff = matter().minus(new_matter);
if (!simulate) {
matter(new_matter);
@ -169,13 +165,13 @@ public class ItemMatterCapacitor extends Item {
}
}
public final BigDecimal storage;
public final Fraction storage;
private static final Component INFINITE_STORAGE = new TranslatableComponent("otm.item.matter.infinite").withStyle(ChatFormatting.GRAY);
private final boolean is_creative;
public ItemMatterCapacitor(BigDecimal storage) {
public ItemMatterCapacitor(Fraction storage) {
super(new Properties().stacksTo(1).tab(OverdriveThatMatters.CREATIVE_TAB));
is_creative = false;
this.storage = storage;

View File

@ -23,6 +23,7 @@ import ru.dbotthepony.mc.otm.capability.MatteryCapability;
import ru.dbotthepony.mc.otm.capability.drive.DrivePool;
import ru.dbotthepony.mc.otm.capability.drive.IMatteryDrive;
import ru.dbotthepony.mc.otm.capability.drive.ItemMatteryDrive;
import ru.dbotthepony.mc.otm.core.Fraction;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@ -32,11 +33,11 @@ import java.util.List;
import java.util.UUID;
public class ItemPortableCondensationDrive extends Item {
public final BigDecimal capacity;
public final Fraction capacity;
public ItemPortableCondensationDrive(int capacity) {
super(new Properties().stacksTo(1).tab(OverdriveThatMatters.CREATIVE_TAB));
this.capacity = new BigDecimal(capacity);
this.capacity = new Fraction(capacity);
}
@SubscribeEvent

View File

@ -10,6 +10,7 @@ import ru.dbotthepony.mc.otm.AbstractGrid;
import ru.dbotthepony.mc.otm.OverdriveThatMatters;
import ru.dbotthepony.mc.otm.capability.MatteryCapability;
import ru.dbotthepony.mc.otm.capability.matter.*;
import ru.dbotthepony.mc.otm.core.Fraction;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
@ -31,81 +32,81 @@ public class MatterGrid extends AbstractGrid<IMatterGridCell> implements IMatter
super(MatteryCapability.MATTER_CELL);
}
public BigDecimal getCapacity() {
BigDecimal summ = BigDecimal.ZERO;
public Fraction getCapacity() {
Fraction summ = Fraction.ZERO;
for (IMatterGridCell cell : cells) {
IMatterHandler handler = cell.getMatterHandler();
if (handler != null && handler.getDirection() == IMatterHandler.MatterDirection.BIDIRECTIONAL) {
summ = summ.add(handler.getMaxStoredMatter());
summ = summ.plus(handler.getMaxStoredMatter());
}
}
return summ;
}
public BigDecimal getPotentialCapacity() {
BigDecimal summ = BigDecimal.ZERO;
public Fraction getPotentialCapacity() {
Fraction summ = Fraction.ZERO;
for (IMatterGridCell cell : cells) {
IMatterHandler handler = cell.getMatterHandler();
if (handler != null && handler.getDirection() != IMatterHandler.MatterDirection.RECEIVE) {
summ = summ.add(handler.getMaxStoredMatter());
summ = summ.plus(handler.getMaxStoredMatter());
}
}
return summ;
}
public BigDecimal getStored() {
BigDecimal summ = BigDecimal.ZERO;
public Fraction getStored() {
Fraction summ = Fraction.ZERO;
for (IMatterGridCell cell : cells) {
IMatterHandler handler = cell.getMatterHandler();
if (handler != null && handler.getDirection() == IMatterHandler.MatterDirection.BIDIRECTIONAL) {
summ = summ.add(handler.getStoredMatter());
summ = summ.plus(handler.getStoredMatter());
}
}
return summ;
}
public BigDecimal getPotentialStored() {
BigDecimal summ = BigDecimal.ZERO;
public Fraction getPotentialStored() {
Fraction summ = Fraction.ZERO;
for (IMatterGridCell cell : cells) {
IMatterHandler handler = cell.getMatterHandler();
if (handler != null && handler.getDirection() != IMatterHandler.MatterDirection.RECEIVE) {
summ = summ.add(handler.getStoredMatter());
summ = summ.plus(handler.getStoredMatter());
}
}
return summ;
}
public BigDecimal extractMatter(BigDecimal howMuch, boolean simulate) {
if (howMuch.compareTo(BigDecimal.ZERO) <= 0)
return BigDecimal.ZERO;
public Fraction extractMatter(Fraction howMuch, boolean simulate) {
if (howMuch.compareTo(Fraction.ZERO) <= 0)
return Fraction.ZERO;
validate();
BigDecimal extracted = BigDecimal.ZERO;
Fraction extracted = Fraction.ZERO;
for (IMatterGridCell cell : cells) {
IMatterHandler handler = cell.getMatterHandler();
if (handler != null && handler.getDirection() != IMatterHandler.MatterDirection.RECEIVE) {
BigDecimal drain = handler.extractMatterOuter(howMuch, simulate);
var drain = handler.extractMatterOuter(howMuch, simulate);
if (!drain.equals(BigDecimal.ZERO)) {
extracted = extracted.add(drain);
howMuch = howMuch.subtract(drain);
if (!drain.equalsCompact(Fraction.ZERO)) {
extracted = extracted.plus(drain);
howMuch = howMuch.minus(drain);
if (howMuch.compareTo(BigDecimal.ZERO) <= 0) {
if (howMuch.compareTo(Fraction.ZERO) <= 0) {
break;
}
}
@ -115,25 +116,25 @@ public class MatterGrid extends AbstractGrid<IMatterGridCell> implements IMatter
return extracted;
}
public BigDecimal softPushMatter(BigDecimal howMuch, boolean simulate) {
if (howMuch.compareTo(BigDecimal.ZERO) <= 0)
return BigDecimal.ZERO;
public Fraction softPushMatter(Fraction howMuch, boolean simulate) {
if (howMuch.compareTo(Fraction.ZERO) <= 0)
return Fraction.ZERO;
validate();
BigDecimal received = BigDecimal.ZERO;
Fraction received = Fraction.ZERO;
for (IMatterGridCell cell : cells) {
IMatterHandler handler = cell.getMatterHandler();
if (handler != null && handler.getDirection() == IMatterHandler.MatterDirection.BIDIRECTIONAL) {
BigDecimal receive = handler.receiveMatterOuter(howMuch, simulate);
var receive = handler.receiveMatterOuter(howMuch, simulate);
if (!receive.equals(BigDecimal.ZERO)) {
received = received.add(receive);
howMuch = howMuch.subtract(receive);
if (!receive.equalsCompact(Fraction.ZERO)) {
received = received.plus(receive);
howMuch = howMuch.minus(receive);
if (howMuch.compareTo(BigDecimal.ZERO) <= 0) {
if (howMuch.compareTo(Fraction.ZERO) <= 0) {
break;
}
}
@ -143,25 +144,25 @@ public class MatterGrid extends AbstractGrid<IMatterGridCell> implements IMatter
return received;
}
public BigDecimal pushMatter(BigDecimal howMuch, boolean simulate) {
if (howMuch.compareTo(BigDecimal.ZERO) <= 0)
return BigDecimal.ZERO;
public Fraction pushMatter(Fraction howMuch, boolean simulate) {
if (howMuch.compareTo(Fraction.ZERO) <= 0)
return Fraction.ZERO;
validate();
BigDecimal received = BigDecimal.ZERO;
Fraction received = Fraction.ZERO;
for (IMatterGridCell cell : cells) {
IMatterHandler handler = cell.getMatterHandler();
if (handler != null && handler.getDirection() != IMatterHandler.MatterDirection.EXTRACT) {
BigDecimal receive = handler.receiveMatterOuter(howMuch, simulate);
var receive = handler.receiveMatterOuter(howMuch, simulate);
if (!receive.equals(BigDecimal.ZERO)) {
received = received.add(receive);
howMuch = howMuch.subtract(receive);
if (!receive.equalsCompact(Fraction.ZERO)) {
received = received.plus(receive);
howMuch = howMuch.minus(receive);
if (howMuch.compareTo(BigDecimal.ZERO) <= 0) {
if (howMuch.compareTo(Fraction.ZERO) <= 0) {
break;
}
}

View File

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

View File

@ -136,7 +136,7 @@ public class DriveViewerMenu extends PoweredMatteryMenu implements INetworkedIte
if (amount == item.getCount()) {
var remaining = last_drive.insertStack(new ItemStackWrapper(item), false);
if (remaining.getCount().intValue() == item.getCount())
if (remaining.getCount().toInt() == item.getCount())
return ItemStack.EMPTY;
if (remaining.isEmpty()) {
@ -147,8 +147,8 @@ public class DriveViewerMenu extends PoweredMatteryMenu implements INetworkedIte
}
var copy = item.copy();
tile.getIOItemCount(item.getCount() - remaining.getCount().intValue(), false);
item.shrink(remaining.getCount().intValue());
tile.getIOItemCount(item.getCount() - remaining.getCount().toInt(), false);
item.shrink(remaining.getCount().toInt());
slot.setChanged();
return copy;
@ -159,12 +159,12 @@ public class DriveViewerMenu extends PoweredMatteryMenu implements INetworkedIte
var remaining = last_drive.insertStack(new ItemStackWrapper(copy_insert), false);
if (remaining.getCount().intValue() == copy_insert.getCount())
if (remaining.getCount().toInt() == copy_insert.getCount())
return ItemStack.EMPTY;
var copy = item.copy();
tile.getIOItemCount(amount - remaining.getCount().intValue(), false);
item.shrink(amount - remaining.getCount().intValue());
tile.getIOItemCount(amount - remaining.getCount().toInt(), false);
item.shrink(amount - remaining.getCount().toInt());
slot.setChanged();
return copy;

View File

@ -6,13 +6,14 @@ import net.minecraft.world.level.block.entity.BlockEntity;
import ru.dbotthepony.mc.otm.Registry;
import ru.dbotthepony.mc.otm.block.entity.BlockEntityEnergyCounter;
import ru.dbotthepony.mc.otm.menu.data.BigDecimalDataContainer;
import ru.dbotthepony.mc.otm.menu.data.FractionDataContainer;
import javax.annotation.Nullable;
public class EnergyCounterMenu extends MatteryMenu {
public final BigDecimalDataContainer passed = new BigDecimalDataContainer();
public final BigDecimalDataContainer average = new BigDecimalDataContainer();
public final BigDecimalDataContainer last_20_ticks = new BigDecimalDataContainer();
public final FractionDataContainer passed = new FractionDataContainer();
public final FractionDataContainer average = new FractionDataContainer();
public final FractionDataContainer last_20_ticks = new FractionDataContainer();
// TODO: Graph and proper networking for it
private int ticks_passed = 0;
@ -33,11 +34,11 @@ public class EnergyCounterMenu extends MatteryMenu {
if (tile != null) {
BlockEntityEnergyCounter tile = (BlockEntityEnergyCounter) this.tile;
passed.setDecimal(tile.getPassed());
average.setDecimal(tile.calcAverage(20));
passed.setValue(tile.getPassed());
average.setValue(tile.calcAverage(20));
if (ticks_passed == 0) {
last_20_ticks.setDecimal(tile.sumHistory(20));
last_20_ticks.setValue(tile.sumHistory(20));
}
ticks_passed = (ticks_passed + 1) % 20;

View File

@ -5,6 +5,7 @@ import net.minecraft.network.chat.FormattedText;
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 java.math.BigDecimal;
import java.math.BigInteger;
@ -33,6 +34,17 @@ public class FormattingHelper {
new BigDecimal("1000000000000000000000000"), // "otm.suffix.yotta": "Y%s",
};
public static final Fraction[] SUFFIX_ABOVE_ONE_FRAC = new Fraction[] {
Fraction.fromString("1000"), // "otm.suffix.kilo": "k%s",
Fraction.fromString("1000000"), // "otm.suffix.mega": "M%s",
Fraction.fromString("1000000000"), // "otm.suffix.giga": "G%s",
Fraction.fromString("1000000000000"), // "otm.suffix.tera": "T%s",
Fraction.fromString("1000000000000000"), // "otm.suffix.peta": "P%s",
Fraction.fromString("1000000000000000000"), // "otm.suffix.exa": "E%s",
Fraction.fromString("1000000000000000000000"), // "otm.suffix.zetta": "Z%s",
Fraction.fromString("1000000000000000000000000"), // "otm.suffix.yotta": "Y%s",
};
public static final String[] SUFFIX_COMPONENTS_BELOW_ONE = new String[] {
"otm.suffix.deci",
"otm.suffix.centi",
@ -59,6 +71,19 @@ public class FormattingHelper {
new BigDecimal("0.000000000000000000000001"), // "otm.suffix.yocto": "y%s",
};
public static final Fraction[] SUFFIX_BELOW_ONE_FRAC = new Fraction[] {
Fraction.fromString("0.1"), // "otm.suffix.milli": "d%s",
Fraction.fromString("0.01"), // "otm.suffix.milli": "c%s",
Fraction.fromString("0.001"), // "otm.suffix.milli": "m%s",
Fraction.fromString("0.000001"), // "otm.suffix.micro": "μ%s",
Fraction.fromString("0.000000001"), // "otm.suffix.nano": "n%s",
Fraction.fromString("0.000000000001"), // "otm.suffix.pico": "p%s",
Fraction.fromString("0.000000000000001"), // "otm.suffix.femto": "f%s",
Fraction.fromString("0.000000000000000001"), // "otm.suffix.atto": "a%s",
Fraction.fromString("0.000000000000000000001"), // "otm.suffix.zepto": "z%s",
Fraction.fromString("0.000000000000000000000001"), // "otm.suffix.yocto": "y%s",
};
public static String formatDecimal(BigDecimal value, int decimals) {
return value.setScale(decimals, RoundingMode.HALF_UP).toString();
}
@ -70,26 +95,50 @@ public class FormattingHelper {
return new TranslatableComponent("otm.gui.level", formatSI(power, POWER_NAME), formatSI(max_power, POWER_NAME));
}
public static Component formatPowerLevel(Fraction power, Fraction 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));
}
public static Component formatMatterLevel(Fraction power, Fraction 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));
}
public static TranslatableComponent formatMatterValue(Fraction matter) {
return new TranslatableComponent("otm.gui.matter.format", formatSI(matter, MATTER_NAME));
}
public static Component formatMatterValuePlain(BigDecimal matter) {
return formatSI(matter, MATTER_NAME);
}
public static Component formatMatterValuePlain(Fraction matter) {
return formatSI(matter, MATTER_NAME);
}
public static Component formatPower(BigDecimal power) {
return formatSI(power, POWER_NAME);
}
public static Component formatPower(Fraction power) {
return formatSI(power, POWER_NAME);
}
public static Component formatSI(BigDecimal value) {
return formatSI(value, "");
}
public static Component formatSI(Fraction value) {
return formatSI(value, "");
}
public static Component formatSI(BigDecimal value, Object end_suffix) {
if (value.compareTo(BigDecimal.ZERO) == 0) {
if ("".equals(end_suffix)) {
@ -133,4 +182,48 @@ public class FormattingHelper {
return new TranslatableComponent("otm.suffix.merge", formatDecimal(value, 2), end_suffix);
}
}
public static Component formatSI(Fraction value, Object end_suffix) {
if (value.compareTo(Fraction.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(Fraction.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_FRAC.length - 1; i >= 0; i--) {
if (value.compareTo(SUFFIX_ABOVE_ONE_FRAC[i]) >= 0) {
return new TranslatableComponent(SUFFIX_COMPONENTS_ABOVE_ONE[i], value.div(SUFFIX_ABOVE_ONE_FRAC[i]).decimalString(2, true), end_suffix);
}
}
if ("".equals(end_suffix)) {
return new TextComponent(value.decimalString(2, true));
} else {
return new TranslatableComponent("otm.suffix.merge", value.decimalString(2, true), end_suffix);
}
}
for (int i = SUFFIX_BELOW_ONE.length - 1; i >= 0; i--) {
if (value.compareTo(SUFFIX_BELOW_ONE_FRAC[i]) < 0) {
return new TranslatableComponent(SUFFIX_COMPONENTS_BELOW_ONE[i], value.div(SUFFIX_BELOW_ONE_FRAC[i]).decimalString(2, true), end_suffix);
}
}
if ("".equals(end_suffix)) {
return new TextComponent(value.decimalString(2, true));
} else {
return new TranslatableComponent("otm.suffix.merge", value.decimalString(2, true), end_suffix);
}
}
}

View File

@ -6,6 +6,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.capability.matter.IMatterHandler;
import ru.dbotthepony.mc.otm.core.Fraction;
import ru.dbotthepony.mc.otm.menu.slot.MatterContainerInputSlot;
import ru.dbotthepony.mc.otm.menu.widget.MatterLevelWidget;
@ -34,13 +35,13 @@ public class MatterCapacitorBankMenu extends MatteryMenu {
return tile.getMatterGrid().getStored();
}
return BigDecimal.ZERO;
return Fraction.ZERO;
}, () -> {
if (tile.getMatterGrid() != null) {
return tile.getMatterGrid().getCapacity();
}
return BigDecimal.ZERO;
return Fraction.ZERO;
});
}

View File

@ -8,6 +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.menu.MatteryMenu;
import ru.dbotthepony.mc.otm.network.MatteryNetworking;
import ru.dbotthepony.mc.otm.network.SetCarriedPacket;
@ -99,8 +100,8 @@ public class NetworkedItemView implements IStorageListener<ItemStackWrapper> {
}
@Override
public void changeObject(UUID id, BigDecimal new_count) {
changeObject(id, new_count.intValue());
public void changeObject(UUID id, Fraction new_count) {
changeObject(id, new_count.toInt());
}
@Override
@ -217,13 +218,13 @@ public class NetworkedItemView implements IStorageListener<ItemStackWrapper> {
}
int amount = calculateIOAmount(action == ClickAction.PRIMARY ? get_state.stack().getMaxStackSize() : Math.max(1, get_state.stack().getMaxStackSize() / 2));
var extracted = provider.extractStack(get_state.id_upstream(), new BigDecimal(amount), true);
var extracted = provider.extractStack(get_state.id_upstream(), new Fraction(amount), true);
if (!extracted.isEmpty()) {
var move = menu.quickMoveToInventory(extracted.stack(), false);
if (move.remaining().getCount() != extracted.stack().getCount()) {
provider.extractStack(get_state.id_upstream(), new BigDecimal(extracted.stack().getCount() - move.remaining().getCount()), false);
provider.extractStack(get_state.id_upstream(), new Fraction(extracted.stack().getCount() - move.remaining().getCount()), false);
doneIOAmount(extracted.stack().getCount() - move.remaining().getCount());
}
}
@ -277,7 +278,7 @@ public class NetworkedItemView implements IStorageListener<ItemStackWrapper> {
int amount = calculateIOAmount(action == ClickAction.PRIMARY ? get_state.stack().getMaxStackSize() : Math.max(1, get_state.stack().getMaxStackSize() / 2));
var extracted = provider.extractStack(get_state.id_upstream(), new BigDecimal(amount), false);
var extracted = provider.extractStack(get_state.id_upstream(), new Fraction(amount), false);
doneIOAmount(extracted.getCountInt());
menu.setCarried(extracted.stack());

View File

@ -3,6 +3,7 @@ package ru.dbotthepony.mc.otm.menu.widget;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TranslatableComponent;
import ru.dbotthepony.mc.otm.capability.IMatteryEnergyStorage;
import ru.dbotthepony.mc.otm.core.Fraction;
import ru.dbotthepony.mc.otm.menu.FormattingHelper;
import ru.dbotthepony.mc.otm.menu.MatteryMenu;
@ -20,7 +21,7 @@ public class BatteryLevelWidget extends StorageGaugeWidget {
super(menu, x, y);
}
public BatteryLevelWidget(MatteryMenu menu, int x, int y, Supplier<BigDecimal> value_supplier, Supplier<BigDecimal> max_value_supplier) {
public BatteryLevelWidget(MatteryMenu menu, int x, int y, Supplier<Fraction> value_supplier, Supplier<Fraction> max_value_supplier) {
super(menu, x, y, value_supplier, max_value_supplier);
}
@ -49,7 +50,7 @@ public class BatteryLevelWidget extends StorageGaugeWidget {
public List<Component> getTooltip() {
return List.of(
new TranslatableComponent("otm.gui.power.percentage_level", String.format("%.2f", getLevel() * 100d)),
FormattingHelper.formatPowerLevel(value_container.getDecimal(), max_value_container.getDecimal())
FormattingHelper.formatPowerLevel(value_container.getValue(), max_value_container.getValue())
);
}
}

View File

@ -3,6 +3,7 @@ package ru.dbotthepony.mc.otm.menu.widget;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TranslatableComponent;
import ru.dbotthepony.mc.otm.capability.matter.IMatterHandler;
import ru.dbotthepony.mc.otm.core.Fraction;
import ru.dbotthepony.mc.otm.menu.FormattingHelper;
import ru.dbotthepony.mc.otm.menu.MatteryMenu;
@ -28,7 +29,7 @@ public class MatterLevelWidget extends StorageGaugeWidget {
this(menu, 0, 0, capability);
}
public MatterLevelWidget(MatteryMenu menu, int x, int y, Supplier<BigDecimal> value_supplier, Supplier<BigDecimal> max_value_supplier) {
public MatterLevelWidget(MatteryMenu menu, int x, int y, Supplier<Fraction> value_supplier, Supplier<Fraction> max_value_supplier) {
super(menu, x, y, value_supplier, max_value_supplier);
}
@ -57,7 +58,7 @@ public class MatterLevelWidget extends StorageGaugeWidget {
public List<Component> getTooltip() {
return List.of(
new TranslatableComponent("otm.gui.matter.percentage_level", String.format("%.2f", getLevel() * 100d)),
FormattingHelper.formatMatterLevel(value_container.getDecimal(), max_value_container.getDecimal())
FormattingHelper.formatMatterLevel(value_container.getValue(), max_value_container.getValue())
);
}
}

View File

@ -1,18 +1,20 @@
package ru.dbotthepony.mc.otm.menu.widget;
import ru.dbotthepony.mc.otm.capability.MatteryCapability;
import ru.dbotthepony.mc.otm.core.Fraction;
import ru.dbotthepony.mc.otm.menu.MatteryMenu;
import ru.dbotthepony.mc.otm.menu.data.BigDecimalDataContainer;
import ru.dbotthepony.mc.otm.menu.data.FractionDataContainer;
import java.math.BigDecimal;
import java.util.function.Supplier;
abstract public class StorageGaugeWidget extends GaugeWidget {
protected Supplier<BigDecimal> value_supplier;
protected Supplier<BigDecimal> max_value_supplier;
protected Supplier<Fraction> value_supplier;
protected Supplier<Fraction> max_value_supplier;
protected final BigDecimalDataContainer value_container = new BigDecimalDataContainer();
protected final BigDecimalDataContainer max_value_container = new BigDecimalDataContainer();
protected final FractionDataContainer value_container = new FractionDataContainer();
protected final FractionDataContainer max_value_container = new FractionDataContainer();
public StorageGaugeWidget(MatteryMenu menu, int x, int y) {
this(menu, x, y, null, null);
@ -22,7 +24,7 @@ abstract public class StorageGaugeWidget extends GaugeWidget {
this(menu, 0, 0, null, null);
}
public StorageGaugeWidget(MatteryMenu menu, int x, int y, Supplier<BigDecimal> value_supplier, Supplier<BigDecimal> max_value_supplier) {
public StorageGaugeWidget(MatteryMenu menu, int x, int y, Supplier<Fraction> value_supplier, Supplier<Fraction> max_value_supplier) {
super(menu, x, y);
this.value_supplier = value_supplier;
this.max_value_supplier = max_value_supplier;
@ -31,7 +33,7 @@ abstract public class StorageGaugeWidget extends GaugeWidget {
addDataSlots(max_value_container);
}
public StorageGaugeWidget(MatteryMenu menu, Supplier<BigDecimal> value_supplier, Supplier<BigDecimal> max_value_supplier) {
public StorageGaugeWidget(MatteryMenu menu, Supplier<Fraction> value_supplier, Supplier<Fraction> max_value_supplier) {
this(menu, 0, 0, value_supplier, max_value_supplier);
}
@ -40,12 +42,12 @@ abstract public class StorageGaugeWidget extends GaugeWidget {
if (value_supplier == null || max_value_supplier == null)
return;
value_container.setDecimal(value_supplier.get());
max_value_container.setDecimal(max_value_supplier.get());
value_container.setValue(value_supplier.get());
max_value_container.setValue(max_value_supplier.get());
}
@Override
public float getLevel() {
return max_value_container.getDecimal().compareTo(BigDecimal.ZERO) == 0 ? 0f : value_container.getDecimal().divide(max_value_container.getDecimal(), MatteryCapability.ROUND_RULES).floatValue();
return max_value_container.getValue().compareTo(Fraction.ZERO) == 0 ? 0f : value_container.getValue().div(max_value_container.getValue()).toFloat();
}
}

View File

@ -7,6 +7,7 @@ import net.minecraftforge.fml.DistExecutor;
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.matter.MatterRegistry;
import java.math.BigDecimal;
@ -14,14 +15,14 @@ import java.util.HashMap;
import java.util.Map;
import java.util.function.Supplier;
public record MatterRegistryPacket(Map<Item, BigDecimal> list) {
public record MatterRegistryPacket(Map<Item, Fraction> list) {
public void write(FriendlyByteBuf buffer) {
buffer.writeInt(list.size());
var registry = (ForgeRegistry<Item>) RegistryManager.ACTIVE.getRegistry(Item.class);
for (var entry : list.entrySet()) {
buffer.writeInt(registry.getID(entry.getKey()));
NetworkHelper.writeDecimal(buffer, entry.getValue());
entry.getValue().write(buffer);
}
}
@ -29,10 +30,10 @@ public record MatterRegistryPacket(Map<Item, BigDecimal> list) {
var size = buffer.readInt();
var registry = (ForgeRegistry<Item>) RegistryManager.ACTIVE.getRegistry(Item.class);
var map = new HashMap<Item, BigDecimal>();
var map = new HashMap<Item, Fraction>();
for (int i = 0; i < size; i++) {
map.put(registry.getValue(buffer.readInt()), NetworkHelper.readDecimal(buffer));
map.put(registry.getValue(buffer.readInt()), Fraction.read(buffer));
}
return new MatterRegistryPacket(map);

View File

@ -23,4 +23,34 @@ public class NetworkHelper {
buffer.writeByte(build.length);
for (byte b : build) buffer.writeByte(b);
}
public static short[] bytesToShorts(byte[] input) {
if (input.length % 2 != 0) {
short[] values = new short[input.length / 2 + 1];
for (int i = 0; i < values.length - 1; i++)
values[i] = (short) ((input[i * 2] & 0xFF) | (input[i * 2 + 1] & 0xFF) << 8);
values[values.length - 1] = input[input.length - 1];
return values;
}
short[] values = new short[input.length / 2];
for (int i = 0; i < values.length; i++)
values[i] = (short) ((input[i * 2] & 0xFF) | (input[i * 2 + 1] & 0xFF) << 8);
return values;
}
public static byte[] shortsToBytes(short[] input) {
byte[] values = new byte[input.length * 2];
for (int i = 0; i < input.length; i++) {
values[i * 2] = (byte) (input[i] & 0xFF);
values[i * 2 + 1] = (byte) ((input[i] & 0xFF00) >> 8);
}
return values;
}
}

View File

@ -6,15 +6,16 @@ import net.minecraftforge.api.distmarker.Dist;
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.network.NetworkHelper;
import java.math.BigDecimal;
import java.util.function.Supplier;
public record AndroidEnergyPacket(boolean is_maximal, BigDecimal energy) {
public record AndroidEnergyPacket(boolean is_maximal, Fraction energy) {
public void write(FriendlyByteBuf buffer) {
buffer.writeBoolean(is_maximal);
NetworkHelper.writeDecimal(buffer, energy);
energy.write(buffer);
}
public void play(Supplier<NetworkEvent.Context> context) {
@ -39,6 +40,6 @@ public record AndroidEnergyPacket(boolean is_maximal, BigDecimal energy) {
}
public static AndroidEnergyPacket read(FriendlyByteBuf buffer) {
return new AndroidEnergyPacket(buffer.readBoolean(), NetworkHelper.readDecimal(buffer));
return new AndroidEnergyPacket(buffer.readBoolean(), Fraction.read(buffer));
}
}

View File

@ -1,6 +1,7 @@
package ru.dbotthepony.mc.otm.storage;
import net.minecraft.MethodsReturnNonnullByDefault;
import ru.dbotthepony.mc.otm.core.Fraction;
import javax.annotation.ParametersAreNonnullByDefault;
import java.math.BigDecimal;
@ -10,6 +11,6 @@ import java.util.UUID;
@ParametersAreNonnullByDefault
public interface IStorageListener<T extends IStorageStack> {
void addObject(T stack, UUID id, IStorageView<T> provider);
void changeObject(UUID id, BigDecimal new_count);
void changeObject(UUID id, Fraction new_count);
void removeObject(UUID id);
}

View File

@ -1,6 +1,7 @@
package ru.dbotthepony.mc.otm.storage;
import net.minecraft.MethodsReturnNonnullByDefault;
import ru.dbotthepony.mc.otm.core.Fraction;
import javax.annotation.ParametersAreNonnullByDefault;
import java.math.BigDecimal;
@ -18,8 +19,8 @@ import java.util.Optional;
public interface IStorageStack {
IStorageStack copy();
void setCount(BigDecimal value);
BigDecimal getCount();
void setCount(Fraction value);
Fraction getCount();
boolean isEmpty();
@ -27,7 +28,7 @@ public interface IStorageStack {
* @return max stack size for this stack object
* Optional.empty() if unlimited (default)
*/
default Optional<BigDecimal> getMaxStackSize() {
default Optional<Fraction> getMaxStackSize() {
return Optional.empty();
}
@ -54,11 +55,11 @@ public interface IStorageStack {
*/
boolean sameItem(IStorageStack other);
default void grow(BigDecimal amount) {
setCount(getCount().add(amount));
default void grow(Fraction amount) {
setCount(getCount().plus(amount));
}
default void shrink(BigDecimal amount) {
setCount(getCount().subtract(amount));
default void shrink(Fraction amount) {
setCount(getCount().minus(amount));
}
}

View File

@ -2,6 +2,7 @@ package ru.dbotthepony.mc.otm.storage;
import net.minecraft.MethodsReturnNonnullByDefault;
import ru.dbotthepony.mc.otm.core.Fraction;
import javax.annotation.ParametersAreNonnullByDefault;
import java.math.BigDecimal;
@ -23,7 +24,7 @@ public interface IStorageView<T extends IStorageStack> extends IStorageTrigger<T
* @param simulate whenever to simulate the action or not
* @return copy of object, with amount of units actually extracted
*/
T extractStack(UUID id, BigDecimal amount, boolean simulate);
T extractStack(UUID id, Fraction amount, boolean simulate);
/**
* Designed for views, for extraction with less computation overhead caused by
@ -34,7 +35,7 @@ public interface IStorageView<T extends IStorageStack> extends IStorageTrigger<T
* @param simulate whenever to simulate the action or not
* @return amount extracted
*/
default BigDecimal extractStackCount(UUID id, BigDecimal amount, boolean simulate) {
default Fraction extractStackCount(UUID id, Fraction amount, boolean simulate) {
return extractStack(id, amount, simulate).getCount();
}

View File

@ -2,6 +2,7 @@ package ru.dbotthepony.mc.otm.storage;
import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.world.item.ItemStack;
import ru.dbotthepony.mc.otm.core.Fraction;
import javax.annotation.ParametersAreNonnullByDefault;
import java.math.BigDecimal;
@ -18,8 +19,8 @@ public record ItemStackWrapper(ItemStack stack) implements IStorageStack {
}
@Override
public void setCount(BigDecimal value) {
setCount(value.intValue());
public void setCount(Fraction value) {
setCount(value.toInt());
}
public void setCount(int value) {
@ -27,8 +28,8 @@ public record ItemStackWrapper(ItemStack stack) implements IStorageStack {
}
@Override
public BigDecimal getCount() {
return new BigDecimal(stack.getCount());
public Fraction getCount() {
return new Fraction(stack.getCount());
}
public int getCountInt() {
@ -36,8 +37,8 @@ public record ItemStackWrapper(ItemStack stack) implements IStorageStack {
}
@Override
public Optional<BigDecimal> getMaxStackSize() {
return Optional.of(new BigDecimal(stack.getMaxStackSize()));
public Optional<Fraction> getMaxStackSize() {
return Optional.of(new Fraction(stack.getMaxStackSize()));
}
@Override

View File

@ -1,6 +1,7 @@
package ru.dbotthepony.mc.otm.storage;
import net.minecraft.MethodsReturnNonnullByDefault;
import ru.dbotthepony.mc.otm.core.Fraction;
import javax.annotation.ParametersAreNonnullByDefault;
import java.math.BigDecimal;
@ -26,11 +27,11 @@ public class VirtualComponent<T extends IStorageStack> implements IStorageCompon
}
public record RemoteTuple<T extends IStorageStack>(T object, UUID remote_id, IStorageView<T> provider, LocalTuple<T> local) {
public T extract(BigDecimal amount, boolean simulate) {
public T extract(Fraction amount, boolean simulate) {
return provider.extractStack(remote_id, amount, simulate);
}
public BigDecimal extractCount(BigDecimal amount, boolean simulate) {
public Fraction extractCount(Fraction amount, boolean simulate) {
return provider.extractStackCount(remote_id, amount, simulate);
}
@ -133,32 +134,30 @@ public class VirtualComponent<T extends IStorageStack> implements IStorageCompon
return tuple != null ? tuple.stack : identity.empty();
}
public static final BigDecimal MINUS_ONE = new BigDecimal(-1);
@Override
@SuppressWarnings("unchecked")
public T extractStack(UUID id, BigDecimal amount, boolean simulate) {
public T extractStack(UUID id, Fraction amount, boolean simulate) {
var tuple = indexed_by_local_uuid.get(id);
if (tuple == null || amount.compareTo(BigDecimal.ZERO) == 0)
if (tuple == null || amount.compareTo(Fraction.ZERO) == 0)
return identity.empty();
if (amount.compareTo(MINUS_ONE) <= 0)
if (amount.compareTo(Fraction.MINUS_ONE) <= 0)
amount = tuple.stack.getMaxStackSize().orElse(tuple.stack.getCount());
BigDecimal extract = tuple.stack.getCount().min(amount);
BigDecimal extracted = BigDecimal.ZERO;
var extract = tuple.stack.getCount().min(amount);
var extracted = Fraction.ZERO;
final var copy = (T) tuple.stack.copy();
for (var remote_tuple : tuple.tuples) {
extracted = extracted.add(remote_tuple.extractCount(extract.subtract(extracted), simulate));
extracted = extracted.plus(remote_tuple.extractCount(extract.minus(extracted), simulate));
if (extracted.compareTo(extract) >= 0)
break;
}
if (extracted.compareTo(BigDecimal.ZERO) > 0) {
if (extracted.compareTo(Fraction.ZERO) > 0) {
copy.setCount(extracted);
return copy;
}
@ -224,14 +223,14 @@ public class VirtualComponent<T extends IStorageStack> implements IStorageCompon
@Override
public void changeObject(UUID id, BigDecimal new_count) {
assert new_count.compareTo(BigDecimal.ZERO) > 0;
public void changeObject(UUID id, Fraction new_count) {
assert new_count.compareTo(Fraction.ZERO) > 0;
var tuple = indexed_by_remote_uuid.get(id);
if (tuple == null)
throw new IllegalStateException("No such tuple with id " + id);
final var diff = new_count.subtract(tuple.object.getCount());
final var diff = new_count.minus(tuple.object.getCount());
tuple.object.setCount(new_count);
tuple.local.stack.grow(diff);
@ -253,7 +252,7 @@ public class VirtualComponent<T extends IStorageStack> implements IStorageCompon
indexed_by_remote_uuid.remove(id);
final boolean a = tuple.local.stack.getCount().compareTo(BigDecimal.ZERO) <= 0;
final boolean a = tuple.local.stack.getCount().compareTo(Fraction.ZERO) <= 0;
final boolean b = tuple.local.tuples.size() == 0;
if (a || b) {

View File

@ -0,0 +1,555 @@
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
import java.math.RoundingMode
fun powScale(int: Int): BigInteger {
if (int <= 0)
return BigInteger.ONE
var result = BigInteger.TEN
for (i in 2 .. int)
result *= BigInteger.TEN
return result
}
fun powUnscaled(unscaled: BigInteger, scale: Int): BigInteger {
if (scale >= 0)
return unscaled
var result = unscaled
for (i in 2 .. -scale)
result *= BigInteger.TEN
return result
}
val DEFAULT_MATH_CONTEXT = MathContext(64, RoundingMode.HALF_UP)
@Suppress("NOTHING_TO_INLINE")
inline fun invertCompare(int: Int): Int {
if (int == 0)
return 0
return if (int < 0) 1 else -1
}
@JvmRecord
data class Fraction @JvmOverloads constructor(@JvmField val value: BigInteger, @JvmField val divisor: BigInteger = BigInteger.ONE, @JvmField val compact: Boolean = true) {
@JvmOverloads constructor(value: Long, compact: Boolean = true) : this(BigInteger.valueOf(value), compact = compact)
@JvmOverloads constructor(value: Int, compact: Boolean = true) : this(BigInteger.valueOf(value.toLong()), compact = compact)
@JvmOverloads constructor(value: Float, compact: Boolean = true) : this(BigDecimal(value.toString()), compact = compact)
@JvmOverloads constructor(value: Double, compact: Boolean = true) : this(BigDecimal(value.toString()), compact = compact)
@JvmOverloads constructor(value: String, compact: Boolean = true) : this(BigDecimal(value), compact = compact)
@JvmOverloads constructor(value: Long, div: Long, compact: Boolean = true) : this(BigInteger.valueOf(value), BigInteger.valueOf(div), compact = compact)
@JvmOverloads constructor(value: Int, div: Int, compact: Boolean = true) : this(BigInteger.valueOf(value.toLong()), BigInteger.valueOf(div.toLong()), compact = compact)
@JvmOverloads constructor(value: Float, div: Float, compact: Boolean = true) : this(BigDecimal(value.toString()), BigDecimal(div.toString()), compact = compact)
@JvmOverloads constructor(value: Double, div: Double, compact: Boolean = true) : this(BigDecimal(value.toString()), BigDecimal(div.toString()), compact = compact)
@JvmOverloads constructor(value: String, div: String, compact: Boolean = true) : this(BigDecimal(value), BigDecimal(div), compact = compact)
@JvmOverloads constructor(value: BigDecimal, compact: Boolean = true) : this(powUnscaled(value.unscaledValue(), value.scale()), powScale(value.scale()), compact = compact)
@JvmOverloads constructor(value: BigDecimal, div: BigDecimal, compact: Boolean = true) : this(powUnscaled(value.unscaledValue(), value.scale()).multiply(powScale(div.scale())), powScale(value.scale()).multiply(powUnscaled(div.unscaledValue(), div.scale())), compact = compact)
fun compactAndCanonize(): Fraction {
if (value == BigInteger.ZERO || value == BigInteger.ONE || divisor == BigInteger.ONE)
return this
val a = signnum()
val b = value.signum()
val c = divisor.signum()
if (a != b && a != c) {
val mod = value % divisor
if (mod == BigInteger.ZERO)
return Fraction(-value / -divisor, compact = compact)
return Fraction(-value, -divisor)
}
val mod = value % divisor
if (mod == BigInteger.ZERO)
return Fraction(value / divisor, compact = compact)
return this
}
fun compact(): Fraction {
if (value == BigInteger.ZERO || value == BigInteger.ONE || divisor == BigInteger.ONE)
return this
val mod = value % divisor
if (mod == BigInteger.ZERO)
return Fraction(value / divisor, compact = compact)
return this
}
fun canonize(): Fraction {
if (value == BigInteger.ZERO || value == BigInteger.ONE || divisor == BigInteger.ONE || divisor == BigInteger.ZERO)
return this
val a = signnum()
val b = value.signum()
val c = divisor.signum()
if (a != b && a != c)
return Fraction(-value, -divisor)
return this
}
// Операторы
fun equalsCompact(other: Fraction?): Boolean {
if (other == null)
return false
val a = compact()
val b = other.compact()
return a.value == b.value && a.divisor == b.divisor
}
operator fun compareTo(other: Fraction): Int {
if (divisor == other.divisor)
return value.compareTo(other.value)
val a = signnum()
val b = other.signnum()
if (a == b && a == 0)
return 0
if (a < b)
return -1
else if (a > b)
return 1
val cmp = (value * other.divisor).compareTo(other.value * divisor)
if (a != value.signum() && a != divisor.signum()) {
if (b != other.value.signum() && b != other.divisor.signum()) {
return cmp
}
return invertCompare(cmp)
} else if (b != other.value.signum() && b != other.divisor.signum()) {
return invertCompare(cmp)
}
return cmp
}
fun plusCompact(other: Fraction): Fraction {
if (divisor == other.divisor) {
if (divisor == BigInteger.ONE)
return Fraction(value + other.value)
val new = value + other.value
val mod = new % divisor
if (mod == BigInteger.ZERO)
return Fraction(new / divisor)
return Fraction(value + other.value, divisor)
}
val new = value * other.divisor + other.value * divisor
val div = divisor * other.divisor
val mod = new % div
if (mod == BigInteger.ZERO)
return Fraction(new / div)
return Fraction(new, div)
}
operator fun plus(other: Fraction): Fraction {
if (compact)
return plusCompact(other)
if (divisor == other.divisor) {
return Fraction(value + other.value, divisor, compact = false)
}
return Fraction(value * other.divisor + other.value * divisor, divisor * other.divisor, compact = false)
}
fun minusCompact(other: Fraction): Fraction {
if (divisor == other.divisor) {
if (divisor == BigInteger.ONE)
return Fraction(value + other.value)
val new = value - other.value
val mod = new % divisor
if (mod == BigInteger.ZERO)
return Fraction(new / divisor)
return Fraction(value + other.value, divisor)
}
val new = value * other.divisor - other.value * divisor
val div = divisor * other.divisor
val mod = new % div
if (mod == BigInteger.ZERO)
return Fraction(new / div)
return Fraction(new, div)
}
operator fun minus(other: Fraction): Fraction {
if (compact)
return minusCompact(other)
if (divisor == other.divisor) {
return Fraction(value - other.value, divisor, compact = false)
}
return Fraction(value * other.divisor - other.value * divisor, divisor * other.divisor, compact = false)
}
fun timesCompact(other: Fraction): Fraction {
val new = value * other.value
val div = divisor * other.divisor
val mod = new % div
if (mod == BigInteger.ZERO)
return Fraction(new / div)
return Fraction(new, div)
}
operator fun times(other: Fraction): Fraction {
if (compact)
return timesCompact(other)
return Fraction(value * other.value, divisor * other.divisor, compact = false)
}
fun divCompact(other: Fraction): Fraction {
val new = value * other.divisor
val div = divisor * other.value
val mod = new % div
if (mod == BigInteger.ZERO)
return Fraction(new / div)
return Fraction(new, div)
}
operator fun div(other: Fraction): Fraction {
if (compact)
return divCompact(other)
return Fraction(value * other.divisor, divisor * other.value, compact = false)
}
operator fun unaryMinus(): Fraction {
return Fraction(-value, divisor)
}
operator fun unaryPlus(): Fraction {
return this
}
operator fun plus(other: Float): Fraction = plus(Fraction(other))
operator fun minus(other: Float): Fraction = minus(Fraction(other))
operator fun times(other: Float): Fraction = times(Fraction(other))
operator fun div(other: Float): Fraction = div(Fraction(other))
operator fun plus(other: Double): Fraction = plus(Fraction(other))
operator fun minus(other: Double): Fraction = minus(Fraction(other))
operator fun times(other: Double): Fraction = times(Fraction(other))
operator fun div(other: Double): Fraction = div(Fraction(other))
// может вызвать путаницу
/*
operator fun plus(other: BigDecimal): Fraction = plus(Fraction(other))
operator fun minus(other: BigDecimal): Fraction = minus(Fraction(other))
operator fun times(other: BigDecimal): Fraction = times(Fraction(other))
operator fun div(other: BigDecimal): Fraction = div(Fraction(other))
operator fun plus(other: BigInteger): Fraction = plus(Fraction(other))
operator fun minus(other: BigInteger): Fraction = minus(Fraction(other))
operator fun times(other: BigInteger): Fraction = times(Fraction(other))
operator fun div(other: BigInteger): Fraction = div(Fraction(other))
*/
operator fun plus(other: Int): Fraction = plus(Fraction(other))
operator fun minus(other: Int): Fraction = minus(Fraction(other))
operator fun times(other: Int): Fraction = times(Fraction(other))
operator fun div(other: Int): Fraction = div(Fraction(other))
operator fun plus(other: Long): Fraction = plus(Fraction(other))
operator fun minus(other: Long): Fraction = minus(Fraction(other))
operator fun times(other: Long): Fraction = times(Fraction(other))
operator fun div(other: Long): Fraction = div(Fraction(other))
/*
fun add(other: Float): Fraction = plus(Fraction(other))
fun subtract(other: Float): Fraction = minus(Fraction(other))
fun multiply(other: Float): Fraction = times(Fraction(other))
fun divide(other: Float): Fraction = div(Fraction(other))
fun add(other: Double): Fraction = plus(Fraction(other))
fun subtract(other: Double): Fraction = minus(Fraction(other))
fun multiply(other: Double): Fraction = times(Fraction(other))
fun divide(other: Double): Fraction = div(Fraction(other))
fun add(other: Int): Fraction = plus(Fraction(other))
fun subtract(other: Int): Fraction = minus(Fraction(other))
fun multiply(other: Int): Fraction = times(Fraction(other))
fun divide(other: Int): Fraction = div(Fraction(other))
fun add(other: Long): Fraction = plus(Fraction(other))
fun subtract(other: Long): Fraction = minus(Fraction(other))
fun multiply(other: Long): Fraction = times(Fraction(other))
fun divide(other: Long): Fraction = div(Fraction(other))
fun add(other: Fraction): Fraction = plus(other)
fun subtract(other: Fraction): Fraction = minus(other)
fun multiply(other: Fraction): Fraction = times(other)
fun divide(other: Fraction): Fraction = div(other)
*/
operator fun rem(other: Fraction): Fraction {
return Fraction((this / other).wholePart())
}
// Преобразования
fun toFloat(): Float {
return (value / divisor).toFloat() + ((value % divisor).toFloat() / divisor.toFloat())
}
fun toDouble(): Double {
return (value / divisor).toDouble() + ((value % divisor).toDouble() / divisor.toDouble())
}
fun toByteArray(): ByteArray {
val bytesA = value.toByteArray()
val bytesB = divisor.toByteArray()
return byteArrayOf(bytesA.size.toByte(), *bytesA, bytesB.size.toByte(), *bytesB)
}
fun toInt(): Int {
return (value / divisor).toInt()
}
fun toLong(): Long {
return (value / divisor).toLong()
}
@JvmOverloads
fun toBigDecimal(context: MathContext = DEFAULT_MATH_CONTEXT): BigDecimal {
return BigDecimal(value).divide(BigDecimal(divisor), context)
}
// Утилиты
fun wholePart(): BigInteger {
return value / divisor
}
fun fractionPart(): Fraction {
return Fraction(value % divisor, divisor)
}
fun modPart(): BigInteger {
return value % divisor
}
override fun toString(): String {
return "$value/$divisor"
}
fun formattedString(): String {
return "${wholePart()} ${modPart()}/$divisor"
}
@JvmOverloads
fun decimalString(nums: Int = 2, strict: Boolean = false): String {
val whole = wholePart()
val fraction = modPart()
if (fraction == BigInteger.ZERO) {
if (!strict)
return whole.toString()
return "${whole}.${"0".repeat(nums)}"
}
var strdec = (fraction.toDouble() / divisor.toDouble()).toString()
if (strdec.length == 1) {
strdec = ""
if (strict) {
strdec = "0".repeat(nums)
}
} else {
strdec = strdec.substring(2)
if (strict && strdec.length < nums) {
strdec += "0".repeat(nums - strdec.length)
} else if (strdec.length > nums) {
strdec = strdec.substring(0, nums)
}
}
if (strdec == "") {
return whole.toString()
}
return "${whole}.$strdec"
}
fun signnum(): Int {
val a = value.signum()
val b = divisor.signum()
if (a == b) {
if (a == 0)
return 0
return 1
}
return -1
}
fun serializeNBT(): ByteArrayTag {
return ByteArrayTag(toByteArray())
}
fun isNaN(): Boolean {
return divisor == BigInteger.ZERO
}
fun write(buff: FriendlyByteBuf) {
buff.writeByteArray(toByteArray())
}
fun max(vararg others: Fraction): Fraction {
var max = this
for (other in others) {
if (max < other) {
max = other
}
}
return max
}
fun min(vararg others: Fraction): Fraction {
var min = this
for (other in others) {
if (min > other) {
min = other
}
}
return min
}
fun moreThanZero(): Fraction {
if (signnum() >= 0)
return this
return ZERO
}
fun lessOrZero(): Fraction {
if (signnum() <= 0)
return this
return ZERO
}
companion object {
@JvmField
val ZERO = Fraction(BigInteger.ZERO)
@JvmField
val HALF = Fraction(BigInteger.ONE, BigInteger.TWO)
@JvmField
val THIRD = Fraction(BigInteger.ONE, BigInteger.valueOf(3))
@JvmField
val ONE = Fraction(BigInteger.ONE)
@JvmField
val TWO = Fraction(BigInteger.TWO)
@JvmField
val MINUS_ONE = Fraction(-1)
@JvmField
val TEN = Fraction(BigInteger.TEN)
@JvmStatic
fun read(buff: FriendlyByteBuf): Fraction {
return fromByteArray(buff.readByteArray())
}
@JvmStatic
fun fromByteArray(bytes: ByteArray): Fraction {
val bytesA = bytes.copyOfRange(1, 1 + bytes[0].toInt())
val offsetB = 1 + bytes[0].toInt()
val bytesB = bytes.copyOfRange(offsetB + 1, offsetB + 1 + bytes[offsetB].toInt())
return Fraction(BigInteger(bytesA), BigInteger(bytesB))
}
@JvmStatic
fun deserializeNBT(bytesTag: ByteArrayTag): Fraction {
val bytes = bytesTag.asByteArray
return fromByteArray(bytes)
}
// Преобразование строки в дробь с подавлением ошибок форматирования
@JvmStatic
fun fromString(str: String): Fraction {
try {
return Fraction(BigDecimal(str))
} catch(err: Throwable) {
return ZERO
}
}
@JvmStatic
fun deserializeNBT(tag: Tag?): Fraction {
if (tag == null)
return ZERO
if (tag is ByteArrayTag)
return deserializeNBT(tag)
if (tag is StringTag)
return try {
fromString(tag.asString)
} catch (anything: Throwable) {
ZERO
}
return ZERO
}
}
}

View File

@ -0,0 +1,51 @@
package ru.dbotthepony.mc.otm.menu.data
import net.minecraft.world.inventory.ContainerData
import ru.dbotthepony.mc.otm.core.Fraction
import ru.dbotthepony.mc.otm.network.NetworkHelper
class FractionDataContainer : ContainerData {
companion object {
const val NETWORK_PAYLOAD_SIZE = 32
}
private var _value: Fraction? = Fraction.ZERO
fun hasComputedValue(): Boolean {
return _value != null
}
var value: Fraction
get() {
if (_value != null)
return _value!!
_value = Fraction.fromByteArray(NetworkHelper.shortsToBytes(buffer))
return _value!!
}
set(value) {
_value = value
if (_value == null) {
buffer.fill(0)
return
}
NetworkHelper.bytesToShorts(_value!!.toByteArray()).copyInto(buffer)
}
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()
_value = null
}
override fun getCount(): Int {
return buffer.size
}
}

View File

@ -0,0 +1,121 @@
package ru.dbotthepony.mc.otm.tests
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test
import ru.dbotthepony.mc.otm.core.Fraction
import java.math.BigDecimal
import java.math.BigInteger
object FractionTests {
@Test
@DisplayName("Fraction declaration")
fun declaration() {
println("BigInteger 1/1 == ${Fraction(BigInteger.valueOf(1), BigInteger.valueOf(1))}")
println("BigDecimal 1 == ${Fraction(BigDecimal("1"))}")
var one = BigDecimal("1.00")
println("Unscaled ${one.unscaledValue()} with scale ${one.scale()} of $one")
println("BigDecimal $one == ${Fraction(one)}")
assert(Fraction(one).compareTo(Fraction.ONE) == 0)
one = BigDecimal("1.0000")
println("Unscaled ${one.unscaledValue()} with scale ${one.scale()} of $one")
println("BigDecimal $one == ${Fraction(one)}")
assert(Fraction(one).compareTo(Fraction.ONE) == 0)
println("1/2 == ${Fraction(1, 2)}")
println("-1/2 == ${Fraction(-1, 2)}")
println("1/-2 == ${Fraction(1, -2)}")
println("-1/-2 == ${Fraction(-1, -2)}")
println("canonical 1/2 == ${Fraction(1, 2).canonize()}")
println("canonical -1/2 == ${Fraction(-1, 2).canonize()}")
println("canonical 1/-2 == ${Fraction(1, -2).canonize()}")
println("canonical -1/-2 == ${Fraction(-1, -2).canonize()}")
}
@Test
@DisplayName("Fraction comparison")
fun equality() {
assert(Fraction(1).compareTo(Fraction.ONE) == 0)
assert(Fraction(1.0).compareTo(Fraction.ONE) == 0)
assert(Fraction(1.0F).compareTo(Fraction.ONE) == 0)
assert(Fraction(1, 1).compareTo(Fraction.ONE) == 0)
assert(Fraction(1.0, 1.0).compareTo(Fraction.ONE) == 0)
assert(Fraction(1.0F, 1.0F).compareTo(Fraction.ONE) == 0)
assert(Fraction(1, 2).compareTo(Fraction.HALF) == 0)
assert(Fraction(1.0, 2.0).compareTo(Fraction.HALF) == 0)
assert(Fraction(1.0F, 2.0F).compareTo(Fraction.HALF) == 0)
assert(Fraction(-1, -2).compareTo(Fraction.HALF) == 0)
assert(Fraction(-1.0, -2.0).compareTo(Fraction.HALF) == 0)
assert(Fraction(-1.0F, -2.0F).compareTo(Fraction.HALF) == 0)
assert(Fraction(-1, 2).compareTo(Fraction.HALF) != 0)
assert(Fraction(-1.0, 2.0).compareTo(Fraction.HALF) != 0)
assert(Fraction(-1.0F, 2.0F).compareTo(Fraction.HALF) != 0)
assert(Fraction(1, 2).compareTo(Fraction.ONE) != 0)
assert(Fraction(1.0, 2.0).compareTo(Fraction.ONE) != 0)
assert(Fraction(1.0F, 2.0F).compareTo(Fraction.ONE) != 0)
assert(Fraction(2).compareTo(Fraction.TWO) == 0)
assert(Fraction(2.0).compareTo(Fraction.TWO) == 0)
assert(Fraction(2.0F).compareTo(Fraction.TWO) == 0)
assert(Fraction(2, 1).compareTo(Fraction.TWO) == 0)
assert(Fraction(2.0, 1.0).compareTo(Fraction.TWO) == 0)
assert(Fraction(2.0F, 1.0F).compareTo(Fraction.TWO) == 0)
assert(Fraction(4, 3) > Fraction(5, 4))
assert(Fraction(4, 4) < Fraction(5, 4))
assert(Fraction(-15, 2) < Fraction(2, 4))
assert(Fraction(-1, 2) < Fraction(2, 4))
assert(Fraction(-15, -2) > Fraction(2, 4))
assert(Fraction(-15, -2) > Fraction(-2, -4))
assert(Fraction(-15, 2) < Fraction(-2, -4))
}
@Test
@DisplayName("Fraction math")
fun math() {
assert((Fraction(1) / Fraction(1)) == Fraction(1))
assert((Fraction(2) / Fraction(1)) == Fraction(2, 1))
assert((Fraction(2) / Fraction(2)) == Fraction(1))
assert((Fraction(4, 3) / Fraction(5, 4)) == (Fraction(4, 3) * Fraction(4, 5)))
assert((Fraction(4, 3) + Fraction(5, 4)) == Fraction(31, 12))
}
@Test
@DisplayName("Fraction serialization test")
fun serialization() {
var value = Fraction(1)
var serialized = value.serializeNBT()
assert(value.compareTo(Fraction.deserializeNBT(serialized)) == 0)
value = Fraction(4, 2)
serialized = value.serializeNBT()
assert(value.compareTo(Fraction.deserializeNBT(serialized)) == 0)
value = Fraction(-4, 2)
serialized = value.serializeNBT()
assert(value.compareTo(Fraction.deserializeNBT(serialized)) == 0)
value = Fraction(-4, -18)
serialized = value.serializeNBT()
assert(value.compareTo(Fraction.deserializeNBT(serialized)) == 0)
value = Fraction("3407203485237459085739045724837543569234750927348902374590872345", "-57777772398450982374590230984532984")
serialized = value.serializeNBT()
assert(value.compareTo(Fraction.deserializeNBT(serialized)) == 0)
}
}

View File

@ -0,0 +1,52 @@
package ru.dbotthepony.mc.otm.tests
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test
import ru.dbotthepony.mc.otm.core.Fraction
import ru.dbotthepony.mc.otm.menu.data.FractionDataContainer
import ru.dbotthepony.mc.otm.network.NetworkHelper
import kotlin.experimental.and
object NetworkingTests {
@Test
@DisplayName("Test FractionDataContainer store/load")
fun fraction() {
val container = FractionDataContainer()
var frac = Fraction(18, 4)
container.value = frac
container[1] = container[1]
assert(!container.hasComputedValue())
assert(container.value.compareTo(frac) == 0) { "${container.value} != $frac" }
frac = Fraction(2_000_000, 1)
container.value = frac
container[1] = container[1]
assert(!container.hasComputedValue())
assert(container.value.compareTo(frac) == 0) { "${container.value} != $frac" }
}
@Test
@DisplayName("Test NetworkHelper byte/short transition")
fun networkHelper() {
var bytes = byteArrayOf(7, 8, -10)
var shorts = NetworkHelper.bytesToShorts(bytes)
assert(shorts.size == 2) { "Shorts array is not size of 2, but size of ${shorts.size}" }
assert((shorts[0].toInt() and 0xFF).toByte() == bytes[0]) { "${shorts[0] and 0xFF} != ${bytes[0]} ${shorts.joinToString()}" }
assert(((shorts[0].toInt() and 0xFF00) shr 8).toByte() == bytes[1]) { "${(shorts[0].toInt() and 0xFF00) shr 8} != ${bytes[1]} ${shorts.joinToString()}" }
assert((shorts[1].toInt() and 0xFF).toByte() == bytes[2]) { "${shorts[1] and 0xFF} != ${bytes[2]} ${shorts.joinToString()}" }
bytes = byteArrayOf(7, 8, -10, 4)
shorts = NetworkHelper.bytesToShorts(bytes)
assert(shorts.size == 2) { "Shorts array is not size of 2, but size of ${shorts.size}" }
assert((shorts[0].toInt() and 0xFF).toByte() == bytes[0]) { "${shorts[0] and 0xFF} != ${bytes[0]} ${shorts.joinToString()}" }
assert(((shorts[0].toInt() and 0xFF00) shr 8).toByte() == bytes[1]) { "${(shorts[0].toInt() and 0xFF00) shr 8} != ${bytes[1]} ${shorts.joinToString()}" }
assert((shorts[1].toInt() and 0xFF).toByte() == bytes[2]) { "${shorts[1] and 0xFF} != ${bytes[2]} ${shorts.joinToString()}" }
assert(((shorts[1].toInt() and 0xFF00) shr 8).toByte() == bytes[3]) { "${(shorts[1].toInt() and 0xFF00) shr 8} != ${bytes[3]} ${shorts.joinToString()}" }
}
}