diff --git a/src/main/kotlin/net/axay/kspigot/commands/Arguments.kt b/src/main/kotlin/net/axay/kspigot/commands/Arguments.kt index eb2cec24..33577a3a 100644 --- a/src/main/kotlin/net/axay/kspigot/commands/Arguments.kt +++ b/src/main/kotlin/net/axay/kspigot/commands/Arguments.kt @@ -5,7 +5,7 @@ import com.mojang.brigadier.builder.ArgumentBuilder import com.mojang.brigadier.builder.RequiredArgumentBuilder import com.mojang.brigadier.context.CommandContext import net.axay.kspigot.commands.internal.ArgumentTypeUtils -import net.axay.kspigot.commands.internal.ServerCommandSource +import net.minecraft.commands.CommandSourceStack /** * Adds an argument. @@ -13,12 +13,12 @@ import net.axay.kspigot.commands.internal.ServerCommandSource * @param name the name of the argument * @param type the type of the argument - e.g. IntegerArgumentType.integer() or StringArgumentType.string() */ -inline fun ArgumentBuilder.argument( +inline fun ArgumentBuilder.argument( name: String, type: ArgumentType, - builder: RequiredArgumentBuilder.() -> Unit = {} -): RequiredArgumentBuilder = - RequiredArgumentBuilder.argument(name, type).apply(builder).also { then(it) } + builder: RequiredArgumentBuilder.() -> Unit = {} +): RequiredArgumentBuilder = + RequiredArgumentBuilder.argument(name, type).apply(builder).also { then(it) } /** * Adds an argument. The argument type will be resolved via the reified @@ -27,14 +27,14 @@ inline fun ArgumentBuilder.argument( * @param name the name of the argument */ @Suppress("UNCHECKED_CAST") -inline fun ArgumentBuilder.argument( +inline fun ArgumentBuilder.argument( name: String, - builder: RequiredArgumentBuilder.() -> Unit = {} -): RequiredArgumentBuilder = - RequiredArgumentBuilder.argument(name, ArgumentTypeUtils.fromReifiedType()).apply(builder).also { then(it) } + builder: RequiredArgumentBuilder.() -> Unit = {} +): RequiredArgumentBuilder = + RequiredArgumentBuilder.argument(name, ArgumentTypeUtils.fromReifiedType()).apply(builder).also { then(it) } /** * Get the value of this argument. */ -inline fun CommandContext.getArgument(name: String): T = +inline fun CommandContext.getArgument(name: String): T = getArgument(name, T::class.java) diff --git a/src/main/kotlin/net/axay/kspigot/commands/CommandContext.kt b/src/main/kotlin/net/axay/kspigot/commands/CommandContext.kt index 322ec3f0..223b220d 100644 --- a/src/main/kotlin/net/axay/kspigot/commands/CommandContext.kt +++ b/src/main/kotlin/net/axay/kspigot/commands/CommandContext.kt @@ -1,19 +1,13 @@ package net.axay.kspigot.commands import com.mojang.brigadier.context.CommandContext -import com.mojang.brigadier.exceptions.SimpleCommandExceptionType -import net.axay.kspigot.commands.internal.ServerCommandSource -import net.minecraft.network.chat.ChatMessage +import net.minecraft.commands.CommandSourceStack import org.bukkit.Location import org.bukkit.Server import org.bukkit.World import org.bukkit.entity.Player -class CommandContext(val nmsContext: CommandContext) { - companion object { - private val REQUIRES_PLAYER_EXCEPTION = SimpleCommandExceptionType(ChatMessage("permissions.requires.player")) - } - +class CommandContext(val nmsContext: CommandContext) { /** * Get the value of the given argument. */ @@ -23,13 +17,13 @@ class CommandContext(val nmsContext: CommandContext) { /** * The source / sender which executed this command. */ - val sender get() = nmsContext.source.bukkitSender + val sender: CommandSourceStack get() = nmsContext.source /** * Validates that this command was executes by a player (sends an error message to the sender if this is not the case) * and returns the [Player]. */ - val player get() = nmsContext.source.bukkitSender as? Player ?: throw REQUIRES_PLAYER_EXCEPTION.create() + val player: Player get() = nmsContext.source.bukkitSender as? Player ?: throw CommandSourceStack.ERROR_NOT_PLAYER.create() /** * The world where the source of this command currently is in. @@ -38,17 +32,17 @@ class CommandContext(val nmsContext: CommandContext) { * these cases are rare (e.g. command called by a datapack function), therefore * this property is not nullable for convenience */ - val world get() = nmsContext.source.world.world as World + val world: World get() = nmsContext.source.bukkitWorld!! /** * The position of the source of this command. */ - val position get() = with(nmsContext.source.position) { - Location(nmsContext.source.world.world as? World?, x, y, z) + val position: Location get() = with(nmsContext.source.position) { + Location(nmsContext.source.bukkitWorld, x, y, z) } /** * The current server instance. */ - val server get() = nmsContext.source.server.server as Server + val server: Server get() = nmsContext.source.server.server as Server } diff --git a/src/main/kotlin/net/axay/kspigot/commands/Creation.kt b/src/main/kotlin/net/axay/kspigot/commands/Creation.kt index 2cd8cb63..1c08b84f 100644 --- a/src/main/kotlin/net/axay/kspigot/commands/Creation.kt +++ b/src/main/kotlin/net/axay/kspigot/commands/Creation.kt @@ -3,7 +3,7 @@ package net.axay.kspigot.commands import com.mojang.brigadier.builder.ArgumentBuilder import com.mojang.brigadier.builder.LiteralArgumentBuilder import net.axay.kspigot.commands.internal.BrigardierSupport -import net.axay.kspigot.commands.internal.ServerCommandSource +import net.minecraft.commands.CommandSourceStack /** * Creates a new command. @@ -14,9 +14,9 @@ import net.axay.kspigot.commands.internal.ServerCommandSource inline fun command( name: String, register: Boolean = true, - builder: LiteralArgumentBuilder.() -> Unit -): LiteralArgumentBuilder = - LiteralArgumentBuilder.literal(name).apply(builder).apply { + builder: LiteralArgumentBuilder.() -> Unit +): LiteralArgumentBuilder = + LiteralArgumentBuilder.literal(name).apply(builder).apply { if (register) BrigardierSupport.commands += this } @@ -26,7 +26,7 @@ inline fun command( * * @param name the name of the literal */ -inline fun ArgumentBuilder.literal( +inline fun ArgumentBuilder.literal( name: String, - builder: LiteralArgumentBuilder.() -> Unit = {} + builder: LiteralArgumentBuilder.() -> Unit = {} ) = command(name, false, builder).also { then(it) } diff --git a/src/main/kotlin/net/axay/kspigot/commands/Execution.kt b/src/main/kotlin/net/axay/kspigot/commands/Execution.kt index a3c6ac11..cf56d6e2 100644 --- a/src/main/kotlin/net/axay/kspigot/commands/Execution.kt +++ b/src/main/kotlin/net/axay/kspigot/commands/Execution.kt @@ -2,7 +2,7 @@ package net.axay.kspigot.commands import com.mojang.brigadier.Command import com.mojang.brigadier.builder.ArgumentBuilder -import net.axay.kspigot.commands.internal.ServerCommandSource +import net.minecraft.commands.CommandSourceStack /** * Adds execution logic to this command. The place where this function @@ -11,7 +11,7 @@ import net.axay.kspigot.commands.internal.ServerCommandSource * * @see com.mojang.brigadier.builder.ArgumentBuilder.executes */ -inline infix fun ArgumentBuilder.runs( +inline infix fun ArgumentBuilder.runs( crossinline executor: CommandContext.() -> Unit, ) = this.apply { executes wrapped@{ @@ -39,6 +39,6 @@ infix fun ArgumentBuilder.runs(executor: Command) = "The name 'simpleExecutes' has been superseded by 'runs'.", ReplaceWith("runs { executor.invoke() }") ) -inline infix fun ArgumentBuilder.simpleExecutes( +inline infix fun ArgumentBuilder.simpleExecutes( crossinline executor: CommandContext.() -> Unit, ) = runs(executor) diff --git a/src/main/kotlin/net/axay/kspigot/commands/Registration.kt b/src/main/kotlin/net/axay/kspigot/commands/Registration.kt index 36c78d80..dfd4772f 100644 --- a/src/main/kotlin/net/axay/kspigot/commands/Registration.kt +++ b/src/main/kotlin/net/axay/kspigot/commands/Registration.kt @@ -4,7 +4,7 @@ import com.mojang.brigadier.CommandDispatcher import com.mojang.brigadier.builder.LiteralArgumentBuilder import net.axay.kspigot.annotations.NMS_General import net.axay.kspigot.commands.internal.BrigardierSupport -import net.minecraft.commands.CommandListenerWrapper +import net.minecraft.commands.CommandSourceStack /** * Registers this command at the [CommandDispatcher] of the server. @@ -14,11 +14,11 @@ import net.minecraft.commands.CommandListenerWrapper * calling this function as the server is starting */ @NMS_General -fun LiteralArgumentBuilder.register(sendToPlayers: Boolean = true) { +fun LiteralArgumentBuilder.register(sendToPlayers: Boolean = true) { if (!BrigardierSupport.executedDefaultRegistration) BrigardierSupport.commands += this else { - BrigardierSupport.commandDispatcher.register(this) + BrigardierSupport.resolveCommandManager().dispatcher.register(this) if (sendToPlayers) BrigardierSupport.updateCommandTree() } diff --git a/src/main/kotlin/net/axay/kspigot/commands/Requires.kt b/src/main/kotlin/net/axay/kspigot/commands/Requires.kt index 8666bbd2..dc284670 100644 --- a/src/main/kotlin/net/axay/kspigot/commands/Requires.kt +++ b/src/main/kotlin/net/axay/kspigot/commands/Requires.kt @@ -1,14 +1,14 @@ package net.axay.kspigot.commands import com.mojang.brigadier.builder.ArgumentBuilder -import net.axay.kspigot.commands.internal.ServerCommandSource +import net.minecraft.commands.CommandSourceStack import org.bukkit.permissions.Permission /** * Defines that the given [permission] is required to interact with this * path of the command. */ -fun ArgumentBuilder.requiresPermission(permission: String): ArgumentBuilder<*, *> = +fun ArgumentBuilder.requiresPermission(permission: String): ArgumentBuilder<*, *> = requires { it.bukkitSender.hasPermission(permission) } @@ -17,7 +17,7 @@ fun ArgumentBuilder.requiresPermission(permission: Strin * Defines that the given [permission] is required to interact with this * path of the command. */ -fun ArgumentBuilder.requiresPermission(permission: Permission): ArgumentBuilder<*, *> = +fun ArgumentBuilder.requiresPermission(permission: Permission): ArgumentBuilder<*, *> = requires { it.bukkitSender.hasPermission(permission) } diff --git a/src/main/kotlin/net/axay/kspigot/commands/internal/BrigardierSupport.kt b/src/main/kotlin/net/axay/kspigot/commands/internal/BrigardierSupport.kt index f8f93348..f4a01162 100644 --- a/src/main/kotlin/net/axay/kspigot/commands/internal/BrigardierSupport.kt +++ b/src/main/kotlin/net/axay/kspigot/commands/internal/BrigardierSupport.kt @@ -2,20 +2,14 @@ package net.axay.kspigot.commands.internal -import com.mojang.brigadier.CommandDispatcher import com.mojang.brigadier.builder.LiteralArgumentBuilder -import net.axay.kspigot.annotations.NMS_1_17 -import net.axay.kspigot.annotations.NMS_General import net.axay.kspigot.event.listen import net.axay.kspigot.extensions.onlinePlayers import net.axay.kspigot.extensions.server import net.axay.kspigot.main.KSpigotMainInstance -import net.axay.kspigot.utils.reflectField -import net.minecraft.commands.CommandListenerWrapper +import net.minecraft.commands.CommandSourceStack import org.bukkit.event.player.PlayerJoinEvent -typealias ServerCommandSource = CommandListenerWrapper - /** * This class provides Brigardier support. It does that * by using reflection once. Additionally, this class is @@ -23,7 +17,7 @@ typealias ServerCommandSource = CommandListenerWrapper */ object BrigardierSupport { @PublishedApi - internal val commands = LinkedHashSet>() + internal val commands = LinkedHashSet>() internal var executedDefaultRegistration = false private set @@ -38,45 +32,27 @@ object BrigardierSupport { } } - /** - * The command manager is used to hold the command dispatcher, - * and to manage and dispatch the brigardier commands for - * all players on the server. - */ - @Suppress("HasPlatformType") // do not refer non-lazily to the type in this class - @NMS_General - val commandManager by lazy { - (server as org.bukkit.craftbukkit.v1_17_R1.CraftServer).server.vanillaCommandDispatcher - } + @Suppress("HasPlatformType") + fun resolveCommandManager() = (server as org.bukkit.craftbukkit.v1_18_R1.CraftServer) + .server.vanillaCommandDispatcher - /** - * The command dispatcher is used to register brigardier commands. - */ - @NMS_1_17 - val commandDispatcher by lazy { - // g = the command dispatcher - commandManager.reflectField>("g") - } - - @NMS_General internal fun registerAll() { executedDefaultRegistration = true // TODO unregister commands which are now missing due to a possible reload if (commands.isNotEmpty()) { commands.forEach { - commandDispatcher.register(it) + resolveCommandManager().dispatcher.register(it) } if (onlinePlayers.isNotEmpty()) updateCommandTree() } } - @NMS_General fun updateCommandTree() { onlinePlayers.forEach { // send the command tree - commandManager.a((it as org.bukkit.craftbukkit.v1_17_R1.entity.CraftPlayer).handle) + resolveCommandManager().sendCommands((it as org.bukkit.craftbukkit.v1_18_R1.entity.CraftPlayer).handle) } } } diff --git a/src/main/kotlin/net/axay/kspigot/data/NBTDataLoader.kt b/src/main/kotlin/net/axay/kspigot/data/NBTDataLoader.kt new file mode 100644 index 00000000..61d72460 --- /dev/null +++ b/src/main/kotlin/net/axay/kspigot/data/NBTDataLoader.kt @@ -0,0 +1,27 @@ +package net.axay.kspigot.data + +import net.axay.kspigot.annotations.NMS_General +import net.minecraft.nbt.CompoundTag +import org.bukkit.craftbukkit.v1_18_R1.entity.CraftEntity +import org.bukkit.craftbukkit.v1_18_R1.inventory.CraftItemStack +import org.bukkit.entity.Entity +import org.bukkit.inventory.ItemStack + +@NMS_General +var Entity.nbtData: CompoundTag + get() { + val nbtTagCompound = CompoundTag() + (this as CraftEntity).handle.save(nbtTagCompound) + return nbtTagCompound + } + set(value) { + (this as CraftEntity).handle.load(value) + } + +@NMS_General +val ItemStack.nbtData: CompoundTag + get() { + CraftItemStack.asNMSCopy(this).let { + return if (it.hasTag()) (it.tag ?: CompoundTag()) else CompoundTag() + } + } diff --git a/src/main/kotlin/net/axay/kspigot/extensions/bukkit/EntityExtensions.kt b/src/main/kotlin/net/axay/kspigot/extensions/bukkit/EntityExtensions.kt index 08a1e73b..767521ea 100644 --- a/src/main/kotlin/net/axay/kspigot/extensions/bukkit/EntityExtensions.kt +++ b/src/main/kotlin/net/axay/kspigot/extensions/bukkit/EntityExtensions.kt @@ -9,7 +9,6 @@ import net.md_5.bungee.api.ChatMessageType import org.bukkit.Location import org.bukkit.Material import org.bukkit.attribute.Attribute -import org.bukkit.craftbukkit.v1_17_R1.CraftWorld import org.bukkit.entity.* import org.bukkit.inventory.EquipmentSlot import org.bukkit.inventory.ItemStack @@ -102,21 +101,15 @@ fun Player.showOnlinePlayers() { onlinePlayers.filter { it != this }.forEach { this.showPlayer(PluginInstance, it) } } -/** - * Kicks the player from the server. - */ -fun Player.kick(reason: String? = "You got kicked!") { - kickPlayer(reason) -} - /** * Spawns an entity without any variations in color, type etc... */ +@Deprecated("This function is unstable and it cannot be guaranteed that it will work at any time in the future.") @NMS_General fun Location.spawnCleanEntity(entityType: EntityType): Entity? { - val craftWorld = world as? CraftWorld ?: return null + val craftWorld = world as? org.bukkit.craftbukkit.v1_18_R1.CraftWorld ?: return null return craftWorld.createEntity(this, entityType.entityClass)?.let { - craftWorld.handle.addEntity(it) + craftWorld.handle.addFreshEntity(it) return@let it.bukkitEntity } } @@ -135,6 +128,7 @@ fun Player.title( stay: Int = 70, fadeOut: Int = 20, ) { + @Suppress("DEPRECATION") sendTitle(mainText, subText, fadeIn, stay, fadeOut) } diff --git a/src/main/kotlin/net/axay/kspigot/structures/Structure.kt b/src/main/kotlin/net/axay/kspigot/structures/Structure.kt index ecc434c6..fc150da9 100644 --- a/src/main/kotlin/net/axay/kspigot/structures/Structure.kt +++ b/src/main/kotlin/net/axay/kspigot/structures/Structure.kt @@ -1,15 +1,16 @@ package net.axay.kspigot.structures import net.axay.kspigot.annotations.NMS_General -import net.axay.kspigot.data.NBTData import net.axay.kspigot.data.nbtData import net.axay.kspigot.extensions.bukkit.spawnCleanEntity import net.axay.kspigot.extensions.geometry.SimpleLocation3D import net.axay.kspigot.particles.KSpigotParticle +import net.minecraft.nbt.CompoundTag import org.bukkit.Location import org.bukkit.Material import org.bukkit.block.Block import org.bukkit.block.data.BlockData +import org.bukkit.craftbukkit.v1_18_R1.entity.CraftEntity import org.bukkit.entity.Entity import org.bukkit.entity.EntityType @@ -54,13 +55,13 @@ data class StructureDataBlock( @NMS_General data class StructureDataEntity( val entityType: EntityType, - val nbtData: NBTData, + val nbtData: CompoundTag, ) : StructureData { constructor(entity: Entity) : this(entity.type, entity.nbtData) - constructor(entityType: EntityType) : this(entityType, NBTData()) + constructor(entityType: EntityType) : this(entityType, CompoundTag()) override fun createAt(loc: Location) { - loc.spawnCleanEntity(entityType)?.nbtData = nbtData + (loc.spawnCleanEntity(entityType) as CraftEntity).handle.load(nbtData) } }