Revisit how android research datapacks work
Instead of "feature results" provide them with just "results", which reference arbitrary features from registry Do the same to research description, with its own registry
This commit is contained in:
parent
dfa14ca2a1
commit
09db4ad9e9
@ -4,6 +4,9 @@ import net.minecraft.tags.ItemTags
|
|||||||
import net.minecraft.world.item.Items
|
import net.minecraft.world.item.Items
|
||||||
import net.minecraftforge.common.Tags
|
import net.minecraftforge.common.Tags
|
||||||
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
||||||
|
import ru.dbotthepony.mc.otm.android.AndroidResearchDescriptions
|
||||||
|
import ru.dbotthepony.mc.otm.android.AndroidResearchResult
|
||||||
|
import ru.dbotthepony.mc.otm.android.AndroidResearchResults
|
||||||
import ru.dbotthepony.mc.otm.android.AndroidResearchType
|
import ru.dbotthepony.mc.otm.android.AndroidResearchType
|
||||||
import ru.dbotthepony.mc.otm.android.feature.EnderTeleporterFeature
|
import ru.dbotthepony.mc.otm.android.feature.EnderTeleporterFeature
|
||||||
import ru.dbotthepony.mc.otm.android.feature.FallDampenersFeature
|
import ru.dbotthepony.mc.otm.android.feature.FallDampenersFeature
|
||||||
@ -132,11 +135,13 @@ fun addResearchData(serializer: Consumer<AndroidResearchType>, lang: MatteryLang
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
.addItem(MItemTags.COPPER_WIRES, 4 + i * 2)
|
.addItem(MItemTags.COPPER_WIRES, 4 + i * 2)
|
||||||
.addFeatureResult(OverdriveThatMatters.loc(MNames.LIMB_OVERCLOCKING), i)
|
|
||||||
|
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
|
research.addFeatureLevel(AndroidFeatures.LIMB_OVERCLOCKING)
|
||||||
research.addPrerequisite(OverdriveThatMatters.loc(MNames.LIMB_OVERCLOCKING_LIST[i - 1]), rigid = true)
|
research.addPrerequisite(OverdriveThatMatters.loc(MNames.LIMB_OVERCLOCKING_LIST[i - 1]), rigid = true)
|
||||||
research.addItem(MItemTags.GOLD_WIRES, i * 2)
|
research.addItem(MItemTags.GOLD_WIRES, i * 2)
|
||||||
|
} else {
|
||||||
|
research.addFeatureResult(AndroidFeatures.LIMB_OVERCLOCKING)
|
||||||
}
|
}
|
||||||
|
|
||||||
research.build()
|
research.build()
|
||||||
@ -155,18 +160,20 @@ fun addResearchData(serializer: Consumer<AndroidResearchType>, lang: MatteryLang
|
|||||||
(i + 1) * 15
|
(i + 1) * 15
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.addFeatureResult(AndroidFeatures.ATTACK_BOOST, i)
|
|
||||||
.addBlocker(NANOBOTS_ARMOR)
|
.addBlocker(NANOBOTS_ARMOR)
|
||||||
|
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
|
research.addFeatureLevel(AndroidFeatures.ATTACK_BOOST)
|
||||||
research.addPrerequisite(OverdriveThatMatters.loc(MNames.ATTACK_BOOST_LIST[i - 1]), rigid = true)
|
research.addPrerequisite(OverdriveThatMatters.loc(MNames.ATTACK_BOOST_LIST[i - 1]), rigid = true)
|
||||||
|
} else {
|
||||||
|
research.addFeatureResult(AndroidFeatures.ATTACK_BOOST)
|
||||||
}
|
}
|
||||||
|
|
||||||
research.build()
|
research.build()
|
||||||
})
|
})
|
||||||
|
|
||||||
regenList.add(run {
|
regenList.add(run {
|
||||||
val regeneration = AndroidResearchType.Builder(modLocation(MNames.NANOBOTS_REGENERATION_LIST[i]))
|
val research = AndroidResearchType.Builder(modLocation(MNames.NANOBOTS_REGENERATION_LIST[i]))
|
||||||
.withExperience(20 + i * 6)
|
.withExperience(20 + i * 6)
|
||||||
.withIconText(TextComponent((i + 1).toString()))
|
.withIconText(TextComponent((i + 1).toString()))
|
||||||
.withIcon(ResearchIcons.ICON_NANOBOTS)
|
.withIcon(ResearchIcons.ICON_NANOBOTS)
|
||||||
@ -179,15 +186,16 @@ fun addResearchData(serializer: Consumer<AndroidResearchType>, lang: MatteryLang
|
|||||||
.addItem(MItems.MATTER_CAPACITOR_PARTS, 1)
|
.addItem(MItems.MATTER_CAPACITOR_PARTS, 1)
|
||||||
.addItem(Items.SUGAR, 2 + i * 2)
|
.addItem(Items.SUGAR, 2 + i * 2)
|
||||||
.addItem(Tags.Items.DUSTS_REDSTONE, 2 + i * 2)
|
.addItem(Tags.Items.DUSTS_REDSTONE, 2 + i * 2)
|
||||||
.addFeatureResult(AndroidFeatures.NANOBOTS_REGENERATION, i)
|
|
||||||
|
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
regeneration.addPrerequisite(OverdriveThatMatters.loc(MNames.NANOBOTS_REGENERATION_LIST[i - 1]), rigid = true)
|
research.addFeatureLevel(AndroidFeatures.NANOBOTS_REGENERATION)
|
||||||
|
research.addPrerequisite(OverdriveThatMatters.loc(MNames.NANOBOTS_REGENERATION_LIST[i - 1]), rigid = true)
|
||||||
} else {
|
} else {
|
||||||
regeneration.addPrerequisite(OverdriveThatMatters.loc(MNames.NANOBOTS), rigid = true)
|
research.addPrerequisite(OverdriveThatMatters.loc(MNames.NANOBOTS), rigid = true)
|
||||||
|
research.addFeatureResult(AndroidFeatures.NANOBOTS_REGENERATION)
|
||||||
}
|
}
|
||||||
|
|
||||||
regeneration.build()
|
research.build()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -216,10 +224,7 @@ fun addResearchData(serializer: Consumer<AndroidResearchType>, lang: MatteryLang
|
|||||||
.addItem(MItemTags.TRITANIUM_PLATES, 2 + i * 2)
|
.addItem(MItemTags.TRITANIUM_PLATES, 2 + i * 2)
|
||||||
.addItem(Items.SUGAR, 1 + i)
|
.addItem(Items.SUGAR, 1 + i)
|
||||||
.addItem(MItems.ELECTROMAGNET)
|
.addItem(MItems.ELECTROMAGNET)
|
||||||
.addFeatureResult(AndroidFeatures.NANOBOTS_ARMOR, 0,
|
.addResult(AndroidResearchResults.NANOBOTS_ARMOR_STRENGTH)
|
||||||
transformersUp = listOf(NanobotsArmorFeature.STRENGTH_TRANSFORMER_UP.bind(level)),
|
|
||||||
transformersDown = listOf(NanobotsArmorFeature.STRENGTH_TRANSFORMER_DOWN.bind(level)),
|
|
||||||
)
|
|
||||||
.build()
|
.build()
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -243,10 +248,7 @@ fun addResearchData(serializer: Consumer<AndroidResearchType>, lang: MatteryLang
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
.addItem(Tags.Items.DUSTS_REDSTONE, 4 + i * 4)
|
.addItem(Tags.Items.DUSTS_REDSTONE, 4 + i * 4)
|
||||||
.addFeatureResult(AndroidFeatures.NANOBOTS_ARMOR, 0,
|
.addResult(AndroidResearchResults.NANOBOTS_ARMOR_SPEED)
|
||||||
transformersUp = listOf(NanobotsArmorFeature.SPEED_TRANSFORMER_UP.bind(level)),
|
|
||||||
transformersDown = listOf(NanobotsArmorFeature.SPEED_TRANSFORMER_DOWN.bind(level)),
|
|
||||||
)
|
|
||||||
.build()
|
.build()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -261,7 +263,7 @@ fun addResearchData(serializer: Consumer<AndroidResearchType>, lang: MatteryLang
|
|||||||
AndroidResearchType.Builder(modLocation(MNames.SHOCKWAVE))
|
AndroidResearchType.Builder(modLocation(MNames.SHOCKWAVE))
|
||||||
.withExperience(40)
|
.withExperience(40)
|
||||||
.withDescription(0 .. 1)
|
.withDescription(0 .. 1)
|
||||||
.appendDescription(ShockwaveFeature.POWER_COST_DESCRIPTION)
|
.withDescription(AndroidResearchDescriptions.SHOCKWAVE)
|
||||||
.withIcon(ResearchIcons.ICON_SHOCKWAVE)
|
.withIcon(ResearchIcons.ICON_SHOCKWAVE)
|
||||||
.addFeatureResult(AndroidFeatures.SHOCKWAVE)
|
.addFeatureResult(AndroidFeatures.SHOCKWAVE)
|
||||||
.addPrerequisite(attackBoostList[2])
|
.addPrerequisite(attackBoostList[2])
|
||||||
@ -276,7 +278,7 @@ fun addResearchData(serializer: Consumer<AndroidResearchType>, lang: MatteryLang
|
|||||||
AndroidResearchType.Builder(modLocation(MNames.ITEM_MAGNET))
|
AndroidResearchType.Builder(modLocation(MNames.ITEM_MAGNET))
|
||||||
.withExperience(28)
|
.withExperience(28)
|
||||||
.withDescription(0 .. 1)
|
.withDescription(0 .. 1)
|
||||||
.appendDescription(ItemMagnetFeature.POWER_COST_DESCRIPTION)
|
.withDescription(AndroidResearchDescriptions.ITEM_MAGNET)
|
||||||
.withIcon(ResearchIcons.ICON_ITEM_MAGNET)
|
.withIcon(ResearchIcons.ICON_ITEM_MAGNET)
|
||||||
.addFeatureResult(AndroidFeatures.ITEM_MAGNET)
|
.addFeatureResult(AndroidFeatures.ITEM_MAGNET)
|
||||||
.addPrerequisite(STEP_ASSIST)
|
.addPrerequisite(STEP_ASSIST)
|
||||||
@ -292,9 +294,9 @@ fun addResearchData(serializer: Consumer<AndroidResearchType>, lang: MatteryLang
|
|||||||
AndroidResearchType.Builder(modLocation(MNames.FALL_DAMPENERS + "_1"))
|
AndroidResearchType.Builder(modLocation(MNames.FALL_DAMPENERS + "_1"))
|
||||||
.withExperience(25)
|
.withExperience(25)
|
||||||
.withDescription()
|
.withDescription()
|
||||||
.appendDescription(FallDampenersFeature.DESCRIPTION.bind(1))
|
.withDescription(AndroidResearchDescriptions.FALL_DAMPENERS.Instance(1))
|
||||||
.withIcon(ResearchIcons.ICON_FEATHER_FALLING)
|
.withIcon(ResearchIcons.ICON_FEATHER_FALLING)
|
||||||
.addFeatureResult(AndroidFeatures.FALL_DAMPENERS, 0)
|
.addFeatureResult(AndroidFeatures.FALL_DAMPENERS)
|
||||||
.addPrerequisite(STEP_ASSIST)
|
.addPrerequisite(STEP_ASSIST)
|
||||||
.addItem(MItems.ELECTROMAGNET, 2)
|
.addItem(MItems.ELECTROMAGNET, 2)
|
||||||
.addItem(ItemTags.WOOL, 2)
|
.addItem(ItemTags.WOOL, 2)
|
||||||
@ -305,9 +307,9 @@ fun addResearchData(serializer: Consumer<AndroidResearchType>, lang: MatteryLang
|
|||||||
AndroidResearchType.Builder(modLocation(MNames.FALL_DAMPENERS + "_2"))
|
AndroidResearchType.Builder(modLocation(MNames.FALL_DAMPENERS + "_2"))
|
||||||
.withExperience(30)
|
.withExperience(30)
|
||||||
.withDescription()
|
.withDescription()
|
||||||
.appendDescription(FallDampenersFeature.DESCRIPTION.bind(2))
|
.withDescription(AndroidResearchDescriptions.FALL_DAMPENERS.Instance(2))
|
||||||
.withIcon(ResearchIcons.ICON_FEATHER_FALLING)
|
.withIcon(ResearchIcons.ICON_FEATHER_FALLING)
|
||||||
.addFeatureResult(AndroidFeatures.FALL_DAMPENERS, 1)
|
.addFeatureLevel(AndroidFeatures.FALL_DAMPENERS)
|
||||||
.addPrerequisite(FALL_DAMPENERS_1)
|
.addPrerequisite(FALL_DAMPENERS_1)
|
||||||
.addItem(MItemTags.GOLD_PLATES, 2)
|
.addItem(MItemTags.GOLD_PLATES, 2)
|
||||||
.addItem(MItemTags.COPPER_WIRES, 4)
|
.addItem(MItemTags.COPPER_WIRES, 4)
|
||||||
@ -319,9 +321,9 @@ fun addResearchData(serializer: Consumer<AndroidResearchType>, lang: MatteryLang
|
|||||||
AndroidResearchType.Builder(modLocation(MNames.FALL_DAMPENERS + "_3"))
|
AndroidResearchType.Builder(modLocation(MNames.FALL_DAMPENERS + "_3"))
|
||||||
.withExperience(35)
|
.withExperience(35)
|
||||||
.withDescription(0 .. 1)
|
.withDescription(0 .. 1)
|
||||||
.appendDescription(FallDampenersFeature.DESCRIPTION.bind(3))
|
.withDescription(AndroidResearchDescriptions.FALL_DAMPENERS.Instance(2))
|
||||||
.withIcon(ResearchIcons.ICON_FEATHER_FALLING)
|
.withIcon(ResearchIcons.ICON_FEATHER_FALLING)
|
||||||
.addFeatureResult(AndroidFeatures.FALL_DAMPENERS, 2)
|
.addFeatureLevel(AndroidFeatures.FALL_DAMPENERS)
|
||||||
.addPrerequisite(FALL_DAMPENERS_2)
|
.addPrerequisite(FALL_DAMPENERS_2)
|
||||||
.addItem(MItemTags.ADVANCED_CIRCUIT, 2)
|
.addItem(MItemTags.ADVANCED_CIRCUIT, 2)
|
||||||
.addItem(Tags.Items.GEMS_DIAMOND, 4)
|
.addItem(Tags.Items.GEMS_DIAMOND, 4)
|
||||||
@ -337,7 +339,7 @@ fun addResearchData(serializer: Consumer<AndroidResearchType>, lang: MatteryLang
|
|||||||
AndroidResearchType.Builder(modLocation(MNames.ENDER_TELEPORTER))
|
AndroidResearchType.Builder(modLocation(MNames.ENDER_TELEPORTER))
|
||||||
.withExperience(35)
|
.withExperience(35)
|
||||||
.withDescription()
|
.withDescription()
|
||||||
.appendDescription(EnderTeleporterFeature.POWER_COST_DESCRIPTION)
|
.withDescription(AndroidResearchDescriptions.ENDER_TELEPORTER)
|
||||||
.withIcon(ResearchIcons.ICON_ENDER_TELEPORT)
|
.withIcon(ResearchIcons.ICON_ENDER_TELEPORT)
|
||||||
.addFeatureResult(AndroidFeatures.ENDER_TELEPORTER)
|
.addFeatureResult(AndroidFeatures.ENDER_TELEPORTER)
|
||||||
.addPrerequisite(FALL_DAMPENERS_1)
|
.addPrerequisite(FALL_DAMPENERS_1)
|
||||||
@ -368,9 +370,9 @@ fun addResearchData(serializer: Consumer<AndroidResearchType>, lang: MatteryLang
|
|||||||
AndroidResearchType.Builder(modLocation(MNames.JUMP_BOOST + "_1"))
|
AndroidResearchType.Builder(modLocation(MNames.JUMP_BOOST + "_1"))
|
||||||
.withExperience(27)
|
.withExperience(27)
|
||||||
.withDescription(0 .. 1)
|
.withDescription(0 .. 1)
|
||||||
.appendDescription(JumpBoostFeature.POWER_COST_DESCRIPTION)
|
.withDescription(AndroidResearchDescriptions.JUMP_BOOST)
|
||||||
.withIcon(ResearchIcons.ICON_JUMP_BOOST)
|
.withIcon(ResearchIcons.ICON_JUMP_BOOST)
|
||||||
.addFeatureResult(AndroidFeatures.JUMP_BOOST, 0)
|
.addFeatureResult(AndroidFeatures.JUMP_BOOST)
|
||||||
.addItem(MItemTags.PISTONS, 2)
|
.addItem(MItemTags.PISTONS, 2)
|
||||||
.addItem(MItemTags.GOLD_WIRES, 4)
|
.addItem(MItemTags.GOLD_WIRES, 4)
|
||||||
.addItem(MItems.ELECTROMAGNET, 2)
|
.addItem(MItems.ELECTROMAGNET, 2)
|
||||||
@ -382,9 +384,9 @@ fun addResearchData(serializer: Consumer<AndroidResearchType>, lang: MatteryLang
|
|||||||
AndroidResearchType.Builder(modLocation(MNames.JUMP_BOOST + "_2"))
|
AndroidResearchType.Builder(modLocation(MNames.JUMP_BOOST + "_2"))
|
||||||
.withExperience(34)
|
.withExperience(34)
|
||||||
.withDescription()
|
.withDescription()
|
||||||
.appendDescription(JumpBoostFeature.POWER_COST_DESCRIPTION)
|
.withDescription(AndroidResearchDescriptions.JUMP_BOOST)
|
||||||
.withIcon(ResearchIcons.ICON_JUMP_BOOST)
|
.withIcon(ResearchIcons.ICON_JUMP_BOOST)
|
||||||
.addFeatureResult(AndroidFeatures.JUMP_BOOST, 1)
|
.addFeatureLevel(AndroidFeatures.JUMP_BOOST)
|
||||||
.addItem(MItems.ELECTRIC_PARTS, 4)
|
.addItem(MItems.ELECTRIC_PARTS, 4)
|
||||||
.addItem(MItems.ELECTROMAGNET, 4)
|
.addItem(MItems.ELECTROMAGNET, 4)
|
||||||
.addPrerequisite(JUMP_BOOST_1)
|
.addPrerequisite(JUMP_BOOST_1)
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package ru.dbotthepony.mc.otm.android
|
package ru.dbotthepony.mc.otm.android
|
||||||
|
|
||||||
import it.unimi.dsi.fastutil.io.FastByteArrayOutputStream
|
import it.unimi.dsi.fastutil.io.FastByteArrayOutputStream
|
||||||
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap
|
|
||||||
import net.minecraft.ChatFormatting
|
import net.minecraft.ChatFormatting
|
||||||
import net.minecraft.nbt.CompoundTag
|
import net.minecraft.nbt.CompoundTag
|
||||||
import net.minecraft.nbt.ListTag
|
import net.minecraft.nbt.ListTag
|
||||||
@ -15,7 +14,6 @@ import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
|
|||||||
import ru.dbotthepony.mc.otm.capability.awareItemsStream
|
import ru.dbotthepony.mc.otm.capability.awareItemsStream
|
||||||
import ru.dbotthepony.mc.otm.core.TextComponent
|
import ru.dbotthepony.mc.otm.core.TextComponent
|
||||||
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
||||||
import ru.dbotthepony.mc.otm.core.addAll
|
|
||||||
import ru.dbotthepony.mc.otm.core.nbt.getCompoundList
|
import ru.dbotthepony.mc.otm.core.nbt.getCompoundList
|
||||||
import ru.dbotthepony.mc.otm.core.registryName
|
import ru.dbotthepony.mc.otm.core.registryName
|
||||||
import ru.dbotthepony.mc.otm.core.nbt.set
|
import ru.dbotthepony.mc.otm.core.nbt.set
|
||||||
@ -46,62 +44,19 @@ class AndroidResearch(val type: AndroidResearchType, val capability: MatteryPlay
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
onUnResearch()
|
onRefunded()
|
||||||
isResearched = false
|
isResearched = false
|
||||||
}
|
}
|
||||||
|
|
||||||
private data class RememberResearchLevel(val level: Int?)
|
fun onRefunded() {
|
||||||
|
for (result in type.results) {
|
||||||
private val oldResearchLevel = Object2ObjectArrayMap<AndroidFeatureType<*>, RememberResearchLevel>()
|
result.onRefunded(this)
|
||||||
|
|
||||||
fun onUnResearch() {
|
|
||||||
for (feature in type.resolvedFeatures) {
|
|
||||||
val level = oldResearchLevel[feature.feature]
|
|
||||||
val get = capability.getFeature(feature.feature)
|
|
||||||
|
|
||||||
if (level != null && get != null) {
|
|
||||||
if (get.level == feature.level) {
|
|
||||||
if (level.level == null) {
|
|
||||||
capability.removeFeature(feature.feature)
|
|
||||||
} else {
|
|
||||||
get.level = level.level
|
|
||||||
|
|
||||||
for (transformer in type.features.first { it.id == feature.feature.registryName }.transformersDown) {
|
|
||||||
transformer.apply(this to get)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
oldResearchLevel.clear()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onResearched() {
|
fun onResearched() {
|
||||||
oldResearchLevel.clear()
|
for (result in type.results) {
|
||||||
|
result.onResearched(this)
|
||||||
try {
|
|
||||||
for (feature in type.resolvedFeatures) {
|
|
||||||
var get = capability.getFeature(feature.feature)
|
|
||||||
|
|
||||||
if (get == null) {
|
|
||||||
get = capability.addFeature(feature.feature)
|
|
||||||
get.level = feature.level
|
|
||||||
oldResearchLevel[feature.feature] = RememberResearchLevel(null)
|
|
||||||
} else {
|
|
||||||
if (get.level < feature.level) {
|
|
||||||
oldResearchLevel[feature.feature] = RememberResearchLevel(feature.level)
|
|
||||||
get.level = feature.level
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (transformer in type.features.first { it.id == feature.feature.registryName }.transformersUp) {
|
|
||||||
transformer.apply(this to get)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch(err: Throwable) {
|
|
||||||
oldResearchLevel.clear()
|
|
||||||
throw err
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -297,7 +252,10 @@ class AndroidResearch(val type: AndroidResearchType, val capability: MatteryPlay
|
|||||||
val tooltipLines: List<Component> get() {
|
val tooltipLines: List<Component> get() {
|
||||||
val lines = ArrayList<Component>()
|
val lines = ArrayList<Component>()
|
||||||
lines.add(type.displayName)
|
lines.add(type.displayName)
|
||||||
lines.addAll(type.description.iterator())
|
|
||||||
|
for (line in type.description) {
|
||||||
|
line.addLines(this, lines)
|
||||||
|
}
|
||||||
|
|
||||||
return lines
|
return lines
|
||||||
}
|
}
|
||||||
@ -382,38 +340,10 @@ class AndroidResearch(val type: AndroidResearchType, val capability: MatteryPlay
|
|||||||
override fun serializeNBT(): CompoundTag {
|
override fun serializeNBT(): CompoundTag {
|
||||||
return CompoundTag().also {
|
return CompoundTag().also {
|
||||||
it["researched"] = isResearched
|
it["researched"] = isResearched
|
||||||
|
|
||||||
it["oldResearchLevel"] = ListTag().also {
|
|
||||||
for ((k, v) in oldResearchLevel) {
|
|
||||||
it.add(CompoundTag().also {
|
|
||||||
it["key"] = k.registryName!!.toString()
|
|
||||||
it["value"] = CompoundTag().also {
|
|
||||||
it["isPresent"] = v.level != null
|
|
||||||
|
|
||||||
if (v.level != null) {
|
|
||||||
it["value"] = v.level
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun deserializeNBT(nbt: CompoundTag) {
|
override fun deserializeNBT(nbt: CompoundTag) {
|
||||||
isResearched = nbt.getBoolean("researched")
|
isResearched = nbt.getBoolean("researched")
|
||||||
|
|
||||||
oldResearchLevel.clear()
|
|
||||||
|
|
||||||
for (tag in nbt.getCompoundList("oldResearchLevel")) {
|
|
||||||
val key = tag.getString("key")
|
|
||||||
val type = MRegistry.ANDROID_FEATURES.getValue(ResourceLocation(key)) ?: continue
|
|
||||||
val value = tag.getCompound("value")
|
|
||||||
|
|
||||||
val isPresent = value.getBoolean("isPresent")
|
|
||||||
val int = value.getInt("value")
|
|
||||||
|
|
||||||
oldResearchLevel[type] = RememberResearchLevel(if (isPresent) int else null)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,8 +50,6 @@ open class AndroidResearchDataProvider() : DataProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final override fun run(output: CachedOutput): CompletableFuture<*> {
|
final override fun run(output: CachedOutput): CompletableFuture<*> {
|
||||||
AndroidResearchManager.fireRegistrationEvent()
|
|
||||||
|
|
||||||
val set = ObjectArraySet<ResourceLocation>()
|
val set = ObjectArraySet<ResourceLocation>()
|
||||||
val added = LinkedList<AndroidResearchType>()
|
val added = LinkedList<AndroidResearchType>()
|
||||||
val futures = ArrayList<CompletableFuture<*>>()
|
val futures = ArrayList<CompletableFuture<*>>()
|
||||||
|
@ -0,0 +1,133 @@
|
|||||||
|
package ru.dbotthepony.mc.otm.android
|
||||||
|
|
||||||
|
import com.mojang.datafixers.util.Either
|
||||||
|
import com.mojang.serialization.Codec
|
||||||
|
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||||
|
import net.minecraft.ChatFormatting
|
||||||
|
import net.minecraft.network.chat.Component
|
||||||
|
import net.minecraftforge.eventbus.api.IEventBus
|
||||||
|
import net.minecraftforge.registries.DeferredRegister
|
||||||
|
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
||||||
|
import ru.dbotthepony.mc.otm.client.ShiftPressedCond
|
||||||
|
import ru.dbotthepony.mc.otm.config.AndroidConfig
|
||||||
|
import ru.dbotthepony.mc.otm.core.TextComponent
|
||||||
|
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
||||||
|
import ru.dbotthepony.mc.otm.core.getValue
|
||||||
|
import ru.dbotthepony.mc.otm.core.util.formatPower
|
||||||
|
import ru.dbotthepony.mc.otm.data.ComponentCodec
|
||||||
|
import ru.dbotthepony.mc.otm.data.SingletonCodec
|
||||||
|
import ru.dbotthepony.mc.otm.data.simpleCodec
|
||||||
|
import ru.dbotthepony.mc.otm.registry.RegistryDelegate
|
||||||
|
|
||||||
|
object AndroidResearchDescriptions {
|
||||||
|
private val registrar = DeferredRegister.create(AndroidResearchDescription.registryKey, OverdriveThatMatters.MOD_ID)
|
||||||
|
|
||||||
|
init {
|
||||||
|
registrar.register("plain") { PlainAndroidResearchDescription }
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun register(bus: IEventBus) {
|
||||||
|
registrar.register(bus)
|
||||||
|
}
|
||||||
|
|
||||||
|
val ENDER_TELEPORTER: AndroidResearchDescription.Singleton by registrar.register("ender_teleporter") {
|
||||||
|
AndroidResearchDescription.singleton {
|
||||||
|
TranslatableComponent("otm.gui.power_cost_per_use", AndroidConfig.EnderTeleporter.ENERGY_COST.formatPower(formatAsReadable = ShiftPressedCond).copy().withStyle(ChatFormatting.YELLOW)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
val FALL_DAMPENERS: AndroidResearchDescription.Leveled by registrar.register("fall_dampeners") {
|
||||||
|
AndroidResearchDescription.Leveled { _, _, level -> TranslatableComponent("otm.fall_dampeners.description", TextComponent("%.1f".format((AndroidConfig.FALL_DAMAGE_REDUCTION_PER_LEVEL * level).toFloat().coerceAtLeast(0f).coerceAtMost(1f) * 100f)).withStyle(ChatFormatting.YELLOW)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
val ITEM_MAGNET: AndroidResearchDescription.Singleton by registrar.register("item_magnet") {
|
||||||
|
AndroidResearchDescription.singleton { TranslatableComponent("otm.gui.power_cost_per_tick", AndroidConfig.Magnet.POWER_DRAW.formatPower(formatAsReadable = ShiftPressedCond).copy().withStyle(ChatFormatting.YELLOW)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
val JUMP_BOOST: AndroidResearchDescription.Singleton by registrar.register("jump_boost") {
|
||||||
|
AndroidResearchDescription.singleton { TranslatableComponent("otm.gui.power_cost_per_use", AndroidConfig.JumpBoost.ENERGY_COST.formatPower(formatAsReadable = ShiftPressedCond).copy().withStyle(ChatFormatting.YELLOW)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
val SHOCKWAVE: AndroidResearchDescription.Singleton by registrar.register("shockwave") {
|
||||||
|
AndroidResearchDescription.singleton { TranslatableComponent("otm.gui.power_cost_per_use", AndroidConfig.Shockwave.ENERGY_COST.formatPower(formatAsReadable = ShiftPressedCond).copy().withStyle(ChatFormatting.YELLOW)) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instance, representing ready to use description populator
|
||||||
|
*/
|
||||||
|
interface AndroidResearchDescription {
|
||||||
|
/**
|
||||||
|
* Type, representing raw description populator in registry
|
||||||
|
*/
|
||||||
|
interface Type<T : AndroidResearchDescription> {
|
||||||
|
val codec: Codec<T>
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class Singleton : AndroidResearchDescription, Type<Singleton> {
|
||||||
|
override val codec = SingletonCodec(this)
|
||||||
|
override val type: Type<*>
|
||||||
|
get() = this
|
||||||
|
}
|
||||||
|
|
||||||
|
class Leveled(val callback: (research: AndroidResearch, lines: MutableList<Component>, level: Int) -> Unit) : Type<Leveled.Instance> {
|
||||||
|
inner class Instance(val level: Int) : AndroidResearchDescription {
|
||||||
|
override fun addLines(research: AndroidResearch, lines: MutableList<Component>) {
|
||||||
|
callback.invoke(research, lines, level)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val type: Type<*>
|
||||||
|
get() = this@Leveled
|
||||||
|
}
|
||||||
|
|
||||||
|
override val codec: Codec<Instance> by lazy {
|
||||||
|
RecordCodecBuilder.create {
|
||||||
|
it.group(Codec.INT.fieldOf("level").forGetter(Instance::level)).apply(it, ::Instance)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addLines(research: AndroidResearch, lines: MutableList<Component>)
|
||||||
|
val type: Type<*>
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val delegate = RegistryDelegate<Type<*>>("android_research_description")
|
||||||
|
|
||||||
|
val registry by delegate
|
||||||
|
val registryKey get() = delegate.key
|
||||||
|
|
||||||
|
val CODEC: Codec<AndroidResearchDescription> by lazy {
|
||||||
|
registry.codec.dispatch({ it.type }, { it.codec })
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun register(bus: IEventBus) {
|
||||||
|
bus.addListener(delegate::build)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun singleton(callback: (research: AndroidResearch) -> Component): Singleton {
|
||||||
|
return object : Singleton() {
|
||||||
|
override fun addLines(research: AndroidResearch, lines: MutableList<Component>) {
|
||||||
|
lines.add(callback.invoke(research))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object PlainAndroidResearchDescription : AndroidResearchDescription.Type<PlainAndroidResearchDescription.Instance> {
|
||||||
|
data class Instance(val line: Component) : AndroidResearchDescription {
|
||||||
|
override fun addLines(research: AndroidResearch, lines: MutableList<Component>) {
|
||||||
|
lines.add(line.copy())
|
||||||
|
}
|
||||||
|
|
||||||
|
override val type: PlainAndroidResearchDescription
|
||||||
|
get() = PlainAndroidResearchDescription
|
||||||
|
}
|
||||||
|
|
||||||
|
fun make(line: Component) = Instance(line)
|
||||||
|
|
||||||
|
override val codec: Codec<Instance> by lazy {
|
||||||
|
Codec
|
||||||
|
.either(ComponentCodec, simpleCodec(::Instance, Instance::line, ComponentCodec))
|
||||||
|
.xmap({ c -> c.map({ Instance(it) }, { it }) }, { c -> Either.left(c.line) })
|
||||||
|
}
|
||||||
|
}
|
@ -6,7 +6,6 @@ import com.google.gson.JsonElement
|
|||||||
import com.google.gson.JsonObject
|
import com.google.gson.JsonObject
|
||||||
import net.minecraft.client.server.IntegratedServer
|
import net.minecraft.client.server.IntegratedServer
|
||||||
import net.minecraft.network.FriendlyByteBuf
|
import net.minecraft.network.FriendlyByteBuf
|
||||||
import net.minecraft.network.chat.Component
|
|
||||||
import net.minecraft.resources.ResourceLocation
|
import net.minecraft.resources.ResourceLocation
|
||||||
import net.minecraft.server.packs.resources.ResourceManager
|
import net.minecraft.server.packs.resources.ResourceManager
|
||||||
import net.minecraft.server.packs.resources.SimpleJsonResourceReloadListener
|
import net.minecraft.server.packs.resources.SimpleJsonResourceReloadListener
|
||||||
@ -23,8 +22,6 @@ import ru.dbotthepony.mc.otm.NULLABLE_MINECRAFT_SERVER
|
|||||||
import ru.dbotthepony.mc.otm.SERVER_IS_LIVE
|
import ru.dbotthepony.mc.otm.SERVER_IS_LIVE
|
||||||
import ru.dbotthepony.mc.otm.capability.matteryPlayer
|
import ru.dbotthepony.mc.otm.capability.matteryPlayer
|
||||||
import ru.dbotthepony.mc.otm.client.minecraft
|
import ru.dbotthepony.mc.otm.client.minecraft
|
||||||
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
|
||||||
import ru.dbotthepony.mc.otm.data.SerializedFunctionRegistry
|
|
||||||
import ru.dbotthepony.mc.otm.network.MatteryPacket
|
import ru.dbotthepony.mc.otm.network.MatteryPacket
|
||||||
import ru.dbotthepony.mc.otm.network.RegistryNetworkChannel
|
import ru.dbotthepony.mc.otm.network.RegistryNetworkChannel
|
||||||
import ru.dbotthepony.mc.otm.network.enqueueWork
|
import ru.dbotthepony.mc.otm.network.enqueueWork
|
||||||
@ -33,47 +30,7 @@ import ru.dbotthepony.mc.otm.onceServer
|
|||||||
import java.util.LinkedList
|
import java.util.LinkedList
|
||||||
import java.util.function.Supplier
|
import java.util.function.Supplier
|
||||||
|
|
||||||
typealias AndroidResultTransformer = SerializedFunctionRegistry.BoundFunction<Pair<AndroidResearch, AndroidFeature>, Unit>
|
|
||||||
typealias ComponentSupplier = SerializedFunctionRegistry.BoundFunction<Unit, Component>
|
|
||||||
|
|
||||||
object AndroidResearchManager : SimpleJsonResourceReloadListener(GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create(), "otm_android_research"), Iterable<AndroidResearchType> {
|
object AndroidResearchManager : SimpleJsonResourceReloadListener(GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create(), "otm_android_research"), Iterable<AndroidResearchType> {
|
||||||
/**
|
|
||||||
* Feel free to register functions inside this thing from anywhere in your code
|
|
||||||
* (registration and querying is completely thread safe).
|
|
||||||
*
|
|
||||||
* Just make sure client and server has the same set of functions defined.
|
|
||||||
*/
|
|
||||||
val featureResultTransformers = SerializedFunctionRegistry<Pair<AndroidResearch, AndroidFeature>, Unit>()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Feel free to register functions inside this thing from anywhere in your code
|
|
||||||
* (registration and querying is completely thread safe).
|
|
||||||
*
|
|
||||||
* Just make sure client and server has the same set of functions defined.
|
|
||||||
*/
|
|
||||||
val descriptionFuncs = SerializedFunctionRegistry<Unit, Component>()
|
|
||||||
|
|
||||||
fun descriptionFunc(name: ResourceLocation, base: String, vararg argument: Supplier<Any>): ComponentSupplier {
|
|
||||||
return descriptionFuncs.register(name) {->
|
|
||||||
return@register TranslatableComponent(base, *argument.map { it.get() }.toTypedArray())
|
|
||||||
}.bind()
|
|
||||||
}
|
|
||||||
|
|
||||||
private var firedRegistrationEvent = false
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Event-style registration of serializable functions, for those who prefer/need it
|
|
||||||
*
|
|
||||||
* Fired *once* on [MinecraftForge.EVENT_BUS] before loading android research
|
|
||||||
*/
|
|
||||||
object RegisterFuncsEvent : Event() {
|
|
||||||
val manager get() = AndroidResearchManager
|
|
||||||
val featureResults by ::featureResultTransformers
|
|
||||||
val descriptionFunctions by ::descriptionFuncs
|
|
||||||
|
|
||||||
fun descriptionFunc(name: ResourceLocation, base: String, vararg argument: Supplier<Any>): ComponentSupplier = AndroidResearchManager.descriptionFunc(name, base, *argument)
|
|
||||||
}
|
|
||||||
|
|
||||||
const val DIRECTORY = "otm_android_research"
|
const val DIRECTORY = "otm_android_research"
|
||||||
private val LOGGER = LogManager.getLogger()
|
private val LOGGER = LogManager.getLogger()
|
||||||
|
|
||||||
@ -97,23 +54,11 @@ object AndroidResearchManager : SimpleJsonResourceReloadListener(GsonBuilder().s
|
|||||||
var researchMap: Map<ResourceLocation, AndroidResearchType> = mapOf()
|
var researchMap: Map<ResourceLocation, AndroidResearchType> = mapOf()
|
||||||
private set
|
private set
|
||||||
|
|
||||||
internal fun fireRegistrationEvent() {
|
|
||||||
if (!firedRegistrationEvent) {
|
|
||||||
try {
|
|
||||||
MinecraftForge.EVENT_BUS.post(RegisterFuncsEvent)
|
|
||||||
} finally {
|
|
||||||
firedRegistrationEvent = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun apply(
|
override fun apply(
|
||||||
jsonElementMap: Map<ResourceLocation, JsonElement>,
|
jsonElementMap: Map<ResourceLocation, JsonElement>,
|
||||||
manager: ResourceManager,
|
manager: ResourceManager,
|
||||||
profiler: ProfilerFiller
|
profiler: ProfilerFiller
|
||||||
) {
|
) {
|
||||||
fireRegistrationEvent()
|
|
||||||
|
|
||||||
val builder = ImmutableMap.builder<ResourceLocation, AndroidResearchType>()
|
val builder = ImmutableMap.builder<ResourceLocation, AndroidResearchType>()
|
||||||
|
|
||||||
for ((k, v) in jsonElementMap) {
|
for ((k, v) in jsonElementMap) {
|
||||||
|
@ -0,0 +1,180 @@
|
|||||||
|
package ru.dbotthepony.mc.otm.android
|
||||||
|
|
||||||
|
import com.mojang.datafixers.util.Either
|
||||||
|
import com.mojang.serialization.Codec
|
||||||
|
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||||
|
import net.minecraft.resources.ResourceLocation
|
||||||
|
import net.minecraftforge.eventbus.api.IEventBus
|
||||||
|
import net.minecraftforge.registries.DeferredRegister
|
||||||
|
import org.apache.logging.log4j.LogManager
|
||||||
|
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
||||||
|
import ru.dbotthepony.mc.otm.core.getValue
|
||||||
|
import ru.dbotthepony.mc.otm.data.SingletonCodec
|
||||||
|
import ru.dbotthepony.mc.otm.registry.AndroidFeatures
|
||||||
|
import ru.dbotthepony.mc.otm.registry.MRegistry
|
||||||
|
import ru.dbotthepony.mc.otm.registry.RegistryDelegate
|
||||||
|
|
||||||
|
object AndroidResearchResults {
|
||||||
|
private val registrar = DeferredRegister.create(AndroidResearchResult.registryKey, OverdriveThatMatters.MOD_ID)
|
||||||
|
|
||||||
|
init {
|
||||||
|
registrar.register("feature") { AndroidResearchResult.Feature.Companion }
|
||||||
|
registrar.register("feature_level") { AndroidResearchResult.FeatureLevel.Companion }
|
||||||
|
}
|
||||||
|
|
||||||
|
private object NanobotsArmorStrength : AndroidResearchResult.Singleton<NanobotsArmorStrength> {
|
||||||
|
override val codec: Codec<NanobotsArmorStrength> = SingletonCodec(this)
|
||||||
|
override val type: AndroidResearchResult.Type<*>
|
||||||
|
get() = this
|
||||||
|
|
||||||
|
override fun onResearched(research: AndroidResearch) {
|
||||||
|
val feature = research.capability.getFeature(AndroidFeatures.NANOBOTS_ARMOR) ?: return
|
||||||
|
feature.strength++
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onRefunded(research: AndroidResearch) {
|
||||||
|
val feature = research.capability.getFeature(AndroidFeatures.NANOBOTS_ARMOR) ?: return
|
||||||
|
feature.strength--
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private object NanobotsArmorSpeed : AndroidResearchResult.Singleton<NanobotsArmorSpeed> {
|
||||||
|
override val codec: Codec<NanobotsArmorSpeed> = SingletonCodec(this)
|
||||||
|
override val type: AndroidResearchResult.Type<*>
|
||||||
|
get() = this
|
||||||
|
|
||||||
|
override fun onResearched(research: AndroidResearch) {
|
||||||
|
val feature = research.capability.getFeature(AndroidFeatures.NANOBOTS_ARMOR) ?: return
|
||||||
|
feature.speed++
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onRefunded(research: AndroidResearch) {
|
||||||
|
val feature = research.capability.getFeature(AndroidFeatures.NANOBOTS_ARMOR) ?: return
|
||||||
|
feature.speed--
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val NANOBOTS_ARMOR_STRENGTH: AndroidResearchResult.Singleton<*> by registrar.register("nanobots_armor_strength") { NanobotsArmorStrength }
|
||||||
|
val NANOBOTS_ARMOR_SPEED: AndroidResearchResult.Singleton<*> by registrar.register("nanobots_armor_speed") { NanobotsArmorSpeed }
|
||||||
|
|
||||||
|
internal fun register(bus: IEventBus) {
|
||||||
|
registrar.register(bus)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface AndroidResearchResult {
|
||||||
|
interface Type<T : AndroidResearchResult> {
|
||||||
|
val codec: Codec<T>
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Singleton<T : Singleton<T>> : Type<T>, AndroidResearchResult
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds specific android feature [id] to target, does nothing if target already has specified feature
|
||||||
|
*/
|
||||||
|
class Feature(val id: ResourceLocation, val optional: Boolean = false) : AndroidResearchResult {
|
||||||
|
val feature = MRegistry.ANDROID_FEATURES.getValue(id) ?: if (optional) null else throw NoSuchElementException("Unknown android feature $id")
|
||||||
|
|
||||||
|
override val type: Type<*>
|
||||||
|
get() = Companion
|
||||||
|
|
||||||
|
override fun onResearched(research: AndroidResearch) {
|
||||||
|
research.capability.addFeature(feature ?: return)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onRefunded(research: AndroidResearch) {
|
||||||
|
research.capability.removeFeature(feature ?: return)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object : Type<Feature> {
|
||||||
|
override val codec: Codec<Feature> by lazy {
|
||||||
|
Codec
|
||||||
|
.either(ResourceLocation.CODEC, RecordCodecBuilder.create<Feature> { // KT-52757
|
||||||
|
it.group(
|
||||||
|
ResourceLocation.CODEC.fieldOf("id").forGetter(Feature::id),
|
||||||
|
Codec.BOOL.optionalFieldOf("optional", false).forGetter(Feature::optional)
|
||||||
|
).apply(it, ::Feature)
|
||||||
|
})
|
||||||
|
.xmap<Feature>(
|
||||||
|
{ c -> c.map({ Feature(it) }, { it }) },
|
||||||
|
{ c -> if (c.optional) Either.left(c.id) else Either.right(c) }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Increases level of specific android feature [id] by specified amount [levels]
|
||||||
|
*/
|
||||||
|
class FeatureLevel(val id: ResourceLocation, val optional: Boolean = false, val levels: Int = 1) : AndroidResearchResult {
|
||||||
|
val feature = MRegistry.ANDROID_FEATURES.getValue(id) ?: if (optional) null else throw NoSuchElementException("Unknown android feature $id")
|
||||||
|
|
||||||
|
override val type: Type<*>
|
||||||
|
get() = Companion
|
||||||
|
|
||||||
|
override fun onResearched(research: AndroidResearch) {
|
||||||
|
val get = research.capability.getFeature(feature ?: return)
|
||||||
|
|
||||||
|
if (get == null) {
|
||||||
|
LOGGER.warn("Unable to advance level of android feature $id for ${research.ply} because they have no such android feature.")
|
||||||
|
} else {
|
||||||
|
get.level += levels
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onRefunded(research: AndroidResearch) {
|
||||||
|
val get = research.capability.getFeature(feature ?: return)
|
||||||
|
|
||||||
|
if (get == null) {
|
||||||
|
LOGGER.warn("Unable to decrease level of android feature $id for ${research.ply} because they have no such android feature.")
|
||||||
|
} else {
|
||||||
|
get.level += levels
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object : Type<FeatureLevel> {
|
||||||
|
override val codec: Codec<FeatureLevel> by lazy {
|
||||||
|
Codec
|
||||||
|
.either(ResourceLocation.CODEC, RecordCodecBuilder.create<FeatureLevel> { // KT-52757
|
||||||
|
it.group(
|
||||||
|
ResourceLocation.CODEC.fieldOf("id").forGetter(FeatureLevel::id),
|
||||||
|
Codec.BOOL.optionalFieldOf("optional", false).forGetter(FeatureLevel::optional),
|
||||||
|
Codec.INT.optionalFieldOf("levels", 1).forGetter(FeatureLevel::levels),
|
||||||
|
).apply(it, ::FeatureLevel)
|
||||||
|
})
|
||||||
|
.xmap(
|
||||||
|
{ c -> c.map({ FeatureLevel(it) }, { it }) },
|
||||||
|
{ c -> if (c.optional && c.levels == 1) Either.left(c.id) else Either.right(c) }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val type: Type<*>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when research is applied
|
||||||
|
*/
|
||||||
|
fun onResearched(research: AndroidResearch) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when research is refunded
|
||||||
|
*/
|
||||||
|
fun onRefunded(research: AndroidResearch) {}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val LOGGER = LogManager.getLogger()
|
||||||
|
private val delegate = RegistryDelegate<Type<*>>("android_research_result")
|
||||||
|
|
||||||
|
val registry by delegate
|
||||||
|
val registryKey get() = delegate.key
|
||||||
|
|
||||||
|
val CODEC: Codec<AndroidResearchResult> by lazy {
|
||||||
|
registry.codec.dispatch({ it.type }, { it.codec })
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun register(bus: IEventBus) {
|
||||||
|
bus.addListener(delegate::build)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,13 +1,13 @@
|
|||||||
package ru.dbotthepony.mc.otm.android
|
package ru.dbotthepony.mc.otm.android
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList
|
import com.google.common.collect.ImmutableList
|
||||||
import com.google.common.collect.Streams
|
|
||||||
import com.google.gson.JsonArray
|
import com.google.gson.JsonArray
|
||||||
import com.google.gson.JsonElement
|
import com.google.gson.JsonElement
|
||||||
import com.google.gson.JsonObject
|
import com.google.gson.JsonObject
|
||||||
import com.google.gson.JsonPrimitive
|
import com.google.gson.JsonPrimitive
|
||||||
import com.google.gson.JsonSyntaxException
|
import com.google.gson.JsonSyntaxException
|
||||||
import com.google.gson.internal.bind.TypeAdapters
|
import com.google.gson.internal.bind.TypeAdapters
|
||||||
|
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet
|
||||||
import net.minecraft.network.FriendlyByteBuf
|
import net.minecraft.network.FriendlyByteBuf
|
||||||
import net.minecraft.network.chat.Component
|
import net.minecraft.network.chat.Component
|
||||||
import net.minecraft.network.chat.ComponentContents
|
import net.minecraft.network.chat.ComponentContents
|
||||||
@ -28,10 +28,12 @@ import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
|||||||
import ru.dbotthepony.mc.otm.core.isActuallyEmpty
|
import ru.dbotthepony.mc.otm.core.isActuallyEmpty
|
||||||
import ru.dbotthepony.mc.otm.core.registryName
|
import ru.dbotthepony.mc.otm.core.registryName
|
||||||
import ru.dbotthepony.mc.otm.core.set
|
import ru.dbotthepony.mc.otm.core.set
|
||||||
import ru.dbotthepony.mc.otm.core.toImmutableList
|
|
||||||
import ru.dbotthepony.mc.otm.core.collect.stream
|
import ru.dbotthepony.mc.otm.core.collect.stream
|
||||||
|
import ru.dbotthepony.mc.otm.core.fromJsonStrict
|
||||||
|
import ru.dbotthepony.mc.otm.core.toJsonStrict
|
||||||
|
import ru.dbotthepony.mc.otm.core.util.readJson
|
||||||
|
import ru.dbotthepony.mc.otm.core.util.writeJson
|
||||||
import ru.dbotthepony.mc.otm.isClient
|
import ru.dbotthepony.mc.otm.isClient
|
||||||
import ru.dbotthepony.mc.otm.registry.MRegistry
|
|
||||||
import java.util.LinkedList
|
import java.util.LinkedList
|
||||||
import java.util.stream.Stream
|
import java.util.stream.Stream
|
||||||
import kotlin.collections.ArrayList
|
import kotlin.collections.ArrayList
|
||||||
@ -39,7 +41,7 @@ import kotlin.collections.HashSet
|
|||||||
|
|
||||||
private fun findPrerequisites(
|
private fun findPrerequisites(
|
||||||
initial: Collection<AndroidResearchType>,
|
initial: Collection<AndroidResearchType>,
|
||||||
add: MutableSet<AndroidResearchType> = HashSet(),
|
add: MutableSet<AndroidResearchType> = ObjectOpenHashSet(),
|
||||||
top: Boolean = true
|
top: Boolean = true
|
||||||
): Set<AndroidResearchType> {
|
): Set<AndroidResearchType> {
|
||||||
for (value in initial) {
|
for (value in initial) {
|
||||||
@ -55,7 +57,7 @@ private fun findPrerequisites(
|
|||||||
|
|
||||||
private fun findAllPrerequisites(
|
private fun findAllPrerequisites(
|
||||||
initial: Collection<AndroidResearchType>,
|
initial: Collection<AndroidResearchType>,
|
||||||
add: MutableSet<AndroidResearchType> = HashSet(),
|
add: MutableSet<AndroidResearchType> = ObjectOpenHashSet(),
|
||||||
): Set<AndroidResearchType> {
|
): Set<AndroidResearchType> {
|
||||||
for (value in initial) {
|
for (value in initial) {
|
||||||
add.add(value)
|
add.add(value)
|
||||||
@ -67,7 +69,7 @@ private fun findAllPrerequisites(
|
|||||||
|
|
||||||
private fun findAllChildren(
|
private fun findAllChildren(
|
||||||
initial: Collection<AndroidResearchType>,
|
initial: Collection<AndroidResearchType>,
|
||||||
add: MutableSet<AndroidResearchType> = HashSet(),
|
add: MutableSet<AndroidResearchType> = ObjectOpenHashSet(),
|
||||||
): Set<AndroidResearchType> {
|
): Set<AndroidResearchType> {
|
||||||
for (value in initial) {
|
for (value in initial) {
|
||||||
add.add(value)
|
add.add(value)
|
||||||
@ -83,10 +85,9 @@ class AndroidResearchType(
|
|||||||
blockedBy: Collection<Reference>,
|
blockedBy: Collection<Reference>,
|
||||||
|
|
||||||
items: Collection<Pair<Ingredient, Int>>,
|
items: Collection<Pair<Ingredient, Int>>,
|
||||||
features: Collection<FeatureReference>,
|
results: Collection<AndroidResearchResult>,
|
||||||
|
|
||||||
descriptionLines: Collection<Component>,
|
description: Collection<AndroidResearchDescription>,
|
||||||
descriptionSuppliers: Collection<ComponentSupplier> = listOf(),
|
|
||||||
|
|
||||||
val experienceLevels: Int = 0,
|
val experienceLevels: Int = 0,
|
||||||
private val customName: Component? = null,
|
private val customName: Component? = null,
|
||||||
@ -145,74 +146,6 @@ class AndroidResearchType(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data class FeatureReference(
|
|
||||||
val id: ResourceLocation,
|
|
||||||
val level: Int = 0,
|
|
||||||
val isRigid: Boolean,
|
|
||||||
val transformersUp: Collection<AndroidResultTransformer> = listOf(),
|
|
||||||
val transformersDown: Collection<AndroidResultTransformer> = listOf(),
|
|
||||||
) {
|
|
||||||
fun toJson(): JsonObject {
|
|
||||||
return JsonObject().also {
|
|
||||||
it["id"] = JsonPrimitive(id.toString())
|
|
||||||
it["level"] = JsonPrimitive(level)
|
|
||||||
it["is_rigid"] = JsonPrimitive(isRigid)
|
|
||||||
it["functions_up"] = JsonArray().also {
|
|
||||||
for (transformer in transformersUp) {
|
|
||||||
it.add(transformer.toJson())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
it["functions_down"] = JsonArray().also {
|
|
||||||
for (transformer in transformersDown) {
|
|
||||||
it.add(transformer.toJson())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun toNetwork(buff: FriendlyByteBuf) {
|
|
||||||
buff.writeUtf(id.toString())
|
|
||||||
buff.writeVarInt(level)
|
|
||||||
buff.writeBoolean(isRigid)
|
|
||||||
buff.writeCollection(transformersUp) { a, b -> b.toNetwork(a) }
|
|
||||||
buff.writeCollection(transformersDown) { a, b -> b.toNetwork(a) }
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
fun fromNetwork(buff: FriendlyByteBuf): FeatureReference {
|
|
||||||
return FeatureReference(
|
|
||||||
ResourceLocation(buff.readUtf()),
|
|
||||||
buff.readVarInt(),
|
|
||||||
buff.readBoolean(),
|
|
||||||
buff.readCollection({ LinkedList() }, AndroidResearchManager.featureResultTransformers::fromNetwork).filterNotNull().toImmutableList(),
|
|
||||||
buff.readCollection({ LinkedList() }, AndroidResearchManager.featureResultTransformers::fromNetwork).filterNotNull().toImmutableList()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun fromJson(value: JsonElement): FeatureReference {
|
|
||||||
if (value is JsonPrimitive) {
|
|
||||||
return FeatureReference(ResourceLocation(value.asString), 0, true)
|
|
||||||
} else if (value is JsonObject) {
|
|
||||||
return FeatureReference(
|
|
||||||
ResourceLocation((value["id"] as? JsonPrimitive ?: throw JsonSyntaxException("Invalid `id` value")).asString),
|
|
||||||
(value["level"] as JsonPrimitive?)?.asInt ?: 0,
|
|
||||||
(value["is_rigid"] as JsonPrimitive?)?.asBoolean ?: true,
|
|
||||||
(value["functions_up"] as JsonArray? ?: JsonArray()).stream().map { AndroidResearchManager.featureResultTransformers.fromJson(it) }.filter { it != null }.collect(ImmutableList.toImmutableList<AndroidResultTransformer>()),
|
|
||||||
(value["functions_down"] as JsonArray? ?: JsonArray()).stream().map { AndroidResearchManager.featureResultTransformers.fromJson(it) }.filter { it != null }.collect(ImmutableList.toImmutableList<AndroidResultTransformer>()),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
throw JsonSyntaxException("Unknown element type ${value::class.qualifiedName}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
data class ResolvedFeature(
|
|
||||||
val feature: AndroidFeatureType<*>,
|
|
||||||
val level: Int,
|
|
||||||
)
|
|
||||||
|
|
||||||
val researchTreeDepth: Int by lazy {
|
val researchTreeDepth: Int by lazy {
|
||||||
if (flatPrerequisites.isEmpty()) {
|
if (flatPrerequisites.isEmpty()) {
|
||||||
return@lazy 0
|
return@lazy 0
|
||||||
@ -248,31 +181,11 @@ class AndroidResearchType(
|
|||||||
ImmutableList.copyOf(this.blockedBy.mapNotNull { AndroidResearchManager[it.id].also { e -> if (e == null && it.isRigid) throw NoSuchElementException("Unable to find research ${it.id}") } })
|
ImmutableList.copyOf(this.blockedBy.mapNotNull { AndroidResearchManager[it.id].also { e -> if (e == null && it.isRigid) throw NoSuchElementException("Unable to find research ${it.id}") } })
|
||||||
}
|
}
|
||||||
|
|
||||||
val features: List<FeatureReference> = ImmutableList.copyOf(features)
|
|
||||||
|
|
||||||
val resolvedFeatures: List<ResolvedFeature> by lazy {
|
|
||||||
ImmutableList.copyOf(features.mapNotNull {
|
|
||||||
MRegistry.ANDROID_FEATURES.getValue(it.id)
|
|
||||||
.let { e -> if (e == null && it.isRigid)
|
|
||||||
throw NoSuchElementException("Unable to find research ${it.id}")
|
|
||||||
else if (e != null)
|
|
||||||
ResolvedFeature(e, it.level)
|
|
||||||
else
|
|
||||||
null } })
|
|
||||||
}
|
|
||||||
|
|
||||||
private val definedItems: List<Pair<Ingredient, Int>> = ImmutableList.copyOf(items)
|
private val definedItems: List<Pair<Ingredient, Int>> = ImmutableList.copyOf(items)
|
||||||
|
|
||||||
|
val results: ImmutableList<AndroidResearchResult> = ImmutableList.copyOf(results)
|
||||||
val items: Stream<out Pair<Ingredient, Int>> get() = definedItems.stream().filter { !it.first.isActuallyEmpty }
|
val items: Stream<out Pair<Ingredient, Int>> get() = definedItems.stream().filter { !it.first.isActuallyEmpty }
|
||||||
|
val description: ImmutableList<AndroidResearchDescription> = ImmutableList.copyOf(description)
|
||||||
private val descriptionLines: List<MutableComponent> = ImmutableList.copyOf(descriptionLines.map { it.copy() })
|
|
||||||
|
|
||||||
private val descriptionSuppliers: List<ComponentSupplier> = ImmutableList.copyOf(descriptionSuppliers)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stream containing copies of original [Component]s in list
|
|
||||||
*/
|
|
||||||
val description: Stream<out Component> get() = Streams.concat(descriptionLines.stream().map { it.copy() }, descriptionSuppliers.stream().map { it.apply(Unit) })
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Flat list of research preceding this research.
|
* Flat list of research preceding this research.
|
||||||
@ -469,14 +382,11 @@ class AndroidResearchType(
|
|||||||
|
|
||||||
fun toJson(): JsonElement {
|
fun toJson(): JsonElement {
|
||||||
return JsonObject().also {
|
return JsonObject().also {
|
||||||
// it["id"] = JsonPrimitive(id.toString())
|
|
||||||
|
|
||||||
it["prerequisites"] = JsonArray().also { for (value in prerequisites) it.add(value.toJson()) }
|
it["prerequisites"] = JsonArray().also { for (value in prerequisites) it.add(value.toJson()) }
|
||||||
it["blocked_by"] = JsonArray().also { for (value in blockedBy) it.add(value.toJson()) }
|
it["blocked_by"] = JsonArray().also { for (value in blockedBy) it.add(value.toJson()) }
|
||||||
it["required_items"] = JsonArray().also { for (item in definedItems) it.add(JsonObject().also { it["count"] = JsonPrimitive(item.second); it["ingredient"] = item.first.toJson() }) }
|
it["required_items"] = JsonArray().also { for (item in definedItems) it.add(JsonObject().also { it["count"] = JsonPrimitive(item.second); it["ingredient"] = item.first.toJson() }) }
|
||||||
it["feature_result"] = JsonArray().also { for (feature in features) it.add(feature.toJson()) }
|
it["results"] = JsonArray().also { for (result in results) it.add(AndroidResearchResult.CODEC.toJsonStrict(result)) }
|
||||||
it["description"] = JsonArray().also { for (line in descriptionLines) it.add(Component.Serializer.toJsonTree(line)) }
|
it["description"] = JsonArray().also { for (line in description) it.add(AndroidResearchDescription.CODEC.toJsonStrict(line)) }
|
||||||
it["description_funcs"] = JsonArray().also { for (line in descriptionSuppliers) it.add(line.toJson()) }
|
|
||||||
it["experience"] = JsonPrimitive(experienceLevels)
|
it["experience"] = JsonPrimitive(experienceLevels)
|
||||||
|
|
||||||
if (skinIcon != null) {
|
if (skinIcon != null) {
|
||||||
@ -498,7 +408,6 @@ class AndroidResearchType(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun validate() {
|
fun validate() {
|
||||||
resolvedFeatures
|
|
||||||
resolvedBlockedBy
|
resolvedBlockedBy
|
||||||
resolvedPrerequisites
|
resolvedPrerequisites
|
||||||
}
|
}
|
||||||
@ -508,9 +417,8 @@ class AndroidResearchType(
|
|||||||
buff.writeCollection(prerequisites) { a, b -> b.toNetwork(a) }
|
buff.writeCollection(prerequisites) { a, b -> b.toNetwork(a) }
|
||||||
buff.writeCollection(blockedBy) { a, b -> b.toNetwork(a) }
|
buff.writeCollection(blockedBy) { a, b -> b.toNetwork(a) }
|
||||||
buff.writeCollection(definedItems) { a, b -> b.first.toNetwork(a); a.writeVarInt(b.second) }
|
buff.writeCollection(definedItems) { a, b -> b.first.toNetwork(a); a.writeVarInt(b.second) }
|
||||||
buff.writeCollection(features) { a, b -> b.toNetwork(a) }
|
buff.writeCollection(results) { a, b -> a.writeJson(AndroidResearchResult.CODEC.toJsonStrict(b)) }
|
||||||
buff.writeCollection(descriptionLines) { a, b -> a.writeComponent(b) }
|
buff.writeCollection(description) { a, b -> a.writeJson(AndroidResearchDescription.CODEC.toJsonStrict(b)) }
|
||||||
buff.writeCollection(descriptionSuppliers) { a, b -> b.toNetwork(a) }
|
|
||||||
buff.writeVarInt(experienceLevels)
|
buff.writeVarInt(experienceLevels)
|
||||||
|
|
||||||
buff.writeBoolean(customName != null)
|
buff.writeBoolean(customName != null)
|
||||||
@ -532,9 +440,8 @@ class AndroidResearchType(
|
|||||||
val prerequisites = buff.readCollection({ LinkedList() }, Reference::fromNetwork)
|
val prerequisites = buff.readCollection({ LinkedList() }, Reference::fromNetwork)
|
||||||
val blockedBy = buff.readCollection({ LinkedList() }, Reference::fromNetwork)
|
val blockedBy = buff.readCollection({ LinkedList() }, Reference::fromNetwork)
|
||||||
val items = buff.readCollection({ LinkedList() }, { Ingredient.fromNetwork(it) to it.readVarInt() })
|
val items = buff.readCollection({ LinkedList() }, { Ingredient.fromNetwork(it) to it.readVarInt() })
|
||||||
val features = buff.readCollection({ LinkedList() }, FeatureReference::fromNetwork)
|
val results = buff.readCollection({ LinkedList() }, { AndroidResearchResult.CODEC.fromJsonStrict(it.readJson()) })
|
||||||
val descriptionLines = buff.readCollection({ LinkedList() }, FriendlyByteBuf::readComponent)
|
val description = buff.readCollection({ LinkedList() }, { AndroidResearchDescription.CODEC.fromJsonStrict(it.readJson()) })
|
||||||
val descriptionSuppliers = buff.readCollection({ LinkedList() }, { AndroidResearchManager.descriptionFuncs.fromNetwork(it) })
|
|
||||||
val experienceLevels = buff.readVarInt()
|
val experienceLevels = buff.readVarInt()
|
||||||
|
|
||||||
val customName = if (buff.readBoolean()) {
|
val customName = if (buff.readBoolean()) {
|
||||||
@ -566,9 +473,8 @@ class AndroidResearchType(
|
|||||||
prerequisites = prerequisites,
|
prerequisites = prerequisites,
|
||||||
blockedBy = blockedBy,
|
blockedBy = blockedBy,
|
||||||
items = items,
|
items = items,
|
||||||
features = features,
|
results = results,
|
||||||
descriptionLines = descriptionLines,
|
description = description,
|
||||||
descriptionSuppliers = descriptionSuppliers.filterNotNull(),
|
|
||||||
experienceLevels = experienceLevels,
|
experienceLevels = experienceLevels,
|
||||||
customName = customName,
|
customName = customName,
|
||||||
iconText = iconTextValue,
|
iconText = iconTextValue,
|
||||||
@ -587,7 +493,6 @@ class AndroidResearchType(
|
|||||||
val items = value["required_items"] as JsonArray? ?: JsonArray()
|
val items = value["required_items"] as JsonArray? ?: JsonArray()
|
||||||
val features = value["feature_result"] as JsonArray? ?: JsonArray()
|
val features = value["feature_result"] as JsonArray? ?: JsonArray()
|
||||||
val description = value["description"] as JsonArray? ?: JsonArray()
|
val description = value["description"] as JsonArray? ?: JsonArray()
|
||||||
val description_funcs = value["description_funcs"] as JsonArray? ?: JsonArray()
|
|
||||||
val experience = value["experience"]?.asInt ?: 0
|
val experience = value["experience"]?.asInt ?: 0
|
||||||
val customName = value["custom_name"]?.let(Component.Serializer::fromJson)
|
val customName = value["custom_name"]?.let(Component.Serializer::fromJson)
|
||||||
val iconText = value["icon_text"]?.let(Component.Serializer::fromJson)
|
val iconText = value["icon_text"]?.let(Component.Serializer::fromJson)
|
||||||
@ -598,15 +503,12 @@ class AndroidResearchType(
|
|||||||
id = id,
|
id = id,
|
||||||
prerequisites = prerequisites.stream().map { Reference.fromJson(it) }.toList(),
|
prerequisites = prerequisites.stream().map { Reference.fromJson(it) }.toList(),
|
||||||
blockedBy = blocked_by.stream().map { Reference.fromJson(it) }.toList(),
|
blockedBy = blocked_by.stream().map { Reference.fromJson(it) }.toList(),
|
||||||
features = features.stream().map { FeatureReference.fromJson(it) }.toList(),
|
results = features.stream().map { AndroidResearchResult.CODEC.fromJsonStrict(it) }.toList(),
|
||||||
items = items.stream()
|
items = items.stream()
|
||||||
.map { it as? JsonObject ?: throw JsonSyntaxException("One of items is not an JsonObject") }
|
.map { it as? JsonObject ?: throw JsonSyntaxException("One of items is not an JsonObject") }
|
||||||
.map { Ingredient.fromJson(it["ingredient"] ?: throw JsonSyntaxException("Missing ingredient key")) to (it["count"]?.asInt ?: throw JsonSyntaxException("Missing count key")) }
|
.map { Ingredient.fromJson(it["ingredient"] ?: throw JsonSyntaxException("Missing ingredient key")) to (it["count"]?.asInt ?: throw JsonSyntaxException("Missing count key")) }
|
||||||
.toList(),
|
.toList(),
|
||||||
descriptionLines = description.stream().map { Component.Serializer.fromJson(it) }.toList() as List<MutableComponent>,
|
description = description.stream().map { AndroidResearchDescription.CODEC.fromJsonStrict(it) }.toList(),
|
||||||
descriptionSuppliers = description_funcs.stream()
|
|
||||||
.map { AndroidResearchManager.descriptionFuncs.fromJson(it) ?: throw NullPointerException("$id is missing description supplier function or it is invalid! JSON: $it") }
|
|
||||||
.toList() as List<ComponentSupplier>,
|
|
||||||
experienceLevels = experience,
|
experienceLevels = experience,
|
||||||
customName = customName,
|
customName = customName,
|
||||||
iconText = iconText,
|
iconText = iconText,
|
||||||
@ -621,18 +523,18 @@ class AndroidResearchType(
|
|||||||
val id: ResourceLocation,
|
val id: ResourceLocation,
|
||||||
var experience: Int = 0,
|
var experience: Int = 0,
|
||||||
var customName: Component? = null,
|
var customName: Component? = null,
|
||||||
var description: MutableList<Component>? = null,
|
description: MutableList<AndroidResearchDescription>? = null,
|
||||||
var descriptionSuppliers: MutableList<ComponentSupplier>? = null,
|
|
||||||
var itemIcon: Item? = null,
|
var itemIcon: Item? = null,
|
||||||
var skinIcon: AbstractMatterySprite? = null,
|
var skinIcon: AbstractMatterySprite? = null,
|
||||||
var iconText: Component? = null,
|
var iconText: Component? = null,
|
||||||
) {
|
) {
|
||||||
|
val description = ArrayList<AndroidResearchDescription>(description ?: listOf())
|
||||||
|
val results = ArrayList<AndroidResearchResult>()
|
||||||
|
|
||||||
private val items = ArrayList<Pair<Ingredient, Int>>()
|
private val items = ArrayList<Pair<Ingredient, Int>>()
|
||||||
private val prerequisites = ArrayList<Reference>()
|
private val prerequisites = ArrayList<Reference>()
|
||||||
private val blockers = ArrayList<Reference>()
|
private val blockers = ArrayList<Reference>()
|
||||||
|
|
||||||
private val features = ArrayList<FeatureReference>()
|
|
||||||
|
|
||||||
fun withIconText(icon: Component? = null): Builder {
|
fun withIconText(icon: Component? = null): Builder {
|
||||||
this.iconText = icon
|
this.iconText = icon
|
||||||
return this
|
return this
|
||||||
@ -661,19 +563,20 @@ class AndroidResearchType(
|
|||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun withDescription(): Builder {
|
fun clearDescription(): Builder {
|
||||||
this.description = mutableListOf(TranslatableComponent("android_research.${id.namespace}.${id.path}.description"))
|
this.description.clear()
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun withDescription(range: IntRange): Builder {
|
fun withDescription(): Builder {
|
||||||
val result = ArrayList<Component>()
|
return withDescription(TranslatableComponent("android_research.${id.namespace}.${id.path}.description"))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun withDescription(range: IntRange): Builder {
|
||||||
for (i in range) {
|
for (i in range) {
|
||||||
result.add(TranslatableComponent("android_research.${id.namespace}.${id.path}.description$i"))
|
withDescription(TranslatableComponent("android_research.${id.namespace}.${id.path}.description$i"))
|
||||||
}
|
}
|
||||||
|
|
||||||
this.description = result
|
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -683,73 +586,21 @@ class AndroidResearchType(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun withDescription(vararg description: Component): Builder {
|
fun withDescription(vararg description: Component): Builder {
|
||||||
this.description = description.toMutableList()
|
for (component in description)
|
||||||
|
withDescription(PlainAndroidResearchDescription.Instance(component))
|
||||||
|
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun withDescription(description: Collection<Component>): Builder {
|
fun withDescription(description: Collection<Component>): Builder {
|
||||||
this.description = ArrayList<Component>(description.size).also { it.addAll(description) }
|
for (component in description)
|
||||||
|
withDescription(PlainAndroidResearchDescription.Instance(component))
|
||||||
|
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun appendDescription(range: IntRange): Builder {
|
fun withDescription(vararg description: AndroidResearchDescription): Builder {
|
||||||
val result = this.description ?: ArrayList()
|
this.description.addAll(description)
|
||||||
|
|
||||||
for (i in range) {
|
|
||||||
result.add(TranslatableComponent("android_research.${id.namespace}.${id.path}.description$i"))
|
|
||||||
}
|
|
||||||
|
|
||||||
this.description = result
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun appendDescription(description: Component): Builder {
|
|
||||||
this.description = (this.description ?: mutableListOf()).also { it.add(description) }
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun appendDescription(vararg description: Component): Builder {
|
|
||||||
this.description = (this.description ?: mutableListOf()).also { it.addAll(description) }
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun appendDescription(description: Collection<Component>): Builder {
|
|
||||||
this.description = (this.description ?: mutableListOf()).also { it.addAll(description) }
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun withDescription(vararg description: ComponentSupplier): Builder {
|
|
||||||
this.descriptionSuppliers = description.toMutableList()
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun withDescriptionSupplier(description: Collection<ComponentSupplier>): Builder {
|
|
||||||
this.descriptionSuppliers = ArrayList<ComponentSupplier>(description.size).also { it.addAll(description) }
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun appendDescription(description: ComponentSupplier): Builder {
|
|
||||||
this.descriptionSuppliers = (this.descriptionSuppliers ?: mutableListOf()).also { it.add(description) }
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun appendDescriptionSupplier(description: ComponentSupplier): Builder {
|
|
||||||
this.descriptionSuppliers = (this.descriptionSuppliers ?: mutableListOf()).also { it.add(description) }
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun appendDescription(vararg description: ComponentSupplier): Builder {
|
|
||||||
this.descriptionSuppliers = (this.descriptionSuppliers ?: mutableListOf()).also { it.addAll(description) }
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun appendDescriptionSupplier(vararg description: ComponentSupplier): Builder {
|
|
||||||
this.descriptionSuppliers = (this.descriptionSuppliers ?: mutableListOf()).also { it.addAll(description) }
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun appendDescriptionSupplier(description: Collection<ComponentSupplier>): Builder {
|
|
||||||
this.descriptionSuppliers = (this.descriptionSuppliers ?: mutableListOf()).also { it.addAll(description) }
|
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -776,43 +627,25 @@ class AndroidResearchType(
|
|||||||
fun addPrerequisite(type: AndroidResearchType, rigid: Boolean = true) = addPrerequisite(type.id, rigid)
|
fun addPrerequisite(type: AndroidResearchType, rigid: Boolean = true) = addPrerequisite(type.id, rigid)
|
||||||
fun addBlocker(type: AndroidResearchType, rigid: Boolean = true) = addBlocker(type.id, rigid)
|
fun addBlocker(type: AndroidResearchType, rigid: Boolean = true) = addBlocker(type.id, rigid)
|
||||||
|
|
||||||
@JvmOverloads
|
fun addResult(result: AndroidResearchResult): Builder {
|
||||||
fun addFeatureResult(
|
results.add(result)
|
||||||
id: ResourceLocation,
|
|
||||||
level: Int = 0,
|
|
||||||
rigid: Boolean = false,
|
|
||||||
transformersUp: Collection<AndroidResultTransformer> = listOf(),
|
|
||||||
transformersDown: Collection<AndroidResultTransformer> = listOf(),
|
|
||||||
): Builder {
|
|
||||||
features.add(FeatureReference(id, level, rigid, transformersUp, transformersDown))
|
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmOverloads
|
fun addFeatureResult(id: ResourceLocation, optional: Boolean = false): Builder {
|
||||||
fun addFeatureResult(
|
return addResult(AndroidResearchResult.Feature(id, optional))
|
||||||
feature: AndroidFeatureType<*>,
|
|
||||||
level: Int = 0,
|
|
||||||
rigid: Boolean = true,
|
|
||||||
transformersUp: Collection<AndroidResultTransformer> = listOf(),
|
|
||||||
transformersDown: Collection<AndroidResultTransformer> = listOf(),
|
|
||||||
): Builder {
|
|
||||||
features.add(FeatureReference(feature.registryName ?: throw NullPointerException("Feature $feature does not have registry name"), level, rigid, transformersUp, transformersDown))
|
|
||||||
return this
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addFeatureResult(
|
fun addFeatureResult(feature: AndroidFeatureType<*>, optional: Boolean = false): Builder {
|
||||||
id: ResourceLocation,
|
return addFeatureResult(feature.registryName!!, optional)
|
||||||
rigid: Boolean = false,
|
|
||||||
transformersUp: Collection<AndroidResultTransformer> = listOf(),
|
|
||||||
transformersDown: Collection<AndroidResultTransformer> = listOf(),
|
|
||||||
): Builder {
|
|
||||||
features.add(FeatureReference(id, 0, rigid, transformersUp, transformersDown))
|
|
||||||
return this
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addFeatureResult(ref: FeatureReference): Builder {
|
fun addFeatureLevel(id: ResourceLocation, optional: Boolean = false, levels: Int = 1): Builder {
|
||||||
features.add(ref)
|
return addResult(AndroidResearchResult.FeatureLevel(id, optional, levels))
|
||||||
return this
|
}
|
||||||
|
|
||||||
|
fun addFeatureLevel(feature: AndroidFeatureType<*>, optional: Boolean = false, levels: Int = 1): Builder {
|
||||||
|
return addFeatureLevel(feature.registryName!!, optional, levels)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addItem(cost: ItemStack): Builder {
|
fun addItem(cost: ItemStack): Builder {
|
||||||
@ -844,9 +677,8 @@ class AndroidResearchType(
|
|||||||
prerequisites = prerequisites,
|
prerequisites = prerequisites,
|
||||||
blockedBy = blockers,
|
blockedBy = blockers,
|
||||||
items = items,
|
items = items,
|
||||||
features = features,
|
results = results,
|
||||||
descriptionLines = description ?: listOf(),
|
description = description,
|
||||||
descriptionSuppliers = descriptionSuppliers ?: listOf(),
|
|
||||||
experienceLevels = experience,
|
experienceLevels = experience,
|
||||||
customName = customName,
|
customName = customName,
|
||||||
skinIcon = skinIcon?.toJson(),
|
skinIcon = skinIcon?.toJson(),
|
||||||
|
@ -2,7 +2,6 @@ package ru.dbotthepony.mc.otm.android.feature
|
|||||||
|
|
||||||
import com.mojang.blaze3d.systems.RenderSystem
|
import com.mojang.blaze3d.systems.RenderSystem
|
||||||
import com.mojang.blaze3d.vertex.PoseStack
|
import com.mojang.blaze3d.vertex.PoseStack
|
||||||
import net.minecraft.ChatFormatting
|
|
||||||
import net.minecraft.client.Camera
|
import net.minecraft.client.Camera
|
||||||
import net.minecraft.client.gui.GuiGraphics
|
import net.minecraft.client.gui.GuiGraphics
|
||||||
import net.minecraft.client.renderer.LevelRenderer
|
import net.minecraft.client.renderer.LevelRenderer
|
||||||
@ -28,25 +27,22 @@ import net.minecraftforge.event.entity.living.LivingDeathEvent
|
|||||||
import ru.dbotthepony.mc.otm.NULLABLE_MINECRAFT_SERVER
|
import ru.dbotthepony.mc.otm.NULLABLE_MINECRAFT_SERVER
|
||||||
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
||||||
import ru.dbotthepony.mc.otm.android.AndroidActiveFeature
|
import ru.dbotthepony.mc.otm.android.AndroidActiveFeature
|
||||||
import ru.dbotthepony.mc.otm.android.AndroidResearchManager
|
|
||||||
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
|
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
|
||||||
import ru.dbotthepony.mc.otm.capability.energy.extractEnergyExact
|
import ru.dbotthepony.mc.otm.capability.energy.extractEnergyExact
|
||||||
import ru.dbotthepony.mc.otm.capability.matteryPlayer
|
import ru.dbotthepony.mc.otm.capability.matteryPlayer
|
||||||
import ru.dbotthepony.mc.otm.client.ShiftPressedCond
|
|
||||||
import ru.dbotthepony.mc.otm.client.render.DynamicBufferSource
|
import ru.dbotthepony.mc.otm.client.render.DynamicBufferSource
|
||||||
import ru.dbotthepony.mc.otm.client.render.ResearchIcons
|
import ru.dbotthepony.mc.otm.client.render.ResearchIcons
|
||||||
import ru.dbotthepony.mc.otm.client.render.sprite
|
|
||||||
import ru.dbotthepony.mc.otm.client.render.linesIgnoreZRenderType
|
import ru.dbotthepony.mc.otm.client.render.linesIgnoreZRenderType
|
||||||
|
import ru.dbotthepony.mc.otm.client.render.sprite
|
||||||
import ru.dbotthepony.mc.otm.config.AndroidConfig
|
import ru.dbotthepony.mc.otm.config.AndroidConfig
|
||||||
|
import ru.dbotthepony.mc.otm.core.genericPositions
|
||||||
|
import ru.dbotthepony.mc.otm.core.holder
|
||||||
|
import ru.dbotthepony.mc.otm.core.isFall
|
||||||
import ru.dbotthepony.mc.otm.core.math.Vector
|
import ru.dbotthepony.mc.otm.core.math.Vector
|
||||||
import ru.dbotthepony.mc.otm.core.math.asVector
|
import ru.dbotthepony.mc.otm.core.math.asVector
|
||||||
import ru.dbotthepony.mc.otm.core.math.component1
|
import ru.dbotthepony.mc.otm.core.math.component1
|
||||||
import ru.dbotthepony.mc.otm.core.math.component2
|
import ru.dbotthepony.mc.otm.core.math.component2
|
||||||
import ru.dbotthepony.mc.otm.core.math.component3
|
import ru.dbotthepony.mc.otm.core.math.component3
|
||||||
import ru.dbotthepony.mc.otm.core.util.formatPower
|
|
||||||
import ru.dbotthepony.mc.otm.core.genericPositions
|
|
||||||
import ru.dbotthepony.mc.otm.core.holder
|
|
||||||
import ru.dbotthepony.mc.otm.core.isFall
|
|
||||||
import ru.dbotthepony.mc.otm.core.math.plus
|
import ru.dbotthepony.mc.otm.core.math.plus
|
||||||
import ru.dbotthepony.mc.otm.core.math.rotateXDegrees
|
import ru.dbotthepony.mc.otm.core.math.rotateXDegrees
|
||||||
import ru.dbotthepony.mc.otm.core.math.rotateYDegrees
|
import ru.dbotthepony.mc.otm.core.math.rotateYDegrees
|
||||||
@ -54,7 +50,6 @@ import ru.dbotthepony.mc.otm.core.math.shortestDistanceBetween
|
|||||||
import ru.dbotthepony.mc.otm.core.math.times
|
import ru.dbotthepony.mc.otm.core.math.times
|
||||||
import ru.dbotthepony.mc.otm.milliTime
|
import ru.dbotthepony.mc.otm.milliTime
|
||||||
import ru.dbotthepony.mc.otm.registry.AndroidFeatures
|
import ru.dbotthepony.mc.otm.registry.AndroidFeatures
|
||||||
import ru.dbotthepony.mc.otm.registry.MNames
|
|
||||||
import ru.dbotthepony.mc.otm.triggers.EnderTeleporterFallDeathTrigger
|
import ru.dbotthepony.mc.otm.triggers.EnderTeleporterFallDeathTrigger
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.math.sin
|
import kotlin.math.sin
|
||||||
@ -399,12 +394,6 @@ class EnderTeleporterFeature(capability: MatteryPlayerCapability) : AndroidActiv
|
|||||||
|
|
||||||
val SPRITE = ResourceLocation(OverdriveThatMatters.MOD_ID, "textures/item/black_hole.png").sprite(0f, 0f, 16f, 16f, 16f, 16f)
|
val SPRITE = ResourceLocation(OverdriveThatMatters.MOD_ID, "textures/item/black_hole.png").sprite(0f, 0f, 16f, 16f, 16f, 16f)
|
||||||
|
|
||||||
val POWER_COST_DESCRIPTION =
|
|
||||||
AndroidResearchManager.descriptionFunc(
|
|
||||||
ResourceLocation(OverdriveThatMatters.MOD_ID, MNames.ENDER_TELEPORTER),
|
|
||||||
"otm.gui.power_cost_per_use",
|
|
||||||
{ AndroidConfig.EnderTeleporter.ENERGY_COST.formatPower(formatAsReadable = ShiftPressedCond).copy().withStyle(ChatFormatting.YELLOW) })
|
|
||||||
|
|
||||||
fun onEntityDeath(event: LivingDeathEvent) {
|
fun onEntityDeath(event: LivingDeathEvent) {
|
||||||
val android = event.entity.matteryPlayer ?: return
|
val android = event.entity.matteryPlayer ?: return
|
||||||
val server = NULLABLE_MINECRAFT_SERVER ?: return
|
val server = NULLABLE_MINECRAFT_SERVER ?: return
|
||||||
|
@ -35,10 +35,4 @@ class FallDampenersFeature(capability: MatteryPlayerCapability) : AndroidFeature
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
|
||||||
val DESCRIPTION = AndroidResearchManager.descriptionFuncs.register(ResourceLocation(OverdriveThatMatters.MOD_ID, MNames.FALL_DAMPENERS)) { level: Int ->
|
|
||||||
TranslatableComponent("otm.fall_dampeners.description", TextComponent("%.1f".format((AndroidConfig.FALL_DAMAGE_REDUCTION_PER_LEVEL * level).toFloat().coerceAtLeast(0f).coerceAtMost(1f) * 100f)).withStyle(ChatFormatting.YELLOW))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -132,12 +132,4 @@ class ItemMagnetFeature(capability: MatteryPlayerCapability) : AndroidSwitchable
|
|||||||
override fun renderIcon(graphics: GuiGraphics, x: Float, y: Float, width: Float, height: Float) {
|
override fun renderIcon(graphics: GuiGraphics, x: Float, y: Float, width: Float, height: Float) {
|
||||||
ResearchIcons.ICON_ITEM_MAGNET.render(graphics, x, y, width, height)
|
ResearchIcons.ICON_ITEM_MAGNET.render(graphics, x, y, width, height)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
|
||||||
val POWER_COST_DESCRIPTION =
|
|
||||||
AndroidResearchManager.descriptionFunc(ResourceLocation(
|
|
||||||
OverdriveThatMatters.MOD_ID, MNames.ITEM_MAGNET),
|
|
||||||
"otm.gui.power_cost_per_tick",
|
|
||||||
{ AndroidConfig.Magnet.POWER_DRAW.formatPower(formatAsReadable = ShiftPressedCond).copy().withStyle(ChatFormatting.YELLOW) })
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -125,13 +125,4 @@ class JumpBoostFeature(capability: MatteryPlayerCapability) : AndroidSwitchableF
|
|||||||
RenderSystem.setShaderColor(1f, 1f, 1f, 1f)
|
RenderSystem.setShaderColor(1f, 1f, 1f, 1f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
val POWER_COST_DESCRIPTION =
|
|
||||||
AndroidResearchManager.descriptionFunc(
|
|
||||||
ResourceLocation(OverdriveThatMatters.MOD_ID, MNames.JUMP_BOOST),
|
|
||||||
"otm.gui.power_cost_per_use",
|
|
||||||
{ AndroidConfig.JumpBoost.ENERGY_COST.formatPower(formatAsReadable = ShiftPressedCond).copy().withStyle(ChatFormatting.YELLOW) })
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -106,33 +106,5 @@ class NanobotsArmorFeature(android: MatteryPlayerCapability) : AndroidFeature(An
|
|||||||
0.45f,
|
0.45f,
|
||||||
0.6f,
|
0.6f,
|
||||||
)
|
)
|
||||||
|
|
||||||
val STRENGTH_TRANSFORMER_UP = AndroidResearchManager.featureResultTransformers.register(ResourceLocation(OverdriveThatMatters.MOD_ID, "nanobots_armor_strength_up"))
|
|
||||||
{ level: Int ->
|
|
||||||
if (second is NanobotsArmorFeature && (second as NanobotsArmorFeature).strength == level - 1) {
|
|
||||||
(second as NanobotsArmorFeature).strength = level
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val STRENGTH_TRANSFORMER_DOWN = AndroidResearchManager.featureResultTransformers.register(ResourceLocation(OverdriveThatMatters.MOD_ID, "nanobots_armor_strength_down"))
|
|
||||||
{ level: Int ->
|
|
||||||
if (second is NanobotsArmorFeature && (second as NanobotsArmorFeature).strength == level) {
|
|
||||||
(second as NanobotsArmorFeature).strength = level - 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val SPEED_TRANSFORMER_UP = AndroidResearchManager.featureResultTransformers.register(ResourceLocation(OverdriveThatMatters.MOD_ID, "nanobots_armor_speed_up"))
|
|
||||||
{ level: Int ->
|
|
||||||
if (second is NanobotsArmorFeature && (second as NanobotsArmorFeature).speed == level - 1) {
|
|
||||||
(second as NanobotsArmorFeature).speed = level
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val SPEED_TRANSFORMER_DOWN = AndroidResearchManager.featureResultTransformers.register(ResourceLocation(OverdriveThatMatters.MOD_ID, "nanobots_armor_speed_down"))
|
|
||||||
{ level: Int ->
|
|
||||||
if (second is NanobotsArmorFeature && (second as NanobotsArmorFeature).speed == level) {
|
|
||||||
(second as NanobotsArmorFeature).speed = level - 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -251,12 +251,4 @@ class ShockwaveFeature(capability: MatteryPlayerCapability) : AndroidSwitchableF
|
|||||||
RenderSystem.setShaderColor(1f, 1f, 1f, 1f)
|
RenderSystem.setShaderColor(1f, 1f, 1f, 1f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
|
||||||
val POWER_COST_DESCRIPTION =
|
|
||||||
AndroidResearchManager.descriptionFunc(
|
|
||||||
ResourceLocation(OverdriveThatMatters.MOD_ID, MNames.SHOCKWAVE),
|
|
||||||
"otm.gui.power_cost_per_use",
|
|
||||||
{ AndroidConfig.Shockwave.ENERGY_COST.formatPower(formatAsReadable = ShiftPressedCond).copy().withStyle(ChatFormatting.YELLOW) })
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
33
src/main/kotlin/ru/dbotthepony/mc/otm/data/Codecs.kt
Normal file
33
src/main/kotlin/ru/dbotthepony/mc/otm/data/Codecs.kt
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
package ru.dbotthepony.mc.otm.data
|
||||||
|
|
||||||
|
import com.mojang.serialization.Codec
|
||||||
|
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||||
|
import kotlin.reflect.KProperty1
|
||||||
|
|
||||||
|
|
||||||
|
fun <V, T1> simpleCodec(factory: (T1) -> V, field1: KProperty1<V, T1>, codec1: Codec<T1>): Codec<V> {
|
||||||
|
return RecordCodecBuilder.create {
|
||||||
|
it.group(
|
||||||
|
codec1.fieldOf(field1.name).forGetter(field1::get)
|
||||||
|
).apply(it, factory)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <V, T1, T2> simpleCodec(factory: (T1, T2) -> V, field1: KProperty1<V, T1>, codec1: Codec<T1>, field2: KProperty1<V, T2>, codec2: Codec<T2>): Codec<V> {
|
||||||
|
return RecordCodecBuilder.create {
|
||||||
|
it.group(
|
||||||
|
codec1.fieldOf(field1.name).forGetter(field1::get),
|
||||||
|
codec2.fieldOf(field2.name).forGetter(field2::get),
|
||||||
|
).apply(it, factory)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <V, T1, T2, T3> simpleCodec(factory: (T1, T2, T3) -> V, field1: KProperty1<V, T1>, codec1: Codec<T1>, field2: KProperty1<V, T2>, codec2: Codec<T2>, field3: KProperty1<V, T3>, codec3: Codec<T3>): Codec<V> {
|
||||||
|
return RecordCodecBuilder.create {
|
||||||
|
it.group(
|
||||||
|
codec1.fieldOf(field1.name).forGetter(field1::get),
|
||||||
|
codec2.fieldOf(field2.name).forGetter(field2::get),
|
||||||
|
codec3.fieldOf(field3.name).forGetter(field3::get),
|
||||||
|
).apply(it, factory)
|
||||||
|
}
|
||||||
|
}
|
25
src/main/kotlin/ru/dbotthepony/mc/otm/data/ComponentCodec.kt
Normal file
25
src/main/kotlin/ru/dbotthepony/mc/otm/data/ComponentCodec.kt
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
package ru.dbotthepony.mc.otm.data
|
||||||
|
|
||||||
|
import com.google.gson.JsonSyntaxException
|
||||||
|
import com.mojang.datafixers.util.Pair
|
||||||
|
import com.mojang.serialization.Codec
|
||||||
|
import com.mojang.serialization.DataResult
|
||||||
|
import com.mojang.serialization.DynamicOps
|
||||||
|
import com.mojang.serialization.JsonOps
|
||||||
|
import net.minecraft.network.chat.Component
|
||||||
|
|
||||||
|
object ComponentCodec : Codec<Component> {
|
||||||
|
override fun <T : Any> encode(input: Component, ops: DynamicOps<T>, prefix: T): DataResult<T> {
|
||||||
|
return DataResult.success(JsonOps.INSTANCE.convertTo(ops, Component.Serializer.toJsonTree(input)))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun <T : Any> decode(ops: DynamicOps<T>, input: T): DataResult<Pair<Component, T>> {
|
||||||
|
val value = ops.convertTo(JsonOps.INSTANCE, input)
|
||||||
|
|
||||||
|
try {
|
||||||
|
return DataResult.success(Pair(Component.Serializer.fromJson(value), ops.empty()))
|
||||||
|
} catch (err: JsonSyntaxException) {
|
||||||
|
return DataResult.error { err.message }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,225 +0,0 @@
|
|||||||
package ru.dbotthepony.mc.otm.data
|
|
||||||
|
|
||||||
import com.google.gson.Gson
|
|
||||||
import com.google.gson.JsonDeserializationContext
|
|
||||||
import com.google.gson.JsonDeserializer
|
|
||||||
import com.google.gson.JsonElement
|
|
||||||
import com.google.gson.JsonObject
|
|
||||||
import com.google.gson.JsonPrimitive
|
|
||||||
import com.google.gson.JsonSerializationContext
|
|
||||||
import com.google.gson.JsonSerializer
|
|
||||||
import com.google.gson.JsonSyntaxException
|
|
||||||
import com.google.gson.TypeAdapter
|
|
||||||
import com.google.gson.internal.bind.TypeAdapters
|
|
||||||
import com.google.gson.stream.JsonReader
|
|
||||||
import com.google.gson.stream.JsonWriter
|
|
||||||
import io.netty.buffer.ByteBufInputStream
|
|
||||||
import io.netty.buffer.ByteBufOutputStream
|
|
||||||
import it.unimi.dsi.fastutil.io.FastByteArrayInputStream
|
|
||||||
import it.unimi.dsi.fastutil.io.FastByteArrayOutputStream
|
|
||||||
import net.minecraft.nbt.NbtAccounter
|
|
||||||
import net.minecraft.network.FriendlyByteBuf
|
|
||||||
import net.minecraft.resources.ResourceLocation
|
|
||||||
import ru.dbotthepony.mc.otm.core.util.readType
|
|
||||||
import ru.dbotthepony.mc.otm.core.util.readVarIntLE
|
|
||||||
import ru.dbotthepony.mc.otm.core.nbt.set
|
|
||||||
import ru.dbotthepony.mc.otm.core.set
|
|
||||||
import ru.dbotthepony.mc.otm.core.util.writeType
|
|
||||||
import ru.dbotthepony.mc.otm.core.util.writeVarIntLE
|
|
||||||
import java.io.DataInputStream
|
|
||||||
import java.io.DataOutputStream
|
|
||||||
import java.lang.reflect.Type
|
|
||||||
import java.util.Base64
|
|
||||||
import java.util.Collections
|
|
||||||
import java.util.LinkedList
|
|
||||||
|
|
||||||
class SerializedFunctionRegistry<R, T>(val gson: Gson = Gson()) : JsonSerializer<SerializedFunctionRegistry.BoundFunction<R, T>>, JsonDeserializer<SerializedFunctionRegistry.BoundFunction<R, T>>, TypeAdapter<SerializedFunctionRegistry.BoundFunction<R, T>>() {
|
|
||||||
fun interface AnonymousFunction<R, T> {
|
|
||||||
fun invoke(receiver: R, arguments: List<Any?>): T
|
|
||||||
}
|
|
||||||
|
|
||||||
data class BoundFunction<R, T>(
|
|
||||||
val function: Function<R, T>,
|
|
||||||
val arguments: List<Any?>
|
|
||||||
) : java.util.function.Function<R, T> {
|
|
||||||
fun toJson(): JsonElement {
|
|
||||||
return JsonObject().also {
|
|
||||||
it["function"] = function.toJson()
|
|
||||||
val stream = FastByteArrayOutputStream()
|
|
||||||
val dataStream = DataOutputStream(stream)
|
|
||||||
|
|
||||||
stream.writeVarIntLE(arguments.size)
|
|
||||||
|
|
||||||
for (argument in arguments) {
|
|
||||||
dataStream.writeType(argument)
|
|
||||||
}
|
|
||||||
|
|
||||||
it["arguments"] = JsonPrimitive(Base64.getEncoder().encode(stream.array.copyOfRange(0, stream.length)).toString(Charsets.UTF_8))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun toNetwork(buff: FriendlyByteBuf) {
|
|
||||||
function.toNetwork(buff)
|
|
||||||
|
|
||||||
val stream = DataOutputStream(ByteBufOutputStream(buff))
|
|
||||||
stream.writeVarIntLE(arguments.size)
|
|
||||||
for (argument in arguments) {
|
|
||||||
stream.writeType(argument)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun apply(t: R): T {
|
|
||||||
return function.body.invoke(t, arguments)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
data class Function<R, T>(
|
|
||||||
val id: ResourceLocation,
|
|
||||||
val body: AnonymousFunction<R, T>,
|
|
||||||
val registry: SerializedFunctionRegistry<R, T>
|
|
||||||
) {
|
|
||||||
fun bind(vararg arguments: Any?): BoundFunction<R, T> {
|
|
||||||
validate(arguments.iterator().withIndex())
|
|
||||||
return BoundFunction(this, Collections.unmodifiableList(LinkedList<Any?>().also { it.addAll(arguments) }))
|
|
||||||
}
|
|
||||||
|
|
||||||
fun bind(arguments: List<Any?>): BoundFunction<R, T> {
|
|
||||||
validate(arguments.iterator().withIndex())
|
|
||||||
return BoundFunction(this, Collections.unmodifiableList(LinkedList<Any?>().also { it.addAll(arguments) }))
|
|
||||||
}
|
|
||||||
|
|
||||||
fun toJson(): JsonElement {
|
|
||||||
return JsonPrimitive(id.toString())
|
|
||||||
}
|
|
||||||
|
|
||||||
fun toNetwork(buff: FriendlyByteBuf) {
|
|
||||||
buff.writeUtf(id.toString())
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
private fun validate(iterator: Iterator<IndexedValue<Any?>>) {
|
|
||||||
try {
|
|
||||||
val stream = DataOutputStream(FastByteArrayOutputStream())
|
|
||||||
|
|
||||||
for ((i, argument) in iterator) {
|
|
||||||
try {
|
|
||||||
stream.writeType(argument)
|
|
||||||
} catch(err: Exception) {
|
|
||||||
throw IllegalArgumentException("Argument at $i can not be serialized", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch(err: Exception) {
|
|
||||||
throw IllegalArgumentException("Argument list validation failed", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private val map = HashMap<ResourceLocation, Function<R, T>>()
|
|
||||||
|
|
||||||
fun register(id: ResourceLocation, function: AnonymousFunction<R, T>): Function<R, T> {
|
|
||||||
synchronized(map) {
|
|
||||||
return map.computeIfAbsent(id) { Function(id, function, this) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun register(id: ResourceLocation, function: R.() -> T): Function<R, T> {
|
|
||||||
return register(id, AnonymousFunction { r, args ->
|
|
||||||
check(args.isEmpty()) { "Invalid amount of arguments. No arguments are required" }
|
|
||||||
function.invoke(r)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
inline fun <reified A : Any> register(id: ResourceLocation, noinline function: R.(A) -> T): Function<R, T> {
|
|
||||||
return register(id, AnonymousFunction { r, args ->
|
|
||||||
check(args.size == 1) { "Invalid amount of arguments. 1 is required" }
|
|
||||||
function.invoke(
|
|
||||||
r,
|
|
||||||
args[0] as? A ?: throw ClassCastException("Argument at 0 is supposed to be ${A::class.qualifiedName}, ${args[0]?.let { it::class.qualifiedName }} given")
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
inline fun <reified A : Any, reified B : Any> register(id: ResourceLocation, noinline function: R.(A, B) -> T): Function<R, T> {
|
|
||||||
return register(id, AnonymousFunction { r, args ->
|
|
||||||
check(args.size == 2) { "Invalid amount of arguments. 2 is required" }
|
|
||||||
|
|
||||||
function.invoke(
|
|
||||||
r,
|
|
||||||
args[0] as? A ?: throw ClassCastException("Argument at 0 is supposed to be ${A::class.qualifiedName}, ${args[0]?.let { it::class.qualifiedName }} given"),
|
|
||||||
args[1] as? B ?: throw ClassCastException("Argument at 1 is supposed to be ${B::class.qualifiedName}, ${args[1]?.let { it::class.qualifiedName }} given"),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
inline fun <reified A : Any, reified B : Any, reified C : Any> register(id: ResourceLocation, noinline function: R.(A, B, C) -> T): Function<R, T> {
|
|
||||||
return register(id, AnonymousFunction { r, args ->
|
|
||||||
check(args.size == 3) { "Invalid amount of arguments. 3 is required" }
|
|
||||||
|
|
||||||
function.invoke(
|
|
||||||
r,
|
|
||||||
args[0] as? A ?: throw ClassCastException("Argument at 0 is supposed to be ${A::class.qualifiedName}, ${args[0]?.let { it::class.qualifiedName }} given"),
|
|
||||||
args[1] as? B ?: throw ClassCastException("Argument at 1 is supposed to be ${B::class.qualifiedName}, ${args[1]?.let { it::class.qualifiedName }} given"),
|
|
||||||
args[2] as? C ?: throw ClassCastException("Argument at 2 is supposed to be ${B::class.qualifiedName}, ${args[2]?.let { it::class.qualifiedName }} given"),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fun get(id: ResourceLocation): Function<R, T>? {
|
|
||||||
synchronized(map) {
|
|
||||||
return map[id]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun fromNetwork(buff: FriendlyByteBuf): BoundFunction<R, T>? {
|
|
||||||
val id = ResourceLocation(buff.readUtf())
|
|
||||||
val stream = DataInputStream(ByteBufInputStream(buff))
|
|
||||||
|
|
||||||
val arguments = LinkedList<Any?>()
|
|
||||||
val sizeLimit = NbtAccounter(1L shl 18 /* 256 KiB */)
|
|
||||||
|
|
||||||
for (i in 0 until stream.readVarIntLE(sizeLimit)) {
|
|
||||||
arguments.add(stream.readType(sizeLimit))
|
|
||||||
}
|
|
||||||
|
|
||||||
return map[id]?.bind(arguments)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun fromJson(value: JsonElement): BoundFunction<R, T>? {
|
|
||||||
if (value !is JsonObject) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
val id = value["function"]?.asString ?: return null
|
|
||||||
val argumentString = value["arguments"]?.asString ?: return null
|
|
||||||
val stream = DataInputStream(FastByteArrayInputStream(Base64.getDecoder().decode(argumentString)))
|
|
||||||
val arguments = LinkedList<Any?>()
|
|
||||||
val sizeLimit = NbtAccounter(1L shl 18 /* 256 KiB */)
|
|
||||||
|
|
||||||
for (i in 0 until stream.readVarIntLE(sizeLimit)) {
|
|
||||||
arguments.add(stream.readType(sizeLimit))
|
|
||||||
}
|
|
||||||
|
|
||||||
return map[ResourceLocation(id)]?.bind(arguments)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun serialize(src: BoundFunction<R, T>, typeOfSrc: Type, context: JsonSerializationContext): JsonElement {
|
|
||||||
return src.toJson()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun deserialize(
|
|
||||||
json: JsonElement,
|
|
||||||
typeOfT: Type,
|
|
||||||
context: JsonDeserializationContext
|
|
||||||
): BoundFunction<R, T> {
|
|
||||||
return fromJson(json) ?: throw JsonSyntaxException("Function is invalid")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun write(out: JsonWriter, value: BoundFunction<R, T>) {
|
|
||||||
TypeAdapters.JSON_ELEMENT.write(out, value.toJson())
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun read(`in`: JsonReader): BoundFunction<R, T> {
|
|
||||||
return fromJson(TypeAdapters.JSON_ELEMENT.read(`in`)) ?: throw JsonSyntaxException("Function is invalid")
|
|
||||||
}
|
|
||||||
}
|
|
16
src/main/kotlin/ru/dbotthepony/mc/otm/data/SingletonCodec.kt
Normal file
16
src/main/kotlin/ru/dbotthepony/mc/otm/data/SingletonCodec.kt
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package ru.dbotthepony.mc.otm.data
|
||||||
|
|
||||||
|
import com.mojang.datafixers.util.Pair
|
||||||
|
import com.mojang.serialization.Codec
|
||||||
|
import com.mojang.serialization.DataResult
|
||||||
|
import com.mojang.serialization.DynamicOps
|
||||||
|
|
||||||
|
class SingletonCodec<V : Any>(val value: V) : Codec<V> {
|
||||||
|
override fun <T : Any> encode(input: V, ops: DynamicOps<T>, prefix: T): DataResult<T> {
|
||||||
|
return DataResult.success(ops.empty())
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun <T : Any> decode(ops: DynamicOps<T>, input: T? /* Так то, оно должно быть null */): DataResult<Pair<V, T>> {
|
||||||
|
return DataResult.success(Pair(value, ops.empty()))
|
||||||
|
}
|
||||||
|
}
|
@ -10,20 +10,20 @@ import ru.dbotthepony.mc.otm.android.feature.*
|
|||||||
object AndroidFeatures {
|
object AndroidFeatures {
|
||||||
private val registry = DeferredRegister.create(MRegistry.ANDROID_FEATURES_KEY, OverdriveThatMatters.MOD_ID)
|
private val registry = DeferredRegister.create(MRegistry.ANDROID_FEATURES_KEY, OverdriveThatMatters.MOD_ID)
|
||||||
|
|
||||||
val AIR_BAGS: AndroidFeatureType<*> by registry.register(MNames.AIR_BAGS) { AndroidFeatureType(::DummyAndroidFeature) }
|
val AIR_BAGS: AndroidFeatureType<DummyAndroidFeature> by registry.register(MNames.AIR_BAGS) { AndroidFeatureType(::DummyAndroidFeature) }
|
||||||
val STEP_ASSIST: AndroidFeatureType<*> by registry.register(MNames.STEP_ASSIST) { AndroidFeatureType(::StepAssistFeature) }
|
val STEP_ASSIST: AndroidFeatureType<StepAssistFeature> by registry.register(MNames.STEP_ASSIST) { AndroidFeatureType(::StepAssistFeature) }
|
||||||
val LIMB_OVERCLOCKING: AndroidFeatureType<*> by registry.register(MNames.LIMB_OVERCLOCKING) { AndroidFeatureType(::LimbOverclockingFeature) }
|
val LIMB_OVERCLOCKING: AndroidFeatureType<LimbOverclockingFeature> by registry.register(MNames.LIMB_OVERCLOCKING) { AndroidFeatureType(::LimbOverclockingFeature) }
|
||||||
val ATTACK_BOOST: AndroidFeatureType<*> by registry.register(MNames.ATTACK_BOOST) { AndroidFeatureType(::AttackBoostFeature) }
|
val ATTACK_BOOST: AndroidFeatureType<AttackBoostFeature> by registry.register(MNames.ATTACK_BOOST) { AndroidFeatureType(::AttackBoostFeature) }
|
||||||
val NANOBOTS_REGENERATION: AndroidFeatureType<*> by registry.register(MNames.NANOBOTS_REGENERATION) { AndroidFeatureType(::NanobotsRegenerationFeature) }
|
val NANOBOTS_REGENERATION: AndroidFeatureType<NanobotsRegenerationFeature> by registry.register(MNames.NANOBOTS_REGENERATION) { AndroidFeatureType(::NanobotsRegenerationFeature) }
|
||||||
val NANOBOTS_ARMOR: AndroidFeatureType<*> by registry.register(MNames.NANOBOTS_ARMOR) { AndroidFeatureType(::NanobotsArmorFeature) }
|
val NANOBOTS_ARMOR: AndroidFeatureType<NanobotsArmorFeature> by registry.register(MNames.NANOBOTS_ARMOR) { AndroidFeatureType(::NanobotsArmorFeature) }
|
||||||
val EXTENDED_REACH: AndroidFeatureType<*> by registry.register(MNames.EXTENDED_REACH) { AndroidFeatureType(::ExtendedReachFeature) }
|
val EXTENDED_REACH: AndroidFeatureType<ExtendedReachFeature> by registry.register(MNames.EXTENDED_REACH) { AndroidFeatureType(::ExtendedReachFeature) }
|
||||||
val NIGHT_VISION: AndroidFeatureType<*> by registry.register(MNames.NIGHT_VISION) { AndroidFeatureType(::NightVisionFeature) }
|
val NIGHT_VISION: AndroidFeatureType<NightVisionFeature> by registry.register(MNames.NIGHT_VISION) { AndroidFeatureType(::NightVisionFeature) }
|
||||||
val SHOCKWAVE: AndroidFeatureType<*> by registry.register(MNames.SHOCKWAVE) { AndroidFeatureType(::ShockwaveFeature) }
|
val SHOCKWAVE: AndroidFeatureType<ShockwaveFeature> by registry.register(MNames.SHOCKWAVE) { AndroidFeatureType(::ShockwaveFeature) }
|
||||||
val ITEM_MAGNET: AndroidFeatureType<*> by registry.register(MNames.ITEM_MAGNET) { AndroidFeatureType(::ItemMagnetFeature) }
|
val ITEM_MAGNET: AndroidFeatureType<ItemMagnetFeature> by registry.register(MNames.ITEM_MAGNET) { AndroidFeatureType(::ItemMagnetFeature) }
|
||||||
val FALL_DAMPENERS: AndroidFeatureType<*> by registry.register(MNames.FALL_DAMPENERS) { AndroidFeatureType(::FallDampenersFeature) }
|
val FALL_DAMPENERS: AndroidFeatureType<FallDampenersFeature> by registry.register(MNames.FALL_DAMPENERS) { AndroidFeatureType(::FallDampenersFeature) }
|
||||||
val PHANTOM_ATTRACTOR: AndroidFeatureType<*> by registry.register(MNames.PHANTOM_ATTRACTOR) { AndroidFeatureType(::PhantomAttractorFeature) }
|
val PHANTOM_ATTRACTOR: AndroidFeatureType<PhantomAttractorFeature> by registry.register(MNames.PHANTOM_ATTRACTOR) { AndroidFeatureType(::PhantomAttractorFeature) }
|
||||||
val JUMP_BOOST: AndroidFeatureType<*> by registry.register(MNames.JUMP_BOOST) { AndroidFeatureType(::JumpBoostFeature) }
|
val JUMP_BOOST: AndroidFeatureType<JumpBoostFeature> by registry.register(MNames.JUMP_BOOST) { AndroidFeatureType(::JumpBoostFeature) }
|
||||||
val ENDER_TELEPORTER: AndroidFeatureType<*> by registry.register(MNames.ENDER_TELEPORTER) { AndroidFeatureType(::EnderTeleporterFeature) }
|
val ENDER_TELEPORTER: AndroidFeatureType<EnderTeleporterFeature> by registry.register(MNames.ENDER_TELEPORTER) { AndroidFeatureType(::EnderTeleporterFeature) }
|
||||||
|
|
||||||
internal fun register(bus: IEventBus) {
|
internal fun register(bus: IEventBus) {
|
||||||
registry.register(bus)
|
registry.register(bus)
|
||||||
|
@ -16,13 +16,13 @@ import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent
|
|||||||
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent
|
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent
|
||||||
import net.minecraftforge.registries.NewRegistryEvent
|
import net.minecraftforge.registries.NewRegistryEvent
|
||||||
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
||||||
|
import ru.dbotthepony.mc.otm.android.AndroidResearchResult
|
||||||
|
import ru.dbotthepony.mc.otm.android.AndroidResearchResults
|
||||||
import ru.dbotthepony.mc.otm.android.AndroidFeatureType
|
import ru.dbotthepony.mc.otm.android.AndroidFeatureType
|
||||||
|
import ru.dbotthepony.mc.otm.android.AndroidResearchDescription
|
||||||
|
import ru.dbotthepony.mc.otm.android.AndroidResearchDescriptions
|
||||||
import ru.dbotthepony.mc.otm.android.feature.EnderTeleporterFeature
|
import ru.dbotthepony.mc.otm.android.feature.EnderTeleporterFeature
|
||||||
import ru.dbotthepony.mc.otm.android.feature.FallDampenersFeature
|
|
||||||
import ru.dbotthepony.mc.otm.android.feature.ItemMagnetFeature
|
|
||||||
import ru.dbotthepony.mc.otm.android.feature.JumpBoostFeature
|
|
||||||
import ru.dbotthepony.mc.otm.android.feature.NanobotsArmorFeature
|
import ru.dbotthepony.mc.otm.android.feature.NanobotsArmorFeature
|
||||||
import ru.dbotthepony.mc.otm.android.feature.ShockwaveFeature
|
|
||||||
import ru.dbotthepony.mc.otm.block.decorative.CargoCrateBlock
|
import ru.dbotthepony.mc.otm.block.decorative.CargoCrateBlock
|
||||||
import ru.dbotthepony.mc.otm.block.decorative.TritaniumPressurePlate
|
import ru.dbotthepony.mc.otm.block.decorative.TritaniumPressurePlate
|
||||||
import ru.dbotthepony.mc.otm.capability.matteryEnergy
|
import ru.dbotthepony.mc.otm.capability.matteryEnergy
|
||||||
@ -208,6 +208,10 @@ object MRegistry {
|
|||||||
MCreativeTabs.initialize(bus)
|
MCreativeTabs.initialize(bus)
|
||||||
|
|
||||||
DecimalProvider.register(bus)
|
DecimalProvider.register(bus)
|
||||||
|
AndroidResearchDescription.register(bus)
|
||||||
|
AndroidResearchDescriptions.register(bus)
|
||||||
|
AndroidResearchResult.register(bus)
|
||||||
|
AndroidResearchResults.register(bus)
|
||||||
|
|
||||||
MBlocks.register(bus)
|
MBlocks.register(bus)
|
||||||
MBlockEntities.register(bus)
|
MBlockEntities.register(bus)
|
||||||
@ -224,10 +228,6 @@ object MRegistry {
|
|||||||
|
|
||||||
// call static constructors
|
// call static constructors
|
||||||
NanobotsArmorFeature.Companion
|
NanobotsArmorFeature.Companion
|
||||||
ShockwaveFeature.Companion
|
|
||||||
ItemMagnetFeature.Companion
|
|
||||||
FallDampenersFeature.Companion
|
|
||||||
JumpBoostFeature.Companion
|
|
||||||
EnderTeleporterFeature.Companion
|
EnderTeleporterFeature.Companion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user