Added 1.21 support

This commit is contained in:
Auxilor 2024-06-20 19:14:26 +01:00
parent f166ebf6fb
commit 0dd8bbeff3
15 changed files with 384 additions and 17 deletions

View File

@ -27,6 +27,7 @@ dependencies {
implementation(project(":eco-core:core-nms:v1_20_R2"))
implementation(project(":eco-core:core-nms:v1_20_R3", configuration = "reobf"))
implementation(project(":eco-core:core-nms:v1_20_6", configuration = "reobf"))
implementation(project(":eco-core:core-nms:v1_21", configuration = "reobf"))
}
allprojects {
@ -41,14 +42,17 @@ allprojects {
maven("https://repo.papermc.io/repository/maven-public/")
maven("https://repo.auxilor.io/repository/maven-public/")
maven("https://jitpack.io")
maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots/")
maven("https://repo.codemc.org/repository/nms/")
maven("https://repo.essentialsx.net/releases/")
maven("https://jitpack.io") {
content { includeGroupByRegex("com\\.github\\..*") }
}
}
dependencies {
compileOnly("com.willfp:eco:6.70.0")
compileOnly("com.willfp:eco:6.71.0")
compileOnly("org.jetbrains:annotations:23.0.0")
compileOnly("org.jetbrains.kotlin:kotlin-stdlib:1.9.20")
compileOnly("com.github.ben-manes.caffeine:caffeine:3.1.5")
@ -65,12 +69,6 @@ allprojects {
}
}
java {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
withSourcesJar()
}
compileJava {
options.isDeprecation = true
options.encoding = "UTF-8"
@ -91,6 +89,17 @@ allprojects {
build {
dependsOn(shadowJar)
}
withType<JavaCompile>().configureEach {
options.release = 17
}
}
java {
withSourcesJar()
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}
}

View File

@ -1,8 +1,7 @@
plugins {
id("io.papermc.paperweight.userdev") version "1.6.2" apply false
id("io.papermc.paperweight.userdev") version "1.7.1" apply false
}
group = "com.willfp"
version = rootProject.version

View File

@ -14,10 +14,8 @@ tasks {
dependsOn(reobfJar)
}
java {
sourceCompatibility = JavaVersion.VERSION_21
targetCompatibility = JavaVersion.VERSION_21
withSourcesJar()
compileJava {
options.release = 21
}
compileKotlin {

View File

@ -7,6 +7,7 @@ version = rootProject.version
dependencies {
paperweight.paperDevBundle("1.20.3-R0.1-SNAPSHOT")
pluginRemapper("net.fabricmc:tiny-remapper:0.10.3:fat")
}
tasks {

View File

@ -0,0 +1,26 @@
plugins {
id("io.papermc.paperweight.userdev")
}
group = "com.willfp"
version = rootProject.version
dependencies {
paperweight.paperDevBundle("1.21-R0.1-SNAPSHOT")
}
tasks {
build {
dependsOn(reobfJar)
}
compileJava {
options.release = 21
}
compileKotlin {
kotlinOptions {
jvmTarget = "21"
}
}
}

View File

@ -0,0 +1,19 @@
package com.willfp.ecoenchants.proxy.v1_21
import com.willfp.eco.core.fast.FastItemStack
import com.willfp.ecoenchants.display.HideStoredEnchantsProxy
import org.bukkit.inventory.ItemFlag
class HideStoredEnchants: HideStoredEnchantsProxy {
override fun hideStoredEnchants(fis: FastItemStack) {
fis.addItemFlags(ItemFlag.HIDE_STORED_ENCHANTS)
}
override fun areStoredEnchantsHidden(fis: FastItemStack): Boolean {
return fis.hasItemFlag(ItemFlag.HIDE_STORED_ENCHANTS)
}
override fun showStoredEnchants(fis: FastItemStack) {
fis.removeItemFlags(ItemFlag.HIDE_STORED_ENCHANTS)
}
}

View File

@ -0,0 +1,140 @@
package com.willfp.ecoenchants.proxy.v1_21
import com.willfp.ecoenchants.enchant.EcoEnchant
import com.willfp.ecoenchants.enchant.EcoEnchants
import com.willfp.ecoenchants.enchant.impl.EcoEnchantBase
import com.willfp.ecoenchants.enchant.registration.modern.ModernEnchantmentRegistererProxy
import com.willfp.ecoenchants.proxy.v1_21.registration.EcoEnchantsCraftEnchantment
import com.willfp.ecoenchants.proxy.v1_21.registration.ModifiedVanillaCraftEnchantment
import com.willfp.ecoenchants.proxy.v1_21.registration.vanillaEcoEnchantsEnchantment
import com.willfp.ecoenchants.setStaticFinal
import io.papermc.paper.registry.PaperRegistryAccess
import io.papermc.paper.registry.RegistryAccess
import io.papermc.paper.registry.RegistryKey
import io.papermc.paper.registry.WritableCraftRegistry
import net.minecraft.core.Holder
import net.minecraft.core.MappedRegistry
import net.minecraft.core.Registry
import net.minecraft.core.RegistrySynchronization
import net.minecraft.core.registries.Registries
import net.minecraft.resources.ResourceKey
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.item.enchantment.Enchantments
import org.bukkit.Bukkit
import org.bukkit.NamespacedKey
import org.bukkit.craftbukkit.CraftRegistry
import org.bukkit.craftbukkit.CraftServer
import org.bukkit.craftbukkit.util.CraftNamespacedKey
import org.bukkit.enchantments.Enchantment
import java.util.HashMap
import java.util.IdentityHashMap
import java.util.function.BiFunction
private val enchantmentRegistry =
(Bukkit.getServer() as CraftServer).server.registryAccess().registryOrThrow(Registries.ENCHANTMENT)
@Suppress("DEPRECATION")
private val bukkitRegistry =
org.bukkit.Registry.ENCHANTMENT
class ModernEnchantmentRegisterer : ModernEnchantmentRegistererProxy {
private val frozenField = MappedRegistry::class.java
.declaredFields
.filter { it.type.isPrimitive }[0]
.apply { isAccessible = true }
private val unregisteredIntrusiveHoldersField = MappedRegistry::class.java
.declaredFields
.last { it.type == Map::class.java }
.apply { isAccessible = true }
private val minecraftToBukkit = bukkitRegistry::class.java
.getDeclaredField("minecraftToBukkit")
.apply { isAccessible = true }
// Paper has two minecraftToBukkit fields, one in CraftRegistry and one in WritableCraftRegistry
private val minecraftToBukkitAlt = CraftRegistry::class.java
.getDeclaredField("minecraftToBukkit")
.apply { isAccessible = true }
private val cache = CraftRegistry::class.java
.getDeclaredField("cache")
.apply { isAccessible = true }
@Suppress("UNCHECKED_CAST")
private val vanillaEnchantments = Enchantments::class.java
.declaredFields
.asSequence()
.filter { it.type == ResourceKey::class.java }
.map { it.get(null) as ResourceKey<net.minecraft.world.item.enchantment.Enchantment> }
.map { it.location() }
.map { CraftNamespacedKey.fromMinecraft(it) }
.toSet()
override fun replaceRegistry() {
val newRegistryMTB =
BiFunction<NamespacedKey, net.minecraft.world.item.enchantment.Enchantment, Enchantment> { key, registry ->
val isVanilla = vanillaEnchantments.contains(key)
val eco = EcoEnchants.getByID(key.key)
if (isVanilla) {
ModifiedVanillaCraftEnchantment(key, registry)
} else if (eco != null) {
eco as Enchantment
} else {
null
}
}
// Update bukkit registry
minecraftToBukkit.set(bukkitRegistry, newRegistryMTB)
minecraftToBukkitAlt.set(bukkitRegistry, newRegistryMTB)
// Clear the enchantment cache
cache.set(bukkitRegistry, mutableMapOf<NamespacedKey, Enchantment>())
// Unfreeze NMS registry
frozenField.set(enchantmentRegistry, false)
unregisteredIntrusiveHoldersField.set(
enchantmentRegistry,
IdentityHashMap<net.minecraft.world.item.enchantment.Enchantment,
Holder.Reference<net.minecraft.world.item.enchantment.Enchantment>>()
)
}
override fun register(enchant: EcoEnchantBase): Enchantment {
// Clear the enchantment cache
cache.set(bukkitRegistry, mutableMapOf<NamespacedKey, Enchantment>())
if (enchantmentRegistry.containsKey(CraftNamespacedKey.toMinecraft(enchant.enchantmentKey))) {
val nms = enchantmentRegistry[CraftNamespacedKey.toMinecraft(enchant.enchantmentKey)]
if (nms != null) {
return EcoEnchantsCraftEnchantment(enchant, nms)
} else {
throw IllegalStateException("Enchantment ${enchant.id} wasn't registered")
}
}
val vanillaEnchantment = vanillaEcoEnchantsEnchantment(enchant)
enchantmentRegistry.createIntrusiveHolder(vanillaEnchantment)
Registry.register(
enchantmentRegistry,
ResourceLocation.withDefaultNamespace(enchant.id),
vanillaEnchantment
)
return register(enchant)
}
override fun unregister(enchant: EcoEnchant) {
/*
You can't unregister from a minecraft registry, so we simply leave the stale reference there.
This shouldn't cause many issues in production as the bukkit registry is replaced on each reload.
*/
}
}

View File

@ -0,0 +1,11 @@
package com.willfp.ecoenchants.proxy.v1_21
import com.willfp.ecoenchants.mechanics.OpenInventoryProxy
import org.bukkit.craftbukkit.entity.CraftPlayer
import org.bukkit.entity.Player
class OpenInventory : OpenInventoryProxy {
override fun getOpenInventory(player: Player): Any {
return (player as CraftPlayer).handle.containerMenu
}
}

View File

@ -0,0 +1,109 @@
package com.willfp.ecoenchants.proxy.v1_21.registration
import com.willfp.eco.util.toComponent
import com.willfp.ecoenchants.display.getFormattedName
import com.willfp.ecoenchants.enchant.EcoEnchant
import com.willfp.ecoenchants.enchant.impl.EcoEnchantBase
import net.kyori.adventure.text.Component
import net.minecraft.world.item.enchantment.Enchantment
import org.bukkit.craftbukkit.enchantments.CraftEnchantment
import org.bukkit.enchantments.EnchantmentTarget
import org.bukkit.inventory.ItemStack
class EcoEnchantsCraftEnchantment(
private val enchant: EcoEnchantBase,
nmsEnchantment: Enchantment
) : CraftEnchantment(enchant.enchantmentKey, nmsEnchantment), EcoEnchant by enchant {
init {
enchant.enchantment = this
}
override fun onRegister() {
// Fix for hardcoded enchantments
if (plugin.isLoaded) {
enchant.onRegister()
}
}
override fun onRemove() {
enchant.onRemove()
}
override fun canEnchantItem(item: ItemStack): Boolean {
return enchant.canEnchantItem(item)
}
override fun conflictsWith(other: org.bukkit.enchantments.Enchantment): Boolean {
return enchant.conflictsWith(other)
}
@Deprecated(
message = "getName is a paper Spigot API",
replaceWith = ReplaceWith("this.displayName(level)")
)
override fun translationKey(): String {
return "ecoenchants:enchantment.$id"
}
@Deprecated(
message = "getName is a legacy Spigot API",
replaceWith = ReplaceWith("this.displayName(level)")
)
override fun getName(): String = this.id.uppercase()
override fun getMaxLevel(): Int = enchant.maximumLevel
override fun getStartLevel(): Int = 1
@Deprecated(
message = "getItemTargets is an incompatible Spigot API",
replaceWith = ReplaceWith("this.targets")
)
@Suppress("DEPRECATION")
override fun getItemTarget(): EnchantmentTarget = EnchantmentTarget.ALL
@Deprecated(
message = "Treasure enchantments do not exist in EcoEnchants",
replaceWith = ReplaceWith("this.isEnchantable")
)
override fun isTreasure(): Boolean = !enchant.isObtainableThroughEnchanting
@Deprecated(
message = "Use EnchantmentType instead",
replaceWith = ReplaceWith("type.id")
)
override fun isCursed(): Boolean {
return false
}
override fun displayName(level: Int): Component {
return enchant.getFormattedName(level).toComponent()
}
override fun isTradeable(): Boolean {
return enchant.isObtainableThroughTrading
}
override fun isDiscoverable(): Boolean {
return enchant.isObtainableThroughDiscovery
}
override fun getMinModifiedCost(level: Int): Int {
return Int.MAX_VALUE
}
override fun getMaxModifiedCost(level: Int): Int {
return Int.MAX_VALUE
}
override fun equals(other: Any?): Boolean {
return other is EcoEnchant && this.enchantmentKey == other.enchantmentKey
}
override fun hashCode(): Int {
return this.enchantmentKey.hashCode()
}
override fun toString(): String {
return "EcoEnchantsCraftEnchantment(key=$key)"
}
}

View File

@ -0,0 +1,23 @@
package com.willfp.ecoenchants.proxy.v1_21.registration
import com.willfp.ecoenchants.enchant.vanillaEnchantmentData
import net.minecraft.world.item.enchantment.Enchantment
import org.bukkit.NamespacedKey
import org.bukkit.craftbukkit.enchantments.CraftEnchantment
class ModifiedVanillaCraftEnchantment(
key: NamespacedKey,
target: Enchantment
) : CraftEnchantment(key, target) {
override fun getMaxLevel(): Int = this.vanillaEnchantmentData?.maxLevel ?: super.getMaxLevel()
override fun conflictsWith(other: org.bukkit.enchantments.Enchantment): Boolean {
val otherConflicts = when (other) {
is ModifiedVanillaCraftEnchantment -> other.vanillaEnchantmentData?.conflicts?.contains(this.key) == true
else -> other.conflictsWith(this)
}
return this.vanillaEnchantmentData?.conflicts?.contains(other.key) ?: super.conflictsWith(other)
|| otherConflicts
}
}

View File

@ -0,0 +1,21 @@
package com.willfp.ecoenchants.proxy.v1_21.registration
import com.willfp.ecoenchants.enchant.EcoEnchant
import net.minecraft.core.HolderSet
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.item.enchantment.Enchantment
fun vanillaEcoEnchantsEnchantment(enchant: EcoEnchant): Enchantment {
val enchantment = Enchantment.enchantment(
Enchantment.definition(
HolderSet.empty(),
1, // 1.21 hardcodes a minimum weight of 1
enchant.maximumLevel,
Enchantment.constantCost(1),
Enchantment.constantCost(1),
0
)
)
return enchantment.build(ResourceLocation.withDefaultNamespace(enchant.id))
}

View File

@ -88,7 +88,7 @@ class EcoEnchantsPlugin : LibreforgePlugin() {
)
}
if (Prerequisite.HAS_1_20_5.isMet) {
if (Prerequisite.HAS_1_20_5.isMet && !Prerequisite.HAS_1_21.isMet) {
getProxy(CodecReplacerProxy::class.java).replaceItemCodec()
}
}
@ -96,8 +96,12 @@ class EcoEnchantsPlugin : LibreforgePlugin() {
override fun handleAfterLoad() {
isLoaded = true
if (Prerequisite.HAS_1_21.isMet) {
plugin.getProxy(ModernEnchantmentRegistererProxy::class.java).replaceRegistry()
}
// Run in afterLoad to prevent items from having their enchantments deleted
if (Prerequisite.HAS_1_20_5.isMet) {
if (Prerequisite.HAS_1_20_5.isMet && !Prerequisite.HAS_1_21.isMet) {
if (!this.configYml.getBool("enable-1-20-6")) {
Bukkit.getPluginManager().disablePlugin(this)

View File

@ -19,6 +19,8 @@ import com.willfp.ecoenchants.type.EnchantmentTypes
import com.willfp.libreforge.loader.LibreforgePlugin
import com.willfp.libreforge.loader.configs.RegistrableCategory
import org.bukkit.ChatColor
import org.bukkit.NamespacedKey
import org.bukkit.enchantments.Enchantment
@Suppress("UNUSED")
object EcoEnchants : RegistrableCategory<EcoEnchant>("enchant", "enchants") {

View File

@ -2,4 +2,4 @@
#Fri May 31 20:38:06 BST 2024
kotlin.code.style=official
libreforge-version=4.59.1
version=12.6.1
version=12.7.0

View File

@ -7,6 +7,10 @@ pluginManagement {
}
}
plugins {
id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0"
}
rootProject.name = "EcoEnchants"
// Core
@ -23,3 +27,4 @@ include(":eco-core:core-nms:v1_20_R1")
include(":eco-core:core-nms:v1_20_R2")
include(":eco-core:core-nms:v1_20_R3")
include(":eco-core:core-nms:v1_20_6")
include(":eco-core:core-nms:v1_21")