Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
1c72487
feat(commands): Add commands to easily manage games
cizetux Mar 30, 2024
4a43712
feat(commands): add permission checks to subcommands
cizetux Apr 12, 2024
1a769a4
feat: add new unwanted events
cizetux May 29, 2024
1cb6aeb
feat: add kit feature system for custom items
cizetux May 29, 2024
e06140e
chore: update commandAPIVersion
cizetux Jun 2, 2024
a3ea84e
feat: update map config with minPlayers and mapCuboid settings
cizetux Jun 3, 2024
d256c0e
refactor: use getGame instead of getByWorld
cizetux Jun 3, 2024
5473c1b
feat: add minPlayers and mapCuboid
cizetux Jun 3, 2024
f33ccc7
refactor: improve world object copying
cizetux Jun 3, 2024
e64d99c
refactor: update kit sending method
cizetux Jun 3, 2024
292d84d
feat: add respawnState and initial coins
cizetux Jul 3, 2024
10ee0da
chore: add some translations
cizetux Jul 3, 2024
cd7278c
feat: initial commit
cizetux Jul 3, 2024
73b0a41
feat: add feedback messages
cizetux Jul 3, 2024
20c22b6
chore: add some kits
cizetux Jul 3, 2024
ee9725e
chore: change world border location
cizetux Jul 3, 2024
0f21f77
chore: update commandAPI version
cizetux Jul 3, 2024
fc885ec
feat: add register kit feature
cizetux Jul 3, 2024
b73014d
feat: add support for kit features
cizetux Jul 9, 2024
0f1c4b8
refactor: change game state name
cizetux Jul 9, 2024
3234d4d
feat: add new subcommands and permissions
cizetux Jul 9, 2024
35e0a54
refactor: enhance with state handling and data updates
cizetux Jul 9, 2024
cec627c
feat: start game automatically when minimum players are reached
cizetux Jul 9, 2024
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
4 changes: 2 additions & 2 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ repositories {
dependencies {
val paperVersion = "1.20-R0.1-SNAPSHOT"
val rushyApiVersion = "2.1.0"
val commandApiVersion = "9.0.3"
val commandApiVersion = "9.5.0"

compileOnly(kotlin("stdlib"))

Expand Down Expand Up @@ -72,4 +72,4 @@ tasks {
shadowJar {
archiveClassifier.set("")
}
}
}
13 changes: 9 additions & 4 deletions src/main/kotlin/com/github/rushyverse/rtf/RTFPlugin.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import com.github.rushyverse.rtf.commands.RTFCommand
import com.github.rushyverse.rtf.config.*
import com.github.rushyverse.rtf.game.GameManager
import com.github.rushyverse.rtf.gui.KitsGUI
import com.github.rushyverse.rtf.kit.*
import com.github.rushyverse.rtf.listener.*
import com.github.shynixn.mccoroutine.bukkit.scope
import kotlinx.coroutines.SupervisorJob
Expand All @@ -28,15 +29,11 @@ class RTFPlugin : Plugin(ID, BUNDLE_RTF) {
const val ID = "RTF"
}


lateinit var config: RTFConfig private set
lateinit var configMaps: List<MapConfig> private set
lateinit var configKits: KitsConfig private set

lateinit var mapsDir: File private set

lateinit var tempDir: File private set

lateinit var kitsGui: KitsGUI private set

override suspend fun onEnableAsync() {
Expand All @@ -56,6 +53,7 @@ class RTFPlugin : Plugin(ID, BUNDLE_RTF) {

RTFCommand(this).register()

registerKitFeatures()
registerListeners()
}

Expand All @@ -80,6 +78,13 @@ class RTFPlugin : Plugin(ID, BUNDLE_RTF) {
}
}

private fun registerKitFeatures() {
registerListener { AutoBridge() }
registerListener { LadderFly() }
registerListener { TntFly() }
registerListener { SnowballSwitch() }
}

private fun registerListeners() {
registerListener { GUIListener(setOf(kitsGui)) }
registerListener { AuthenticationListener() }
Expand Down
3 changes: 3 additions & 0 deletions src/main/kotlin/com/github/rushyverse/rtf/client/ClientRTF.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@ import java.util.*
class ClientRTF(
val stats: RTFStats = RTFStats(),
uuid: UUID,
val coins: Int = 0,
scope: CoroutineScope
) : Client(uuid, scope) {

var respawnState: Boolean = false

/**
* Represents the current kit of the player.
* Null by default.
Expand Down
143 changes: 107 additions & 36 deletions src/main/kotlin/com/github/rushyverse/rtf/commands/RTFCommand.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ import com.github.rushyverse.rtf.client.ClientRTF
import com.github.rushyverse.rtf.game.GameManager
import com.github.shynixn.mccoroutine.bukkit.launch
import dev.jorel.commandapi.arguments.IntegerArgument
import dev.jorel.commandapi.arguments.StringArgument
import dev.jorel.commandapi.kotlindsl.*
import net.kyori.adventure.text.Component.text
import net.kyori.adventure.text.format.NamedTextColor
import org.bukkit.entity.Player

class RTFCommand(
private val plugin: RTFPlugin
Expand All @@ -30,68 +32,93 @@ class RTFCommand(
suspend fun register() {
commandAPICommand("rtf") {

subcommand("spectate") {

withArguments(IntegerArgument("game"))
// OP-ONLY
subcommand("create") {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 'create' subcommand is not permission secured.

withArguments(IntegerArgument("gameID"))
withPermission("rtf.command.create")

playerExecutor { player, args ->
anyExecutor { commandSender, args ->
val gameIndex = args[0] as Int
var game = games.getGame(gameIndex)

plugin.launch {

if (game == null && gameIndex == 1) {
if (game == null) {
game = games.createAndSave(gameIndex)
} else {
commandSender.sendMessage("game.already.exists")
return@launch
}
if (commandSender is Player) {
game?.clientSpectate(clients.getClient(commandSender) as ClientRTF)
}

game?.clientSpectate(clients.getClient(player) as ClientRTF)
}
}
}

subcommand("join") {
playerExecutor { player, _ ->
val game = games.getByWorld(player.world) ?: return@playerExecutor

plugin.launch {
val client = clients.getClient(player) as ClientRTF

if (game.getClientTeam(client) != null) {
client.send(
text(
translator.get("join.already.in.team", client.lang().locale),
NamedTextColor.RED
)
)
return@launch
}
// OP-ONLY
subcommand("list") {
withPermission("rtf.command.list")

game.clientJoin(client)
playerExecutor { player, _ ->
val length = games.games.size
player.sendMessage("List of games ($length):")
for (game in games.games) {
player.sendMessage("#${game.id} - ${game.players.size}/${game.config.game.maxGames} - ${game.state()}")
}
}
}

// OP-ONLY
subcommand("start") {
withPermission("rtf.command.start")
playerExecutor { player, _ ->
val game = games.getByWorld(player.world) ?: return@playerExecutor
withOptionalArguments(StringArgument("force"))

if (game.state() != GameState.STARTED) {
plugin.launch { game.start(true) }
playerExecutor { player, args ->
val game = games.getGame(player.world) ?: return@playerExecutor
val force = args[0] as String?

if (game.state() == GameState.WAITING) {
val forceStart= force == "force"
plugin.launch {
game.start(forceStart)
}
} else {
player.sendMessage("The game is already started.")
player.sendMessage("The game has already started.")
}
}
}

// OP-ONLY
subcommand("end") {
withPermission("rtf.end")
withArguments(IntegerArgument("gameID"))

anyExecutor { player, args ->
val gameId = args[0] as Int
player.sendMessage("game.ask.delete")
val game = games.getGame(gameId)
plugin.launch {
game?.end(null)
player.sendMessage("game.deleted")
}
}
}

// DEV
// OP-ONLY
subcommand("win") {
withPermission("rtf.win")
stringArgument("team")

playerExecutor { player, arg ->
val teamName = arg[0].toString()
val type = TeamType.valueOf(teamName.uppercase())
val game = games.getByWorld(player.world) ?: return@playerExecutor
val game = games.getGame(player.world) ?: return@playerExecutor

if (game.state() != GameState.STARTED) {
player.sendMessage("La game n'a pas commencé.")
return@playerExecutor
}

val team = game.teams.firstOrNull { it.type == type }

if (team == null) {
Expand All @@ -103,12 +130,56 @@ class RTFCommand(
}
}

subcommand("end") {
withPermission("rtf.end")
subcommand("spectate") {
withArguments(IntegerArgument("gameID"))
// withPermission("rtf.command.spectate")

playerExecutor { player, args ->
val gameIndex = args[0] as Int
val game = games.getGame(gameIndex)

if (game == null) {
player.sendMessage("game.not.exists")
} else {
plugin.launch { game.clientSpectate(clients.getClient(player) as ClientRTF) }
}
}
}

subcommand("join") {
// withPermission("rtf.command.join")

playerExecutor { player, _ ->
val game = games.getByWorld(player.world) ?: return@playerExecutor
val game = games.getGame(player.world) ?: return@playerExecutor

plugin.launch {
val client = clients.getClient(player) as ClientRTF

plugin.launch { game.end(null) }
if (game.getClientTeam(client) != null) {
client.send(
text(
translator.get("join.already.in.team", client.lang().locale),
NamedTextColor.RED
)
)
return@launch
}

game.clientJoin(client)
}
}
}

subcommand("kits") {
// withPermission("rtf.kits")

playerExecutor { player, args ->
val game = games.getGame(player.world)
if (game != null) {
plugin.launch {
plugin.kitsGui.open(clients.getClient(player))
}
}
}
}
}
Expand Down
36 changes: 27 additions & 9 deletions src/main/kotlin/com/github/rushyverse/rtf/config/KitsConfig.kt
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package com.github.rushyverse.rtf.config

import com.github.rushyverse.api.serializer.ItemStackSerializer
import com.github.rushyverse.rtf.client.ClientRTF
import com.github.rushyverse.rtf.kit.KitFeature.Companion.featureMap
import kotlinx.serialization.Contextual
import kotlinx.serialization.Serializable
import org.bukkit.inventory.ItemStack
import org.bukkit.inventory.PlayerInventory

typealias ItemStackSerializable = @Contextual ItemStack

Expand All @@ -20,19 +21,36 @@ data class Kit(
val name: String,
val description: String,
val icon: ItemStackSerializable,
val armor: ArmorConfig,
val items: Set<@Serializable(with = ItemStackSerializer::class) ItemStack>
val features: Set<String> = emptySet(),
val armor: ArmorConfig? = null,
val items: Set<@Serializable(with = ItemStackSerializer::class) ItemStack>,
) {

fun sendItems(inventory: PlayerInventory) {
fun giveKit(client: ClientRTF) {
val inventory = client.player!!.inventory
armor.let {
inventory.helmet = it.helmet
inventory.chestplate = it.chestplate
inventory.leggings = it.leggings
inventory.boots = it.boots
if (it != null) {
inventory.helmet = it.helmet
}
if (it != null) {
inventory.chestplate = it.chestplate
}
if (it != null) {
inventory.leggings = it.leggings
}
if (it != null) {
inventory.boots = it.boots
}
}

inventory.addItem(*items.toTypedArray())

// Give items of features attributed to this kit
features?.forEach { featureName ->
val feature = featureMap[featureName]!!
feature.item()?.apply { inventory.addItem(this) }
// feature.onGiveKit(client) (not working properly)
}
}
}

Expand All @@ -43,4 +61,4 @@ data class ArmorConfig(
val chestplate: ItemStackSerializable,
val leggings: ItemStackSerializable,
val boots: ItemStackSerializable
)
)
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ import org.bukkit.Material
@SerialName("map")
data class MapConfig(
val worldTemplateName: String,
val limitY: Int,
val minPlayers: Int,
val mapCuboid: CubeArea,
val allowedBlocks: Set<Material>,
val teams: List<TeamRTFConfig>
)
Expand Down
Loading