Make it compile

This commit is contained in:
DBotThePony 2022-11-06 00:29:28 +07:00
parent 68a1e8c9e8
commit 0cf1bbcf24
Signed by: DBot
GPG Key ID: DCC23B5715498507
18 changed files with 305 additions and 1031 deletions

View File

@ -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")

View File

@ -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);

View File

@ -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
}
}
}

View File

@ -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
}
}

View File

@ -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)
}
}

View File

@ -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,

View File

@ -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

View File

@ -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)

View File

@ -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,

View File

@ -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

View File

@ -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
}

View File

@ -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)
}

View File

@ -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()

View File

@ -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)
}
}
}

View File

@ -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

View File

@ -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)
}
// Выход

View File

@ -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)

View File

@ -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)
}
}