From d8a6b7ecd91bdcf187d89ea2a7d0718414343d13 Mon Sep 17 00:00:00 2001 From: Jkibbels Date: Mon, 4 Nov 2024 19:45:28 -0500 Subject: [PATCH] [issue/chat-system] GLOBAL CONTENT git br This branch is HIJACKED for all features now until release of server. Inclusion of more financial system; transaction data; and banking information --- .../BankMgr/AccountNumberGenerator.java | 51 ++++ .../keeblarcraft/BankMgr/BankManager.java | 252 +----------------- .../BankMgr/IndividualAccount.java | 107 ++++++++ .../keeblarcraft/BankMgr/IndividualBank.java | 67 +++++ .../BankMgr/TransactionMetadata.java | 15 ++ .../keeblarcraft/Commands/BankCommands.java | 2 +- 6 files changed, 254 insertions(+), 240 deletions(-) create mode 100644 src/main/java/jesse/keeblarcraft/BankMgr/AccountNumberGenerator.java create mode 100644 src/main/java/jesse/keeblarcraft/BankMgr/IndividualAccount.java create mode 100644 src/main/java/jesse/keeblarcraft/BankMgr/IndividualBank.java create mode 100644 src/main/java/jesse/keeblarcraft/BankMgr/TransactionMetadata.java diff --git a/src/main/java/jesse/keeblarcraft/BankMgr/AccountNumberGenerator.java b/src/main/java/jesse/keeblarcraft/BankMgr/AccountNumberGenerator.java new file mode 100644 index 0000000..a59883f --- /dev/null +++ b/src/main/java/jesse/keeblarcraft/BankMgr/AccountNumberGenerator.java @@ -0,0 +1,51 @@ +package jesse.keeblarcraft.BankMgr; + +import java.util.Random; +/* + Account number composition: + + EXAMPLE: + KCSB-9284-0JKI94358732 + + EXPLANATION: + The composition of the above number is mostly not random. The composition is 'C' = LETTER, and the first 4 represent the 4-letter combination + of the financial establishment (think of the stock market NASDAQ). The first 4 '#' (# = Number) digits represent the ROUTING number of the bank. + The next '#' (in its own brackets) represents ACCOUNT TYPE. This means the mod supports up to 9 configurations; some examples would be CHECKING + or SAVINGS. The next three '#' (in their own brackets too) will be the first three letters of the username of the account holder inside an ASCII + table. If the letter is not UTF 8 compatible - then the default will be '0'. The LAST eight '#' (not in brackets) are randomly generated via Java. + + * Please note that the brackets in this example are only for demonstration of separating numbers from each other. They do not show up at all in generation. + + + CCCC-####-[#][###]######## + + * Additional note - enums are not implicitly integers under the hood like C++; so, a financial establishment could pass in ANY 0-9 digit for "account type" and + each establishment is allowed to treat that however they want. In one banks case it make checking accounts 3; but in anothers it's 4. This is a general programming + note for now. It is probably best to keep this consistent in your server/mod so tellers can understand them universally. +*/ + +public class AccountNumberGenerator { + + // Callers of this function are required to verify the given number is unique. + public static String NewAccountNumber(String symbol, Integer routingNumber, Integer accountType, String username) { + String generatedAccountNumber = symbol + "-" + routingNumber + "-" + accountType + "-"; + + // Block to translate part of username into number format + for (int i = 0; i < 3; i++) { + if (username.length() >= 3 && username.charAt(i) <= 255) { // 255 is largest ASCII value. Might be a sloppy check; can always test later (if I find someone with non ASCII) + generatedAccountNumber += (int) username.charAt(i); + } else if (username.charAt(i) <= 255) { // Case where length is less than 3 but is still in ASCII table + generatedAccountNumber += (int) username.charAt(i); + } else { // Case where the length is less than 3 and is not standard ASCII + generatedAccountNumber += '0'; + } + } + + // Guarentee an 8 digit number. 10000000 is floor and max rng int is at most 89999999. Combined they total 99999999 + Random rng = new Random(); + Integer randInteger = 10000000 + rng.nextInt(89999999); + generatedAccountNumber += randInteger; + + return generatedAccountNumber; + } +} diff --git a/src/main/java/jesse/keeblarcraft/BankMgr/BankManager.java b/src/main/java/jesse/keeblarcraft/BankMgr/BankManager.java index ccf6a31..8d0d634 100644 --- a/src/main/java/jesse/keeblarcraft/BankMgr/BankManager.java +++ b/src/main/java/jesse/keeblarcraft/BankMgr/BankManager.java @@ -1,256 +1,30 @@ package jesse.keeblarcraft.BankMgr; import java.util.HashMap; -import java.util.Map.Entry; - -import jesse.CommonServerUtils; import jesse.keeblarcraft.ConfigMgr.ConfigManager; -import jesse.keeblarcraft.Utils.ChatUtil; -import jesse.keeblarcraft.Utils.ChatUtil.CONSOLE_COLOR; -import jesse.keeblarcraft.Utils.CustomExceptions.FILE_WRITE_EXCEPTION; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.PlayerManager; -import net.minecraft.server.network.ServerPlayerEntity; +// 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 (TODO for this). +// public class BankManager { - BankManagerFile bankInfo = new BankManagerFile(); // not sure why we make another one but i guess so we - ConfigManager config = new ConfigManager(); // for read and write privs - CommonServerUtils commonServerUtils = new CommonServerUtils(); + ConfigManager config = new ConfigManager(); - public BankManager(String uuid) { - Boolean existingFile = false; - try { - bankInfo = config.GetJsonObjectFromFile("bank/" + uuid + ".json", BankManagerFile.class); - existingFile = true; - } catch (Exception e) { - // Do nothing. This means the file does not exist - } - // In the event the above code failed out, this means a new file has to be - // created for the player's uuid - if (!existingFile) { - System.out.println(ChatUtil.ColoredString("Trying to create new file", CONSOLE_COLOR.BLUE)); - try { - FlashConfig(bankInfo.uuid); - } catch (Exception e) { - System.out.println(ChatUtil.ColoredString("Could not write to file", CONSOLE_COLOR.RED)); - } - } else { - System.out.println(ChatUtil.ColoredString("Moving on", CONSOLE_COLOR.BLUE)); - } + // Contains all account information for a given bank + private class BankAccountInformation { - if ("".equals(bankInfo.uuid)) { - System.out.println(ChatUtil.ColoredString("Assigning new config file for this uuid. No previous existing", - CONSOLE_COLOR.BLUE)); - bankInfo.uuid = uuid; - } } - //this class is the structure for the hashmap in BankManagerFile - private class BankManagerMetaData { - public BankManagerMetaData(long money, String reason, long payment, String otherParty, Integer time) { - this.balance = money; - this.reason = reason; - this.payment = payment; - this.otherParty = otherParty; - this.time = time; - } + // Structure of all the players banking information across all banks. + private class PlayerFinances { - long balance = 0; - String reason; //not sure why my compiler is saying unused - long payment; - String otherParty; - Integer time; + // Key = Bank UUID + // Value = The account information for THIS player + HashMap allBanks; } - // This is the general bank account of the read-in config for the player uuid ||| the class that gets converted into a json for the players file - public class BankManagerFile { - // Players uuid is the name of the file - String uuid; + public BankManager() { - // Contents of file - /* - * Example: - * player_uuid_here: - * { - * "1": - * { - * "balance": "10"; - * "reason": "tax evasion"; - * "payment": $-44 - * "other party": "jt"; - * "time": "30"; - * } - * "2": - * { - * Etc. - * } - * } - */ - public HashMap bank = new HashMap(); - } - - public long GetBalance() { - long ret = 0; - for (Entry entry : bankInfo.bank.entrySet()) { - ret = entry.getValue().balance; - } - return ret; - } - //https://maven.fabricmc.net/docs/fabric-api-0.34.8+1.17/net/fabricmc/fabric/api/networking/v1/PlayerLookup.html maybe this for getting the players im still not sure - public void SetBalance(Integer newBalance, String reason, String otherParty) { - Integer transactionNumber = bankInfo.bank.size(); - bankInfo.bank.put(transactionNumber.toString(), - new BankManagerMetaData(newBalance, reason, newBalance, otherParty, 0)); - - FlashConfig(PlayerListNameChecker(otherParty)); - } - - public void AddMoney(String reason, long payment, String otherParty) { - if (bankInfo.bank.size() > 0) { - for (Entry entry : bankInfo.bank.entrySet()) { - entry.getValue().balance += payment; - entry.getValue().reason = "SERVER: " + reason; - entry.getValue().payment = payment; - entry.getValue().otherParty = otherParty; - entry.getValue().time = 0; - } - } else { - bankInfo.bank.put(bankInfo.uuid, new BankManagerMetaData(payment, reason, payment, otherParty, 0)); - } - - FlashConfig(PlayerListNameChecker(otherParty)); - } - - public void SubtractBalance(String reason, long payment, String otherParty) { - if (bankInfo.bank.size() > 0) { - for (Entry entry : bankInfo.bank.entrySet()) { - entry.getValue().balance -= payment;//not working? - entry.getValue().reason = "SERVER: " + reason; - entry.getValue().payment = payment; - entry.getValue().otherParty = otherParty; - entry.getValue().time = 0; - } - } else { - bankInfo.bank.put(bankInfo.uuid, new BankManagerMetaData(0, reason, payment, otherParty, 0)); - } - - FlashConfig(PlayerListNameChecker(otherParty)); - } - - public void Wire(String reason, long payment, String otherParty) { - if (bankInfo.bank.size() > 0) { - for (Entry entry : bankInfo.bank.entrySet()) { - entry.getValue().balance -= payment; - entry.getValue().reason = reason; - entry.getValue().payment = payment; - entry.getValue().otherParty = otherParty; - entry.getValue().time = 0; - - if (payment <= 0) { - // add a error for the PLAYER not the server - return; - } - } - // make a server instance - MinecraftServer server = CommonServerUtils.GetServerInstance(); - String[] playerList = server.getPlayerNames(); - //NOT SURE IF THIS FOR LOOP IS ONE OFF COULD POSSIBLEY BE SO IF NO ONE IS GETTING MONEY DOUBLE CHECK FOR LOOP - for (int i = 0; i < playerList.length; i++) { - System.out.println(ChatUtil.ColoredString("PLAYERS: " + playerList, CONSOLE_COLOR.YELLOW)); - if (playerList[i] == otherParty) { - System.out.println(ChatUtil.ColoredString("Found Player: " + otherParty, CONSOLE_COLOR.GREEN)); - // we will use getuuidbyname then set the other VALID players bank BE SURE TO - // MAKE THEM A BANK FIRST IF THEY DONT HAVE ONE fortnite forever - if (config.GetFile("bank/" + GetUuidByName(server, otherParty) + ".json").size() < 1) { - BankManagerFile newBankInfo = new BankManagerFile(); - BankManagerMetaData newBank = new BankManagerMetaData(0, "Account Created", 0, "Server", 0); - newBankInfo.bank.put(GetUuidByName(server, otherParty).toString(), newBank); - try { - config.WriteToJsonFile("bank/" + newBankInfo.uuid + ".json", newBankInfo); - } catch (FILE_WRITE_EXCEPTION e) { - System.out.println(ChatUtil.ColoredString("Could not flash notes configuration file", CONSOLE_COLOR.RED)); - return; - } - } - - //since the other player has a account now and we have access to it we can start fucking around - BankManagerFile newBankInfo = new BankManagerFile(); - newBankInfo = config.GetJsonObjectFromFile("bank/" + GetUuidByName(server, otherParty) + ".json", BankManagerFile.class); - // for now we will only use adding valance and not subtracting since that dosent make any sense - for (Entry entry : newBankInfo.bank.entrySet()) { - entry.getValue().balance += payment; - entry.getValue().reason = reason; - entry.getValue().payment = payment; - entry.getValue().otherParty = otherParty; - entry.getValue().time = 0; - } - //cannot use regular flash config since the hard coded values need to add agurment for the uuid - //needs to be inside the player check - FlashConfig(newBankInfo.uuid); - try { - config.WriteToJsonFile("bank/" + newBankInfo.uuid + ".json", bankInfo); - } catch (FILE_WRITE_EXCEPTION e) { - System.out.println(ChatUtil.ColoredString("Could not flash notes configuration file", CONSOLE_COLOR.RED)); - } - - } else { - System.out.println(ChatUtil.ColoredString("Player Not Found: " + otherParty, CONSOLE_COLOR.RED)); - return; - } - } - } else { - System.out.println(ChatUtil.ColoredString("You need to finance better", CONSOLE_COLOR.RED)); - return; - } - } - - String GetUuidByName(MinecraftServer server, String playerName) { - PlayerManager playerManager = server.getPlayerManager(); - ServerPlayerEntity player = playerManager.getPlayer(playerName); - if (player.getUuid() != null) { - return player.getUuidAsString(); - } else { - return ""; - } - } - - String PlayerListNameChecker(String otherParty) { - MinecraftServer server = CommonServerUtils.GetServerInstance(); - String[] playerList = server.getPlayerNames(); - - for (int i = 0; i < playerList.length; i++) { - System.out.println(ChatUtil.ColoredString("PLAYERS: " + playerList, CONSOLE_COLOR.YELLOW)); - if (playerList[i] == otherParty) { - System.out.println(ChatUtil.ColoredString("Found Player: " + otherParty, CONSOLE_COLOR.GREEN)); - // we will use getuuidbyname then set the other VALID players bank BE SURE TO - // MAKE THEM A BANK FIRST IF THEY DONT HAVE ONE fortnite forever - if (config.GetFile("bank/" + GetUuidByName(server, otherParty) + ".json").size() < 1) { - BankManagerFile newBankInfo = new BankManagerFile(); - BankManagerMetaData newBank = new BankManagerMetaData(0, "Account Created", 0, "Server", 0); - newBankInfo.bank.put(GetUuidByName(server, otherParty).toString(), newBank); - try { - config.WriteToJsonFile("bank/" + newBankInfo.uuid + ".json", newBankInfo); - } catch (FILE_WRITE_EXCEPTION e) { - System.out.println(ChatUtil.ColoredString("Could not flash notes configuration file", CONSOLE_COLOR.RED)); - return ""; - } - } - else { - System.out.println(ChatUtil.ColoredString("Bank Account Found", CONSOLE_COLOR.GREEN)); - } - return GetUuidByName(server, otherParty); - } - } - System.out.println(ChatUtil.ColoredString("For Loop condition bypassed Null Playerlist or Null Server instance", CONSOLE_COLOR.RED)); - return ""; - } - - public void FlashConfig(String uuid) { - try { - config.WriteToJsonFile("bank/" + uuid + ".json", bankInfo); - } catch (FILE_WRITE_EXCEPTION e) { - System.out.println(ChatUtil.ColoredString("Could not flash notes configuration file", CONSOLE_COLOR.RED)); - } } } diff --git a/src/main/java/jesse/keeblarcraft/BankMgr/IndividualAccount.java b/src/main/java/jesse/keeblarcraft/BankMgr/IndividualAccount.java new file mode 100644 index 0000000..1585d12 --- /dev/null +++ b/src/main/java/jesse/keeblarcraft/BankMgr/IndividualAccount.java @@ -0,0 +1,107 @@ +package jesse.keeblarcraft.BankMgr; + +import java.util.List; + +// Contains the information of an individuals player's bank account. +// TODO: Add ability to store NBT data of items in the future so we can store not just money but items too +// like a safety deposit box +public class IndividualAccount { + private String accountNumber; + private String accountNumberAlias; + private String routingNumber; // Will always be the bank it's in + private List accountHolders; + private Integer accountBalance; + private Boolean allowNegativeBalance; + private Boolean accountLocked; + private String accountType; // TODO: Replace with enum in future. Valid is "checking" and "savings" right now + + + public IndividualAccount() {} + + public IndividualAccount(String accountNumber, String routingNumber, List holders, + Boolean allowNegativeBalance, Integer initialBalance, String alias) { + this.accountNumber = accountNumber; + this.routingNumber = routingNumber; + this.accountHolders = holders; + this.allowNegativeBalance = allowNegativeBalance; + this.accountBalance = initialBalance; + this.accountNumberAlias = alias; + } + + public void AliasAccount(String newAlias) { + this.accountNumberAlias = newAlias; + } + + public Boolean IsLocked() { + return accountLocked; + } + + public Boolean Deposit(Integer amount) { + Boolean success = false; + if (!accountLocked) + { + accountBalance += amount; + success = true; + } + + return success; + } + + public Boolean Withdraw(Integer amount) { + Boolean success = false; + + if (!accountLocked) + { + // Determine remaining balance + Integer remaining = accountBalance - amount; + success = (remaining < 0 && !allowNegativeBalance); + + // Complete the transaction if successful + if (success) { + accountBalance = remaining; + } + } + return success; + } + + public Boolean CanWithdraw(Integer amount) { + Boolean canWithdraw = false; + + if (!accountLocked && accountBalance - amount >= 0) { + canWithdraw = true; + } + + return canWithdraw; + } + + public Boolean IsHolder(String name) { + Boolean ret = false; + + if (accountHolders.contains(name)) { + ret = true; + } + + return ret; + } + + public Boolean AllowsNegative() { + return this.allowNegativeBalance; + } + + public List GetAccountHolders() { + return accountHolders; + } + + public Integer GetAccountBalance() { + return accountBalance; + } + + public String GetAccountNumber() { + return accountNumber; + } + + public String GetRoutingNumber() { + return routingNumber; + } + +} diff --git a/src/main/java/jesse/keeblarcraft/BankMgr/IndividualBank.java b/src/main/java/jesse/keeblarcraft/BankMgr/IndividualBank.java new file mode 100644 index 0000000..3369381 --- /dev/null +++ b/src/main/java/jesse/keeblarcraft/BankMgr/IndividualBank.java @@ -0,0 +1,67 @@ +package jesse.keeblarcraft.BankMgr; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import jesse.keeblarcraft.ConfigMgr.ConfigManager; + +// Contains the information of an individual bank +// +// The bank will keep track of all accounts within its facilities. In addition to accounts, the bank +// maintains its own identifier which is unique and other misc things. +public class IndividualBank { + ConfigManager config = new ConfigManager(); + private String routingNumber; // this is the banks unique identifier + private String numberOfAccounts; // Total number of accounts the bank has. This includes only active accounts + + // Think FDIC but from the servers account (keeblarcraft insurance corporation) + // KBIC will ensure an amount of money based on its trustworthiness to a bank and the number of holders it has. + private Integer kbicInsuredAmount; + private Boolean kbicInsured; + + // bankMoney is the total amount of money the bank possesses itself. The bank itself is personally responsible + // for backing the amount of money it claims it has and this is the balance that is withdrawn from for credits. + // A bank can have a sum of money that is less than the total amount of money of all its account holders + private Integer bankMoney; + + // Key = ACCOUNT NUMBER + // Value = ACCOUNT + private HashMap accountsList; + private HashMap> accountsListFromName; // This is a list that just points to a list of account numbers by person. USEFUL + private List lockedUsers; // A list of users who are locked out of the bank and are incapable of performing more actions within it + + public IndividualBank(String routingNumber) { + accountsList = new HashMap(); + accountsListFromName = new HashMap>(); + + // READ IN BANK CONFIG + + // A modified config reader is needed here for when each IndividualAccount is read in - the name is taken from that and is attached to the + // 'accountsListFromName' structure. This makes it no worse than O(n) to fill these two structures in + } + + public Boolean CreateAccount(String holderName, String accountType) { + if (accountType.toLowerCase() != "checking" || accountType.toLowerCase() != "savings") { + return false; + } // TODO: Replace String with enum type in future and remove this early return + + Boolean success = false; + + // Verify this isn't a blacklisted user + if (!lockedUsers.contains(holderName)) { + + } + + return success; + } + + public Boolean HasAccount(String accountIdentifier) { + Boolean containsAccount = false; + if (accountsList.containsKey(accountIdentifier)) { + containsAccount = true; + } + return true; + } +} diff --git a/src/main/java/jesse/keeblarcraft/BankMgr/TransactionMetadata.java b/src/main/java/jesse/keeblarcraft/BankMgr/TransactionMetadata.java new file mode 100644 index 0000000..64c122b --- /dev/null +++ b/src/main/java/jesse/keeblarcraft/BankMgr/TransactionMetadata.java @@ -0,0 +1,15 @@ +package jesse.keeblarcraft.BankMgr; + +// All details that involve a transaction attempt +public class TransactionMetadata { + enum TRANSACTION_TYPE { + DEBIT, + CREDIT + } + + public String fromParty; // Account ID + public String toParty; // Account ID + public Integer amount; + public String transactionId; + public TRANSACTION_TYPE transactionType; +} diff --git a/src/main/java/jesse/keeblarcraft/Commands/BankCommands.java b/src/main/java/jesse/keeblarcraft/Commands/BankCommands.java index 40eb1e8..9048758 100644 --- a/src/main/java/jesse/keeblarcraft/Commands/BankCommands.java +++ b/src/main/java/jesse/keeblarcraft/Commands/BankCommands.java @@ -463,7 +463,7 @@ public class BankCommands { * * Finally - calls to BankManager here for more * - */ + */ } else { player.sendMessage(Text.of("Unrecognized create account command. Please run /bank help create for more information"));