From f4bf70032a45b4daa7805ca38f2d820645dc9a6b Mon Sep 17 00:00:00 2001 From: nea Date: Fri, 29 Jul 2022 20:51:53 +0200 Subject: no arch --- build.gradle.kts | 140 +++++++------ common/build.gradle.kts | 36 ---- .../moe/nea/notenoughupdates/NotEnoughUpdates.kt | 21 -- .../moe/nea/notenoughupdates/rei/NEUReiPlugin.kt | 38 ---- .../notenoughupdates/rei/SBItemEntryDefinition.kt | 98 --------- .../moe/nea/notenoughupdates/repo/ItemCache.kt | 75 ------- .../moe/nea/notenoughupdates/util/ItemUtil.kt | 23 -- .../nea/notenoughupdates/util/LegacyTagParser.kt | 232 --------------------- common/src/main/resources/architectury.common.json | 3 - .../resources/notenoughupdates-common.mixins.json | 12 -- .../main/resources/notenoughupdates.accesswidener | 1 - fabric/build.gradle.kts | 113 ---------- .../kotlin/moe/nea/notenoughupdates/FabricMain.kt | 10 - fabric/src/main/resources/fabric.mod.json | 34 --- .../main/resources/notenoughupdates.mixins.json | 12 -- gradle.properties | 4 +- settings.gradle.kts | 3 - .../moe/nea/notenoughupdates/NotEnoughUpdates.kt | 18 ++ .../moe/nea/notenoughupdates/rei/NEUReiPlugin.kt | 38 ++++ .../notenoughupdates/rei/SBItemEntryDefinition.kt | 98 +++++++++ .../moe/nea/notenoughupdates/repo/ItemCache.kt | 75 +++++++ .../notenoughupdates/repo/RepoDownloadManager.kt | 17 ++ .../moe/nea/notenoughupdates/util/ItemUtil.kt | 23 ++ .../nea/notenoughupdates/util/LegacyTagParser.kt | 232 +++++++++++++++++++++ src/main/resources/fabric.mod.json | 36 ++++ src/main/resources/notenoughupdates.accesswidener | 1 + src/main/resources/notenoughupdates.mixins.json | 12 ++ 27 files changed, 625 insertions(+), 780 deletions(-) delete mode 100644 common/build.gradle.kts delete mode 100644 common/src/main/kotlin/moe/nea/notenoughupdates/NotEnoughUpdates.kt delete mode 100644 common/src/main/kotlin/moe/nea/notenoughupdates/rei/NEUReiPlugin.kt delete mode 100644 common/src/main/kotlin/moe/nea/notenoughupdates/rei/SBItemEntryDefinition.kt delete mode 100644 common/src/main/kotlin/moe/nea/notenoughupdates/repo/ItemCache.kt delete mode 100644 common/src/main/kotlin/moe/nea/notenoughupdates/util/ItemUtil.kt delete mode 100644 common/src/main/kotlin/moe/nea/notenoughupdates/util/LegacyTagParser.kt delete mode 100644 common/src/main/resources/architectury.common.json delete mode 100644 common/src/main/resources/notenoughupdates-common.mixins.json delete mode 100644 common/src/main/resources/notenoughupdates.accesswidener delete mode 100644 fabric/build.gradle.kts delete mode 100644 fabric/src/main/kotlin/moe/nea/notenoughupdates/FabricMain.kt delete mode 100644 fabric/src/main/resources/fabric.mod.json delete mode 100644 fabric/src/main/resources/notenoughupdates.mixins.json create mode 100644 src/main/kotlin/moe/nea/notenoughupdates/NotEnoughUpdates.kt create mode 100644 src/main/kotlin/moe/nea/notenoughupdates/rei/NEUReiPlugin.kt create mode 100644 src/main/kotlin/moe/nea/notenoughupdates/rei/SBItemEntryDefinition.kt create mode 100644 src/main/kotlin/moe/nea/notenoughupdates/repo/ItemCache.kt create mode 100644 src/main/kotlin/moe/nea/notenoughupdates/repo/RepoDownloadManager.kt create mode 100644 src/main/kotlin/moe/nea/notenoughupdates/util/ItemUtil.kt create mode 100644 src/main/kotlin/moe/nea/notenoughupdates/util/LegacyTagParser.kt create mode 100644 src/main/resources/fabric.mod.json create mode 100644 src/main/resources/notenoughupdates.accesswidener create mode 100644 src/main/resources/notenoughupdates.mixins.json diff --git a/build.gradle.kts b/build.gradle.kts index 162f269..21a5cda 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,84 +1,92 @@ -import net.fabricmc.loom.api.LoomGradleExtensionAPI import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { java - `kotlin-dsl` - id("architectury-plugin") version "3.4-SNAPSHOT" - id("dev.architectury.loom") version "0.12.0.+" apply false + `maven-publish` + kotlin("jvm") version "1.7.10" + id("dev.architectury.loom") version "0.12.0.+" + id("com.github.johnrengelman.plugin-shadow") version "2.0.3" } -architectury { - minecraft = rootProject.property("minecraft_version").toString() +loom { + accessWidenerPath.set(project.file("src/main/resources/notenoughupdates.accesswidener")) + launches { + removeIf { it.name != "client" } + named("client") { + property("fabric.log.level", "info") + } + } +} + +repositories { + maven("https://maven.terraformersmc.com/releases/") + maven("https://maven.shedaniel.me") + maven("https://pkgs.dev.azure.com/djtheredstoner/DevAuth/_packaging/public/maven/v1") + maven("https://api.modrinth.com/maven") { + content { + includeGroup("maven.modrinth") + } + } + mavenLocal() } -subprojects { - apply(plugin = "dev.architectury.loom") +val shadowMe by configurations.creating { + configurations.implementation.get().extendsFrom(this) +} - val loom = project.extensions.getByName("loom") +dependencies { + // Minecraft dependencies + "minecraft"("com.mojang:minecraft:${project.property("minecraft_version")}") + "mappings"(loom.officialMojangMappings()) + // Fabric dependencies + modImplementation("net.fabricmc:fabric-loader:${project.property("fabric_loader_version")}") + modApi("net.fabricmc.fabric-api:fabric-api:${project.property("fabric_api_version")}") + modImplementation("net.fabricmc:fabric-language-kotlin:1.8.2+kotlin.1.7.10") + + // Actual dependencies + modCompileOnly("me.shedaniel:RoughlyEnoughItems-api:${rootProject.property("rei_version")}") + shadowMe("io.github.moulberry:neurepoparser:0.0.1") + + // Dev environment preinstalled mods + modRuntimeOnly("me.shedaniel:RoughlyEnoughItems-fabric:${project.property("rei_version")}") + modRuntimeOnly("me.djtheredstoner:DevAuth-fabric:${project.property("devauth_version")}") + modRuntimeOnly("maven.modrinth:modmenu:${project.property("modmenu_version")}") - dependencies { - "minecraft"("com.mojang:minecraft:${project.property("minecraft_version")}") - // The following line declares the mojmap mappings, you may use other mappings as well - "mappings"( - loom.officialMojangMappings() - ) - // The following line declares the yarn mappings you may select this one as well. - // "mappings"("net.fabricmc:yarn:1.18.2+build.3:v2") - } } -allprojects { - apply(plugin = "java") - apply(plugin = "architectury-plugin") - apply(plugin = "maven-publish") - apply(plugin = "org.jetbrains.kotlin.jvm") - - base.archivesName.set(rootProject.property("archives_base_name").toString()) - //base.archivesBaseName = rootProject.property("archives_base_name").toString() - version = rootProject.property("mod_version").toString() - group = rootProject.property("maven_group").toString() - - repositories { - // Add repositories to retrieve artifacts from in here. - // You should only use this when depending on other mods because - // Loom adds the essential maven repositories to download Minecraft and libraries from automatically. - // See https://docs.gradle.org/current/userguide/declaring_repositories.html - // for more information about repositories. - maven("https://maven.terraformersmc.com/releases/") - maven("https://maven.shedaniel.me") - maven("https://pkgs.dev.azure.com/djtheredstoner/DevAuth/_packaging/public/maven/v1") - maven("https://api.modrinth.com/maven") { - content { - includeGroup("maven.modrinth") - } - } - mavenLocal() - } - dependencies { - "compileClasspath"("org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.21") - implementation("io.github.moulberry:neurepoparser:0.0.1") - } +version = rootProject.property("mod_version").toString() +group = rootProject.property("maven_group").toString() - tasks.withType { - options.encoding = "UTF-8" - options.release.set(17) - } +tasks.withType { + options.encoding = "UTF-8" + options.release.set(17) +} - java { - withSourcesJar() - toolchain.languageVersion.set(JavaLanguageVersion.of(17)) - } +java { + withSourcesJar() + toolchain.languageVersion.set(JavaLanguageVersion.of(17)) +} - // could not set to 17, up to 16 - val compileKotlin: KotlinCompile by tasks - compileKotlin.kotlinOptions { - jvmTarget = "16" - } - val compileTestKotlin: KotlinCompile by tasks - compileTestKotlin.kotlinOptions { - jvmTarget = "16" - } +// could not set to 17, up to 16 +val compileKotlin: KotlinCompile by tasks +compileKotlin.kotlinOptions { + jvmTarget = "16" +} +val compileTestKotlin: KotlinCompile by tasks +compileTestKotlin.kotlinOptions { + jvmTarget = "16" +} + +tasks.shadowJar { + configurations = listOf(shadowMe) + archiveClassifier.set("dev-thicc") +} + +tasks.remapJar { + injectAccessWidener.set(true) + inputFile.set(tasks.shadowJar.flatMap { it.archiveFile }) + dependsOn(tasks.shadowJar) + archiveClassifier.set("thicc") } diff --git a/common/build.gradle.kts b/common/build.gradle.kts deleted file mode 100644 index 17146d0..0000000 --- a/common/build.gradle.kts +++ /dev/null @@ -1,36 +0,0 @@ -plugins { - `maven-publish` -} - -architectury { - val enabled_platforms: String by rootProject - common(enabled_platforms.split(",")) -} - -loom { - accessWidenerPath.set(file("src/main/resources/notenoughupdates.accesswidener")) -} - -dependencies { - // We depend on fabric loader here to use the fabric @Environment annotations and get the mixin dependencies - // Do NOT use other classes from fabric loader - modImplementation("net.fabricmc:fabric-loader:${rootProject.property("fabric_loader_version")}") - // Remove the next line if you don't want to depend on the API - modApi("dev.architectury:architectury:${rootProject.property("architectury_version")}") - modCompileOnly("me.shedaniel:RoughlyEnoughItems-api:${rootProject.property("rei_version")}") - implementation(kotlin("stdlib-jdk8")) -} - -publishing { - publications { - create("maven") { - artifactId = rootProject.property("archives_base_name").toString() - from(components.getByName("java")) - } - } - - // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing. - repositories { - // Add repositories to publish to here. - } -} diff --git a/common/src/main/kotlin/moe/nea/notenoughupdates/NotEnoughUpdates.kt b/common/src/main/kotlin/moe/nea/notenoughupdates/NotEnoughUpdates.kt deleted file mode 100644 index 3526bc4..0000000 --- a/common/src/main/kotlin/moe/nea/notenoughupdates/NotEnoughUpdates.kt +++ /dev/null @@ -1,21 +0,0 @@ -package moe.nea.notenoughupdates - -import dev.architectury.registry.registries.Registries -import io.github.moulberry.repo.NEURepository -import java.nio.file.Path -import java.util.logging.Logger - -object NotEnoughUpdates { - val REGISTRIES by lazy { Registries.get(MOD_ID) } - - const val MOD_ID = "notenoughupdates" - - val neuRepo = NEURepository.of(Path.of("NotEnoughUpdates-REPO")).also { - it.reload() - } - - - fun init() { - - } -} diff --git a/common/src/main/kotlin/moe/nea/notenoughupdates/rei/NEUReiPlugin.kt b/common/src/main/kotlin/moe/nea/notenoughupdates/rei/NEUReiPlugin.kt deleted file mode 100644 index cc4b0f1..0000000 --- a/common/src/main/kotlin/moe/nea/notenoughupdates/rei/NEUReiPlugin.kt +++ /dev/null @@ -1,38 +0,0 @@ -package moe.nea.notenoughupdates.rei - -import io.github.moulberry.repo.data.NEUItem -import me.shedaniel.rei.api.client.plugins.REIClientPlugin -import me.shedaniel.rei.api.client.registry.entry.EntryRegistry -import me.shedaniel.rei.api.common.entry.EntryStack -import me.shedaniel.rei.api.common.entry.type.EntryTypeRegistry -import me.shedaniel.rei.api.common.entry.type.VanillaEntryTypes -import moe.nea.notenoughupdates.NotEnoughUpdates.neuRepo -import moe.nea.notenoughupdates.repo.ItemCache.asItemStack -import net.minecraft.resources.ResourceLocation -import net.minecraft.world.item.ItemStack - - -class NEUReiPlugin : REIClientPlugin { - - companion object { - - fun EntryStack.asItemEntry(): EntryStack { - return EntryStack.of(VanillaEntryTypes.ITEM, value.asItemStack()) - } - - - val SKYBLOCK_ITEM_TYPE_ID = ResourceLocation("notenoughupdates", "skyblockitems") - } - - override fun registerEntryTypes(registry: EntryTypeRegistry) { - registry.register(SKYBLOCK_ITEM_TYPE_ID, SBItemEntryDefinition) - } - - - override fun registerEntries(registry: EntryRegistry) { - neuRepo.items.items.values.forEach { - if (!it.isVanilla) - registry.addEntry(EntryStack.of(SBItemEntryDefinition, it)) - } - } -} diff --git a/common/src/main/kotlin/moe/nea/notenoughupdates/rei/SBItemEntryDefinition.kt b/common/src/main/kotlin/moe/nea/notenoughupdates/rei/SBItemEntryDefinition.kt deleted file mode 100644 index 6726b4f..0000000 --- a/common/src/main/kotlin/moe/nea/notenoughupdates/rei/SBItemEntryDefinition.kt +++ /dev/null @@ -1,98 +0,0 @@ -package moe.nea.notenoughupdates.rei - -import com.mojang.blaze3d.vertex.PoseStack -import io.github.moulberry.repo.data.NEUItem -import me.shedaniel.math.Point -import me.shedaniel.math.Rectangle -import me.shedaniel.rei.api.client.entry.renderer.EntryRenderer -import me.shedaniel.rei.api.client.gui.widgets.Tooltip -import me.shedaniel.rei.api.client.gui.widgets.TooltipContext -import me.shedaniel.rei.api.common.entry.EntrySerializer -import me.shedaniel.rei.api.common.entry.EntryStack -import me.shedaniel.rei.api.common.entry.comparison.ComparisonContext -import me.shedaniel.rei.api.common.entry.type.EntryDefinition -import me.shedaniel.rei.api.common.entry.type.EntryType -import me.shedaniel.rei.api.common.entry.type.VanillaEntryTypes -import moe.nea.notenoughupdates.rei.NEUReiPlugin.Companion.asItemEntry -import moe.nea.notenoughupdates.repo.ItemCache.asItemStack -import moe.nea.notenoughupdates.repo.ItemCache.getResourceLocation -import net.minecraft.network.chat.Component -import net.minecraft.resources.ResourceLocation -import net.minecraft.tags.TagKey -import net.minecraft.world.item.ItemStack -import java.util.stream.Stream - -object SBItemEntryDefinition : EntryDefinition { - override fun equals(o1: NEUItem?, o2: NEUItem?, context: ComparisonContext?): Boolean { - return o1 == o2 - } - - override fun cheatsAs(entry: EntryStack?, value: NEUItem?): ItemStack? { - return value?.asItemStack() - } - - override fun getValueType(): Class = NEUItem::class.java - override fun getType(): EntryType = - EntryType.deferred(NEUReiPlugin.SKYBLOCK_ITEM_TYPE_ID) - - override fun getRenderer(): EntryRenderer = object : EntryRenderer { - override fun render( - entry: EntryStack, - matrices: PoseStack, - bounds: Rectangle, - mouseX: Int, - mouseY: Int, - delta: Float - ) { - VanillaEntryTypes.ITEM.definition.renderer - .render( - entry.asItemEntry(), - matrices, bounds, mouseX, mouseY, delta - ) - } - - override fun getTooltip(entry: EntryStack, tooltipContext: TooltipContext): Tooltip? { - return VanillaEntryTypes.ITEM.definition.renderer - .getTooltip(entry.asItemEntry(), tooltipContext) - } - - } - - override fun getSerializer(): EntrySerializer? { - return null - } - - override fun getTagsFor(entry: EntryStack?, value: NEUItem?): Stream> { - return Stream.empty() - } - - override fun asFormattedText(entry: EntryStack, value: NEUItem): Component { - return VanillaEntryTypes.ITEM.definition.asFormattedText(entry.asItemEntry(), value.asItemStack()) - } - - override fun hash(entry: EntryStack, value: NEUItem, context: ComparisonContext): Long { - return value.skyblockItemId.hashCode().toLong() - } - - override fun wildcard(entry: EntryStack, value: NEUItem): NEUItem { - return value - } - - override fun normalize(entry: EntryStack, value: NEUItem): NEUItem { - return value - } - - override fun copy(entry: EntryStack?, value: NEUItem): NEUItem { - return value - } - - override fun isEmpty(entry: EntryStack?, value: NEUItem?): Boolean { - return false - } - - override fun getIdentifier(entry: EntryStack?, value: NEUItem): ResourceLocation { - return value.getResourceLocation() - } - - -} diff --git a/common/src/main/kotlin/moe/nea/notenoughupdates/repo/ItemCache.kt b/common/src/main/kotlin/moe/nea/notenoughupdates/repo/ItemCache.kt deleted file mode 100644 index aa93fec..0000000 --- a/common/src/main/kotlin/moe/nea/notenoughupdates/repo/ItemCache.kt +++ /dev/null @@ -1,75 +0,0 @@ -package moe.nea.notenoughupdates.repo - -import com.mojang.serialization.Dynamic -import io.github.moulberry.repo.IReloadable -import io.github.moulberry.repo.NEURepository -import io.github.moulberry.repo.data.NEUItem -import moe.nea.notenoughupdates.util.LegacyTagParser -import moe.nea.notenoughupdates.util.appendLore -import net.minecraft.nbt.CompoundTag -import net.minecraft.nbt.NbtOps -import net.minecraft.network.chat.Component -import net.minecraft.resources.ResourceLocation -import net.minecraft.util.datafix.DataFixers -import net.minecraft.util.datafix.fixes.References -import net.minecraft.world.item.ItemStack -import net.minecraft.world.item.Items -import java.util.concurrent.ConcurrentHashMap - -object ItemCache : IReloadable { - val cache: MutableMap = ConcurrentHashMap() - val df = DataFixers.getDataFixer() - var isFlawless = true - - private fun NEUItem.get10809CompoundTag(): CompoundTag = CompoundTag().apply { - put("tag", LegacyTagParser.parse(nbttag)) - putString("id", minecraftItemId) - putByte("Count", 1) - putShort("Damage", damage.toShort()) - } - - private fun CompoundTag.transformFrom10809ToModern(): CompoundTag? = - try { - df.update( - References.ITEM_STACK, - Dynamic(NbtOps.INSTANCE, this), - -1, - 2975 - ).value as CompoundTag - } catch (e: Exception) { - e.printStackTrace() - isFlawless = false - null - } - - private fun NEUItem.asItemStackNow(): ItemStack { - val oldItemTag = get10809CompoundTag() - val modernItemTag = oldItemTag.transformFrom10809ToModern() - ?: return ItemStack(Items.PAINTING).apply { - setHoverName(Component.literal(this@asItemStackNow.displayName)) - appendLore(listOf(Component.literal("Exception rendering item: $skyblockItemId"))) - } - val itemInstance = ItemStack.of(modernItemTag) - if (itemInstance.tag?.contains("Enchantments") == true) { - itemInstance.enchantmentTags.add(CompoundTag()) - } - return itemInstance - } - - fun NEUItem.asItemStack(): ItemStack { - var s = cache[this.skyblockItemId] - if (s == null) { - s = asItemStackNow() - cache[this.skyblockItemId] = s - } - return s - } - - fun NEUItem.getResourceLocation() = - ResourceLocation("skyblockitem", skyblockItemId.lowercase().replace(";", "__")) - - - override fun reload(repository: NEURepository) { - cache.clear() - } -} diff --git a/common/src/main/kotlin/moe/nea/notenoughupdates/util/ItemUtil.kt b/common/src/main/kotlin/moe/nea/notenoughupdates/util/ItemUtil.kt deleted file mode 100644 index d5b8881..0000000 --- a/common/src/main/kotlin/moe/nea/notenoughupdates/util/ItemUtil.kt +++ /dev/null @@ -1,23 +0,0 @@ -package moe.nea.notenoughupdates.util - -import net.minecraft.nbt.CompoundTag -import net.minecraft.nbt.ListTag -import net.minecraft.nbt.StringTag -import net.minecraft.network.chat.Component -import net.minecraft.world.item.ItemStack - -fun ItemStack.appendLore(args: List) { - val compoundTag = getOrCreateTagElement("display") - val loreList = compoundTag.getOrCreateList("Lore", StringTag.TAG_STRING) - for (arg in args) { - loreList.add(StringTag.valueOf(Component.Serializer.toJson(arg))) - } -} - -fun CompoundTag.getOrCreateList(label: String, tag: Byte): ListTag = getList(label, tag.toInt()).also { - put(label, it) -} - -fun CompoundTag.getOrCreateCompoundTag(label: String): CompoundTag = getCompound(label).also { - put(label, it) -} diff --git a/common/src/main/kotlin/moe/nea/notenoughupdates/util/LegacyTagParser.kt b/common/src/main/kotlin/moe/nea/notenoughupdates/util/LegacyTagParser.kt deleted file mode 100644 index a4ec7e1..0000000 --- a/common/src/main/kotlin/moe/nea/notenoughupdates/util/LegacyTagParser.kt +++ /dev/null @@ -1,232 +0,0 @@ -package moe.nea.notenoughupdates.util - -import net.minecraft.nbt.* -import java.util.* - -class LegacyTagParser private constructor(string: String) { - data class TagParsingException(val baseString: String, val offset: Int, val mes0: String) : - Exception("$mes0 at $offset in `$baseString`.") - - class StringRacer(val backing: String) { - var idx = 0 - val stack = Stack() - - fun pushState() { - stack.push(idx) - } - - fun popState() { - idx = stack.pop() - } - - fun discardState() { - stack.pop() - } - - fun peek(count: Int): String { - return backing.substring(minOf(idx, backing.length), minOf(idx + count, backing.length)) - } - - fun finished(): Boolean { - return peek(1).isEmpty() - } - - fun peekReq(count: Int): String? { - val p = peek(count) - if (p.length != count) - return null - return p - } - - fun consumeCountReq(count: Int): String? { - val p = peekReq(count) - if (p != null) - idx += count - return p - } - - fun tryConsume(string: String): Boolean { - val p = peek(string.length) - if (p != string) - return false - idx += p.length - return true - } - - fun consumeWhile(shouldConsumeThisString: (String) -> Boolean): String { - var lastString: String = "" - while (true) { - val nextString = lastString + peek(1) - if (!shouldConsumeThisString(nextString)) { - return lastString - } - idx++ - lastString = nextString - } - } - - fun expect(search: String, errorMessage: String) { - if (!tryConsume(search)) - error(errorMessage) - } - - fun error(errorMessage: String): Nothing { - throw TagParsingException(backing, idx, errorMessage) - } - - } - - val racer = StringRacer(string) - val baseTag = parseTag() - - companion object { - val digitRange = '0'..'9' - fun parse(string: String): CompoundTag { - return LegacyTagParser(string).baseTag - } - } - - fun skipWhitespace() { - racer.consumeWhile { Character.isWhitespace(it.last()) } // Only check last since other chars are always checked before. - } - - fun parseTag(): CompoundTag { - skipWhitespace() - racer.expect("{", "Expected '{’ at start of tag") - skipWhitespace() - val tag = CompoundTag() - while (!racer.tryConsume("}")) { - skipWhitespace() - val lhs = parseIdentifier() - skipWhitespace() - racer.expect(":", "Expected ':' after identifier in tag") - skipWhitespace() - val rhs = parseAny() - tag.put(lhs, rhs) - racer.tryConsume(",") - skipWhitespace() - } - return tag - } - - private fun parseAny(): Tag { - skipWhitespace() - val nextChar = racer.peekReq(1) ?: racer.error("Expected new object, found EOF") - return when { - nextChar == "{" -> parseTag() - nextChar == "[" -> parseList() - nextChar == "\"" -> parseStringTag() - nextChar.first() in (digitRange) -> parseNumericTag() - else -> racer.error("Unexpected token found. Expected start of new element") - } - } - - fun parseList(): ListTag { - skipWhitespace() - racer.expect("[", "Expected '[' at start of tag") - skipWhitespace() - val list = ListTag() - while (!racer.tryConsume("]")) { - skipWhitespace() - racer.pushState() - val lhs = racer.consumeWhile { it.all { it in digitRange } } - skipWhitespace() - if (!racer.tryConsume(":") || lhs.isEmpty()) { // No prefixed 0: - racer.popState() - list.add(parseAny()) // Reparse our number (or not a number) as actual tag - } else { - racer.discardState() - skipWhitespace() - list.add(parseAny()) // Ignore prefix indexes. They should not be generated out of order by any vanilla implementation (which is what NEU should export). Instead append where it appears in order. - } - skipWhitespace() - racer.tryConsume(",") - } - return list - } - - fun parseQuotedString(): String { - skipWhitespace() - racer.expect("\"", "Expected '\"' at string start") - val sb = StringBuilder() - while (true) { - when (val peek = racer.consumeCountReq(1)) { - "\"" -> break - "\\" -> { - val escaped = racer.consumeCountReq(1) ?: racer.error("Unfinished backslash escape") - if (escaped != "\"" && escaped != "\\") { - // Surprisingly i couldn't find unicode escapes to be generated by the original minecraft 1.8.9 implementation - racer.idx-- - racer.error("Invalid backslash escape '$escaped'") - } - sb.append(escaped) - } - null -> racer.error("Unfinished string") - else -> { - sb.append(peek) - } - } - } - return sb.toString() - } - - fun parseStringTag(): StringTag { - return StringTag.valueOf(parseQuotedString()) - } - - object Patterns { - val DOUBLE = "([-+]?[0-9]*\\.?[0-9]+)[d|D]".toRegex() - val FLOAT = "([-+]?[0-9]*\\.?[0-9]+)[f|F]".toRegex() - val BYTE = "([-+]?[0-9]+)[b|B]".toRegex() - val LONG = "([-+]?[0-9]+)[l|L]".toRegex() - val SHORT = "([-+]?[0-9]+)[s|S]".toRegex() - val INTEGER = "([-+]?[0-9]+)".toRegex() - val DOUBLE_UNTYPED = "([-+]?[0-9]*\\.?[0-9]+)".toRegex() - val ROUGH_PATTERN = "[-+]?[0-9]*\\.?[0-9]+[dDbBfFlLsS]?".toRegex() - } - - fun parseNumericTag(): NumericTag { - skipWhitespace() - val textForm = racer.consumeWhile { Patterns.ROUGH_PATTERN.matchEntire(it) != null } - if (textForm.isEmpty()) { - racer.error("Expected numeric tag (starting with either -, +, . or a digit") - } - val doubleMatch = Patterns.DOUBLE.matchEntire(textForm) ?: Patterns.DOUBLE_UNTYPED.matchEntire(textForm) - if (doubleMatch != null) { - return DoubleTag.valueOf(doubleMatch.groups[1]!!.value.toDouble()) - } - val floatMatch = Patterns.FLOAT.matchEntire(textForm) - if (floatMatch != null) { - return FloatTag.valueOf(floatMatch.groups[1]!!.value.toFloat()) - } - val byteMatch = Patterns.BYTE.matchEntire(textForm) - if (byteMatch != null) { - return ByteTag.valueOf(byteMatch.groups[1]!!.value.toByte()) - } - val longMatch = Patterns.LONG.matchEntire(textForm) - if (longMatch != null) { - return LongTag.valueOf(longMatch.groups[1]!!.value.toLong()) - } - val shortMatch = Patterns.SHORT.matchEntire(textForm) - if (shortMatch != null) { - return ShortTag.valueOf(shortMatch.groups[1]!!.value.toShort()) - } - val integerMatch = Patterns.INTEGER.matchEntire(textForm) - if (integerMatch != null) { - return IntTag.valueOf(integerMatch.groups[1]!!.value.toInt()) - } - throw IllegalStateException("Could not properly parse numeric tag '$textForm', despite passing rough verification. This is a bug in the LegacyTagParser") - } - - private fun parseIdentifier(): String { - skipWhitespace() - if (racer.peek(1) == "\"") { - return parseQuotedString() - } - return racer.consumeWhile { - val x = it.last() - x != ':' && !Character.isWhitespace(x) - } - } - -} diff --git a/common/src/main/resources/architectury.common.json b/common/src/main/resources/architectury.common.json deleted file mode 100644 index 017e6cd..0000000 --- a/common/src/main/resources/architectury.common.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "accessWidener": "notenoughupdates.accesswidener" -} diff --git a/common/src/main/resources/notenoughupdates-common.mixins.json b/common/src/main/resources/notenoughupdates-common.mixins.json deleted file mode 100644 index e83444e..0000000 --- a/common/src/main/resources/notenoughupdates-common.mixins.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "required": true, - "package": "net.examplemod.mixin", - "compatibilityLevel": "JAVA_16", - "client": [ - ], - "mixins": [ - ], - "injectors": { - "defaultRequire": 1 - } -} diff --git a/common/src/main/resources/notenoughupdates.accesswidener b/common/src/main/resources/notenoughupdates.accesswidener deleted file mode 100644 index 236e6b1..0000000 --- a/common/src/main/resources/notenoughupdates.accesswidener +++ /dev/null @@ -1 +0,0 @@ -accessWidener v2 named diff --git a/fabric/build.gradle.kts b/fabric/build.gradle.kts deleted file mode 100644 index 1e39832..0000000 --- a/fabric/build.gradle.kts +++ /dev/null @@ -1,113 +0,0 @@ -plugins { - id("com.github.johnrengelman.shadow") version "7.1.2" -} - -architectury { - platformSetupLoomIde() - fabric() -} - -loom { - accessWidenerPath.set(project(":common").loom.accessWidenerPath) - launches { - named("client") { - property("fabric.log.level", "info") - } - } -} - -/** - * @see: https://docs.gradle.org/current/userguide/migrating_from_groovy_to_kotlin_dsl.html - * */ -val common: Configuration by configurations.creating -val shadowCommon: Configuration by configurations.creating // Don't use shadow from the shadow plugin because we don't want IDEA to index this. -val developmentFabric: Configuration = configurations.getByName("developmentFabric") -configurations { - compileClasspath.get().extendsFrom(configurations["common"]) - runtimeClasspath.get().extendsFrom(configurations["common"]) - developmentFabric.extendsFrom(configurations["common"]) -} - -dependencies { - modImplementation("net.fabricmc:fabric-loader:${rootProject.property("fabric_loader_version")}") - modApi("net.fabricmc.fabric-api:fabric-api:${rootProject.property("fabric_api_version")}") - // Remove the next line if you don't want to depend on the API - modApi("dev.architectury:architectury-fabric:${rootProject.property("architectury_version")}") - - common(project(":common", configuration = "namedElements")) { isTransitive = false } - shadowCommon(project(":common", configuration = "transformProductionFabric")) { isTransitive = false } - common(kotlin("stdlib-jdk8")) - modRuntimeOnly("me.shedaniel:RoughlyEnoughItems-fabric:${rootProject.property("rei_version")}") - modRuntimeOnly("me.djtheredstoner:DevAuth-fabric:${rootProject.property("devauth_version")}") - modRuntimeOnly("maven.modrinth:modmenu:${rootProject.property("modmenu_version")}") -} - -val javaComponent = components.getByName("java", AdhocComponentWithVariants::class) -javaComponent.withVariantsFromConfiguration(configurations["sourcesElements"]) { - skip() -} - -tasks { - processResources { - inputs.property("version", project.version) - - filesMatching("fabric.mod.json") { - expand("version" to project.version) - } - } - - shadowJar { - exclude("architectury.common.json") - /** - * magic! - * groovy -> kotlin dsl - * [project.configurations.shadowCommon] -> listOf(project.configurations["shadowCommon"]) - * */ - configurations = listOf(project.configurations["shadowCommon"]) - archiveClassifier.set("dev-shadow") - } - - remapJar { - injectAccessWidener.set(true) - /** - * magic! - * groovy -> kotlin dsl - * shadowJar.archiveFile -> shadowJar.flatMap { it.archiveFile } - * */ - inputFile.set(shadowJar.flatMap { it.archiveFile }) - dependsOn(shadowJar) - /** - * affect suffix of build jar name - * if { archiveClassifier.set("fabric") } - * name will be examplemod-1.0.0-fabric.jar - */ - archiveClassifier.set("fabric") - } - - jar { - archiveClassifier.set("dev") - } - - sourcesJar { - val commonSources = project(":common").tasks.getByName("sourcesJar", Jar::class) - dependsOn(commonSources) - from(commonSources.archiveFile.map { zipTree(it) }) - } - - - - publishing { - publications { - create("mavenFabric") { - artifactId = "${rootProject.property("archives_base_name")}-${project.name}" - from(javaComponent) - } - } - - // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing. - repositories { - // Add repositories to publish to here. - } - } -} - diff --git a/fabric/src/main/kotlin/moe/nea/notenoughupdates/FabricMain.kt b/fabric/src/main/kotlin/moe/nea/notenoughupdates/FabricMain.kt deleted file mode 100644 index 918100b..0000000 --- a/fabric/src/main/kotlin/moe/nea/notenoughupdates/FabricMain.kt +++ /dev/null @@ -1,10 +0,0 @@ -package moe.nea.notenoughupdates - -import moe.nea.notenoughupdates.NotEnoughUpdates.init -import net.fabricmc.api.ModInitializer - -class FabricMain : ModInitializer { - override fun onInitialize() { - init() - } -} diff --git a/fabric/src/main/resources/fabric.mod.json b/fabric/src/main/resources/fabric.mod.json deleted file mode 100644 index 3ff8349..0000000 --- a/fabric/src/main/resources/fabric.mod.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "schemaVersion": 1, - "id": "notenoughupdates", - "version": "${version}", - "name": "Not Enough Updates", - "description": "Not Enough Updates - A mod for Hypixel Skyblock", - "authors": [ - "nea89" - ], - "contact": { - "homepage": "https://github.com/romangraef/TODO", - "sources": "https://github.com/romangraef/TODO" - }, - "license": "LGPL-3.0", - "icon": "assets/notenoughupdates/icon.png", - "environment": "client", - "entrypoints": { - "main": [ - "moe.nea.notenoughupdates.FabricMain" - ], - "rei": [ - "moe.nea.notenoughupdates.rei.NEUReiPlugin" - ] - }, - "mixins": [ - "notenoughupdates.mixins.json", - "notenoughupdates-common.mixins.json" - ], - "depends": { - "fabric": "*", - "minecraft": ">=1.18.2", - "architectury": ">=4.2.50" - } -} diff --git a/fabric/src/main/resources/notenoughupdates.mixins.json b/fabric/src/main/resources/notenoughupdates.mixins.json deleted file mode 100644 index ab40cb1..0000000 --- a/fabric/src/main/resources/notenoughupdates.mixins.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "required": true, - "package": "net.examplemod.mixin.fabric", - "compatibilityLevel": "JAVA_16", - "client": [ - ], - "mixins": [ - ], - "injectors": { - "defaultRequire": 1 - } -} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 73d85fc..8473b3f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,7 @@ org.gradle.jvmargs=-Xmx4096M minecraft_version=1.19 -enabled_platforms=fabric +loom.platform=fabric archives_base_name=notenoughupdates mod_version=1.0.0 @@ -12,8 +12,6 @@ architectury_version=5.10.33 fabric_loader_version=0.14.8 fabric_api_version=0.58.0+1.19 -kotlin_version=1.7.0-RC - rei_version=9.1.518 devauth_version=1.0.0 modmenu_version=4.0.4 diff --git a/settings.gradle.kts b/settings.gradle.kts index ca29fa8..e2fd19e 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -16,8 +16,5 @@ pluginManagement { } } -include("common") -include("fabric") - rootProject.name = "NotEnoughApdates" diff --git a/src/main/kotlin/moe/nea/notenoughupdates/NotEnoughUpdates.kt b/src/main/kotlin/moe/nea/notenoughupdates/NotEnoughUpdates.kt new file mode 100644 index 0000000..79b8819 --- /dev/null +++ b/src/main/kotlin/moe/nea/notenoughupdates/NotEnoughUpdates.kt @@ -0,0 +1,18 @@ +package moe.nea.notenoughupdates + +import io.github.moulberry.repo.NEURepository +import net.fabricmc.api.ModInitializer +import java.nio.file.Path + +object NotEnoughUpdates : ModInitializer { + val DATA_DIR = Path.of(".notenoughupdates") + + const val MOD_ID = "notenoughupdates" + + val neuRepo = NEURepository.of(Path.of("NotEnoughUpdates-REPO")).also { + it.reload() + } + + override fun onInitialize() { + } +} diff --git a/src/main/kotlin/moe/nea/notenoughupdates/rei/NEUReiPlugin.kt b/src/main/kotlin/moe/nea/notenoughupdates/rei/NEUReiPlugin.kt new file mode 100644 index 0000000..cc4b0f1 --- /dev/null +++ b/src/main/kotlin/moe/nea/notenoughupdates/rei/NEUReiPlugin.kt @@ -0,0 +1,38 @@ +package moe.nea.notenoughupdates.rei + +import io.github.moulberry.repo.data.NEUItem +import me.shedaniel.rei.api.client.plugins.REIClientPlugin +import me.shedaniel.rei.api.client.registry.entry.EntryRegistry +import me.shedaniel.rei.api.common.entry.EntryStack +import me.shedaniel.rei.api.common.entry.type.EntryTypeRegistry +import me.shedaniel.rei.api.common.entry.type.VanillaEntryTypes +import moe.nea.notenoughupdates.NotEnoughUpdates.neuRepo +import moe.nea.notenoughupdates.repo.ItemCache.asItemStack +import net.minecraft.resources.ResourceLocation +import net.minecraft.world.item.ItemStack + + +class NEUReiPlugin : REIClientPlugin { + + companion object { + + fun EntryStack.asItemEntry(): EntryStack { + return EntryStack.of(VanillaEntryTypes.ITEM, value.asItemStack()) + } + + + val SKYBLOCK_ITEM_TYPE_ID = ResourceLocation("notenoughupdates", "skyblockitems") + } + + override fun registerEntryTypes(registry: EntryTypeRegistry) { + registry.register(SKYBLOCK_ITEM_TYPE_ID, SBItemEntryDefinition) + } + + + override fun registerEntries(registry: EntryRegistry) { + neuRepo.items.items.values.forEach { + if (!it.isVanilla) + registry.addEntry(EntryStack.of(SBItemEntryDefinition, it)) + } + } +} diff --git a/src/main/kotlin/moe/nea/notenoughupdates/rei/SBItemEntryDefinition.kt b/src/main/kotlin/moe/nea/notenoughupdates/rei/SBItemEntryDefinition.kt new file mode 100644 index 0000000..6726b4f --- /dev/null +++ b/src/main/kotlin/moe/nea/notenoughupdates/rei/SBItemEntryDefinition.kt @@ -0,0 +1,98 @@ +package moe.nea.notenoughupdates.rei + +import com.mojang.blaze3d.vertex.PoseStack +import io.github.moulberry.repo.data.NEUItem +import me.shedaniel.math.Point +import me.shedaniel.math.Rectangle +import me.shedaniel.rei.api.client.entry.renderer.EntryRenderer +import me.shedaniel.rei.api.client.gui.widgets.Tooltip +import me.shedaniel.rei.api.client.gui.widgets.TooltipContext +import me.shedaniel.rei.api.common.entry.EntrySerializer +import me.shedaniel.rei.api.common.entry.EntryStack +import me.shedaniel.rei.api.common.entry.comparison.ComparisonContext +import me.shedaniel.rei.api.common.entry.type.EntryDefinition +import me.shedaniel.rei.api.common.entry.type.EntryType +import me.shedaniel.rei.api.common.entry.type.VanillaEntryTypes +import moe.nea.notenoughupdates.rei.NEUReiPlugin.Companion.asItemEntry +import moe.nea.notenoughupdates.repo.ItemCache.asItemStack +import moe.nea.notenoughupdates.repo.ItemCache.getResourceLocation +import net.minecraft.network.chat.Component +import net.minecraft.resources.ResourceLocation +import net.minecraft.tags.TagKey +import net.minecraft.world.item.ItemStack +import java.util.stream.Stream + +object SBItemEntryDefinition : EntryDefinition { + override fun equals(o1: NEUItem?, o2: NEUItem?, context: ComparisonContext?): Boolean { + return o1 == o2 + } + + override fun cheatsAs(entry: EntryStack?, value: NEUItem?): ItemStack? { + return value?.asItemStack() + } + + override fun getValueType(): Class = NEUItem::class.java + override fun getType(): EntryType = + EntryType.deferred(NEUReiPlugin.SKYBLOCK_ITEM_TYPE_ID) + + override fun getRenderer(): EntryRenderer = object : EntryRenderer { + override fun render( + entry: EntryStack, + matrices: PoseStack, + bounds: Rectangle, + mouseX: Int, + mouseY: Int, + delta: Float + ) { + VanillaEntryTypes.ITEM.definition.renderer + .render( + entry.asItemEntry(), + matrices, bounds, mouseX, mouseY, delta + ) + } + + override fun getTooltip(entry: EntryStack, tooltipContext: TooltipContext): Tooltip? { + return VanillaEntryTypes.ITEM.definition.renderer + .getTooltip(entry.asItemEntry(), tooltipContext) + } + + } + + override fun getSerializer(): EntrySerializer? { + return null + } + + override fun getTagsFor(entry: EntryStack?, value: NEUItem?): Stream> { + return Stream.empty() + } + + override fun asFormattedText(entry: EntryStack, value: NEUItem): Component { + return VanillaEntryTypes.ITEM.definition.asFormattedText(entry.asItemEntry(), value.asItemStack()) + } + + override fun hash(entry: EntryStack, value: NEUItem, context: ComparisonContext): Long { + return value.skyblockItemId.hashCode().toLong() + } + + override fun wildcard(entry: EntryStack, value: NEUItem): NEUItem { + return value + } + + override fun normalize(entry: EntryStack, value: NEUItem): NEUItem { + return value + } + + override fun copy(entry: EntryStack?, value: NEUItem): NEUItem { + return value + } + + override fun isEmpty(entry: EntryStack?, value: NEUItem?): Boolean { + return false + } + + override fun getIdentifier(entry: EntryStack?, value: NEUItem): ResourceLocation { + return value.getResourceLocation() + } + + +} diff --git a/src/main/kotlin/moe/nea/notenoughupdates/repo/ItemCache.kt b/src/main/kotlin/moe/nea/notenoughupdates/repo/ItemCache.kt new file mode 100644 index 0000000..aa93fec --- /dev/null +++ b/src/main/kotlin/moe/nea/notenoughupdates/repo/ItemCache.kt @@ -0,0 +1,75 @@ +package moe.nea.notenoughupdates.repo + +import com.mojang.serialization.Dynamic +import io.github.moulberry.repo.IReloadable +import io.github.moulberry.repo.NEURepository +import io.github.moulberry.repo.data.NEUItem +import moe.nea.notenoughupdates.util.LegacyTagParser +import moe.nea.notenoughupdates.util.appendLore +import net.minecraft.nbt.CompoundTag +import net.minecraft.nbt.NbtOps +import net.minecraft.network.chat.Component +import net.minecraft.resources.ResourceLocation +import net.minecraft.util.datafix.DataFixers +import net.minecraft.util.datafix.fixes.References +import net.minecraft.world.item.ItemStack +import net.minecraft.world.item.Items +import java.util.concurrent.ConcurrentHashMap + +object ItemCache : IReloadable { + val cache: MutableMap = ConcurrentHashMap() + val df = DataFixers.getDataFixer() + var isFlawless = true + + private fun NEUItem.get10809CompoundTag(): CompoundTag = CompoundTag().apply { + put("tag", LegacyTagParser.parse(nbttag)) + putString("id", minecraftItemId) + putByte("Count", 1) + putShort("Damage", damage.toShort()) + } + + private fun CompoundTag.transformFrom10809ToModern(): CompoundTag? = + try { + df.update( + References.ITEM_STACK, + Dynamic(NbtOps.INSTANCE, this), + -1, + 2975 + ).value as CompoundTag + } catch (e: Exception) { + e.printStackTrace() + isFlawless = false + null + } + + private fun NEUItem.asItemStackNow(): ItemStack { + val oldItemTag = get10809CompoundTag() + val modernItemTag = oldItemTag.transformFrom10809ToModern() + ?: return ItemStack(Items.PAINTING).apply { + setHoverName(Component.literal(this@asItemStackNow.displayName)) + appendLore(listOf(Component.literal("Exception rendering item: $skyblockItemId"))) + } + val itemInstance = ItemStack.of(modernItemTag) + if (itemInstance.tag?.contains("Enchantments") == true) { + itemInstance.enchantmentTags.add(CompoundTag()) + } + return itemInstance + } + + fun NEUItem.asItemStack(): ItemStack { + var s = cache[this.skyblockItemId] + if (s == null) { + s = asItemStackNow() + cache[this.skyblockItemId] = s + } + return s + } + + fun NEUItem.getResourceLocation() = + ResourceLocation("skyblockitem", skyblockItemId.lowercase().replace(";", "__")) + + + override fun reload(repository: NEURepository) { + cache.clear() + } +} diff --git a/src/main/kotlin/moe/nea/notenoughupdates/repo/RepoDownloadManager.kt b/src/main/kotlin/moe/nea/notenoughupdates/repo/RepoDownloadManager.kt new file mode 100644 index 0000000..47b2878 --- /dev/null +++ b/src/main/kotlin/moe/nea/notenoughupdates/repo/RepoDownloadManager.kt @@ -0,0 +1,17 @@ +package moe.nea.notenoughupdates.repo + +import moe.nea.notenoughupdates.NotEnoughUpdates + +object RepoDownloadManager { + + val repoSavedLocation = NotEnoughUpdates.DATA_DIR.resolve("repo-extracted") + val repoMetadataLocation = NotEnoughUpdates.DATA_DIR.resolve("loaded-repo.json") + + data class RepoMetadata( + var latestCommit: String, + var user: String, + var repository: String, + var branch: String, + ) + +} diff --git a/src/main/kotlin/moe/nea/notenoughupdates/util/ItemUtil.kt b/src/main/kotlin/moe/nea/notenoughupdates/util/ItemUtil.kt new file mode 100644 index 0000000..d5b8881 --- /dev/null +++ b/src/main/kotlin/moe/nea/notenoughupdates/util/ItemUtil.kt @@ -0,0 +1,23 @@ +package moe.nea.notenoughupdates.util + +import net.minecraft.nbt.CompoundTag +import net.minecraft.nbt.ListTag +import net.minecraft.nbt.StringTag +import net.minecraft.network.chat.Component +import net.minecraft.world.item.ItemStack + +fun ItemStack.appendLore(args: List) { + val compoundTag = getOrCreateTagElement("display") + val loreList = compoundTag.getOrCreateList("Lore", StringTag.TAG_STRING) + for (arg in args) { + loreList.add(StringTag.valueOf(Component.Serializer.toJson(arg))) + } +} + +fun CompoundTag.getOrCreateList(label: String, tag: Byte): ListTag = getList(label, tag.toInt()).also { + put(label, it) +} + +fun CompoundTag.getOrCreateCompoundTag(label: String): CompoundTag = getCompound(label).also { + put(label, it) +} diff --git a/src/main/kotlin/moe/nea/notenoughupdates/util/LegacyTagParser.kt b/src/main/kotlin/moe/nea/notenoughupdates/util/LegacyTagParser.kt new file mode 100644 index 0000000..a4ec7e1 --- /dev/null +++ b/src/main/kotlin/moe/nea/notenoughupdates/util/LegacyTagParser.kt @@ -0,0 +1,232 @@ +package moe.nea.notenoughupdates.util + +import net.minecraft.nbt.* +import java.util.* + +class LegacyTagParser private constructor(string: String) { + data class TagParsingException(val baseString: String, val offset: Int, val mes0: String) : + Exception("$mes0 at $offset in `$baseString`.") + + class StringRacer(val backing: String) { + var idx = 0 + val stack = Stack() + + fun pushState() { + stack.push(idx) + } + + fun popState() { + idx = stack.pop() + } + + fun discardState() { + stack.pop() + } + + fun peek(count: Int): String { + return backing.substring(minOf(idx, backing.length), minOf(idx + count, backing.length)) + } + + fun finished(): Boolean { + return peek(1).isEmpty() + } + + fun peekReq(count: Int): String? { + val p = peek(count) + if (p.length != count) + return null + return p + } + + fun consumeCountReq(count: Int): String? { + val p = peekReq(count) + if (p != null) + idx += count + return p + } + + fun tryConsume(string: String): Boolean { + val p = peek(string.length) + if (p != string) + return false + idx += p.length + return true + } + + fun consumeWhile(shouldConsumeThisString: (String) -> Boolean): String { + var lastString: String = "" + while (true) { + val nextString = lastString + peek(1) + if (!shouldConsumeThisString(nextString)) { + return lastString + } + idx++ + lastString = nextString + } + } + + fun expect(search: String, errorMessage: String) { + if (!tryConsume(search)) + error(errorMessage) + } + + fun error(errorMessage: String): Nothing { + throw TagParsingException(backing, idx, errorMessage) + } + + } + + val racer = StringRacer(string) + val baseTag = parseTag() + + companion object { + val digitRange = '0'..'9' + fun parse(string: String): CompoundTag { + return LegacyTagParser(string).baseTag + } + } + + fun skipWhitespace() { + racer.consumeWhile { Character.isWhitespace(it.last()) } // Only check last since other chars are always checked before. + } + + fun parseTag(): CompoundTag { + skipWhitespace() + racer.expect("{", "Expected '{’ at start of tag") + skipWhitespace() + val tag = CompoundTag() + while (!racer.tryConsume("}")) { + skipWhitespace() + val lhs = parseIdentifier() + skipWhitespace() + racer.expect(":", "Expected ':' after identifier in tag") + skipWhitespace() + val rhs = parseAny() + tag.put(lhs, rhs) + racer.tryConsume(",") + skipWhitespace() + } + return tag + } + + private fun parseAny(): Tag { + skipWhitespace() + val nextChar = racer.peekReq(1) ?: racer.error("Expected new object, found EOF") + return when { + nextChar == "{" -> parseTag() + nextChar == "[" -> parseList() + nextChar == "\"" -> parseStringTag() + nextChar.first() in (digitRange) -> parseNumericTag() + else -> racer.error("Unexpected token found. Expected start of new element") + } + } + + fun parseList(): ListTag { + skipWhitespace() + racer.expect("[", "Expected '[' at start of tag") + skipWhitespace() + val list = ListTag() + while (!racer.tryConsume("]")) { + skipWhitespace() + racer.pushState() + val lhs = racer.consumeWhile { it.all { it in digitRange } } + skipWhitespace() + if (!racer.tryConsume(":") || lhs.isEmpty()) { // No prefixed 0: + racer.popState() + list.add(parseAny()) // Reparse our number (or not a number) as actual tag + } else { + racer.discardState() + skipWhitespace() + list.add(parseAny()) // Ignore prefix indexes. They should not be generated out of order by any vanilla implementation (which is what NEU should export). Instead append where it appears in order. + } + skipWhitespace() + racer.tryConsume(",") + } + return list + } + + fun parseQuotedString(): String { + skipWhitespace() + racer.expect("\"", "Expected '\"' at string start") + val sb = StringBuilder() + while (true) { + when (val peek = racer.consumeCountReq(1)) { + "\"" -> break + "\\" -> { + val escaped = racer.consumeCountReq(1) ?: racer.error("Unfinished backslash escape") + if (escaped != "\"" && escaped != "\\") { + // Surprisingly i couldn't find unicode escapes to be generated by the original minecraft 1.8.9 implementation + racer.idx-- + racer.error("Invalid backslash escape '$escaped'") + } + sb.append(escaped) + } + null -> racer.error("Unfinished string") + else -> { + sb.append(peek) + } + } + } + return sb.toString() + } + + fun parseStringTag(): StringTag { + return StringTag.valueOf(parseQuotedString()) + } + + object Patterns { + val DOUBLE = "([-+]?[0-9]*\\.?[0-9]+)[d|D]".toRegex() + val FLOAT = "([-+]?[0-9]*\\.?[0-9]+)[f|F]".toRegex() + val BYTE = "([-+]?[0-9]+)[b|B]".toRegex() + val LONG = "([-+]?[0-9]+)[l|L]".toRegex() + val SHORT = "([-+]?[0-9]+)[s|S]".toRegex() + val INTEGER = "([-+]?[0-9]+)".toRegex() + val DOUBLE_UNTYPED = "([-+]?[0-9]*\\.?[0-9]+)".toRegex() + val ROUGH_PATTERN = "[-+]?[0-9]*\\.?[0-9]+[dDbBfFlLsS]?".toRegex() + } + + fun parseNumericTag(): NumericTag { + skipWhitespace() + val textForm = racer.consumeWhile { Patterns.ROUGH_PATTERN.matchEntire(it) != null } + if (textForm.isEmpty()) { + racer.error("Expected numeric tag (starting with either -, +, . or a digit") + } + val doubleMatch = Patterns.DOUBLE.matchEntire(textForm) ?: Patterns.DOUBLE_UNTYPED.matchEntire(textForm) + if (doubleMatch != null) { + return DoubleTag.valueOf(doubleMatch.groups[1]!!.value.toDouble()) + } + val floatMatch = Patterns.FLOAT.matchEntire(textForm) + if (floatMatch != null) { + return FloatTag.valueOf(floatMatch.groups[1]!!.value.toFloat()) + } + val byteMatch = Patterns.BYTE.matchEntire(textForm) + if (byteMatch != null) { + return ByteTag.valueOf(byteMatch.groups[1]!!.value.toByte()) + } + val longMatch = Patterns.LONG.matchEntire(textForm) + if (longMatch != null) { + return LongTag.valueOf(longMatch.groups[1]!!.value.toLong()) + } + val shortMatch = Patterns.SHORT.matchEntire(textForm) + if (shortMatch != null) { + return ShortTag.valueOf(shortMatch.groups[1]!!.value.toShort()) + } + val integerMatch = Patterns.INTEGER.matchEntire(textForm) + if (integerMatch != null) { + return IntTag.valueOf(integerMatch.groups[1]!!.value.toInt()) + } + throw IllegalStateException("Could not properly parse numeric tag '$textForm', despite passing rough verification. This is a bug in the LegacyTagParser") + } + + private fun parseIdentifier(): String { + skipWhitespace() + if (racer.peek(1) == "\"") { + return parseQuotedString() + } + return racer.consumeWhile { + val x = it.last() + x != ':' && !Character.isWhitespace(x) + } + } + +} diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json new file mode 100644 index 0000000..c739445 --- /dev/null +++ b/src/main/resources/fabric.mod.json @@ -0,0 +1,36 @@ +{ + "schemaVersion": 1, + "id": "notenoughupdates", + "version": "${version}", + "name": "Not Enough Updates", + "description": "Not Enough Updates - A mod for Hypixel Skyblock", + "authors": [ + "nea89" + ], + "contact": { + "homepage": "https://github.com/romangraef/TODO", + "sources": "https://github.com/romangraef/TODO" + }, + "license": "LGPL-3.0", + "icon": "assets/notenoughupdates/icon.png", + "environment": "client", + "entrypoints": { + "main": [ + { + "adapter": "kotlin", + "value": "moe.nea.notenoughupdates.NotEnoughUpdates" + } + ], + "rei": [ + "moe.nea.notenoughupdates.rei.NEUReiPlugin" + ] + }, + "mixins": [ + "notenoughupdates.mixins.json" + ], + "depends": { + "fabric": "*", + "fabric-language-kotlin": ">=1.8.2+kotlin.1.7.10", + "minecraft": ">=1.18.2" + } +} diff --git a/src/main/resources/notenoughupdates.accesswidener b/src/main/resources/notenoughupdates.accesswidener new file mode 100644 index 0000000..236e6b1 --- /dev/null +++ b/src/main/resources/notenoughupdates.accesswidener @@ -0,0 +1 @@ +accessWidener v2 named diff --git a/src/main/resources/notenoughupdates.mixins.json b/src/main/resources/notenoughupdates.mixins.json new file mode 100644 index 0000000..3067bcc --- /dev/null +++ b/src/main/resources/notenoughupdates.mixins.json @@ -0,0 +1,12 @@ +{ + "required": true, + "package": "moe.nea.notenoughupdates.mixins", + "compatibilityLevel": "JAVA_16", + "client": [ + ], + "mixins": [ + ], + "injectors": { + "defaultRequire": 1 + } +} -- cgit