Skip to content

Commit

Permalink
cleanup enchant
Browse files Browse the repository at this point in the history
  • Loading branch information
Miles Holder committed May 9, 2024
1 parent b805cdf commit df5a4ef
Show file tree
Hide file tree
Showing 10 changed files with 290 additions and 117 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.github.spigotbasics.core.command.parsed.arguments

import org.bukkit.Bukkit
import org.bukkit.Keyed
import org.bukkit.NamespacedKey
import org.bukkit.Registry
import org.bukkit.command.CommandSender
import java.util.stream.Collectors

class BukkitRegistryArg<T : Keyed>(name: String, registryClass: Class<T>) : CommandArgument<T>(name) {
private val registry: Registry<T> = Bukkit.getRegistry(registryClass) ?: error("$registryClass is not a bukkit registry type")

override fun parse(
sender: CommandSender,
value: String,
): T? {
return if (value.isBlank()) null else registry.get(NamespacedKey.fromString(value) ?: return null)
}

override fun tabComplete(
sender: CommandSender,
typing: String,
): List<String> {
return registry.stream().map { entry ->
val namespacedKeyed = entry.key
if (namespacedKeyed.namespace == NamespacedKey.MINECRAFT) {
return@map namespacedKeyed.key
}
return@map namespacedKeyed.toString()
}.collect(Collectors.toList())
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ class SpigotChatEventListener(private val module: BasicsChatFormatModule) : List
event.format =
module.chatFormat.concerns(event.player)
.tagUnparsed("message", event.message) // TODO: To allow MiniMessage in chat, this should be parsed.
.tagParsed("message-color", "<${module.chatFormatStore.getChatDataOrDefault(event.player.uniqueId).color}>").toLegacyString()
.tagParsed(
"message-color",
"<${module.chatFormatStore.getChatDataOrDefault(event.player.uniqueId).color}>",
).toLegacyString()
.escapeFormat()
}
}
12 changes: 8 additions & 4 deletions modules/basics-enchant/README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
| Command | Permission |
|------------------------------|-----------------------|
| `/enchant <enchant> [level]` | basics.enchant |
| Command | Permission |
|---------------------------------------|----------------------|
| `/enchant <enchant> [level]` | basics.enchant |
| `/enchant <target> <enchant> [level]` | basics.enchant.other |

> [!NOTE]
> Players additionally require enchantment-specific permissions: `basics.enchant.<enchantment>`.
> [!NOTE]
> Enchanting items with unsafe levels additionally requires permission `basics.enchant.unsafe`.
> Enchanting items with unsafe levels additionally requires permission `basics.enchant.unsafe.level`.
> [!NOTE]
> Enchanting items with unsafe enchants additional requires permission `basics.enchant.unsafe.enchant`
Original file line number Diff line number Diff line change
@@ -1,107 +1,78 @@
package com.github.spigotbasics.modules.basicsenchant

import com.github.spigotbasics.core.command.common.BasicsCommandExecutor
import com.github.spigotbasics.core.command.common.CommandResult
import com.github.spigotbasics.core.command.raw.RawCommandContext
import com.github.spigotbasics.core.extensions.partialMatches
import com.github.spigotbasics.core.extensions.toHumanReadable
import com.github.spigotbasics.core.command.parsed.arguments.BukkitRegistryArg
import com.github.spigotbasics.core.command.parsed.arguments.IntRangeArg
import com.github.spigotbasics.core.command.parsed.arguments.SelectorMultiEntityArg
import com.github.spigotbasics.core.command.parsed.arguments.SelectorSinglePlayerArg
import com.github.spigotbasics.core.config.ConfigName
import com.github.spigotbasics.core.module.AbstractBasicsModule
import com.github.spigotbasics.core.module.loader.ModuleInstantiationContext
import org.bukkit.Bukkit
import com.github.spigotbasics.modules.basicsenchant.command.EnchantmentCommandOther
import com.github.spigotbasics.modules.basicsenchant.command.EnchantmentCommandSelf
import org.bukkit.enchantments.Enchantment
import org.bukkit.entity.Player

