legacy tag parsing and transformation
This commit is contained in:
@@ -0,0 +1,232 @@
|
|||||||
|
package moe.nea.notenoughupdates
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package moe.nea.notenoughupdates
|
||||||
|
|
||||||
|
import dev.architectury.registry.registries.Registries
|
||||||
|
import io.github.moulberry.repo.NEURepository
|
||||||
|
import java.nio.file.Path
|
||||||
|
|
||||||
|
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() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
package moe.nea.notenoughupdates.rei
|
package moe.nea.notenoughupdates.rei
|
||||||
|
|
||||||
import com.mojang.blaze3d.vertex.PoseStack
|
import com.mojang.blaze3d.vertex.PoseStack
|
||||||
import io.github.moulberry.repo.NEURepository
|
import com.mojang.serialization.Dynamic
|
||||||
|
import io.github.moulberry.repo.data.NEUItem
|
||||||
import me.shedaniel.math.Point
|
import me.shedaniel.math.Point
|
||||||
import me.shedaniel.math.Rectangle
|
import me.shedaniel.math.Rectangle
|
||||||
import me.shedaniel.rei.api.client.entry.renderer.EntryRenderer
|
import me.shedaniel.rei.api.client.entry.renderer.EntryRenderer
|
||||||
@@ -16,45 +17,105 @@ import me.shedaniel.rei.api.common.entry.type.EntryType
|
|||||||
import me.shedaniel.rei.api.common.entry.type.EntryTypeRegistry
|
import me.shedaniel.rei.api.common.entry.type.EntryTypeRegistry
|
||||||
import me.shedaniel.rei.api.common.entry.type.VanillaEntryTypes
|
import me.shedaniel.rei.api.common.entry.type.VanillaEntryTypes
|
||||||
import me.shedaniel.rei.api.common.util.EntryStacks
|
import me.shedaniel.rei.api.common.util.EntryStacks
|
||||||
import net.minecraft.core.Registry
|
import moe.nea.notenoughupdates.LegacyTagParser
|
||||||
|
import moe.nea.notenoughupdates.NotEnoughUpdates.neuRepo
|
||||||
|
import net.minecraft.ChatFormatting
|
||||||
|
import net.minecraft.nbt.CompoundTag
|
||||||
|
import net.minecraft.nbt.NbtOps
|
||||||
|
import net.minecraft.nbt.StringTag
|
||||||
import net.minecraft.network.chat.Component
|
import net.minecraft.network.chat.Component
|
||||||
import net.minecraft.network.chat.TextComponent
|
import net.minecraft.network.chat.TextComponent
|
||||||
import net.minecraft.resources.ResourceLocation
|
import net.minecraft.resources.ResourceLocation
|
||||||
import net.minecraft.tags.TagKey
|
import net.minecraft.tags.TagKey
|
||||||
import net.minecraft.world.item.Item
|
import net.minecraft.util.datafix.DataFixers.getDataFixer
|
||||||
|
import net.minecraft.util.datafix.fixes.References
|
||||||
import net.minecraft.world.item.ItemStack
|
import net.minecraft.world.item.ItemStack
|
||||||
import net.minecraft.world.item.Items
|
import net.minecraft.world.item.Items
|
||||||
import net.minecraft.world.item.enchantment.Enchantments
|
import net.minecraft.world.item.enchantment.Enchantments
|
||||||
import java.nio.file.Path
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
import java.util.stream.Stream
|
import java.util.stream.Stream
|
||||||
|
|
||||||
|
|
||||||
class NEUReiPlugin : REIClientPlugin {
|
class NEUReiPlugin : REIClientPlugin {
|
||||||
|
|
||||||
data class SBItem(val sbname: String, val backing: Item)
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
fun EntryStack<NEUReiPlugin.SBItem>.asItemStack() =
|
fun EntryStack<NEUItem>.asItemEntry(): EntryStack<ItemStack> {
|
||||||
EntryStack.of(VanillaEntryTypes.ITEM, ItemStack(this.value.backing).also {
|
return EntryStack.of(VanillaEntryTypes.ITEM, value.asItemStack())
|
||||||
it.enchant(Enchantments.BINDING_CURSE, 1)
|
}
|
||||||
it.hoverName = TextComponent(value.sbname)
|
|
||||||
})
|
fun ItemStack.appendLore(args: List<Component>) {
|
||||||
|
val compoundTag = getOrCreateTagElement("display")
|
||||||
|
val loreList = compoundTag.getList("Lore", StringTag.TAG_STRING.toInt())
|
||||||
|
for (arg in args) {
|
||||||
|
loreList.add(StringTag.valueOf(Component.Serializer.toJson(arg)))
|
||||||
|
}
|
||||||
|
compoundTag.put("Lore", loreList)
|
||||||
|
}
|
||||||
|
|
||||||
|
val cache: MutableMap<String, ItemStack> = ConcurrentHashMap()
|
||||||
|
|
||||||
|
fun NEUItem.asItemStackNow(): ItemStack {
|
||||||
|
val df = getDataFixer()
|
||||||
|
val itemTag1_8_9 = CompoundTag()
|
||||||
|
itemTag1_8_9.put("tag", LegacyTagParser.parse(this.nbttag))
|
||||||
|
itemTag1_8_9.putString("id", this.minecraftItemId)
|
||||||
|
itemTag1_8_9.putByte("Count", 1)
|
||||||
|
itemTag1_8_9.putShort("Damage", this.damage.toShort())
|
||||||
|
val itemTag_modern = try {
|
||||||
|
df.update(
|
||||||
|
References.ITEM_STACK,
|
||||||
|
Dynamic(NbtOps.INSTANCE, itemTag1_8_9),
|
||||||
|
99,
|
||||||
|
2975
|
||||||
|
).value as CompoundTag
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
return ItemStack(Items.PAINTING).apply {
|
||||||
|
appendLore(listOf(TextComponent("Exception rendering item: $skyblockItemId")))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val itemInstance = ItemStack.of(itemTag_modern)
|
||||||
|
return itemInstance.also {
|
||||||
|
if(false)it.appendLore(
|
||||||
|
listOf(
|
||||||
|
TextComponent("Old: $minecraftItemId").withStyle {
|
||||||
|
it.withItalic(false).withColor(ChatFormatting.RED)
|
||||||
|
},
|
||||||
|
TextComponent("Modern: $itemTag_modern").withStyle {
|
||||||
|
it.withItalic(false).withColor(ChatFormatting.RED)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
)
|
||||||
|
it.hoverName = TextComponent(this.skyblockItemId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun NEUItem.asItemStack(): ItemStack {
|
||||||
|
var s = cache[this.skyblockItemId]
|
||||||
|
if (s == null) {
|
||||||
|
s = asItemStackNow()
|
||||||
|
cache[this.skyblockItemId] = s
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
val hehe = ResourceLocation("notenoughupdates", "skyblockitems")
|
val hehe = ResourceLocation("notenoughupdates", "skyblockitems")
|
||||||
}
|
}
|
||||||
|
|
||||||
object SBItemEntryDefinition : EntryDefinition<SBItem> {
|
object SBItemEntryDefinition : EntryDefinition<NEUItem> {
|
||||||
override fun equals(o1: SBItem?, o2: SBItem?, context: ComparisonContext?): Boolean {
|
override fun equals(o1: NEUItem?, o2: NEUItem?, context: ComparisonContext?): Boolean {
|
||||||
return o1 == o2
|
return o1 == o2
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getValueType(): Class<SBItem> = SBItem::class.java
|
override fun getValueType(): Class<NEUItem> = NEUItem::class.java
|
||||||
override fun getType(): EntryType<SBItem> =
|
override fun getType(): EntryType<NEUItem> =
|
||||||
EntryType.deferred(hehe)
|
EntryType.deferred(hehe)
|
||||||
|
|
||||||
override fun getRenderer(): EntryRenderer<SBItem> = object : EntryRenderer<SBItem> {
|
override fun getRenderer(): EntryRenderer<NEUItem> = object : EntryRenderer<NEUItem> {
|
||||||
override fun render(
|
override fun render(
|
||||||
entry: EntryStack<SBItem>,
|
entry: EntryStack<NEUItem>,
|
||||||
matrices: PoseStack,
|
matrices: PoseStack,
|
||||||
bounds: Rectangle,
|
bounds: Rectangle,
|
||||||
mouseX: Int,
|
mouseX: Int,
|
||||||
@@ -63,75 +124,64 @@ class NEUReiPlugin : REIClientPlugin {
|
|||||||
) {
|
) {
|
||||||
VanillaEntryTypes.ITEM.definition.renderer
|
VanillaEntryTypes.ITEM.definition.renderer
|
||||||
.render(
|
.render(
|
||||||
entry.asItemStack(),
|
entry.asItemEntry(),
|
||||||
matrices, bounds, mouseX, mouseY, delta
|
matrices, bounds, mouseX, mouseY, delta
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getTooltip(entry: EntryStack<SBItem>, mouse: Point): Tooltip? {
|
override fun getTooltip(entry: EntryStack<NEUItem>, mouse: Point): Tooltip? {
|
||||||
return VanillaEntryTypes.ITEM.definition.renderer
|
return VanillaEntryTypes.ITEM.definition.renderer
|
||||||
.getTooltip(entry.asItemStack(), mouse)
|
.getTooltip(entry.asItemEntry(), mouse)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getSerializer(): EntrySerializer<SBItem>? {
|
override fun getSerializer(): EntrySerializer<NEUItem>? {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getTagsFor(entry: EntryStack<SBItem>?, value: SBItem?): Stream<out TagKey<*>> {
|
override fun getTagsFor(entry: EntryStack<NEUItem>?, value: NEUItem?): Stream<out TagKey<*>> {
|
||||||
return Stream.empty()
|
return Stream.empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun asFormattedText(entry: EntryStack<SBItem>, value: SBItem): Component {
|
override fun asFormattedText(entry: EntryStack<NEUItem>, value: NEUItem): Component {
|
||||||
return VanillaEntryTypes.ITEM.definition.asFormattedText(entry.asItemStack(), ItemStack(value.backing))
|
return VanillaEntryTypes.ITEM.definition.asFormattedText(entry.asItemEntry(), value.asItemStack())
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun hash(entry: EntryStack<SBItem>, value: SBItem, context: ComparisonContext): Long {
|
override fun hash(entry: EntryStack<NEUItem>, value: NEUItem, context: ComparisonContext): Long {
|
||||||
return value.sbname.hashCode().toLong()
|
return value.skyblockItemId.hashCode().toLong()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun wildcard(entry: EntryStack<SBItem>, value: SBItem): SBItem {
|
override fun wildcard(entry: EntryStack<NEUItem>, value: NEUItem): NEUItem {
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun normalize(entry: EntryStack<SBItem>, value: SBItem): SBItem {
|
override fun normalize(entry: EntryStack<NEUItem>, value: NEUItem): NEUItem {
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun copy(entry: EntryStack<SBItem>?, value: SBItem): SBItem {
|
override fun copy(entry: EntryStack<NEUItem>?, value: NEUItem): NEUItem {
|
||||||
return value.copy()
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun isEmpty(entry: EntryStack<SBItem>?, value: SBItem?): Boolean {
|
override fun isEmpty(entry: EntryStack<NEUItem>?, value: NEUItem?): Boolean {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getIdentifier(entry: EntryStack<SBItem>?, value: SBItem): ResourceLocation? {
|
override fun getIdentifier(entry: EntryStack<NEUItem>?, value: NEUItem): ResourceLocation {
|
||||||
return ResourceLocation("skyblockitem", value.sbname)
|
return ResourceLocation("skyblockitem", value.skyblockItemId.lowercase().replace(";", "__"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val neuRepo = NEURepository.of(Path.of("NotEnoughUpdates-REPO")).also {
|
|
||||||
it.reload()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun registerEntryTypes(registry: EntryTypeRegistry) {
|
override fun registerEntryTypes(registry: EntryTypeRegistry) {
|
||||||
registry.register(hehe, SBItemEntryDefinition)
|
registry.register(hehe, SBItemEntryDefinition)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun registerEntries(registry: EntryRegistry) {
|
override fun registerEntries(registry: EntryRegistry) {
|
||||||
neuRepo.items.items.values.forEach {
|
neuRepo.items.items.values.forEach {
|
||||||
println("Adding item: $it")
|
registry.addEntry(EntryStack.of(SBItemEntryDefinition, it))
|
||||||
registry.addEntry(
|
|
||||||
EntryStack.of(
|
|
||||||
SBItemEntryDefinition, SBItem(
|
|
||||||
it.skyblockItemId.lowercase().replace(";", "__"), Registry.ITEM.get(ResourceLocation(it.minecraftItemId))
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
registry.addEntry(EntryStacks.of(ItemStack(Items.DIAMOND).also {
|
registry.addEntry(EntryStacks.of(ItemStack(Items.DIAMOND).also {
|
||||||
it.enchant(Enchantments.ALL_DAMAGE_PROTECTION, 10)
|
it.enchant(Enchantments.ALL_DAMAGE_PROTECTION, 10)
|
||||||
|
|||||||
@@ -1,30 +0,0 @@
|
|||||||
package net.examplemod
|
|
||||||
|
|
||||||
import dev.architectury.injectables.annotations.ExpectPlatform
|
|
||||||
import dev.architectury.platform.Platform
|
|
||||||
import java.nio.file.Path
|
|
||||||
|
|
||||||
object ExampleExpectPlatform {
|
|
||||||
/**
|
|
||||||
* We can use [Platform.getConfigFolder] but this is just an example of [ExpectPlatform].
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* This must be a **public static** method. The platform-implemented solution must be placed under a
|
|
||||||
* platform sub-package, with its class suffixed with `Impl`.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Example:
|
|
||||||
* Expect: net.examplemod.ExampleExpectPlatform#getConfigDirectory()
|
|
||||||
* Actual Fabric: net.examplemod.fabric.ExampleExpectPlatformImpl#getConfigDirectory()
|
|
||||||
* Actual Forge: net.examplemod.forge.ExampleExpectPlatformImpl#getConfigDirectory()
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* [You should also get the IntelliJ plugin to help with @ExpectPlatform.](https://plugins.jetbrains.com/plugin/16210-architectury)
|
|
||||||
*/
|
|
||||||
@ExpectPlatform
|
|
||||||
@JvmStatic
|
|
||||||
fun getConfigDirectory(): Path {
|
|
||||||
// Just throw an error, the content should get replaced at runtime.
|
|
||||||
throw AssertionError()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
package net.examplemod
|
|
||||||
|
|
||||||
import com.google.common.base.Suppliers
|
|
||||||
import dev.architectury.registry.CreativeTabRegistry
|
|
||||||
import dev.architectury.registry.registries.DeferredRegister
|
|
||||||
import dev.architectury.registry.registries.Registries
|
|
||||||
import dev.architectury.registry.registries.RegistrySupplier
|
|
||||||
import net.minecraft.core.Registry
|
|
||||||
import net.minecraft.resources.ResourceLocation
|
|
||||||
import net.minecraft.world.item.CreativeModeTab
|
|
||||||
import net.minecraft.world.item.Item
|
|
||||||
import net.minecraft.world.item.ItemStack
|
|
||||||
import java.util.function.Supplier
|
|
||||||
|
|
||||||
object ExampleMod {
|
|
||||||
const val MOD_ID = "examplemod"
|
|
||||||
|
|
||||||
// We can use this if we don't want to use DeferredRegister
|
|
||||||
@Suppress("unused")
|
|
||||||
val REGISTRIES: Supplier<Registries> = Suppliers.memoize { Registries.get(MOD_ID) }
|
|
||||||
|
|
||||||
// Registering a new creative tab
|
|
||||||
val EXAMPLE_TAB: CreativeModeTab = CreativeTabRegistry.create(ResourceLocation(MOD_ID, "example_tab")) { ItemStack(EXAMPLE_ITEM.get()) }
|
|
||||||
val ITEMS: DeferredRegister<Item> = DeferredRegister.create(MOD_ID, Registry.ITEM_REGISTRY)
|
|
||||||
val EXAMPLE_ITEM: RegistrySupplier<Item> = ITEMS.register("example_item") { Item(Item.Properties().tab(EXAMPLE_TAB)) }
|
|
||||||
|
|
||||||
fun init() {
|
|
||||||
ITEMS.register()
|
|
||||||
println(ExampleExpectPlatform.getConfigDirectory().toAbsolutePath().normalize().toString())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
package net.examplemod.mixin
|
|
||||||
|
|
||||||
import net.minecraft.client.gui.screens.TitleScreen
|
|
||||||
import org.objectweb.asm.Opcodes
|
|
||||||
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.Redirect
|
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo
|
|
||||||
|
|
||||||
@Mixin(TitleScreen::class)
|
|
||||||
class MixinTitleScreen {
|
|
||||||
@Inject(at = [At("HEAD")], method = ["init()V"])
|
|
||||||
private fun init(info: CallbackInfo) {
|
|
||||||
println("Hello from example architectury common mixin!")
|
|
||||||
}
|
|
||||||
|
|
||||||
@Redirect(method = ["render"], at = At("FIELD", target = "minceraftEasterEgg", opcode = Opcodes.GETFIELD))
|
|
||||||
private fun nextFloat(t: TitleScreen): Boolean {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
"item.examplemod.example_item": "Example Item"
|
|
||||||
}
|
|
||||||
@@ -3,7 +3,6 @@
|
|||||||
"package": "net.examplemod.mixin",
|
"package": "net.examplemod.mixin",
|
||||||
"compatibilityLevel": "JAVA_16",
|
"compatibilityLevel": "JAVA_16",
|
||||||
"client": [
|
"client": [
|
||||||
"MixinTitleScreen"
|
|
||||||
],
|
],
|
||||||
"mixins": [
|
"mixins": [
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -9,6 +9,11 @@ architectury {
|
|||||||
|
|
||||||
loom {
|
loom {
|
||||||
accessWidenerPath.set(project(":common").loom.accessWidenerPath)
|
accessWidenerPath.set(project(":common").loom.accessWidenerPath)
|
||||||
|
launches {
|
||||||
|
named("client") {
|
||||||
|
property("fabric.log.level", "info")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package moe.nea.notenoughupdates
|
||||||
|
|
||||||
|
import moe.nea.notenoughupdates.NotEnoughUpdates.init
|
||||||
|
import net.fabricmc.api.ModInitializer
|
||||||
|
|
||||||
|
class FabricMain : ModInitializer {
|
||||||
|
override fun onInitialize() {
|
||||||
|
init()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
package net.examplemod.fabric
|
|
||||||
|
|
||||||
import net.fabricmc.loader.api.FabricLoader
|
|
||||||
import java.nio.file.Path
|
|
||||||
import net.examplemod.ExampleExpectPlatform
|
|
||||||
|
|
||||||
object ExampleExpectPlatformImpl {
|
|
||||||
/**
|
|
||||||
* This is our actual method to [ExampleExpectPlatform.getConfigDirectory].
|
|
||||||
*/
|
|
||||||
@JvmStatic
|
|
||||||
fun getConfigDirectory(): Path = FabricLoader.getInstance().configDir
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
package net.examplemod.fabric
|
|
||||||
|
|
||||||
import net.examplemod.ExampleMod.init
|
|
||||||
import net.fabricmc.api.ModInitializer
|
|
||||||
|
|
||||||
class ExampleModFabric : ModInitializer {
|
|
||||||
override fun onInitialize() {
|
|
||||||
init()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
"environment": "client",
|
"environment": "client",
|
||||||
"entrypoints": {
|
"entrypoints": {
|
||||||
"main": [
|
"main": [
|
||||||
"net.examplemod.fabric.ExampleModFabric"
|
"moe.nea.notenoughupdates.FabricMain"
|
||||||
],
|
],
|
||||||
"rei": [
|
"rei": [
|
||||||
"moe.nea.notenoughupdates.rei.NEUReiPlugin"
|
"moe.nea.notenoughupdates.rei.NEUReiPlugin"
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
package net.examplemod.forge
|
package net.examplemod.forge
|
||||||
|
|
||||||
import dev.architectury.platform.forge.EventBuses
|
import dev.architectury.platform.forge.EventBuses
|
||||||
import net.examplemod.ExampleMod
|
import moe.nea.notenoughupdates.NotEnoughUpdates
|
||||||
import net.examplemod.ExampleMod.init
|
import moe.nea.notenoughupdates.NotEnoughUpdates.init
|
||||||
import net.minecraftforge.fml.common.Mod
|
import net.minecraftforge.fml.common.Mod
|
||||||
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext
|
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext
|
||||||
|
|
||||||
@Mod(ExampleMod.MOD_ID)
|
@Mod(NotEnoughUpdates.MOD_ID)
|
||||||
class ExampleModForge {
|
class ExampleModForge {
|
||||||
init {
|
init {
|
||||||
// Submit our event bus to let architectury register our content on the right time
|
// Submit our event bus to let architectury register our content on the right time
|
||||||
EventBuses.registerModEventBus(ExampleMod.MOD_ID, FMLJavaModLoadingContext.get().modEventBus)
|
EventBuses.registerModEventBus(NotEnoughUpdates.MOD_ID, FMLJavaModLoadingContext.get().modEventBus)
|
||||||
init()
|
init()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
package net.examplemod.quilt
|
package net.examplemod.quilt
|
||||||
|
|
||||||
import net.examplemod.ExampleMod.init
|
import moe.nea.notenoughupdates.NotEnoughUpdates.init
|
||||||
import org.quiltmc.loader.api.ModContainer
|
import org.quiltmc.loader.api.ModContainer
|
||||||
import org.quiltmc.qsl.base.api.entrypoint.ModInitializer
|
import org.quiltmc.qsl.base.api.entrypoint.ModInitializer
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user