Reworked commands

::commands now very pretty, paged and documents each command user has access to including privilege required
Command definitions now support adding documentation in-place.
Adds new command to hot-reload JSON while server is running (::reloadjson)
This commit is contained in:
Ceikry
2022-07-05 13:20:55 +00:00
committed by Ryan
parent b5213c40b4
commit 7c95c0725f
13 changed files with 189 additions and 86 deletions
+3 -3
View File
@@ -41,9 +41,9 @@ interface Commands : ContentInterface {
* @param name the name of the command. Example: ::example would be just "example" * @param name the name of the command. Example: ::example would be just "example"
* @param privilege the rights level needed to execute the command. Options are [Privilege.STANDARD], [Privilege.MODERATOR], [Privilege.ADMIN]. Defaults to [Privilege.STANDARD] * @param privilege the rights level needed to execute the command. Options are [Privilege.STANDARD], [Privilege.MODERATOR], [Privilege.ADMIN]. Defaults to [Privilege.STANDARD]
*/ */
fun define(name: String, privilege: Privilege = Privilege.STANDARD, handle: (Player, Array<String>) -> Unit){ fun define(name: String, privilege: Privilege = Privilege.STANDARD, usage: String = "", description: String = "", handle: (Player, Array<String>) -> Unit){
CommandMapping.register(Command(name, privilege, handle)) CommandMapping.register(Command(name, privilege, usage, description, handle))
} }
fun defineCommands() fun defineCommands()
} }
@@ -2,19 +2,19 @@ package rs09.game.system.command
import core.game.node.entity.player.Player import core.game.node.entity.player.Player
import rs09.game.world.GameWorld import rs09.game.world.GameWorld
import kotlin.collections.ArrayList
/** /**
* Base class for Commands in the new system. Can pass a lambda as part of the constructor or after the constructor. * Base class for Commands in the new system. Can pass a lambda as part of the constructor or after the constructor.
* @author Ceikry * @author Ceikry
*/ */
class Command(val name: String, val privilege: Privilege, val handle: (Player, Array<String>) -> Unit) { class Command(val name: String, val privilege: Privilege, val usage: String = "UNDOCUMENTED", val description: String = "UNDOCUMENTED", val handle: (Player, Array<String>) -> Unit) {
fun attemptHandling(player: Player, args: Array<String>?){ fun attemptHandling(player: Player, args: Array<String>?){
args ?: return args ?: return
if(player.rights.ordinal >= privilege.ordinal || GameWorld.settings?.isDevMode == true){ if(player.rights.ordinal >= privilege.ordinal || GameWorld.settings?.isDevMode == true){
handle(player,args) handle(player,args)
} }
} }
} }
object CommandMapping { object CommandMapping {
@@ -35,4 +35,24 @@ object CommandMapping {
fun getNames(): Array<String> { fun getNames(): Array<String> {
return mapping.keys.toTypedArray() return mapping.keys.toTypedArray()
} }
}
fun getPageIndices(rights: Int): IntArray {
val list = ArrayList<Int>()
list.add(0)
var lineCounter = 0
for ((index, command) in getCommands().filter { it.privilege.ordinal <= rights }.withIndex()) {
lineCounter += 2
if (command.usage.isNotEmpty()) lineCounter++
if (command.description.isNotEmpty()) lineCounter++
if (lineCounter > 306) {
list.add(index)
lineCounter = 0
}
}
return list.toIntArray()
}
}
@@ -20,7 +20,7 @@ class AnimationCommandSet : CommandSet(Privilege.ADMIN) {
/** /**
* Force the player to play animation <Animation ID> * Force the player to play animation <Animation ID>
*/ */
define("anim"){ player, args -> define("anim", Privilege.ADMIN, "::anim <lt>Animation ID<gt>", "Plays the animation with the given ID."){ player, args ->
if (args.size < 2) { if (args.size < 2) {
reject(player, "Syntax error: ::anim <Animation ID>") reject(player, "Syntax error: ::anim <Animation ID>")
} }
@@ -31,7 +31,7 @@ class AnimationCommandSet : CommandSet(Privilege.ADMIN) {
/** /**
* Force the player to loop animation <Animation ID> * Force the player to loop animation <Animation ID>
*/ */
define("loopanim"){ player, args -> define("loopanim", Privilege.ADMIN, "::loopanim <lt>Animation ID<gt> <lt>Times<gt>", "Plays the animation with the given ID the given number of times"){ player, args ->
if (args.size < 2) { if (args.size < 2) {
reject(player, "Syntax error: ::loopanim <Animation ID> <Loop Amount>") reject(player, "Syntax error: ::loopanim <Animation ID> <Loop Amount>")
} }
@@ -53,7 +53,7 @@ class AnimationCommandSet : CommandSet(Privilege.ADMIN) {
/** /**
* Change the player's render animation to <Render Animation ID> * Change the player's render animation to <Render Animation ID>
*/ */
define("ranim"){ player, args -> define("ranim", Privilege.ADMIN, "::ranim <lt>Render Anim ID<gt>", "Sets the player's render (walk/idle) animation."){ player, args ->
if (args.size < 2) { if (args.size < 2) {
reject(player, "Syntax error: ::ranim <Render Animation ID>") reject(player, "Syntax error: ::ranim <Render Animation ID>")
} }
@@ -69,11 +69,11 @@ class AnimationCommandSet : CommandSet(Privilege.ADMIN) {
/** /**
* Reset the player's render animation to default * Reset the player's render animation to default
*/ */
define("ranimreset"){ player, _ -> define("ranimreset", Privilege.ADMIN, "", "Resets the player's render (walk/idle) animation to default."){ player, _ ->
player.appearance.prepareBodyData(player) player.appearance.prepareBodyData(player)
player.appearance.setDefaultAnimations() player.appearance.setDefaultAnimations()
player.appearance.setAnimations() player.appearance.setAnimations()
player.appearance.sync() player.appearance.sync()
} }
} }
} }
@@ -14,6 +14,11 @@ import rs09.tools.stringtools.colorize
@Initializable @Initializable
class BottingCommandSet : CommandSet(Privilege.STANDARD) { class BottingCommandSet : CommandSet(Privilege.STANDARD) {
override fun defineCommands() { override fun defineCommands() {
if (GameWorld.settings?.enabled_botting != true) {
return
}
define("scripts"){player, _ -> define("scripts"){player, _ ->
if(GameWorld.settings?.enabled_botting != true){ if(GameWorld.settings?.enabled_botting != true){
player.sendChat("I just tried to do something silly!") player.sendChat("I just tried to do something silly!")
@@ -69,4 +74,4 @@ class BottingCommandSet : CommandSet(Privilege.STANDARD) {
player.interfaceManager.closeOverlay() player.interfaceManager.closeOverlay()
} }
} }
} }
@@ -51,7 +51,7 @@ abstract class CommandSet(val defaultPrivilege: Privilege) : Plugin<Any?> {
* @param name the name of the command. Example: ::example would be just "example" * @param name the name of the command. Example: ::example would be just "example"
* @param privilege (optional) privilege override from the set default. * @param privilege (optional) privilege override from the set default.
*/ */
fun define(name: String, privilege: Privilege = defaultPrivilege, handle: (Player, Array<String>) -> Unit){ fun define(name: String, privilege: Privilege = defaultPrivilege, usage: String = "", description: String = "", handle: (Player, Array<String>) -> Unit){
CommandMapping.register(Command(name, privilege, handle)) CommandMapping.register(Command(name, privilege, usage, description, handle))
} }
} }
@@ -41,7 +41,7 @@ class ConfigCommandSet : CommandSet(Privilege.ADMIN){
/** /**
* Opens an interface component * Opens an interface component
*/ */
define("iface"){player, args -> define("iface", Privilege.ADMIN, "::iface <lt>Interface ID<gt>", "Opens the interface with the given ID."){player, args ->
if (args.size < 2) { if (args.size < 2) {
reject(player, "usage: iface id") reject(player, "usage: iface id")
return@define return@define
@@ -50,4 +50,4 @@ class ConfigCommandSet : CommandSet(Privilege.ADMIN){
player.interfaceManager.openComponent(id as Int) player.interfaceManager.openComponent(id as Int)
} }
} }
} }
@@ -33,7 +33,7 @@ class DevelopmentCommandSet : CommandSet(Privilege.ADMIN) {
/** /**
* Gives the player a set of tools used to test farming stuff. * Gives the player a set of tools used to test farming stuff.
*/ */
define("farmkit"){player,_ -> define("farmkit", Privilege.ADMIN, "", "Provides a kit of various farming equipment."){player,_ ->
for(item in farmKitItems){ for(item in farmKitItems){
player.inventory.add(Item(item)) player.inventory.add(Item(item))
} }
@@ -51,11 +51,11 @@ class DevelopmentCommandSet : CommandSet(Privilege.ADMIN) {
sendMessage(player, "All achievement diaries cleared successfully.") sendMessage(player, "All achievement diaries cleared successfully.")
} }
define("region") {player, args -> define("region", Privilege.STANDARD, "", "Prints your current Region ID.") {player, args ->
sendMessage(player, "Region ID: ${player.viewport.region.regionId}") sendMessage(player, "Region ID: ${player.viewport.region.regionId}")
} }
define("spellbook"){player, args -> define("spellbook", Privilege.ADMIN, "::spellbook <lt>book ID<gt> (0 = MODERN, 1 = ANCIENTS, 2 = LUNARS)", "Swaps your spellbook to the given book ID."){player, args ->
if(args.size < 2){ if(args.size < 2){
reject(player,"Usage: ::spellbook [int]. 0 = MODERN, 1 = ANCIENTS, 2 = LUNARS") reject(player,"Usage: ::spellbook [int]. 0 = MODERN, 1 = ANCIENTS, 2 = LUNARS")
} }
@@ -64,7 +64,7 @@ class DevelopmentCommandSet : CommandSet(Privilege.ADMIN) {
player.spellBookManager.update(player) player.spellBookManager.update(player)
} }
define("killme") { player, _ -> define("killme", Privilege.ADMIN, "", "Does exactly what it says on the tin.") { player, _ ->
player.impactHandler.manualHit(player, player.skills.lifepoints, HitsplatType.NORMAL) player.impactHandler.manualHit(player, player.skills.lifepoints, HitsplatType.NORMAL)
} }
@@ -82,7 +82,7 @@ class DevelopmentCommandSet : CommandSet(Privilege.ADMIN) {
SystemLogger.logInfo(def.toString()) SystemLogger.logInfo(def.toString())
} }
define("dumpstructs") {player, _ -> define("dumpstructs", Privilege.ADMIN, "", "Dumps all the cache structs to structs.txt") {player, _ ->
val dump = File("structs.txt") val dump = File("structs.txt")
val writer = BufferedWriter(FileWriter(dump)) val writer = BufferedWriter(FileWriter(dump))
val index = Cache.getIndexes()[2] val index = Cache.getIndexes()[2]
@@ -101,7 +101,7 @@ class DevelopmentCommandSet : CommandSet(Privilege.ADMIN) {
writer.close() writer.close()
} }
define("dumpdatamaps") {player, _ -> define("dumpdatamaps", Privilege.ADMIN, "", "Dumps all the cache data maps to datamaps.txt") {player, _ ->
val index = Cache.getIndexes()[17] val index = Cache.getIndexes()[17]
val containers = index.information.containersIndexes val containers = index.information.containersIndexes
@@ -126,7 +126,7 @@ class DevelopmentCommandSet : CommandSet(Privilege.ADMIN) {
writer.close() writer.close()
} }
define("rolldrops") { player: Player, args: Array<String> -> define("rolldrops", Privilege.ADMIN, "::rolldrops <lt>NPC ID<gt> <lt>AMOUNT<gt>", "Rolls the given NPC drop table AMOUNT times.") { player: Player, args: Array<String> ->
if(args.size < 2){ if(args.size < 2){
reject(player,"Usage: ::rolldrops npcid amount") reject(player,"Usage: ::rolldrops npcid amount")
} }
@@ -146,9 +146,9 @@ class DevelopmentCommandSet : CommandSet(Privilege.ADMIN) {
container.open(player) container.open(player)
} }
define("varbits") { player, args -> define("varbits", Privilege.ADMIN, "::varbits <lt>Varp ID<gt>", "Lists all the varbits assigned to the given varp.") { player, args ->
if(args.size < 2) if(args.size < 2)
reject(player, "Usage: ::list_varbits varpIndex") reject(player, "Usage: ::varbits varpIndex")
val varp = args[1].toIntOrNull() ?: reject(player, "Please use a valid int for the varpIndex.") val varp = args[1].toIntOrNull() ?: reject(player, "Please use a valid int for the varpIndex.")
GlobalScope.launch { GlobalScope.launch {
@@ -29,7 +29,7 @@ class FunCommandSet : CommandSet(Privilege.ADMIN) {
/** /**
* Force animation + messages on all NPCs in a radius of 10 from the player. * Force animation + messages on all NPCs in a radius of 10 from the player.
*/ */
define("npcareaanim") { player, args -> define("npcareaanim", Privilege.ADMIN, "::npcareaanim <lt>Animation ID<gt> <lt>String<gt>") { player, args ->
if (args.size < 3) { if (args.size < 3) {
reject(player, "Syntax error: ::npcareaanim <Animation ID> <String>") reject(player, "Syntax error: ::npcareaanim <Animation ID> <String>")
} }
@@ -47,7 +47,7 @@ class FunCommandSet : CommandSet(Privilege.ADMIN) {
/** /**
* Transform a player's appearance into that of an NPC. * Transform a player's appearance into that of an NPC.
*/ */
define("pnpc", Privilege.MODERATOR){ player, args -> define("pnpc", Privilege.MODERATOR, "::pnpc <lt>NPC ID<gt>", "Transforms the player into the given NPC."){ player, args ->
if(args.size < 2){ if(args.size < 2){
reject(player, "Usage: ::pnpc <npcid>") reject(player, "Usage: ::pnpc <npcid>")
return@define return@define
@@ -66,14 +66,14 @@ class FunCommandSet : CommandSet(Privilege.ADMIN) {
/** /**
* Open bank * Open bank
*/ */
define("bank"){ player, _ -> define("bank", Privilege.ADMIN, "", "Opens your bank."){ player, _ ->
player.getBank().open() player.getBank().open()
} }
/** /**
* Toggle invisibility * Toggle invisibility
*/ */
define("invis"){ player, _ -> define("invis", Privilege.ADMIN, "", "Makes you invisible to others."){ player, _ ->
player.isInvisible = !player.isInvisible player.isInvisible = !player.isInvisible
notify(player,"You are now ${if (player.isInvisible) "invisible" else "visible"} to others.") notify(player,"You are now ${if (player.isInvisible) "invisible" else "visible"} to others.")
} }
@@ -82,7 +82,7 @@ class FunCommandSet : CommandSet(Privilege.ADMIN) {
/** /**
* Toggle 1-hit kills * Toggle 1-hit kills
*/ */
define("1hit"){ player, _ -> define("1hit", Privilege.ADMIN, "", "Makes you kill things in 1 hit."){ player, _ ->
player.setAttribute("1hko", !player.getAttribute("1hko", false)) player.setAttribute("1hko", !player.getAttribute("1hko", false))
notify(player,"1-hit KO mode " + if (player.getAttribute("1hko", false)) "on." else "off.") notify(player,"1-hit KO mode " + if (player.getAttribute("1hko", false)) "on." else "off.")
} }
@@ -91,7 +91,7 @@ class FunCommandSet : CommandSet(Privilege.ADMIN) {
/** /**
* Toggle god mode * Toggle god mode
*/ */
define("god"){ player, _ -> define("god", Privilege.ADMIN, "", "Makes you invulnerable to damage."){ player, _ ->
player.setAttribute("godMode", !player.getAttribute("godMode", false)) player.setAttribute("godMode", !player.getAttribute("godMode", false))
notify(player,"God mode ${if (player.getAttribute("godMode", false)) "enabled." else "disabled."}") notify(player,"God mode ${if (player.getAttribute("godMode", false)) "enabled." else "disabled."}")
} }
@@ -45,11 +45,11 @@ class MiscCommandSet : CommandSet(Privilege.ADMIN){
/** /**
* Toggles debug mode * Toggles debug mode
*/ */
define("debug", Privilege.STANDARD){ player, _ -> define("debug", Privilege.STANDARD, "", "Toggles debug mode."){ player, _ ->
player.toggleDebug() player.toggleDebug()
} }
define("calc_accuracy", Privilege.STANDARD){ player, args -> define("calc_accuracy", Privilege.STANDARD, "::calc_accuracy <lt>NPC ID<gt>", "Calculates and prints your current chance to hit a given NPC."){ player, args ->
val handler = player.getSwingHandler(false) val handler = player.getSwingHandler(false)
player.sendMessage("handler type: ${handler.type}") player.sendMessage("handler type: ${handler.type}")
player.sendMessage("calculateAccuracy: ${handler.calculateAccuracy(player)}") player.sendMessage("calculateAccuracy: ${handler.calculateAccuracy(player)}")
@@ -64,7 +64,7 @@ class MiscCommandSet : CommandSet(Privilege.ADMIN){
} }
} }
define("movcam", Privilege.ADMIN) {player, args -> define("movcam", Privilege.ADMIN, "::movcam <lt>Region X<gt> <lt>Region Y<gt> [<lt>Height<gt> <lt>Speed<gt>]", "Moves the camera to the given region-local coordinates.") {player, args ->
val regionX = args[1].toIntOrNull() ?: return@define val regionX = args[1].toIntOrNull() ?: return@define
val regionY = args[2].toIntOrNull() ?: return@define val regionY = args[2].toIntOrNull() ?: return@define
var height = 300 var height = 300
@@ -83,7 +83,7 @@ class MiscCommandSet : CommandSet(Privilege.ADMIN){
PlayerCamera(player).panTo(globalLoc.x, globalLoc.y, height, speed) PlayerCamera(player).panTo(globalLoc.x, globalLoc.y, height, speed)
} }
define("rotcam", Privilege.ADMIN) {player, args -> define("rotcam", Privilege.ADMIN, "::rotcam <lt>Region X<gt> <lt>Region Y<gt> [<lt>Height<gt> <lt>Speed<gt>]", "Rotates the camera to face the given region-local coordinates.") {player, args ->
val regionX = args[1].toIntOrNull() ?: return@define val regionX = args[1].toIntOrNull() ?: return@define
val regionY = args[2].toIntOrNull() ?: return@define val regionY = args[2].toIntOrNull() ?: return@define
var height = 300 var height = 300
@@ -109,7 +109,7 @@ class MiscCommandSet : CommandSet(Privilege.ADMIN){
/** /**
* Prints player's current location * Prints player's current location
*/ */
define("loc", Privilege.STANDARD){ player, _-> define("loc", Privilege.STANDARD, "", "Prints quite a lot of information about your current location."){ player, _->
val l = player.location val l = player.location
val r = player.viewport.region val r = player.viewport.region
var obj: Scenery? = null var obj: Scenery? = null
@@ -145,7 +145,7 @@ class MiscCommandSet : CommandSet(Privilege.ADMIN){
notify(player, "Do you mean ::loc?") notify(player, "Do you mean ::loc?")
} }
define("calcmaxhit", Privilege.STANDARD) { player, _ -> define("calcmaxhit", Privilege.STANDARD, "", "Calculates and shows you your current max hit.") { player, _ ->
val swingHandler = player.getSwingHandler(false) val swingHandler = player.getSwingHandler(false)
val hit = swingHandler.calculateHit(player, player, 1.0) val hit = swingHandler.calculateHit(player, player, 1.0)
notify(player, "max hit (${(swingHandler as Object).getClass().getName()}): ${hit}") notify(player, "max hit (${(swingHandler as Object).getClass().getName()}): ${hit}")
@@ -155,7 +155,7 @@ class MiscCommandSet : CommandSet(Privilege.ADMIN){
* Empty a player's inventory * Empty a player's inventory
* ADMIN only (for obvious reasons) * ADMIN only (for obvious reasons)
*/ */
define("empty"){player,_-> define("empty", Privilege.ADMIN, "", "Empties your inventory."){player,_->
player.inventory.clear() player.inventory.clear()
player.inventory.refresh() player.inventory.refresh()
} }
@@ -163,7 +163,7 @@ class MiscCommandSet : CommandSet(Privilege.ADMIN){
/** /**
* Announces a message in chat (NEWS) * Announces a message in chat (NEWS)
*/ */
define("announce"){_,args -> define("announce", Privilege.ADMIN, "::announce <lt>String<gt>", "Sends the given string as a News message."){_,args ->
val message = args.slice(1 until args.size).joinToString(" ") val message = args.slice(1 until args.size).joinToString(" ")
Repository.sendNews(message) Repository.sendNews(message)
} }
@@ -171,7 +171,7 @@ class MiscCommandSet : CommandSet(Privilege.ADMIN){
/** /**
* Lists the players currently online * Lists the players currently online
*/ */
define("players", Privilege.MODERATOR){ player, _ -> define("players", Privilege.MODERATOR, "", "Lists the online players."){ player, _ ->
val rights = player.rights.ordinal val rights = player.rights.ordinal
if (player!!.interfaceManager.isOpened && player.interfaceManager.opened.id != Components.QUESTJOURNAL_SCROLL_275 || player.locks.isMovementLocked || player.locks.isTeleportLocked) { if (player!!.interfaceManager.isOpened && player.interfaceManager.opened.id != Components.QUESTJOURNAL_SCROLL_275 || player.locks.isMovementLocked || player.locks.isTeleportLocked) {
reject(player, "Please finish what you're doing first.") reject(player, "Please finish what you're doing first.")
@@ -198,14 +198,14 @@ class MiscCommandSet : CommandSet(Privilege.ADMIN){
/** /**
* Opens the credit/voting shop * Opens the credit/voting shop
*/ */
define("shop", Privilege.STANDARD){ player, _ -> define("shop", Privilege.STANDARD, "", "Opens the credit shop."){ player, _ ->
player.interfaceManager.open(Component(Components.CREDIT_SHOP)) player.interfaceManager.open(Component(Components.CREDIT_SHOP))
} }
/** /**
* Shows the player a list of currently active GE sell offers * Shows the player a list of currently active GE sell offers
*/ */
define("ge", Privilege.STANDARD) { player, args -> define("ge", Privilege.STANDARD, "::ge <lt>MODE<gt> (Modes: buying, selling, search, bots, botsearch)", "Various commands for viewing GE offers.") { player, args ->
if(args.size < 2){ if(args.size < 2){
reject(player, "Usage: ::ge mode", "Available modes: buying, selling, search, bots, botsearch") reject(player, "Usage: ::ge mode", "Available modes: buying, selling, search, bots, botsearch")
} }
@@ -232,21 +232,64 @@ class MiscCommandSet : CommandSet(Privilege.ADMIN){
/** /**
* List all commands * List all commands
*/ */
define("commands"){player,_ -> define("commands", Privilege.STANDARD, "::commands <lt>page<gt>", "Lists all the commands (you are here.)"){player, args ->
val page = if (args.size > 1) (args[1].toIntOrNull() ?: 1) - 1 else 0
var lineid = 11
var pages = CommandMapping.getPageIndices(player.rights.ordinal)
var end = if (page < (pages.size - 1)) pages[page + 1] else CommandMapping.getCommands().size
player.interfaceManager.close()
if (page < 0) {
reject(player, "Usage: ::commands <lt>page<gt>")
}
for (i in 0..310) { for (i in 0..310) {
player.packetDispatch.sendString("", Components.QUESTJOURNAL_SCROLL_275, i) player.packetDispatch.sendString("", Components.QUESTJOURNAL_SCROLL_275, i)
} }
var lineid = 11
player.packetDispatch.sendString("Commands",Components.QUESTJOURNAL_SCROLL_275,2) player.packetDispatch.sendString(
for(line in CommandMapping.getNames().sorted()) "Commands" + if (pages.size > 1) " (${page + 1}/${pages.size})" else "",
player.packetDispatch.sendString(line,Components.QUESTJOURNAL_SCROLL_275,lineid++) Components.QUESTJOURNAL_SCROLL_275,
2
)
for(i in pages[page] until end) {
var command = CommandMapping.getCommands()[i]
var title = "${command.name}"
var rights = command.privilege.ordinal
var icon = rights - 1
if (rights > player.rights.ordinal) continue
if (rights > 0)
title = "(<img=$icon>) $title"
player.packetDispatch.sendString(title, Components.QUESTJOURNAL_SCROLL_275, lineid++)
if (command.usage.isNotEmpty())
player.packetDispatch.sendString("Usage: ${command.usage}", Components.QUESTJOURNAL_SCROLL_275, lineid++)
if (command.description.isNotEmpty())
player.packetDispatch.sendString(command.description, Components.QUESTJOURNAL_SCROLL_275, lineid++)
player.packetDispatch.sendString("<str>-------------------------------</str>", Components.QUESTJOURNAL_SCROLL_275, lineid++)
if (lineid > 306) {
player.packetDispatch.sendString("To view the next page, use ::commands ${page + 2}", Components.QUESTJOURNAL_SCROLL_275, lineid)
break
}
}
player.interfaceManager.open(Component(Components.QUESTJOURNAL_SCROLL_275)) player.interfaceManager.open(Component(Components.QUESTJOURNAL_SCROLL_275))
} }
/** /**
* Reply to PMs (also enables tab-to-reply) * Reply to PMs (also enables tab-to-reply)
*/ */
define("reply", Privilege.STANDARD){ player, _ -> define("reply", Privilege.STANDARD, "", "Opens a reply prompt to your last DM. Same as pressing tab."){ player, _ ->
if(player.interfaceManager.isOpened){ if(player.interfaceManager.isOpened){
reject(player, "<col=e74c3c>Please finish what you're doing first.") reject(player, "<col=e74c3c>Please finish what you're doing first.")
} }
@@ -266,7 +309,7 @@ class MiscCommandSet : CommandSet(Privilege.ADMIN){
/** /**
* Max account stats * Max account stats
*/ */
define("max"){player,_ -> define("max", Privilege.ADMIN, "", "Gives you all 99s."){player,_ ->
var index = 0 var index = 0
Skills.SKILL_NAME.forEach { Skills.SKILL_NAME.forEach {
player.skills.setStaticLevel(index,99) player.skills.setStaticLevel(index,99)
@@ -276,7 +319,7 @@ class MiscCommandSet : CommandSet(Privilege.ADMIN){
player.skills.updateCombatLevel() player.skills.updateCombatLevel()
} }
define("noobme"){ player,_ -> define("noobme", Privilege.ADMIN, "", "Sets you back to default stats."){ player,_ ->
var index = 0 var index = 0
Skills.SKILL_NAME.forEach { Skills.SKILL_NAME.forEach {
if (index == Skills.HITPOINTS) { if (index == Skills.HITPOINTS) {
@@ -295,7 +338,7 @@ class MiscCommandSet : CommandSet(Privilege.ADMIN){
/** /**
* Set a specific skill to a specific level * Set a specific skill to a specific level
*/ */
define("setlevel"){player,args -> define("setlevel", Privilege.ADMIN, "::setlevel <lt>SKILL NAME<gt> <lt>LEVEL<gt>", "Sets SKILL NAME to LEVEL."){player,args ->
if(args.size < 2) reject(player,"Usage: ::setlevel skillname level") if(args.size < 2) reject(player,"Usage: ::setlevel skillname level")
val skillname = args[1] val skillname = args[1]
val desiredLevel: Int? = args[2].toIntOrNull() val desiredLevel: Int? = args[2].toIntOrNull()
@@ -312,7 +355,7 @@ class MiscCommandSet : CommandSet(Privilege.ADMIN){
player.skills.updateCombatLevel() player.skills.updateCombatLevel()
} }
define("completediaries"){player,_ -> define("completediaries", Privilege.ADMIN, "", "Completes all diaries."){player,_ ->
player.achievementDiaryManager.diarys.forEach { player.achievementDiaryManager.diarys.forEach {
for(level in it.taskCompleted.indices){ for(level in it.taskCompleted.indices){
for(task in it.taskCompleted[level].indices){ for(task in it.taskCompleted[level].indices){
@@ -322,7 +365,7 @@ class MiscCommandSet : CommandSet(Privilege.ADMIN){
} }
} }
define("log"){player,_ -> define("log", Privilege.ADMIN){player,_ ->
var log: ArrayList<String>? = player.getAttribute("loc-log") var log: ArrayList<String>? = player.getAttribute("loc-log")
log = log ?: ArrayList<String>() log = log ?: ArrayList<String>()
val locString = "{${player.location.x},${player.location.y},${player.location.z},1,0}" val locString = "{${player.location.x},${player.location.y},${player.location.z},1,0}"
@@ -350,7 +393,7 @@ class MiscCommandSet : CommandSet(Privilege.ADMIN){
player.setAttribute("loc-log",log) player.setAttribute("loc-log",log)
} }
define("rolltrawlerloot"){player,args -> define("rolltrawlerloot", Privilege.ADMIN, "::rolltrawlerloot <lt>ROLL COUNT<gt>", "Rolls some trawler loot."){player,args ->
val rolls = if(args.size < 2){ val rolls = if(args.size < 2){
100 100
} else { } else {
@@ -359,18 +402,18 @@ class MiscCommandSet : CommandSet(Privilege.ADMIN){
player.bank.add(*TrawlerLoot.getLoot(player.skills.getLevel(Skills.FISHING), rolls, false).toTypedArray()) player.bank.add(*TrawlerLoot.getLoot(player.skills.getLevel(Skills.FISHING), rolls, false).toTypedArray())
} }
define("fillbank"){player,_ -> define("fillbank", Privilege.ADMIN, "", "Right as it says on the tin."){player,_ ->
for(i in 0 until ServerConstants.BANK_SIZE){ for(i in 0 until ServerConstants.BANK_SIZE){
player.bank.add(Item(i)) player.bank.add(Item(i))
} }
} }
define("emptybank"){player,_ -> define("emptybank", Privilege.ADMIN, "", "Right as it says on the tin."){player,_ ->
player.bank.clear() player.bank.clear()
player.bank.update() player.bank.update()
} }
define("setconfig"){player,args -> define("setconfig", Privilege.ADMIN, "", "DEPRECATED: Use setvarp or setvarbit."){player,args ->
if(args.size < 3){ if(args.size < 3){
reject(player,"Syntax: ::setconfig configID value") reject(player,"Syntax: ::setconfig configID value")
} }
@@ -387,7 +430,7 @@ class MiscCommandSet : CommandSet(Privilege.ADMIN){
notify(player, "${VarbitDefinition.forObjectID(SceneryDefinition.forId(objectID).varbitID).configId}") notify(player, "${VarbitDefinition.forObjectID(SceneryDefinition.forId(objectID).varbitID).configId}")
} }
define("define_varbit"){ player, args -> define("define_varbit", Privilege.ADMIN, "::define_varbit <lt>VARBIT ID<gt>", "Prints information about the given varbit."){ player, args ->
if(args.size < 2) { if(args.size < 2) {
reject(player, "Syntax: ::define_varbit varbitId") reject(player, "Syntax: ::define_varbit varbitId")
} }
@@ -466,7 +509,7 @@ class MiscCommandSet : CommandSet(Privilege.ADMIN){
notify(player,"Slayer task tracker is now " + (if(disabled) colorize("%RON") else colorize("%ROFF")) + ".") notify(player,"Slayer task tracker is now " + (if(disabled) colorize("%RON") else colorize("%ROFF")) + ".")
} }
define("setvarbit", Privilege.ADMIN){ define("setvarbit", Privilege.ADMIN, "::setvarbit <lt>VARBIT ID<gt> <lt>VALUE<gt>", ""){
player,args -> player,args ->
if(args.size != 3){ if(args.size != 3){
reject(player,"Usage: ::setvarbit varbit value") reject(player,"Usage: ::setvarbit varbit value")
@@ -481,7 +524,7 @@ class MiscCommandSet : CommandSet(Privilege.ADMIN){
player.varpManager.setVarbit(index!!, value!!) player.varpManager.setVarbit(index!!, value!!)
} }
define("setvarp", Privilege.ADMIN){ define("setvarp", Privilege.ADMIN, "::setvarp <lt>VARP ID<gt> <lt>BIT OFFSET<gt> <lt>VALUE<gt>", "Sets the value starting at the BIT OFFSET of the varp."){
player,args -> player,args ->
if(args.size < 4){ if(args.size < 4){
reject(player,"Usage: ::setvarp index offset value") reject(player,"Usage: ::setvarp index offset value")
@@ -497,7 +540,7 @@ class MiscCommandSet : CommandSet(Privilege.ADMIN){
player.varpManager.get(index!!).setVarbit(offset!!, value!!).send(player) player.varpManager.get(index!!).setVarbit(offset!!, value!!).send(player)
} }
define("setvarc", Privilege.ADMIN) { player, args -> define("setvarc", Privilege.ADMIN, "::setvarc <lt>VARC ID<gt> <lt>VALUE<gt>") { player, args ->
if(args.size < 3){ if(args.size < 3){
reject(player,"Usage: ::setvarc index value") reject(player,"Usage: ::setvarc index value")
} }
@@ -511,7 +554,7 @@ class MiscCommandSet : CommandSet(Privilege.ADMIN){
player.packetDispatch.sendVarcUpdate(index!!, value!!) player.packetDispatch.sendVarcUpdate(index!!, value!!)
} }
define("grow", Privilege.ADMIN){ player, _ -> define("grow", Privilege.ADMIN, "", "Grows all planted crops by 1 stage."){ player, _ ->
val state: FarmingState = player.states.get("farming") as FarmingState? ?: return@define val state: FarmingState = player.states.get("farming") as FarmingState? ?: return@define
for(patch in state.getPatches()){ for(patch in state.getPatches()){
@@ -519,7 +562,7 @@ class MiscCommandSet : CommandSet(Privilege.ADMIN){
} }
} }
define("finishbins", Privilege.ADMIN){ player, _ -> define("finishbins", Privilege.ADMIN, "", "Finishes any in-progress compost bins."){ player, _ ->
val state: FarmingState = player.states.get("farming") as FarmingState? ?: return@define val state: FarmingState = player.states.get("farming") as FarmingState? ?: return@define
for(bin in state.getBins()){ for(bin in state.getBins()){
@@ -541,12 +584,12 @@ class MiscCommandSet : CommandSet(Privilege.ADMIN){
player.details.credits += 100 player.details.credits += 100
} }
define("resetgwdropes", Privilege.STANDARD){ player, _ -> define("resetgwdropes", Privilege.STANDARD, "", "OLD: Was used for fixing broken data."){ player, _ ->
player.varpManager.get(1048).clearBitRange(0,31) player.varpManager.get(1048).clearBitRange(0,31)
player.varpManager.get(1048).send(player) player.varpManager.get(1048).send(player)
} }
define("resetmistag", Privilege.STANDARD){ player, _ -> define("resetmistag", Privilege.STANDARD, "", "OLD: Was used for fixing broken data."){ player, _ ->
player.removeAttribute("mistag-greeted") player.removeAttribute("mistag-greeted")
} }
@@ -41,7 +41,7 @@ class ModerationCommandSet : CommandSet(Privilege.MODERATOR){
* Ban a player * Ban a player
* ============================================================================================================= * =============================================================================================================
*/ */
define("ban", Privilege.ADMIN){ player, args -> define("ban", Privilege.ADMIN, "::ban <lt>USERNAME<gt> <lt>TIME<gt>", "Bans the user. Time format: <lt>INT<gt>d/s/m/h ex: 30d for 30 days."){ player, args ->
val name = args[1] val name = args[1]
if(!GameWorld.accountStorage.checkUsernameTaken(name)) { if(!GameWorld.accountStorage.checkUsernameTaken(name)) {
reject(player, "Invalid username: $name") reject(player, "Invalid username: $name")
@@ -88,7 +88,7 @@ class ModerationCommandSet : CommandSet(Privilege.MODERATOR){
* Mute a player * Mute a player
* ============================================================================================================= * =============================================================================================================
*/ */
define("mute", Privilege.MODERATOR){ player, args -> define("mute", Privilege.MODERATOR, "::mute <lt>USERNAME<gt> <lt>TIME<gt>", "Mutes the user. Time format: <lt>INT<gt>d/s/m/h ex: 30d for 30 days."){ player, args ->
val name = args[1] val name = args[1]
if(!GameWorld.accountStorage.checkUsernameTaken(name)) { if(!GameWorld.accountStorage.checkUsernameTaken(name)) {
reject(player, "Invalid username: $name") reject(player, "Invalid username: $name")
@@ -136,7 +136,7 @@ class ModerationCommandSet : CommandSet(Privilege.MODERATOR){
* Jail a player * Jail a player
* ============================================================================================================= * =============================================================================================================
*/ */
define("jail"){player,args -> define("jail", Privilege.MODERATOR, "::jail <lt>SECONDS<gt> <lt>USERNAME<gt>", "Sends the player to the jail cells in Varrock."){player,args ->
if(args.size < 3) { if(args.size < 3) {
reject(player,"Usage: ::jail <seconds> <player>") reject(player,"Usage: ::jail <seconds> <player>")
} }
@@ -179,4 +179,4 @@ class ModerationCommandSet : CommandSet(Privilege.MODERATOR){
* ============================================================================================================= * =============================================================================================================
*/ */
} }
} }
@@ -40,7 +40,7 @@ class SystemCommandSet : CommandSet(Privilege.ADMIN) {
/** /**
* Allows a player to reset their password * Allows a player to reset their password
*/ */
define("resetpassword", Privilege.STANDARD) { player, args -> define("resetpassword", Privilege.STANDARD, "", "WARNING: Case insensitive due to dialogue limitations.") { player, args ->
sendInputDialogue(player, InputType.STRING_SHORT, "Enter Current Password:"){value -> sendInputDialogue(player, InputType.STRING_SHORT, "Enter Current Password:"){value ->
val pass = value.toString() val pass = value.toString()
SystemLogger.logInfo(pass) SystemLogger.logInfo(pass)
@@ -69,7 +69,7 @@ class SystemCommandSet : CommandSet(Privilege.ADMIN) {
/** /**
* Allows an Administrator to reset a password * Allows an Administrator to reset a password
*/ */
define("setpasswordother", Privilege.ADMIN) { player, args -> define("setpasswordother", Privilege.ADMIN, "::resetpasswordother <lt>USERNAME<gt> <lt>NEW<gt>", "Gives the username password NEW.") { player, args ->
if (args.size != 3) { if (args.size != 3) {
reject(player, "Usage: ::resetpasswordother user new", "WARNING: THIS IS PERMANENT.", "WARNING: PASSWORD CAN NOT CONTAIN SPACES.") reject(player, "Usage: ::resetpasswordother user new", "WARNING: THIS IS PERMANENT.", "WARNING: PASSWORD CAN NOT CONTAIN SPACES.")
} }
@@ -94,7 +94,7 @@ class SystemCommandSet : CommandSet(Privilege.ADMIN) {
} }
} }
define("giveitem", Privilege.ADMIN) { player, args -> define("giveitem", Privilege.ADMIN, "::giveitem <lt>USERNAME<gt> <lt>ITEM ID<gt> <lt>AMOUNT<gt>", "Gives the user the amount of the given item.") { player, args ->
if (args.size == 3 || args.size == 4) { if (args.size == 3 || args.size == 4) {
val victim = Repository.getPlayerByName(args[1]) val victim = Repository.getPlayerByName(args[1])
val itemID = args[2].toIntOrNull() val itemID = args[2].toIntOrNull()
@@ -130,7 +130,7 @@ class SystemCommandSet : CommandSet(Privilege.ADMIN) {
} }
} }
define("removeitem", Privilege.ADMIN) { player, args -> define("removeitem", Privilege.ADMIN, "::removeitem <lt>LOC<gt> <lt>USERNAME<gt> <lt>ITEM ID<gt> <lt>AMOUNT<gt>", "LOC = bank,inventory,equipment") { player, args ->
if (args.size == 4 || args.size == 5) { if (args.size == 4 || args.size == 5) {
val itemLoc = args[1].toLowerCase() val itemLoc = args[1].toLowerCase()
val victim = Repository.getPlayerByName(args[2]) val victim = Repository.getPlayerByName(args[2])
@@ -181,7 +181,7 @@ class SystemCommandSet : CommandSet(Privilege.ADMIN) {
} }
} }
define("removeitemall", Privilege.ADMIN) { player, args -> define("removeitemall", Privilege.ADMIN, "::removeitemall <lt>USERNAME<gt> <lt>ITEM ID<gt>", "Removes ALL of a given item from the player.") { player, args ->
if (args.size == 3) { if (args.size == 3) {
val victim = Repository.getPlayerByName(args[1]) val victim = Repository.getPlayerByName(args[1])
val itemID = args[2].toIntOrNull() val itemID = args[2].toIntOrNull()
@@ -229,7 +229,7 @@ class SystemCommandSet : CommandSet(Privilege.ADMIN) {
} }
} }
define("potato") { player, _ -> define("potato", Privilege.ADMIN, "", "Gives you a rotten potato.") { player, _ ->
player.inventory.add(Item(Items.ROTTEN_POTATO_5733)) player.inventory.add(Item(Items.ROTTEN_POTATO_5733))
} }
@@ -238,4 +238,4 @@ class SystemCommandSet : CommandSet(Privilege.ADMIN) {
} }
} }
} }
@@ -17,7 +17,7 @@ class TeleportCommandSet : CommandSet(Privilege.ADMIN){
/** /**
* Allows teleporting by location name * Allows teleporting by location name
*/ */
define("to"){player,args -> define("to", Privilege.ADMIN, "::to <lt>String<gt>", "See ServerConstants.TELEPORT_DESTINATIONS"){player,args ->
var destination: Location? = null var destination: Location? = null
val place = args.slice(1 until args.size).joinToString(" ") val place = args.slice(1 until args.size).joinToString(" ")
for (destinations in ServerConstants.TELEPORT_DESTINATIONS) { for (destinations in ServerConstants.TELEPORT_DESTINATIONS) {
@@ -40,7 +40,7 @@ class TeleportCommandSet : CommandSet(Privilege.ADMIN){
/** /**
* Teleport to location using coordinates * Teleport to location using coordinates
*/ */
define("tele"){player,args -> define("tele", Privilege.ADMIN, "::tele <lt>X<gt> <lt>Y<gt> <lt>Z<gt> OR <lt>JAGCOORD<gt>", "JAGCOORD is Z_REGIONX_REGIONY_LOCALX_LOCALY"){player,args ->
if (args.size == 2 && args[1].contains(",")) { if (args.size == 2 && args[1].contains(",")) {
val args2 = args[1].split(",".toRegex()).toTypedArray() val args2 = args[1].split(",".toRegex()).toTypedArray()
val x = args2[1].toInt() shl 6 or args2[3].toInt() val x = args2[1].toInt() shl 6 or args2[3].toInt()
@@ -102,7 +102,7 @@ class TeleportCommandSet : CommandSet(Privilege.ADMIN){
/** /**
* Teleport to the first object with the given name in the given regionX regionY * Teleport to the first object with the given name in the given regionX regionY
*/ */
define("teleobj"){player, args -> define("teleobj", Privilege.ADMIN, "::teleobj <lt>RX_RY<gt> <lt>OBJ NAME<gt>", "Teleports to the first object with the given name."){player, args ->
if(args.size < 3) reject(player, "Usage: regionX_regionY Object Name") if(args.size < 3) reject(player, "Usage: regionX_regionY Object Name")
var objName = "" var objName = ""
for(i in 2 until args.size) objName += (args[i] + if(i + 1 == args.size) "" else " ") for(i in 2 until args.size) objName += (args[i] + if(i + 1 == args.size) "" else " ")
@@ -141,7 +141,7 @@ class TeleportCommandSet : CommandSet(Privilege.ADMIN){
/** /**
* Teleport to a specific player * Teleport to a specific player
*/ */
define("teleto"){player,args -> define("teleto", Privilege.ADMIN, "::teleto <lt>USERNAME<gt>", "Teleports to the named player."){player,args ->
if (args.size < 1) { if (args.size < 1) {
reject(player,"syntax error: name") reject(player,"syntax error: name")
} }
@@ -160,7 +160,7 @@ class TeleportCommandSet : CommandSet(Privilege.ADMIN){
/** /**
* Teleport a specific player to you * Teleport a specific player to you
*/ */
define("teletome"){player,args -> define("teletome", Privilege.ADMIN, "::teletome <lt>USERNAME<gt>", "Teleports the given user to you."){player,args ->
if (args.size < 1) { if (args.size < 1) {
reject(player,"syntax error: name") reject(player,"syntax error: name")
} }
@@ -179,8 +179,8 @@ class TeleportCommandSet : CommandSet(Privilege.ADMIN){
/** /**
* Teleports to the server's home location * Teleports to the server's home location
*/ */
define("home"){player,_ -> define("home", Privilege.ADMIN, "", "Teleports to ServerConstants.HOME_LOCATION"){player,_ ->
player.properties.teleportLocation = ServerConstants.HOME_LOCATION player.properties.teleportLocation = ServerConstants.HOME_LOCATION
} }
} }
} }
@@ -1,9 +1,16 @@
package rs09.game.system.config package rs09.game.system.config
import api.*
import rs09.game.world.repository.Repository
import rs09.game.system.command.Privilege
import core.game.world.map.RegionManager
import core.game.node.item.GroundItemManager
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
class ConfigParser { class ConfigParser : Commands {
fun prePlugin() { fun prePlugin() {
NPCConfigParser().load() NPCConfigParser().load()
ItemConfigParser().load() ItemConfigParser().load()
@@ -20,4 +27,32 @@ class ConfigParser {
MusicConfigLoader().load() MusicConfigLoader().load()
RangedConfigLoader().load() RangedConfigLoader().load()
} }
}
fun reloadConfigs(callback: () -> Unit) {
GlobalScope.launch {
Repository.npcs.toTypedArray().forEach { npc ->
npc.isRespawn = false
npc.clear()
Repository.npcs.remove(npc)
Repository.removeRenderableNPC(npc)
}
GroundItemManager.getItems().toTypedArray().forEach {gi ->
GroundItemManager.getItems().remove(gi)
RegionManager.getRegionPlane(gi.location).remove(gi)
}
prePlugin()
postPlugin()
callback.invoke()
}
}
override fun defineCommands() {
define("reloadjson", Privilege.ADMIN, "", "Reloads all the JSON configs.") { player, _ ->
notify(player, "Reloading JSON...")
reloadConfigs() { notify(player, "JSON reloaded.") }
}
}
}