no arch
This commit is contained in:
18
src/main/kotlin/moe/nea/notenoughupdates/NotEnoughUpdates.kt
Normal file
18
src/main/kotlin/moe/nea/notenoughupdates/NotEnoughUpdates.kt
Normal file
@@ -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() {
|
||||
}
|
||||
}
|
||||
38
src/main/kotlin/moe/nea/notenoughupdates/rei/NEUReiPlugin.kt
Normal file
38
src/main/kotlin/moe/nea/notenoughupdates/rei/NEUReiPlugin.kt
Normal file
@@ -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<NEUItem>.asItemEntry(): EntryStack<ItemStack> {
|
||||
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))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<NEUItem> {
|
||||
override fun equals(o1: NEUItem?, o2: NEUItem?, context: ComparisonContext?): Boolean {
|
||||
return o1 == o2
|
||||
}
|
||||
|
||||
override fun cheatsAs(entry: EntryStack<NEUItem>?, value: NEUItem?): ItemStack? {
|
||||
return value?.asItemStack()
|
||||
}
|
||||
|
||||
override fun getValueType(): Class<NEUItem> = NEUItem::class.java
|
||||
override fun getType(): EntryType<NEUItem> =
|
||||
EntryType.deferred(NEUReiPlugin.SKYBLOCK_ITEM_TYPE_ID)
|
||||
|
||||
override fun getRenderer(): EntryRenderer<NEUItem> = object : EntryRenderer<NEUItem> {
|
||||
override fun render(
|
||||
entry: EntryStack<NEUItem>,
|
||||
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<NEUItem>, tooltipContext: TooltipContext): Tooltip? {
|
||||
return VanillaEntryTypes.ITEM.definition.renderer
|
||||
.getTooltip(entry.asItemEntry(), tooltipContext)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun getSerializer(): EntrySerializer<NEUItem>? {
|
||||
return null
|
||||
}
|
||||
|
||||
override fun getTagsFor(entry: EntryStack<NEUItem>?, value: NEUItem?): Stream<out TagKey<*>> {
|
||||
return Stream.empty()
|
||||
}
|
||||
|
||||
override fun asFormattedText(entry: EntryStack<NEUItem>, value: NEUItem): Component {
|
||||
return VanillaEntryTypes.ITEM.definition.asFormattedText(entry.asItemEntry(), value.asItemStack())
|
||||
}
|
||||
|
||||
override fun hash(entry: EntryStack<NEUItem>, value: NEUItem, context: ComparisonContext): Long {
|
||||
return value.skyblockItemId.hashCode().toLong()
|
||||
}
|
||||
|
||||
override fun wildcard(entry: EntryStack<NEUItem>, value: NEUItem): NEUItem {
|
||||
return value
|
||||
}
|
||||
|
||||
override fun normalize(entry: EntryStack<NEUItem>, value: NEUItem): NEUItem {
|
||||
return value
|
||||
}
|
||||
|
||||
override fun copy(entry: EntryStack<NEUItem>?, value: NEUItem): NEUItem {
|
||||
return value
|
||||
}
|
||||
|
||||
override fun isEmpty(entry: EntryStack<NEUItem>?, value: NEUItem?): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun getIdentifier(entry: EntryStack<NEUItem>?, value: NEUItem): ResourceLocation {
|
||||
return value.getResourceLocation()
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
75
src/main/kotlin/moe/nea/notenoughupdates/repo/ItemCache.kt
Normal file
75
src/main/kotlin/moe/nea/notenoughupdates/repo/ItemCache.kt
Normal file
@@ -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<String, ItemStack> = 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()
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
}
|
||||
23
src/main/kotlin/moe/nea/notenoughupdates/util/ItemUtil.kt
Normal file
23
src/main/kotlin/moe/nea/notenoughupdates/util/ItemUtil.kt
Normal file
@@ -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<Component>) {
|
||||
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)
|
||||
}
|
||||
232
src/main/kotlin/moe/nea/notenoughupdates/util/LegacyTagParser.kt
Normal file
232
src/main/kotlin/moe/nea/notenoughupdates/util/LegacyTagParser.kt
Normal file
@@ -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<Int>()
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
36
src/main/resources/fabric.mod.json
Normal file
36
src/main/resources/fabric.mod.json
Normal file
@@ -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"
|
||||
}
|
||||
}
|
||||
1
src/main/resources/notenoughupdates.accesswidener
Normal file
1
src/main/resources/notenoughupdates.accesswidener
Normal file
@@ -0,0 +1 @@
|
||||
accessWidener v2 named
|
||||
12
src/main/resources/notenoughupdates.mixins.json
Normal file
12
src/main/resources/notenoughupdates.mixins.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"required": true,
|
||||
"package": "moe.nea.notenoughupdates.mixins",
|
||||
"compatibilityLevel": "JAVA_16",
|
||||
"client": [
|
||||
],
|
||||
"mixins": [
|
||||
],
|
||||
"injectors": {
|
||||
"defaultRequire": 1
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user