Skip to content

Commit

Permalink
Added 1.20.3 support
Browse files Browse the repository at this point in the history
  • Loading branch information
WillFP committed Dec 7, 2023
1 parent 9ad12c2 commit 8d2d615
Show file tree
Hide file tree
Showing 20 changed files with 691 additions and 3 deletions.
3 changes: 2 additions & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ dependencies {
implementation(project(path = ":eco-core:core-nms:v1_19_R3", configuration = "reobf"))
implementation(project(path = ":eco-core:core-nms:v1_20_R1", configuration = "reobf"))
implementation(project(path = ":eco-core:core-nms:v1_20_R2", configuration = "reobf"))
implementation(project(path = ":eco-core:core-nms:v1_20_R3", configuration = "reobf"))
}

allprojects {
Expand All @@ -41,8 +42,8 @@ allprojects {
repositories {
mavenCentral()
mavenLocal()
maven("https://jitpack.io")
maven("https://repo.auxilor.io/repository/maven-public/")
maven("https://jitpack.io")

// CustomCrafting
maven("https://maven.wolfyscript.com/repository/public/")
Expand Down
8 changes: 8 additions & 0 deletions eco-api/src/main/java/com/willfp/eco/core/Prerequisite.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,14 @@ public class Prerequisite {
"Requires server to have ProtocolLib"
);

/**
* Requires the server to be running 1.20.3.
*/
public static final Prerequisite HAS_1_20_3 = new Prerequisite(
() -> ProxyConstants.NMS_VERSION.contains("20_R3"),
"Requires server to be running 1.20.3+"
);

/**
* Requires the server to be running 1.20.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ public final class ProxyConstants {
"v1_19_R2",
"v1_19_R3",
"v1_20_R1",
"v1_20_R2"
"v1_20_R2",
"v1_20_R3"
);

private ProxyConstants() {
Expand Down
39 changes: 39 additions & 0 deletions eco-core/core-nms/v1_20_R3/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
plugins {
id("io.papermc.paperweight.userdev")
}

group = "com.willfp"
version = rootProject.version

dependencies {
implementation(project(":eco-core:core-nms:nms-common"))
paperweight.paperDevBundle("1.20.3-R0.1-SNAPSHOT")

implementation("net.kyori:adventure-text-minimessage:4.11.0") {
version {
strictly("4.11.0")
}
exclude(group = "net.kyori", module = "adventure-api")
}
}

tasks {
build {
dependsOn(reobfJar)
}

reobfJar {
mustRunAfter(shadowJar)
}

shadowJar {
relocate(
"com.willfp.eco.internal.spigot.proxy.common",
"com.willfp.eco.internal.spigot.proxy.v1_20_R3.common"
)
relocate(
"net.kyori.adventure.text.minimessage",
"com.willfp.eco.internal.spigot.proxy.v1_20_R3.minimessage"
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.willfp.eco.internal.spigot.proxy.v1_20_R3

import com.willfp.eco.core.command.PluginCommandBase
import com.willfp.eco.internal.spigot.proxy.BukkitCommandsProxy
import org.bukkit.Bukkit
import org.bukkit.command.Command
import org.bukkit.command.SimpleCommandMap
import org.bukkit.craftbukkit.v1_20_R3.CraftServer
import java.lang.reflect.Field

class BukkitCommands : BukkitCommandsProxy {
private val knownCommandsField: Field by lazy {
SimpleCommandMap::class.java.getDeclaredField("knownCommands")
.apply {
isAccessible = true
}
}

@Suppress("UNCHECKED_CAST")
private val knownCommands: MutableMap<String, Command>
get() = knownCommandsField.get(getCommandMap()) as MutableMap<String, Command>

override fun getCommandMap(): SimpleCommandMap {
return (Bukkit.getServer() as CraftServer).commandMap
}

override fun syncCommands() {
(Bukkit.getServer() as CraftServer).syncCommands()
}

override fun unregisterCommand(command: PluginCommandBase) {
knownCommands.remove(command.name)
knownCommands.remove("${command.plugin.name.lowercase()}:${command.name}")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
package com.willfp.eco.internal.spigot.proxy.v1_20_R3

import com.willfp.eco.core.EcoPlugin
import com.willfp.eco.internal.spigot.proxy.CommonsInitializerProxy
import com.willfp.eco.internal.spigot.proxy.common.CommonsProvider
import com.willfp.eco.internal.spigot.proxy.common.packet.PacketInjectorListener
import com.willfp.eco.internal.spigot.proxy.common.toResourceLocation
import net.minecraft.core.registries.BuiltInRegistries
import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.Tag
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.entity.PathfinderMob
import net.minecraft.world.item.Item
import org.bukkit.Bukkit
import org.bukkit.Material
import org.bukkit.NamespacedKey
import org.bukkit.craftbukkit.v1_20_R3.CraftServer
import org.bukkit.craftbukkit.v1_20_R3.entity.CraftEntity
import org.bukkit.craftbukkit.v1_20_R3.entity.CraftMob
import org.bukkit.craftbukkit.v1_20_R3.entity.CraftPlayer
import org.bukkit.craftbukkit.v1_20_R3.inventory.CraftItemStack
import org.bukkit.craftbukkit.v1_20_R3.persistence.CraftPersistentDataContainer
import org.bukkit.craftbukkit.v1_20_R3.persistence.CraftPersistentDataTypeRegistry
import org.bukkit.craftbukkit.v1_20_R3.util.CraftMagicNumbers
import org.bukkit.craftbukkit.v1_20_R3.util.CraftNamespacedKey
import org.bukkit.entity.LivingEntity
import org.bukkit.entity.Mob
import org.bukkit.entity.Player
import org.bukkit.inventory.ItemStack
import org.bukkit.persistence.PersistentDataContainer
import java.lang.reflect.Field

class CommonsInitializer : CommonsInitializerProxy {
override fun init(plugin: EcoPlugin) {
CommonsProvider.setIfNeeded(CommonsProviderImpl)
plugin.onEnable {
plugin.eventManager.registerListener(PacketInjectorListener)
}
}

object CommonsProviderImpl : CommonsProvider {
private val cisHandle: Field = CraftItemStack::class.java.getDeclaredField("handle").apply {
isAccessible = true
}

private val pdcRegsitry = Class.forName("org.bukkit.craftbukkit.v1_20_R3.inventory.CraftMetaItem")
.getDeclaredField("DATA_TYPE_REGISTRY")
.apply { isAccessible = true }
.get(null) as CraftPersistentDataTypeRegistry

override val nbtTagString = CraftMagicNumbers.NBT.TAG_STRING

override fun toPathfinderMob(mob: Mob): PathfinderMob? {
val craft = mob as? CraftMob ?: return null
return craft.handle as? PathfinderMob
}

override fun toResourceLocation(namespacedKey: NamespacedKey): ResourceLocation =
CraftNamespacedKey.toMinecraft(namespacedKey)

override fun asNMSStack(itemStack: ItemStack): net.minecraft.world.item.ItemStack {
return if (itemStack !is CraftItemStack) {
CraftItemStack.asNMSCopy(itemStack)
} else {
cisHandle[itemStack] as net.minecraft.world.item.ItemStack? ?: CraftItemStack.asNMSCopy(itemStack)
}
}

override fun asBukkitStack(itemStack: net.minecraft.world.item.ItemStack): ItemStack {
return CraftItemStack.asCraftMirror(itemStack)
}

override fun mergeIfNeeded(itemStack: ItemStack, nmsStack: net.minecraft.world.item.ItemStack) {
if (itemStack !is CraftItemStack) {
itemStack.itemMeta = CraftItemStack.asCraftMirror(nmsStack).itemMeta
}
}

override fun toBukkitEntity(entity: net.minecraft.world.entity.LivingEntity): LivingEntity? =
CraftEntity.getEntity(Bukkit.getServer() as CraftServer, entity) as? LivingEntity

override fun makePdc(tag: CompoundTag, base: Boolean): PersistentDataContainer {
fun emptyPdc(): CraftPersistentDataContainer = CraftPersistentDataContainer(pdcRegsitry)

fun CompoundTag?.toPdc(): PersistentDataContainer {
val pdc = emptyPdc()
this ?: return pdc
val keys = this.allKeys
for (key in keys) {
pdc.put(key, this[key])
}

return pdc
}

return if (base) {
tag.toPdc()
} else {
if (tag.contains("PublicBukkitValues")) {
tag.getCompound("PublicBukkitValues").toPdc()
} else {
emptyPdc()
}
}
}

override fun setPdc(
tag: CompoundTag,
pdc: PersistentDataContainer?,
item: net.minecraft.world.item.ItemStack?
) {
fun CraftPersistentDataContainer.toTag(): CompoundTag {
val compound = CompoundTag()
val rawPublicMap: Map<String, Tag> = this.raw
for ((key, value) in rawPublicMap) {
compound.put(key, value)
}

return compound
}

val container = when (pdc) {
is CraftPersistentDataContainer? -> pdc
else -> null
}

if (item != null) {
if (container != null && !container.isEmpty) {
for (key in tag.allKeys.toSet()) {
tag.remove(key)
}

tag.merge(container.toTag())
} else {
item.tag = null
}
} else {
if (container != null && !container.isEmpty) {
tag.put("PublicBukkitValues", container.toTag())
} else {
tag.remove("PublicBukkitValues")
}
}
}

override fun materialToItem(material: Material): Item =
BuiltInRegistries.ITEM.getOptional(material.key.toResourceLocation())
.orElseThrow { IllegalArgumentException("Material is not item!") }

override fun itemToMaterial(item: Item) =
Material.getMaterial(BuiltInRegistries.ITEM.getKey(item).path.uppercase())
?: throw IllegalArgumentException("Invalid material!")

override fun toNMS(player: Player): ServerPlayer {
return (player as CraftPlayer).handle
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package com.willfp.eco.internal.spigot.proxy.v1_20_R3

import com.willfp.eco.core.packet.Packet
import com.willfp.eco.core.packet.sendPacket
import com.willfp.eco.internal.spigot.proxy.DisplayNameProxy
import io.papermc.paper.adventure.PaperAdventure
import net.kyori.adventure.text.Component
import net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket
import net.minecraft.network.syncher.EntityDataAccessor
import net.minecraft.network.syncher.SynchedEntityData
import net.minecraft.world.entity.Entity
import org.bukkit.craftbukkit.v1_20_R3.entity.CraftLivingEntity
import org.bukkit.craftbukkit.v1_20_R3.entity.CraftMob
import org.bukkit.entity.LivingEntity
import org.bukkit.entity.Mob
import org.bukkit.entity.Player
import java.util.Optional

@Suppress("UNCHECKED_CAST")
class DisplayName : DisplayNameProxy {
private val displayNameAccessor = Entity::class.java
.declaredFields
.filter { it.type == EntityDataAccessor::class.java }
.toList()[2]
.apply { isAccessible = true }
.get(null) as EntityDataAccessor<Optional<net.minecraft.network.chat.Component>>

private val customNameVisibleAccessor = Entity::class.java
.declaredFields
.filter { it.type == EntityDataAccessor::class.java }
.toList()[3]
.apply { isAccessible = true }
.get(null) as EntityDataAccessor<Boolean>

override fun setClientsideDisplayName(entity: LivingEntity, player: Player, displayName: Component, visible: Boolean) {
if (entity !is CraftLivingEntity) {
return
}

val nmsComponent = PaperAdventure.asVanilla(displayName)
?: throw IllegalStateException("Display name component is null!")

val nmsEntity = entity.handle
nmsEntity.isCustomNameVisible
val entityData = SynchedEntityData(nmsEntity)

entityData.forceSet(displayNameAccessor, Optional.of(nmsComponent))
entityData.forceSet(customNameVisibleAccessor, visible)

val packet = ClientboundSetEntityDataPacket(
nmsEntity.id,
entityData.packDirty() ?: throw IllegalStateException("No packed entity data")
)

player.sendPacket(Packet(packet))
}

private fun <T: Any> SynchedEntityData.forceSet(
accessor: EntityDataAccessor<T>,
value: T
) {
if (!this.hasItem(accessor)) {
this.define(accessor, value)
}
this[accessor] = value
this.markDirty(accessor)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.willfp.eco.internal.spigot.proxy.v1_20_R3

import com.willfp.eco.internal.entities.EcoDummyEntity
import com.willfp.eco.internal.spigot.proxy.DummyEntityFactoryProxy
import org.bukkit.Location
import org.bukkit.craftbukkit.v1_20_R3.CraftWorld
import org.bukkit.entity.Entity
import org.bukkit.entity.EntityType
import org.bukkit.entity.Zombie

class DummyEntityFactory : DummyEntityFactoryProxy {
override fun createDummyEntity(location: Location): Entity {
val world = location.world as CraftWorld
return EcoDummyEntity(world.createEntity(location, Zombie::class.java))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.willfp.eco.internal.spigot.proxy.v1_20_R3

import com.willfp.eco.core.entities.ai.EntityController
import com.willfp.eco.internal.spigot.proxy.EntityControllerFactoryProxy
import com.willfp.eco.internal.spigot.proxy.v1_20_R3.entity.EcoEntityController
import org.bukkit.entity.Mob

class EntityControllerFactory : EntityControllerFactoryProxy {
override fun <T : Mob> createEntityController(entity: T): EntityController<T> {
return EcoEntityController(entity)
}
}
Loading

0 comments on commit 8d2d615

Please sign in to comment.