Compare commits

...

7 Commits

32 changed files with 384 additions and 254 deletions

View File

@ -631,6 +631,8 @@ private fun blocks(provider: MatteryLanguageProvider) {
add(MBlocks.ENERGY_COUNTER[null]!!, "switch", "Switch input facing")
add(MBlocks.ENERGY_COUNTER[null]!!, "limit", "I/O Limit. -1 means no limit")
add(MBlocks.ENERGY_COUNTER[null]!!, "display_this", "Display this information on block's screen")
add(MBlocks.ENERGY_COUNTER[null]!!, "do_pull", "Pull energy from input side and push to output")
add(MBlocks.ENERGY_COUNTER[null]!!, "dont_pull", "Don't pull energy")
addBlock(MBlocks.CHEMICAL_GENERATOR.values, "Chemical Generator")
addBlock(MBlocks.CHEMICAL_GENERATOR.values, "desc", "Generates power by burning solid fuels")

View File

@ -635,6 +635,8 @@ private fun blocks(provider: MatteryLanguageProvider) {
add(MBlocks.ENERGY_COUNTER[null]!!, "switch", "Сменить сторону входа")
add(MBlocks.ENERGY_COUNTER[null]!!, "limit", "Лимит ввода/вывода. -1 для отключения лимитов")
add(MBlocks.ENERGY_COUNTER[null]!!, "display_this", "Отображать эти данные на экране блока")
add(MBlocks.ENERGY_COUNTER[null]!!, "do_pull", "Забирать энергию на входе и выталкивать её на выходе")
add(MBlocks.ENERGY_COUNTER[null]!!, "dont_pull", "Не забирать энергию на входе")
addBlock(MBlocks.CHEMICAL_GENERATOR.values, "Химический генератор")
addBlock(MBlocks.CHEMICAL_GENERATOR.values, "desc", "Генерирует энергию сжигая твёрдое топливо")

View File

@ -24,6 +24,7 @@ import ru.dbotthepony.mc.otm.config.MachinesConfig
import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.container.HandlerFilter
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.nextDecimal
import ru.dbotthepony.mc.otm.core.otmRandom
import ru.dbotthepony.mc.otm.graph.matter.MatterGraph
import ru.dbotthepony.mc.otm.item.matter.MatterDustItem
@ -137,7 +138,7 @@ class MatterRecyclerBlockEntity(blockPos: BlockPos, blockState: BlockState)
else if (matter.receiveMatter(toReceive, true) != toReceive)
return status.noMatter()
matter.receiveMatter(toReceive * 0.4 + level!!.otmRandom.nextDouble() * 0.6, false)
matter.receiveMatter(toReceive * level!!.otmRandom.nextDecimal(BASE_RECEIVE, Decimal.ONE), false)
job.totalMatter -= toReceive
}
@ -151,4 +152,8 @@ class MatterRecyclerBlockEntity(blockPos: BlockPos, blockState: BlockState)
matter.extractMatter(received, false)
}
}
companion object {
private val BASE_RECEIVE = Decimal("0.4")
}
}

View File

