Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create & List Commands #135

Open
wants to merge 19 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
45ad34f
Started working on create & list commands.
dmccoystephenson Mar 2, 2023
e786123
Added unit tests for 'fief' package.
dmccoystephenson Mar 2, 2023
9014360
Added tests for FiefsCommand class.
dmccoystephenson Mar 2, 2023
74bebc9
Implemented the create & list commands.
dmccoystephenson Mar 2, 2023
9adfe1a
Modified message colors for create & list commands.
dmccoystephenson Mar 2, 2023
dc7ceac
Required players to be in a faction and not already be in a fief in o…
dmccoystephenson Mar 2, 2023
72e1aab
Made a message red.
dmccoystephenson Mar 5, 2023
bca28b9
Modified chatcolor formatting for messages.
dmccoystephenson Mar 5, 2023
b2f3e2c
Extended base command description in plugin.yml
dmccoystephenson Mar 10, 2023
ecc1974
Made mock plugin a class field in TestFiefsCommand.kt
dmccoystephenson Mar 10, 2023
bc56e81
Switched order of some arguments to assertEquals() in TestFief.kt
dmccoystephenson Mar 10, 2023
534e22c
Cast return value of onTabComplete() method in FiefCommand.kt to List…
dmccoystephenson Mar 10, 2023
b560da2
Removed FiefFactory.kt
dmccoystephenson Mar 12, 2023
c9b4c9a
Fixed onTabComplete methods.
dmccoystephenson Mar 12, 2023
a235cd1
Removed useless cast.
dmccoystephenson Mar 12, 2023
141bbd3
Switched over to using MfFactionId instead of UUID to track faction m…
dmccoystephenson Mar 12, 2023
37ba2fe
Modified message verification in TestFiefsCommand.kt
dmccoystephenson Mar 12, 2023
911b789
Added mfFactionId field in Fief.kt
dmccoystephenson Mar 12, 2023
fdbf004
Created the MfFiefId value class.
dmccoystephenson Mar 12, 2023
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
3 changes: 3 additions & 0 deletions src/main/kotlin/com/dansplugins/fiefs/Fiefs.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@ package com.dansplugins.fiefs

import com.dansplugins.factionsystem.MedievalFactions
import com.dansplugins.fiefs.command.fiefs.FiefsCommand
import com.dansplugins.fiefs.fief.FiefRepository
import org.bstats.bukkit.Metrics
import org.bukkit.plugin.java.JavaPlugin

