Portal module
This commit is contained in:
119
.gitignore
vendored
Normal file
119
.gitignore
vendored
Normal file
@ -0,0 +1,119 @@
|
||||
# User-specific stuff
|
||||
.idea/
|
||||
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
|
||||
# IntelliJ
|
||||
out/
|
||||
# mpeltonen/sbt-idea plugin
|
||||
.idea_modules/
|
||||
|
||||
# JIRA plugin
|
||||
atlassian-ide-plugin.xml
|
||||
|
||||
# Compiled class file
|
||||
*.class
|
||||
|
||||
# Log file
|
||||
*.log
|
||||
|
||||
# BlueJ files
|
||||
*.ctxt
|
||||
|
||||
# Package Files #
|
||||
*.jar
|
||||
*.war
|
||||
*.nar
|
||||
*.ear
|
||||
*.zip
|
||||
*.tar.gz
|
||||
*.rar
|
||||
|
||||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||
hs_err_pid*
|
||||
|
||||
*~
|
||||
|
||||
# temporary files which can be created if a process still has a handle open of a deleted file
|
||||
.fuse_hidden*
|
||||
|
||||
# KDE directory preferences
|
||||
.directory
|
||||
|
||||
# Linux trash folder which might appear on any partition or disk
|
||||
.Trash-*
|
||||
|
||||
# .nfs files are created when an open file is removed but is still being accessed
|
||||
.nfs*
|
||||
|
||||
# General
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
|
||||
# Icon must end with two \r
|
||||
Icon
|
||||
|
||||
# Thumbnails
|
||||
._*
|
||||
|
||||
# Files that might appear in the root of a volume
|
||||
.DocumentRevisions-V100
|
||||
.fseventsd
|
||||
.Spotlight-V100
|
||||
.TemporaryItems
|
||||
.Trashes
|
||||
.VolumeIcon.icns
|
||||
.com.apple.timemachine.donotpresent
|
||||
|
||||
# Directories potentially created on remote AFP share
|
||||
.AppleDB
|
||||
.AppleDesktop
|
||||
Network Trash Folder
|
||||
Temporary Items
|
||||
.apdisk
|
||||
|
||||
# Windows thumbnail cache files
|
||||
Thumbs.db
|
||||
Thumbs.db:encryptable
|
||||
ehthumbs.db
|
||||
ehthumbs_vista.db
|
||||
|
||||
# Dump file
|
||||
*.stackdump
|
||||
|
||||
# Folder config file
|
||||
[Dd]esktop.ini
|
||||
|
||||
# Recycle Bin used on file shares
|
||||
$RECYCLE.BIN/
|
||||
|
||||
# Windows Installer files
|
||||
*.cab
|
||||
*.msi
|
||||
*.msix
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
# Windows shortcuts
|
||||
*.lnk
|
||||
|
||||
.gradle
|
||||
build/
|
||||
|
||||
# Ignore Gradle GUI config
|
||||
gradle-app.setting
|
||||
|
||||
# Cache of project
|
||||
.gradletasknamecache
|
||||
|
||||
**/build/
|
||||
|
||||
# Common working directory
|
||||
run/
|
||||
runs/
|
||||
|
||||
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
|
||||
!gradle-wrapper.jar
|
||||
50
build.gradle.kts
Normal file
50
build.gradle.kts
Normal file
@ -0,0 +1,50 @@
|
||||
plugins {
|
||||
kotlin("jvm") version "2.2.0-Beta2"
|
||||
id("com.gradleup.shadow") version "8.3.0"
|
||||
id("xyz.jpenilla.run-paper") version "2.3.1"
|
||||
}
|
||||
|
||||
group = "com.pobnellion"
|
||||
version = "2.0-SNAPSHOT"
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven("https://repo.papermc.io/repository/maven-public/") {
|
||||
name = "papermc-repo"
|
||||
}
|
||||
maven("https://oss.sonatype.org/content/groups/public/") {
|
||||
name = "sonatype"
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly("io.papermc.paper:paper-api:1.21.5-R0.1-SNAPSHOT")
|
||||
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
|
||||
}
|
||||
|
||||
tasks {
|
||||
runServer {
|
||||
// Configure the Minecraft version for our task.
|
||||
// This is the only required configuration besides applying the plugin.
|
||||
// Your plugin's jar (or shadowJar if present) will be used automatically.
|
||||
minecraftVersion("1.21")
|
||||
}
|
||||
}
|
||||
|
||||
val targetJavaVersion = 21
|
||||
kotlin {
|
||||
jvmToolchain(targetJavaVersion)
|
||||
}
|
||||
|
||||
tasks.build {
|
||||
dependsOn("shadowJar")
|
||||
}
|
||||
|
||||
tasks.processResources {
|
||||
val props = mapOf("version" to version)
|
||||
inputs.properties(props)
|
||||
filteringCharset = "UTF-8"
|
||||
filesMatching("plugin.yml") {
|
||||
expand(props)
|
||||
}
|
||||
}
|
||||
0
gradle.properties
Normal file
0
gradle.properties
Normal file
1
gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
1
gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@ -0,0 +1 @@
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip
|
||||
1
settings.gradle.kts
Normal file
1
settings.gradle.kts
Normal file
@ -0,0 +1 @@
|
||||
rootProject.name = "pobutils"
|
||||
77
src/main/kotlin/com/pobnellion/pobutils/Pobutils.kt
Normal file
77
src/main/kotlin/com/pobnellion/pobutils/Pobutils.kt
Normal file
@ -0,0 +1,77 @@
|
||||
package com.pobnellion.pobutils
|
||||
|
||||
import com.pobnellion.pobutils.modules.CmdModule
|
||||
import com.pobnellion.pobutils.modules.ModuleBase
|
||||
import com.pobnellion.pobutils.modules.portals.Portals
|
||||
import org.bukkit.plugin.java.JavaPlugin
|
||||
|
||||
|
||||
class Pobutils : JavaPlugin() {
|
||||
companion object {
|
||||
val availableModules = mutableMapOf<String, ModuleBase>()
|
||||
val enabledModules : MutableMap<String, ModuleBase> = mutableMapOf()
|
||||
fun getDisabledModuleNames() = availableModules.keys.filter { name -> !enabledModules.containsKey(name) }
|
||||
fun isEnabled(moduleName: String) : Boolean = enabledModules.containsKey(moduleName)
|
||||
}
|
||||
|
||||
override fun onEnable() {
|
||||
loadDefaultConfig()
|
||||
|
||||
CmdModule.register(this)
|
||||
|
||||
registerModule(Portals(this))
|
||||
|
||||
logger.info("Registered ${availableModules.size} modules: [${availableModules.keys.joinToString()}]")
|
||||
|
||||
// Enable modules
|
||||
for ((name, module) in availableModules) {
|
||||
if (config.getBoolean("modules.${name}")) {
|
||||
module.onEnable()
|
||||
enabledModules[name] = module
|
||||
}
|
||||
}
|
||||
|
||||
logger.info("Loaded ${enabledModules.size} modules: [${enabledModules.keys.joinToString()}]")
|
||||
}
|
||||
|
||||
override fun onDisable() {
|
||||
// Plugin shutdown logic
|
||||
}
|
||||
|
||||
private fun registerModule(module: ModuleBase) {
|
||||
availableModules[module.name] = module
|
||||
module.register()
|
||||
}
|
||||
|
||||
private fun loadDefaultConfig() {
|
||||
saveResource("config.yml", false)
|
||||
|
||||
config.addDefault("modules.noJoinMessage", false)
|
||||
config.addDefault("modules.sit", false)
|
||||
config.addDefault("modules.spawn", false)
|
||||
config.addDefault("modules.portals", 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.snowballDamage", false)
|
||||
config.addDefault("data.spawn.location", "")
|
||||
config.addDefault("data.spawn.spawnOnJoin", false)
|
||||
config.addDefault("data.spawn.spawnOnDeath", false)
|
||||
|
||||
// config.addDefault("data.spawn.spawnOnFirstJoin", false);
|
||||
config.addDefault("data.portals", "")
|
||||
config.addDefault("data.warps", "")
|
||||
config.addDefault("data.formatChat.serverAlias", "?")
|
||||
config.addDefault("data.formatChat.messageFormat", "<gray><server_alias> <white><username>: <message>")
|
||||
config.addDefault("data.formatChat.formatMessageText", true)
|
||||
|
||||
config.addDefault("settings.snowballDamage.damageExceptions", ArrayList<String?>())
|
||||
config.addDefault("settings.snowballDamage.snowmenDontHitEachother", true)
|
||||
|
||||
config.options().copyDefaults(true)
|
||||
saveConfig()
|
||||
}
|
||||
}
|
||||
96
src/main/kotlin/com/pobnellion/pobutils/modules/CmdModule.kt
Normal file
96
src/main/kotlin/com/pobnellion/pobutils/modules/CmdModule.kt
Normal file
@ -0,0 +1,96 @@
|
||||
package com.pobnellion.pobutils.modules
|
||||
|
||||
import com.mojang.brigadier.Command
|
||||
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.plugin.lifecycle.event.types.LifecycleEvents
|
||||
import net.kyori.adventure.text.Component
|
||||
import net.kyori.adventure.text.TextComponent
|
||||
import net.kyori.adventure.text.format.NamedTextColor
|
||||
import org.bukkit.plugin.java.JavaPlugin
|
||||
|
||||
@Suppress("UnstableApiUsage")
|
||||
object CmdModule {
|
||||
fun register(plugin: JavaPlugin) {
|
||||
val command = Commands.literal("module")
|
||||
.requires { source -> source.sender.hasPermission("pobutils.admin") }
|
||||
.then(handleAction("enable", plugin))
|
||||
.then(handleAction("disable", plugin))
|
||||
.then(handleAction("reload", plugin))
|
||||
.build()
|
||||
|
||||
plugin.lifecycleManager.registerEventHandler(LifecycleEvents.COMMANDS) {commands ->
|
||||
commands.registrar().register(command)
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleAction(action: String, plugin: JavaPlugin) : LiteralArgumentBuilder<CommandSourceStack> {
|
||||
return Commands.literal(action)
|
||||
.then(Commands.argument("module", StringArgumentType.word())
|
||||
.suggests { ctx, builder ->
|
||||
when (action) {
|
||||
"enable" -> Pobutils.getDisabledModuleNames().forEach { module -> builder.suggest(module) }
|
||||
"disable" -> Pobutils.enabledModules.keys.forEach { module -> builder.suggest(module) }
|
||||
"reload" -> Pobutils.enabledModules.keys.forEach { module -> builder.suggest(module) }
|
||||
}
|
||||
|
||||
return@suggests builder.buildFuture()
|
||||
}
|
||||
.executes { ctx ->
|
||||
val moduleName = StringArgumentType.getString(ctx, "module")
|
||||
|
||||
val module = Pobutils.availableModules[moduleName]
|
||||
|
||||
if (module == null) {
|
||||
ctx.source.sender.sendMessage(Component.text("No module named '$moduleName'", NamedTextColor.RED))
|
||||
return@executes Command.SINGLE_SUCCESS
|
||||
}
|
||||
|
||||
val message : TextComponent
|
||||
when (action) {
|
||||
"enable" -> {
|
||||
if (Pobutils.isEnabled(moduleName)) {
|
||||
message = Component.text("Module '$moduleName' is already enabled", NamedTextColor.RED)
|
||||
}
|
||||
else {
|
||||
Pobutils.enabledModules[moduleName] = module
|
||||
module.onEnable()
|
||||
plugin.config.set("modules.$moduleName", true)
|
||||
plugin.saveConfig()
|
||||
message = Component.text("Module '$moduleName' enabled", NamedTextColor.YELLOW)
|
||||
}
|
||||
}
|
||||
"disable" -> {
|
||||
if (!Pobutils.isEnabled(moduleName)) {
|
||||
message = Component.text("Module '$moduleName' is already disabled", NamedTextColor.RED)
|
||||
}
|
||||
else {
|
||||
Pobutils.enabledModules.remove(moduleName)
|
||||
module.onDisable()
|
||||
plugin.config.set("modules.$moduleName", false)
|
||||
plugin.saveConfig()
|
||||
message = Component.text("Module '$moduleName' disabled", NamedTextColor.YELLOW)
|
||||
}
|
||||
}
|
||||
"reload" -> {
|
||||
if (!Pobutils.isEnabled(moduleName)) {
|
||||
message = Component.text("Module '$moduleName' is not currently enabled", NamedTextColor.RED)
|
||||
}
|
||||
else {
|
||||
module.reload()
|
||||
message = Component.text("Module '$moduleName' reloaded", NamedTextColor.YELLOW)
|
||||
}
|
||||
}
|
||||
else -> message = Component.text("Unknown argument '$action'", NamedTextColor.RED)
|
||||
}
|
||||
|
||||
plugin.server.onlinePlayers.forEach { player -> player.updateCommands() }
|
||||
ctx.source.sender.sendMessage(message)
|
||||
|
||||
return@executes Command.SINGLE_SUCCESS
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
package com.pobnellion.pobutils.modules
|
||||
|
||||
import org.bukkit.plugin.java.JavaPlugin
|
||||
|
||||
abstract class ModuleBase(val plugin: JavaPlugin) {
|
||||
abstract val name : String
|
||||
abstract fun register()
|
||||
abstract fun reload()
|
||||
abstract fun onDisable()
|
||||
abstract fun onEnable()
|
||||
}
|
||||
@ -0,0 +1,115 @@
|
||||
package com.pobnellion.pobutils.modules.portals
|
||||
|
||||
import com.mojang.brigadier.Command
|
||||
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 CmdPortal {
|
||||
val serverList: MutableList<String> = mutableListOf()
|
||||
|
||||
fun register(plugin: JavaPlugin, portals: Portals) {
|
||||
val command = Commands.literal("portal")
|
||||
.requires { source ->
|
||||
Pobutils.isEnabled("portals") &&
|
||||
source.sender.hasPermission("pobutils.admin") &&
|
||||
source.sender is Player
|
||||
}
|
||||
.then(addOrUpdatePortal("add", portals))
|
||||
.then(addOrUpdatePortal("update", portals))
|
||||
.then(removePortal(portals))
|
||||
.then(listPortals(portals))
|
||||
.build()
|
||||
|
||||
plugin.lifecycleManager.registerEventHandler(LifecycleEvents.COMMANDS) { commands ->
|
||||
commands.registrar().register(command)
|
||||
}
|
||||
}
|
||||
|
||||
private fun addOrUpdatePortal(action: String, portals: Portals) : LiteralArgumentBuilder<CommandSourceStack> {
|
||||
var portalSubCommand = Commands.argument("name", StringArgumentType.word())
|
||||
|
||||
if (action == "update")
|
||||
portalSubCommand = portalSubCommand.suggests { ctx, builder ->
|
||||
portals.portals.forEach { portal -> builder.suggest(portal.name) }
|
||||
return@suggests builder.buildFuture()
|
||||
}
|
||||
|
||||
portalSubCommand.then(Commands.argument("location1", ArgumentTypes.blockPosition())
|
||||
.then(Commands.argument("location2", ArgumentTypes.blockPosition())
|
||||
.then(Commands.argument("destinationServer", StringArgumentType.word())
|
||||
.suggests { ctx, builder ->
|
||||
serverList.forEach { serverName -> builder.suggest(serverName) }
|
||||
return@suggests builder.buildFuture()
|
||||
}
|
||||
.executes { ctx ->
|
||||
val name = StringArgumentType.getString(ctx, "name")
|
||||
val destServer = StringArgumentType.getString(ctx, "destinationServer")
|
||||
val location1 = ctx.getArgument("location1", BlockPositionResolver::class.java).resolve(ctx.source)
|
||||
val location2 = ctx.getArgument("location2", BlockPositionResolver::class.java).resolve(ctx.source)
|
||||
|
||||
if (!serverList.contains(destServer)) {
|
||||
ctx.source.sender.sendMessage(Component.text("No server named $destServer", NamedTextColor.RED))
|
||||
return@executes Command.SINGLE_SUCCESS
|
||||
}
|
||||
|
||||
when (action) {
|
||||
"add" if portals.exists(name) -> ctx.source.sender.sendMessage(Component.text("A portal called $name already exists!", NamedTextColor.RED))
|
||||
"update" if !portals.exists(name) -> ctx.source.sender.sendMessage(Component.text("No portal named $name!", NamedTextColor.RED))
|
||||
else -> {
|
||||
portals.addOrUpdate(name, location1, location2, destServer)
|
||||
val actionVerb = if (action == "add") "Added" else "Updated"
|
||||
ctx.source.sender.sendMessage(Component.text("$actionVerb portal '$name'", NamedTextColor.YELLOW))
|
||||
}
|
||||
}
|
||||
|
||||
return@executes Command.SINGLE_SUCCESS
|
||||
})))
|
||||
|
||||
return Commands
|
||||
.literal(action)
|
||||
.then(portalSubCommand)
|
||||
}
|
||||
|
||||
private fun removePortal(portals: Portals) : LiteralArgumentBuilder<CommandSourceStack> {
|
||||
return Commands.literal("remove")
|
||||
.then(Commands.argument("portal", StringArgumentType.word())
|
||||
.suggests { ctx, builder ->
|
||||
portals.portals.forEach { portal -> builder.suggest(portal.name) }
|
||||
return@suggests builder.buildFuture()
|
||||
}
|
||||
.executes { ctx ->
|
||||
val name = StringArgumentType.getString(ctx, "portal")
|
||||
|
||||
if (!portals.exists(name))
|
||||
ctx.source.sender.sendMessage(Component.text("No portal named $name!", NamedTextColor.RED))
|
||||
else
|
||||
portals.remove(name)
|
||||
|
||||
return@executes Command.SINGLE_SUCCESS
|
||||
})
|
||||
}
|
||||
|
||||
private fun listPortals(portals: Portals) : LiteralArgumentBuilder<CommandSourceStack> {
|
||||
return Commands.literal("list")
|
||||
.executes { ctx ->
|
||||
ctx.source.sender.sendMessage(Component.text("There are ${portals.portals.count()} portals:", NamedTextColor.YELLOW))
|
||||
|
||||
portals.portals.forEach { portal ->
|
||||
ctx.source.sender.sendMessage(Component.text(portal.toString(), NamedTextColor.YELLOW))
|
||||
}
|
||||
|
||||
return@executes Command.SINGLE_SUCCESS
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,58 @@
|
||||
package com.pobnellion.pobutils.modules.portals
|
||||
|
||||
import org.bukkit.Location
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
class Portal {
|
||||
|
||||
val name: String
|
||||
val destServer: String
|
||||
private val x1: Int
|
||||
private val y1: Int
|
||||
private val z1: Int
|
||||
private val x2: Int
|
||||
private val y2: Int
|
||||
private val z2: Int
|
||||
|
||||
constructor(name: String, destServer: String, x1: Int, y1: Int, z1: Int, x2: Int, y2: Int, z2: Int) {
|
||||
this.name = name
|
||||
this.destServer = destServer
|
||||
this.x1 = min(x1, x2)
|
||||
this.y1 = min(y1, y2)
|
||||
this.z1 = min(z1, z2)
|
||||
this.x2 = max(x1, x2)
|
||||
this.y2 = max(y1, y2)
|
||||
this.z2 = max(z1, z2)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun deserialize(name: String, serializedData: String) : Portal {
|
||||
val data = serializedData.split(" ")
|
||||
|
||||
return Portal(
|
||||
name,
|
||||
data[6],
|
||||
data[0].toInt(),
|
||||
data[1].toInt(),
|
||||
data[2].toInt(),
|
||||
data[3].toInt(),
|
||||
data[4].toInt(),
|
||||
data[5].toInt())
|
||||
}
|
||||
}
|
||||
|
||||
fun serialize(): String {
|
||||
return "$x1 $y1 $z1 $x2 $y2 $z2 $destServer"
|
||||
}
|
||||
|
||||
fun contains(location: Location) : Boolean {
|
||||
return location.blockX >= x1 && location.blockX <= x2 &&
|
||||
location.blockY >= y1 && location.blockY <= y2 &&
|
||||
location.blockZ >= z1 && location.blockZ <= z2
|
||||
}
|
||||
|
||||
override fun toString() : String {
|
||||
return "[$name] ($x1 $y1 $z1) ($x2 $y2 $z2) dest: $destServer"
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,164 @@
|
||||
package com.pobnellion.pobutils.modules.portals
|
||||
|
||||
import com.google.common.io.ByteStreams
|
||||
import com.pobnellion.pobutils.Pobutils
|
||||
import com.pobnellion.pobutils.modules.ModuleBase
|
||||
import io.papermc.paper.math.BlockPosition
|
||||
import org.bukkit.Bukkit
|
||||
import org.bukkit.Location
|
||||
import org.bukkit.NamespacedKey
|
||||
import org.bukkit.attribute.Attribute
|
||||
import org.bukkit.attribute.AttributeModifier
|
||||
import org.bukkit.entity.Player
|
||||
import org.bukkit.event.EventHandler
|
||||
import org.bukkit.event.Listener
|
||||
import org.bukkit.event.player.PlayerJoinEvent
|
||||
import org.bukkit.event.player.PlayerMoveEvent
|
||||
import org.bukkit.event.player.PlayerQuitEvent
|
||||
import org.bukkit.plugin.java.JavaPlugin
|
||||
import org.bukkit.plugin.messaging.PluginMessageListener
|
||||
|
||||
|
||||
@Suppress("UnstableApiUsage")
|
||||
class Portals(plugin: JavaPlugin) : ModuleBase(plugin), Listener, PluginMessageListener {
|
||||
val portals: MutableList<Portal> = mutableListOf()
|
||||
val portalCooldowns: MutableMap<Player, Location> = mutableMapOf()
|
||||
override val name: String = "portals"
|
||||
|
||||
override fun register() {
|
||||
Bukkit.getPluginManager().registerEvents(this, plugin)
|
||||
plugin.server.pluginManager.registerEvents(this, plugin)
|
||||
|
||||
CmdPortal.register(plugin, this)
|
||||
}
|
||||
|
||||
override fun reload() {
|
||||
onDisable()
|
||||
onEnable()
|
||||
}
|
||||
|
||||
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)
|
||||
if (plugin.server.onlinePlayers.count() > 0)
|
||||
refreshServerList(plugin.server.onlinePlayers.first())
|
||||
}
|
||||
|
||||
override fun onDisable() {
|
||||
portals.clear()
|
||||
CmdPortal.serverList.clear()
|
||||
|
||||
plugin.server.messenger.unregisterOutgoingPluginChannel(plugin)
|
||||
plugin.server.messenger.unregisterIncomingPluginChannel(plugin)
|
||||
}
|
||||
|
||||
private fun loadConfig() {
|
||||
plugin.reloadConfig()
|
||||
val config = plugin.config.getConfigurationSection("data.portals")
|
||||
|
||||
if (config != null)
|
||||
portals.addAll(config.getKeys(false)
|
||||
.map { name -> Portal.deserialize(name, config.get(name) as String) })
|
||||
|
||||
plugin.logger.info("Loaded ${portals.count()} portals")
|
||||
}
|
||||
|
||||
private fun updateConfig() {
|
||||
val portalsConfig = portals.associateBy(
|
||||
{ portal -> portal.name },
|
||||
{ portal -> portal.serialize() })
|
||||
|
||||
plugin.config.set("data.portals", portalsConfig)
|
||||
plugin.saveConfig()
|
||||
}
|
||||
|
||||
fun addOrUpdate(name: String, p1: BlockPosition, p2: BlockPosition, destServer: String) {
|
||||
portals.removeIf { portal -> portal.name == name }
|
||||
val portal = Portal(name, destServer, p1.blockX(), p1.blockY(), p1.blockZ(), p2.blockX(), p2.blockY(), p2.blockZ())
|
||||
portals.add(portal)
|
||||
updateConfig()
|
||||
}
|
||||
|
||||
fun remove(name: String) {
|
||||
if (!portals.removeIf { portal -> portal.name == name })
|
||||
plugin.componentLogger.error("Failed to remove portal $name")
|
||||
updateConfig()
|
||||
}
|
||||
|
||||
fun exists(name: String?) : Boolean {
|
||||
if (name == null)
|
||||
return false
|
||||
|
||||
return portals.any { portal -> portal.name == name }
|
||||
}
|
||||
|
||||
private fun refreshServerList(player: Player) {
|
||||
plugin.logger.info("Refreshing server list")
|
||||
val message = ByteStreams.newDataOutput()
|
||||
message.writeUTF("GetServers")
|
||||
player.sendPluginMessage(plugin, "BungeeCord", message.toByteArray())
|
||||
}
|
||||
|
||||
private fun usePortal(event: PlayerMoveEvent, portal: Portal) {
|
||||
val stopModifier = AttributeModifier(NamespacedKey.minecraft("stop"), -1.0, AttributeModifier.Operation.ADD_SCALAR)
|
||||
event.player.getAttribute(Attribute.MOVEMENT_SPEED)!!.addTransientModifier(stopModifier)
|
||||
event.player.getAttribute(Attribute.JUMP_STRENGTH)!!.addTransientModifier(stopModifier)
|
||||
portalCooldowns[event.player] = event.from
|
||||
|
||||
val message = ByteStreams.newDataOutput()
|
||||
message.writeUTF("Connect")
|
||||
message.writeUTF(portal.destServer)
|
||||
event.player.sendPluginMessage(plugin, "BungeeCord", message.toByteArray())
|
||||
}
|
||||
|
||||
override fun onPluginMessageReceived(channel: String, player: Player, message: ByteArray) {
|
||||
if (channel != "BungeeCord")
|
||||
return
|
||||
|
||||
val message = ByteStreams.newDataInput(message)
|
||||
val subchannel = message.readUTF()
|
||||
if (subchannel == "GetServers") {
|
||||
val serverList = message.readUTF()
|
||||
CmdPortal.serverList.clear()
|
||||
CmdPortal.serverList.addAll(serverList.split(", "))
|
||||
}
|
||||
}
|
||||
|
||||
// Switch player server when they enter a portal
|
||||
@EventHandler
|
||||
fun onPlayerMove(event: PlayerMoveEvent) {
|
||||
if (!Pobutils.isEnabled(this.name))
|
||||
return
|
||||
|
||||
if (portalCooldowns.containsKey(event.player))
|
||||
return
|
||||
|
||||
for (portal in portals) {
|
||||
if (portal.contains(event.to)) {
|
||||
usePortal(event, portal)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// When they leave, reset player to where they were before they entered the portal
|
||||
@EventHandler
|
||||
fun onPlayerQuit(event: PlayerQuitEvent) {
|
||||
if (portalCooldowns.containsKey(event.player)) {
|
||||
event.player.teleport(portalCooldowns[event.player] as Location)
|
||||
portalCooldowns.remove(event.player)
|
||||
}
|
||||
}
|
||||
|
||||
// Update server list used for command completion
|
||||
// Plugin message requires a player to send the event so we wait for a player
|
||||
@EventHandler
|
||||
fun onPlayerJoin(event: PlayerJoinEvent) {
|
||||
if (Pobutils.isEnabled(this.name) && CmdPortal.serverList.isEmpty())
|
||||
plugin.server.scheduler.runTaskLaterAsynchronously(plugin, {_ -> refreshServerList(event.player) }, 10 )
|
||||
}
|
||||
}
|
||||
27
src/main/resources/config.yml
Normal file
27
src/main/resources/config.yml
Normal file
@ -0,0 +1,27 @@
|
||||
modules:
|
||||
noJoinMessage: true
|
||||
sit: true
|
||||
spawn: false
|
||||
portals: false
|
||||
warp: false
|
||||
hub: true
|
||||
disableTNT: false
|
||||
tabList: false
|
||||
formatChat: true
|
||||
disableTrample: false
|
||||
snowballDamage: false
|
||||
data:
|
||||
spawn:
|
||||
location: ''
|
||||
spawnOnJoin: false
|
||||
spawnOnDeath: false
|
||||
portals: ''
|
||||
warps: ''
|
||||
formatChat:
|
||||
serverAlias: '?'
|
||||
messageFormat: '<gray><server_alias> <white><username>: <message>'
|
||||
formatMessageText: true
|
||||
settings:
|
||||
snowballDamage:
|
||||
damageExceptions: []
|
||||
snowmenDontHitEachother: true
|
||||
49
src/main/resources/plugin.yml
Normal file
49
src/main/resources/plugin.yml
Normal file
@ -0,0 +1,49 @@
|
||||
name: pobutils
|
||||
version: '2.0-SNAPSHOT'
|
||||
main: com.pobnellion.pobutils.Pobutils
|
||||
api-version: '1.21'
|
||||
prefix: PobUtils
|
||||
authors: [ Bizink ]
|
||||
|
||||
commands:
|
||||
module:
|
||||
description: configure a module
|
||||
usage: /module <module> <enable|disable|config>
|
||||
permission: pobutils.admin
|
||||
|
||||
spawn:
|
||||
description: Teleport to spawn
|
||||
usage: /spawn
|
||||
permission: pobutils.user
|
||||
|
||||
setspawn:
|
||||
description: Set spawn location
|
||||
usage: /setspawn [location]
|
||||
permission: pobutils.admin
|
||||
|
||||
sit:
|
||||
description: Sit down for a while buddy
|
||||
usage: /sit
|
||||
permission: pobutils.user
|
||||
|
||||
portal:
|
||||
description: add or remove a portal to another server
|
||||
usage: /portal <add|update|remove> <name> [x1] [y1] [z1] [x2] [y2] [z2] [destinationServer]
|
||||
permission: pobutils.admin
|
||||
|
||||
warp:
|
||||
description: list or go to warps
|
||||
usage: /warp [add|del|list|warpName] [warpName] [x] [y] [z] [yaw] [pitch]
|
||||
permission: pobutils.user
|
||||
|
||||
hub:
|
||||
description: go to hub server
|
||||
usage: /hub
|
||||
permission: pobutils.user
|
||||
|
||||
permissions:
|
||||
pobutils.user:
|
||||
default: true
|
||||
|
||||
pobutils.admin:
|
||||
default: op
|
||||
Reference in New Issue
Block a user