package jesse.keeblarcraft.BankMgr; import java.util.HashMap; import java.util.List; import java.util.ArrayList; import java.util.Map.Entry; import jesse.keeblarcraft.BankMgr.BankAccountType.ACCOUNT_TYPE; import jesse.keeblarcraft.ConfigMgr.ConfigManager; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.text.Text; // The bank manager takes care of routing any and all transactions throughout the server. // It is a singleton object that is active throughout the mods lifetime and will cache players accounts // when they log in to avoid constant look-ups through JSON. public final class BankManager { private static BankManager static_inst; public static BankManager GetInstance() { if (static_inst == null) { static_inst = new BankManager(); } return static_inst; } private class PlayerBankConfig { List activeBanks = new ArrayList(); // List of all banks a player has accounts in String defaultSelectedBank = ""; String defaultSelectedAccount = ""; } // Key = player uuid // Val = player config HashMap playerConfigs = new HashMap(); // Stores global detail information for bank mgr to use private static Integer KEEBLARCRAFT_SERVER_BANK_ID = 1000; // Server global bank (default bank on server) ConfigManager config = new ConfigManager(); // KEY = Bank routing number // Val = Bank object private HashMap banks = new HashMap(); // KEY = Bank name // Val = Bank routing number private HashMap bankNameFastMap = new HashMap(); public BankManager() { if (playerConfigs == null) { playerConfigs = new HashMap(); } } // TODO: THIS NEEDS TO READ IN FROM A FILE TO STOP NUKING BANKS ON REBOOT ///////////////////////////////////////////////////////////////////////////// /// @fn InitializeBanks /// /// @brief Initializes all the banks on the server at construction time ///////////////////////////////////////////////////////////////////////////// public void InitializeBanks() { banks.put(KEEBLARCRAFT_SERVER_BANK_ID, new IndividualBank(Integer.toString(KEEBLARCRAFT_SERVER_BANK_ID), "KeeblarcraftGlobal")); // Initialize fast map for (Entry bank : banks.entrySet()) { bankNameFastMap.put(bank.getValue().GetBankName(), bank.getValue().GetRoutingNumber()); } } ///////////////////////////////////////////////////////////////////////////// /// @fn GetAllBankNames /// /// @return List of all the banks that exist on a server ///////////////////////////////////////////////////////////////////////////// public List GetAllBankNames() { List names = new ArrayList(); // Iterate through all banks in the list to get their names for (Entry bank : banks.entrySet()) { names.add(bank.getValue().GetBankName()); } return names; } ///////////////////////////////////////////////////////////////////////////// /// @fn GetBankByRoutingNumber /// /// @return The IndividualBank object by routing number if the bank exists ///////////////////////////////////////////////////////////////////////////// public IndividualBank GetBankByRoutingNumber(Integer number) { IndividualBank bank = null; if (banks.containsKey(number)) { bank = banks.get(number); } return bank; } ///////////////////////////////////////////////////////////////////////////// /// @fn GetBankByName /// /// @return The Individualbank object by name if the bank exists ///////////////////////////////////////////////////////////////////////////// public IndividualBank GetBankByName(String name) { IndividualBank bank = null; System.out.println("GetBankByName called with value " + name); if (bankNameFastMap.containsKey(name)) { System.out.println("Value of bank with name is " + bankNameFastMap.get(name)); System.out.println("Banks map size is " + banks.size()); bank = banks.get(bankNameFastMap.get(name)); } System.out.println("Returning bank information"); return bank; } ///////////////////////////////////////////////////////////////////////////// /// @fn ChangeDefaultPlayerAccount /// /// @param[in] player Player object to change default accounts of /// /// @param[in] The new default account global account identifier /// /// @return Changes the players default account at a selected bank ///////////////////////////////////////////////////////////////////////////// public void ChangeDefaultPlayerAccount(ServerPlayerEntity player, String newDefaultAccount) { String bankName = AccountNumberGenerator.GetFinancialSymbolFromId(newDefaultAccount); // Verify bank exists first System.out.println(bankNameFastMap); for(Entry entry : bankNameFastMap.entrySet()) { System.out.println("KEY: " + entry.getKey()); } if (bankNameFastMap.containsKey(bankName)) { Integer routNum = bankNameFastMap.get(bankName); IndividualBank bank = banks.get(routNum); // Verify this person has access to this account if(bank.IsAccountHolder(newDefaultAccount, player.getUuidAsString())) { // Finally update config to this account since checks pass playerConfigs.get(player.getUuidAsString()).defaultSelectedAccount = newDefaultAccount; } } else { player.sendMessage(Text.of("Could not change default selected account. Bank does not exist!")); } } // This guarentees a player config exists; and so can be called from many areas. Does not erase pre-existing config public boolean EnsurePlayerConfigExists(String uuid) { if (!playerConfigs.containsKey(uuid)) { playerConfigs.put(uuid, new PlayerBankConfig()); } return true; } // Allows the player to select a bank public void ChangeDefaultSelectedBank(ServerPlayerEntity player, String bankName) { if (bankNameFastMap.containsKey(bankName) && EnsurePlayerConfigExists(player.getUuidAsString())) { playerConfigs.get(player.getUuidAsString()).defaultSelectedBank = bankName; player.sendMessage(Text.of("You have successfully selected the following financial institution: " + bankName)); player.sendMessage(Text.of("Please be aware the context of commands following this will likely be done under this financial institution")); } else { player.sendMessage(Text.of("That bank does not exist.")); } } ///////////////////////////////////////////////////////////////////////////// /// @fn AdminChangeFunds /// /// @param[in] initiator The player object who is initiating this call /// /// @param[in] accountId The account to change funds of /// /// @param[in] amount The amount to change funds of in changeType /// /// @param[in] changeType The type of funds change being initiated /// /// @param[in] optionalReason The optional reason of changing funds /// /// @brief Command manager to initiate a funds change from an admins /// perspective (safe guards dropped). Valid changeTypes are /// found inside the switch-case statement in the below function ///////////////////////////////////////////////////////////////////////////// public void AdminChangeFunds(ServerPlayerEntity initiator, String accountId, Integer amount, String changeType, String optionalReason) { // Check to make sure account id exists Integer routingNum = AccountNumberGenerator.GetRoutingNumberFromId(accountId); IndividualBank bankFromRout = GetBankByRoutingNumber(routingNum); System.out.println("Is bank null? " + (bankFromRout == null ? "YES" : "NO")); System.out.println("Bank specified: " + bankFromRout); System.out.println("Routing number: " + routingNum); // Verify bank exists if (bankFromRout != null) { // Verify account exists System.out.println("accountNumber is " + accountId); String accountNumber = AccountNumberGenerator.GetAccountNumberFromId(accountId); System.out.println("changeType is " + changeType); switch (changeType) { case "add": bankFromRout.AddMoneyToAccount(accountNumber, amount); break; case "subtract": bankFromRout.SubtractMoneyFromAccount(accountNumber, amount); break; case "set": bankFromRout.SetMoneyOnAccount(accountNumber, amount); break; default: System.out.println("The operation that was specified by the developer does not exist. Valid operations are add/subtract/set"); break; } } else { initiator.sendMessage(Text.of("That bank does not exist!")); } } ///////////////////////////////////////////////////////////////////////////// /// @fn InitiateBankFundsTransfer /// /// @param[in] fromPlayer is the player funds are coming out of /// /// @param[in] toAccount is the account the funds are going to /// /// @param[in] amount is the amount of money coming from the player /// /// @brief Initiate a funds transfer between accounts or banks ///////////////////////////////////////////////////////////////////////////// public void InitiateBankFundsTransfer(ServerPlayerEntity fromPlayer, String toAccount, Integer amount, String reason) { // Get player default selection String fromAccount = playerConfigs.get(fromPlayer.getUuidAsString()).defaultSelectedAccount; String fromAccountSymbol = AccountNumberGenerator.GetFinancialSymbolFromId(fromAccount); String toAccountSymbol = AccountNumberGenerator.GetFinancialSymbolFromId(toAccount); System.out.println("InitiateBankFundsTransfer: FROM_ACCOUNT, FROM_ACCOUNT_SYMBOL, TO_ACCOUNT_SYMBOL: " + fromAccount + ", " + fromAccountSymbol + ", " + toAccountSymbol); Integer destRoutingNumber = bankNameFastMap.get(toAccountSymbol); Integer fromRoutingNumber = bankNameFastMap.get(fromAccountSymbol); IndividualBank destBank = banks.get(destRoutingNumber); IndividualBank fromBank = banks.get(fromRoutingNumber); // Verify banks exist if (destBank != null && fromBank != null) { if (fromBank.IsValidWithdrawal(amount, fromAccount)) { fromBank.SubtractMoneyFromAccount(fromAccount, amount); destBank.AddMoneyToAccount(toAccount, amount); fromPlayer.sendMessage(Text.of("[" + fromAccountSymbol + "]: Your wire has processed.")); } else { fromPlayer.sendMessage(Text.of("[" + fromAccountSymbol + "]: You are not allowed to make this withdrawal.")); } } else { fromPlayer.sendMessage(Text.of("Something went wrong! Either your bank or their bank does not exist. You shouldn't get this error!")); } } public void InitiateBankAccountClosure(String bankIdentifier, ServerPlayerEntity player, String bankAccountId) { } ///////////////////////////////////////////////////////////////////////////// /// @fn GetDefaultSelectedAccount /// /// @param[in] playerUuid is the player to get their default account /// /// @param[in] bankIdentifier is the bank the default account is at /// /// @brief Gets a players default account /// /// @return The global account identifier of the default selected account ///////////////////////////////////////////////////////////////////////////// public String GetDefaultSelectedAccount(String playerUuid, String bankIdentifier) { String account = ""; if (playerConfigs.containsKey(playerUuid)) { account = playerConfigs.get(playerUuid).defaultSelectedAccount; } return account; } public String GetPlayerSelectedBank(String playerUuid) { String bank = ""; if (playerConfigs.containsKey(playerUuid)) { bank = playerConfigs.get(playerUuid).defaultSelectedBank; } return bank; } ///////////////////////////////////////////////////////////////////////////// /// @fn InitiateBankAccountCreation /// /// @param[in] bankIdentifier is the bank routing number /// /// @param[in] player is the player object trying to create account /// /// @paran[in] accountType Is the type of account the player wants to make /// /// @brief Initiates a bank account creation with a bank ///////////////////////////////////////////////////////////////////////////// public void InitiateBankAccountCreation(String bankIdentifier, ServerPlayerEntity player, ACCOUNT_TYPE accountType) { Boolean success = false; IndividualBank bank = GetBankByName(bankIdentifier); if (bank != null) { success = bank.CreateAccount(player.getUuidAsString(), player.getEntityName(), accountType); } if (success) { player.sendMessage(Text.of("The banking operation was successful and your banking information has been updated")); } else { player.sendMessage(Text.of("The banking operating FAILED. Make sure you selected this bank before creating it!")); } } }