Normalized lists of research

This commit is contained in:
DBotThePony 2022-08-19 18:08:38 +07:00
parent 4fc037327f
commit 589d3a5499
Signed by: DBot
GPG Key ID: DCC23B5715498507
4 changed files with 155 additions and 27 deletions

View File

@ -141,8 +141,8 @@ abstract class AndroidResearch(val type: AndroidResearchType<*>, val capability:
isResearched = nbt.getBoolean("researched")
}
inline val prerequisites get() = type.prerequisites
inline val unlocks get() = type.unlocks
inline val blockedBy get() = type.blockedBy
inline val blocking get() = type.blocking
inline val prerequisites get() = type.definedPrerequisites
inline val unlocks get() = type.flatUnlocks
inline val blockedBy get() = type.definedBlockedBy
inline val blocking get() = type.flatBlocking
}

View File

@ -335,7 +335,7 @@ class AndroidResearchBuilder(
))
}
for (value in this.type.prerequisites) {
for (value in this.type.flatPrerequisites) {
val instance = capability.getResearch(value)
builder.add(TranslatableComponent("android_research.status.requires", instance.screenTooltipHeader).withStyle(
@ -346,11 +346,11 @@ class AndroidResearchBuilder(
))
}
for (value in this.type.blockedBy) {
for (value in this.type.definedBlockedBy) {
builder.add(TranslatableComponent("android_research.status.blocked_by", capability.getResearch(value).screenTooltipHeader).withStyle(ChatFormatting.DARK_RED))
}
for (value in this.type.blocking) {
for (value in this.type.flatBlocking) {
builder.add(TranslatableComponent("android_research.status.blocks", capability.getResearch(value).screenTooltipHeader).withStyle(ChatFormatting.DARK_RED))
}
@ -367,7 +367,7 @@ class AndroidResearchBuilder(
override val displayDescription: List<Component>
get() = description ?: super.displayDescription
override val prerequisites: List<AndroidResearchType<*>> by lazy {
override val definedPrerequisites: List<AndroidResearchType<*>> by lazy {
val builder = ImmutableList.builder<AndroidResearchType<*>>()
for ((value, rigid) in prerequisites) {
@ -383,7 +383,7 @@ class AndroidResearchBuilder(
builder.build()
}
override val blockedBy: List<AndroidResearchType<*>> by lazy {
override val definedBlockedBy: List<AndroidResearchType<*>> by lazy {
val builder = ImmutableList.builder<AndroidResearchType<*>>()
for ((value, rigid) in blockers) {

View File

@ -1,6 +1,7 @@
package ru.dbotthepony.mc.otm.android
import com.google.common.collect.ImmutableList
import it.unimi.dsi.fastutil.objects.ObjectArraySet
import net.minecraft.network.chat.Component
import net.minecraft.network.chat.ComponentContents
import net.minecraft.network.chat.MutableComponent
@ -14,17 +15,150 @@ fun interface AndroidResearchFactory<R : AndroidResearch> {
fun factory(type: AndroidResearchType<*>, capability: AndroidCapabilityPlayer): R
}
private fun findPrerequisites(
initial: Collection<AndroidResearchType<*>>,
add: MutableSet<AndroidResearchType<*>> = HashSet(),
top: Boolean = true
): Set<AndroidResearchType<*>> {
for (value in initial) {
if (!top) {
add.add(value)
}
findPrerequisites(value.definedPrerequisites, add, false)
}
return add
}
private fun findAllPrerequisites(
initial: Collection<AndroidResearchType<*>>,
add: MutableSet<AndroidResearchType<*>> = HashSet(),
): Set<AndroidResearchType<*>> {
for (value in initial) {
add.add(value)
findAllPrerequisites(value.flatPrerequisites, add)
}
return add
}
private fun findAllChildren(
initial: Collection<AndroidResearchType<*>>,
add: MutableSet<AndroidResearchType<*>> = HashSet(),
): Set<AndroidResearchType<*>> {
for (value in initial) {
add.add(value)
findAllChildren(value.flatUnlocks, add)
}
return add
}
open class AndroidResearchType<R : AndroidResearch>(
protected val factory: AndroidResearchFactory<R>
) {
open val prerequisites: List<AndroidResearchType<*>> get() = emptyList()
open val blockedBy: List<AndroidResearchType<*>> get() = emptyList()
val researchTreeDepth: Int by lazy {
if (flatPrerequisites.isEmpty()) {
return@lazy 0
}
val blocking: List<AndroidResearchType<*>> by lazy {
var depth = 1
for (value in flatPrerequisites) {
depth = depth.coerceAtLeast(value.researchTreeDepth + 1)
}
return@lazy depth
}
/**
* Prerequisites as-is
*/
open val definedPrerequisites: List<AndroidResearchType<*>> get() = emptyList()
/**
* Blocked by list as-is
*/
open val definedBlockedBy: List<AndroidResearchType<*>> get() = emptyList()
/**
* Flat list of research preceding this research.
*
* This list won't contain research following the same research path twice (guaranteed to be flat).
*
* E.g.
*
* * C depends on B
* * B depends on A
*
* C specify both B and A as it's prerequisites, [flatPrerequisites] will contain only B, when [definedPrerequisites] will contain
* both B and A
*/
val flatPrerequisites: List<AndroidResearchType<*>> by lazy {
val parentPrerequisites = findPrerequisites(definedPrerequisites)
val builder = ImmutableList.builder<AndroidResearchType<*>>()
for (value in definedPrerequisites) {
if (value !in parentPrerequisites) {
builder.add(value)
}
}
builder.build()
}
/**
* All prerequisite research, including indirect ones
*/
val allPrerequisites: List<AndroidResearchType<*>> by lazy {
ImmutableList.copyOf(findAllPrerequisites(flatPrerequisites))
}
/**
* Flat list of research blocked by this research.
*
* This list won't contain children of any blocked research (guaranteed to be flat).
*
* E.g.
*
* * C depends on B
* * B is blocked by A
* * C is blocked by A
*
* Both C and B specify A as it's blockers, [flatBlocking] will contain only B, because C is blocked by A through B.
*/
val flatBlocking: List<AndroidResearchType<*>> by lazy {
val list = ImmutableList.builder<AndroidResearchType<*>>()
for (research in MRegistry.ANDROID_RESEARCH) {
if (research.blockedBy.contains(this)) {
if (this in research.definedBlockedBy) {
var hit = false
for (parent in research.allPrerequisites) {
if (this in parent.definedBlockedBy) {
hit = true
break
}
}
if (!hit) {
list.add(research)
}
}
}
return@lazy list.build()
}
/**
* All research directly unlocked by this research.
*/
val flatUnlocks: List<AndroidResearchType<*>> by lazy {
val list = ImmutableList.builder<AndroidResearchType<*>>()
for (research in MRegistry.ANDROID_RESEARCH) {
if (this in research.flatPrerequisites) {
list.add(research)
}
}
@ -32,16 +166,11 @@ open class AndroidResearchType<R : AndroidResearch>(
return@lazy list.build()
}
val unlocks: List<AndroidResearchType<*>> by lazy {
val list = ImmutableList.builder<AndroidResearchType<*>>()
for (research in MRegistry.ANDROID_RESEARCH) {
if (research.prerequisites.contains(this)) {
list.add(research)
}
}
return@lazy list.build()
/**
* All research unlocked by this research, including indirect ones
*/
val allUnlocks: List<AndroidResearchType<*>> by lazy {
ImmutableList.copyOf(findAllChildren(flatUnlocks))
}
fun factory(capability: AndroidCapabilityPlayer) = factory.factory(this, capability)

View File

@ -21,7 +21,6 @@ import ru.dbotthepony.mc.otm.core.RGBAColor
import ru.dbotthepony.mc.otm.menu.AndroidStationMenu
import ru.dbotthepony.mc.otm.network.AndroidNetworkChannel
import ru.dbotthepony.mc.otm.network.AndroidResearchRequestPacket
import ru.dbotthepony.mc.otm.network.MatteryNetworking
import ru.dbotthepony.mc.otm.registry.MRegistry
import java.util.*
@ -130,12 +129,12 @@ class AndroidStationScreen constructor(p_97741_: AndroidStationMenu, p_97742_: I
createdButtonsIdx[level]++
rowsWidth[level] += 22f
for (_research in research.unlocks) {
for (_research in research.flatUnlocks) {
dive(cap, _research, level + 1)
}
if (level > 0) {
for (_research in research.prerequisites) {
for (_research in research.definedPrerequisites) {
dive(cap, _research, level - 1)
}
}
@ -164,7 +163,7 @@ class AndroidStationScreen constructor(p_97741_: AndroidStationMenu, p_97742_: I
nextX = 0f
for (research in MRegistry.ANDROID_RESEARCH.values) {
if (research.prerequisites.size == 0) {
if (research.definedPrerequisites.size == 0) {
dive(it, research, 0)
var max = 0f