package jesse.keeblarcraft.Commands; import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.context.CommandContext; import java.util.List; import java.util.ArrayList; import java.util.Map; import java.util.Map.Entry; import static java.util.Map.entry; import jesse.keeblarcraft.BankMgr.BankManager; import jesse.keeblarcraft.BankMgr.IndividualAccount; import jesse.keeblarcraft.BankMgr.IndividualBank; import jesse.keeblarcraft.ChatStuff.ChatFormatting.COLOR_CODE; import jesse.keeblarcraft.ChatStuff.ChatMsg; import jesse.keeblarcraft.ConfigMgr.ConfigManager; import net.minecraft.server.command.CommandManager; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.text.Text; import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; public class BankCommands { private static List FILLER_WORDS = new ArrayList(List.of("of", "from", "as", "with", "name", "dubbed", "coined", "note")); private static String HELPCMD_HELP = "help"; private static String HELPCMD_CREATE = "create"; private static String HELPCMD_SELECT = "select"; private static String HELPCMD_CLOSE = "close"; private static String HELPCMD_REPORT = "report"; private static String HELPCMD_BALANCE = "balance"; private static String HELPCMD_EXAMPLES = "examples"; private static String HELPCMD_MOVE = "move"; private static String HELPCMD_SYNTAX = "syntax"; private static String HELPCMD_ALIAS = "alias"; private static String HELPCMD_WIRE = "wire"; private static String HELPCMD_ACCOUNTS = "accounts"; private static String HELPCMD_ADMIN_BALANCE_CHANGE = "admin-set-balance"; private static String HELPCMD_ADMIN_BALANCE_GET = "admin-get-balance"; private static String HELPCMD_ADMIN_CREATE_BANK = "admin-create-bank"; private static String HELPCMD_ADMIN_CLOSE_BANK = "admin-close-bank"; private static String HELPCMD_ADMIN_FORCE_WIRE = "admin-force-wire"; private static String HELPCMD_ADMIN_LOCK_BANK = "admin-lock-bank"; private static String HELPCMD_SET_SERVER_ALLOWANCE = "admin-set-server-allowance"; private static String HELPCMD_GET_SERVER_ALLOWANCE = "admin-get-server-allowance"; private static String HELPCMD_ADMIN_COMMANDS_LIST = "admin-commands-list"; private static String HELPCMD_ADMIN_ACCOUNTS = "admin-accounts"; private static String HELPCMD_ADMIN_ACCOUNTS_LIST = "admin-accounts-list"; private static String HELPCMD_ADMIN_ACCOUNTS_MOVE = "admin-accounts-move"; private static String HELPCMD_ADMIN_ACCOUNTS_FORCE_CLOSE = "admin-accounts-force-close"; private static String HELPCMD_ADMIN_ACCOUNTS_ADD = "admin-accounts-add"; private static String HELPCMD_ADMIN_ACCOUNTS_TRANSACTIONS = "admin-accounts-transactions"; private static String HELPCMD_ADMIN_ACCOUNTS_LOCK = "admin-accounts-lock"; ChatMsg msgFormatter = new ChatMsg(); private static Map HELP_COMMANDS = Map.ofEntries( entry ( HELPCMD_HELP, "Usage: /bank help. This is the general help message for the bank system. For detailed help messages, please run /bank help . List of possible " + "commands are: CREATE, SELECT, CLOSE, REPORT, BALANCE, EXAMPLES, WIRE, MOVE, SYNTAX, ALIAS" ), entry ( HELPCMD_CREATE, "Usage: /bank create {checking|savings}. This will create a bank account with the default selected bank (/bank select {BANK_ID} to choose other)." ), entry ( HELPCMD_SELECT, "Usage: /bank select {BANK_ID}. Do `/bank list` for a list of banks on the server." ), entry ( HELPCMD_CLOSE, "Usage: /bank close {ACCOUNT_ID}. Do `/bank accounts list` to see all the accounts you have! Note: CANNOT close accounts that aren't 0 balance." ), entry ( HELPCMD_REPORT, "Usage: /bank report [ACCOUNT_ID|none]. Optional args mean you can get a specific report list for one account; but if none specified we default to all accounts." ), entry ( HELPCMD_BALANCE, "Usage: /bank balance [ACCOUNT_ID]. Optional args get balances for other accounts that aren't the default selected account. You may run `/bank accounts list` to " + "see all possible options to get a balance for." ), entry ( HELPCMD_EXAMPLES, "Usage: /bank examples. This will print a much larger command with more thorough examples (and even shortcuts!) of all the commands from the bank system." ), entry ( HELPCMD_MOVE, "Usage: /bank move {ACCOUNT_ID} to {BANK_ID}. The intended use of this command is to move accounts across banks, but you could also plug in another ACCOUNT_ID in " + " the `BANK_ID` part to perform an internal wire instead. NOTE: Moving might not succeed based on bank rules!" ), entry ( HELPCMD_SYNTAX, "Usage: /bank syntax. This banking system was written to be human readable in command-form and often operates like a database. You can put certain filler-words inside your commands that are " + "parsed out at runtime if it helps with reading. Example command: \"/bank select 942-3449-42\" will work just fine to select a bank account as a primary account. HOWEVER, you can also " + "type \"/bank select for-bills as default\" so long as you aliased the account identifier as 'for-bills'. Much nicer to read and work with. [Related: /bank help aliases]" ), entry ( HELPCMD_ALIAS, "Usage: /bank alias {ACCOUNT_ID} {UNIQUE_NAME}. Alias provides a handy way to refer to bank accounts by their unique names instead of long-form account ids. NOTE: Aliases " + "are ONLY unique within the context of an individual bank and not across all banks, but generally you can replace `ACCOUNT_ID` as seen in other commands with the alias if it exists." ), entry ( HELPCMD_WIRE, "Usage: /bank wire {AMOUNT} to {ACCOUNT_ID|NAME}. It is recommended to wire a specific account ID over a name since it works if the other player is offline. If name is specified, " + " the wire will go through to that players default account. Use with caution!" ), entry ( HELPCMD_ACCOUNTS, "Usage: /bank accounts {BANK_ID}. Prints out all of your banking information at a bank assuming you have any." ), entry ( HELPCMD_ADMIN_BALANCE_CHANGE, "Usage: /bank admin {set-bal|add-money|subtract-money} {ACCOUNT_ID|BANK_ID} {AMOUNT}. This command covers set/add/subtract money. Usage varies on context, but general help command is going to be " + "/bank admin {set-bal|add-money|sub-money} {USER_ACCOUNT_ID|BANK_ROUTING_NUM} {amount}. Please note that the \"|\" in this context means OR - you do not put both! " + "So you can set a banks balance or accounts balance with this command." ), entry ( HELPCMD_ADMIN_BALANCE_GET, "Usage: /bank admin get {USER_ACCOUNT_ID|BANK_ID}. Please note that the \"|\" in this means OR. Do NOT put both!" ), entry ( HELPCMD_ADMIN_CREATE_BANK, "Usage: /bank admin create {new bank name}. Bank name must be longer than 4 letters!" ), entry ( HELPCMD_ADMIN_CLOSE_BANK, "Usage: /bank admin close {BANK_ID}. Please be aware if the bank has an active balance or user accounts you will be asked to " + "confirm if this is really what you want to do. Money is not magic, so if you specify to close the bank the bank balance is transferred back " + "to the servers primary bank account & all user accounts money are transferred to the server bank. Accounts will automatically be opened to preserve " + "the money for users to claim because banks are not ordinarily supposed to just close. Only run this command if you absolutely have to!" ), entry ( HELPCMD_ADMIN_FORCE_WIRE, "Usage: /bank admin wire {AMOUNT} from {ACCOUNT_ID} to {ACCOUNT_ID}. Please be aware this is a heavy handed command and may " + "unintentionally override a bank accounts default setting. A bank account with a rule that can't go negative WILL go negative if this command is " + "run because it's an administrative command! Use with caution" ), entry ( HELPCMD_ADMIN_LOCK_BANK, "Usage: /bank admin lock-bank {BANK_ID}. Completely freezes all activity in and out of a bank." ), entry ( HELPCMD_SET_SERVER_ALLOWANCE, "Usage: /bank admin set-server-allowance {amount} {interval}. Example usage: /bank admin set-server-allowance 1,000,000 " + "30d. Supported interval characters: d/m/y (day/month/year). These times are in MINECRAFT in-game time, not real life time! Months are assumed to be equally " + "30 days and years are 365 days. If you need precision, just specify your amount in days!" ), entry ( HELPCMD_GET_SERVER_ALLOWANCE, "Usage: /bank admin get-server-allowance. Returns the amount of money in the allowance for server and the interval it is in. " ), entry ( HELPCMD_ADMIN_COMMANDS_LIST, "Usage: /bank admin {sub-command} [optionals]. POSSIBLE ADMIN COMMANDS LIST: [set-bal, add-money, get-bal, sub-money, accounts, create-bank, close-bank, lock-bank, unlock, " + "force-wire, get-server-allowance, set-server-allowance]. Commands FROM [accounts] cmd => [list, move, force-close, add, transactions, lock]" ), entry ( HELPCMD_ADMIN_ACCOUNTS, "Usage: /bank admin accounts {sub-command} [optionals]. This command has sub-commands that are expected. Possible => [list, move, force-close, add, transactions, lock]. General syntax is " + "/bank admin accounts [sub-command]" ), entry ( HELPCMD_ADMIN_ACCOUNTS_ADD, "Usage: /bank admin accounts add {ONLINE_PLAYER} [BANK_ID]. Adds a regular checking account to a bank for a player who is online. " + "If BANK_ID not specified; defaults to the servers default bank" ), entry ( HELPCMD_ADMIN_ACCOUNTS_FORCE_CLOSE, "Usage: /bank admin accounts force-close {ACCOUNT_ID}. Command not supported in this version." ), entry ( HELPCMD_ADMIN_ACCOUNTS_LIST, "Usage: /bank admin accounts list {USERNAME}. Command not supported in this version." ), entry ( HELPCMD_ADMIN_ACCOUNTS_LOCK, "Usage: /bank admin accounts lock {ACCOUNT_ID}. Command not supported in this version." ), entry ( HELPCMD_ADMIN_ACCOUNTS_MOVE, "Usage: /bank admin accounts move {ACCOUNT_ID} to {BANK_ID}. Command not supported in this version." ), entry ( HELPCMD_ADMIN_ACCOUNTS_TRANSACTIONS, "Usage: /bank admin accounts transactions {ACCOUNT_ID}. Command not supported in this version." ) ); ConfigManager config = new ConfigManager(); ///////////////////////////////////////////////////////////////////////////// /// @fn RegisterCommands /// /// @brief Registers all bank commands on the server ///////////////////////////////////////////////////////////////////////////// public void RegisterCommands() { CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> { // This is basically a small re-created SQL language but for bank commands. I recommend asking me for the drawn // image to better understand what this is accomplishing if it is confusing. Essentially it is easy though, as it // is just /bank ACTION-WORD [arguments...] [optionals] var bankRoot = CommandManager.literal("bank").build(); // Removing "argList" and just running the entire list as an argList from actionWord makes `/bank help` possible var argList = CommandManager.argument("ARG_LIST", StringArgumentType.greedyString()) .executes(context -> ParseBankCommand ( context, StringArgumentType.getString(context, "ARG_LIST")) ) .build(); // Building the argument tree here dispatcher.getRoot().addChild(bankRoot); bankRoot.addChild(argList); }); } ///////////////////////////////////////////////////////////////////////////// /// @fn RemoveFillerWords /// /// @brief Takes in a list of arguments with the intention to remove /// all words found in the filler list. This helps with dynamic /// typing /// /// @return List of arguments without filler words ///////////////////////////////////////////////////////////////////////////// public List RemoveFillerWords(List argList) { int index = 0; for (String str : argList) { if (FILLER_WORDS.contains(str)) { argList.remove(index); } // Also make every word lower case str = str.toLowerCase(); index++; } return argList; } ///////////////////////////////////////////////////////////////////////////// /// @fn ParseBankCommand /// /// @brief Parses the global bank command ///////////////////////////////////////////////////////////////////////////// public int ParseBankCommand(CommandContext context, String unformattedArgList) { List formattedArgList = List.of(unformattedArgList.split("\\s+")); // REGEX is matching 1+ whitespace characters System.out.println("After formatting the arg list, the size of arg list is size { " + formattedArgList.size() + " }"); formattedArgList = RemoveFillerWords(formattedArgList); String actionWord = formattedArgList.get(0); System.out.println("The action word for this operation is " + actionWord.toUpperCase()); System.out.println("Parsing bank command on action word { " + actionWord + " } with arg list { " + formattedArgList + " }"); switch(actionWord) { case "create": System.out.println("Calling create command..."); CreateCommand(context.getSource().getPlayer(), formattedArgList.subList(1, formattedArgList.size())); break; case "close": CloseCommand(context.getSource().getPlayer(), formattedArgList); break; case "select": SelectCommand(context.getSource().getPlayer(), formattedArgList.subList(1, formattedArgList.size())); break; case "wire": WireCommand(context.getSource().getPlayer(), formattedArgList.subList(1, formattedArgList.size())); break; case "balance": BalanceCommand(context.getSource().getPlayer(), formattedArgList); break; case "help": HelpCommand(context.getSource().getPlayer(), formattedArgList); break; case "move": MoveCommand(context.getSource().getPlayer(), formattedArgList); break; case "alias": AliasCommand(context.getSource().getPlayer(), formattedArgList); break; case "report": ReportCommand(context.getSource().getPlayer(), formattedArgList); break; case "examples": HelpCommand(context.getSource().getPlayer(), List.of(HELPCMD_EXAMPLES)); break; case "syntax": HelpCommand(context.getSource().getPlayer(), List.of(HELPCMD_SYNTAX)); break; case "list": ListAllBanks(context.getSource().getPlayer(), formattedArgList); break; case "account": case "accounts": ManageAccounts(context.getSource().getPlayer(), formattedArgList.subList(1, formattedArgList.size())); break; case "admin": AdminCommand(context.getSource().getPlayer(), formattedArgList.subList(1, formattedArgList.size())); break; default: if (context.getSource().isExecutedByPlayer()) { context.getSource().getPlayer().sendMessage(Text.of("You have entered an improperly formatted message. Please reference the bank manual if you are confused how to form a command!")); } break; } return 0; } ///////////////////////////////////////////////////////////////////////////// /// @fn ParseToInteger /// /// @param[in] player is the player to send message to on failure /// /// @param[in] possibleInt is string to be parsed /// /// @param[in] helpCmd is help command to send player on failure to parse /// /// @brief Helper is designed to parse a string to a number (helpful in /// banking) and upon a failure of parse send a designated help /// message for that command (this system is non-trivial to use) /// /// @return The parsed integer if successful parse. If false, the server /// should catch and a help command is sent ///////////////////////////////////////////////////////////////////////////// public Integer ParseToInteger(ServerPlayerEntity player, String possibleInt, String helpCmd) { Integer amount = 0; try { amount = Integer.parseInt(possibleInt); } catch (NumberFormatException exception) { HelpCommand(player, List.of(helpCmd)); } System.out.println("ParseToInteger was called. The input was " + possibleInt + " and the parsed int is " + amount); return amount; } ///////////////////////////////////////////////////////////////////////////// /// @fn IsOperator /// /// @param[in] player is the player to be tested /// /// @brief Check to see if player is operator (move to util in future) /// /// @return True if player is operator, false if not ///////////////////////////////////////////////////////////////////////////// public Boolean IsOperator(ServerPlayerEntity player) { if (player.hasPermissionLevel(4)) { return true; } else { return false; } } // Possible code paths ({}=required, []=optionals, ()=explanation): // REQUIRED (path) = {SetBal|AddMoney|SubMoney} {LONG_ID|BANK_ID} {amount} (Depending on context, changes balance somehow from an account ID or bank) // REQUIRED (path) = {GetBal} {LONG_ID:BANK_ID} (Gets the balance of a bank account or bank) // REQUIRED (path) = {accounts} {list} {PLAYER_NAME} (Returns summarized account information on a player) // REQUIRED (path) = {accounts} {move} {LONG_ID} to {BANK_ID} (Will move account to diff bank. May generate new account ID) // REQUIRED (path) = {accounts} {force-close} {LOND_ID} (Forces an account to be closed. Money is returned to server bank account) // REQUIRED (path) = {accounts} {add} to {PLAYER_NAME} [BANK_ID] (Adds an account to a player to server by default. Specify other for other) // REQUIRED (path) = {accounts} {transactions} from {LONG_ID} (Gets transaction report from an account by ID) // REQUIRED (path) = {accounts} {lock} {LONG_ID:USER} (Locks a specific bank account OR all bank accounts owned by $USER) // REQUIRED (path) = {create-bank} {BANK_ID} (Create a new bank. Default is owned by server) // REQUIRED (path) = {close-bank} {BANK_ID} (Closing a bank forces a close on all accounts. Banks money is returned to server bank) // REQUIRED (path) = {lock-bank} {BANK_ID} (Freezes all activities through a bank) // REQUIRED (path) = {unlock} {BANK_ID:ACCOUNT_ID:USER} (will unlock a bank, account, or all of a users accounts) // REQUIRED (path) = {wire} {amount} from {ACCOUNT_ID} to {ACCOUNT_ID} (Forces a wire from one account to another. Overrides overdraft setting since it's administrative) // REQUIRED (path) = {get-server-allowance} (Returns the rate of which the server adds money to itself magically & how much) // REQUIRED (path) = {set-server-allowance} {amount} {interval} (Sets the magic allowance rate of server & period in which it does it to add money magically to server bank) ///////////////////////////////////////////////////////////////////////////// /// @fn AdminCommand /// /// @param[in] sourcePlayer is player running command /// /// @param[in] argList is the argument list to be parsed /// /// @brief Code paths should be read in above comment. Primary admin list /// of commands that are possible to run ///////////////////////////////////////////////////////////////////////////// public void AdminCommand(ServerPlayerEntity sourcePlayer, List argList) { // The player must be opped & the size must be at LEAST 2 (1 keyword + extra for sublist) String pName = sourcePlayer.getEntityName(); System.out.println("Is player admin? " + (IsOperator(sourcePlayer) ? "YES" : "NO")); if (IsOperator(sourcePlayer) && argList.size() >= 1) { String arg = argList.get(0); List remainingArgs = argList.subList(1, argList.size()); switch (arg) { case "account": case "accounts": break; case "submoney": case "subtract-money": case "subtractmoney": case "sub-money": // Require account identifier + balance if (remainingArgs.size() >= 2) { String accountId = remainingArgs.get(0); Integer amount = ParseToInteger(sourcePlayer, remainingArgs.get(1), HELPCMD_ADMIN_BALANCE_CHANGE); String optionalReason = ""; if (remainingArgs.size() >= 3) { optionalReason = remainingArgs.get(2); } AdminBalanceChange(sourcePlayer, accountId, amount, "subtract", optionalReason); } else { HelpCommand(sourcePlayer, List.of(HELPCMD_ADMIN_BALANCE_CHANGE)); } break; case "addmoney": case "add-money": // Require account identifier + balance if (remainingArgs.size() >= 2) { String accountId = remainingArgs.get(0); Integer amount = ParseToInteger(sourcePlayer, remainingArgs.get(1), HELPCMD_ADMIN_BALANCE_CHANGE); String optionalReason = ""; if (remainingArgs.size() >= 3) { optionalReason = remainingArgs.get(2); } AdminBalanceChange(sourcePlayer, accountId, amount, "add", optionalReason); } else { HelpCommand(sourcePlayer, List.of(HELPCMD_ADMIN_BALANCE_CHANGE)); } break; case "setbal": case "set-bal": case "setbalance": case "set-balance": // Require account identifier + balance if (remainingArgs.size() >= 2) { String accountId = remainingArgs.get(0); Integer amount = ParseToInteger(sourcePlayer, remainingArgs.get(1), HELPCMD_ADMIN_BALANCE_CHANGE); String optionalReason = ""; if (remainingArgs.size() >= 3) { optionalReason = remainingArgs.get(2); } System.out.println("Running set-balance with amount " + amount); if (amount != 0) { AdminBalanceChange(sourcePlayer, accountId, amount, "set", optionalReason); } else { HelpCommand(sourcePlayer, List.of(HELPCMD_ADMIN_BALANCE_CHANGE)); } } else { HelpCommand(sourcePlayer, List.of(HELPCMD_ADMIN_BALANCE_CHANGE)); } break; case "getbal": case "get-bal": case "getbalance": case "get-balance": // Require account identifier if (remainingArgs.size() >= 1) { } else { HelpCommand(sourcePlayer, List.of(HELPCMD_ADMIN_BALANCE_GET)); } break; case "createbank": case "create-bank": if (remainingArgs.size() >= 1) { } else { HelpCommand(sourcePlayer, List.of(HELPCMD_ADMIN_CREATE_BANK)); } break; case "closebank": case "close-bank": if (remainingArgs.size() >= 1) { } else { HelpCommand(sourcePlayer, List.of(HELPCMD_ADMIN_CLOSE_BANK)); } break; case "forcewire": case "force-wire": case "wiremoney": case "wire-money": case "wire": if (remainingArgs.size() >= 3) { } else { HelpCommand(sourcePlayer, List.of(HELPCMD_ADMIN_FORCE_WIRE)); } break; case "lock-bank": case "lockbank": if (remainingArgs.size() >= 1) { } else { HelpCommand(sourcePlayer, List.of(HELPCMD_ADMIN_LOCK_BANK)); } break; case "get-server-allowance": case "getserverallowance": sourcePlayer.sendMessage(Text.of(GetServerAllowance())); break; case "setserverallowance": case "set-server-allowance": if (remainingArgs.size() >= 1) { } else { HelpCommand(sourcePlayer, List.of(HELPCMD_SET_SERVER_ALLOWANCE)); } break; default: HelpCommand(sourcePlayer, List.of(HELPCMD_ADMIN_COMMANDS_LIST)); break; } } else { sourcePlayer.sendMessage(Text.of("Only admins can use this command!")); } } public String GetServerAllowance() { return ""; } ///////////////////////////////////////////////////////////////////////////// /// @fn AdminBalanceChange /// /// @param[in] player is player who ran command /// /// @param[in] accountId is account id to change balance of /// /// @param[in] amount is amount to change account balance /// /// @param[in] type is type of fund change (parsed on @ref BankManager.java) /// /// @param[in] optionalReason is the optional reason of balance change /// /// @brief Admin command to change the balance of an account by some /// amount ///////////////////////////////////////////////////////////////////////////// public void AdminBalanceChange(ServerPlayerEntity player, String accountId, Integer amount, String type, String optionalReason) { System.out.println("AdminChangeFunds on account " + accountId); BankManager.GetInstance().AdminChangeFunds(player, accountId, amount, type, optionalReason); } public void AdminGetBalance(String accountId) { } public void AdminWireMoney(String fromAccount, String toAccount, Integer amount, String optionalReason) { } public void AdminCreateBank(String bankName, Integer initialBankBalance, Integer kbicInsuredAmount) { } public void AdminCloseBank(String bankIdentifier, String optionalReason, Boolean forceClosure) { } public void AdminAccounts() { } public void LockBank(String bankIdentifier, String optionalReason) { } public void LockPlayer(String playerName, String optionalReason) { } public void LockBankAccount(String accountId, String optionalReason) { } // Possible code paths: // REQUIRED = {Routing # or Bank name} // OPTIONAL = [] ///////////////////////////////////////////////////////////////////////////// /// @fn ManageAccounts /// /// @brief Change the balance of a designated account ///////////////////////////////////////////////////////////////////////////// public void ManageAccounts(ServerPlayerEntity sourcePlayer, List argList) { System.out.println("Manage accounts arg list is { " + argList + " }"); if (argList.size() > 0) { // TODO: For now we assume they reference the bank name and not routing # String bankName = argList.get(0).toUpperCase(); IndividualBank bank = BankManager.GetInstance().GetBankByName(bankName); System.out.println("Test print on memory"); Boolean isNull = bank == null; System.out.println("isNull: " + isNull); if (bank != null) { System.out.println("Grabbing user account information"); List userAccounts = bank.GetAccountsOfUser(sourcePlayer.getUuidAsString()); sourcePlayer.sendMessage(Text.of("[BANK INFO FOR " + bankName.toUpperCase() + "]")); System.out.println("userAccounts size: " + userAccounts.size()); for (int i = 0; i < userAccounts.size(); i++) { String accountNumber = userAccounts.get(i).GetAccountNumber(); String globalAccountNumber = userAccounts.get(i).GetGlobalAccountNumber(); List accountHolders = userAccounts.get(i).GetAccountHolders(); Integer accountBalance = userAccounts.get(i).GetAccountBalance(); String l1 = "ACCOUNT NUMBER: " + msgFormatter.ColorMsg(accountNumber, COLOR_CODE.BLUE); String l2 = "GLOBAL ACCOUNT NUMBER: " + msgFormatter.ColorMsg(globalAccountNumber, COLOR_CODE.BLUE); String l3 = "HOLDERS: " + msgFormatter.ColorMsg(accountHolders, COLOR_CODE.GRAY); String l4 = "BALANCE: " + msgFormatter.ColorMsg(accountBalance, COLOR_CODE.GREEN); sourcePlayer.sendMessage((Text) msgFormatter.MakeCopyableTxt(l1, "Click to copy", accountNumber)); sourcePlayer.sendMessage((Text) msgFormatter.MakeCopyableTxt(l2, "Click to copy", globalAccountNumber)); sourcePlayer.sendMessage((Text) msgFormatter.MakeCopyableTxt(l3, "Click to copy", accountHolders)); sourcePlayer.sendMessage((Text) msgFormatter.MakeCopyableTxt(l4, "Click to copy", accountBalance)); sourcePlayer.sendMessage(Text.of("\n")); } } else { sourcePlayer.sendMessage(Text.of(msgFormatter.ColorMsg("That bank does not exist", COLOR_CODE.RED))); } } else { sourcePlayer.sendMessage(Text.of("Unrecognized move command. Please use \"/bank help ACCOUNTS\" for more information.")); } } public void ListAllBanks(ServerPlayerEntity sourcePlayer, List argList) { sourcePlayer.sendMessage(Text.of("Here is a list of available banks on the server: " + BankManager.GetInstance().GetAllBankNames())); } // Possible code paths: // REQUIRED (path 1) = {AMOUNT} [FROM:{INTERNAL ACCOUNT #|ALIAS}] TO:{INTERNAL ACCOUNT #|ALIAS} ***Note: can be assumed to be SELECTED default if not specified // REQUIRED (path 2) = {INTERNAL ACCOUNT #|ALIAS} {EXTERNAL BANK/FACTION ID} // OPTIONAL = [] ///////////////////////////////////////////////////////////////////////////// /// @fn MoveCommand /// /// @param[in] player is player who ran command /// /// @param[in] argList is the argument list to be parsed /// /// @brief Command to move account. Read above comment for code paths ///////////////////////////////////////////////////////////////////////////// public void MoveCommand(ServerPlayerEntity sourcePlayer, List argList) { if (argList.size() >= 2) { String possibleExternalIdentifier = argList.get(1); boolean isExternalTransfer = false; /* * CALL TO BANKMGR TO VERIFY IF ABOVE IS VALID BANK ID. IF NOT; THIS IS INTERNAL TRANSFER */ if (isExternalTransfer) { // External move to another bank or faction String targetMoveAccount = argList.get(0); String destBankId = argList.get(1); /* * CALL TO BANKMGR TO MOVE ACCOUNTS HERE */ } else { // Internal transfer to this players accounts within system String optionalFromAccount = ""; /* CALL TO BANKMGR TO GET DEFAULT SELECTED ACCOUNT FOR `FROM` FIELD */ if (argList.size() == 3) { optionalFromAccount = argList.get(1); } String transferAmount = argList.get(0); String destinationTransfer = argList.get(2); /* * BANK MGR CALL HERE */ } } else { sourcePlayer.sendMessage(Text.of("Unrecognized move command. Please use \"/bank help MOVE\" for more information.")); } } // Posible code paths: // REQUIRED = {ACCOUNT-ID|ALIAS} {ALIAS} // OPTIONAL = [] ///////////////////////////////////////////////////////////////////////////// /// @fn AliasCommand /// /// @param[in] player is player who ran command /// /// @param[in] argList is the argument list to be parsed /// /// @brief Aliases an account with a nick name ///////////////////////////////////////////////////////////////////////////// public void AliasCommand(ServerPlayerEntity sourcePlayer, List argList) { if (argList.size() > 0) { String newAlias = argList.get(0); /* * CALL TO BANKMGR TO SEE IF ALIAS ARG ALREADY EXISTS */ } else { sourcePlayer.sendMessage(Text.of("Unrecognized alias command. Please run \"/bank help ALIAS\" for more information.")); } } // Possible code paths: // REQUIRED = {...} valid argList required // OPTIONAL = [] // NOTE: This is just a shorthand to get to `/bank create report` ///////////////////////////////////////////////////////////////////////////// /// @fn ReportCommand /// /// @param[in] player is player who ran command /// /// @param[in] argList is the argument list to be parsed /// /// @brief Shorthand function call-through to CreateCommand for generating /// an account(s) report. ///////////////////////////////////////////////////////////////////////////// public void ReportCommand(ServerPlayerEntity sourcePlayer, List argList) { if (argList.size() > 0) { argList.add(0, "report"); // Since we lose 'report' when we pass it as an alias/passthrough; we just shim it into the first spot CreateCommand(sourcePlayer, argList); } else { sourcePlayer.sendMessage(Text.of("Unrecognized report command. Please run \"/bank help REPORT\" for more information.")); } } // Possible code paths: // REQUIRED = {} // OPTIONAL = [identifier|alias] public int BalanceCommand(ServerPlayerEntity sourcePlayer, List argList) { String accountToBalance = "default"; /* * * Code here to get default account from player * */ if (argList.size() == 1) { /* * Set accountToBalance here */ } /* * Return to player balance here in new chatutil function not yet made */ return 0; } // Create command - valid arg list types: // /... CREATE {CA/checking/savings/checking-account/savings-account/report} ///////////////////////////////////////////////////////////////////////////// /// @fn CreateCommand /// /// @param[in] player is player who ran command /// /// @param[in] argList is the argument list to be parsed /// /// @brief Create a bank account or create report on account ///////////////////////////////////////////////////////////////////////////// public int CreateCommand(ServerPlayerEntity sourcePlayer, List argList) { System.out.println("Attempting account creation given arg list { " + argList + " }."); System.out.println("argList size is " + argList.size()); if (argList.size() > 0) { String action = argList.get(0).toLowerCase(); System.out.println("action word is " + action); switch (action) { // Checking & Savings are handled in the same function so we can just "alias" all of these to the same call! case "ca": case "checking": case "checking-account": case "sa": case "savings": case "savings-account": System.out.println("Creating account. Removing index 0 in argList. New argList is { " + argList + " }"); CreateAccount(sourcePlayer, argList); break; case "rep": case "report": GenerateAccountReport(sourcePlayer, argList); break; default: // Unrecognized creation type } } else { sourcePlayer.sendMessage(Text.of("Unrecognized create command formed on bank. Please run \"/bank help CREATE\" for more information")); } return 0; } // Possible code paths: // REQUIRED = {ACCOUNT ID|ALIAS} // OPTIONAL = [] public int CloseCommand(ServerPlayerEntity sourcePlayer, List argList) { if (argList.size() > 0) { String accountToClose = argList.get(0); /* * CALL TO BANKMGR TO DO STUFF */ } else { sourcePlayer.sendMessage(Text.of("Unrecognized close command. Please see \"/bank help CLOSE\" for more information.")); } return 0; } // Possible code paths: // required = {account id | alias} // optional = [default|secondary|backup] public int SelectCommand(ServerPlayerEntity sourcePlayer, List argList) { if (argList.size() > 0) { String requiredArg = argList.get(0); // If the optional args exist; fetch them String optionalArg = ""; if (argList.size() == 2) { optionalArg = argList.get(1); } BankManager.GetInstance().ChangeDefaultPlayerAccount(sourcePlayer, requiredArg); } else { sourcePlayer.sendMessage(Text.of("Unrecognized select command. Please run /bank help select for more information.")); } return 0; } // Possible code paths: // REQUIRED = {AMOUNT} {ACCOUNT_ID} [optional] // OPTIONAL = [reason] ///////////////////////////////////////////////////////////////////////////// /// @fn WireCommand /// /// @param[in] player is player who ran command /// /// @param[in] argList is the argument list to be parsed /// /// @brief Create wire on bank account ///////////////////////////////////////////////////////////////////////////// public int WireCommand(ServerPlayerEntity sourcePlayer, List argList) { System.out.println("WireCommand called with arg size " + argList.size()); if (argList.size() >= 2) { Integer amountToWire = ParseToInteger(sourcePlayer, argList.get(0), HELPCMD_WIRE); String destAccount = argList.get(1); String optionalReason = ""; if (argList.size() >= 3) { optionalReason = argList.get(3); } System.out.println("optional reason: " + optionalReason); BankManager.GetInstance().InitiateBankFundsTransfer(sourcePlayer, destAccount, amountToWire); } else { sourcePlayer.sendMessage(Text.of("Unrecognized wire command. Please run /bank help wire for more information.")); } return 0; } // Possible code paths: // REQUIRED = {} // OPTIONAL = [command|subcommand] ///////////////////////////////////////////////////////////////////////////// /// @fn HelpCommand /// /// @param[in] player is player who ran command /// /// @param[in] helpCommand is the argument list to be parsed /// /// @brief Builds a dynamic help list to the player to see all command /// options on the server ///////////////////////////////////////////////////////////////////////////// public int HelpCommand(ServerPlayerEntity sourcePlayer, List helpCommand) { System.out.println("Running help command"); if (helpCommand.size() == 0) { // General help command for (Entry helpCmd : HELP_COMMANDS.entrySet()) { String cmd = msgFormatter.ColorMsg(helpCmd.getKey(), COLOR_CODE.GOLD); String details = msgFormatter.FormatMsg(helpCmd.getValue(), COLOR_CODE.BLUE, COLOR_CODE.GRAY); sourcePlayer.sendMessage(Text.of(cmd + " --> " + details)); sourcePlayer.sendMessage(Text.of("\n")); } } else { // Iterate over list; verifying what commands are found List unknownCmds = new ArrayList(); for (int i = 0; i < helpCommand.size(); i++) { String newHelpCmd = helpCommand.get(i); if (HELP_COMMANDS.containsKey(newHelpCmd)) { // Print help for this specific command String cmd = msgFormatter.ColorMsg(newHelpCmd, COLOR_CODE.GOLD); String details = msgFormatter.FormatMsg(HELP_COMMANDS.get(newHelpCmd), COLOR_CODE.BLUE, COLOR_CODE.GRAY); sourcePlayer.sendMessage(Text.of(cmd + " -> " + details)); } else { // Add to unknown list at end unknownCmds.add(newHelpCmd); } } // After all prints have finished tell the player the commands they plugged in that we did not recognize if (unknownCmds.size() > 0) { String msg = msgFormatter.ColorMsg("The following commands do not exist or were mispelt: ", COLOR_CODE.RED); sourcePlayer.sendMessage(Text.of(msg + unknownCmds)); } } return 0; } // Possible args: // /bank create {SAVINGS/CHECKING} [optional: alias] ///////////////////////////////////////////////////////////////////////////// /// @fn CreateAccount /// /// @param[in] player is player who ran command /// /// @param[in] accountArgs is the argument list to be parsed /// /// @brief Creates a bank account ///////////////////////////////////////////////////////////////////////////// public void CreateAccount(ServerPlayerEntity player, List accountArgs) { System.out.println("Attempting to create checking account with arg list { " + accountArgs + " }"); if (accountArgs.size() > 0) { String accountType = accountArgs.get(0); String accountAlias = "NO_ALIAS"; // Set the optional account alias for ease-of-reference if (accountArgs.size() >= 2) { accountAlias = accountArgs.get(1).toLowerCase(); } System.out.println("ACCOUNT CREATION REQUESTED WITH TYPE " + accountType + " AND ALIAS " + accountAlias); // FIXME: This is just a patch at the moment to let players make bank accounts in server bank BankManager.GetInstance().InitiateBankAccountCreation(null, player, accountType); } else { player.sendMessage(Text.of("Unrecognized create account command. Please run /bank help create for more information")); } } // Possible code paths for /bank create report // required = {ACCOUNT ID / ALIAS} or {ALL} ///////////////////////////////////////////////////////////////////////////// /// @fn GenerateAccountReport /// /// @param[in] player is player who ran command /// /// @param[in] reportArgs is the argument list to be parsed /// /// @brief Creates a bank account(s) report ///////////////////////////////////////////////////////////////////////////// public void GenerateAccountReport(ServerPlayerEntity player, List reportArgs) { if (reportArgs.size() > 0) { String reportIdentifier = reportArgs.get(0).toLowerCase(); // First path is just to run a report on all accounts this player is attached to: if (reportIdentifier == "all") { /* BANKMANAGER CALL HERE. LOOP LIKELY NEEDED */ } else { /* BANKMANAGER CALL HERE */ } } else { player.sendMessage(Text.of("Unrecognized report field data. Please run /bank help report for more information")); } } }