class BasicsEnchantModule(context: ModuleInstantiationContext) : AbstractBasicsModule(context) {
val permission =
private val commandPermission =
permissionManager.createSimplePermission("basics.enchant", "Allows players access to the /enchant command")
private val commandOtherPermission = permissionManager.createSimplePermission(
"basics.enchant.other",
"Allows players access to the /enchant command to enchant others"
)
val unsafeLevelsPermission =
permissionManager.createSimplePermission(
"basics.enchant",
"Allows the player to enchant items",
"basics.enchant.unsafe.level",
"Allows assignment of unsafe levels for enchantments",
)

val permissionUnsafeLevels =
val unsafeEnchantPermission =
permissionManager.createSimplePermission(
"basics.enchant.allowunsafe",
"Allows the player to enchant items with unsafe levels",
"basics.enchant.unsafe.enchant",
"Allows assignment of unsafe enchantments to item",
)

val enchantments = Bukkit.getRegistry(Enchantment::class.java)?.map { it.key.key.lowercase() }?.toList() ?: emptyList()

val enchantmentPermissions =
Bukkit.getRegistry(Enchantment::class.java)?.associateWith { enchantment ->
val name = enchantment.key.key.lowercase()
permissionManager.createSimplePermission(
"basics.enchant.$name",
"Allows the player to enchant items with the ${name.toHumanReadable()} enchantment",
)
} ?: emptyMap()

fun msgEnchantedSelf(tag: EnchantOperationMessageTag) = messages.getMessage("enchanted-self").tags(tag)

// TODO: Cannot enchant others stuff yet
fun msgEnchantedOthers(
tag: EnchantOperationMessageTag,
player: Player,
) = messages.getMessage("enchanted-others")
.tags(tag)
.concerns(player)

fun msgRemovedSelf(tag: EnchantOperationMessageTag) = messages.getMessage("removed-self").tags(tag)
override val messages: Messages = getConfig(ConfigName.MESSAGES, Messages::class.java)

override fun onEnable() {
commandFactory.rawCommandBuilder("enchant", permission)
.description("Enchants the item in the player's hand")
.usage("<enchantment> [level]")
.executor(EnchantExecutor())
.register()
}

inner class EnchantExecutor : BasicsCommandExecutor(this@BasicsEnchantModule) {
override fun execute(context: RawCommandContext): CommandResult {
val player = requirePlayerOrMustSpecifyPlayerFromConsole(context.sender) // TODO: Create a requirePlayer(Sender) method
val args = context.args
if (args.size == 0) return CommandResult.USAGE
val item = requireItemInHand(player)
val enchantment = getEnchantment(args[0]) ?: throw failInvalidArgument(args[0]).asException()
var desiredLevel = (item.itemMeta?.getEnchantLevel(enchantment) ?: 0) + 1
val maxLevel = enchantment.maxLevel
if (args.size > 1) {
desiredLevel = args[1].toIntOrNull() ?: throw failInvalidArgument(args[1]).asException()
val instance = this
commandFactory.parsedCommandBuilder("enchant", commandPermission).mapContext {
val basicExecutor = EnchantmentCommandSelf(instance)
val otherExecutor = EnchantmentCommandOther(instance)
usage = "<enchantment> [level]"
path {
playerOnly()
arguments {
named("enchantment", BukkitRegistryArg("enchantment", Enchantment::class.java))
}
executor(basicExecutor)
}

// Unsafe levels require extra perm
if (desiredLevel > maxLevel) {
requirePermission(context.sender, permissionUnsafeLevels)
path {
playerOnly()
arguments {
named("enchantment", BukkitRegistryArg("enchantment", Enchantment::class.java))
named("level", IntRangeArg("level", { 0 }, { 255 }))
executor(basicExecutor)
}
}

// Enchantment-specific permissions
enchantmentPermissions[enchantment]?.let { requirePermission(context.sender, it) }

val tag = EnchantOperationMessageTag(item, enchantment, desiredLevel)

if (desiredLevel == 0) {
item.removeEnchantment(enchantment) // TODO: message "removed enchantment"
msgRemovedSelf(tag).sendToPlayer(player)
return CommandResult.SUCCESS
path {
permissions(commandOtherPermission)
arguments {
named("targets", SelectorMultiEntityArg("targets"))
named("enchantment", BukkitRegistryArg("enchantment", Enchantment::class.java))
named("level", IntRangeArg("level", { 0 }, { 255 }))
executor(otherExecutor)
}
}

item.addUnsafeEnchantment(
enchantment,
desiredLevel,
) // TODO: Separate permission for unsafe enchants, separate permission for max-level and for enchantment type
msgEnchantedSelf(tag).sendToPlayer(player)
return CommandResult.SUCCESS
}

override fun tabComplete(context: RawCommandContext): List<String>? {
val args = context.args
if (args.size == 1) {
return enchantments.partialMatches(args[0])
path {
permissions(commandOtherPermission)
arguments {
named("player", SelectorSinglePlayerArg("player"))
named("enchantment", BukkitRegistryArg("enchantment", Enchantment::class.java))
named("level", IntRangeArg("level", { 0 }, { 255 }))
executor(otherExecutor)
}
}
return null
}

private fun getEnchantment(name: String): Enchantment? {
return Bukkit.getRegistry(Enchantment::class.java)?.match(name.lowercase())
}
}.register()
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package com.github.spigotbasics.modules.basicsenchant

import com.github.spigotbasics.core.config.ConfigInstantiationContext
import com.github.spigotbasics.core.config.SavedConfig
import com.github.spigotbasics.core.extensions.toHumanReadable
import com.github.spigotbasics.core.extensions.toRoman
import com.github.spigotbasics.core.messages.Message
import org.bukkit.enchantments.Enchantment
import org.bukkit.entity.LivingEntity
import org.bukkit.entity.Player
import org.bukkit.inventory.ItemStack

class Messages(context: ConfigInstantiationContext) : SavedConfig(context) {
fun enchantmentSelf(
item: ItemStack,
enchantment: Enchantment,
level: Int,
): Message = modifyEnchantMessage(getMessage("enchanted-self"), item, enchantment, level)

fun enchantEntity(
entity: LivingEntity,
item: ItemStack,
enchantment: Enchantment,
level: Int,
): Message =
modifyEnchantMessage(
getMessage("enchanted-entity"),
item,
enchantment,
level,
).tagParsed("entity", entity.type.key.key.toHumanReadable())

fun enchantPlayer(
player: Player,
item: ItemStack,
enchantment: Enchantment,
level: Int,
): Message = modifyEnchantMessage(getMessage("enchanted-others"), item, enchantment, level).tagParsed("player", player.name)

fun enchantInvalidCombinationSelf(
item: ItemStack,
enchantment: Enchantment,
): Message =
getMessage("enchanted-invalid-combination-self")
.tagParsed("item", item.type.name.toHumanReadable())
.tagParsed("enchantment", enchantment.key.key.toHumanReadable())

fun enchantInvalidCombinationEntity(
entity: LivingEntity,
item: ItemStack,
enchantment: Enchantment,
): Message =
getMessage("enchanted-invalid-combination-entity")
.tagParsed("entity", entity.type.key.key.toHumanReadable())
.tagParsed("item", item.type.name.toHumanReadable())
.tagParsed("enchantment", enchantment.key.key.toHumanReadable())

fun enchantInvalidCombinationOther(
item: ItemStack,
enchantment: Enchantment,
): Message =
getMessage("enchanted-invalid-combination-others")
.tagParsed("item", item.type.name.toHumanReadable())
.tagParsed("enchantment", enchantment.key.key.toHumanReadable())

private fun modifyEnchantMessage(
message: Message,
item: ItemStack,
enchantment: Enchantment,
level: Int,
): Message =
message.tagParsed("item", item.type.name.toHumanReadable())
.tagParsed("enchantment", enchantment.key.key.toHumanReadable())
.tagParsed("level", level.toString())
.tagUnparsed("roman-level", level.toRoman())
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package com.github.spigotbasics.modules.basicsenchant.command

import com.github.spigotbasics.core.command.parsed.CommandContextExecutor
import com.github.spigotbasics.core.command.parsed.context.MapContext
import com.github.spigotbasics.core.messages.Message
import com.github.spigotbasics.modules.basicsenchant.BasicsEnchantModule
import org.bukkit.Material
import org.bukkit.command.CommandSender
import org.bukkit.enchantments.Enchantment
import org.bukkit.entity.LivingEntity
import org.bukkit.entity.Player

class EnchantmentCommandOther(private val module: BasicsEnchantModule) : CommandContextExecutor<MapContext> {
override fun execute(
sender: CommandSender,
context: MapContext,
) {
val targets = mutableListOf<LivingEntity>()
if (context["targets"] is List<*>) {
targets.addAll((context["targets"] as List<*>).filterIsInstance<LivingEntity>())
} else if (context["player"] is Player) {
targets.add(context["player"] as LivingEntity)
}

val enchantment = context["enchantment"] as Enchantment
val level = context["level"] as Int

if (level > enchantment.maxLevel && !sender.hasPermission(module.unsafeLevelsPermission)) {
module.coreMessages.invalidValueForArgument("level", level.toString()).concerns(sender as? Player).sendToSender(sender)
return
}

targets.forEach {
val equipment = it.equipment ?: return
val item = equipment.itemInMainHand
if (item.type == Material.AIR) {
return@forEach
}

if (!enchantment.canEnchantItem(item) && sender.hasPermission(module.unsafeEnchantPermission)) {
val message: Message =
if (it is Player) {
module.messages.enchantInvalidCombinationOther(item, enchantment).concerns(it)
} else {
module.messages.enchantInvalidCombinationEntity(it, item, enchantment)
}
message.sendToSender(sender)
return
}

val meta = item.itemMeta!!
meta.addEnchant(enchantment, level, sender.hasPermission(module.unsafeLevelsPermission))
item.itemMeta = meta
equipment.setItemInMainHand(item)

val message =
if (it is Player) {
module.messages.enchantPlayer(it, item, enchantment, level).concerns(it)
} else {
module.messages.enchantEntity(it, item, enchantment, level)
}

message.sendToSender(sender)
}
}
}
Loading

0 comments on commit df5a4ef

Please sign in to comment.