Make it compile
This commit is contained in:
parent
68a1e8c9e8
commit
0cf1bbcf24
@ -104,6 +104,8 @@ private fun sounds(provider: MatteryLanguageProvider) {
|
||||
|
||||
private fun misc(provider: MatteryLanguageProvider) {
|
||||
with(provider.english) {
|
||||
gui("ticks", "ticks")
|
||||
|
||||
gui("power_cost_per_use", "Power cost per use: %s")
|
||||
gui("power_cost_per_tick", "Power cost per tick: %s")
|
||||
|
||||
|
@ -38,9 +38,7 @@ import ru.dbotthepony.mc.otm.item.ItemTritaniumArmor;
|
||||
import ru.dbotthepony.mc.otm.item.QuantumBatteryItem;
|
||||
import ru.dbotthepony.mc.otm.item.weapon.AbstractWeaponItem;
|
||||
import ru.dbotthepony.mc.otm.item.PortableCondensationDriveItem;
|
||||
import ru.dbotthepony.mc.otm.matter.MatterDataKt;
|
||||
import ru.dbotthepony.mc.otm.matter.MatterManager;
|
||||
import ru.dbotthepony.mc.otm.matter.MatterRegistryKt;
|
||||
import ru.dbotthepony.mc.otm.matter.RecipeResolverManager;
|
||||
import ru.dbotthepony.mc.otm.network.*;
|
||||
import ru.dbotthepony.mc.otm.registry.*;
|
||||
@ -135,8 +133,6 @@ public final class OverdriveThatMatters {
|
||||
EVENT_BUS.addListener(EventPriority.NORMAL, MatteryPlayerCapability.Companion::onStartTracking);
|
||||
EVENT_BUS.addListener(EventPriority.NORMAL, MatteryPlayerCapability.Companion::onStopTracking);
|
||||
|
||||
EVENT_BUS.addListener(EventPriority.LOW, MatterDataKt::serverStartData);
|
||||
EVENT_BUS.addListener(EventPriority.NORMAL, MatterRegistryKt::onPlayerJoin);
|
||||
EVENT_BUS.addListener(EventPriority.NORMAL, ExplosionQueue.Companion::onWorldTick);
|
||||
EVENT_BUS.addListener(EventPriority.NORMAL, AbstractWeaponItem.Companion::tick);
|
||||
EVENT_BUS.addListener(EventPriority.NORMAL, QuantumBatteryItem.Companion::tick);
|
||||
@ -176,7 +172,7 @@ public final class OverdriveThatMatters {
|
||||
}
|
||||
|
||||
private void setupClient(final FMLClientSetupEvent event) {
|
||||
EVENT_BUS.addListener(EventPriority.NORMAL, MatterRegistryKt::tooltipEvent);
|
||||
EVENT_BUS.addListener(EventPriority.NORMAL, MatterManager.INSTANCE::tooltipEvent);
|
||||
|
||||
EVENT_BUS.addListener(EventPriority.NORMAL, AbstractWeaponItem.Companion::playerRenderHook);
|
||||
EVENT_BUS.addListener(EventPriority.NORMAL, AbstractWeaponItem.Companion::fovHook);
|
||||
|
@ -24,13 +24,13 @@ import ru.dbotthepony.mc.otm.block.entity.SynchronizedBlockEntity
|
||||
import ru.dbotthepony.mc.otm.block.entity.blackhole.ExplosionQueue.Companion.queueForLevel
|
||||
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
|
||||
import ru.dbotthepony.mc.otm.core.plus
|
||||
import ru.dbotthepony.mc.otm.matter.getMatterValue
|
||||
import ru.dbotthepony.mc.otm.registry.MBlockEntities
|
||||
import ru.dbotthepony.mc.otm.registry.MItems
|
||||
import ru.dbotthepony.mc.otm.registry.MRegistry
|
||||
import ru.dbotthepony.mc.otm.core.getSphericalBlockPositions
|
||||
import ru.dbotthepony.mc.otm.core.mapIf
|
||||
import ru.dbotthepony.mc.otm.core.set
|
||||
import ru.dbotthepony.mc.otm.matter.MatterManager
|
||||
import ru.dbotthepony.mc.otm.triggers.BlackHoleTrigger
|
||||
import java.util.LinkedList
|
||||
import kotlin.math.pow
|
||||
@ -251,10 +251,10 @@ class BlackHoleBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Synchro
|
||||
if (item.item.item === MItems.GRAVITATIONAL_DISRUPTOR) {
|
||||
collapse()
|
||||
} else {
|
||||
val mass = getMatterValue(item.item)
|
||||
val mass = MatterManager.getValue(item.item)
|
||||
|
||||
if (!mass.isZero)
|
||||
this.mass += mass.value * item.item.count
|
||||
if (mass.hasMatterValue)
|
||||
this.mass += mass.matter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -33,15 +33,13 @@ import ru.dbotthepony.mc.otm.graph.Graph6Node
|
||||
import ru.dbotthepony.mc.otm.graph.matter.IMatterGraphNode
|
||||
import ru.dbotthepony.mc.otm.graph.matter.MatterNetworkGraph
|
||||
import ru.dbotthepony.mc.otm.item.MatterDustItem
|
||||
import ru.dbotthepony.mc.otm.matter.baselineComplexityDecomposeTicks
|
||||
import ru.dbotthepony.mc.otm.matter.canDecompose
|
||||
import ru.dbotthepony.mc.otm.matter.getMatterValue
|
||||
import ru.dbotthepony.mc.otm.menu.MatterDecomposerMenu
|
||||
import ru.dbotthepony.mc.otm.registry.MBlockEntities
|
||||
import ru.dbotthepony.mc.otm.registry.MBlocks
|
||||
import ru.dbotthepony.mc.otm.registry.MItems
|
||||
import ru.dbotthepony.mc.otm.registry.MNames
|
||||
import ru.dbotthepony.mc.otm.core.WriteOnce
|
||||
import ru.dbotthepony.mc.otm.matter.MatterManager
|
||||
|
||||
fun moveMatterAsDustIntoContainer(_matterValue: ImpreciseFraction, container: MatteryContainer, OUTPUT_DUST_MAIN: Int, OUTPUT_DUST_STACKING: Int): ImpreciseFraction {
|
||||
var matterValue = _matterValue
|
||||
@ -144,7 +142,7 @@ class MatterDecomposerBlockEntity(pos: BlockPos, state: BlockState)
|
||||
private val itemHandler = LazyOptional.of<IItemHandler> {
|
||||
container.handler(object : MatteryContainerHooks {
|
||||
override fun canInsert(slot: Int, stack: ItemStack): Boolean {
|
||||
return slot == INPUT_SLOT && canDecompose(stack)
|
||||
return slot == INPUT_SLOT && MatterManager.canDecompose(stack)
|
||||
}
|
||||
|
||||
override fun canExtract(slot: Int, amount: Int, stack: ItemStack): Boolean {
|
||||
@ -221,11 +219,11 @@ class MatterDecomposerBlockEntity(pos: BlockPos, state: BlockState)
|
||||
val copy = stack.copy()
|
||||
copy.count = 1
|
||||
|
||||
if (canDecompose(copy)) {
|
||||
val matter = getMatterValue(copy)
|
||||
if (MatterManager.canDecompose(copy)) {
|
||||
val matter = MatterManager.getValue(copy)
|
||||
stack.count--
|
||||
|
||||
return DecomposerJob((level?.random?.nextDouble() ?: 1.0) <= 0.2, matter.value, matter.complexity * baselineComplexityDecomposeTicks) to null
|
||||
return DecomposerJob((level?.random?.nextDouble() ?: 1.0) <= 0.2, matter.matter, matter.complexity) to null
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -149,7 +149,7 @@ class MatterRecyclerBlockEntity(blockPos: BlockPos, blockState: BlockState)
|
||||
val dustMatter = (stack.item as MatterDustItem).getMatterValue(stack.copy().also { it.count = 1 }) ?: return null to IdleReason.ITEM
|
||||
stack.shrink(1)
|
||||
container.setChanged(0)
|
||||
return Job(dustMatter.value.toDouble() * MATTER_TICKS, POWER_CONSUMPTION) to null
|
||||
return Job(dustMatter.matter.toDouble() * MATTER_TICKS, POWER_CONSUMPTION) to null
|
||||
}
|
||||
|
||||
override fun onWorkTick(requiredPower: ImpreciseFraction, extractedPower: ImpreciseFraction, ticksAdvanced: Double): Status {
|
||||
@ -197,7 +197,8 @@ class MatterRecyclerBlockEntity(blockPos: BlockPos, blockState: BlockState)
|
||||
builder.pop()
|
||||
}
|
||||
|
||||
private const val MATTER_TICKS = 200.0
|
||||
// TODO: config
|
||||
private const val MATTER_TICKS = 0.8
|
||||
private val MATTER_PER_TICK = ImpreciseFraction(1.0 / MATTER_TICKS)
|
||||
}
|
||||
}
|
||||
|
@ -28,14 +28,13 @@ import ru.dbotthepony.mc.otm.container.MatteryContainerHandler
|
||||
import ru.dbotthepony.mc.otm.graph.Graph6Node
|
||||
import ru.dbotthepony.mc.otm.graph.matter.IMatterGraphNode
|
||||
import ru.dbotthepony.mc.otm.graph.matter.MatterNetworkGraph
|
||||
import ru.dbotthepony.mc.otm.matter.baselineComplexityReplicateTicks
|
||||
import ru.dbotthepony.mc.otm.matter.getMatterValue
|
||||
import ru.dbotthepony.mc.otm.menu.MatterReplicatorMenu
|
||||
import ru.dbotthepony.mc.otm.registry.MBlockEntities
|
||||
import ru.dbotthepony.mc.otm.core.*
|
||||
import ru.dbotthepony.mc.otm.registry.MBlocks
|
||||
import ru.dbotthepony.mc.otm.registry.MNames
|
||||
import ru.dbotthepony.mc.otm.core.WriteOnce
|
||||
import ru.dbotthepony.mc.otm.matter.MatterManager
|
||||
|
||||
class MatterReplicatorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
|
||||
MatteryWorkerBlockEntity<MatterReplicatorBlockEntity.ReplicatorJob>(MBlockEntities.MATTER_REPLICATOR, p_155229_, p_155230_, {
|
||||
@ -195,18 +194,18 @@ class MatterReplicatorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
|
||||
val graph = matterNode.graph as MatterNetworkGraph? ?: return null to null
|
||||
val allocation = graph.allocateTask(simulate = false) ?: return null to IdleReason.OBSERVING
|
||||
val stack = allocation.task.stack(1)
|
||||
val matter = getMatterValue(stack)
|
||||
val matter = MatterManager.getValue(stack)
|
||||
|
||||
// ????????
|
||||
if (matter.isZero) return null to null
|
||||
if (!matter.hasMatterValue) return null to null
|
||||
|
||||
val ticks = matter.complexity * baselineComplexityReplicateTicks
|
||||
val ticks = matter.complexity
|
||||
|
||||
return ReplicatorJob(
|
||||
itemStack = stack,
|
||||
matterPerTick = matter.value / ticks,
|
||||
matterPerTick = matter.matter / ticks,
|
||||
task = allocation.task.asImmutable(),
|
||||
matterValue = matter.value,
|
||||
matterValue = matter.matter,
|
||||
pattern = allocation.pattern?.asImmutable(),
|
||||
asDust = (level?.random?.nextDouble() ?: 1.0) > (allocation.pattern?.researchPercent ?: 2.0),
|
||||
ticks = ticks,
|
||||
|
@ -33,12 +33,12 @@ import ru.dbotthepony.mc.otm.core.map
|
||||
import ru.dbotthepony.mc.otm.graph.Graph6Node
|
||||
import ru.dbotthepony.mc.otm.graph.matter.IMatterGraphNode
|
||||
import ru.dbotthepony.mc.otm.graph.matter.MatterNetworkGraph
|
||||
import ru.dbotthepony.mc.otm.matter.*
|
||||
import ru.dbotthepony.mc.otm.menu.MatterScannerMenu
|
||||
import ru.dbotthepony.mc.otm.registry.MBlockEntities
|
||||
import ru.dbotthepony.mc.otm.registry.MBlocks
|
||||
import ru.dbotthepony.mc.otm.registry.MNames
|
||||
import ru.dbotthepony.mc.otm.core.WriteOnce
|
||||
import ru.dbotthepony.mc.otm.matter.MatterManager
|
||||
import java.util.*
|
||||
import kotlin.math.pow
|
||||
|
||||
@ -50,7 +50,7 @@ class MatterScannerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
|
||||
|
||||
private val itemHandler = container.handler(object : MatteryContainerHooks {
|
||||
override fun canInsert(slot: Int, stack: ItemStack): Boolean {
|
||||
return canDecompose(stack)
|
||||
return MatterManager.canDecompose(stack)
|
||||
}
|
||||
|
||||
override fun canExtract(slot: Int, amount: Int, stack: ItemStack): Boolean {
|
||||
@ -135,7 +135,7 @@ class MatterScannerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
|
||||
val grid = matterNode.graph as MatterNetworkGraph? ?: return Status.FAILURE_WAIT
|
||||
|
||||
val stack = job.itemStack
|
||||
if (stack.isEmpty || !hasMatterValue(stack)) return Status.SUCCESS
|
||||
if (stack.isEmpty || !MatterManager.hasMatterValue(stack)) return Status.SUCCESS
|
||||
|
||||
var findState: IPatternState? = null
|
||||
|
||||
@ -147,7 +147,7 @@ class MatterScannerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
|
||||
}
|
||||
}
|
||||
|
||||
val researchAdvance = getResearchAdvance(stack.item)
|
||||
val researchAdvance = MatterManager.getResearchAdvance(stack.item)
|
||||
|
||||
val new: IPatternState =
|
||||
if (findState != null) {
|
||||
@ -171,7 +171,7 @@ class MatterScannerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
|
||||
val grid = matterNode.graph as MatterNetworkGraph? ?: return null to null
|
||||
|
||||
val stack = container.getItem(0)
|
||||
if (stack.isEmpty || !canDecompose(stack)) return null to IdleReason.ITEM
|
||||
if (stack.isEmpty || !MatterManager.canDecompose(stack)) return null to IdleReason.ITEM
|
||||
|
||||
var findState: IPatternState? = null
|
||||
|
||||
@ -185,7 +185,7 @@ class MatterScannerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
|
||||
}
|
||||
}
|
||||
|
||||
val researchAdvance = getResearchAdvance(stack.item)
|
||||
val researchAdvance = MatterManager.getResearchAdvance(stack.item)
|
||||
|
||||
val new: IPatternState =
|
||||
if (findState != null) {
|
||||
@ -198,8 +198,8 @@ class MatterScannerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
|
||||
val copy = stack.copy().also { it.count = 1 }
|
||||
stack.shrink(1)
|
||||
container.setChanged()
|
||||
val complexity = getMatterValue(copy).complexity
|
||||
return ItemJob(copy, (if (complexity > 1.0) complexity.pow(2.0) else complexity.pow(0.5)) * baselineComplexityScanTicks, BASE_CONSUMPTION) to null
|
||||
val complexity = MatterManager.getValue(copy).complexity
|
||||
return ItemJob(copy, (if (complexity > 1.0) complexity.pow(2.0) else complexity.pow(0.5)), BASE_CONSUMPTION) to null
|
||||
}
|
||||
|
||||
return null to IdleReason.ITEM
|
||||
|
@ -93,6 +93,7 @@ enum class SiPrefix(
|
||||
|
||||
val long = if (!fractional) string.toLongOrNull() else null
|
||||
val int = if (!fractional) string.toIntOrNull() else null
|
||||
val double = string.toDouble()
|
||||
|
||||
companion object {
|
||||
val MULTIPLIES: List<SiPrefix> = ImmutableList.builder<SiPrefix>()
|
||||
@ -339,6 +340,32 @@ fun Int.determineSiPrefix(): SiPrefix? {
|
||||
return prev
|
||||
}
|
||||
|
||||
fun Double.determineSiPrefix(): SiPrefix? {
|
||||
if (this == 0.0) {
|
||||
return null
|
||||
}
|
||||
|
||||
var num = this
|
||||
|
||||
if (this < 0) {
|
||||
num = -this
|
||||
}
|
||||
|
||||
var prev: SiPrefix? = null
|
||||
|
||||
if (num >= 1) {
|
||||
for (value in SiPrefix.MULTIPLIES) {
|
||||
if (value.double <= num) {
|
||||
prev = value
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return prev
|
||||
}
|
||||
|
||||
fun ImpreciseFraction.formatSi(decimalPlaces: Int = 2): String {
|
||||
require(decimalPlaces >= 0) { "Invalid amount of decimal places required: $decimalPlaces" }
|
||||
val prefix = determineSiPrefix() ?: return toString(decimalPlaces)
|
||||
@ -347,11 +374,16 @@ fun ImpreciseFraction.formatSi(decimalPlaces: Int = 2): String {
|
||||
|
||||
fun Int.formatSiComponent(suffix: Any = "", decimalPlaces: Int = 2): Component {
|
||||
require(decimalPlaces >= 0) { "Invalid amount of decimal places required: $decimalPlaces" }
|
||||
val prefix = determineSiPrefix() ?: return if (suffix == "") TextComponent(toString()) else if (suffix is Component) TextComponent(
|
||||
toString() + " " + suffix.string) else TextComponent(toString() + " " + suffix)
|
||||
val prefix = determineSiPrefix() ?: return if (suffix == "") TextComponent(toString()) else if (suffix is Component) TextComponent(toString() + " " + suffix.string) else TextComponent(toString() + " " + suffix)
|
||||
return TranslatableComponent(prefix.formatLocaleKey, "%f.$decimalPlaces".format(this.toFloat() / prefix.int!!.toFloat()), suffix)
|
||||
}
|
||||
|
||||
fun Double.formatSiComponent(suffix: Any = "", decimalPlaces: Int = 2): Component {
|
||||
require(decimalPlaces >= 0) { "Invalid amount of decimal places required: $decimalPlaces" }
|
||||
val prefix = determineSiPrefix() ?: return if (suffix == "") TextComponent(toString()) else if (suffix is Component) TextComponent(toString() + " " + suffix.string) else TextComponent(toString() + " " + suffix)
|
||||
return TranslatableComponent(prefix.formatLocaleKey, "%f.$decimalPlaces".format(this / prefix.double), suffix)
|
||||
}
|
||||
|
||||
fun ImpreciseFraction.formatSiComponent(suffix: Any = "", decimalPlaces: Int = 2): Component {
|
||||
require(decimalPlaces >= 0) { "Invalid amount of decimal places required: $decimalPlaces" }
|
||||
val prefix = determineSiPrefix() ?: return if (suffix == "") TextComponent(toString(decimalPlaces)) else if (suffix is Component) TextComponent(toString(decimalPlaces) + " " + suffix.string) else TextComponent(toString(decimalPlaces) + " " + suffix)
|
||||
|
@ -22,9 +22,7 @@ import ru.dbotthepony.mc.otm.capability.matter.PatternInsertStatus
|
||||
import ru.dbotthepony.mc.otm.capability.matter.PatternState
|
||||
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
||||
import ru.dbotthepony.mc.otm.core.getID
|
||||
import ru.dbotthepony.mc.otm.matter.derivedEntriesAccess
|
||||
import ru.dbotthepony.mc.otm.matter.matterRegistryStream
|
||||
import ru.dbotthepony.mc.otm.matter.rootEntriesAccess
|
||||
import ru.dbotthepony.mc.otm.matter.MatterManager
|
||||
import java.util.*
|
||||
import java.util.stream.Stream
|
||||
|
||||
@ -33,13 +31,19 @@ class CreativePatternItem : Item(Properties().rarity(Rarity.EPIC).tab(OverdriveT
|
||||
private val resolver = LazyOptional.of<IPatternStorage> { this }
|
||||
|
||||
override val patterns: Stream<out IPatternState>
|
||||
get() = matterRegistryStream.map { PatternState(UUID(34783464838L, 4463458382L + ForgeRegistries.ITEMS.getID(it.key)), it.key, 1.0) }
|
||||
get() = MatterManager.resolveAndStream().map { PatternState(UUID(34783464838L, 4463458382L + ForgeRegistries.ITEMS.getID(it.key)), it.key, 1.0) }
|
||||
|
||||
override val patternCapacity: Int
|
||||
get() = rootEntriesAccess.size + derivedEntriesAccess.size
|
||||
get() {
|
||||
MatterManager.resolveEverything()
|
||||
return MatterManager.computedEntriesSize
|
||||
}
|
||||
|
||||
override val storedPatterns: Int
|
||||
get() = rootEntriesAccess.size + derivedEntriesAccess.size
|
||||
get() {
|
||||
MatterManager.resolveEverything()
|
||||
return MatterManager.computedEntriesSize
|
||||
}
|
||||
|
||||
override fun insertPattern(
|
||||
pattern: IPatternState,
|
||||
|
@ -10,9 +10,8 @@ import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
||||
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
||||
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
|
||||
import ru.dbotthepony.mc.otm.matter.IMatterItem
|
||||
import ru.dbotthepony.mc.otm.matter.MatterTuple
|
||||
import ru.dbotthepony.mc.otm.container.set
|
||||
import ru.dbotthepony.mc.otm.core.set
|
||||
import ru.dbotthepony.mc.otm.matter.MatterManager
|
||||
|
||||
class MatterDustItem : Item(Properties().tab(OverdriveThatMatters.INSTANCE.CREATIVE_TAB).stacksTo(64)), IMatterItem {
|
||||
private fun matter(stack: ItemStack): ImpreciseFraction {
|
||||
@ -23,9 +22,9 @@ class MatterDustItem : Item(Properties().tab(OverdriveThatMatters.INSTANCE.CREAT
|
||||
stack.orCreateTag["matter"] = matter.serializeNBT()
|
||||
}
|
||||
|
||||
override fun getMatterValue(stack: ItemStack): MatterTuple? {
|
||||
override fun getMatterValue(stack: ItemStack): MatterManager.IMatterValue? {
|
||||
val value = stack.tag?.get("matter") ?: return null
|
||||
return MatterTuple(ImpreciseFraction.deserializeNBT(value), 0.0)
|
||||
return MatterManager.MatterValue(ImpreciseFraction.deserializeNBT(value), 0.0)
|
||||
}
|
||||
|
||||
override fun canDecompose(stack: ItemStack) = false
|
||||
|
@ -0,0 +1,9 @@
|
||||
package ru.dbotthepony.mc.otm.matter
|
||||
|
||||
import net.minecraft.world.item.ItemStack
|
||||
|
||||
interface IMatterItem {
|
||||
fun getMatterValue(stack: ItemStack): MatterManager.IMatterValue?
|
||||
fun hasMatterValue(stack: ItemStack) = getMatterValue(stack) != null
|
||||
fun canDecompose(stack: ItemStack): Boolean
|
||||
}
|
@ -1,516 +0,0 @@
|
||||
package ru.dbotthepony.mc.otm.matter
|
||||
|
||||
import net.minecraft.tags.ItemTags
|
||||
import net.minecraft.tags.TagKey
|
||||
import net.minecraft.world.item.Item
|
||||
import net.minecraft.world.item.Items
|
||||
import net.minecraft.world.item.crafting.Recipe
|
||||
import net.minecraft.world.item.crafting.RecipeType
|
||||
import net.minecraftforge.event.server.ServerStartedEvent
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent
|
||||
import net.minecraftforge.registries.ForgeRegistries
|
||||
import net.minecraftforge.registries.tags.ITag
|
||||
import org.apache.logging.log4j.LogManager
|
||||
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
|
||||
import ru.dbotthepony.mc.otm.registry.MItems
|
||||
import ru.dbotthepony.mc.otm.registry.MRecipes
|
||||
import kotlin.math.pow
|
||||
import kotlin.math.sqrt
|
||||
|
||||
/**
|
||||
* baselineComplexityReplicateTicks * complexity = replicate ticks
|
||||
* baselineComplexityDecomposeTicks * complexity = decompose ticks
|
||||
*/
|
||||
const val baselineComplexityReplicateTicks = 1000.0
|
||||
const val baselineComplexityDecomposeTicks = 400.0
|
||||
const val baselineComplexityScanTicks = 4000.0
|
||||
|
||||
@JvmField val BASELINE = ImpreciseFraction(0.001)
|
||||
@JvmField val DIRT = BASELINE
|
||||
@JvmField val STONY = BASELINE * 0.92
|
||||
|
||||
@JvmField val IRON = BASELINE * 60
|
||||
@JvmField val COPPER = BASELINE * 36
|
||||
@JvmField val GOLD = IRON * 2.5
|
||||
@JvmField val LAPIS = IRON * 1.15
|
||||
@JvmField val REDSTONE = IRON * 1.4
|
||||
@JvmField val DIAMOND = GOLD * 4
|
||||
@JvmField val EMERALD = DIAMOND
|
||||
@JvmField val QUARTZ = IRON * 0.97
|
||||
@JvmField val COAL = DIAMOND * 0.08
|
||||
@JvmField val TRITANIUM = IRON * 1.95
|
||||
|
||||
@JvmField val WATER = BASELINE * 0.3
|
||||
|
||||
@JvmField val AMETHYST = EMERALD * 0.44
|
||||
|
||||
@JvmField val NETHER_STAR = ImpreciseFraction(40)
|
||||
|
||||
@JvmField val MUSIC_DISC = BASELINE * 200
|
||||
|
||||
@JvmField val SOUL_SAND = BASELINE * 6.66666666
|
||||
@JvmField val GLOWSTONE_DUST = GOLD * 0.44 + REDSTONE * 0.7
|
||||
|
||||
@JvmField val SEEDS = BASELINE * 1.8
|
||||
@JvmField val PLANTS = BASELINE * 4.6
|
||||
@JvmField val GRASS = PLANTS * 0.65
|
||||
|
||||
@JvmField val SIMPLE_ORGANICS = BASELINE * 9
|
||||
@JvmField val STRINGS = SIMPLE_ORGANICS * 0.8
|
||||
@JvmField val FEATHERS = SIMPLE_ORGANICS * 1.2
|
||||
@JvmField val BONES = SIMPLE_ORGANICS * 1.8
|
||||
|
||||
@JvmField val ADVANCED_ORGANICS = SIMPLE_ORGANICS * 4.2
|
||||
|
||||
@JvmField val PRISMARINE = IRON * 0.44
|
||||
|
||||
@JvmField val LOGS = BASELINE * 4
|
||||
@JvmField val STRIPPED_LOGS = LOGS * 0.91
|
||||
@JvmField val PLANKS = LOGS * 6
|
||||
|
||||
// трава?
|
||||
@JvmField val CORALS = ADVANCED_ORGANICS * 0.83
|
||||
@JvmField val DEAD_CORALS = CORALS * 0.91
|
||||
|
||||
private val seenItems = ArrayDeque<Item>()
|
||||
private val seenRecipes = ArrayDeque<Recipe<*>>()
|
||||
private val LOGGER = LogManager.getLogger()
|
||||
private val mappedOutputs = HashMap<Item, ArrayList<Recipe<*>>>()
|
||||
private val mappedInputs = HashMap<Item, ArrayList<Recipe<*>>>()
|
||||
|
||||
private fun defaultComplexity(value: ImpreciseFraction): Double {
|
||||
val double = value.toDouble()
|
||||
|
||||
if (double < 1.0) {
|
||||
return sqrt(double)
|
||||
}
|
||||
|
||||
return double.pow(1.4)
|
||||
}
|
||||
|
||||
private fun make(item: Item, value: ImpreciseFraction, complexity: Double = defaultComplexity(value)) {
|
||||
rootEntriesAccess[item] = MatterTuple(value, complexity)
|
||||
}
|
||||
|
||||
private fun derive(from: Item, to: Item, multValue: ImpreciseFraction = ImpreciseFraction.ONE, multComplexity: Double = 1.0) {
|
||||
val getValue = getMatterValueNullable(from)
|
||||
|
||||
if (getValue != null) {
|
||||
derivedEntriesAccess[to] = MatterTuple(getValue.value * multValue, getValue.complexity * multComplexity)
|
||||
}
|
||||
}
|
||||
|
||||
private fun derive(from: Item, to: Item, multValue: Double, multComplexity: Double = 1.0) = derive(from, to, ImpreciseFraction(multValue), multComplexity)
|
||||
|
||||
private fun deriveIfMissing(from: Item, to: Item, multValue: ImpreciseFraction = ImpreciseFraction.ONE, multComplexity: Double = 1.0) {
|
||||
if (getMatterValueNullable(to) != null)
|
||||
return
|
||||
|
||||
val getValue = getMatterValueNullable(from)
|
||||
|
||||
if (getValue != null) {
|
||||
derivedEntriesAccess[to] = MatterTuple(getValue.value * multValue, getValue.complexity * multComplexity)
|
||||
}
|
||||
}
|
||||
|
||||
private fun deriveIfMissing(from: Item, to: Item, multValue: Double, multComplexity: Double = 1.0) = deriveIfMissing(from, to, ImpreciseFraction(multValue), multComplexity)
|
||||
|
||||
private fun make(tag: ITag<Item>, value: ImpreciseFraction, complexity: Double = defaultComplexity(value)) {
|
||||
for (item in tag.stream().iterator()) {
|
||||
make(item, value, complexity)
|
||||
}
|
||||
}
|
||||
|
||||
private fun make(tag: TagKey<Item>, value: ImpreciseFraction, complexity: Double = defaultComplexity(value)) {
|
||||
val resolved = ForgeRegistries.ITEMS.tags()?.getTag(tag)
|
||||
|
||||
if (resolved != null) {
|
||||
make(resolved, value, complexity)
|
||||
}
|
||||
}
|
||||
|
||||
private fun logResolutionError(text: String) {
|
||||
//LOGGER.debug("... Item chain: " + seenItems.joinToString(" -> "))
|
||||
// LOGGER.error("Recipe chain: " + seenRecipes.joinToString(" -> "))
|
||||
//LOGGER.debug(text)
|
||||
}
|
||||
|
||||
private enum class ResultType {
|
||||
RESOLVED,
|
||||
RECURSION,
|
||||
UNKNOWN_VALUE
|
||||
}
|
||||
|
||||
private data class Result(val type: ResultType = ResultType.UNKNOWN_VALUE, val tuple: MatterTuple? = null)
|
||||
|
||||
fun serverStartData(event: ServerStartedEvent) {
|
||||
rootEntriesAccess.clear()
|
||||
derivedEntriesAccess.clear()
|
||||
mappedOutputs.clear()
|
||||
mappedInputs.clear()
|
||||
|
||||
building = true
|
||||
registerRoots()
|
||||
|
||||
floodRecipeCategory(event.server.recipeManager.getAllRecipesFor(RecipeType.SMELTING))
|
||||
floodRecipeCategory(event.server.recipeManager.getAllRecipesFor(RecipeType.BLASTING))
|
||||
floodRecipeCategory(event.server.recipeManager.getAllRecipesFor(RecipeType.SMOKING))
|
||||
floodRecipeCategory(event.server.recipeManager.getAllRecipesFor(RecipeType.STONECUTTING))
|
||||
floodRecipeCategory(event.server.recipeManager.getAllRecipesFor(MRecipes.PLATE_PRESS))
|
||||
floodRecipeCategory(event.server.recipeManager.getAllRecipesFor(RecipeType.CRAFTING))
|
||||
|
||||
for (item in mappedInputs.keys) {
|
||||
determineMatterValue(item)
|
||||
}
|
||||
|
||||
for (item in mappedOutputs.keys) {
|
||||
determineMatterValue(item)
|
||||
}
|
||||
|
||||
registerDerived()
|
||||
building = false
|
||||
}
|
||||
|
||||
private fun floodRecipeCategory(list: Collection<Recipe<*>>) {
|
||||
for (recipe in list) {
|
||||
val result = recipe.resultItem
|
||||
|
||||
if (!result.isEmpty) {
|
||||
mappedOutputs.computeIfAbsent(result.item) {ArrayList()}.add(recipe)
|
||||
|
||||
for (inputI in recipe.ingredients) {
|
||||
for (stack in inputI.items) {
|
||||
if (!stack.isEmpty) {
|
||||
mappedInputs.computeIfAbsent(stack.item) {ArrayList()}.add(recipe)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun determineMatterValue(item: Item): Result {
|
||||
val rootEntry = getMatterValueNullable(item)
|
||||
|
||||
if (rootEntry != null)
|
||||
return Result(ResultType.RESOLVED, rootEntry)
|
||||
|
||||
val recipes = mappedOutputs[item] ?: return Result(ResultType.UNKNOWN_VALUE)
|
||||
|
||||
if (seenItems.contains(item)) {
|
||||
// logResolutionError("Already seen this item: $item")
|
||||
return Result(ResultType.RECURSION)
|
||||
}
|
||||
|
||||
seenItems.addLast(item)
|
||||
var minimal: MatterTuple? = null
|
||||
var anyRecursion = false
|
||||
|
||||
for (recipe in recipes) {
|
||||
if (seenRecipes.contains(recipe)) {
|
||||
logResolutionError("Already seen this recipe: $recipe")
|
||||
continue
|
||||
}
|
||||
|
||||
seenRecipes.addLast(recipe)
|
||||
var sum = MatterTuple.ZERO
|
||||
var recursiveRecipe = false
|
||||
var once = false
|
||||
|
||||
for (ingredient in recipe.ingredients) {
|
||||
var minIngredient: MatterTuple? = null
|
||||
var recursive = false
|
||||
|
||||
for (stack in ingredient.items) {
|
||||
val getStackTuple = determineMatterValue(stack.item)
|
||||
|
||||
if (getStackTuple.type == ResultType.UNKNOWN_VALUE) {
|
||||
logResolutionError("Failed to resolve $item value because ${stack.item} is unknown")
|
||||
seenItems.removeLast()
|
||||
seenRecipes.removeLast()
|
||||
return getStackTuple
|
||||
} else if (getStackTuple.type == ResultType.RESOLVED) {
|
||||
if (minIngredient == null || minIngredient > getStackTuple.tuple!!)
|
||||
minIngredient = getStackTuple.tuple
|
||||
} else {
|
||||
recursive = true
|
||||
}
|
||||
}
|
||||
|
||||
//if (minIngredient == null) {
|
||||
// if (recursive) {
|
||||
// recursiveRecipe = true
|
||||
// break
|
||||
// }
|
||||
|
||||
// logResolutionError("Failed to resolve $item value because $ingredient is empty (${ingredient.items.joinToString(", ")})???")
|
||||
// seenItems.removeLast()
|
||||
// seenRecipes.removeLast()
|
||||
// return Result(ResultType.UNKNOWN_VALUE)
|
||||
//}
|
||||
|
||||
if (recursive) {
|
||||
recursiveRecipe = true
|
||||
}
|
||||
|
||||
if (minIngredient != null) {
|
||||
sum += minIngredient
|
||||
once = true
|
||||
}
|
||||
}
|
||||
|
||||
seenRecipes.removeLast()
|
||||
|
||||
if (recursiveRecipe) {
|
||||
anyRecursion = true
|
||||
// logResolutionError("$recipe is anything but recursion?")
|
||||
// continue
|
||||
}
|
||||
|
||||
if (!once) {
|
||||
if (recursiveRecipe) {
|
||||
//logResolutionError("Escaping resolution of $item early because $recipe is recursive")
|
||||
//seenItems.removeLast()
|
||||
//return Result(ResultType.RECURSION)
|
||||
continue
|
||||
}
|
||||
|
||||
logResolutionError("Failed to resolve $item because $recipe is unresolvable")
|
||||
seenItems.removeLast()
|
||||
return Result(ResultType.UNKNOWN_VALUE)
|
||||
}
|
||||
|
||||
sum = MatterTuple(sum.value / recipe.resultItem.count, sum.complexity / recipe.resultItem.count)
|
||||
|
||||
if (minimal == null || minimal > sum) {
|
||||
minimal = sum
|
||||
}
|
||||
}
|
||||
|
||||
seenItems.removeLast()
|
||||
|
||||
if (minimal != null) {
|
||||
derivedEntriesAccess[item] = minimal
|
||||
return Result(ResultType.RESOLVED, minimal)
|
||||
}
|
||||
|
||||
if (anyRecursion) {
|
||||
logResolutionError("Failed to resolve $item because hit recursive recipes")
|
||||
return Result(ResultType.RECURSION)
|
||||
}
|
||||
|
||||
logResolutionError("Failed to resolve $item because no appropriate recipes were found")
|
||||
return Result()
|
||||
}
|
||||
|
||||
private fun registerRoots() {
|
||||
make(Items.STONE, STONY)
|
||||
make(Items.COBBLESTONE, STONY)
|
||||
make(Items.GRAVEL, STONY)
|
||||
make(Items.TUFF, STONY * 1.17)
|
||||
make(Items.CALCITE, STONY * 1.17)
|
||||
make(Items.SAND, STONY)
|
||||
make(Items.RED_SAND, STONY)
|
||||
make(Items.FLINT, STONY)
|
||||
make(Items.NETHERRACK, STONY * 0.7)
|
||||
make(Items.SOUL_SAND, SOUL_SAND)
|
||||
make(Items.SOUL_SOIL, SOUL_SAND)
|
||||
make(Items.DEEPSLATE, STONY * 1.15)
|
||||
make(Items.COBBLED_DEEPSLATE, STONY * 1.15)
|
||||
make(Items.BLACKSTONE, STONY * 1.21)
|
||||
make(Items.OBSIDIAN, STONY * 3.5)
|
||||
|
||||
make(Items.INFESTED_COBBLESTONE, STONY + ADVANCED_ORGANICS * 3.6)
|
||||
make(Items.MOSSY_COBBLESTONE, STONY + GRASS * 0.6)
|
||||
|
||||
make(Items.SNOWBALL, WATER / 4)
|
||||
|
||||
make(ItemTags.PLANKS, PLANKS)
|
||||
|
||||
make(ItemTags.LOGS, LOGS)
|
||||
|
||||
make(ItemTags.SAPLINGS, PLANTS * 2.6)
|
||||
|
||||
make(Items.STRIPPED_OAK_LOG, STRIPPED_LOGS)
|
||||
make(Items.STRIPPED_SPRUCE_LOG, STRIPPED_LOGS)
|
||||
make(Items.STRIPPED_BIRCH_LOG, STRIPPED_LOGS)
|
||||
make(Items.STRIPPED_JUNGLE_LOG, STRIPPED_LOGS)
|
||||
make(Items.STRIPPED_ACACIA_LOG, STRIPPED_LOGS)
|
||||
make(Items.STRIPPED_DARK_OAK_LOG, STRIPPED_LOGS)
|
||||
make(Items.STRIPPED_CRIMSON_STEM, STRIPPED_LOGS)
|
||||
make(Items.STRIPPED_WARPED_STEM, STRIPPED_LOGS)
|
||||
make(Items.STRIPPED_OAK_WOOD, STRIPPED_LOGS)
|
||||
make(Items.STRIPPED_SPRUCE_WOOD, STRIPPED_LOGS)
|
||||
make(Items.STRIPPED_BIRCH_WOOD, STRIPPED_LOGS)
|
||||
make(Items.STRIPPED_JUNGLE_WOOD, STRIPPED_LOGS)
|
||||
make(Items.STRIPPED_ACACIA_WOOD, STRIPPED_LOGS)
|
||||
make(Items.STRIPPED_DARK_OAK_WOOD, STRIPPED_LOGS)
|
||||
make(Items.STRIPPED_CRIMSON_HYPHAE, STRIPPED_LOGS)
|
||||
make(Items.STRIPPED_WARPED_HYPHAE, STRIPPED_LOGS)
|
||||
|
||||
make(Items.DIRT, DIRT)
|
||||
make(Items.DIRT_PATH, DIRT)
|
||||
make(Items.GRASS_BLOCK, DIRT * 1.1)
|
||||
make(Items.PODZOL, DIRT * 1.15)
|
||||
|
||||
make(Items.COAL, COAL)
|
||||
make(Items.QUARTZ, QUARTZ)
|
||||
make(Items.AMETHYST_SHARD, AMETHYST)
|
||||
make(Items.DIAMOND, DIAMOND)
|
||||
make(Items.IRON_INGOT, IRON)
|
||||
make(MItems.TRITANIUM_INGOT, TRITANIUM)
|
||||
make(Items.COPPER_INGOT, COPPER)
|
||||
make(Items.LAPIS_LAZULI, LAPIS)
|
||||
make(Items.REDSTONE, REDSTONE)
|
||||
make(Items.GOLD_INGOT, GOLD)
|
||||
make(Items.EMERALD, EMERALD)
|
||||
make(Items.NETHER_STAR, NETHER_STAR)
|
||||
make(Items.GLOWSTONE_DUST, GLOWSTONE_DUST)
|
||||
|
||||
make(Items.GUNPOWDER, BASELINE * 2.4)
|
||||
make(Items.CLAY_BALL, BASELINE * 1.9)
|
||||
make(Items.PRISMARINE_CRYSTALS, PRISMARINE * 1.3)
|
||||
make(Items.PRISMARINE_SHARD, PRISMARINE)
|
||||
|
||||
make(Items.WHEAT, PLANTS)
|
||||
make(Items.BEETROOT, PLANTS * 1.1)
|
||||
make(Items.NETHER_WART, PLANTS * 2.4)
|
||||
make(Items.WHEAT_SEEDS, SEEDS)
|
||||
make(Items.MELON_SEEDS, SEEDS * 1.1)
|
||||
make(Items.PUMPKIN_SEEDS, SEEDS * 0.9)
|
||||
make(Items.BEETROOT_SEEDS, SEEDS * 1.26)
|
||||
make(Items.SUGAR, PLANTS * 0.75)
|
||||
make(Items.SUGAR_CANE, PLANTS * 1.55)
|
||||
make(Items.BAMBOO, PLANTS * 1.45)
|
||||
make(Items.CACTUS, PLANTS * 1.8)
|
||||
make(Items.VINE, PLANTS * 0.9)
|
||||
make(Items.GLOW_LICHEN, PLANTS * 1.35)
|
||||
make(Items.LILY_PAD, PLANTS)
|
||||
make(Items.SPORE_BLOSSOM, PLANTS * 1.4)
|
||||
make(Items.CHORUS_FRUIT, PLANTS * 1.55)
|
||||
make(Items.CHORUS_PLANT, PLANTS * 1.55)
|
||||
make(Items.CHORUS_FLOWER, PLANTS * 1.55)
|
||||
|
||||
make(Items.SUNFLOWER, PLANTS * 1.5)
|
||||
make(Items.LILAC, PLANTS * 1.5)
|
||||
make(Items.ROSE_BUSH, PLANTS * 1.5)
|
||||
make(Items.PEONY, PLANTS * 1.5)
|
||||
make(Items.DANDELION, PLANTS * 1.24)
|
||||
make(Items.POPPY, PLANTS * 1.24)
|
||||
make(Items.BLUE_ORCHID, PLANTS * 1.24)
|
||||
make(Items.ALLIUM, PLANTS * 1.24)
|
||||
make(Items.AZURE_BLUET, PLANTS * 1.24)
|
||||
make(Items.RED_TULIP, PLANTS * 1.24)
|
||||
make(Items.ORANGE_TULIP, PLANTS * 1.24)
|
||||
make(Items.WHITE_TULIP, PLANTS * 1.24)
|
||||
make(Items.PINK_TULIP, PLANTS * 1.24)
|
||||
make(Items.OXEYE_DAISY, PLANTS * 1.24)
|
||||
make(Items.CORNFLOWER, PLANTS * 1.24)
|
||||
make(Items.LILY_OF_THE_VALLEY, PLANTS * 1.24)
|
||||
|
||||
make(Items.WITHER_ROSE, PLANTS * 2.35)
|
||||
|
||||
make(Items.BROWN_MUSHROOM, PLANTS)
|
||||
make(Items.RED_MUSHROOM, PLANTS)
|
||||
make(Items.COCOA_BEANS, PLANTS * 1.4)
|
||||
make(Items.CRIMSON_FUNGUS, PLANTS * 1.161)
|
||||
make(Items.WARPED_FUNGUS, PLANTS * 1.161)
|
||||
make(Items.CRIMSON_ROOTS, GRASS * 1.161)
|
||||
make(Items.WARPED_ROOTS, GRASS * 1.161)
|
||||
make(Items.NETHER_SPROUTS, GRASS * 0.8)
|
||||
make(Items.WEEPING_VINES, GRASS * 1.161)
|
||||
make(Items.TWISTING_VINES, GRASS * 1.261)
|
||||
make(Items.DEAD_BUSH, GRASS * 0.64)
|
||||
|
||||
make(Items.TALL_GRASS, GRASS * 1.7)
|
||||
make(Items.GRASS, GRASS)
|
||||
make(Items.FERN, GRASS * 1.02)
|
||||
make(Items.LARGE_FERN, GRASS * 1.91)
|
||||
make(Items.SEAGRASS, GRASS * 0.94)
|
||||
|
||||
make(Items.KELP, PLANTS * 0.94)
|
||||
make(Items.MOSS_BLOCK, PLANTS * 1.4)
|
||||
make(Items.HANGING_ROOTS, PLANTS * 0.8)
|
||||
make(Items.BIG_DRIPLEAF, PLANTS * 1.15)
|
||||
make(Items.SMALL_DRIPLEAF, PLANTS * 1.1)
|
||||
make(Items.AZALEA, PLANTS * 1.3)
|
||||
make(Items.FLOWERING_AZALEA, PLANTS * 1.4)
|
||||
make(Items.FLOWERING_AZALEA_LEAVES, PLANTS * 1.5)
|
||||
|
||||
make(Items.BONE, BONES)
|
||||
make(Items.STRING, STRINGS)
|
||||
make(Items.FEATHER, FEATHERS)
|
||||
|
||||
make(Items.PORKCHOP, ADVANCED_ORGANICS * 0.65)
|
||||
make(Items.BEEF, ADVANCED_ORGANICS * 0.65)
|
||||
make(Items.LEATHER, ADVANCED_ORGANICS * 0.7)
|
||||
make(Items.EGG, ADVANCED_ORGANICS * 0.75)
|
||||
make(Items.HONEYCOMB, ADVANCED_ORGANICS * 1.15)
|
||||
make(Items.BLAZE_ROD, ADVANCED_ORGANICS * 2.3)
|
||||
make(Items.ENDER_PEARL, ADVANCED_ORGANICS * 6.5)
|
||||
|
||||
make(Items.SLIME_BALL, SIMPLE_ORGANICS * 1.7)
|
||||
make(Items.INK_SAC, SIMPLE_ORGANICS * 1.4)
|
||||
make(Items.GLOW_INK_SAC, SIMPLE_ORGANICS * 2.1)
|
||||
make(Items.NAUTILUS_SHELL, SIMPLE_ORGANICS * 2.3)
|
||||
make(Items.HEART_OF_THE_SEA, SIMPLE_ORGANICS * 4)
|
||||
|
||||
make(Items.MUSIC_DISC_13, MUSIC_DISC)
|
||||
make(Items.MUSIC_DISC_CAT, MUSIC_DISC)
|
||||
make(Items.MUSIC_DISC_BLOCKS, MUSIC_DISC)
|
||||
make(Items.MUSIC_DISC_CHIRP, MUSIC_DISC)
|
||||
make(Items.MUSIC_DISC_FAR, MUSIC_DISC)
|
||||
make(Items.MUSIC_DISC_MALL, MUSIC_DISC)
|
||||
make(Items.MUSIC_DISC_MELLOHI, MUSIC_DISC)
|
||||
make(Items.MUSIC_DISC_STAL, MUSIC_DISC)
|
||||
make(Items.MUSIC_DISC_STRAD, MUSIC_DISC)
|
||||
make(Items.MUSIC_DISC_WARD, MUSIC_DISC)
|
||||
make(Items.MUSIC_DISC_11, MUSIC_DISC)
|
||||
make(Items.MUSIC_DISC_WAIT, MUSIC_DISC)
|
||||
make(Items.MUSIC_DISC_OTHERSIDE, MUSIC_DISC)
|
||||
make(Items.MUSIC_DISC_PIGSTEP, MUSIC_DISC)
|
||||
|
||||
make(Items.TUBE_CORAL, CORALS)
|
||||
make(Items.BRAIN_CORAL, CORALS)
|
||||
make(Items.BUBBLE_CORAL, CORALS)
|
||||
make(Items.FIRE_CORAL, CORALS)
|
||||
make(Items.HORN_CORAL, CORALS)
|
||||
|
||||
make(Items.SEA_PICKLE, CORALS * 1.27)
|
||||
|
||||
make(Items.DEAD_BRAIN_CORAL, DEAD_CORALS)
|
||||
make(Items.DEAD_BUBBLE_CORAL, DEAD_CORALS)
|
||||
make(Items.DEAD_FIRE_CORAL, DEAD_CORALS)
|
||||
make(Items.DEAD_HORN_CORAL, DEAD_CORALS)
|
||||
make(Items.DEAD_TUBE_CORAL, DEAD_CORALS)
|
||||
|
||||
derive(Items.IRON_INGOT, Items.IRON_NUGGET, 1.0 / 9.0, 1.0 / 9.0)
|
||||
derive(Items.GOLD_INGOT, Items.GOLD_NUGGET, 1.0 / 9.0, 1.0 / 9.0)
|
||||
}
|
||||
|
||||
private fun registerDerived() {
|
||||
deriveIfMissing(Items.BROWN_MUSHROOM, Items.BROWN_MUSHROOM_BLOCK)
|
||||
deriveIfMissing(Items.RED_MUSHROOM, Items.RED_MUSHROOM_BLOCK)
|
||||
deriveIfMissing(Items.COBWEB, Items.STRING)
|
||||
deriveIfMissing(Items.FARMLAND, Items.DIRT)
|
||||
|
||||
derive(Items.ANVIL, Items.CHIPPED_ANVIL, 0.75, 0.85)
|
||||
derive(Items.ANVIL, Items.DAMAGED_ANVIL, 0.6, 0.78)
|
||||
|
||||
derive(Items.WHITE_CONCRETE_POWDER, Items.WHITE_CONCRETE)
|
||||
derive(Items.ORANGE_CONCRETE_POWDER, Items.ORANGE_CONCRETE)
|
||||
derive(Items.MAGENTA_CONCRETE_POWDER, Items.MAGENTA_CONCRETE)
|
||||
derive(Items.LIGHT_BLUE_CONCRETE_POWDER, Items.LIGHT_BLUE_CONCRETE)
|
||||
derive(Items.YELLOW_CONCRETE_POWDER, Items.YELLOW_CONCRETE)
|
||||
derive(Items.LIME_CONCRETE_POWDER, Items.LIME_CONCRETE)
|
||||
derive(Items.PINK_CONCRETE_POWDER, Items.PINK_CONCRETE)
|
||||
derive(Items.GRAY_CONCRETE_POWDER, Items.GRAY_CONCRETE)
|
||||
derive(Items.LIGHT_GRAY_CONCRETE_POWDER, Items.LIGHT_GRAY_CONCRETE)
|
||||
derive(Items.CYAN_CONCRETE_POWDER, Items.CYAN_CONCRETE)
|
||||
derive(Items.PURPLE_CONCRETE_POWDER, Items.PURPLE_CONCRETE)
|
||||
derive(Items.BLUE_CONCRETE_POWDER, Items.BLUE_CONCRETE)
|
||||
derive(Items.BROWN_CONCRETE_POWDER, Items.BROWN_CONCRETE)
|
||||
derive(Items.GREEN_CONCRETE_POWDER, Items.GREEN_CONCRETE)
|
||||
derive(Items.RED_CONCRETE_POWDER, Items.RED_CONCRETE)
|
||||
derive(Items.BLACK_CONCRETE_POWDER, Items.BLACK_CONCRETE)
|
||||
}
|
@ -8,8 +8,11 @@ import com.google.gson.JsonObject
|
||||
import com.google.gson.JsonParseException
|
||||
import com.google.gson.JsonPrimitive
|
||||
import com.google.gson.JsonSyntaxException
|
||||
import com.mojang.blaze3d.platform.InputConstants
|
||||
import it.unimi.dsi.fastutil.objects.Reference2ObjectFunction
|
||||
import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap
|
||||
import net.minecraft.ChatFormatting
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.packs.resources.ResourceManager
|
||||
import net.minecraft.server.packs.resources.SimpleJsonResourceReloadListener
|
||||
@ -17,16 +20,33 @@ import net.minecraft.tags.ItemTags
|
||||
import net.minecraft.tags.TagKey
|
||||
import net.minecraft.util.profiling.ProfilerFiller
|
||||
import net.minecraft.world.item.Item
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.level.ItemLike
|
||||
import net.minecraftforge.event.AddReloadListenerEvent
|
||||
import net.minecraftforge.event.entity.player.ItemTooltipEvent
|
||||
import net.minecraftforge.registries.ForgeRegistries
|
||||
import org.apache.logging.log4j.LogManager
|
||||
import org.lwjgl.glfw.GLFW
|
||||
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
||||
import ru.dbotthepony.mc.otm.SystemTime
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryCapability
|
||||
import ru.dbotthepony.mc.otm.capability.drive.IMatteryDrive
|
||||
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
|
||||
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
||||
import ru.dbotthepony.mc.otm.core.formatMatterFull
|
||||
import ru.dbotthepony.mc.otm.core.formatSiComponent
|
||||
import ru.dbotthepony.mc.otm.core.integerDivisionDown
|
||||
import ru.dbotthepony.mc.otm.core.integerDivisionUp
|
||||
import ru.dbotthepony.mc.otm.core.isZero
|
||||
import ru.dbotthepony.mc.otm.core.orNull
|
||||
import ru.dbotthepony.mc.otm.core.probablyParallelStream
|
||||
import ru.dbotthepony.mc.otm.core.registryName
|
||||
import ru.dbotthepony.mc.otm.core.set
|
||||
import ru.dbotthepony.mc.otm.data.stream
|
||||
import ru.dbotthepony.mc.otm.storage.ItemStackWrapper
|
||||
import java.math.BigInteger
|
||||
import java.util.stream.Stream
|
||||
import kotlin.math.pow
|
||||
|
||||
object MatterManager : SimpleJsonResourceReloadListener(GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create(), "otm_matter") {
|
||||
const val DIRECTORY = "otm_matter"
|
||||
@ -663,6 +683,14 @@ object MatterManager : SimpleJsonResourceReloadListener(GsonBuilder().setPrettyP
|
||||
|
||||
val hasMatterValue: Boolean get() = matter.isPositive && complexity > 0.0
|
||||
|
||||
operator fun plus(other: IMatterValue): IMatterValue {
|
||||
return MatterValue(matter + other.matter, complexity + other.complexity)
|
||||
}
|
||||
|
||||
operator fun minus(other: IMatterValue): IMatterValue {
|
||||
return MatterValue(matter - other.matter, complexity - other.complexity)
|
||||
}
|
||||
|
||||
override fun compareTo(other: IMatterValue): Int {
|
||||
val matterComparison = matter.compareTo(other.matter)
|
||||
|
||||
@ -684,6 +712,11 @@ object MatterManager : SimpleJsonResourceReloadListener(GsonBuilder().setPrettyP
|
||||
}
|
||||
}
|
||||
|
||||
data class MatterValue(
|
||||
override val matter: ImpreciseFraction,
|
||||
override val complexity: Double
|
||||
) : IMatterValue
|
||||
|
||||
sealed class Entry(
|
||||
val modificationChain: List<ResourceLocation>,
|
||||
final override val matter: ImpreciseFraction,
|
||||
@ -724,9 +757,16 @@ object MatterManager : SimpleJsonResourceReloadListener(GsonBuilder().setPrettyP
|
||||
/**
|
||||
* Returns directly defined matter value
|
||||
*/
|
||||
@JvmStatic
|
||||
fun getDirect(value: Item): Entry {
|
||||
check(canCompute) { "MatteryManager is not ready to compute matter values" }
|
||||
|
||||
val get = computedEntries.get(value)
|
||||
|
||||
if (get != null) {
|
||||
return get
|
||||
}
|
||||
|
||||
synchronized(computedEntries) {
|
||||
return computedEntries.computeIfAbsent(value, Reference2ObjectFunction {
|
||||
it as Item
|
||||
@ -749,14 +789,185 @@ object MatterManager : SimpleJsonResourceReloadListener(GsonBuilder().setPrettyP
|
||||
}
|
||||
}
|
||||
|
||||
operator fun get(value: Item): IMatterValue {
|
||||
@JvmStatic
|
||||
val computedEntriesSize: Int get() = computedEntries.size
|
||||
|
||||
@JvmStatic
|
||||
fun stream(): Stream<Map.Entry<Item, Entry>> {
|
||||
return computedEntries.entries.stream().filter { it.value.hasMatterValue }
|
||||
}
|
||||
|
||||
private var resolvedEverything = false
|
||||
|
||||
/**
|
||||
* Iterates through [ForgeRegistries.ITEMS] if it hadn't already and resolves everything
|
||||
*
|
||||
* THIS IS A VERY SLOW OPERATION TO PERFORM!
|
||||
*/
|
||||
@JvmStatic
|
||||
fun resolveEverything() {
|
||||
if (resolvedEverything) {
|
||||
return
|
||||
}
|
||||
|
||||
val time = SystemTime()
|
||||
LOGGER.info("resolveEverything() was called")
|
||||
|
||||
for (value in ForgeRegistries.ITEMS.values) {
|
||||
getValue(value)
|
||||
}
|
||||
|
||||
resolvedEverything = true
|
||||
LOGGER.info("resolveEverything() finished in ${time.millis}ms")
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterates through [ForgeRegistries.ITEMS] if it hadn't already and resolves everything,
|
||||
* then returns stream of entries
|
||||
*
|
||||
* THIS IS A VERY SLOW OPERATION TO PERFORM!
|
||||
*/
|
||||
@JvmStatic
|
||||
fun resolveAndStream(): Stream<Map.Entry<Item, Entry>> {
|
||||
resolveEverything()
|
||||
return stream()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getValue(value: Item): IMatterValue {
|
||||
val direct = getDirect(value)
|
||||
|
||||
if (direct.hasMatterValue) {
|
||||
return direct
|
||||
}
|
||||
|
||||
return RecipeResolverManager[value]
|
||||
return RecipeResolverManager.getDetermined(value)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun hasMatterValue(value: Item): Boolean {
|
||||
return getValue(value).hasMatterValue
|
||||
}
|
||||
|
||||
private fun getValue(value: ItemStack, level: Int): IMatterValue {
|
||||
if (value.isEmpty) {
|
||||
return IMatterValue.Companion
|
||||
}
|
||||
|
||||
var matter: IMatterValue
|
||||
var undamagedMatterValue: IMatterValue
|
||||
|
||||
if (value.item is IMatterItem)
|
||||
matter = (value.item as IMatterItem).getMatterValue(value) ?: IMatterValue.Companion
|
||||
else
|
||||
matter = getValue(value.item)
|
||||
|
||||
if (matter.hasMatterValue && value.isDamageableItem) {
|
||||
val severity = 1.0 - value.damageValue.toDouble() / value.maxDamage.toDouble()
|
||||
undamagedMatterValue = matter
|
||||
matter = MatterValue(matter.matter * severity, matter.complexity * (0.5 + severity / 2))
|
||||
} else {
|
||||
undamagedMatterValue = matter
|
||||
}
|
||||
|
||||
val matterCap = value.getCapability(MatteryCapability.MATTER).orNull()
|
||||
|
||||
if (matterCap != null) {
|
||||
matter = MatterValue(matter.matter + matterCap.storedMatter, matter.complexity)
|
||||
undamagedMatterValue = MatterValue(undamagedMatterValue.matter + matterCap.storedMatter, undamagedMatterValue.complexity)
|
||||
}
|
||||
|
||||
val drive = value.getCapability(MatteryCapability.DRIVE).orNull()
|
||||
|
||||
if (drive != null && drive.storageType === OverdriveThatMatters.INSTANCE.ITEM_STORAGE()) {
|
||||
for (item in (drive as IMatteryDrive<ItemStackWrapper>).stacks) {
|
||||
val tuple = getValue(item.stack.stack, level + 1)
|
||||
|
||||
if (tuple.hasMatterValue) {
|
||||
matter += tuple
|
||||
undamagedMatterValue += tuple
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (matter.hasMatterValue && value.count > 1) {
|
||||
return MatterValue(matter.matter + undamagedMatterValue.matter * (value.count - 1), matter.complexity + undamagedMatterValue.complexity * (value.count - 1))
|
||||
}
|
||||
|
||||
return matter
|
||||
}
|
||||
|
||||
/**
|
||||
* Matter value for itemstack, accounting for capabilities and stack size
|
||||
*/
|
||||
@JvmStatic
|
||||
fun getValue(value: ItemStack): IMatterValue {
|
||||
return getValue(value, 0)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun hasMatterValue(value: ItemStack): Boolean {
|
||||
return getValue(value).hasMatterValue
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun canDecompose(value: Item): Boolean {
|
||||
if (value is IMatterItem)
|
||||
return value.canDecompose(ItemStack.EMPTY)
|
||||
|
||||
return getValue(value).hasMatterValue
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun canDecompose(value: ItemStack): Boolean {
|
||||
var can = true
|
||||
|
||||
if (value.item is IMatterItem)
|
||||
can = (value.item as IMatterItem).canDecompose(value)
|
||||
|
||||
can = can && (value.getCapability(MatteryCapability.MATTER).orNull()?.storedMatter ?: ImpreciseFraction.ZERO).isZero
|
||||
can = can && (value.getCapability(MatteryCapability.DRIVE).orNull()?.storedCount ?: BigInteger.ZERO).isZero
|
||||
|
||||
return can && getValue(value).hasMatterValue
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getResearchAdvance(complexity: Double): Double {
|
||||
if (complexity <= 0.0) {
|
||||
return 0.0
|
||||
}
|
||||
|
||||
return (1.0 / (complexity.pow(1.0 / 3.0) * 12.0).coerceAtLeast(0.01)).coerceAtMost(0.2).coerceAtLeast(0.025)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getResearchAdvance(stack: ItemStack): Double {
|
||||
return getResearchAdvance(getValue(stack).complexity)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getResearchAdvance(stack: ItemLike): Double {
|
||||
return getResearchAdvance(getValue(stack.asItem()).complexity)
|
||||
}
|
||||
|
||||
fun tooltipEvent(event: ItemTooltipEvent) {
|
||||
val window = Minecraft.getInstance().window.window
|
||||
|
||||
if (InputConstants.isKeyDown(window, GLFW.GLFW_KEY_LEFT_SHIFT) || InputConstants.isKeyDown(window, GLFW.GLFW_KEY_RIGHT_SHIFT)) {
|
||||
val matter = getValue(event.itemStack)
|
||||
|
||||
if (matter.hasMatterValue) {
|
||||
if (matter.complexity >= 1.0E-3) {
|
||||
event.toolTip.add(
|
||||
TranslatableComponent("otm.gui.matter.format_and_complexity",
|
||||
matter.matter.formatMatterFull(),
|
||||
matter.complexity.formatSiComponent(TranslatableComponent("otm.gui.ticks"))
|
||||
).withStyle(ChatFormatting.AQUA))
|
||||
} else {
|
||||
event.toolTip.add(matter.matter.formatMatterFull().withStyle(ChatFormatting.AQUA))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun reloadEvent(event: AddReloadListenerEvent) {
|
||||
@ -794,6 +1005,7 @@ object MatterManager : SimpleJsonResourceReloadListener(GsonBuilder().setPrettyP
|
||||
|
||||
try {
|
||||
canCompute = false
|
||||
resolvedEverything = false
|
||||
|
||||
keyEntries.clear()
|
||||
tagEntries.clear()
|
||||
|
@ -1,446 +0,0 @@
|
||||
package ru.dbotthepony.mc.otm.matter
|
||||
|
||||
import com.google.common.collect.Streams
|
||||
import com.mojang.blaze3d.platform.InputConstants
|
||||
import net.minecraft.ChatFormatting
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.network.FriendlyByteBuf
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.item.Item
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.level.ItemLike
|
||||
import net.minecraftforge.event.entity.player.ItemTooltipEvent
|
||||
import net.minecraftforge.event.entity.player.PlayerEvent
|
||||
import net.minecraftforge.network.NetworkEvent
|
||||
import net.minecraftforge.network.PacketDistributor
|
||||
import org.lwjgl.glfw.GLFW
|
||||
import ru.dbotthepony.mc.otm.*
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryCapability
|
||||
import ru.dbotthepony.mc.otm.capability.drive.IMatteryDrive
|
||||
import ru.dbotthepony.mc.otm.core.*
|
||||
import ru.dbotthepony.mc.otm.network.MatteryPacket
|
||||
import ru.dbotthepony.mc.otm.network.RegistryNetworkChannel
|
||||
import ru.dbotthepony.mc.otm.storage.ItemStackWrapper
|
||||
import java.math.BigInteger
|
||||
import java.util.function.Supplier
|
||||
import java.util.stream.Stream
|
||||
import kotlin.math.pow
|
||||
|
||||
internal var building = false
|
||||
|
||||
interface IMatterItem {
|
||||
fun getMatterValue(stack: ItemStack): MatterTuple?
|
||||
fun hasMatterValue(stack: ItemStack) = getMatterValue(stack) != null
|
||||
fun canDecompose(stack: ItemStack): Boolean
|
||||
}
|
||||
|
||||
private val rootEntries = HashMap<Item, MatterTuple>()
|
||||
private val derivedEntries = HashMap<Item, MatterTuple>()
|
||||
|
||||
/**
|
||||
* Nothing prevents you from writing to this map.
|
||||
* This derived class is designed solely to network YOUR changes to players online in real-time.
|
||||
*
|
||||
* If you use MapEntry#setValue, it is your fault this map go out of sync with clients.
|
||||
*/
|
||||
@JvmField
|
||||
val rootEntriesAccess = object : MutableMap<Item, MatterTuple> by rootEntries {
|
||||
override fun put(key: Item, value: MatterTuple): MatterTuple? {
|
||||
RegistryNetworkChannel.send(PacketDistributor.ALL.noArg(), RegistryPacketUpdate(MatterRegistryType.ROOT, key, value))
|
||||
return rootEntries.put(key, value)
|
||||
}
|
||||
|
||||
override fun putAll(from: Map<out Item, MatterTuple>) {
|
||||
rootEntries.putAll(from)
|
||||
|
||||
if (!building) {
|
||||
val distr = PacketDistributor.ALL.noArg()
|
||||
|
||||
for ((key, value) in from) {
|
||||
RegistryNetworkChannel.send(distr, RegistryPacketUpdate(MatterRegistryType.ROOT, key, value))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun remove(key: Item): MatterTuple? {
|
||||
val value = rootEntries.remove(key)
|
||||
|
||||
if (!building && value != null)
|
||||
RegistryNetworkChannel.send(PacketDistributor.ALL.noArg(), RegistryPacketRemove(MatterRegistryType.ROOT, key))
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
override fun clear() {
|
||||
rootEntries.clear()
|
||||
|
||||
if (!building && NULLABLE_MINECRAFT_SERVER != null) {
|
||||
RegistryNetworkChannel.send(PacketDistributor.ALL.noArg(), RegistryPacketClear.ROOT)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Nothing prevents you from writing to this map.
|
||||
* This derived class is designed solely to network YOUR changes to players online in real-time.
|
||||
*
|
||||
* If you use MapEntry#setValue, it is your fault this map go out of sync with clients.
|
||||
*/
|
||||
@JvmField
|
||||
val derivedEntriesAccess = object : MutableMap<Item, MatterTuple> by derivedEntries {
|
||||
override fun put(key: Item, value: MatterTuple): MatterTuple? {
|
||||
RegistryNetworkChannel.send(PacketDistributor.ALL.noArg(), RegistryPacketUpdate(MatterRegistryType.DERIVED, key, value))
|
||||
return derivedEntries.put(key, value)
|
||||
}
|
||||
|
||||
override fun putAll(from: Map<out Item, MatterTuple>) {
|
||||
derivedEntries.putAll(from)
|
||||
|
||||
if (!building) {
|
||||
val distr = PacketDistributor.ALL.noArg()
|
||||
|
||||
for ((key, value) in from) {
|
||||
RegistryNetworkChannel.send(distr, RegistryPacketUpdate(MatterRegistryType.DERIVED, key, value))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun remove(key: Item): MatterTuple? {
|
||||
val value = derivedEntries.remove(key)
|
||||
|
||||
if (!building && value != null)
|
||||
RegistryNetworkChannel.send(PacketDistributor.ALL.noArg(), RegistryPacketRemove(MatterRegistryType.DERIVED, key))
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
override fun clear() {
|
||||
derivedEntries.clear()
|
||||
|
||||
if (!building && NULLABLE_MINECRAFT_SERVER != null) {
|
||||
RegistryNetworkChannel.send(PacketDistributor.ALL.noArg(), RegistryPacketClear.DERIVED)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val matterRegistryStream: Stream<Map.Entry<Item, MatterTuple>> get() {
|
||||
return Streams.concat(rootEntries.entries.stream(), derivedEntries.entries.stream())
|
||||
}
|
||||
|
||||
fun getMatterValue(item: Item): MatterTuple {
|
||||
if (item is IMatterItem)
|
||||
return item.getMatterValue(ItemStack.EMPTY) ?: MatterTuple.ZERO
|
||||
|
||||
return MatterManager[item].let { MatterTuple(it.matter, it.complexity) }
|
||||
}
|
||||
|
||||
fun getMatterValueNullable(item: Item): MatterTuple? {
|
||||
if (item is IMatterItem)
|
||||
return item.getMatterValue(ItemStack.EMPTY)
|
||||
|
||||
return MatterManager[item].let { MatterTuple(it.matter, it.complexity) }
|
||||
}
|
||||
|
||||
fun hasMatterValue(item: Item): Boolean {
|
||||
if (item is IMatterItem)
|
||||
return item.hasMatterValue(ItemStack.EMPTY)
|
||||
|
||||
return !getMatterValue(item).isZero
|
||||
}
|
||||
|
||||
fun hasMatterValue(stack: ItemStack): Boolean {
|
||||
val item = stack.item
|
||||
|
||||
if (item is IMatterItem)
|
||||
return item.hasMatterValue(stack)
|
||||
|
||||
return !getMatterValue(stack).isZero
|
||||
}
|
||||
|
||||
fun canDecompose(item: Item): Boolean {
|
||||
if (item is IMatterItem)
|
||||
return item.canDecompose(ItemStack.EMPTY)
|
||||
|
||||
return hasMatterValue(item)
|
||||
}
|
||||
|
||||
fun canDecompose(stack: ItemStack): Boolean {
|
||||
val item = stack.item
|
||||
|
||||
if (item is IMatterItem)
|
||||
return item.canDecompose(stack)
|
||||
|
||||
return canDecompose(stack.item) &&
|
||||
(stack.getCapability(MatteryCapability.MATTER).orNull()?.storedMatter ?: ImpreciseFraction.ZERO).isZero &&
|
||||
(stack.getCapability(MatteryCapability.DRIVE).orNull()?.storedCount ?: BigInteger.ZERO).isZero
|
||||
}
|
||||
|
||||
private const val MAX_NESTING = 100
|
||||
|
||||
private fun getMatterValue(stack: ItemStack, level: Int): MatterTuple {
|
||||
if (level >= MAX_NESTING) {
|
||||
return MatterTuple.ZERO
|
||||
}
|
||||
|
||||
var matter = getMatterValue(stack.item)
|
||||
|
||||
if (stack.item is IMatterItem)
|
||||
matter = (stack.item as IMatterItem).getMatterValue(stack) ?: MatterTuple.ZERO
|
||||
|
||||
if (!matter.isZero && stack.isDamageableItem) {
|
||||
val severity = 1.0 - stack.damageValue.toDouble() / stack.maxDamage.toDouble()
|
||||
matter = MatterTuple(matter.value * severity, matter.complexity * (0.5 + severity / 2))
|
||||
}
|
||||
|
||||
val matterCap = stack.getCapability(MatteryCapability.MATTER).orNull()
|
||||
|
||||
if (matterCap != null) {
|
||||
matter = MatterTuple(matter.value + matterCap.storedMatter, matter.complexity)
|
||||
}
|
||||
|
||||
val drive = stack.getCapability(MatteryCapability.DRIVE).orNull()
|
||||
|
||||
if (drive != null && drive.storageType === OverdriveThatMatters.INSTANCE.ITEM_STORAGE()) {
|
||||
for (item in (drive as IMatteryDrive<ItemStackWrapper>).stacks) {
|
||||
val tuple = getMatterValue(item.stack.stack, level + 1)
|
||||
|
||||
if (!tuple.isZero) {
|
||||
matter += tuple
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return matter
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает массу предмета БЕЗ учёта размера стопки
|
||||
*/
|
||||
fun getMatterValue(stack: ItemStack): MatterTuple {
|
||||
return getMatterValue(stack, 0)
|
||||
}
|
||||
|
||||
fun getResearchAdvance(complexity: Double): Double {
|
||||
if (complexity <= 0.0) {
|
||||
return 0.0
|
||||
}
|
||||
|
||||
return (1.0 / (complexity.pow(1.0 / 3.0) * 12.0).coerceAtLeast(0.01)).coerceAtMost(0.2).coerceAtLeast(0.025)
|
||||
}
|
||||
|
||||
fun getResearchAdvance(stack: ItemStack): Double {
|
||||
return getResearchAdvance(getMatterValue(stack).complexity)
|
||||
}
|
||||
|
||||
fun getResearchAdvance(stack: ItemLike): Double {
|
||||
return getResearchAdvance(getMatterValue(stack.asItem()).complexity)
|
||||
}
|
||||
|
||||
fun onPlayerJoin(event: PlayerEvent.PlayerLoggedInEvent) {
|
||||
if (NULLABLE_MINECRAFT_SERVER != null) {
|
||||
RegistryNetworkChannel.send(PacketDistributor.PLAYER.with { event.entity as ServerPlayer }, RegistryPacketFullUpdate(MatterRegistryType.ROOT, rootEntries))
|
||||
RegistryNetworkChannel.send(PacketDistributor.PLAYER.with { event.entity as ServerPlayer }, RegistryPacketFullUpdate(MatterRegistryType.DERIVED, derivedEntries))
|
||||
}
|
||||
}
|
||||
|
||||
fun tooltipEvent(event: ItemTooltipEvent) {
|
||||
val window = Minecraft.getInstance().window.window
|
||||
|
||||
if (InputConstants.isKeyDown(window, GLFW.GLFW_KEY_LEFT_SHIFT) || InputConstants.isKeyDown(window, GLFW.GLFW_KEY_RIGHT_SHIFT)) {
|
||||
val matter = getMatterValue(event.itemStack)
|
||||
|
||||
if (!matter.isZero) {
|
||||
if (matter.complexity >= 1.0E-3) {
|
||||
event.toolTip.add(
|
||||
TranslatableComponent("otm.gui.matter.format_and_complexity",
|
||||
matter.value.formatMatterFull(),
|
||||
"%.3f".format(matter.complexity)
|
||||
).withStyle(ChatFormatting.AQUA))
|
||||
} else {
|
||||
event.toolTip.add(matter.value.formatMatterFull().withStyle(ChatFormatting.AQUA))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class MatterTuple(val value: ImpreciseFraction, val complexity: Double): Comparable<MatterTuple> {
|
||||
operator fun plus(other: MatterTuple) = MatterTuple(value + other.value, complexity + other.complexity)
|
||||
operator fun minus(other: MatterTuple) = MatterTuple(value - other.value, complexity - other.complexity)
|
||||
|
||||
override operator fun compareTo(other: MatterTuple): Int {
|
||||
if (compareValues(other) != 0) {
|
||||
return compareComplexity(other)
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
fun compareValues(other: MatterTuple) = value.compareTo(other.value)
|
||||
fun compareComplexity(other: MatterTuple): Int {
|
||||
if (complexity == other.complexity)
|
||||
return 0
|
||||
|
||||
return if (complexity < other.complexity) -1 else 1
|
||||
}
|
||||
|
||||
fun write(buff: FriendlyByteBuf) {
|
||||
buff.writeImpreciseFraction(value)
|
||||
buff.writeDouble(complexity)
|
||||
}
|
||||
|
||||
val isZero get() = value.isZero
|
||||
val isZeroComplexity get() = complexity <= 0.0
|
||||
|
||||
companion object {
|
||||
@JvmField val ZERO = MatterTuple(ImpreciseFraction.ZERO, 0.0)
|
||||
|
||||
fun read(buff: FriendlyByteBuf): MatterTuple {
|
||||
return MatterTuple(buff.readImpreciseFraction(), buff.readDouble())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal enum class MatterRegistryType {ROOT, DERIVED}
|
||||
|
||||
internal class RegistryPacketUpdate(val type: MatterRegistryType, val item: Item, val tuple: MatterTuple) : MatteryPacket {
|
||||
override fun play(context: Supplier<NetworkEvent.Context>) {
|
||||
context.get().packetHandled = true
|
||||
|
||||
when (type) {
|
||||
MatterRegistryType.ROOT -> {
|
||||
synchronized(rootEntries) {
|
||||
rootEntries[item] = tuple
|
||||
}
|
||||
}
|
||||
|
||||
MatterRegistryType.DERIVED -> {
|
||||
synchronized(derivedEntries) {
|
||||
derivedEntries[item] = tuple
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun write(buff: FriendlyByteBuf) {
|
||||
buff.writeEnum(type)
|
||||
buff.writeRegistryId(item)
|
||||
tuple.write(buff)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun read(buff: FriendlyByteBuf): RegistryPacketUpdate {
|
||||
return RegistryPacketUpdate(buff.readEnum(MatterRegistryType::class.java), buff.readRegistryIdSafe(Item::class.java), MatterTuple.read(buff))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class RegistryPacketRemove(val type: MatterRegistryType, val item: Item) : MatteryPacket {
|
||||
override fun play(context: Supplier<NetworkEvent.Context>) {
|
||||
context.get().packetHandled = true
|
||||
|
||||
when (type) {
|
||||
MatterRegistryType.ROOT -> {
|
||||
synchronized(rootEntries) {
|
||||
rootEntries.remove(item)
|
||||
}
|
||||
}
|
||||
|
||||
MatterRegistryType.DERIVED -> {
|
||||
synchronized(derivedEntries) {
|
||||
derivedEntries.remove(item)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun write(buff: FriendlyByteBuf) {
|
||||
buff.writeEnum(type)
|
||||
buff.writeRegistryId(item)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun read(buff: FriendlyByteBuf): RegistryPacketRemove {
|
||||
return RegistryPacketRemove(buff.readEnum(MatterRegistryType::class.java), buff.readRegistryIdSafe(Item::class.java))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class RegistryPacketFullUpdate(val type: MatterRegistryType, val map: Map<Item, MatterTuple>) : MatteryPacket {
|
||||
override fun play(context: Supplier<NetworkEvent.Context>) {
|
||||
context.get().packetHandled = true
|
||||
|
||||
when (type) {
|
||||
MatterRegistryType.ROOT -> {
|
||||
synchronized(rootEntries) {
|
||||
rootEntries.clear()
|
||||
rootEntries.putAll(map)
|
||||
}
|
||||
}
|
||||
|
||||
MatterRegistryType.DERIVED -> {
|
||||
synchronized(derivedEntries) {
|
||||
derivedEntries.clear()
|
||||
derivedEntries.putAll(map)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun write(buff: FriendlyByteBuf) {
|
||||
buff.writeEnum(type)
|
||||
buff.writeInt(map.size)
|
||||
|
||||
for ((key, value) in map) {
|
||||
buff.writeRegistryId(key)
|
||||
value.write(buff)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun read(buff: FriendlyByteBuf): RegistryPacketFullUpdate {
|
||||
val map = HashMap<Item, MatterTuple>()
|
||||
val type = buff.readEnum(MatterRegistryType::class.java)
|
||||
|
||||
val size = buff.readInt()
|
||||
|
||||
for (i in 0 until size) {
|
||||
map[buff.readRegistryId()] = MatterTuple.read(buff)
|
||||
}
|
||||
|
||||
return RegistryPacketFullUpdate(type, map)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal enum class RegistryPacketClear(val type: MatterRegistryType) : MatteryPacket {
|
||||
ROOT(MatterRegistryType.ROOT),
|
||||
DERIVED(MatterRegistryType.DERIVED);
|
||||
|
||||
override fun play(context: Supplier<NetworkEvent.Context>) {
|
||||
context.get().packetHandled = true
|
||||
|
||||
when (type) {
|
||||
MatterRegistryType.ROOT -> {
|
||||
synchronized(rootEntries) {
|
||||
rootEntries.clear()
|
||||
}
|
||||
}
|
||||
|
||||
MatterRegistryType.DERIVED -> {
|
||||
synchronized(derivedEntries) {
|
||||
derivedEntries.clear()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun write(buff: FriendlyByteBuf) {
|
||||
buff.writeEnum(type)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun read(buff: FriendlyByteBuf): RegistryPacketClear {
|
||||
return buff.readEnum(RegistryPacketClear::class.java)
|
||||
}
|
||||
}
|
||||
}
|
@ -210,7 +210,7 @@ object RecipeResolverManager : SimpleJsonResourceReloadListener(GsonBuilder().se
|
||||
}
|
||||
}
|
||||
|
||||
operator fun get(index: Item): MatterManager.IMatterValue {
|
||||
fun getDetermined(index: Item): MatterManager.IMatterValue {
|
||||
return determinedValues[index] ?: MatterManager.IMatterValue.Companion
|
||||
}
|
||||
|
||||
@ -309,10 +309,7 @@ object RecipeResolverManager : SimpleJsonResourceReloadListener(GsonBuilder().se
|
||||
return Result.MISSING
|
||||
}
|
||||
|
||||
val result = object : MatterManager.IMatterValue {
|
||||
override val matter: ImpreciseFraction = minimalMatter
|
||||
override val complexity: Double = minimalComplexity
|
||||
}
|
||||
val result = MatterManager.MatterValue(minimalMatter, minimalComplexity)
|
||||
|
||||
changes = true
|
||||
determinedValues[item] = result
|
||||
|
@ -10,8 +10,8 @@ import net.minecraft.world.SimpleContainer
|
||||
import net.minecraft.world.inventory.Slot
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryCapability
|
||||
import ru.dbotthepony.mc.otm.matter.canDecompose
|
||||
import ru.dbotthepony.mc.otm.core.orNull
|
||||
import ru.dbotthepony.mc.otm.matter.MatterManager
|
||||
import ru.dbotthepony.mc.otm.registry.MMenus
|
||||
|
||||
class MatterDecomposerMenu @JvmOverloads constructor(
|
||||
@ -30,7 +30,7 @@ class MatterDecomposerMenu @JvmOverloads constructor(
|
||||
|
||||
// Вход
|
||||
input = object : MatterySlot(container, 0) {
|
||||
override fun mayPlace(p_40231_: ItemStack) = canDecompose(p_40231_)
|
||||
override fun mayPlace(itemStack: ItemStack) = MatterManager.canDecompose(itemStack)
|
||||
}
|
||||
|
||||
// Выход
|
||||
|
@ -6,12 +6,10 @@ import ru.dbotthepony.mc.otm.block.entity.matter.MatterScannerBlockEntity
|
||||
import ru.dbotthepony.mc.otm.menu.widget.ProgressGaugeWidget
|
||||
import ru.dbotthepony.mc.otm.menu.widget.LevelGaugeWidget
|
||||
import net.minecraft.world.SimpleContainer
|
||||
import net.minecraft.world.inventory.Slot
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
|
||||
import ru.dbotthepony.mc.otm.matter.canDecompose
|
||||
import ru.dbotthepony.mc.otm.matter.MatterManager
|
||||
import ru.dbotthepony.mc.otm.registry.MMenus
|
||||
import java.math.BigInteger
|
||||
|
||||
class MatterScannerMenu @JvmOverloads constructor(
|
||||
p_38852_: Int,
|
||||
@ -28,9 +26,7 @@ class MatterScannerMenu @JvmOverloads constructor(
|
||||
val container = tile?.container ?: SimpleContainer(1)
|
||||
|
||||
input = object : MatterySlot(container, 0, 64, 38) {
|
||||
override fun mayPlace(p_40231_: ItemStack): Boolean {
|
||||
return canDecompose(p_40231_)
|
||||
}
|
||||
override fun mayPlace(itemStack: ItemStack) = MatterManager.canDecompose(itemStack)
|
||||
}
|
||||
|
||||
addSlot(input)
|
||||
|
@ -2,21 +2,12 @@ package ru.dbotthepony.mc.otm.network
|
||||
|
||||
import net.minecraftforge.network.NetworkDirection
|
||||
import ru.dbotthepony.mc.otm.android.AndroidResearchManager
|
||||
import ru.dbotthepony.mc.otm.matter.RegistryPacketClear
|
||||
import ru.dbotthepony.mc.otm.matter.RegistryPacketFullUpdate
|
||||
import ru.dbotthepony.mc.otm.matter.RegistryPacketRemove
|
||||
import ru.dbotthepony.mc.otm.matter.RegistryPacketUpdate
|
||||
|
||||
object RegistryNetworkChannel : MatteryNetworkChannel(
|
||||
version = "1",
|
||||
name = "registry"
|
||||
) {
|
||||
fun register() {
|
||||
add(RegistryPacketRemove::class.java, RegistryPacketRemove.Companion::read, NetworkDirection.PLAY_TO_CLIENT)
|
||||
add(RegistryPacketClear::class.java, RegistryPacketClear.Companion::read, NetworkDirection.PLAY_TO_CLIENT)
|
||||
add(RegistryPacketFullUpdate::class.java, RegistryPacketFullUpdate.Companion::read, NetworkDirection.PLAY_TO_CLIENT)
|
||||
add(RegistryPacketUpdate::class.java, RegistryPacketUpdate.Companion::read, NetworkDirection.PLAY_TO_CLIENT)
|
||||
|
||||
add(AndroidResearchManager.SyncPacket::class.java, AndroidResearchManager::readSyncPacket, NetworkDirection.PLAY_TO_CLIENT)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user