@ -22,7 +22,7 @@ import ru.dbotthepony.mc.otm.core.chart.DecimalHistoryChart
import ru.dbotthepony.mc.otm.core.math.BlockRotation
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.math.RelativeSide
import ru.dbotthepony.mc.otm.core.math.getDecimal
import ru.dbotthepony.mc.otm.core.nbt.getDecimal
import ru.dbotthepony.mc.otm.core.nbt.mapPresent
import ru.dbotthepony.mc.otm.core.nbt.set
import ru.dbotthepony.mc.otm.core.util.countingLazy
@ -31,6 +31,7 @@ import ru.dbotthepony.mc.otm.registry.game.MBlockEntities
class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : MatteryDeviceBlockEntity(MBlockEntities.ENERGY_COUNTER, p_155229_, p_155230_) {
var passed by syncher.decimal()
var pullEnergyFromInput by syncher.boolean()
override val blockRotation: BlockRotation by countingLazy(blockStateChangesCounter) {
BlockRotation.of(blockState[EnergyCounterBlock.INPUT_DIRECTION])
@ -86,10 +87,8 @@ class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mat
savetables.stateful(::history1h)
savetables.stateful(::history6h)
savetables.stateful(::history24h)
}
override fun saveLevel(nbt: CompoundTag, registry: HolderLookup.Provider) {
super.saveLevel(nbt, registry)
savetablesConfig.bool(::pullEnergyFromInput)
}
override fun loadAdditional(nbt: CompoundTag, registry: HolderLookup.Provider) {
@ -267,6 +266,14 @@ class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mat
override fun tick() {
super.tick()
if (pullEnergyFromInput) {
val input = inputCapability
val output = outputCapability
if (input != null && output != null)
thisTick += moveEnergy(source = input, destination = output, simulate = false)
}
lastTick = thisTick
charts.forEach { it.add(thisTick) }
thisTick = Decimal.ZERO

View File

@ -15,7 +15,7 @@ import ru.dbotthepony.mc.otm.capability.FlowDirection
import ru.dbotthepony.mc.otm.capability.extractEnergy
import ru.dbotthepony.mc.otm.capability.receiveEnergy
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.math.getDecimal
import ru.dbotthepony.mc.otm.core.nbt.getDecimal
import ru.dbotthepony.mc.otm.core.nbt.set
import ru.dbotthepony.mc.otm.registry.StatNames
import ru.dbotthepony.mc.otm.triggers.AndroidBatteryTrigger

View File

@ -111,7 +111,19 @@ class EnergyCounterScreen(menu: EnergyCounterMenu, inventory: Inventory, title:
}
}
makeDeviceControls(this, frame, redstoneConfig = menu.redstone)
val controls = makeDeviceControls(this, frame, redstoneConfig = menu.redstone)
controls.addButton(
BooleanButtonPanel.square18(
this,
controls,
menu.pullEnergyFromInput,
iconActive = Widgets18.LEFT_CONTROLS.push,
iconInactive = Widgets18.LEFT_CONTROLS.output,
tooltipActive = TranslatableComponent("block.overdrive_that_matters.energy_counter.do_pull"),
tooltipInactive = TranslatableComponent("block.overdrive_that_matters.energy_counter.dont_pull")
)
)
return frame
}

View File

@ -13,8 +13,8 @@ import ru.dbotthepony.mc.otm.compat.jade.JadeUids
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.core.getCapability
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.math.getDecimal
import ru.dbotthepony.mc.otm.core.math.putDecimal
import ru.dbotthepony.mc.otm.core.nbt.getDecimal
import ru.dbotthepony.mc.otm.core.nbt.putDecimal
import ru.dbotthepony.mc.otm.core.util.formatMatter
import snownee.jade.api.BlockAccessor
import snownee.jade.api.IBlockComponentProvider

View File

@ -13,8 +13,8 @@ import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.kommons.math.RGBAColor
import ru.dbotthepony.mc.otm.capability.IProfiledStorage
import ru.dbotthepony.mc.otm.core.getCapability
import ru.dbotthepony.mc.otm.core.math.getDecimal
import ru.dbotthepony.mc.otm.core.math.putDecimal
import ru.dbotthepony.mc.otm.core.nbt.getDecimal
import ru.dbotthepony.mc.otm.core.nbt.putDecimal
import ru.dbotthepony.mc.otm.core.util.formatPower
import snownee.jade.api.*
import snownee.jade.api.config.IPluginConfig

View File

@ -7,7 +7,6 @@ import ru.dbotthepony.kommons.util.Delegate
import ru.dbotthepony.kommons.util.getValue
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.math.defineDecimal
import ru.dbotthepony.mc.otm.core.util.WriteOnce
abstract class AbstractConfig(private val configName: String, private val type: ModConfig.Type = ModConfig.Type.SERVER) {

View File

@ -3,7 +3,6 @@ package ru.dbotthepony.mc.otm.config
import ru.dbotthepony.kommons.util.getValue
import ru.dbotthepony.kommons.util.setValue
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.math.defineDecimal
object CablesConfig : AbstractConfig("cables") {
enum class E(throughput: Decimal) {

View File

@ -0,0 +1,58 @@
package ru.dbotthepony.mc.otm.config
import net.neoforged.neoforge.common.ModConfigSpec
import ru.dbotthepony.mc.otm.core.math.Decimal
class DecimalConfigValue(
parent: ModConfigSpec.ConfigValue<String>,
val minimum: Decimal? = null,
val maximum: Decimal? = null,
) : ObservedConfigValue<Decimal>(parent) {
override fun fromString(value: String): Decimal? {
try {
val parsed = Decimal(value)
if (minimum != null && minimum > parsed) {
return minimum
} else if (maximum != null && maximum < parsed) {
return maximum
}
return parsed
} catch (err: java.lang.NumberFormatException) {
return null
}
}
override fun toString(value: Decimal): Pair<String, Decimal> {
if (minimum != null && minimum > value) {
return minimum.toString() to minimum
} else if (maximum != null && maximum < value) {
return maximum.toString() to maximum
}
return value.toString() to value
}
}
private fun ModConfigSpec.Builder.commentRange(minimum: Decimal?, maximum: Decimal?) {
if (minimum != null && maximum != null) {
comment("Range: $minimum ~ $maximum")
} else if (minimum != null) {
comment("Range: >= $minimum")
} else if (maximum != null) {
comment("Range: <= $maximum")
}
}
fun ModConfigSpec.Builder.defineDecimal(path: String, defaultValue: Decimal, minimum: Decimal? = null, maximum: Decimal? = null): DecimalConfigValue {
commentRange(minimum, maximum)
comment("Default: $defaultValue")
return DecimalConfigValue(define(path, defaultValue.toString()), minimum, maximum)
}
fun ModConfigSpec.Builder.defineDecimal(path: List<String>, defaultValue: Decimal, minimum: Decimal? = null, maximum: Decimal? = null): DecimalConfigValue {
commentRange(minimum, maximum)
comment("Default: $defaultValue")
return DecimalConfigValue(define(path, defaultValue.toString()), minimum, maximum)
}

View File

@ -2,7 +2,6 @@ package ru.dbotthepony.mc.otm.config
import ru.dbotthepony.kommons.util.getValue
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.math.defineDecimal
object ExopackConfig : AbstractConfig("exopack") {
val ENERGY_CAPACITY by builder

View File

@ -2,7 +2,6 @@ package ru.dbotthepony.mc.otm.config
import ru.dbotthepony.kommons.util.getValue
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.math.defineDecimal
import ru.dbotthepony.mc.otm.registry.MNames
object ItemsConfig : AbstractConfig("items") {

View File

@ -2,7 +2,6 @@ package ru.dbotthepony.mc.otm.config
import ru.dbotthepony.kommons.util.getValue
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.math.defineDecimal
import ru.dbotthepony.mc.otm.registry.MNames
object MachinesConfig : AbstractConfig("machines") {

View File

@ -2,7 +2,6 @@ package ru.dbotthepony.mc.otm.config
import ru.dbotthepony.kommons.util.getValue
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.math.defineDecimal
object PlayerConfig : AbstractConfig("player") {
init {

View File

@ -2,7 +2,6 @@ package ru.dbotthepony.mc.otm.config
import ru.dbotthepony.kommons.util.getValue
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.math.defineDecimal
object ServerConfig : AbstractConfig("misc") {
val LABORATORY_LAMP_LIGHT_LENGTH: Int by builder.comment("In blocks").defineInRange("LABORATORY_LAMP_LIGHT_LENGTH", 6, 1, 128)

View File

@ -10,7 +10,6 @@ import com.google.common.collect.ImmutableSet
import com.google.gson.JsonElement
import com.google.gson.JsonObject
import com.google.gson.JsonPrimitive
import it.unimi.dsi.fastutil.ints.IntList
import it.unimi.dsi.fastutil.objects.ObjectComparators
import net.minecraft.Util
import net.minecraft.core.BlockPos
@ -29,7 +28,6 @@ import net.minecraft.network.chat.contents.TranslatableContents
import net.minecraft.resources.ResourceKey
import net.minecraft.resources.ResourceLocation
import net.minecraft.tags.TagKey
import net.minecraft.util.RandomSource
import net.minecraft.world.entity.Entity
import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack
@ -65,13 +63,10 @@ import java.util.concurrent.Callable
import java.util.concurrent.Future
import java.util.function.Consumer
import java.util.function.Supplier
import java.util.random.RandomGenerator
import java.util.stream.Stream
import java.util.stream.StreamSupport
import kotlin.NoSuchElementException
import kotlin.jvm.optionals.getOrNull
import kotlin.math.ln
import kotlin.math.sqrt
import kotlin.reflect.KProperty
operator fun RecipeInput.get(index: Int): ItemStack = getItem(index)
@ -189,43 +184,6 @@ fun <T : Enum<T>> T.prev(values: Array<out T>): T {
return values[next]
}
fun IntArray.shuffle(random: RandomSource): IntArray {
for (i in lastIndex downTo 1) {
val j = random.nextInt(i + 1)
val copy = this[i]
this[i] = this[j]
this[j] = copy
}
return this
}
fun <L : IntList> L.shuffle(random: RandomSource): L {
for (i in lastIndex downTo 1) {
val j = random.nextInt(i + 1)
set(j, set(i, getInt(j)))
}
return this
}
fun <T, L : MutableList<T>> L.shuffle(random: RandomSource): L {
Util.shuffle(this, random)
return this
}
fun <T> List<T>.random(random: RandomGenerator): T {
if (isEmpty())
throw NoSuchElementException("This list is empty")
return get(random.nextInt(size))
}
fun <T> List<T>.random(random: RandomSource): T {
if (isEmpty())
throw NoSuchElementException("This list is empty")
return get(random.nextInt(size))
}
inline fun <T : Any> immutableList(size: Int, initializer: (index: Int) -> T): ImmutableList<T> {
require(size >= 0) { "Invalid list size $size" }
@ -635,58 +593,3 @@ infix fun FluidStack.isNotSameAs(other: FluidStack): Boolean {
return !FluidStack.isSameFluidSameComponents(this, other) && amount == other.amount
}
data class DoublePair(val first: Double, val second: Double)
fun RandomSource.nextUUID(): UUID {
return UUID(nextLong(), nextLong())
}
// normal distribution via Marsaglia polar method
fun RandomGenerator.nextNormalDoubles(stddev: Double, mean: Double): DoublePair {
var rand1: Double
var rand2: Double
var distSqr: Double
do {
rand1 = 2.0 * nextDouble() - 1.0
rand2 = 2.0 * nextDouble() - 1.0
distSqr = rand1 * rand1 + rand2 * rand2
} while (distSqr >= 1.0 || distSqr == 0.0)
val mapping = sqrt(-2.0 * ln(distSqr) / distSqr)
return DoublePair(
rand1 * mapping * stddev + mean,
rand2 * mapping * stddev + mean
)
}
// All Mojang's random sources use MarsagliaPolarGaussian for generating normal distributed doubles
fun RandomSource.nextNormalDoubles(stddev: Double, mean: Double): DoublePair {
return DoublePair(
nextGaussian() * stddev + mean,
nextGaussian() * stddev + mean
)
}
fun RandomSource.nextNormalDouble(stddev: Double, mean: Double): Double {
return nextGaussian() * stddev + mean
}
fun RandomSource.nextFloat(min: Float, max: Float): Float {
if (this is RandomGenerator)
return nextFloat(min, max)
require(max >= min) { "Min is bigger than max: $min vs $max" }
if (min == max) return min
return min + nextFloat() * (max - min)
}
fun RandomSource.nextDouble(min: Double, max: Double): Double {
if (this is RandomGenerator)
return nextDouble(min, max)
require(max >= min) { "Min is bigger than max: $min vs $max" }
if (min == max) return min
return min + nextDouble() * (max - min)
}

View File

@ -0,0 +1,221 @@
package ru.dbotthepony.mc.otm.core
import it.unimi.dsi.fastutil.ints.IntList
import net.minecraft.Util
import net.minecraft.util.RandomSource
import ru.dbotthepony.mc.otm.core.math.Decimal
import java.math.BigInteger
import java.util.*
import java.util.random.RandomGenerator
import kotlin.experimental.and
import kotlin.math.ln
import kotlin.math.sqrt
data class DoublePair(val first: Double, val second: Double)
fun RandomSource.nextUUID(): UUID {
return UUID(nextLong(), nextLong())
}
// normal distribution via Marsaglia polar method
fun RandomGenerator.nextNormalDoubles(stddev: Double, mean: Double): DoublePair {
var rand1: Double
var rand2: Double
var distSqr: Double
do {
rand1 = 2.0 * nextDouble() - 1.0
rand2 = 2.0 * nextDouble() - 1.0
distSqr = rand1 * rand1 + rand2 * rand2
} while (distSqr >= 1.0 || distSqr == 0.0)
val mapping = sqrt(-2.0 * ln(distSqr) / distSqr)
return DoublePair(
rand1 * mapping * stddev + mean,
rand2 * mapping * stddev + mean
)
}
// All Mojang's random sources use MarsagliaPolarGaussian for generating normal distributed doubles
fun RandomSource.nextNormalDoubles(stddev: Double, mean: Double): DoublePair {
return DoublePair(
nextGaussian() * stddev + mean,
nextGaussian() * stddev + mean
)
}
fun RandomSource.nextNormalDouble(stddev: Double, mean: Double): Double {
return nextGaussian() * stddev + mean
}
fun RandomSource.nextFloat(min: Float, max: Float): Float {
if (this is RandomGenerator)
return nextFloat(min, max)
require(max >= min) { "Min is bigger than max: $min vs $max" }
if (min == max) return min
return min + nextFloat() * (max - min)
}
fun RandomSource.nextDouble(min: Double, max: Double): Double {
if (this is RandomGenerator)
return nextDouble(min, max)
require(max >= min) { "Min is bigger than max: $min vs $max" }
if (min == max) return min
return min + nextDouble() * (max - min)
}
fun IntArray.shuffle(random: RandomSource): IntArray {
for (i in lastIndex downTo 1) {
val j = random.nextInt(i + 1)
val copy = this[i]
this[i] = this[j]
this[j] = copy
}
return this
}
fun <L : IntList> L.shuffle(random: RandomSource): L {
for (i in lastIndex downTo 1) {
val j = random.nextInt(i + 1)
set(j, set(i, getInt(j)))
}
return this
}
fun <T, L : MutableList<T>> L.shuffle(random: RandomSource): L {
Util.shuffle(this, random)
return this
}
fun <T> List<T>.random(random: RandomGenerator): T {
if (isEmpty())
throw NoSuchElementException("This list is empty")
return get(random.nextInt(size))
}
fun <T> List<T>.random(random: RandomSource): T {
if (isEmpty())
throw NoSuchElementException("This list is empty")
return get(random.nextInt(size))
}
class RandomByteSource(private val source: RandomSource) {
private val bytes = ByteArray(8)
private var i = 7
fun next(): Byte {
if (++i == 8) {
i = 0
var generate = source.nextLong()
for (i in 0 .. 7) {
bytes[i] = generate.toByte()
generate = generate ushr 8
}
}
return bytes[i]
}
fun next(bound: Int): Byte {
require(bound > 0) { "Bound must be positive" }
val m = bound - 1
var r = next().toInt().and(0xFF)
if (bound and m == 0) {
r = r and m
} else {
var u = r ushr 1
while (true) {
r = u % bound
if (u + m - r < 0) {
u = next().toInt().and(0xFF).ushr(1)
} else {
break
}
}
}
return r.toByte()
}
fun next(bytes: ByteArray) {
for (i in bytes.indices) {
bytes[i] = next()
}
}
}
/**
* Uniformely distributed [Decimal] value on [0,[bound]) range
*
* If [round] is `true`, will only return integers
*/
fun RandomSource.nextDecimal(bound: Decimal, round: Boolean = false): Decimal {
if (round)
require(bound > Decimal.ZERO) { "Bound must be positive, $bound given" }
else
require(bound >= Decimal.ONE) { "Bound must be 1 or bigger, $bound given" }
require(bound.isFinite) { "Bound must be finite" }
val bytes = RandomByteSource(this)
if (round) {
val thisBytes = bound.whole.toByteArray()
val generateBytes = ByteArray(thisBytes.size)
bytes.next(generateBytes)
generateBytes[0] = generateBytes[0].and(127)
if (generateBytes[0] >= thisBytes[0]) {
generateBytes[0] = bytes.next(thisBytes[0].toInt().and(127))
}
return Decimal(BigInteger(generateBytes))
} else {
val thisBytes = bound.mag.toByteArray()
val generateBytes = ByteArray(thisBytes.size)
bytes.next(generateBytes)
generateBytes[0] = generateBytes[0].and(127)
if (generateBytes[0] >= thisBytes[0]) {
generateBytes[0] = bytes.next(thisBytes[0].toInt().and(127))
}
return Decimal.raw(BigInteger(generateBytes))
}
}
/**
* Uniformely distributed [Decimal] value on [[origin],[bound]) range
*
* If [round] is `true`, will only return integers
*/
fun RandomSource.nextDecimal(origin: Decimal, bound: Decimal, round: Boolean = false): Decimal {
require(origin < bound) { "Origin must be less than bound: $origin < $bound" }
require(origin.isFinite) { "Origin must be finite" }
require(bound.isFinite) { "Bound must be finite" }
return origin + nextDecimal(bound - origin, round)
}
/**
* Uniformely distributed [Decimal] value on [0,1) range
*/
fun RandomSource.nextDecimal(): Decimal {
return nextDecimal(Decimal.ZERO, Decimal.ONE)
}
fun RandomSource.nextVariance(value: Decimal, round: Boolean = false): Decimal {
return nextDecimal(-value / 2, value / 2, round)
}

View File

@ -1,17 +1,9 @@
package ru.dbotthepony.mc.otm.core.math
import net.minecraft.nbt.ByteArrayTag
import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.StringTag
import net.minecraft.nbt.Tag
import net.minecraft.network.FriendlyByteBuf
import net.minecraft.util.RandomSource
import net.neoforged.neoforge.common.ModConfigSpec
import ru.dbotthepony.mc.otm.config.ObservedConfigValue
import ru.dbotthepony.mc.otm.core.util.readVarIntLE
import ru.dbotthepony.mc.otm.core.util.writeVarIntLE
import java.io.InputStream
import java.io.OutputStream
import java.math.BigDecimal
import java.math.BigInteger
import java.math.MathContext
@ -47,6 +39,8 @@ sealed class Decimal : Number(), Comparable<Decimal> {
*/
abstract val fractional: BigInteger
abstract internal val mag: BigInteger
/**
* *Signed* normalized (-1,1) fractional part of this Decimal, as [Float]
*/
@ -189,7 +183,7 @@ sealed class Decimal : Number(), Comparable<Decimal> {
return toBigDecmial().divide(divisor.toBigDecmial(), PERCENTAGE_CONTEXT).toFloat()
}
private class Regular(val mag: BigInteger, marker: Nothing?) : Decimal() {
private class Regular(override val mag: BigInteger, marker: Nothing?) : Decimal() {
constructor(value: BigInteger) : this(value * PRECISION_POW_BI, null)
constructor(value: BigDecimal) : this(value.setScale(PRECISION, RoundingMode.HALF_UP).unscaledValue(), null)
constructor(value: Float) : this(BigDecimal.valueOf(value.toDouble()))
@ -711,6 +705,9 @@ sealed class Decimal : Number(), Comparable<Decimal> {
}
private object PositiveInfinity : Decimal() {
override val mag: BigInteger
get() = throw UnsupportedOperationException()
private fun readResolve(): Any = PositiveInfinity
override val isInfinite: Boolean
@ -960,6 +957,9 @@ sealed class Decimal : Number(), Comparable<Decimal> {
}
private object NegativeInfinity : Decimal() {
override val mag: BigInteger
get() = throw UnsupportedOperationException()
private fun readResolve(): Any = NegativeInfinity
override val isInfinite: Boolean
@ -1203,6 +1203,9 @@ sealed class Decimal : Number(), Comparable<Decimal> {
}
private object Zero : Decimal() {
override val mag: BigInteger
get() = BigInteger.ZERO
private fun readResolve(): Any = Zero
override val isInfinite: Boolean
@ -1603,28 +1606,6 @@ sealed class Decimal : Number(), Comparable<Decimal> {
}
}
fun FriendlyByteBuf.readDecimal() = Decimal.read(this)
fun FriendlyByteBuf.writeDecimal(value: Decimal) = value.write(this)
fun InputStream.readDecimal(): Decimal {
val size = readVarIntLE()
require(size >= 0) { "Negative payload size: $size" }
val bytes = ByteArray(size)
read(bytes)
return Decimal.fromByteArray(bytes)
}
fun OutputStream.writeDecimal(value: Decimal) {
val bytes = value.toByteArray()
writeVarIntLE(bytes.size)
write(bytes)
}
fun CompoundTag.getDecimal(key: String) = Decimal.deserializeNBT(this[key])
fun CompoundTag.putDecimal(key: String, value: Decimal) = put(key, value.serializeNBT())
operator fun CompoundTag.set(key: String, value: Decimal) = putDecimal(key, value)
fun Float.toDecimal() = Decimal(this)
fun Double.toDecimal() = Decimal(this)
fun Int.toDecimal() = Decimal(this)
@ -1633,70 +1614,3 @@ fun Short.toDecimal() = Decimal(this)
fun Long.toDecimal() = Decimal(this)
fun Decimal.toDecimal() = this
class DecimalConfigValue(
parent: ModConfigSpec.ConfigValue<String>,
val minimum: Decimal? = null,
val maximum: Decimal? = null,
) : ObservedConfigValue<Decimal>(parent) {
override fun fromString(value: String): Decimal? {
try {
val parsed = Decimal(value)
if (minimum != null && minimum > parsed) {
return minimum
} else if (maximum != null && maximum < parsed) {
return maximum
}
return parsed
} catch (err: java.lang.NumberFormatException) {
return null
}
}
override fun toString(value: Decimal): Pair<String, Decimal> {
if (minimum != null && minimum > value) {
return minimum.toString() to minimum
} else if (maximum != null && maximum < value) {
return maximum.toString() to maximum
}
return value.toString() to value
}
}
private fun ModConfigSpec.Builder.commentRange(minimum: Decimal?, maximum: Decimal?) {
if (minimum != null && maximum != null) {
comment("Range: $minimum ~ $maximum")
} else if (minimum != null) {
comment("Range: >= $minimum")
} else if (maximum != null) {
comment("Range: <= $maximum")
}
}
fun ModConfigSpec.Builder.defineDecimal(path: String, defaultValue: Decimal, minimum: Decimal? = null, maximum: Decimal? = null): DecimalConfigValue {
commentRange(minimum, maximum)
comment("Default: $defaultValue")
return DecimalConfigValue(define(path, defaultValue.toString()), minimum, maximum)
}
fun ModConfigSpec.Builder.defineDecimal(path: List<String>, defaultValue: Decimal, minimum: Decimal? = null, maximum: Decimal? = null): DecimalConfigValue {
commentRange(minimum, maximum)
comment("Default: $defaultValue")
return DecimalConfigValue(define(path, defaultValue.toString()), minimum, maximum)
}
fun RandomSource.nextDecimal(min: Decimal, max: Decimal, round: Boolean = false): Decimal {
val value = nextDouble()
return if (round) {
Decimal((min + (max - min) * value).whole)
} else {
min + (max - min) * value
}
}
fun RandomSource.nextVariance(value: Decimal, round: Boolean = false): Decimal {
return nextDecimal(-value / 2, value / 2, round)
}

View File

@ -20,6 +20,7 @@ import net.minecraft.nbt.ShortTag
import net.minecraft.nbt.StringTag
import net.minecraft.nbt.Tag
import net.minecraft.world.item.ItemStack
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.util.readBinaryJson
import ru.dbotthepony.mc.otm.core.util.writeBinaryJson
import java.util.UUID
@ -115,3 +116,7 @@ fun CompoundTag.getJson(key: String, sizeLimit: NbtAccounter = NbtAccounter(1 sh
fun CompoundTag.getBoolean(index: String, orElse: Boolean): Boolean {
return (this[index] as? NumericTag)?.asInt?.let { it > 0 } ?: orElse
}
fun CompoundTag.getDecimal(key: String) = Decimal.deserializeNBT(this[key])
fun CompoundTag.putDecimal(key: String, value: Decimal) = put(key, value.serializeNBT())
operator fun CompoundTag.set(key: String, value: Decimal) = putDecimal(key, value)

View File

@ -5,12 +5,14 @@ import net.minecraft.core.registries.BuiltInRegistries
import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.NbtAccounter
import net.minecraft.nbt.NbtIo
import net.minecraft.network.FriendlyByteBuf
import net.minecraft.network.chat.Component
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.material.Fluid
import net.neoforged.neoforge.fluids.FluidStack
import ru.dbotthepony.mc.otm.core.math.Decimal
import java.io.*
import java.math.BigDecimal
import java.math.BigInteger
@ -238,3 +240,20 @@ fun OutputStream.writeBinaryString(input: String) {
writeVarIntLE(bytes.size)
write(bytes)
}
fun FriendlyByteBuf.readDecimal() = Decimal.read(this)
fun FriendlyByteBuf.writeDecimal(value: Decimal) = value.write(this)
fun InputStream.readDecimal(): Decimal {
val size = readVarIntLE()
require(size >= 0) { "Negative payload size: $size" }
val bytes = ByteArray(size)
read(bytes)
return Decimal.fromByteArray(bytes)
}
fun OutputStream.writeDecimal(value: Decimal) {
val bytes = value.toByteArray()
writeVarIntLE(bytes.size)
write(bytes)
}

View File

@ -38,8 +38,8 @@ import ru.dbotthepony.mc.otm.core.ResourceLocation
import ru.dbotthepony.mc.otm.core.TextComponent
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.math.readDecimal
import ru.dbotthepony.mc.otm.core.math.writeDecimal
import ru.dbotthepony.mc.otm.core.util.readDecimal
import ru.dbotthepony.mc.otm.core.util.writeDecimal
import ru.dbotthepony.mc.otm.core.readBlockType
import ru.dbotthepony.mc.otm.core.registryName
import ru.dbotthepony.mc.otm.core.util.formatPower

View File

@ -8,7 +8,7 @@ import net.minecraft.util.RandomSource
import net.neoforged.bus.api.IEventBus
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.math.nextDecimal
import ru.dbotthepony.mc.otm.core.nextDecimal
import ru.dbotthepony.mc.otm.data.codec.DecimalCodec
import ru.dbotthepony.mc.otm.registry.MBuiltInRegistries
import ru.dbotthepony.mc.otm.registry.MDeferredRegister

View File

@ -38,11 +38,10 @@ import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.core.collect.filter
import ru.dbotthepony.mc.otm.core.isNotEmpty
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.math.getDecimal
import ru.dbotthepony.mc.otm.core.math.readDecimal
import ru.dbotthepony.mc.otm.core.math.set
import ru.dbotthepony.mc.otm.core.math.writeDecimal
import ru.dbotthepony.mc.otm.core.nbt.getDecimal
import ru.dbotthepony.mc.otm.core.util.readDecimal
import ru.dbotthepony.mc.otm.core.nbt.set
import ru.dbotthepony.mc.otm.core.util.writeDecimal
import ru.dbotthepony.mc.otm.core.nextUUID
import ru.dbotthepony.mc.otm.core.util.formatPower
import ru.dbotthepony.mc.otm.isClientThread

View File

@ -29,9 +29,9 @@ import ru.dbotthepony.mc.otm.player.matteryPlayer
import ru.dbotthepony.mc.otm.core.ResourceLocation
import ru.dbotthepony.mc.otm.core.damageType
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.math.DecimalConfigValue
import ru.dbotthepony.mc.otm.core.math.defineDecimal
import ru.dbotthepony.mc.otm.core.math.nextVariance
import ru.dbotthepony.mc.otm.config.DecimalConfigValue
import ru.dbotthepony.mc.otm.config.defineDecimal
import ru.dbotthepony.mc.otm.core.nextVariance
import ru.dbotthepony.mc.otm.core.otmRandom
import ru.dbotthepony.mc.otm.core.util.WriteOnce
import ru.dbotthepony.mc.otm.item.MatteryItem

View File

@ -29,9 +29,9 @@ import ru.dbotthepony.mc.otm.player.matteryPlayer
import ru.dbotthepony.mc.otm.core.ResourceLocation
import ru.dbotthepony.mc.otm.core.damageType
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.math.DecimalConfigValue
import ru.dbotthepony.mc.otm.core.math.defineDecimal
import ru.dbotthepony.mc.otm.core.math.nextVariance
import ru.dbotthepony.mc.otm.config.DecimalConfigValue
import ru.dbotthepony.mc.otm.config.defineDecimal
import ru.dbotthepony.mc.otm.core.nextVariance
import ru.dbotthepony.mc.otm.core.otmRandom
import ru.dbotthepony.mc.otm.core.util.WriteOnce
import ru.dbotthepony.mc.otm.item.MatteryItem

View File

@ -2,8 +2,8 @@ package ru.dbotthepony.mc.otm.matter
import net.minecraft.network.FriendlyByteBuf
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.math.readDecimal
import ru.dbotthepony.mc.otm.core.math.writeDecimal
import ru.dbotthepony.mc.otm.core.util.readDecimal
import ru.dbotthepony.mc.otm.core.util.writeDecimal
import ru.dbotthepony.mc.otm.core.util.readDouble
import ru.dbotthepony.mc.otm.core.util.writeDouble
import java.io.InputStream

View File

@ -12,19 +12,21 @@ import ru.dbotthepony.mc.otm.core.chart.DecimalHistoryChart
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.math.toDecimal
import ru.dbotthepony.mc.otm.menu.MatteryMenu
import ru.dbotthepony.mc.otm.menu.input.BooleanInputWithFeedback
import ru.dbotthepony.mc.otm.menu.input.EnumInputWithFeedback
import ru.dbotthepony.mc.otm.menu.input.IntInputWithFeedback
import ru.dbotthepony.mc.otm.registry.game.MMenus
import java.math.BigDecimal
import java.util.function.Supplier
class EnergyCounterMenu(
p_38852_: Int,
inventory: Inventory,
tile: EnergyCounterBlockEntity? = null
) : MatteryMenu(MMenus.ENERGY_COUNTER, p_38852_, inventory, tile) {
var passed by mSynchronizer.decimal()
var lastTick by mSynchronizer.decimal()
var maxIO by mSynchronizer.decimal()
var passed by mSynchronizer.computedDecimal { tile?.passed ?: Decimal.ZERO }
var lastTick by mSynchronizer.computedDecimal { tile?.lastTick ?: Decimal.ZERO }
var maxIO by mSynchronizer.computedDecimal { tile?.ioLimit ?: Decimal.ZERO }
val history5s = tile?.history5s ?: DecimalHistoryChart(1, 100)
val history15s = tile?.history15s ?: DecimalHistoryChart(3, 100)
@ -34,6 +36,8 @@ class EnergyCounterMenu(
val history6h = tile?.history6h ?: DecimalHistoryChart(720 * 6, 100)
val history24h = tile?.history24h ?: DecimalHistoryChart(720 * 24, 100)
val pullEnergyFromInput = BooleanInputWithFeedback(this, tile?.let { it::pullEnergyFromInput })
init {
mSynchronizer.add(history5s)
mSynchronizer.add(history15s)
@ -59,7 +63,7 @@ class EnergyCounterMenu(
}
}
var inputDirection: Direction by mSynchronizer.enum(Direction.UP)
val inputDirection: Direction by mSynchronizer.computedEnum { tile?.blockState?.getValue(EnergyCounterBlock.INPUT_DIRECTION) ?: Direction.UP}
val maxIOInput = decimalInput {
if (tile is EnergyCounterBlockEntity) {
@ -70,20 +74,4 @@ class EnergyCounterMenu(
}
}
}
override fun beforeBroadcast() {
super.beforeBroadcast()
if (tile is EnergyCounterBlockEntity) {
passed = tile.passed
lastTick = tile.lastTick
inputDirection = tile.blockState.getValue(EnergyCounterBlock.INPUT_DIRECTION)
maxIO = tile.ioLimit?.toDecimal() ?: -Decimal.ONE
}
}
companion object {
private val MINUS_ONE = -BigDecimal.ONE
}
}

View File

@ -9,8 +9,8 @@ import net.minecraft.resources.ResourceLocation
import net.minecraft.world.level.block.Block
import net.minecraft.world.level.block.state.BlockState
import ru.dbotthepony.kommons.math.RGBAColor
import ru.dbotthepony.mc.otm.core.math.readDecimal
import ru.dbotthepony.mc.otm.core.math.writeDecimal
import ru.dbotthepony.mc.otm.core.util.readDecimal
import ru.dbotthepony.mc.otm.core.util.writeDecimal
import ru.dbotthepony.mc.otm.core.readBlockType
import ru.dbotthepony.mc.otm.core.readItemType
import ru.dbotthepony.mc.otm.core.writeBlockType

View File

@ -270,6 +270,10 @@ class SynchableGroup : Observer, ISynchable, Iterable<ISynchable> {
return add(ListenableDelegate.maskSmart(value, getter, setter), MatteryStreamCodec.Enum(value::class.java))
}
inline fun <reified E : Enum<E>> computedEnum(value: Supplier<E>): SynchableDelegate<E> {
return computed(value, MatteryStreamCodec.Enum(E::class.java))
}
fun decimal(value: Decimal = Decimal.ZERO, setter: DelegateSetter<Decimal> = DelegateSetter.passthrough(), getter: DelegateGetter<Decimal> = DelegateGetter.passthrough()): SynchableDelegate<Decimal> {
return add(ListenableDelegate.maskSmart(value, getter, setter), StreamCodecs.DECIMAL)
}

View File

@ -14,8 +14,7 @@ import ru.dbotthepony.mc.otm.config.IFoodRegenerationValues
import ru.dbotthepony.mc.otm.config.PlayerConfig
import ru.dbotthepony.mc.otm.core.damageType
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.math.getDecimal
import ru.dbotthepony.mc.otm.core.math.set
import ru.dbotthepony.mc.otm.core.nbt.getDecimal
import ru.dbotthepony.mc.otm.core.nbt.set
import ru.dbotthepony.mc.otm.registry.MDamageTypes
import kotlin.math.max

View File

@ -1,6 +1,5 @@
package ru.dbotthepony.mc.otm.worldgen.feature
import com.mojang.serialization.Codec
import com.mojang.serialization.codecs.RecordCodecBuilder
import net.minecraft.world.level.levelgen.feature.Feature
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext
@ -8,7 +7,7 @@ import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfigur
import ru.dbotthepony.mc.otm.block.entity.blackhole.BlackHoleBlockEntity
import ru.dbotthepony.mc.otm.config.ServerConfig
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.math.nextDecimal
import ru.dbotthepony.mc.otm.core.nextDecimal
import ru.dbotthepony.mc.otm.data.codec.DecimalCodec
import ru.dbotthepony.mc.otm.registry.game.MBlocks