feat: Add overlay item exporter
This commit is contained in:
@@ -0,0 +1,26 @@
|
|||||||
|
package moe.nea.firmament.mixins;
|
||||||
|
|
||||||
|
import moe.nea.firmament.util.mc.InitLevel;
|
||||||
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
|
@Mixin(MinecraftClient.class)
|
||||||
|
public class MinecraftInitLevelListener {
|
||||||
|
@Inject(method = "<init>", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/systems/RenderSystem;initBackendSystem()Lnet/minecraft/util/TimeSupplier$Nanoseconds;"))
|
||||||
|
private void onInitRenderBackend(CallbackInfo ci) {
|
||||||
|
InitLevel.bump(InitLevel.RENDER_INIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject(method = "<init>", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/systems/RenderSystem;initRenderer(JIZLjava/util/function/BiFunction;Z)V"))
|
||||||
|
private void onInitRender(CallbackInfo ci) {
|
||||||
|
InitLevel.bump(InitLevel.RENDER);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject(method = "onFinishedLoading", at = @At(value = "HEAD"))
|
||||||
|
private void onFinishedLoading(CallbackInfo ci) {
|
||||||
|
InitLevel.bump(InitLevel.MAIN_MENU);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -51,6 +51,7 @@ import moe.nea.firmament.repo.RepoManager
|
|||||||
import moe.nea.firmament.util.MC
|
import moe.nea.firmament.util.MC
|
||||||
import moe.nea.firmament.util.SBData
|
import moe.nea.firmament.util.SBData
|
||||||
import moe.nea.firmament.util.data.IDataHolder
|
import moe.nea.firmament.util.data.IDataHolder
|
||||||
|
import moe.nea.firmament.util.mc.InitLevel
|
||||||
import moe.nea.firmament.util.tr
|
import moe.nea.firmament.util.tr
|
||||||
|
|
||||||
object Firmament {
|
object Firmament {
|
||||||
@@ -134,6 +135,7 @@ object Firmament {
|
|||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun onClientInitialize() {
|
fun onClientInitialize() {
|
||||||
|
InitLevel.bump(InitLevel.MC_INIT)
|
||||||
FeatureManager.subscribeEvents()
|
FeatureManager.subscribeEvents()
|
||||||
ClientTickEvents.END_CLIENT_TICK.register(ClientTickEvents.EndTick { instance ->
|
ClientTickEvents.END_CLIENT_TICK.register(ClientTickEvents.EndTick { instance ->
|
||||||
TickEvent.publish(TickEvent(MC.currentTick++))
|
TickEvent.publish(TickEvent(MC.currentTick++))
|
||||||
|
|||||||
@@ -3,17 +3,25 @@ package moe.nea.firmament.features.debug
|
|||||||
import com.mojang.serialization.Codec
|
import com.mojang.serialization.Codec
|
||||||
import com.mojang.serialization.codecs.RecordCodecBuilder
|
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||||
import java.util.Optional
|
import java.util.Optional
|
||||||
|
import net.minecraft.SharedConstants
|
||||||
|
import moe.nea.firmament.Firmament
|
||||||
|
|
||||||
data class ExportedTestConstantMeta(
|
data class ExportedTestConstantMeta(
|
||||||
val dataVersion: Int,
|
val dataVersion: Int,
|
||||||
val modVersion: Optional<String>,
|
val modVersion: Optional<String>,
|
||||||
) {
|
) {
|
||||||
companion object {
|
companion object {
|
||||||
|
val current = ExportedTestConstantMeta(
|
||||||
|
SharedConstants.getGameVersion().saveVersion.id,
|
||||||
|
Optional.of("Firmament ${Firmament.version.friendlyString}")
|
||||||
|
)
|
||||||
|
|
||||||
val CODEC: Codec<ExportedTestConstantMeta> = RecordCodecBuilder.create {
|
val CODEC: Codec<ExportedTestConstantMeta> = RecordCodecBuilder.create {
|
||||||
it.group(
|
it.group(
|
||||||
Codec.INT.fieldOf("dataVersion").forGetter(ExportedTestConstantMeta::dataVersion),
|
Codec.INT.fieldOf("dataVersion").forGetter(ExportedTestConstantMeta::dataVersion),
|
||||||
Codec.STRING.optionalFieldOf("modVersion").forGetter(ExportedTestConstantMeta::modVersion),
|
Codec.STRING.optionalFieldOf("modVersion").forGetter(ExportedTestConstantMeta::modVersion),
|
||||||
).apply(it, ::ExportedTestConstantMeta)
|
).apply(it, ::ExportedTestConstantMeta)
|
||||||
}
|
}
|
||||||
|
val SOURCE_CODEC = CODEC.fieldOf("source").codec()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,252 +1,53 @@
|
|||||||
package moe.nea.firmament.features.debug.itemeditor
|
package moe.nea.firmament.features.debug.itemeditor
|
||||||
|
|
||||||
import kotlinx.serialization.json.JsonArray
|
|
||||||
import kotlinx.serialization.json.JsonElement
|
|
||||||
import kotlinx.serialization.json.buildJsonObject
|
|
||||||
import kotlinx.serialization.json.jsonObject
|
import kotlinx.serialization.json.jsonObject
|
||||||
import kotlinx.serialization.json.jsonPrimitive
|
import kotlinx.serialization.json.jsonPrimitive
|
||||||
import kotlinx.serialization.json.put
|
|
||||||
import kotlin.concurrent.thread
|
|
||||||
import kotlin.io.path.createParentDirectories
|
import kotlin.io.path.createParentDirectories
|
||||||
import kotlin.io.path.relativeTo
|
import kotlin.io.path.relativeTo
|
||||||
import kotlin.io.path.writeText
|
import kotlin.io.path.writeText
|
||||||
import net.minecraft.component.DataComponentTypes
|
|
||||||
import net.minecraft.item.ItemStack
|
import net.minecraft.item.ItemStack
|
||||||
import net.minecraft.nbt.NbtCompound
|
import net.minecraft.nbt.NbtOps
|
||||||
import net.minecraft.nbt.NbtInt
|
|
||||||
import net.minecraft.nbt.NbtString
|
|
||||||
import net.minecraft.text.Text
|
|
||||||
import net.minecraft.util.Unit
|
|
||||||
import moe.nea.firmament.Firmament
|
import moe.nea.firmament.Firmament
|
||||||
import moe.nea.firmament.annotations.Subscribe
|
import moe.nea.firmament.annotations.Subscribe
|
||||||
import moe.nea.firmament.events.ClientStartedEvent
|
|
||||||
import moe.nea.firmament.events.HandledScreenKeyPressedEvent
|
import moe.nea.firmament.events.HandledScreenKeyPressedEvent
|
||||||
|
import moe.nea.firmament.features.debug.ExportedTestConstantMeta
|
||||||
import moe.nea.firmament.features.debug.PowerUserTools
|
import moe.nea.firmament.features.debug.PowerUserTools
|
||||||
import moe.nea.firmament.repo.RepoDownloadManager
|
import moe.nea.firmament.repo.RepoDownloadManager
|
||||||
import moe.nea.firmament.util.HypixelPetInfo
|
|
||||||
import moe.nea.firmament.util.LegacyTagWriter.Companion.toLegacyString
|
|
||||||
import moe.nea.firmament.util.StringUtil.words
|
|
||||||
import moe.nea.firmament.util.directLiteralStringContent
|
|
||||||
import moe.nea.firmament.util.extraAttributes
|
|
||||||
import moe.nea.firmament.util.focusedItemStack
|
import moe.nea.firmament.util.focusedItemStack
|
||||||
import moe.nea.firmament.util.getLegacyFormatString
|
import moe.nea.firmament.util.mc.SNbtFormatter.Companion.toPrettyString
|
||||||
import moe.nea.firmament.util.json.toJsonArray
|
|
||||||
import moe.nea.firmament.util.mc.displayNameAccordingToNbt
|
|
||||||
import moe.nea.firmament.util.mc.loreAccordingToNbt
|
|
||||||
import moe.nea.firmament.util.mc.toNbtList
|
|
||||||
import moe.nea.firmament.util.skyBlockId
|
|
||||||
import moe.nea.firmament.util.skyblock.Rarity
|
|
||||||
import moe.nea.firmament.util.tr
|
import moe.nea.firmament.util.tr
|
||||||
import moe.nea.firmament.util.transformEachRecursively
|
|
||||||
import moe.nea.firmament.util.unformattedString
|
|
||||||
|
|
||||||
class ItemExporter(var itemStack: ItemStack) {
|
object ItemExporter {
|
||||||
var lore = itemStack.loreAccordingToNbt
|
|
||||||
var name = itemStack.displayNameAccordingToNbt
|
|
||||||
val extraAttribs = itemStack.extraAttributes.copy()
|
|
||||||
val legacyNbt = NbtCompound()
|
|
||||||
val warnings = mutableListOf<String>()
|
|
||||||
|
|
||||||
fun preprocess() {
|
|
||||||
// TODO: split up preprocess steps into preprocess actions that can be toggled in a ui
|
|
||||||
extraAttribs.remove("timestamp")
|
|
||||||
extraAttribs.remove("uuid")
|
|
||||||
extraAttribs.remove("modifier")
|
|
||||||
extraAttribs.getString("petInfo").ifPresent { petInfoJson ->
|
|
||||||
var petInfo = Firmament.json.decodeFromString<HypixelPetInfo>(petInfoJson)
|
|
||||||
petInfo = petInfo.copy(candyUsed = 0, heldItem = null, exp = 0.0, active = null, uuid = null)
|
|
||||||
extraAttribs.putString("petInfo", Firmament.tightJson.encodeToString(petInfo))
|
|
||||||
}
|
|
||||||
itemStack.skyBlockId?.let {
|
|
||||||
extraAttribs.putString("id", it.neuItem)
|
|
||||||
}
|
|
||||||
trimLore()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun trimLore() {
|
@Subscribe
|
||||||
val rarityIdx = lore.indexOfLast {
|
fun onKeyBind(event: HandledScreenKeyPressedEvent) {
|
||||||
val firstWordInLine = it.unformattedString.words().filter { it.length > 2 }.firstOrNull()
|
if (event.matches(PowerUserTools.TConfig.exportItemStackToRepo)) {
|
||||||
firstWordInLine?.let(Rarity::fromString) != null
|
val itemStack = event.screen.focusedItemStack ?: return
|
||||||
}
|
val exporter = LegacyItemExporter.createExporter(itemStack)
|
||||||
if (rarityIdx >= 0) {
|
val json = exporter.exportJson()
|
||||||
lore = lore.subList(0, rarityIdx + 1)
|
val jsonFormatted = Firmament.twoSpaceJson.encodeToString(json)
|
||||||
}
|
val fileName = json.jsonObject["internalname"]!!.jsonPrimitive.content
|
||||||
deleteLineUntilNextSpace { it.startsWith("Held Item: ") }
|
val itemFile = RepoDownloadManager.repoSavedLocation.resolve("items").resolve("${fileName}.json")
|
||||||
deleteLineUntilNextSpace { it.startsWith("Progress to Level ") }
|
itemFile.createParentDirectories()
|
||||||
deleteLineUntilNextSpace { it.startsWith("MAX LEVEL") }
|
itemFile.writeText(jsonFormatted)
|
||||||
collapseWhitespaces()
|
val overlayFile = RepoDownloadManager.repoSavedLocation.resolve("itemsOverlay")
|
||||||
|
.resolve(ExportedTestConstantMeta.current.dataVersion.toString())
|
||||||
|
.resolve("${fileName}.snbt")
|
||||||
|
overlayFile.createParentDirectories()
|
||||||
|
overlayFile.writeText(exporter.exportModernSnbt().toPrettyString())
|
||||||
|
|
||||||
name = name.transformEachRecursively {
|
PowerUserTools.lastCopiedStack = Pair(
|
||||||
var string = it.directLiteralStringContent ?: return@transformEachRecursively it
|
itemStack,
|
||||||
string = string.replace("Lvl \\d+".toRegex(), "Lvl {LVL}")
|
tr(
|
||||||
Text.literal(string).setStyle(it.style)
|
"firmament.repoexport.success",
|
||||||
}
|
"Exported item to ${itemFile.relativeTo(RepoDownloadManager.repoSavedLocation)}${
|
||||||
}
|
exporter.warnings.joinToString(
|
||||||
|
""
|
||||||
fun collapseWhitespaces() {
|
) { "\nWarning: $it" }
|
||||||
lore = (listOf(null as Text?) + lore).zipWithNext()
|
}"
|
||||||
.filter { !it.first?.unformattedString.isNullOrBlank() || !it.second?.unformattedString.isNullOrBlank() }
|
|
||||||
.map { it.second!! }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun deleteLineUntilNextSpace(search: (String) -> Boolean) {
|
|
||||||
val idx = lore.indexOfFirst { search(it.unformattedString) }
|
|
||||||
if (idx < 0) return
|
|
||||||
val l = lore.toMutableList()
|
|
||||||
val p = l.subList(idx, l.size)
|
|
||||||
val nextBlank = p.indexOfFirst { it.unformattedString.isEmpty() }
|
|
||||||
if (nextBlank < 0)
|
|
||||||
p.clear()
|
|
||||||
else
|
|
||||||
p.subList(0, nextBlank).clear()
|
|
||||||
lore = l
|
|
||||||
}
|
|
||||||
|
|
||||||
fun processNbt() {
|
|
||||||
// TODO: calculate hideflags
|
|
||||||
legacyNbt.put("HideFlags", NbtInt.of(254))
|
|
||||||
copyUnbreakable()
|
|
||||||
copyItemModel()
|
|
||||||
copyExtraAttributes()
|
|
||||||
copyLegacySkullNbt()
|
|
||||||
copyDisplay()
|
|
||||||
copyEnchantments()
|
|
||||||
copyEnchantGlint()
|
|
||||||
// TODO: copyDisplay
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun copyItemModel() {
|
|
||||||
val itemModel = itemStack.get(DataComponentTypes.ITEM_MODEL) ?: return
|
|
||||||
legacyNbt.put("ItemModel", NbtString.of(itemModel.toString()))
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun copyDisplay() {
|
|
||||||
legacyNbt.put("display", NbtCompound().apply {
|
|
||||||
put("Lore", lore.map { NbtString.of(it.getLegacyFormatString(trimmed = true)) }.toNbtList())
|
|
||||||
putString("Name", name.getLegacyFormatString(trimmed = true))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fun exportJson(): JsonElement {
|
|
||||||
preprocess()
|
|
||||||
processNbt()
|
|
||||||
return buildJsonObject {
|
|
||||||
val (itemId, damage) = legacyifyItemStack()
|
|
||||||
put("itemid", itemId)
|
|
||||||
put("displayname", name.getLegacyFormatString(trimmed = true))
|
|
||||||
put("nbttag", legacyNbt.toLegacyString())
|
|
||||||
put("damage", damage)
|
|
||||||
put("lore", lore.map { it.getLegacyFormatString(trimmed = true) }.toJsonArray())
|
|
||||||
val sbId = itemStack.skyBlockId
|
|
||||||
if (sbId == null)
|
|
||||||
warnings.add("Could not find skyblock id")
|
|
||||||
put("internalname", sbId?.neuItem)
|
|
||||||
put("clickcommand", "")
|
|
||||||
put("crafttext", "")
|
|
||||||
put("modver", "Firmament ${Firmament.version.friendlyString}")
|
|
||||||
put("infoType", "")
|
|
||||||
put("info", JsonArray(listOf()))
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
@Subscribe
|
|
||||||
fun load(event: ClientStartedEvent) {
|
|
||||||
thread(start = true, name = "ItemExporter Meta Load Thread") {
|
|
||||||
LegacyItemData.itemLut
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Subscribe
|
|
||||||
fun onKeyBind(event: HandledScreenKeyPressedEvent) {
|
|
||||||
if (event.matches(PowerUserTools.TConfig.exportItemStackToRepo)) {
|
|
||||||
val itemStack = event.screen.focusedItemStack ?: return
|
|
||||||
val exporter = ItemExporter(itemStack)
|
|
||||||
val json = exporter.exportJson()
|
|
||||||
val jsonFormatted = Firmament.twoSpaceJson.encodeToString(json)
|
|
||||||
val itemFile = RepoDownloadManager.repoSavedLocation.resolve("items")
|
|
||||||
.resolve("${json.jsonObject["internalname"]!!.jsonPrimitive.content}.json")
|
|
||||||
itemFile.createParentDirectories()
|
|
||||||
itemFile.writeText(jsonFormatted)
|
|
||||||
PowerUserTools.lastCopiedStack = Pair(
|
|
||||||
itemStack,
|
|
||||||
tr(
|
|
||||||
"firmament.repoexport.success",
|
|
||||||
"Exported item to ${itemFile.relativeTo(RepoDownloadManager.repoSavedLocation)}${
|
|
||||||
exporter.warnings.joinToString(
|
|
||||||
""
|
|
||||||
) { "\nWarning: $it" }
|
|
||||||
}"
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun copyEnchantGlint() {
|
|
||||||
if (itemStack.get(DataComponentTypes.ENCHANTMENT_GLINT_OVERRIDE) == true) {
|
|
||||||
val ench = legacyNbt.getListOrEmpty("ench")
|
|
||||||
legacyNbt.put("ench", ench)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun copyUnbreakable() {
|
|
||||||
if (itemStack.get(DataComponentTypes.UNBREAKABLE) == Unit.INSTANCE) {
|
|
||||||
legacyNbt.putBoolean("Unbreakable", true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun copyEnchantments() {
|
|
||||||
val enchantments = itemStack.get(DataComponentTypes.ENCHANTMENTS)?.takeIf { !it.isEmpty } ?: return
|
|
||||||
val enchTag = legacyNbt.getListOrEmpty("ench")
|
|
||||||
legacyNbt.put("ench", enchTag)
|
|
||||||
enchantments.enchantmentEntries.forEach { entry ->
|
|
||||||
val id = entry.key.key.get().value
|
|
||||||
val legacyId = LegacyItemData.enchantmentLut[id]
|
|
||||||
if (legacyId == null) {
|
|
||||||
warnings.add("Could not find legacy enchantment id for ${id}")
|
|
||||||
return@forEach
|
|
||||||
}
|
|
||||||
enchTag.add(NbtCompound().apply {
|
|
||||||
putShort("lvl", entry.intValue.toShort())
|
|
||||||
putShort(
|
|
||||||
"id",
|
|
||||||
legacyId.id.toShort()
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun copyExtraAttributes() {
|
|
||||||
legacyNbt.put("ExtraAttributes", extraAttribs)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun copyLegacySkullNbt() {
|
|
||||||
val profile = itemStack.get(DataComponentTypes.PROFILE) ?: return
|
|
||||||
legacyNbt.put("SkullOwner", NbtCompound().apply {
|
|
||||||
profile.id.ifPresent {
|
|
||||||
putString("Id", it.toString())
|
|
||||||
}
|
|
||||||
putBoolean("hypixelPopulated", true)
|
|
||||||
put("Properties", NbtCompound().apply {
|
|
||||||
profile.properties().forEach { prop, value ->
|
|
||||||
val list = getListOrEmpty(prop)
|
|
||||||
put(prop, list)
|
|
||||||
list.add(NbtCompound().apply {
|
|
||||||
value.signature?.let {
|
|
||||||
putString("Signature", it)
|
|
||||||
}
|
|
||||||
putString("Value", value.value)
|
|
||||||
putString("Name", value.name)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fun legacyifyItemStack(): LegacyItemData.LegacyItemType {
|
|
||||||
// TODO: add a default here
|
|
||||||
return LegacyItemData.itemLut[itemStack.item]!!
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
240
src/main/kotlin/features/debug/itemeditor/LegacyItemExporter.kt
Normal file
240
src/main/kotlin/features/debug/itemeditor/LegacyItemExporter.kt
Normal file
@@ -0,0 +1,240 @@
|
|||||||
|
package moe.nea.firmament.features.debug.itemeditor
|
||||||
|
|
||||||
|
import kotlinx.serialization.json.JsonArray
|
||||||
|
import kotlinx.serialization.json.JsonElement
|
||||||
|
import kotlinx.serialization.json.buildJsonObject
|
||||||
|
import kotlinx.serialization.json.put
|
||||||
|
import kotlin.concurrent.thread
|
||||||
|
import net.minecraft.component.DataComponentTypes
|
||||||
|
import net.minecraft.item.ItemStack
|
||||||
|
import net.minecraft.nbt.NbtCompound
|
||||||
|
import net.minecraft.nbt.NbtElement
|
||||||
|
import net.minecraft.nbt.NbtInt
|
||||||
|
import net.minecraft.nbt.NbtOps
|
||||||
|
import net.minecraft.nbt.NbtString
|
||||||
|
import net.minecraft.text.Text
|
||||||
|
import net.minecraft.util.Unit
|
||||||
|
import moe.nea.firmament.Firmament
|
||||||
|
import moe.nea.firmament.annotations.Subscribe
|
||||||
|
import moe.nea.firmament.events.ClientStartedEvent
|
||||||
|
import moe.nea.firmament.features.debug.ExportedTestConstantMeta
|
||||||
|
import moe.nea.firmament.util.HypixelPetInfo
|
||||||
|
import moe.nea.firmament.util.LegacyTagWriter.Companion.toLegacyString
|
||||||
|
import moe.nea.firmament.util.StringUtil.words
|
||||||
|
import moe.nea.firmament.util.directLiteralStringContent
|
||||||
|
import moe.nea.firmament.util.extraAttributes
|
||||||
|
import moe.nea.firmament.util.getLegacyFormatString
|
||||||
|
import moe.nea.firmament.util.json.toJsonArray
|
||||||
|
import moe.nea.firmament.util.mc.displayNameAccordingToNbt
|
||||||
|
import moe.nea.firmament.util.mc.loreAccordingToNbt
|
||||||
|
import moe.nea.firmament.util.mc.toNbtList
|
||||||
|
import moe.nea.firmament.util.skyBlockId
|
||||||
|
import moe.nea.firmament.util.skyblock.Rarity
|
||||||
|
import moe.nea.firmament.util.transformEachRecursively
|
||||||
|
import moe.nea.firmament.util.unformattedString
|
||||||
|
|
||||||
|
class LegacyItemExporter private constructor(var itemStack: ItemStack) {
|
||||||
|
var lore = itemStack.loreAccordingToNbt
|
||||||
|
var name = itemStack.displayNameAccordingToNbt
|
||||||
|
val extraAttribs = itemStack.extraAttributes.copy()
|
||||||
|
val legacyNbt = NbtCompound()
|
||||||
|
val warnings = mutableListOf<String>()
|
||||||
|
|
||||||
|
// TODO: check if lore contains non 1.8.9 able hex codes and emit lore in overlay files if so
|
||||||
|
|
||||||
|
fun preprocess() {
|
||||||
|
// TODO: split up preprocess steps into preprocess actions that can be toggled in a ui
|
||||||
|
extraAttribs.remove("timestamp")
|
||||||
|
extraAttribs.remove("uuid")
|
||||||
|
extraAttribs.remove("modifier")
|
||||||
|
extraAttribs.getString("petInfo").ifPresent { petInfoJson ->
|
||||||
|
var petInfo = Firmament.json.decodeFromString<HypixelPetInfo>(petInfoJson)
|
||||||
|
petInfo = petInfo.copy(candyUsed = 0, heldItem = null, exp = 0.0, active = null, uuid = null)
|
||||||
|
extraAttribs.putString("petInfo", Firmament.tightJson.encodeToString(petInfo))
|
||||||
|
}
|
||||||
|
itemStack.skyBlockId?.let {
|
||||||
|
extraAttribs.putString("id", it.neuItem)
|
||||||
|
}
|
||||||
|
trimLore()
|
||||||
|
itemStack.loreAccordingToNbt = itemStack.item.defaultStack.loreAccordingToNbt
|
||||||
|
itemStack.remove(DataComponentTypes.CUSTOM_NAME)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun trimLore() {
|
||||||
|
val rarityIdx = lore.indexOfLast {
|
||||||
|
val firstWordInLine = it.unformattedString.words().filter { it.length > 2 }.firstOrNull()
|
||||||
|
firstWordInLine?.let(Rarity::fromString) != null
|
||||||
|
}
|
||||||
|
if (rarityIdx >= 0) {
|
||||||
|
lore = lore.subList(0, rarityIdx + 1)
|
||||||
|
}
|
||||||
|
deleteLineUntilNextSpace { it.startsWith("Held Item: ") }
|
||||||
|
deleteLineUntilNextSpace { it.startsWith("Progress to Level ") }
|
||||||
|
deleteLineUntilNextSpace { it.startsWith("MAX LEVEL") }
|
||||||
|
collapseWhitespaces()
|
||||||
|
|
||||||
|
name = name.transformEachRecursively {
|
||||||
|
var string = it.directLiteralStringContent ?: return@transformEachRecursively it
|
||||||
|
string = string.replace("Lvl \\d+".toRegex(), "Lvl {LVL}")
|
||||||
|
Text.literal(string).setStyle(it.style)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun collapseWhitespaces() {
|
||||||
|
lore = (listOf(null as Text?) + lore).zipWithNext()
|
||||||
|
.filter { !it.first?.unformattedString.isNullOrBlank() || !it.second?.unformattedString.isNullOrBlank() }
|
||||||
|
.map { it.second!! }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun deleteLineUntilNextSpace(search: (String) -> Boolean) {
|
||||||
|
val idx = lore.indexOfFirst { search(it.unformattedString) }
|
||||||
|
if (idx < 0) return
|
||||||
|
val l = lore.toMutableList()
|
||||||
|
val p = l.subList(idx, l.size)
|
||||||
|
val nextBlank = p.indexOfFirst { it.unformattedString.isEmpty() }
|
||||||
|
if (nextBlank < 0)
|
||||||
|
p.clear()
|
||||||
|
else
|
||||||
|
p.subList(0, nextBlank).clear()
|
||||||
|
lore = l
|
||||||
|
}
|
||||||
|
|
||||||
|
fun processNbt() {
|
||||||
|
// TODO: calculate hideflags
|
||||||
|
legacyNbt.put("HideFlags", NbtInt.of(254))
|
||||||
|
copyUnbreakable()
|
||||||
|
copyItemModel()
|
||||||
|
copyExtraAttributes()
|
||||||
|
copyLegacySkullNbt()
|
||||||
|
copyDisplay()
|
||||||
|
copyEnchantments()
|
||||||
|
copyEnchantGlint()
|
||||||
|
// TODO: copyDisplay
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun copyItemModel() {
|
||||||
|
val itemModel = itemStack.get(DataComponentTypes.ITEM_MODEL) ?: return
|
||||||
|
legacyNbt.put("ItemModel", NbtString.of(itemModel.toString()))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun copyDisplay() {
|
||||||
|
legacyNbt.put("display", NbtCompound().apply {
|
||||||
|
put("Lore", lore.map { NbtString.of(it.getLegacyFormatString(trimmed = true)) }.toNbtList())
|
||||||
|
putString("Name", name.getLegacyFormatString(trimmed = true))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fun exportModernSnbt(): NbtElement {
|
||||||
|
val overlay = ItemStack.CODEC.encodeStart(NbtOps.INSTANCE, itemStack)
|
||||||
|
.orThrow
|
||||||
|
val overlayWithVersion =
|
||||||
|
ExportedTestConstantMeta.SOURCE_CODEC.encode(ExportedTestConstantMeta.current, NbtOps.INSTANCE, overlay)
|
||||||
|
.orThrow
|
||||||
|
return overlayWithVersion
|
||||||
|
}
|
||||||
|
|
||||||
|
fun prepare() {
|
||||||
|
preprocess()
|
||||||
|
processNbt()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun exportJson(): JsonElement {
|
||||||
|
return buildJsonObject {
|
||||||
|
val (itemId, damage) = legacyifyItemStack()
|
||||||
|
put("itemid", itemId)
|
||||||
|
put("displayname", name.getLegacyFormatString(trimmed = true))
|
||||||
|
put("nbttag", legacyNbt.toLegacyString())
|
||||||
|
put("damage", damage)
|
||||||
|
put("lore", lore.map { it.getLegacyFormatString(trimmed = true) }.toJsonArray())
|
||||||
|
val sbId = itemStack.skyBlockId
|
||||||
|
if (sbId == null)
|
||||||
|
warnings.add("Could not find skyblock id")
|
||||||
|
put("internalname", sbId?.neuItem)
|
||||||
|
put("clickcommand", "")
|
||||||
|
put("crafttext", "")
|
||||||
|
put("modver", "Firmament ${Firmament.version.friendlyString}")
|
||||||
|
put("infoType", "")
|
||||||
|
put("info", JsonArray(listOf()))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun createExporter(itemStack: ItemStack): LegacyItemExporter {
|
||||||
|
return LegacyItemExporter(itemStack.copy()).also { it.prepare() }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
fun load(event: ClientStartedEvent) {
|
||||||
|
thread(start = true, name = "ItemExporter Meta Load Thread") {
|
||||||
|
LegacyItemData.itemLut
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun copyEnchantGlint() {
|
||||||
|
if (itemStack.get(DataComponentTypes.ENCHANTMENT_GLINT_OVERRIDE) == true) {
|
||||||
|
val ench = legacyNbt.getListOrEmpty("ench")
|
||||||
|
legacyNbt.put("ench", ench)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun copyUnbreakable() {
|
||||||
|
if (itemStack.get(DataComponentTypes.UNBREAKABLE) == Unit.INSTANCE) {
|
||||||
|
legacyNbt.putBoolean("Unbreakable", true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun copyEnchantments() {
|
||||||
|
val enchantments = itemStack.get(DataComponentTypes.ENCHANTMENTS)?.takeIf { !it.isEmpty } ?: return
|
||||||
|
val enchTag = legacyNbt.getListOrEmpty("ench")
|
||||||
|
legacyNbt.put("ench", enchTag)
|
||||||
|
enchantments.enchantmentEntries.forEach { entry ->
|
||||||
|
val id = entry.key.key.get().value
|
||||||
|
val legacyId = LegacyItemData.enchantmentLut[id]
|
||||||
|
if (legacyId == null) {
|
||||||
|
warnings.add("Could not find legacy enchantment id for ${id}")
|
||||||
|
return@forEach
|
||||||
|
}
|
||||||
|
enchTag.add(NbtCompound().apply {
|
||||||
|
putShort("lvl", entry.intValue.toShort())
|
||||||
|
putShort(
|
||||||
|
"id",
|
||||||
|
legacyId.id.toShort()
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun copyExtraAttributes() {
|
||||||
|
legacyNbt.put("ExtraAttributes", extraAttribs)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun copyLegacySkullNbt() {
|
||||||
|
val profile = itemStack.get(DataComponentTypes.PROFILE) ?: return
|
||||||
|
legacyNbt.put("SkullOwner", NbtCompound().apply {
|
||||||
|
profile.id.ifPresent {
|
||||||
|
putString("Id", it.toString())
|
||||||
|
}
|
||||||
|
putBoolean("hypixelPopulated", true)
|
||||||
|
put("Properties", NbtCompound().apply {
|
||||||
|
profile.properties().forEach { prop, value ->
|
||||||
|
val list = getListOrEmpty(prop)
|
||||||
|
put(prop, list)
|
||||||
|
list.add(NbtCompound().apply {
|
||||||
|
value.signature?.let {
|
||||||
|
putString("Signature", it)
|
||||||
|
}
|
||||||
|
putString("Value", value.value)
|
||||||
|
putString("Name", value.name)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fun legacyifyItemStack(): LegacyItemData.LegacyItemType {
|
||||||
|
// TODO: add a default here
|
||||||
|
return LegacyItemData.itemLut[itemStack.item]!!
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -49,7 +49,7 @@ class ManagedOption<T : Any>(
|
|||||||
value = handler.fromJson(root[propertyName]!!)
|
value = handler.fromJson(root[propertyName]!!)
|
||||||
return
|
return
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
ErrorUtil.softError(
|
ErrorUtil.logError(
|
||||||
"Exception during loading of config file ${element.name}. This will reset this config.",
|
"Exception during loading of config file ${element.name}. This will reset this config.",
|
||||||
e
|
e
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import net.minecraft.client.MinecraftClient
|
|||||||
import net.minecraft.client.util.InputUtil
|
import net.minecraft.client.util.InputUtil
|
||||||
import net.minecraft.text.Text
|
import net.minecraft.text.Text
|
||||||
import moe.nea.firmament.util.MC
|
import moe.nea.firmament.util.MC
|
||||||
|
import moe.nea.firmament.util.mc.InitLevel
|
||||||
|
|
||||||
// TODO: add support for mouse keybindings
|
// TODO: add support for mouse keybindings
|
||||||
@Serializable
|
@Serializable
|
||||||
@@ -113,8 +114,11 @@ data class SavedKeyBinding(
|
|||||||
if (shift) {
|
if (shift) {
|
||||||
stroke.append("SHIFT + ") // TODO: translations?
|
stroke.append("SHIFT + ") // TODO: translations?
|
||||||
}
|
}
|
||||||
|
if (InitLevel.isAtLeast(InitLevel.RENDER_INIT)) {
|
||||||
stroke.append(InputUtil.Type.KEYSYM.createFromCode(keyCode).localizedText)
|
stroke.append(InputUtil.Type.KEYSYM.createFromCode(keyCode).localizedText)
|
||||||
|
} else {
|
||||||
|
stroke.append(keyCode.toString())
|
||||||
|
}
|
||||||
return stroke
|
return stroke
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import kotlinx.coroutines.awaitAll
|
|||||||
import kotlinx.coroutines.cancel
|
import kotlinx.coroutines.cancel
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
import kotlin.io.path.readText
|
||||||
import kotlin.jvm.optionals.getOrNull
|
import kotlin.jvm.optionals.getOrNull
|
||||||
import net.minecraft.SharedConstants
|
import net.minecraft.SharedConstants
|
||||||
import net.minecraft.component.DataComponentTypes
|
import net.minecraft.component.DataComponentTypes
|
||||||
@@ -28,11 +29,13 @@ import net.minecraft.nbt.NbtCompound
|
|||||||
import net.minecraft.nbt.NbtElement
|
import net.minecraft.nbt.NbtElement
|
||||||
import net.minecraft.nbt.NbtOps
|
import net.minecraft.nbt.NbtOps
|
||||||
import net.minecraft.nbt.NbtString
|
import net.minecraft.nbt.NbtString
|
||||||
|
import net.minecraft.nbt.StringNbtReader
|
||||||
import net.minecraft.text.MutableText
|
import net.minecraft.text.MutableText
|
||||||
import net.minecraft.text.Style
|
import net.minecraft.text.Style
|
||||||
import net.minecraft.text.Text
|
import net.minecraft.text.Text
|
||||||
import net.minecraft.util.Identifier
|
import net.minecraft.util.Identifier
|
||||||
import moe.nea.firmament.Firmament
|
import moe.nea.firmament.Firmament
|
||||||
|
import moe.nea.firmament.features.debug.ExportedTestConstantMeta
|
||||||
import moe.nea.firmament.repo.RepoManager.initialize
|
import moe.nea.firmament.repo.RepoManager.initialize
|
||||||
import moe.nea.firmament.util.LegacyFormattingCode
|
import moe.nea.firmament.util.LegacyFormattingCode
|
||||||
import moe.nea.firmament.util.LegacyTagParser
|
import moe.nea.firmament.util.LegacyTagParser
|
||||||
@@ -67,6 +70,7 @@ object ItemCache : IReloadable {
|
|||||||
|
|
||||||
@ExpensiveItemCacheApi
|
@ExpensiveItemCacheApi
|
||||||
private fun NbtCompound.transformFrom10809ToModern() = convert189ToModern(this@transformFrom10809ToModern)
|
private fun NbtCompound.transformFrom10809ToModern() = convert189ToModern(this@transformFrom10809ToModern)
|
||||||
|
val currentSaveVersion = SharedConstants.getGameVersion().saveVersion.id
|
||||||
|
|
||||||
@ExpensiveItemCacheApi
|
@ExpensiveItemCacheApi
|
||||||
fun convert189ToModern(nbtComponent: NbtCompound): NbtCompound? =
|
fun convert189ToModern(nbtComponent: NbtCompound): NbtCompound? =
|
||||||
@@ -75,7 +79,7 @@ object ItemCache : IReloadable {
|
|||||||
TypeReferences.ITEM_STACK,
|
TypeReferences.ITEM_STACK,
|
||||||
Dynamic(NbtOps.INSTANCE, nbtComponent),
|
Dynamic(NbtOps.INSTANCE, nbtComponent),
|
||||||
-1,
|
-1,
|
||||||
SharedConstants.getGameVersion().saveVersion.id
|
currentSaveVersion
|
||||||
).value as NbtCompound
|
).value as NbtCompound
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
isFlawless = false
|
isFlawless = false
|
||||||
@@ -138,24 +142,48 @@ object ItemCache : IReloadable {
|
|||||||
return base
|
return base
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun tryFindFromModernFormat(skyblockId: SkyblockId): NbtCompound? {
|
||||||
|
val overlayFile =
|
||||||
|
RepoManager.overlayData.getMostModernReadableOverlay(skyblockId, currentSaveVersion) ?: return null
|
||||||
|
val overlay = StringNbtReader.readCompound(overlayFile.path.readText())
|
||||||
|
val result = ExportedTestConstantMeta.SOURCE_CODEC.decode(
|
||||||
|
NbtOps.INSTANCE, overlay
|
||||||
|
).result().getOrNull() ?: return null
|
||||||
|
val meta = result.first
|
||||||
|
return df.update(
|
||||||
|
TypeReferences.ITEM_STACK,
|
||||||
|
Dynamic(NbtOps.INSTANCE, result.second),
|
||||||
|
meta.dataVersion,
|
||||||
|
currentSaveVersion
|
||||||
|
).value as NbtCompound
|
||||||
|
}
|
||||||
|
|
||||||
@ExpensiveItemCacheApi
|
@ExpensiveItemCacheApi
|
||||||
private fun NEUItem.asItemStackNow(): ItemStack {
|
private fun NEUItem.asItemStackNow(): ItemStack {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
var modernItemTag = tryFindFromModernFormat(this.skyblockId)
|
||||||
val oldItemTag = get10809CompoundTag()
|
val oldItemTag = get10809CompoundTag()
|
||||||
val modernItemTag = oldItemTag.transformFrom10809ToModern()
|
var usedOldNbt = false
|
||||||
?: return brokenItemStack(this)
|
if (modernItemTag == null) {
|
||||||
|
usedOldNbt = true
|
||||||
|
modernItemTag = oldItemTag.transformFrom10809ToModern()
|
||||||
|
?: return brokenItemStack(this)
|
||||||
|
}
|
||||||
val itemInstance =
|
val itemInstance =
|
||||||
ItemStack.fromNbt(MC.defaultRegistries, modernItemTag).getOrNull() ?: return brokenItemStack(this)
|
ItemStack.fromNbt(MC.defaultRegistries, modernItemTag).getOrNull() ?: return brokenItemStack(this)
|
||||||
|
if (usedOldNbt) {
|
||||||
|
val tag = oldItemTag.getCompound("tag")
|
||||||
|
val extraAttributes = tag.flatMap { it.getCompound("ExtraAttributes") }
|
||||||
|
.getOrNull()
|
||||||
|
if (extraAttributes != null)
|
||||||
|
itemInstance.set(DataComponentTypes.CUSTOM_DATA, NbtComponent.of(extraAttributes))
|
||||||
|
val itemModel = tag.flatMap { it.getString("ItemModel") }.getOrNull()
|
||||||
|
if (itemModel != null)
|
||||||
|
itemInstance.set(DataComponentTypes.ITEM_MODEL, Identifier.of(itemModel))
|
||||||
|
}
|
||||||
itemInstance.loreAccordingToNbt = lore.map { un189Lore(it) }
|
itemInstance.loreAccordingToNbt = lore.map { un189Lore(it) }
|
||||||
itemInstance.displayNameAccordingToNbt = un189Lore(displayName)
|
itemInstance.displayNameAccordingToNbt = un189Lore(displayName)
|
||||||
val tag = oldItemTag.getCompound("tag")
|
|
||||||
val extraAttributes = tag.flatMap { it.getCompound("ExtraAttributes") }
|
|
||||||
.getOrNull()
|
|
||||||
if (extraAttributes != null)
|
|
||||||
itemInstance.set(DataComponentTypes.CUSTOM_DATA, NbtComponent.of(extraAttributes))
|
|
||||||
val itemModel = tag.flatMap { it.getString("ItemModel") }.getOrNull()
|
|
||||||
if (itemModel != null)
|
|
||||||
itemInstance.set(DataComponentTypes.ITEM_MODEL, Identifier.of(itemModel))
|
|
||||||
return itemInstance
|
return itemInstance
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
|
|||||||
39
src/main/kotlin/repo/ModernOverlaysData.kt
Normal file
39
src/main/kotlin/repo/ModernOverlaysData.kt
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
package moe.nea.firmament.repo
|
||||||
|
|
||||||
|
import io.github.moulberry.repo.IReloadable
|
||||||
|
import io.github.moulberry.repo.NEURepository
|
||||||
|
import java.nio.file.Path
|
||||||
|
import kotlin.io.path.extension
|
||||||
|
import kotlin.io.path.listDirectoryEntries
|
||||||
|
import kotlin.io.path.nameWithoutExtension
|
||||||
|
import moe.nea.firmament.util.SkyblockId
|
||||||
|
|
||||||
|
// TODO: move this over to the repo parser
|
||||||
|
class ModernOverlaysData : IReloadable {
|
||||||
|
data class OverlayFile(
|
||||||
|
val version: Int,
|
||||||
|
val path: Path,
|
||||||
|
)
|
||||||
|
|
||||||
|
var overlays: Map<SkyblockId, List<OverlayFile>> = mapOf()
|
||||||
|
override fun reload(repo: NEURepository) {
|
||||||
|
val items = mutableMapOf<SkyblockId, MutableList<OverlayFile>>()
|
||||||
|
repo.baseFolder.resolve("itemsOverlay")
|
||||||
|
.listDirectoryEntries()
|
||||||
|
.forEach { versionFolder ->
|
||||||
|
val version = versionFolder.fileName.toString().toIntOrNull() ?: return@forEach
|
||||||
|
versionFolder.listDirectoryEntries()
|
||||||
|
.forEach { item ->
|
||||||
|
if (item.extension != "snbt") return@forEach
|
||||||
|
val itemId = item.nameWithoutExtension
|
||||||
|
items.getOrPut(SkyblockId(itemId)) { mutableListOf() }.add(OverlayFile(version, item))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.overlays = items
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getOverlayFiles(skyblockId: SkyblockId) = overlays[skyblockId] ?: listOf()
|
||||||
|
fun getMostModernReadableOverlay(skyblockId: SkyblockId, version: Int) = getOverlayFiles(skyblockId)
|
||||||
|
.filter { it.version <= version }
|
||||||
|
.maxByOrNull { it.version }
|
||||||
|
}
|
||||||
@@ -66,9 +66,11 @@ object RepoManager {
|
|||||||
val essenceRecipeProvider = EssenceRecipeProvider()
|
val essenceRecipeProvider = EssenceRecipeProvider()
|
||||||
val recipeCache = BetterRepoRecipeCache(essenceRecipeProvider, ReforgeStore)
|
val recipeCache = BetterRepoRecipeCache(essenceRecipeProvider, ReforgeStore)
|
||||||
val miningData = MiningRepoData()
|
val miningData = MiningRepoData()
|
||||||
|
val overlayData = ModernOverlaysData()
|
||||||
|
|
||||||
fun makeNEURepository(path: Path): NEURepository {
|
fun makeNEURepository(path: Path): NEURepository {
|
||||||
return NEURepository.of(path).apply {
|
return NEURepository.of(path).apply {
|
||||||
|
registerReloadListener(overlayData)
|
||||||
registerReloadListener(ItemCache)
|
registerReloadListener(ItemCache)
|
||||||
registerReloadListener(RepoItemTypeCache)
|
registerReloadListener(RepoItemTypeCache)
|
||||||
registerReloadListener(ExpLadders)
|
registerReloadListener(ExpLadders)
|
||||||
|
|||||||
@@ -29,12 +29,19 @@ object ErrorUtil {
|
|||||||
|
|
||||||
inline fun softError(message: String, exception: Throwable) {
|
inline fun softError(message: String, exception: Throwable) {
|
||||||
if (aggressiveErrors) throw IllegalStateException(message, exception)
|
if (aggressiveErrors) throw IllegalStateException(message, exception)
|
||||||
else Firmament.logger.error(message, exception)
|
else logError(message, exception)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun logError(message: String, exception: Throwable) {
|
||||||
|
Firmament.logger.error(message, exception)
|
||||||
|
}
|
||||||
|
fun logError(message: String) {
|
||||||
|
Firmament.logger.error(message)
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fun softError(message: String) {
|
inline fun softError(message: String) {
|
||||||
if (aggressiveErrors) error(message)
|
if (aggressiveErrors) error(message)
|
||||||
else Firmament.logger.error(message)
|
else logError(message)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <T> Result<T>.intoCatch(message: String): Catch<T> {
|
fun <T> Result<T>.intoCatch(message: String): Catch<T> {
|
||||||
|
|||||||
25
src/main/kotlin/util/mc/InitLevel.kt
Normal file
25
src/main/kotlin/util/mc/InitLevel.kt
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
package moe.nea.firmament.util.mc
|
||||||
|
|
||||||
|
enum class InitLevel {
|
||||||
|
STARTING,
|
||||||
|
MC_INIT,
|
||||||
|
RENDER_INIT,
|
||||||
|
RENDER,
|
||||||
|
MAIN_MENU,
|
||||||
|
;
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
var initLevel = InitLevel.STARTING
|
||||||
|
private set
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun isAtLeast(wantedLevel: InitLevel): Boolean = initLevel >= wantedLevel
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun bump(nextLevel: InitLevel) {
|
||||||
|
if (nextLevel.ordinal != initLevel.ordinal + 1)
|
||||||
|
error("Cannot bump initLevel $nextLevel from $initLevel")
|
||||||
|
initLevel = nextLevel
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user