Compare commits

..

14 Commits

Author SHA1 Message Date
dependabot[bot]
5f38b59340 Bump com.github.Gypopo:EconomyShopGUI-API from 1.4.6 to 1.7.0
Bumps com.github.Gypopo:EconomyShopGUI-API from 1.4.6 to 1.7.0.

---
updated-dependencies:
- dependency-name: com.github.Gypopo:EconomyShopGUI-API
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-26 12:45:38 +00:00
Will FP
476faeec61 Fixed issues with CustomCrafting 2023-12-26 13:38:39 +01:00
Will FP
64647e3dad Merge remote-tracking branch 'origin/master'
# Conflicts:
#	gradle.properties
2023-12-26 13:34:19 +01:00
Will FP
dba640f8ee Updated to 6.68.0 2023-12-26 13:33:56 +01:00
Will FP
f52a760bbe Added yaml autosaving 2023-12-26 13:33:46 +01:00
Auxilor
c80cdf7b60 Oops 2023-12-20 12:59:59 +00:00
Auxilor
749f6229ac Updated to 6.67.3 2023-12-20 12:56:22 +00:00
Auxilor
e6318c0727 Updated DecentHOlos 2023-12-20 12:56:14 +00:00
Auxilor
989118a653 Updated IridiumSkyblock integration 2023-12-20 12:52:57 +00:00
Auxilor
6134e8de04 Fixed ESGUI circular load 2023-12-20 12:28:07 +00:00
Auxilor
5a8c2828f7 Fixed loadbefore 2023-12-20 12:23:52 +00:00
Will FP
0dba790bb2 Switched some plugins to loadbefore 2023-12-08 12:16:07 +00:00
Will FP
85991b6d7e Updated to 6.67.2 2023-12-08 12:12:44 +00:00
Will FP
ad272a2f6b Added clientside entity display name API for all versions 2023-12-08 12:12:04 +00:00
37 changed files with 657 additions and 25 deletions

View File

