Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 15 additions & 3 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import org.jetbrains.kotlin.gradle.dsl.JvmTarget

plugins {
kotlin("jvm") version "2.2.0"
Expand All @@ -14,6 +15,9 @@ repositories {
maven("https://repo.papermc.io/repository/maven-public/") {
name = "papermc-repo"
}
maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots/") {
name = "spigotmc-repo"
}
maven("https://oss.sonatype.org/content/groups/public/") {
name = "sonatype"
}
Expand All @@ -22,7 +26,7 @@ repositories {
}

dependencies {
compileOnly("io.papermc.paper:paper-api:1.21.6-R0.1-SNAPSHOT")
compileOnly("org.spigotmc:spigot-api:1.8.8-R0.1-SNAPSHOT")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
// implementation("org.incendo:cloud-paper:2.0.0-beta.10")
// implementation("org.incendo:cloud-kotlin-coroutines-annotations:2.0.0")
Expand Down Expand Up @@ -61,7 +65,15 @@ tasks {
}
}

val targetJavaVersion = 21
val buildJavaVersion = 21
kotlin {
jvmToolchain(targetJavaVersion)
jvmToolchain(buildJavaVersion)
compilerOptions {
jvmTarget.set(JvmTarget.JVM_1_8)
}
}

java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
24 changes: 22 additions & 2 deletions src/main/kotlin/network/warzone/uranus/UranusCommandGraph.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ import org.bukkit.command.CommandSender
import org.bukkit.entity.Player
import tc.oc.pgm.command.parsers.PlayerParser
import tc.oc.pgm.command.util.CommandGraph
import tc.oc.pgm.lib.org.incendo.cloud.exception.InvalidSyntaxException
import tc.oc.pgm.lib.org.incendo.cloud.minecraft.extras.MinecraftHelp
import tc.oc.pgm.lib.org.incendo.cloud.parser.ArgumentParser
import tc.oc.pgm.util.Audience
import tc.oc.pgm.util.text.TextException
import java.lang.reflect.Type


Expand All @@ -22,13 +24,20 @@ class UranusCommandGraph(plugin: UranusPlugin) : CommandGraph<UranusPlugin>(plug
override fun setupInjectors() {
}

override fun setupExceptionHandlers() {
super.setupExceptionHandlers()
registerExceptionHandler(InvalidSyntaxException::class.java) {
TextException.usage(formatUsage(it.correctSyntax()))
}
}

override fun setupParsers() {
registerParser(Player::class.java, PlayerParser())
}

override fun registerCommands() {
// Default commands
// TBD
register(plugin.mutationManager.command)
}

public override fun register(command: Any) {
Expand All @@ -39,5 +48,16 @@ class UranusCommandGraph(plugin: UranusPlugin) : CommandGraph<UranusPlugin>(plug
super.registerParser(type, parser)
}

private fun formatUsage(syntax: String): String {
val formatted = syntax
.replace("mutation warden <state>", "mutation warden [on/off]")
.replace("mutation warden state", "mutation warden [on/off]")
.replace("mutation rage <state>", "mutation rage [on/off]")
.replace("mutation rage state", "mutation rage [on/off]")
.replace("mutation speedster <state>", "mutation speedster [on/off]")
.replace("mutation speedster state", "mutation speedster [on/off]")

return if (formatted.startsWith("/")) formatted else "/$formatted"
}

}
}
15 changes: 14 additions & 1 deletion src/main/kotlin/network/warzone/uranus/UranusPlugin.kt
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package network.warzone.uranus

import de.maxhenkel.voicechat.api.BukkitVoicechatService
import network.warzone.uranus.mutations.MutationManager
import network.warzone.uranus.voice.UranusVoicePlugin
import org.bukkit.Bukkit
import org.bukkit.event.Listener
import org.bukkit.plugin.java.JavaPlugin
import tc.oc.pgm.api.PGM

class UranusPlugin : JavaPlugin() {

Expand All @@ -14,20 +16,31 @@ class UranusPlugin : JavaPlugin() {
}

lateinit var commandGraph: UranusCommandGraph
lateinit var mutationManager: MutationManager

override fun onEnable() {
instance = this
this.loadMutations()
this.loadCommandManager()
this.loadVoiceChatIntegration()
}

override fun onDisable() {
// Plugin shutdown logic
if (::mutationManager.isInitialized) {
runCatching {
PGM.get().matchManager.matches.forEachRemaining(mutationManager::disableAll)
}
}
}

fun loadCommandManager() {
this.commandGraph = UranusCommandGraph(this)
}

fun loadMutations() {
this.mutationManager = MutationManager(this)
}

fun loadVoiceChatIntegration() {
if (server.pluginManager.isPluginEnabled("voicechat")) {
val service = server.servicesManager.load(BukkitVoicechatService::class.java)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ package network.warzone.uranus.listeners

import org.bukkit.event.EventHandler
import org.bukkit.event.Listener
import org.bukkit.event.entity.EntityPickupItemEvent
import org.bukkit.event.player.PlayerPickupItemEvent
import tc.oc.pgm.api.PGM
import tc.oc.pgm.spawner.Spawner

object GeneratorSplittingListener : Listener {

@EventHandler
fun onItemPickup(event: EntityPickupItemEvent) {
fun onItemPickup(event: PlayerPickupItemEvent) {
val item = event.item

val metadata = item.getMetadata(Spawner.METADATA_KEY).firstOrNull {
Expand All @@ -21,12 +21,13 @@ object GeneratorSplittingListener : Listener {
}

// Give the same amount of items to all nearby players
item.location.getNearbyPlayers(1.5)
.filter { it != event.entity }
item.world.players
.filter { it != event.player }
.filter { it.location.distanceSquared(item.location) <= 2.25 }
.forEach {
it.inventory.addItem(item.itemStack)
}

}

}
}
26 changes: 26 additions & 0 deletions src/main/kotlin/network/warzone/uranus/mutations/Mutation.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package network.warzone.uranus.mutations

import org.bukkit.command.CommandSender
import tc.oc.pgm.api.match.Match

interface Mutation {

val id: String
val name: String

fun isAvailable(sender: CommandSender): Boolean = true

fun isEnabled(match: Match): Boolean

fun enable(match: Match): MutationResult

fun disable(match: Match): MutationResult

}

data class MutationResult(
val success: Boolean,
val message: String,
val mutation: Mutation? = null,
val enabled: Boolean = false
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package network.warzone.uranus.mutations

import network.warzone.uranus.UranusPlugin
import network.warzone.uranus.mutations.commands.MutationCommand
import network.warzone.uranus.mutations.effects.RageMutation
import network.warzone.uranus.mutations.effects.SpeedsterMutation
import network.warzone.uranus.mutations.warden.WardenSpawnMutation
import org.bukkit.event.Listener
import tc.oc.pgm.api.match.Match

class MutationManager(plugin: UranusPlugin) {

private val mutations = listOf<Mutation>(
WardenSpawnMutation(),
RageMutation(),
SpeedsterMutation()
).associateBy { it.id }

val command = MutationCommand(this)

init {
mutations.values
.filterIsInstance<Listener>()
.forEach(plugin::registerEvents)
}

fun get(id: String): Mutation? = mutations[id.lowercase()]

fun disableAll(match: Match) {
mutations.values
.filter { it.isEnabled(match) }
.forEach { it.disable(match) }
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
package network.warzone.uranus.mutations.commands

import net.kyori.adventure.text.Component.text
import net.kyori.adventure.text.format.NamedTextColor
import network.warzone.uranus.mutations.MutationManager
import org.bukkit.Bukkit
import org.bukkit.command.CommandSender
import org.bukkit.entity.Player
import tc.oc.pgm.api.PGM
import tc.oc.pgm.api.match.Match
import tc.oc.pgm.api.match.MatchPhase
import tc.oc.pgm.lib.org.incendo.cloud.annotations.Argument
import tc.oc.pgm.lib.org.incendo.cloud.annotations.Command
import tc.oc.pgm.lib.org.incendo.cloud.annotations.CommandDescription
import tc.oc.pgm.lib.org.incendo.cloud.annotations.Permission
import tc.oc.pgm.util.Audience

class MutationCommand(private val mutations: MutationManager) {

@Command("mutation warden")
@CommandDescription("Toggle the Warden spawn mutation")
@Permission("uranus.mutation.warden")
fun toggleWarden(sender: CommandSender) {
handleMutation(sender, "warden", null)
}

@Command("mutation warden <state>")
@CommandDescription("Enable or disable the Warden spawn mutation")
@Permission("uranus.mutation.warden")
fun setWarden(sender: CommandSender, @Argument("state") state: String) {
handleMutation(sender, "warden", parseState(sender, state) ?: return)
}

@Command("mutation rage")
@CommandDescription("Toggle the Rage mutation")
@Permission("uranus.mutation.rage")
fun toggleRage(sender: CommandSender) {
handleMutation(sender, "rage", null)
}

@Command("mutation rage <state>")
@CommandDescription("Enable or disable the Rage mutation")
@Permission("uranus.mutation.rage")
fun setRage(sender: CommandSender, @Argument("state") state: String) {
handleMutation(sender, "rage", parseState(sender, state) ?: return)
}

@Command("mutation speedster")
@CommandDescription("Toggle the Speedster mutation")
@Permission("uranus.mutation.speedster")
fun toggleSpeedster(sender: CommandSender) {
handleMutation(sender, "speedster", null)
}

@Command("mutation speedster <state>")
@CommandDescription("Enable or disable the Speedster mutation")
@Permission("uranus.mutation.speedster")
fun setSpeedster(sender: CommandSender, @Argument("state") state: String) {
handleMutation(sender, "speedster", parseState(sender, state) ?: return)
}

private fun handleMutation(sender: CommandSender, mutationId: String, enabled: Boolean?) {
val mutation = mutations.get(mutationId) ?: return
val match = getMatch(sender) ?: run {
Audience.get(sender).sendWarning(text("No active PGM match was found.", NamedTextColor.RED))
return
}

if (!mutation.isAvailable(sender)) {
Audience.get(sender).sendWarning(text("${mutation.name} is not available on this server version.", NamedTextColor.RED))
return
}

val shouldEnable = enabled ?: !mutation.isEnabled(match)
if (shouldEnable && match.phase != MatchPhase.RUNNING) {
Audience.get(sender).sendWarning(text("Mutations cannot be enabled before the match starts!", NamedTextColor.RED))
return
}

val result = if (shouldEnable) {
mutation.enable(match)
} else {
mutation.disable(match)
}

if (result.success && result.enabled && result.mutation != null) {
announceEnabled(match, result.mutation.name)
} else {
Audience.get(sender).sendWarning(text(result.message, if (result.success) NamedTextColor.GREEN else NamedTextColor.RED))
}
}

private fun getMatch(sender: CommandSender): Match? {
return PGM.get().matchManager.getMatch(sender)
}

private fun parseState(sender: CommandSender, state: String): Boolean? {
return when (state.lowercase()) {
"on", "enable", "enabled", "true", "yes" -> true
"off", "disable", "disabled", "false", "no" -> false
else -> {
Audience.get(sender).sendWarning(text("Use on or off.", NamedTextColor.RED))
null
}
}
}

private fun announceEnabled(match: Match, mutationName: String) {
val title = "\u00A73\u00A7l\u00A7k[]\u00A7r \u00A73\u00A7lMutation \u00A7k[]"
val subtitle = "\u00A7a$mutationName"
val message = "\u00A73[Mutations] \u00A77The \u00A7b$mutationName \u00A77mutation has been enabled!"

Bukkit.getOnlinePlayers().forEach {
sendTitle(it, title, subtitle)
playSound(it, "minecraft:entity.ender_dragon.growl")
it.sendMessage(message)
}
}

private fun sendTitle(player: Player, title: String, subtitle: String) {
val playerClass = player.javaClass
val titleSent = runCatching {
val method = playerClass.getMethod(
"sendTitle",
String::class.java,
String::class.java,
Int::class.javaPrimitiveType,
Int::class.javaPrimitiveType,
Int::class.javaPrimitiveType
)
method.invoke(player, title, subtitle, 10, 100, 15)
}.isSuccess

if (titleSent) return

val legacyTitleSent = runCatching {
val method = playerClass.getMethod("sendTitle", String::class.java, String::class.java)
method.invoke(player, title, subtitle)
}.isSuccess

if (!legacyTitleSent) {
player.sendMessage("$title \u00A7r$subtitle")
}
}

private fun playSound(player: Player, sound: String) {
runCatching {
val method = player.javaClass.getMethod(
"playSound",
org.bukkit.Location::class.java,
String::class.java,
Float::class.javaPrimitiveType,
Float::class.javaPrimitiveType
)
method.invoke(player, player.location, sound, 1f, 1f)
}
}

}
Loading