From a5fd8286d54ed2e14dbe950714fee6c391193086 Mon Sep 17 00:00:00 2001 From: bizink Date: Sat, 14 Jun 2025 22:07:12 +1000 Subject: [PATCH] Sit, Spawn, Hub and DisableTrample --- .../com/pobnellion/pobutils/Pobutils.kt | 26 ++-- .../modules/disableTrample/DisableTrample.kt | 33 +++++ .../pobnellion/pobutils/modules/hub/Hub.kt | 39 ++++++ .../pobutils/modules/portals/Portals.kt | 3 - .../pobnellion/pobutils/modules/sit/CmdSit.kt | 9 +- .../pobnellion/pobutils/modules/sit/Sit.kt | 27 ++-- .../pobutils/modules/spawn/CmdSpawn.kt | 124 ++++++++++++++++++ .../pobutils/modules/spawn/Spawn.kt | 54 ++++++++ 8 files changed, 293 insertions(+), 22 deletions(-) create mode 100644 src/main/kotlin/com/pobnellion/pobutils/modules/disableTrample/DisableTrample.kt create mode 100644 src/main/kotlin/com/pobnellion/pobutils/modules/hub/Hub.kt create mode 100644 src/main/kotlin/com/pobnellion/pobutils/modules/spawn/CmdSpawn.kt create mode 100644 src/main/kotlin/com/pobnellion/pobutils/modules/spawn/Spawn.kt diff --git a/src/main/kotlin/com/pobnellion/pobutils/Pobutils.kt b/src/main/kotlin/com/pobnellion/pobutils/Pobutils.kt index d734523..138acec 100644 --- a/src/main/kotlin/com/pobnellion/pobutils/Pobutils.kt +++ b/src/main/kotlin/com/pobnellion/pobutils/Pobutils.kt @@ -2,9 +2,12 @@ package com.pobnellion.pobutils import com.pobnellion.pobutils.modules.CmdModule import com.pobnellion.pobutils.modules.ModuleBase +import com.pobnellion.pobutils.modules.disableTrample.DisableTrample +import com.pobnellion.pobutils.modules.hub.Hub import com.pobnellion.pobutils.modules.noJoinMessage.NoJoinMessage import com.pobnellion.pobutils.modules.portals.Portals import com.pobnellion.pobutils.modules.sit.Sit +import com.pobnellion.pobutils.modules.spawn.Spawn import org.bukkit.plugin.java.JavaPlugin @@ -23,8 +26,12 @@ class Pobutils : JavaPlugin() { registerModule(Portals(this)) registerModule(NoJoinMessage(this)) - registerModule(Sit(this)) + registerModule(Sit(this)) // TODO: maybe sit when right click stairs? + registerModule(Spawn(this)) + registerModule(Hub(this)) + registerModule(DisableTrample(this)) + server.messenger.registerOutgoingPluginChannel(this, "BungeeCord") logger.info("Registered ${availableModules.size} modules: [${availableModules.keys.joinToString()}]") // Enable modules @@ -39,7 +46,9 @@ class Pobutils : JavaPlugin() { } override fun onDisable() { - // Plugin shutdown logic + for ((_, module) in enabledModules) { + module.onDisable() + } } private fun registerModule(module: ModuleBase) { @@ -52,17 +61,18 @@ class Pobutils : JavaPlugin() { config.addDefault("modules.noJoinMessage", false) config.addDefault("modules.portals", false) - config.addDefault("modules.sit", false) - config.addDefault("modules.spawn", false) - config.addDefault("modules.warp", false) config.addDefault("modules.hub", false) - config.addDefault("modules.disableTNT", false) - config.addDefault("modules.tabList", false) - config.addDefault("modules.formatChat", false) config.addDefault("modules.disableTrample", false) + + + config.addDefault("modules.tabList", false) + config.addDefault("modules.disableTNT", false) + config.addDefault("modules.formatChat", false) + config.addDefault("modules.warp", false) config.addDefault("modules.snowballDamage", false) + config.addDefault("data.spawn.location", "") config.addDefault("data.spawn.spawnOnJoin", false) config.addDefault("data.spawn.spawnOnDeath", false) diff --git a/src/main/kotlin/com/pobnellion/pobutils/modules/disableTrample/DisableTrample.kt b/src/main/kotlin/com/pobnellion/pobutils/modules/disableTrample/DisableTrample.kt new file mode 100644 index 0000000..507c468 --- /dev/null +++ b/src/main/kotlin/com/pobnellion/pobutils/modules/disableTrample/DisableTrample.kt @@ -0,0 +1,33 @@ +package com.pobnellion.pobutils.modules.disableTrample + +import com.pobnellion.pobutils.Pobutils +import com.pobnellion.pobutils.modules.ModuleBase +import org.bukkit.Material +import org.bukkit.event.EventHandler +import org.bukkit.event.Listener +import org.bukkit.event.block.Action +import org.bukkit.event.player.PlayerInteractEvent +import org.bukkit.plugin.java.JavaPlugin + +class DisableTrample(plugin: JavaPlugin) : ModuleBase(plugin) , Listener { + override val name: String = "disableTrample" + + override fun register() { + plugin.server.pluginManager.registerEvents(this, plugin) + } + + override fun reload() { } + + override fun onDisable() { } + + override fun onEnable() { } + + @EventHandler + fun onTrample(event: PlayerInteractEvent) { + if (Pobutils.isEnabled(this.name) + && event.action == Action.PHYSICAL + && event.hand == null + && event.clickedBlock?.type == Material.FARMLAND) + event.isCancelled = true + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/pobnellion/pobutils/modules/hub/Hub.kt b/src/main/kotlin/com/pobnellion/pobutils/modules/hub/Hub.kt new file mode 100644 index 0000000..1c215f3 --- /dev/null +++ b/src/main/kotlin/com/pobnellion/pobutils/modules/hub/Hub.kt @@ -0,0 +1,39 @@ +package com.pobnellion.pobutils.modules.hub + +import com.google.common.io.ByteStreams +import com.mojang.brigadier.Command +import com.pobnellion.pobutils.Pobutils +import com.pobnellion.pobutils.modules.ModuleBase +import io.papermc.paper.command.brigadier.Commands +import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents +import org.bukkit.entity.Player +import org.bukkit.plugin.java.JavaPlugin + +@Suppress("UnstableApiUsage") +class Hub(plugin: JavaPlugin) : ModuleBase(plugin) { + override val name: String = "hub" + + override fun register() { + val command = Commands.literal("hub") + .requires { source -> Pobutils.isEnabled(this.name) } + .executes { ctx -> + val message = ByteStreams.newDataOutput() + message.writeUTF("Connect") + message.writeUTF("hub") + (ctx.source.sender as Player).sendPluginMessage(plugin, "BungeeCord", message.toByteArray()) + + return@executes Command.SINGLE_SUCCESS + } + .build() + + plugin.lifecycleManager.registerEventHandler(LifecycleEvents.COMMANDS) { commands -> + commands.registrar().register(command) + } + } + + override fun reload() { } + + override fun onDisable() { } + + override fun onEnable() { } +} \ No newline at end of file diff --git a/src/main/kotlin/com/pobnellion/pobutils/modules/portals/Portals.kt b/src/main/kotlin/com/pobnellion/pobutils/modules/portals/Portals.kt index a69d0f6..108d7ca 100644 --- a/src/main/kotlin/com/pobnellion/pobutils/modules/portals/Portals.kt +++ b/src/main/kotlin/com/pobnellion/pobutils/modules/portals/Portals.kt @@ -37,7 +37,6 @@ class Portals(plugin: JavaPlugin) : ModuleBase(plugin), Listener, PluginMessageL override fun onEnable() { loadConfig() - plugin.server.messenger.registerOutgoingPluginChannel(plugin, "BungeeCord") plugin.server.messenger.registerIncomingPluginChannel(plugin, "BungeeCord", this) // use a player to trigger server list refresh (otherwise refresh will happen on player join) @@ -48,8 +47,6 @@ class Portals(plugin: JavaPlugin) : ModuleBase(plugin), Listener, PluginMessageL override fun onDisable() { portals.clear() CmdPortal.serverList.clear() - - plugin.server.messenger.unregisterOutgoingPluginChannel(plugin) plugin.server.messenger.unregisterIncomingPluginChannel(plugin) } diff --git a/src/main/kotlin/com/pobnellion/pobutils/modules/sit/CmdSit.kt b/src/main/kotlin/com/pobnellion/pobutils/modules/sit/CmdSit.kt index ca765a0..be4b86d 100644 --- a/src/main/kotlin/com/pobnellion/pobutils/modules/sit/CmdSit.kt +++ b/src/main/kotlin/com/pobnellion/pobutils/modules/sit/CmdSit.kt @@ -13,7 +13,14 @@ object CmdSit { val command = Commands.literal("sit") .requires { source -> Pobutils.isEnabled(sit.name) && source.sender is Player } .executes { ctx -> - sit.sit(ctx.source.sender as Player) + val player = ctx.source.sender as Player + + // cool + if (sit.isSitting(player)) + sit.standUp(player) + else + sit.sit(player) + return@executes Command.SINGLE_SUCCESS } .build() diff --git a/src/main/kotlin/com/pobnellion/pobutils/modules/sit/Sit.kt b/src/main/kotlin/com/pobnellion/pobutils/modules/sit/Sit.kt index 2cff8c3..d8915b7 100644 --- a/src/main/kotlin/com/pobnellion/pobutils/modules/sit/Sit.kt +++ b/src/main/kotlin/com/pobnellion/pobutils/modules/sit/Sit.kt @@ -22,16 +22,13 @@ class Sit(plugin: JavaPlugin) : ModuleBase(plugin), Listener { override fun reload() { onDisable() - onEnable() } override fun onEnable() { } override fun onDisable() { - for ((_, seat) in sittingPlayers) - seat.remove() - - sittingPlayers.clear() + for (player in sittingPlayers.keys) + standUp(player) } fun sit(player: Player) { @@ -41,21 +38,31 @@ class Sit(plugin: JavaPlugin) : ModuleBase(plugin), Listener { sittingPlayers[player] = seat } + fun standUp(player: Player) { + if (isSitting(player)) { + sittingPlayers[player]?.remove() + sittingPlayers.remove(player) + player.teleport(player.location.add(0.0, 0.7, 0.0)) + } + } + + fun isSitting(player: Player) : Boolean { + return sittingPlayers.containsKey(player) + } + @EventHandler fun onPlayerDismount(event: EntityDismountEvent) { if (event.entity !is Player || !Pobutils.isEnabled(this.name)) return - val player = event.entity as Player - if (sittingPlayers.containsKey(player)) - sittingPlayers[player]?.remove() + standUp(event.entity as Player) } @EventHandler fun onPlayerLeave(event: PlayerQuitEvent) { - if (!Pobutils.isEnabled(this.name) || !sittingPlayers.containsKey(event.player)) + if (!Pobutils.isEnabled(this.name) || !isSitting(event.player)) return - sittingPlayers[event.player]?.remove() + standUp(event.player) } } \ No newline at end of file diff --git a/src/main/kotlin/com/pobnellion/pobutils/modules/spawn/CmdSpawn.kt b/src/main/kotlin/com/pobnellion/pobutils/modules/spawn/CmdSpawn.kt new file mode 100644 index 0000000..73cd9bc --- /dev/null +++ b/src/main/kotlin/com/pobnellion/pobutils/modules/spawn/CmdSpawn.kt @@ -0,0 +1,124 @@ +package com.pobnellion.pobutils.modules.spawn + +import com.mojang.brigadier.Command +import com.mojang.brigadier.arguments.BoolArgumentType +import com.mojang.brigadier.arguments.StringArgumentType +import com.mojang.brigadier.builder.LiteralArgumentBuilder +import com.pobnellion.pobutils.Pobutils +import io.papermc.paper.command.brigadier.CommandSourceStack +import io.papermc.paper.command.brigadier.Commands +import io.papermc.paper.command.brigadier.argument.ArgumentTypes +import io.papermc.paper.command.brigadier.argument.resolvers.BlockPositionResolver +import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.format.NamedTextColor +import org.bukkit.entity.Player +import org.bukkit.plugin.java.JavaPlugin + +@Suppress("UnstableApiUsage") +object CmdSpawn { + fun register(plugin: JavaPlugin, spawn: Spawn) { + val command = Commands.literal("spawn") + .requires { source -> Pobutils.isEnabled(spawn.name) && source.sender is Player } + .then(setSpawn(plugin, spawn)) + .then(config(plugin)) + .executes { ctx -> + if (spawn.spawnLocation == null) + ctx.source.sender.sendMessage(Component.text("A spawn location has not been set", NamedTextColor.RED)) + else + (ctx.source.sender as Player).teleport(spawn.spawnLocation!!) + + return@executes Command.SINGLE_SUCCESS + } + .build() + + plugin.lifecycleManager.registerEventHandler(LifecycleEvents.COMMANDS) { commands -> + commands.registrar().register(command) + } + } + + private fun setSpawn(plugin: JavaPlugin, spawn: Spawn) : LiteralArgumentBuilder { + return Commands.literal("set") + .requires { source -> source.sender.hasPermission("pobutils.admin") } + .then(Commands.argument("position", ArgumentTypes.blockPosition()) + .then(Commands.argument("direction", StringArgumentType.word()) + .suggests { ctx, builder -> + builder.suggest("north") + builder.suggest("south") + builder.suggest("east") + builder.suggest("west") + + return@suggests builder.buildFuture() + }.executes { ctx -> + val position = ctx.getArgument("position", BlockPositionResolver::class.java).resolve(ctx.source) + val direction = StringArgumentType.getString(ctx, "direction") + + val location = position.toLocation((ctx.source.sender as Player).world) + location.pitch = 0.0f + + when (direction.lowercase()) { + "north" -> location.yaw = 180f; + "east" -> location.yaw = 270f; + "south" -> location.yaw = 0f; + "west" -> location.yaw = 90f; + else -> { + ctx.source.sender.sendMessage(Component.text("Unknown direction: $direction", NamedTextColor.RED)) + return@executes Command.SINGLE_SUCCESS + } + } + + spawn.spawnLocation = location + plugin.config.set("data.spawn.location", location) + plugin.saveConfig() + ctx.source.sender.sendMessage(Component.text("Set spawn location to ${location.x} ${location.y} ${location.z}", NamedTextColor.YELLOW)) + return@executes Command.SINGLE_SUCCESS + })) + } + + private fun config(plugin: JavaPlugin) : LiteralArgumentBuilder { + return Commands.literal("config") + .requires { source -> source.sender.hasPermission("pobutils.admin") } + .then(Commands.argument("variable", StringArgumentType.word()) + .suggests { ctx, builder -> + builder.suggest("spawnOnJoin") + builder.suggest("spawnOnDeath") + + return@suggests builder.buildFuture() + } + .then(Commands.argument("value", BoolArgumentType.bool()) + .executes { ctx -> + val variable = StringArgumentType.getString(ctx, "variable") + val value = BoolArgumentType.getBool(ctx, "value") + + when (variable) { + "spawnOnJoin" -> plugin.config.set("data.spawn.spawnOnJoin", value) + "spawnOnDeath" -> plugin.config.set("data.spawn.spawnOnDeath", value) + else -> { + ctx.source.sender.sendMessage(Component.text("Unknown config variable: $variable", NamedTextColor.RED)) + return@executes Command.SINGLE_SUCCESS + } + } + + plugin.saveConfig() + plugin.reloadConfig() + ctx.source.sender.sendMessage(Component.text("$variable set to: $value", NamedTextColor.YELLOW)) + return@executes Command.SINGLE_SUCCESS + })) + .executes { ctx -> + val location = plugin.config.getLocation("data.spawn.location") + ctx.source.sender.sendMessage("Spawn config:") + + ctx.source.sender.sendMessage(Component.text("location: ", NamedTextColor.YELLOW) + .append(Component.text("${location?.x} ${location?.y} ${location?.z}", NamedTextColor.WHITE))) + + ctx.source.sender.sendMessage(Component.text("spawnOnJoin: ", NamedTextColor.YELLOW) + .append(Component.text(plugin.config.getString("data.spawn.spawnOnJoin").orEmpty(), NamedTextColor.WHITE))) + + ctx.source.sender.sendMessage(Component.text("spawnOnDeath: ", NamedTextColor.YELLOW) + .append(Component.text(plugin.config.getString("data.spawn.spawnOnDeath").orEmpty(), NamedTextColor.WHITE))) + + return@executes Command.SINGLE_SUCCESS + } + + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/pobnellion/pobutils/modules/spawn/Spawn.kt b/src/main/kotlin/com/pobnellion/pobutils/modules/spawn/Spawn.kt new file mode 100644 index 0000000..ef909d2 --- /dev/null +++ b/src/main/kotlin/com/pobnellion/pobutils/modules/spawn/Spawn.kt @@ -0,0 +1,54 @@ +package com.pobnellion.pobutils.modules.spawn + +import com.pobnellion.pobutils.Pobutils +import com.pobnellion.pobutils.modules.ModuleBase +import org.bukkit.Location +import org.bukkit.event.EventHandler +import org.bukkit.event.Listener +import org.bukkit.event.entity.PlayerDeathEvent +import org.bukkit.event.player.PlayerJoinEvent +import org.bukkit.event.player.PlayerRespawnEvent +import org.bukkit.plugin.java.JavaPlugin +import org.spigotmc.event.player.PlayerSpawnLocationEvent + +class Spawn(plugin: JavaPlugin) : ModuleBase(plugin), Listener { + override val name: String = "spawn" + var spawnLocation: Location? = null + + override fun register() { + plugin.server.pluginManager.registerEvents(this, plugin) + CmdSpawn.register(plugin, this) + } + + override fun reload() { + onDisable() + plugin.reloadConfig() + onEnable() + } + + override fun onDisable() { + spawnLocation = null + } + + override fun onEnable() { + spawnLocation = plugin.config.getLocation("data.spawn.location") + } + + @EventHandler + fun onPlayerRespawn(event: PlayerRespawnEvent) { + if (Pobutils.isEnabled(this.name) + && spawnLocation != null + && plugin.config.getBoolean("data.spawn.spawnOnDeath")) { + event.respawnLocation = spawnLocation!! + } + } + + @EventHandler + fun onPlayerJoin(event: PlayerSpawnLocationEvent) { + if (Pobutils.isEnabled(this.name) + && spawnLocation != null + && plugin.config.getBoolean("data.spawn.spawnOnJoin")) { + event.spawnLocation = spawnLocation!! + } + } +} \ No newline at end of file