class Fiefs : JavaPlugin() {
lateinit var medievalFactions: MedievalFactions

val fiefRepository = FiefRepository(this)

override fun onEnable() {
saveDefaultConfig()
config.options().copyDefaults(true)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,32 +1,39 @@
package com.dansplugins.fiefs.command.fiefs

import com.dansplugins.fiefs.Fiefs
import com.dansplugins.fiefs.command.fiefs.create.FiefsCreateCommand
import com.dansplugins.fiefs.command.fiefs.help.FiefsHelpCommand
import org.bukkit.ChatColor.AQUA
import org.bukkit.ChatColor.GREEN
import com.dansplugins.fiefs.command.fiefs.list.FiefsListCommand
import org.bukkit.ChatColor
import org.bukkit.command.Command
import org.bukkit.command.CommandExecutor
import org.bukkit.command.CommandSender
import org.bukkit.command.TabCompleter

class FiefsCommand(private val plugin: Fiefs) : CommandExecutor, TabCompleter {
private val helpCommand = FiefsHelpCommand(plugin)
private val createCommand = FiefsCreateCommand(plugin)
private val listCommand = FiefsListCommand(plugin)

private val subcommands = listOf(
"help"
"help",
"create",
"list"
)

override fun onCommand(sender: CommandSender, command: Command, label: String, args: Array<out String>): Boolean {
return when (args.firstOrNull()?.lowercase()) {
"help" -> helpCommand.onCommand(sender, command, label, args.drop(1).toTypedArray())
"create" -> createCommand.onCommand(sender, command, label, args.drop(1).toTypedArray())
"list" -> listCommand.onCommand(sender, command, label, args.drop(1).toTypedArray())
else -> {
// send plugin information
sender.sendMessage("$AQUA" + "Fiefs v${plugin.description.version}")
sender.sendMessage("$AQUA" + "Author: ${plugin.description.authors}")
sender.sendMessage("$AQUA" + "Description: ${plugin.description.description}")
sender.sendMessage("${ChatColor.AQUA}Fiefs v${plugin.description.version}")
sender.sendMessage("${ChatColor.AQUA}Author: ${plugin.description.authors}")
sender.sendMessage("${ChatColor.AQUA}Description: ${plugin.description.description}")

// send help message
sender.sendMessage("$GREEN" + "Type /fiefs help for a list of commands.")
sender.sendMessage("${ChatColor.GREEN}Type /fiefs help for a list of commands.")
return true
}
}
Expand All @@ -42,6 +49,8 @@ class FiefsCommand(private val plugin: Fiefs) : CommandExecutor, TabCompleter {
1 -> subcommands.filter { it.startsWith(args[0]) }.toMutableList()
else -> when(args.first().lowercase()) {
"help" -> helpCommand.onTabComplete(sender, command, alias, args.drop(1).toTypedArray())
"create" -> createCommand.onTabComplete(sender, command, alias, args.drop(1).toTypedArray())
"list" -> listCommand.onTabComplete(sender, command, alias, args.drop(1).toTypedArray())
else -> emptyList()
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package com.dansplugins.fiefs.command.fiefs.create

import com.dansplugins.fiefs.Fiefs
import com.dansplugins.fiefs.fief.Fief
import org.bukkit.ChatColor
import org.bukkit.command.Command
import org.bukkit.command.CommandExecutor
import org.bukkit.command.CommandSender
import org.bukkit.command.TabCompleter
import org.bukkit.entity.Player

class FiefsCreateCommand(private val plugin: Fiefs) : CommandExecutor, TabCompleter {
override fun onCommand(sender: CommandSender, command: Command, label: String, args: Array<out String>): Boolean {
if (sender !is Player) {
sender.sendMessage("${ChatColor.RED}This command can only be run by a player.")
return false
}
val name = args.firstOrNull()
if (name == null) {
sender.sendMessage("${ChatColor.RED}Please specify a name for the fief.")
return false
}
if (plugin.fiefRepository.getFief(name) != null) {
sender.sendMessage("${ChatColor.RED}A fief with that name already exists.")
return false
}

// player must be in a faction
val mfPlayer = plugin.medievalFactions.services.playerService.getPlayer(sender)
val faction = plugin.medievalFactions.services.factionService.getFaction(mfPlayer?.id ?: return false)
if (faction == null) {
sender.sendMessage("${ChatColor.RED}You must be in a faction to create a fief.")
return false
}

// player must not be in a fief already
val playersFief = plugin.fiefRepository.getPlayersFief(mfPlayer.id)
if (playersFief != null) {
sender.sendMessage("${ChatColor.RED}You're already in a fief. You must leave it first.")
return false
}

val newFief = Fief(name, mfPlayer.id, faction.id)
plugin.fiefRepository.addFief(newFief)
sender.sendMessage("${ChatColor.GREEN}Fief created.")
return true
}

override fun onTabComplete(
sender: CommandSender,
command: Command,
alias: String,
args: Array<out String>
): List<String> {
return emptyList()
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.dansplugins.fiefs.command.fiefs.help

import com.dansplugins.fiefs.Fiefs
import org.bukkit.ChatColor.AQUA
import org.bukkit.ChatColor
import org.bukkit.command.Command
import org.bukkit.command.CommandExecutor
import org.bukkit.command.CommandSender
Expand All @@ -10,8 +10,10 @@ import org.bukkit.command.TabCompleter
class FiefsHelpCommand(private val plugin: Fiefs) : CommandExecutor, TabCompleter {
override fun onCommand(sender: CommandSender, command: Command, label: String, args: Array<out String>): Boolean {
// send list of commands
sender.sendMessage("${AQUA}=== Fiefs Commands ===")
sender.sendMessage("${AQUA}/fiefs help - Displays a list of useful commands.")
sender.sendMessage("${ChatColor.AQUA}=== Fiefs Commands ===")
sender.sendMessage("${ChatColor.AQUA}/fiefs help - Displays a list of useful commands.")
sender.sendMessage("${ChatColor.AQUA}/fiefs create <name> - Creates a fief.")
sender.sendMessage("${ChatColor.AQUA}/fiefs list - Lists all fiefs.")
return true
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.dansplugins.fiefs.command.fiefs.list

import com.dansplugins.fiefs.Fiefs
import org.bukkit.ChatColor
import org.bukkit.command.Command
import org.bukkit.command.CommandExecutor
import org.bukkit.command.CommandSender
import org.bukkit.command.TabCompleter

class FiefsListCommand(private val plugin: Fiefs) : CommandExecutor, TabCompleter {
override fun onCommand(sender: CommandSender, command: Command, label: String, args: Array<out String>): Boolean {
if (plugin.fiefRepository.getFiefs().isEmpty()) {
Copy link
Member

Choose a reason for hiding this comment

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

Assuming the fief repository will read these from the database, you may wish to be careful about threading - commands are run on the main thread, and database queries perform I/O which would cause lag spikes each time the command was run.
Additionally, I'd recommend adding another layer of abstraction in a fief service type thing (which contains any domain logic) so your command isn't interfacing directly with the database.

sender.sendMessage("${ChatColor.RED}There are no fiefs.")
return false
}
sender.sendMessage("${ChatColor.AQUA}=== Fiefs ===")
for (fief in plugin.fiefRepository.getFiefs()) {
sender.sendMessage("${ChatColor.AQUA}" + fief.getName())
}
return true
}

override fun onTabComplete(
sender: CommandSender,
command: Command,
alias: String,
args: Array<out String>
): List<String> {
return emptyList()
}
}
38 changes: 38 additions & 0 deletions src/main/kotlin/com/dansplugins/fiefs/fief/Fief.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.dansplugins.fiefs.fief

import com.dansplugins.factionsystem.faction.MfFactionId
import com.dansplugins.factionsystem.player.MfPlayerId
import java.util.UUID

data class Fief(private val name: String, private val ownerMfPlayerId: MfPlayerId, private val mfFactionid: MfFactionId) {
private var id = MfFiefId.generate()
private var members: MutableList<MfPlayerId> = mutableListOf()
Copy link
Member

Choose a reason for hiding this comment

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

Unless you're replacing the entire list, this can be a val.
Additionally, if you use a List instead of a MutableList, this class can be immutable.
id and members could probably be moved into the constructor and given a default value.


fun getId(): MfFiefId {
return id
}

fun addMember(mfPlayerId: MfPlayerId) {
members.add(mfPlayerId)
}

fun removeMember(mfPlayerId: MfPlayerId) {
members.remove(mfPlayerId)
}

fun isMember(mfPlayerId: MfPlayerId): Boolean {
return members.contains(mfPlayerId) || ownerMfPlayerId == mfPlayerId
}

fun getMembers(): List<MfPlayerId> {
return members
}

fun getOwnerId(): MfPlayerId {
return ownerMfPlayerId
}

fun getName(): String {
return name
}
}
79 changes: 79 additions & 0 deletions src/main/kotlin/com/dansplugins/fiefs/fief/FiefRepository.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package com.dansplugins.fiefs.fief

import com.dansplugins.factionsystem.player.MfPlayerId
import com.dansplugins.fiefs.Fiefs
import java.util.*

/**
* Stores all Fiefs in a list and provides methods for accessing and modifying the list.
*/
class FiefRepository(private val plugin: Fiefs) {
private val fiefs = mutableListOf<Fief>()
Copy link
Member

Choose a reason for hiding this comment

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

I assume eventually this will be backed by a DB, negating the need for the list in the repository, but this is fine for testing purposes.


/**
* Adds a Fief to the list.
* @param fief The Fief to add.
*/
fun addFief(fief: Fief) {
fiefs.add(fief)
}

/**
* Removes a Fief from the list.
* @param fief The Fief to remove.
*/
fun removeFief(fief: Fief) {
fiefs.remove(fief)
}

/**
* Gets a Fief from the list.
* @param name The name of the Fief to get.
* @return The Fief with the given name.
*/
fun getFief(name: String): Fief? {
for (fief in fiefs) {
Copy link
Member

Choose a reason for hiding this comment

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

The more functional approach to this adds a good deal of brevity and is clearer in its intent imo:
return fiefs.single { it.name == name }

You can also use .equals(ignoreCase = true) if you want case insensitive comparisons.

Can multiple fiefs have the same name?

if (fief.getName() == name) {
return fief
}
}
return null
}

/**
* Gets a Fief from the list.
* @param mfFiefId The ID of the Fief to get.
* @return The Fief with the given UUID.
*/
fun getFief(mfFiefId: MfFiefId): Fief? {
for (fief in fiefs) {
if (fief.getId() == mfFiefId) {
return fief
}
}
return null
}

/**
* Gets a player's fief from the list.
* @param mfPlayerId The ID of the player whose fief to get.
* @return The Fief which the player is a member of.
* @return null if the player is not a member of any fief.
*/
fun getPlayersFief(mfPlayerId: MfPlayerId): Fief? {
for (fief in fiefs) {
if (fief.isMember(mfPlayerId)) {
return fief
}
}
return null
}

/**
* Gets a list of all Fiefs.
* @return A list of all Fiefs.
*/
fun getFiefs(): List<Fief> {
return fiefs
}
}
10 changes: 10 additions & 0 deletions src/main/kotlin/com/dansplugins/fiefs/fief/MfFiefId.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.dansplugins.fiefs.fief

import java.util.*

@JvmInline
value class MfFiefId(val value: String) {
companion object {
fun generate() = MfFiefId(UUID.randomUUID().toString())
}
}
12 changes: 9 additions & 3 deletions src/main/resources/plugin.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,16 @@ description: An expansion for Medieval Factions that allows faction members to c

commands:
fiefs:
description: The main command for Fiefs.
usage: /fiefs
description: The main command for Fiefs. Subcommands include:: help, create, list
aliases: [fi]

permissions:
fiefs.help:
default: true
default: true
description: Allows the player to view the help menu.
fiefs.create:
default: true
description: Allows the player to create a fief.
fiefs.list:
default: true
description: Allows the player to view a list of all fiefs.
43 changes: 43 additions & 0 deletions src/test/kotlin/com/dansplugins/fiefs/command/TestFiefsCommand.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.dansplugins.fiefs.command

import com.dansplugins.fiefs.Fiefs
import com.dansplugins.fiefs.command.fiefs.FiefsCommand
import io.mockk.every
import io.mockk.mockk
import io.mockk.verify
import org.bukkit.ChatColor
import org.bukkit.command.Command
import org.bukkit.command.CommandSender
import org.junit.jupiter.api.Test

class TestFiefsCommand {

private val mockPlugin = mockk<Fiefs>() {
every { description.version } returns "1.0.0"
every { description.authors } returns listOf("Dan")
every { description.description } returns "A plugin about fiefs."
}

@Test
fun testFiefsCommandNoArguments() {
// prepare
val mockSender = mockk<CommandSender>() {
every { sendMessage(any<String>()) } returns Unit
}
val mockCommand = mockk<Command>()
val args = emptyArray<String>()
val label = "fiefs"
val fiefsCommand = FiefsCommand(mockPlugin)

// execute
fiefsCommand.onCommand(mockSender, mockCommand, label, args)

// verify
val expectedAuthors = mockPlugin.description.authors
val expectedDescription = mockPlugin.description.description
verify(exactly = 1) { mockSender.sendMessage("${ChatColor.AQUA}Fiefs v1.0.0") }
verify(exactly = 1) { mockSender.sendMessage("${ChatColor.AQUA}Author: $expectedAuthors") }
verify(exactly = 1) { mockSender.sendMessage("${ChatColor.AQUA}Description: $expectedDescription") }
verify(exactly = 1) { mockSender.sendMessage("${ChatColor.GREEN}Type /fiefs help for a list of commands.") }
}
}
Loading