@@ -45,9 +45,6 @@ allprojects {
maven("https://repo.auxilor.io/repository/maven-public/")
maven("https://jitpack.io")
// CustomCrafting
maven("https://maven.wolfyscript.com/repository/public/")
// SuperiorSkyblock2
maven("https://repo.bg-software.com/repository/api/")
@@ -89,6 +86,9 @@ allprojects {
// Denizen
maven("https://maven.citizensnpcs.co/repo")
// IridiumSkyblock
maven("https://nexus.iridiumdevelopment.net/repository/maven-releases/")
}
dependencies {

View File

@@ -29,6 +29,22 @@ public interface LoadableConfig extends Config {
*/
void save() throws IOException;
/**
* Save the config asynchronously.
*/
default void saveAsync() {
// This default implementation exists purely for backwards compatibility
// with legacy Config implementations that don't have saveAsync().
// Default eco implementations of Config have saveAsync() implemented.
new Thread(() -> {
try {
this.save();
} catch (IOException e) {
e.printStackTrace();
}
}).start();
}
/**
* Get the config file.
*

View File

@@ -10,6 +10,8 @@ import java.io.IOException
import java.io.InputStreamReader
import java.io.OutputStream
import java.io.Reader
import java.nio.ByteBuffer
import java.nio.channels.AsynchronousFileChannel
import java.nio.file.Files
import java.nio.file.StandardOpenOption
@@ -74,6 +76,20 @@ open class EcoLoadableConfig(
}
}
override fun saveAsync() {
// Save asynchronously using NIO
AsynchronousFileChannel.open(
configFile.toPath(),
StandardOpenOption.WRITE,
StandardOpenOption.CREATE
).use { channel ->
channel.write(
ByteBuffer.wrap(this.toPlaintext().toByteArray()),
0
)
}
}
private fun makeHeader(contents: String) {
header.clear()

View File

@@ -1,9 +1,12 @@
package com.willfp.eco.internal.spigot.proxy.common
import com.willfp.eco.core.Prerequisite
import com.willfp.eco.core.entities.ai.EntityGoal
import com.willfp.eco.core.entities.ai.TargetGoal
import com.willfp.eco.internal.spigot.proxy.common.ai.EntityGoalFactory
import com.willfp.eco.internal.spigot.proxy.common.ai.TargetGoalFactory
import io.papermc.paper.adventure.PaperAdventure
import net.kyori.adventure.text.Component
import net.minecraft.nbt.CompoundTag
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer
@@ -68,6 +71,9 @@ fun CompoundTag.setPdc(pdc: PersistentDataContainer?, item: net.minecraft.world.
fun Player.toNMS(): ServerPlayer =
impl.toNMS(this)
fun Component.toNMS(): net.minecraft.network.chat.Component =
if (Prerequisite.HAS_PAPER.isMet) PaperAdventure.asVanilla(this) else impl.toNMS(this)
interface CommonsProvider {
val nbtTagString: Int
@@ -101,6 +107,8 @@ interface CommonsProvider {
fun toNMS(player: Player): ServerPlayer
fun toNMS(component: Component): net.minecraft.network.chat.Component
companion object {
fun setIfNeeded(provider: CommonsProvider) {
if (::impl.isInitialized) {

View File

@@ -5,6 +5,8 @@ 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.kyori.adventure.text.Component
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer
import net.minecraft.core.Registry
import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.Tag
@@ -155,5 +157,10 @@ class CommonsInitializer : CommonsInitializerProxy {
override fun toNMS(player: Player): ServerPlayer {
return (player as CraftPlayer).handle
}
override fun toNMS(component: Component): net.minecraft.network.chat.Component {
val json = GsonComponentSerializer.gson().serialize(component)
return net.minecraft.network.chat.Component.Serializer.fromJson(json)!!
}
}
}

View File

@@ -0,0 +1,83 @@
package com.willfp.eco.internal.spigot.proxy.v1_17_R1
import com.willfp.eco.core.packet.Packet
import com.willfp.eco.core.packet.sendPacket
import com.willfp.eco.internal.spigot.proxy.DisplayNameProxy
import com.willfp.eco.internal.spigot.proxy.common.toNMS
import it.unimi.dsi.fastutil.ints.Int2ObjectMap
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_17_R1.entity.CraftLivingEntity
import org.bukkit.entity.LivingEntity
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>
private val itemsByIDMapField = SynchedEntityData::class.java
.declaredFields
.filter { it.type == Int2ObjectMap::class.java }
.toList()[0]
.apply { isAccessible = true }
override fun setClientsideDisplayName(
entity: LivingEntity,
player: Player,
displayName: Component,
visible: Boolean
) {
if (entity !is CraftLivingEntity) {
return
}
val nmsComponent = displayName.toNMS()
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,
true
)
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)
}
private fun <T : Any> SynchedEntityData.hasItem(accessor: EntityDataAccessor<T>): Boolean {
val itemsByIDMap = itemsByIDMapField.get(this) as Int2ObjectMap<Any>
return itemsByIDMap.containsKey(accessor.id)
}
}

View File

@@ -5,6 +5,8 @@ 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.kyori.adventure.text.Component
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer
import net.minecraft.core.Registry
import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.Tag
@@ -155,5 +157,10 @@ class CommonsInitializer : CommonsInitializerProxy {
override fun toNMS(player: Player): ServerPlayer {
return (player as CraftPlayer).handle
}
override fun toNMS(component: Component): net.minecraft.network.chat.Component {
val json = GsonComponentSerializer.gson().serialize(component)
return net.minecraft.network.chat.Component.Serializer.fromJson(json)!!
}
}
}

View File

@@ -0,0 +1,83 @@
package com.willfp.eco.internal.spigot.proxy.v1_18_R1
import com.willfp.eco.core.packet.Packet
import com.willfp.eco.core.packet.sendPacket
import com.willfp.eco.internal.spigot.proxy.DisplayNameProxy
import com.willfp.eco.internal.spigot.proxy.common.toNMS
import it.unimi.dsi.fastutil.ints.Int2ObjectMap
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_18_R1.entity.CraftLivingEntity
import org.bukkit.entity.LivingEntity
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>
private val itemsByIDMapField = SynchedEntityData::class.java
.declaredFields
.filter { it.type == Int2ObjectMap::class.java }
.toList()[0]
.apply { isAccessible = true }
override fun setClientsideDisplayName(
entity: LivingEntity,
player: Player,
displayName: Component,
visible: Boolean
) {
if (entity !is CraftLivingEntity) {
return
}
val nmsComponent = displayName.toNMS()
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,
true
)
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)
}
private fun <T : Any> SynchedEntityData.hasItem(accessor: EntityDataAccessor<T>): Boolean {
val itemsByIDMap = itemsByIDMapField.get(this) as Int2ObjectMap<Any>
return itemsByIDMap.containsKey(accessor.id)
}
}

View File

@@ -5,6 +5,8 @@ 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.kyori.adventure.text.Component
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer
import net.minecraft.core.Registry
import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.Tag
@@ -155,5 +157,10 @@ class CommonsInitializer : CommonsInitializerProxy {
override fun toNMS(player: Player): ServerPlayer {
return (player as CraftPlayer).handle
}
override fun toNMS(component: Component): net.minecraft.network.chat.Component {
val json = GsonComponentSerializer.gson().serialize(component)
return net.minecraft.network.chat.Component.Serializer.fromJson(json)!!
}
}
}

View File

@@ -0,0 +1,83 @@
package com.willfp.eco.internal.spigot.proxy.v1_18_R2
import com.willfp.eco.core.packet.Packet
import com.willfp.eco.core.packet.sendPacket
import com.willfp.eco.internal.spigot.proxy.DisplayNameProxy
import com.willfp.eco.internal.spigot.proxy.common.toNMS
import it.unimi.dsi.fastutil.ints.Int2ObjectMap
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_18_R2.entity.CraftLivingEntity
import org.bukkit.entity.LivingEntity
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>
private val itemsByIDMapField = SynchedEntityData::class.java
.declaredFields
.filter { it.type == Int2ObjectMap::class.java }
.toList()[0]
.apply { isAccessible = true }
override fun setClientsideDisplayName(
entity: LivingEntity,
player: Player,
displayName: Component,
visible: Boolean
) {
if (entity !is CraftLivingEntity) {
return
}
val nmsComponent = displayName.toNMS()
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,
true
)
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)
}
private fun <T : Any> SynchedEntityData.hasItem(accessor: EntityDataAccessor<T>): Boolean {
val itemsByIDMap = itemsByIDMapField.get(this) as Int2ObjectMap<Any>
return itemsByIDMap.containsKey(accessor.id)
}
}

View File

@@ -5,6 +5,8 @@ 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.kyori.adventure.text.Component
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer
import net.minecraft.core.Registry
import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.Tag
@@ -155,5 +157,10 @@ class CommonsInitializer : CommonsInitializerProxy {
override fun toNMS(player: Player): ServerPlayer {
return (player as CraftPlayer).handle
}
override fun toNMS(component: Component): net.minecraft.network.chat.Component {
val json = GsonComponentSerializer.gson().serialize(component)
return net.minecraft.network.chat.Component.Serializer.fromJson(json)!!
}
}
}

View File

@@ -0,0 +1,83 @@
package com.willfp.eco.internal.spigot.proxy.v1_19_R1
import com.willfp.eco.core.packet.Packet
import com.willfp.eco.core.packet.sendPacket
import com.willfp.eco.internal.spigot.proxy.DisplayNameProxy
import com.willfp.eco.internal.spigot.proxy.common.toNMS
import it.unimi.dsi.fastutil.ints.Int2ObjectMap
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_19_R1.entity.CraftLivingEntity
import org.bukkit.entity.LivingEntity
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>
private val itemsByIDMapField = SynchedEntityData::class.java
.declaredFields
.filter { it.type == Int2ObjectMap::class.java }
.toList()[0]
.apply { isAccessible = true }
override fun setClientsideDisplayName(
entity: LivingEntity,
player: Player,
displayName: Component,
visible: Boolean
) {
if (entity !is CraftLivingEntity) {
return
}
val nmsComponent = displayName.toNMS()
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,
true
)
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)
}
private fun <T : Any> SynchedEntityData.hasItem(accessor: EntityDataAccessor<T>): Boolean {
val itemsByIDMap = itemsByIDMapField.get(this) as Int2ObjectMap<Any>
return itemsByIDMap.containsKey(accessor.id)
}
}

View File

@@ -6,6 +6,8 @@ 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 io.netty.channel.Channel
import net.kyori.adventure.text.Component
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer
import net.minecraft.core.registries.BuiltInRegistries
import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.Tag
@@ -157,5 +159,10 @@ class CommonsInitializer : CommonsInitializerProxy {
override fun toNMS(player: Player): ServerPlayer {
return (player as CraftPlayer).handle
}
override fun toNMS(component: Component): net.minecraft.network.chat.Component {
val json = GsonComponentSerializer.gson().serialize(component)
return net.minecraft.network.chat.Component.Serializer.fromJson(json)!!
}
}
}

View File

@@ -0,0 +1,82 @@
package com.willfp.eco.internal.spigot.proxy.v1_19_R2
import com.willfp.eco.core.packet.Packet
import com.willfp.eco.core.packet.sendPacket
import com.willfp.eco.internal.spigot.proxy.DisplayNameProxy
import com.willfp.eco.internal.spigot.proxy.common.toNMS
import it.unimi.dsi.fastutil.ints.Int2ObjectMap
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_19_R2.entity.CraftLivingEntity
import org.bukkit.entity.LivingEntity
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>
private val itemsByIDMapField = SynchedEntityData::class.java
.declaredFields
.filter { it.type == Int2ObjectMap::class.java }
.toList()[0]
.apply { isAccessible = true }
override fun setClientsideDisplayName(
entity: LivingEntity,
player: Player,
displayName: Component,
visible: Boolean
) {
if (entity !is CraftLivingEntity) {
return
}
val nmsComponent = displayName.toNMS()
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)
}
private fun <T : Any> SynchedEntityData.hasItem(accessor: EntityDataAccessor<T>): Boolean {
val itemsByIDMap = itemsByIDMapField.get(this) as Int2ObjectMap<Any>
return itemsByIDMap.containsKey(accessor.id)
}
}

View File

@@ -5,6 +5,8 @@ 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.kyori.adventure.text.Component
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer
import net.minecraft.core.registries.BuiltInRegistries
import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.Tag
@@ -155,5 +157,10 @@ class CommonsInitializer : CommonsInitializerProxy {
override fun toNMS(player: Player): ServerPlayer {
return (player as CraftPlayer).handle
}
override fun toNMS(component: Component): net.minecraft.network.chat.Component {
val json = GsonComponentSerializer.gson().serialize(component)
return net.minecraft.network.chat.Component.Serializer.fromJson(json)!!
}
}
}

View File

@@ -0,0 +1,82 @@
package com.willfp.eco.internal.spigot.proxy.v1_19_R3
import com.willfp.eco.core.packet.Packet
import com.willfp.eco.core.packet.sendPacket
import com.willfp.eco.internal.spigot.proxy.DisplayNameProxy
import com.willfp.eco.internal.spigot.proxy.common.toNMS
import it.unimi.dsi.fastutil.ints.Int2ObjectMap
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_19_R3.entity.CraftLivingEntity
import org.bukkit.entity.LivingEntity
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>
private val itemsByIDMapField = SynchedEntityData::class.java
.declaredFields
.filter { it.type == Int2ObjectMap::class.java }
.toList()[0]
.apply { isAccessible = true }
override fun setClientsideDisplayName(
entity: LivingEntity,
player: Player,
displayName: Component,
visible: Boolean
) {
if (entity !is CraftLivingEntity) {
return
}
val nmsComponent = displayName.toNMS()
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)
}
private fun <T : Any> SynchedEntityData.hasItem(accessor: EntityDataAccessor<T>): Boolean {
val itemsByIDMap = itemsByIDMapField.get(this) as Int2ObjectMap<Any>
return itemsByIDMap.containsKey(accessor.id)
}
}

View File

@@ -5,6 +5,8 @@ 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.kyori.adventure.text.Component
import net.kyori.adventure.text.serializer.json.JSONComponentSerializer
import net.minecraft.core.registries.BuiltInRegistries
import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.Tag
@@ -155,5 +157,10 @@ class CommonsInitializer : CommonsInitializerProxy {
override fun toNMS(player: Player): ServerPlayer {
return (player as CraftPlayer).handle
}
override fun toNMS(component: Component): net.minecraft.network.chat.Component {
val json = JSONComponentSerializer.json().serialize(component)
return net.minecraft.network.chat.Component.Serializer.fromJson(json)!!
}
}
}

View File

@@ -3,6 +3,7 @@ package com.willfp.eco.internal.spigot.proxy.v1_20_R1
import com.willfp.eco.core.packet.Packet
import com.willfp.eco.core.packet.sendPacket
import com.willfp.eco.internal.spigot.proxy.DisplayNameProxy
import com.willfp.eco.internal.spigot.proxy.common.toNMS
import io.papermc.paper.adventure.PaperAdventure
import net.kyori.adventure.text.Component
import net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket
@@ -40,8 +41,7 @@ class DisplayName : DisplayNameProxy {
return
}
val nmsComponent = PaperAdventure.asVanilla(displayName)
?: throw IllegalStateException("Display name component is null!")
val nmsComponent = displayName.toNMS()
val nmsEntity = entity.handle
nmsEntity.isCustomNameVisible

View File

@@ -5,6 +5,8 @@ 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.kyori.adventure.text.Component
import net.kyori.adventure.text.serializer.json.JSONComponentSerializer
import net.minecraft.core.registries.BuiltInRegistries
import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.Tag
@@ -155,5 +157,10 @@ class CommonsInitializer : CommonsInitializerProxy {
override fun toNMS(player: Player): ServerPlayer {
return (player as CraftPlayer).handle
}
override fun toNMS(component: Component): net.minecraft.network.chat.Component {
val json = JSONComponentSerializer.json().serialize(component)
return net.minecraft.network.chat.Component.Serializer.fromJson(json)!!
}
}
}

View File

@@ -3,6 +3,7 @@ package com.willfp.eco.internal.spigot.proxy.v1_20_R2
import com.willfp.eco.core.packet.Packet
import com.willfp.eco.core.packet.sendPacket
import com.willfp.eco.internal.spigot.proxy.DisplayNameProxy
import com.willfp.eco.internal.spigot.proxy.common.toNMS
import io.papermc.paper.adventure.PaperAdventure
import net.kyori.adventure.text.Component
import net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket
@@ -37,8 +38,7 @@ class DisplayName : DisplayNameProxy {
return
}
val nmsComponent = PaperAdventure.asVanilla(displayName)
?: throw IllegalStateException("Display name component is null!")
val nmsComponent = displayName.toNMS()
val nmsEntity = entity.handle
nmsEntity.isCustomNameVisible

View File

@@ -5,6 +5,8 @@ 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.kyori.adventure.text.Component
import net.kyori.adventure.text.serializer.json.JSONComponentSerializer
import net.minecraft.core.registries.BuiltInRegistries
import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.Tag
@@ -155,5 +157,10 @@ class CommonsInitializer : CommonsInitializerProxy {
override fun toNMS(player: Player): ServerPlayer {
return (player as CraftPlayer).handle
}
override fun toNMS(component: Component): net.minecraft.network.chat.Component {
val json = JSONComponentSerializer.json().serialize(component)
return net.minecraft.network.chat.Component.Serializer.fromJson(json)!!
}
}
}

View File

@@ -3,6 +3,7 @@ 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 com.willfp.eco.internal.spigot.proxy.common.toNMS
import io.papermc.paper.adventure.PaperAdventure
import net.kyori.adventure.text.Component
import net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket
@@ -37,8 +38,7 @@ class DisplayName : DisplayNameProxy {
return
}
val nmsComponent = PaperAdventure.asVanilla(displayName)
?: throw IllegalStateException("Display name component is null!")
val nmsComponent = displayName.toNMS()
val nmsEntity = entity.handle
nmsEntity.isCustomNameVisible

View File

@@ -48,9 +48,8 @@ dependencies {
compileOnly("com.bgsoftware:SuperiorSkyblockAPI:1.8.3")
compileOnly("com.github.MilkBowl:VaultAPI:1.7")
compileOnly("com.github.WhipDevelopment:CrashClaim:f9cd7d92eb")
compileOnly("com.wolfyscript.wolfyutilities:wolfyutilities:3.16.0.0")
compileOnly("com.github.decentsoftware-eu:decentholograms:2.1.2")
compileOnly("com.github.Gypopo:EconomyShopGUI-API:1.4.6")
compileOnly("com.github.decentsoftware-eu:decentholograms:2.8.5")
compileOnly("com.github.Gypopo:EconomyShopGUI-API:1.7.0")
compileOnly("com.github.N0RSKA:ScytherAPI:55a")
compileOnly("org.black_ixx:playerpoints:3.2.5")
compileOnly("com.github.Ssomar-Developement:SCore:3.4.7")
@@ -62,6 +61,7 @@ dependencies {
compileOnly("com.denizenscript:denizen:1.2.7-SNAPSHOT") {
exclude(group = "*", module = "*")
}
compileOnly("com.iridium:IridiumSkyblock:4.0.8")
compileOnly(fileTree("../../lib") {
include("*.jar")

View File

@@ -352,7 +352,5 @@ class EcoImpl : EcoSpigotPlugin(), Eco {
placeholderParser.getPlaceholderResult(plugin, args, context)
override fun setClientsideDisplayName(entity: LivingEntity, player: Player, name: Component, visible: Boolean) =
if (Prerequisite.HAS_PAPER.isMet && Prerequisite.HAS_1_20.isMet)
this.getProxy(DisplayNameProxy::class.java).setClientsideDisplayName(entity, player, name, visible)
else Unit
this.getProxy(DisplayNameProxy::class.java).setClientsideDisplayName(entity, player, name, visible)
}

View File

@@ -261,6 +261,8 @@ abstract class EcoSpigotPlugin : EcoPlugin() {
profileHandler.migrateIfNeeded()
}
profileHandler.startAutosaving()
ProfileSaver(this, profileHandler).startTicking()
this.scheduler.runTimer(

View File

@@ -169,4 +169,17 @@ class ProfileHandler(
localHandler.initialize()
}
}
fun startAutosaving() {
if (!plugin.configYml.getBool("yaml.autosave")) {
return
}
val interval = plugin.configYml.getInt("yaml.autosave-interval") * 20L
plugin.scheduler.runTimer(20, interval) {
handler.saveAsync()
localHandler.saveAsync()
}
}
}

View File

@@ -27,6 +27,10 @@ abstract class DataHandler(
}
open fun saveAsync() {
}
open fun initialize() {
}

View File

@@ -18,6 +18,10 @@ class YamlDataHandler(
dataYml.save()
}
override fun saveAsync() {
dataYml.saveAsync()
}
override fun <T : Any> read(uuid: UUID, key: PersistentDataKey<T>): T? {
// Separate `as T?` for each branch to prevent compiler warnings.
val value = when (key.type) {

View File

@@ -1,7 +1,7 @@
package com.willfp.eco.internal.spigot.integrations.antigrief
import com.iridium.iridiumskyblock.PermissionType
import com.iridium.iridiumskyblock.api.IridiumSkyblockAPI
import com.iridium.iridiumteams.PermissionType
import com.willfp.eco.core.integrations.antigrief.AntigriefIntegration
import org.bukkit.Location
import org.bukkit.block.Block
@@ -49,8 +49,13 @@ class AntigriefIridiumSkyblock : AntigriefIntegration {
}
override fun canPickupItem(player: Player, location: Location): Boolean {
return true
/*
val api = IridiumSkyblockAPI.getInstance()
return api.getIslandPermission(api.getIslandViaLocation(location).orElse(null) ?: return true, api.getUser(player), PermissionType.PICKUP_ITEMS)
PICKUP_ITEMS was removed in Iridium v4
*/
}
override fun getPluginName(): String {

View File

@@ -7,7 +7,7 @@ import org.bukkit.Location
import java.util.UUID
class HologramDecentHolograms : HologramIntegration {
override fun createHologram(location: Location, contents: MutableList<String>): Hologram {
override fun createHologram(location: Location, contents: List<String>): Hologram {
val id = UUID.randomUUID().toString()
DHAPI.createHologram(id, location, contents)
@@ -26,8 +26,8 @@ class HologramDecentHolograms : HologramIntegration {
DHAPI.getHologram(id)?.destroy()
}
override fun setContents(contents: MutableList<String>) {
override fun setContents(contents: List<String>) {
DHAPI.setHologramLines(DHAPI.getHologram(id), contents)
}
}
}
}

View File

@@ -30,6 +30,10 @@ mysql:
user: username
password: passy
yaml:
autosave: true # If data should be saved automatically
autosave-interval: 1800 # How often data should be saved (in seconds)
# How many ticks to wait between committing data to a database. This doesn't
# affect yaml storage, only MySQL and MongoDB. By default, data is committed
# every tick, but you can increase this to be every x ticks, for example 20

View File

@@ -5,18 +5,24 @@ api-version: 1.17
authors: [ Auxilor ]
website: willfp.com
load: STARTUP
# Fixes some plugins breaking load order
loadbefore:
- Spartan
- CustomCrafting
- Lands
- EconomyShopGUI
- EconomyShopGUI-Premium
softdepend:
- ProtocolLib
- WorldGuard
- GriefPrevention
- Towny
- FactionsUUID
- Lands
- Kingdoms
- NoCheatPlus
- AAC
- Matrix
- Spartan
- Vulcan
- PlaceholderAPI
- mcMMO
@@ -40,11 +46,8 @@ softdepend:
- CrashClaim
- DecentHolograms
- MythicMobs
- CustomCrafting
- ExecutableItems
- RPGHorses
- EconomyShopGUI
- EconomyShopGUI-Premium
- zShop
- DeluxeSellwands
- Scyther

View File

@@ -1,2 +1,2 @@
version = 6.67.1
version = 6.68.0
kotlin.incremental.useClasspathSnapshot=false

Binary file not shown.

Binary file not shown.

Binary file not shown.