issue/finish-factions-and-banking #2

Merged
jkibbels merged 11 commits from issue/finish-factions-and-banking into dev 2025-02-01 19:26:22 +00:00
49 changed files with 1397 additions and 543 deletions

View File

@ -1,19 +1,26 @@
package jesse.keeblarcraft;
import jesse.keeblarcraft.Entities.EntityRegistration;
import jesse.keeblarcraft.GuiMgr.Entities.ShopKeeperRenderer;
import jesse.keeblarcraft.gui.ClientHandlers;
// import jesse.keeblarcraft.gui.ScreenManager;
// import jesse.keeblarcraft.gui.widgets.TreeWidget;
import jesse.keeblarcraft.Shortcuts.ShortcutManager;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.client.rendereregistry.v1.EntityRendererRegistry;
import net.minecraft.client.render.entity.model.EntityModelLayer;
import net.minecraft.util.Identifier;
public class KeeblarcraftClient implements ClientModInitializer {
public static final EntityModelLayer SHOP_KEEPER_LAYER = new EntityModelLayer(new Identifier("textures/entity/villager/villager.png"), "VILLAGE_ENTITY_MODEL_LAYER");
@Override
public void onInitializeClient() {
ShortcutManager.RegisterKeybinds();
ClientHandlers.RegisterHandlers();
// EntityRendererRegistry.INSTANCE.register(EntityRegistration.SHOP_KEEPER_ENTITY_TYPE, (context) -> {
// return new ShopKeeperRenderer(context);
// });
// ScreenManager.GetInstance();
// ScreenManager.AddWidget(TreeWidget.class, 10);
}

View File

@ -2,9 +2,13 @@ package jesse.keeblarcraft.AttributeMgr.AttributeNodes.FactionNodes;
import java.util.HashMap;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import jesse.keeblarcraft.AttributeMgr.AttributeNodes.AbstractNode;
import jesse.keeblarcraft.FactionMgr.FactionTier;
import jesse.keeblarcraft.FactionMgr.Callbacks.PlayerInBaseCallback;
import jesse.keeblarcraft.FactionMgr.FactionTier.FactionTierEnum;
import net.minecraft.entity.effect.StatusEffectInstance;
import net.minecraft.entity.effect.StatusEffects;
import net.minecraft.server.network.ServerPlayerEntity;
@ -12,7 +16,10 @@ import net.minecraft.util.ActionResult;
public class FactionBeacon extends AbstractNode {
private int beaconStrength = 1; // Increases with faction power; 1 is default
private float absorptionAmnt = 0.2f * beaconStrength;
private int potionEffectLastingTimeTicks = 200; // 20 ticks per second makes this 10 seconds
private final Integer timerLengthMillis = 5000; // The default potion length is 10 seconds; so reset every 5 to be sure!
private Boolean resetTimer = true;
private final Timer timer = new Timer();
@Override
public String GetNodeTitle() {
return "faction_beacon";
@ -30,20 +37,101 @@ public class FactionBeacon extends AbstractNode {
return ret;
}
private void ApplyEffects(ServerPlayerEntity player) {
private Integer GetBeaconAmplifier(FactionTierEnum tier) {
switch (tier) {
case TIER_I:
Review

you should leave a commet saying TIER_I has no effects this could be confusing

you should leave a commet saying TIER_I has no effects this could be confusing
case TIER_II:
beaconStrength = 0;
break;
case TIER_III:
beaconStrength = 1;
break;
case TIER_IV:
beaconStrength = 2;
break;
case TIER_V:
beaconStrength = 3;
break;
case TIER_VI:
beaconStrength = 8;
break;
default:
// Invalid case; in which case the beacon probably should do nothing
beaconStrength = 0;
break;
}
return beaconStrength;
}
private void ApplyEffects(ServerPlayerEntity player, FactionTierEnum tier) {
// player.setAbsorptionAmount(absorptionAmnt);
StatusEffectInstance sei = new StatusEffectInstance(StatusEffects.REGENERATION, 1000, 1, true, true, true);
player.addStatusEffect(sei);
// Duration is in ticks
beaconStrength = GetBeaconAmplifier(tier);
// Tier 2 effects
if (FactionTier.IsGreaterOrEqualTo(tier, FactionTierEnum.TIER_II)) {
StatusEffectInstance regen = new StatusEffectInstance(StatusEffects.REGENERATION, potionEffectLastingTimeTicks, beaconStrength, true, true, true);
StatusEffectInstance fire = new StatusEffectInstance(StatusEffects.FIRE_RESISTANCE, potionEffectLastingTimeTicks, beaconStrength, true, true, true);
player.addStatusEffect(regen);
player.addStatusEffect(fire);
}
// Tier 3 effects
if (FactionTier.IsGreaterOrEqualTo(tier, FactionTierEnum.TIER_III)) {
StatusEffectInstance hero = new StatusEffectInstance(StatusEffects.HERO_OF_THE_VILLAGE, potionEffectLastingTimeTicks, beaconStrength, true, true, true);
StatusEffectInstance haste = new StatusEffectInstance(StatusEffects.HASTE, potionEffectLastingTimeTicks, beaconStrength, true, true, true);
player.addStatusEffect(hero);
player.addStatusEffect(haste);
}
// Tier 4 effects
if (FactionTier.IsGreaterOrEqualTo(tier, FactionTierEnum.TIER_IV)) {
StatusEffectInstance conduit = new StatusEffectInstance(StatusEffects.CONDUIT_POWER, potionEffectLastingTimeTicks, 0, true,true, true);
StatusEffectInstance luck = new StatusEffectInstance(StatusEffects.LUCK, potionEffectLastingTimeTicks, beaconStrength, true, true, true);
StatusEffectInstance absorption = new StatusEffectInstance(StatusEffects.ABSORPTION, potionEffectLastingTimeTicks, beaconStrength, true, true, true);
StatusEffectInstance waterBreathing = new StatusEffectInstance(StatusEffects.WATER_BREATHING, potionEffectLastingTimeTicks, beaconStrength, true, true, true);
player.addStatusEffect(conduit);
player.addStatusEffect(luck);
player.addStatusEffect(absorption);
player.addStatusEffect(waterBreathing);
}
// Tier 5 effects
if (FactionTier.IsGreaterOrEqualTo(tier, FactionTierEnum.TIER_V)) {
StatusEffectInstance resistance = new StatusEffectInstance(StatusEffects.RESISTANCE, potionEffectLastingTimeTicks, beaconStrength, true, true, true);
StatusEffectInstance strength = new StatusEffectInstance(StatusEffects.STRENGTH, potionEffectLastingTimeTicks, beaconStrength, true, true, true);
StatusEffectInstance dolphins = new StatusEffectInstance(StatusEffects.DOLPHINS_GRACE, potionEffectLastingTimeTicks, beaconStrength, true, true, true);
player.addStatusEffect(resistance);
player.addStatusEffect(strength);
player.addStatusEffect(dolphins);
}
// Tier 6 effects
if (FactionTier.IsGreaterOrEqualTo(tier, FactionTierEnum.TIER_VI)) {
StatusEffectInstance freeHealth = new StatusEffectInstance(StatusEffects.HEALTH_BOOST, potionEffectLastingTimeTicks, beaconStrength, true, true, true);
player.addStatusEffect(freeHealth);
}
}
@Override
public void RegisterCallbacks() {
System.out.println("REGISTER CALLBACKS FOR FACTION BEACON CALLED");
PlayerInBaseCallback.EVENT.register((player, world) -> {
// Make sure player can fly while inside the border. We don't ever want to run this more than once!
// player.sendMessage(Text.of("Applying effects"));
ApplyEffects((ServerPlayerEntity) player);
return ActionResult.SUCCESS;
PlayerInBaseCallback.EVENT.register((player, world, power, factionTier) -> {
if (resetTimer) {
// The timer is super necessary because some effects (like regen) will not actually regen the player unless they can run for a few seconds
timer.schedule(new TimerTask() {
@Override
public void run() {
ApplyEffects((ServerPlayerEntity) player, factionTier);
resetTimer = true;
}
}, timerLengthMillis);
resetTimer = false;
}
return ActionResult.PASS;
});
}

View File

@ -78,7 +78,7 @@ public class FactionFlight extends AbstractNode {
@Override
public void RegisterCallbacks() {
PlayerEnteredBaseCallback.EVENT.register((player, world) -> {
PlayerEnteredBaseCallback.EVENT.register((player, world, power, factionTier) -> {
player.sendMessage(Text.of("Faction flight enabled"));
canFly = true;
ServerPlayerEntity serverPlayer = (ServerPlayerEntity) player;
@ -88,7 +88,7 @@ public class FactionFlight extends AbstractNode {
return ActionResult.PASS;
});
PlayerInBaseCallback.EVENT.register((player, world) -> {
PlayerInBaseCallback.EVENT.register((player, world, power, factionTier) -> {
// Make sure player can fly while inside the border. We don't ever want to run this more than once!
if (!canFly && !loginInBaseToggle) {
player.sendMessage(Text.of("Faction flight enabled"));
@ -100,7 +100,7 @@ public class FactionFlight extends AbstractNode {
return ActionResult.PASS;
});
PlayerCommandFlightCallback.EVENT.register((player, world) -> {
PlayerCommandFlightCallback.EVENT.register((player, world, power, factionTier) -> {
ServerPlayerEntity serverPlayer = (ServerPlayerEntity) player;
Boolean isFlying = TurnOnFlight(serverPlayer);
// This is a toggle command; so first we get if the player is flying
@ -124,7 +124,7 @@ public class FactionFlight extends AbstractNode {
return ActionResult.PASS;
});
PlayerExitedBaseCallback.EVENT.register((player, world) -> {
PlayerExitedBaseCallback.EVENT.register((player, world, power, factionTier) -> {
Timer timer = new Timer();
canFly = false;
player.sendMessage(Text.of("You left the faction's perimeter! Flight will disable in 5 seconds..."));

View File

@ -4,8 +4,11 @@ import java.util.HashMap;
import java.util.List;
import java.util.ArrayList;
import java.util.Map.Entry;
import java.util.Optional;
import jesse.keeblarcraft.BankMgr.BankAccountType.ACCOUNT_TYPE;
import jesse.keeblarcraft.ChatStuff.ChatFormatting;
import jesse.keeblarcraft.ChatStuff.ChatMsg;
import jesse.keeblarcraft.ConfigMgr.ConfigManager;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.Text;
@ -23,7 +26,7 @@ public final class BankManager {
return static_inst;
}
private class PlayerBankConfig {
private static class PlayerBankConfig {
List<String> activeBanks = new ArrayList<String>(); // List of all banks a player has accounts in
String defaultSelectedBank = "";
String defaultSelectedAccount = "";
@ -31,10 +34,10 @@ public final class BankManager {
// Key = player uuid
// Val = player config
HashMap<String, PlayerBankConfig> playerConfigs = new HashMap<String, PlayerBankConfig>(); // Stores global detail information for bank mgr to use
private HashMap<String, PlayerBankConfig> playerConfigs = new HashMap<String, PlayerBankConfig>(); // 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();
private ConfigManager config = new ConfigManager();
// KEY = Bank routing number
// Val = Bank object
@ -45,9 +48,6 @@ public final class BankManager {
private HashMap<String, Integer> bankNameFastMap = new HashMap<String, Integer>();
public BankManager() {
if (playerConfigs == null) {
playerConfigs = new HashMap<String, PlayerBankConfig>();
}
}
// TODO: THIS NEEDS TO READ IN FROM A FILE TO STOP NUKING BANKS ON REBOOT
@ -57,14 +57,39 @@ public final class BankManager {
/// @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"));
banks.put(KEEBLARCRAFT_SERVER_BANK_ID, new IndividualBank(Integer.toString(KEEBLARCRAFT_SERVER_BANK_ID), "Keeblarcraft"));
// Initialize fast map
for (Entry<Integer, IndividualBank> bank : banks.entrySet()) {
bankNameFastMap.put(bank.getValue().GetBankName(), bank.getValue().GetRoutingNumber());
bankNameFastMap.put(bank.getValue().GetBankName().toUpperCase(), bank.getValue().GetRoutingNumber());
}
}
// Retrieves balance of the default selected account should that be selected
public void GetBalance(ServerPlayerEntity player) {
if (playerConfigs.containsKey(player.getUuidAsString()) && !playerConfigs.get(player.getUuidAsString()).defaultSelectedAccount.isEmpty()) {
String playerSelectedBank = GetPlayerSelectedBank(player.getUuidAsString());
if (!playerSelectedBank.isEmpty()) {
IndividualBank bank = GetBankByName(playerSelectedBank);
Optional<Integer> amount = bank.GetAccountBalance(AccountNumberGenerator.GetAccountNumberFromId(playerConfigs.get(player.getUuidAsString()).defaultSelectedAccount));
if (amount.isPresent()) {
jkibbels marked this conversation as resolved
Review

if this actually works id be impressed with it >_>

if this actually works id be impressed with it >_>
player.sendMessage(Text.of(ChatMsg.ColorMsg("You have " + amount.get() + " keebucks", ChatFormatting.COLOR_CODE.GREEN)));
} else {
player.sendMessage(Text.of(ChatMsg.ColorMsg("It appears your default account cannot be found at this bank! Re-select your default account maybe?", ChatFormatting.COLOR_CODE.RED)));
}
} else {
player.sendMessage(Text.of(ChatMsg.ColorMsg("You don't have a bank selected first! To use balance you need a default bank AND account selected!", ChatFormatting.COLOR_CODE.RED)));
}
} else {
player.sendMessage(Text.of(ChatMsg.ColorMsg("You don't have a bank selected first! To use balance you need a default bank AND account selected!", ChatFormatting.COLOR_CODE.RED)));
}
}
public Boolean IsDefaultAccount(String playerUuid, String globalAccountId) {
return playerConfigs.containsKey(playerUuid) && playerConfigs.get(playerUuid).defaultSelectedAccount.equals(globalAccountId);
}
/////////////////////////////////////////////////////////////////////////////
/// @fn GetAllBankNames
///
@ -100,14 +125,10 @@ public final class BankManager {
/////////////////////////////////////////////////////////////////////////////
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;
}
@ -117,34 +138,23 @@ public final class BankManager {
/// @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<String, Integer> 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
Integer routingNumber = AccountNumberGenerator.GetRoutingNumberFromId(newDefaultAccount);
if (banks.containsKey(routingNumber)) {
IndividualBank bank = banks.get(routingNumber);
String accountId = AccountNumberGenerator.GetAccountNumberFromId(newDefaultAccount); // Short ID; not global!
if (bank.IsAccountHolder(accountId, player.getUuidAsString())) {
playerConfigs.get(player.getUuidAsString()).defaultSelectedAccount = newDefaultAccount;
} else {
player.sendMessage(Text.of("You are not an account holder on this account! Cannot set"));
}
} 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
// This guarantees 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());
@ -227,17 +237,17 @@ public final class BankManager {
/////////////////////////////////////////////////////////////////////////////
public void InitiateBankFundsTransfer(ServerPlayerEntity fromPlayer, String toAccount, Integer amount, String reason) {
// Get player default selection
if (!playerConfigs.containsKey(fromPlayer.getUuidAsString()) || playerConfigs.get(fromPlayer.getUuidAsString()).defaultSelectedAccount.isEmpty()) {
fromPlayer.sendMessage(Text.of("You need to select a default bank account from the bank you have selected to wire from first! /bank select-default-account"));
return;
}
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);
Integer fromRoutingNumber = AccountNumberGenerator.GetRoutingNumberFromId(fromAccount);
Integer toRoutingNumber = AccountNumberGenerator.GetRoutingNumberFromId(toAccount);
IndividualBank destBank = banks.get(fromRoutingNumber);
IndividualBank fromBank = banks.get(toRoutingNumber);
String fromAccountSymbol = AccountNumberGenerator.GetFinancialSymbolFromId(fromAccount); // For chat
// Verify banks exist
if (destBank != null && fromBank != null) {
@ -254,8 +264,21 @@ public final class BankManager {
}
}
public void InitiateBankAccountClosure(String bankIdentifier, ServerPlayerEntity player, String bankAccountId) {
public void InitiateBankAccountClosure(ServerPlayerEntity player, String accountId) {
Integer routing = AccountNumberGenerator.GetRoutingNumberFromId(accountId);
if (banks.containsKey(routing)) {
IndividualBank bank = banks.get(routing);
boolean success = bank.CloseAccount(AccountNumberGenerator.GetAccountNumberFromId(accountId), player.getUuidAsString());
if (success) {
player.sendMessage(Text.of("Successfully closed account."));
} else {
player.sendMessage(Text.of(ChatMsg.ColorMsg("Failed to close account. Contact bank manager for more information.", ChatFormatting.COLOR_CODE.RED)));
}
} else {
player.sendMessage(Text.of(ChatMsg.ColorMsg("That bank doesn't exist.", ChatFormatting.COLOR_CODE.RED)));
}
}
/////////////////////////////////////////////////////////////////////////////

View File

@ -15,9 +15,9 @@ public class IndividualAccount {
private Integer routingNumber; // Will always be the bank it's in
private List<String> accountHolders;
private List<String> accountHolderUuids;
private Integer accountBalance;
private Boolean allowNegativeBalance;
private Boolean accountLocked;
private int accountBalance;
private boolean allowNegativeBalance = false;
private boolean accountLocked = false;
private ACCOUNT_TYPE accountType;
@ -117,7 +117,9 @@ public class IndividualAccount {
/// @return True if succeeds, false if fails
/////////////////////////////////////////////////////////////////////////////
public Boolean Deposit(Integer amount) {
Boolean success = false;
boolean success = false;
System.out.println("Depositing " + amount);
System.out.println("is account locked: " + accountLocked);
if (!accountLocked)
{
accountBalance += amount;
@ -137,13 +139,13 @@ public class IndividualAccount {
/// @return True if succeeds, false if fails
/////////////////////////////////////////////////////////////////////////////
public Boolean Withdraw(Integer amount) {
Boolean success = false;
boolean success = false;
if (!accountLocked)
{
// Determine remaining balance
Integer remaining = accountBalance - amount;
success = (remaining < 0 && !allowNegativeBalance);
int remaining = accountBalance - amount;
success = (remaining >= 0 || allowNegativeBalance);
jkibbels marked this conversation as resolved
Review

is allowNegativeBalance a method?

is allowNegativeBalance a method?
// Complete the transaction if successful
if (success) {
@ -159,13 +161,10 @@ public class IndividualAccount {
/// @return True if account can afford withdrawal, false if not
/////////////////////////////////////////////////////////////////////////////
public Boolean CanWithdraw(Integer amount) {
Boolean canWithdraw = false;
if (!accountLocked && (accountBalance - amount >= 0 || allowNegativeBalance)) {
canWithdraw = true;
}
return canWithdraw;
System.out.println("Account balance: " + accountBalance);
System.out.println("Allow negative balance: " + allowNegativeBalance);
System.out.println("Account positive after deduction: " + (accountBalance - amount >= 0));
return !accountLocked && (accountBalance - amount >= 0 || allowNegativeBalance);
}
/////////////////////////////////////////////////////////////////////////////
@ -173,14 +172,8 @@ public class IndividualAccount {
///
/// @return True if name is on name list
/////////////////////////////////////////////////////////////////////////////
public Boolean IsHolder(String name) {
Boolean ret = false;
if (accountHolders.contains(name)) {
ret = true;
}
return ret;
public Boolean IsHolder(String uuid) {
return accountHolderUuids.contains(uuid);
}
/////////////////////////////////////////////////////////////////////////////
@ -210,6 +203,10 @@ public class IndividualAccount {
return accountBalance;
}
public ACCOUNT_TYPE GetAccountType() {
return accountType;
}
/////////////////////////////////////////////////////////////////////////////
/// @fn GetAccountNumber
///

View File

@ -1,9 +1,6 @@
package jesse.keeblarcraft.BankMgr;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
Review

is this actually nessesary? or is this alot of extra imports IE:https://www.geeksforgeeks.org/java-util-package-java/

is this actually nessesary? or is this alot of extra imports IE:https://www.geeksforgeeks.org/java-util-package-java/
import java.util.Map.Entry;
import static java.util.Map.entry;
@ -13,6 +10,7 @@ import java.io.File;
import jesse.keeblarcraft.ConfigMgr.ConfigManager;
import jesse.keeblarcraft.Keeblarcraft;
import jesse.keeblarcraft.BankMgr.BankAccountType.ACCOUNT_TYPE;
import jesse.keeblarcraft.Utils.CommonStructures.Pair;
// Contains the information of an individual bank
//
@ -35,7 +33,7 @@ public class IndividualBank {
// 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 = 0;
private Integer kbicInsuredAmount = 75_000;
private Boolean kbicInsured = false;
Review

maaaaaaan is it boolean or Boolean

maaaaaaan is it boolean or Boolean
Review

both

both
// bankMoney is the total amount of money the bank possesses itself. The bank itself is personally responsible
@ -83,7 +81,7 @@ public class IndividualBank {
String accountsListDir = CONFIG_LOCATION + routingNumber.toString() + "/accounts/";
System.out.println("accountsListDir + bankName is " + accountsListDir + nameOfBank);
accounts = config.GetJsonObjectFromFile(accountsListDir + nameOfBank, Accounts.class);
existingFile = true;
existingFile = accounts != null;
// TODO: REPLACE WITH SQL SERVER. DIRTY ITERATE OVER ALL FILES IN DIRECTORY TO LOAD STRUCTURE
File dir = new File(accountsListDir);
@ -129,13 +127,13 @@ public class IndividualBank {
List<String> accountHolders = account.getValue().GetAccountHolders();
// Match each user to the secondary map & add to list-value if not existing
for (Integer holderIndex = 0; holderIndex < accountHolders.size(); holderIndex++) {
if (accounts.accountsListFromName.containsKey(accountHolders.get(holderIndex))) {
for (String accountHolder : accountHolders) {
if (accounts.accountsListFromName.containsKey(accountHolder)) {
// Case 1: User exists, update map entry
accounts.accountsListFromName.get(accountHolders.get(holderIndex)).add(account.getKey()); // Add a new account id to this person in the new flat map
accounts.accountsListFromName.get(accountHolder).add(account.getKey()); // Add a new account id to this person in the new flat map
} else {
// Case 2: User does not already exist; add a new map entry
accounts.accountsListFromName.put(accountHolders.get(holderIndex), List.of(account.getKey())); // Store name as key, and new List with the value of ACCOUNT #
accounts.accountsListFromName.put(accountHolder, List.of(account.getKey())); // Store name as key, and new List with the value of ACCOUNT #
}
}
}
@ -168,9 +166,9 @@ public class IndividualBank {
List<IndividualAccount> accountsFromUser = new ArrayList<IndividualAccount>();
List<String> listOfAccounts = accounts.accountsListFromName.get(uuid);
if (listOfAccounts != null && listOfAccounts.size() > 0) {
for (int i = 0; i < listOfAccounts.size(); i++) {
accountsFromUser.add(accounts.accountsList.get(listOfAccounts.get(i)));
if (listOfAccounts != null && !listOfAccounts.isEmpty()) {
for (String listOfAccount : listOfAccounts) {
accountsFromUser.add(accounts.accountsList.get(listOfAccount));
}
}
return accountsFromUser;
@ -298,11 +296,17 @@ public class IndividualBank {
/// @brief Adds money to an account at this bank if it exists
/////////////////////////////////////////////////////////////////////////////
public void AddMoneyToAccount(String accountId, Integer amount) {
IndividualAccount account = accounts.accountsList.get(accountId);
IndividualAccount account = accounts.accountsList.get(AccountNumberGenerator.GetAccountNumberFromId(accountId));
System.out.println("Received account # " + accountId + " and money amnt " + amount);
System.out.println("Is account null? " + (account == null ? "YES":"NO"));
if (account != null) {
account.Deposit(amount);
System.out.println("accounts.accountList.size() : " + accounts.accountsList.size());
for (Entry<String, IndividualAccount> accnt : accounts.accountsList.entrySet()) {
System.out.println("Account num in entry: " + accnt.getValue().GetAccountNumber());
}
if (account != null && account.Deposit(amount)) {
GenerateTransactionReport(TransactionMetadata.TRANSACTION_TYPE.DEPOSIT, new Pair<>("ADMIN", "ADMIN"), new Pair<>("ADMIN", "ADMIN"), amount, "ADMIN");
FlashConfig("bank/" + routingNumber + "/accounts");
}
}
@ -317,15 +321,10 @@ public class IndividualBank {
/// @brief Subtracts money from an account at this bank if it exists
/////////////////////////////////////////////////////////////////////////////
public void SubtractMoneyFromAccount(String accountId, Integer amount) {
IndividualAccount account = accounts.accountsList.get(accountId);
IndividualAccount account = accounts.accountsList.get(AccountNumberGenerator.GetAccountNumberFromId(accountId));
for (Entry<String, IndividualAccount> debug : accounts.accountsList.entrySet()) {
System.out.println("ACCOUNT ID: " + debug.getKey());
System.out.println("ACCOUNT NUM: " + debug.getValue().GetAccountNumber());
}
if (account != null) {
account.Withdraw(amount);
if (account != null && account.Withdraw(amount)) {
GenerateTransactionReport(TransactionMetadata.TRANSACTION_TYPE.WITHDRAWAL, new Pair<>("ADMIN", "ADMIN"), new Pair<>("ADMIN", "ADMIN"), amount, "ADMIN");
FlashConfig("bank/" + routingNumber + "/accounts");
}
}
@ -351,6 +350,7 @@ public class IndividualBank {
if (account != null) {
account.SetMoney(amount);
GenerateTransactionReport(TransactionMetadata.TRANSACTION_TYPE.OTHER, new Pair<>("ADMIN", "ADMIN"), new Pair<>("ADMIN", "ADMIN"), amount, "ADMIN");
FlashConfig("bank/" + routingNumber + "/accounts");
}
}
@ -407,20 +407,37 @@ public class IndividualBank {
return success;
}
/////////////////////////////////////////////////////////////////////////////
/// @fn AliasAccount
///
/// @param[in] accountId to alias
///
/// @param[in] newAlias is name to give this account
///
/// @brief Alias an account
/////////////////////////////////////////////////////////////////////////////
public void AliasAccount(String accountId, String newAlias) {
String accountNumber = AccountNumberGenerator.GetAccountNumberFromId(accountId);
if (accounts.accountsList.containsKey(accountNumber)) {
accounts.accountsList.get(accountNumber).AliasAccount(newAlias);
// fromParty is expected to be UUID mapped to username
// toParty is expected to be UUID mapped to username
// NOTHING should be null in this generation!
public void GenerateTransactionReport(TransactionMetadata.TRANSACTION_TYPE transactionType, Pair<String, String> fromParty, Pair<String, String> toParty, Integer amount, String reason) {
// The transaction ID is to be formatted (for now) as #-FROMUUID-TOUUID-RNG
// For this version, we pray there is not a duplicate RNG dupe and no checking is done for now!
StringBuilder transactionId = new StringBuilder("#" + fromParty.GetKey() + "-" + toParty.GetKey() + Integer.toString(new Random().nextInt(100_000_000) + 1_000_000));
TransactionMetadata trans = new TransactionMetadata(transactionType, fromParty, toParty, amount, transactionId.toString(), reason);
// This is a hacky solution to make sure the transaction file doesn't exist. It is "technically" possible we fail 10 times in a row
// then can't write and thus no papertrail is left - however if the RNG fails to make a unique enough number with these UUID's between
// 1 million and 100 million then we have other issues to worry about.
int maxTries = 10;
// We now want to iterate over the files in the transaction dir and pop a new file in
while (config.DoesFileExist("bank/" + routingNumber + "/transactions/" + transactionId) && maxTries-- >= 0) {
transactionId.append(Integer.toString(new Random().nextInt(100_000_000) + 1_000_000));
}
if (!config.DoesFileExist("bank/" + routingNumber + "/transactions/" + transactionId)) {
config.WriteToJsonFile("bank/" + routingNumber + "/transactions/" + transactionId + ".json", trans);
}
}
// The value 0 should be treated as either non-exist
public Optional<Integer> GetAccountBalance(String accountId) {
Optional<Integer> amount = Optional.empty();
if (accounts.accountsList.containsKey(accountId)) {
IndividualAccount account = accounts.accountsList.get(accountId);
amount = Optional.of(account.GetAccountBalance());
}
return amount;
}
/////////////////////////////////////////////////////////////////////////////
@ -435,7 +452,7 @@ public class IndividualBank {
public Boolean LockAccountHolder(String holderName) {
Boolean success = false;
Integer accountIter = 0;
int accountIter = 0;
for (Entry<String, List<String>> holderAccounts : accounts.accountsListFromName.entrySet()) {
accounts.accountsList.get(holderAccounts.getValue().get(accountIter++)).LockAccount();
}
@ -453,13 +470,15 @@ public class IndividualBank {
///
/// @return True if can close, false if not
/////////////////////////////////////////////////////////////////////////////
public Boolean CloseAccount(String accountId) {
Boolean success = false;
public Boolean CloseAccount(String accountId, String playerUuid) {
boolean success = false;
String accountNumber = AccountNumberGenerator.GetAccountNumberFromId(accountId);
if (accounts.accountsList.get(accountNumber).GetAccountBalance() == 0) {
accounts.accountsList.remove(accountNumber);
if (accounts.accountsList.containsKey(accountId) && accounts.accountsList.get(accountId).GetAccountBalance() == 0) {
System.out.println("Closing user account...");
// The below two lists should ALWAYS be in sync. If there is a discrepancy; this may segfault!
accounts.accountsList.remove(accountId);
accounts.accountsListFromName.get(playerUuid).remove(accountId);
FlashConfig("bank/" + routingNumber + "/accounts");
success = true;
}
return success;
@ -476,11 +495,7 @@ public class IndividualBank {
/// @return True if this bank has this account identifier, false if not
/////////////////////////////////////////////////////////////////////////////
public Boolean HasAccount(String accountIdentifier) {
Boolean containsAccount = false;
if (accounts.accountsList.containsKey(accountIdentifier)) {
containsAccount = true;
}
return containsAccount;
return accounts.accountsList.containsKey(accountIdentifier);
}
/////////////////////////////////////////////////////////////////////////////
@ -496,10 +511,16 @@ public class IndividualBank {
/// @return True if this account can afford this withdrawal. False if not
/////////////////////////////////////////////////////////////////////////////
public Boolean IsValidWithdrawal(Integer withdrawalAmount, String accountIdentifier) {
Boolean isValid = false;
boolean isValid = false;
if (accounts.accountsList.containsKey(accountIdentifier)) {
IndividualAccount account = accounts.accountsList.get(accountIdentifier);
System.out.println("Account id: " + accountIdentifier);
System.out.println("Short account id: " + AccountNumberGenerator.GetAccountNumberFromId(accountIdentifier));
String localAccountId = AccountNumberGenerator.GetAccountNumberFromId(accountIdentifier);
System.out.println("Amount to withdraw: " + withdrawalAmount);
System.out.println("accounts list map: " + accounts.accountsList);
if (accounts.accountsList.containsKey(localAccountId)) {
IndividualAccount account = accounts.accountsList.get(localAccountId);
System.out.println("Is account null? " + (account == null));
if (account.CanWithdraw(withdrawalAmount)) {
isValid = true;
@ -524,9 +545,16 @@ public class IndividualBank {
public Boolean IsAccountHolder(String accountIdentifier, String uuid) {
Boolean isHolder = false;
System.out.println("Looking for accountIdentifier: " + accountIdentifier);
for (Entry<String, IndividualAccount> account : accounts.accountsList.entrySet()) {
System.out.println("ACCOUNT ID: " + account.getKey());
}
// Verify account exists first
if (accounts.accountsList.containsKey(accountIdentifier)) {
isHolder = accounts.accountsList.get(accountIdentifier).IsHolder(uuid);
} else {
System.out.println("Account identifier found to not exist");
}
return isHolder;
@ -546,7 +574,7 @@ public class IndividualBank {
/////////////////////////////////////////////////////////////////////////////
public void FlashConfig(String dirName) {
for (Entry<String, IndividualAccount> singleAccount : accounts.accountsList.entrySet()) {
System.out.println("FlashConfig. dirname: " + dirName);
// Iterate over each one & verify if a file exists inside the dir. if it does;
// nuke it and
// replace it with the new contents in memory
@ -554,6 +582,7 @@ public class IndividualBank {
// delete file
File file = new File(dirName + "/" + accountNum + ".json");
System.out.println("Checking path: " + dirName + "/" + accountNum + ".json");
if (file.exists()) {
file.delete();
}

View File

@ -1,17 +1,30 @@
package jesse.keeblarcraft.BankMgr;
import jesse.keeblarcraft.Utils.CommonStructures.Pair;
// All details that involve a transaction attempt
public class TransactionMetadata {
enum TRANSACTION_TYPE {
public enum TRANSACTION_TYPE {
DEBIT,
CREDIT,
WITHDRAWAL,
DEPOSIT
DEPOSIT,
OTHER
}
public String fromParty; // Account ID
public String toParty; // Account ID or party (like ATM/self,etc)
public Pair<String, String> fromParty; // Account ID
public Pair<String, String> toParty; // Account ID or party (like ATM/self,etc)
public Integer amount;
public String transactionId;
public TRANSACTION_TYPE transactionType;
public String reason;
public TransactionMetadata(TRANSACTION_TYPE transactionType, Pair<String, String> fromParty, Pair<String, String> toParty, Integer amount, String reason, String transactionId) {
this.transactionType = transactionType;
this.transactionId = transactionId;
this.amount = amount;
this.toParty = toParty;
this.fromParty = fromParty;
this.reason = reason;
}
}

View File

@ -0,0 +1,24 @@
package jesse.keeblarcraft.Callbacks;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
import net.minecraft.entity.mob.MobEntity;
import net.minecraft.util.ActionResult;
import net.minecraft.world.World;
public interface MobSpawnCallback {
Event<MobSpawnCallback> EVENT = EventFactory.createArrayBacked(MobSpawnCallback.class,
(listeners) -> (world, mob) -> {
for (MobSpawnCallback listener : listeners) {
ActionResult result = listener.interact(world, mob);
if (result != ActionResult.PASS) {
return result;
}
}
return ActionResult.PASS;
});
ActionResult interact(World world, MobEntity mob);
}

View File

@ -24,20 +24,12 @@ public class ChatFormatting {
/////////////////////////////////////////////////////////////////////////////
public static String GetColor(COLOR_CODE code) {
String colorStr = COLOR_START;
switch(code) {
case BLUE:
return colorStr + "9";
case GRAY:
return colorStr + "7";
case GOLD:
return colorStr + "6";
case RED:
return colorStr + "4";
case GREEN:
return colorStr + "2";
}
// If this code is reachable, then someone has not properly handled the above switch-case
return colorStr;
return switch (code) {
jkibbels marked this conversation as resolved
Review

:O return switch is awesome

:O return switch is awesome
case BLUE -> colorStr + "9";
case GRAY -> colorStr + "7";
case GOLD -> colorStr + "6";
case RED -> colorStr + "4";
case GREEN -> colorStr + "2";
};
}
}
jkibbels marked this conversation as resolved
Review

no code here and also maybe use a default case: if your worried about it

no code here and also maybe use a default case: if your worried about it

View File

@ -5,18 +5,27 @@ import java.util.List;
import jesse.keeblarcraft.ChatStuff.ChatFormatting.COLOR_CODE;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.MutableText;
import net.minecraft.text.Text;
// Create a "chat menu" which is just a menu in chat with pages that a user can click to display
// the next page.
public class ChatMenu {
private List<Text> msgList = new ArrayList<>();
private ArrayList<Text> msgList = new ArrayList<>();
private Text header;
private Text headerFooterSpacing = Text.of(" ");
private Text leftArrow;
private Text rightArrow;
private int pageLimit = 5; // Messages per page in this menu
private int pageLimit = 25; // Messages per page in this menu (//TODO: This is being increased to show all info at once. Need to add callback to flip a page somehow)
private int pageCount = 1; // Calculated at runtime
private ChatMsg formatter = new ChatMsg();
private int currentPage = 0;
ServerPlayerEntity lastTarget;
private enum TURN_DIRECTION {
BACK,
FORWARD
}
public ChatMenu() {
// Initialize default header and arrows
@ -34,6 +43,10 @@ public class ChatMenu {
this.header = header;
}
public void SetHeader(ChatMsg msg) {
this.header = msg.mutableText;
}
public void SetLeftArrow(Text leftArrow) {
this.leftArrow = leftArrow;
}
@ -42,6 +55,57 @@ public class ChatMenu {
this.rightArrow = rightArrow;
}
private Text MakeFooter() {
jkibbels marked this conversation as resolved
Review

Footnote?

Footnote?
Review

? This is for making the footer in the message sent to the user

? This is for making the footer in the message sent to the user
// leftArrow = (Text) formatter.MakeClickCallback((MutableText) leftArrow, new ChatMsgClickEvent(() -> TurnPage(TURN_DIRECTION.BACK)));
// leftArrow = Text.literal("TEST").styled(style -> style.withClickEvent(new ChatMsgClickEvent(() -> {
// System.out.println("Click event called from server");
// })));
MutableText footer = (MutableText) leftArrow;
// This spacing is arbitrary and may be changed in future. It just looks OK for now
footer.append(Text.of(" "));
// rightArrow = formatter.MakeClickCallback((MutableText) rightArrow, new ChatMsgClickEvent(() -> TurnPage(TURN_DIRECTION.FORWARD)));
footer.append(rightArrow);
return (Text) footer;
}
private void TurnPage(TURN_DIRECTION turn) {
System.out.println("TurnPage called");
// The page we need to turn to will be calculated as so:
// msgList[index] where index = (0 + pageLimit) * currentPage(+- 1)
pageCount = (int) Math.ceil(msgList.size() / (double) pageLimit);
// Guard clause: Cannot turn further than end of all pages or before page 1
if ((turn == TURN_DIRECTION.BACK && currentPage == 1) || (turn == TURN_DIRECTION.FORWARD && currentPage == pageCount)) {
return;
}
// Adjust new page number
if (turn == TURN_DIRECTION.BACK) {
--currentPage;
} else {
++currentPage;
}
// Send updated message to player (msg takes care of printing page)
if (lastTarget != null) {
SendMsg(lastTarget);
}
}
private Text MakeHeader() {
MutableText head = (MutableText) Text.of(" ");
head.append(header);
head.append(Text.of(" "));
header = (Text) head;
return header;
}
public void AddMsg(Text newMsg) {
msgList.add(newMsg);
}
@ -50,6 +114,20 @@ public class ChatMenu {
AddMsg(Text.of(newMsg));
}
public void AddMsg(ChatMsg newMsg) {
AddMsg(newMsg.mutableText);
}
public void AddMsg(List<ChatMsg> newMsgList) {
for (int i = 0; i < newMsgList.size(); i++) {
AddMsg(newMsgList.get(i));
}
}
public void AddNewLine() {
AddMsg(Text.of(""));
}
public void ClearList() {
msgList.clear();
pageCount = 1;
@ -61,8 +139,48 @@ public class ChatMenu {
}
}
// Prints the current page
public void SendMsg(ServerPlayerEntity target) {
// Calculate number of pages
pageCount = (int) Math.ceil(msgList.size() / (double) pageLimit);
int startIdx = currentPage * pageLimit;
// Send the header
target.sendMessage(MakeHeader());
int maxCapoutDebug = 20;
int stopIdx = startIdx + pageLimit;
for (int pageItem = startIdx; pageItem < stopIdx && pageItem < msgList.size(); pageItem++) {
target.sendMessage(msgList.get(pageItem));
--maxCapoutDebug;
if (maxCapoutDebug <= 0) {
break;
}
}
// Send the body
// int msgIndex = 0;
// for (int page = 0; page < pageCount && msgList.get(msgIndex) != null; page++) {
// for (int i = 0; i < pageLimit && msgList.get(msgIndex) != null; i++) {
// Text msg = msgList.get(msgIndex);
// if (msg == null) {
// target.sendMessage(msg);
// }
// }
// }
// Send the footer
target.sendMessage(MakeFooter());
// ChatMsg temp = new ChatMsg();
// Text test = (Text) temp.MakeCopyableTxt("<<", "Click to copy", "Copied string");
// Text test2 = (Text) temp.MakeCopyableTxt(">>", "Click to copy", "Copied");
// MutableText temp3 = (MutableText) test;
// temp3.append(test2);
// target.sendMessage((Text) temp3);
}
}

View File

@ -19,6 +19,8 @@ import net.minecraft.text.Style;
import net.minecraft.text.Text;
public class ChatMsg {
public static Text regularText = Text.of("");
public static MutableText mutableText = (MutableText) regularText;
/////////////////////////////////////////////////////////////////////////////
/// @fn MakeCopyableTxt
///
@ -33,7 +35,7 @@ public class ChatMsg {
///
/// @return MutableText of text intended to be used to send to player
/////////////////////////////////////////////////////////////////////////////
public MutableText MakeCopyableTxt(String terminalTxt, String hoverTxt, Integer copyInt) {
public static MutableText MakeCopyableTxt(String terminalTxt, String hoverTxt, Integer copyInt) {
return MakeCopyableTxt(terminalTxt, hoverTxt, Integer.toString(copyInt));
}
@ -51,23 +53,29 @@ public class ChatMsg {
///
/// @return MutableText of text intended to be used to send to player
/////////////////////////////////////////////////////////////////////////////
public MutableText MakeCopyableTxt(String terminalTxt, String hoverTxt, List<String> expandedList) {
String expanded = "[";
public static MutableText MakeCopyableTxt(String terminalTxt, String hoverTxt, List<String> expandedList) {
StringBuilder expanded = new StringBuilder("[");
int index = 0;
for (String str : expandedList) {
expanded += str;
expanded.append(str);
// Add delimiter if next index is not at size
if (++index < expandedList.size()) {
expanded += ",";
expanded.append(",");
}
}
expanded += "]";
expanded.append("]");
return MakeCopyableTxt(terminalTxt, hoverTxt, expanded);
return MakeCopyableTxt(terminalTxt, hoverTxt, expanded.toString());
}
// TODO: This will be added eventually; but requires Mixin black magic
// public MutableText MakeClickCallback(MutableText text, ChatMsgClickEvent callback) {
// text.styled(style -> style.withClickEvent(callback));
// return text;
// }
/////////////////////////////////////////////////////////////////////////////
/// @fn MakeCopyableTxt
///
@ -82,16 +90,14 @@ public class ChatMsg {
///
/// @return MutableText of text intended to be used to send to player
/////////////////////////////////////////////////////////////////////////////
public MutableText MakeCopyableTxt(String terminalTxt, String hoverTxt, String copyStr) {
public static MutableText MakeCopyableTxt(String terminalTxt, String hoverTxt, String copyStr) {
Text copyableText = Text.of(terminalTxt);
MutableText testTxt = (MutableText) copyableText;
System.out.println("Making hoverable stuff");
testTxt.setStyle(Style.EMPTY.withClickEvent(new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, copyStr))
.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Text.of(hoverTxt))));
System.out.println("Done making hoverable stuff");
System.out.println("Value of copyAbleText: " + copyableText.getString());
System.out.println("Value of testTxt: " + testTxt.getString());
mutableText = testTxt;
regularText = copyableText;
return testTxt;
}
@ -108,7 +114,9 @@ public class ChatMsg {
///
/// @return Formatted string of colored text
/////////////////////////////////////////////////////////////////////////////
public String ColorMsg(Integer msg, COLOR_CODE color) {
public static String ColorMsg(Integer msg, COLOR_CODE color) {
regularText = Text.of(ChatFormatting.GetColor(color) + msg + ChatFormatting.COLOR_END);
mutableText = (MutableText) regularText;
return ChatFormatting.GetColor(color) + msg + ChatFormatting.COLOR_END;
}
@ -130,7 +138,9 @@ public class ChatMsg {
/// first with functions inside this class.
/////////////////////////////////////////////////////////////////////////////
public Text ColorMsg(Text msg, COLOR_CODE color) {
return Text.of(ChatFormatting.GetColor(color) + msg.getString() + ChatFormatting.COLOR_END);
regularText = Text.of(ChatFormatting.GetColor(color) + msg.getString() + ChatFormatting.COLOR_END);
mutableText = (MutableText) regularText;
return regularText;
}
/////////////////////////////////////////////////////////////////////////////
@ -147,7 +157,7 @@ public class ChatMsg {
///
/// @return Formatted list of strings
/////////////////////////////////////////////////////////////////////////////
public List<String> ColorMsg(List<String> msg, COLOR_CODE color) {
public static List<String> ColorMsg(List<String> msg, COLOR_CODE color) {
List<String> retList = new ArrayList<String>();
for (String str : msg) {
@ -169,7 +179,7 @@ public class ChatMsg {
///
/// @return Formatted string of colored text
/////////////////////////////////////////////////////////////////////////////
public String ColorMsg(String msg, COLOR_CODE color) {
public static String ColorMsg(String msg, COLOR_CODE color) {
return ChatFormatting.GetColor(color) + msg + ChatFormatting.COLOR_END;
}
@ -190,18 +200,16 @@ public class ChatMsg {
///
/// @return Formatted string of colored text
/////////////////////////////////////////////////////////////////////////////
public String FormatMsg(String helpCmd, COLOR_CODE primaryColor, COLOR_CODE secondaryColor) {
String coloredStr = ChatFormatting.GetColor(primaryColor);
public static String FormatMsg(String helpCmd, COLOR_CODE primaryColor, COLOR_CODE secondaryColor) {
StringBuilder coloredStr = new StringBuilder(ChatFormatting.GetColor(primaryColor));
List<String> splitStr = List.of(helpCmd.split("\\."));
Boolean isFirst = true;
boolean isFirst = true;
for (String str : splitStr) {
coloredStr.append(str);
if (isFirst) {
coloredStr += str;
isFirst = false;
coloredStr += ChatFormatting.GetColor(secondaryColor);
} else {
coloredStr += str;
coloredStr.append(ChatFormatting.GetColor(secondaryColor));
}
}

View File

@ -2,7 +2,6 @@ package jesse.keeblarcraft.Commands;
import com.mojang.brigadier.arguments.IntegerArgumentType;
import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.context.CommandContext;
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
@ -11,54 +10,52 @@ import java.util.Map.Entry;
import static java.util.Map.entry;
import jesse.keeblarcraft.BankMgr.BankAccountType;
import jesse.keeblarcraft.BankMgr.BankManager;
import jesse.keeblarcraft.BankMgr.IndividualAccount;
import jesse.keeblarcraft.BankMgr.IndividualBank;
import jesse.keeblarcraft.BankMgr.BankAccountType.ACCOUNT_TYPE;
import jesse.keeblarcraft.ChatStuff.ChatFormatting;
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<String> FILLER_WORDS = new ArrayList<String>(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";
private static final String HELPCMD_HELP = "help";
private static final String HELPCMD_CREATE = "create";
private static final String HELPCMD_SELECT = "select";
private static final String HELPCMD_CLOSE = "close";
private static final String HELPCMD_REPORT = "report";
private static final String HELPCMD_BALANCE = "balance";
private static final String HELPCMD_EXAMPLES = "examples";
private static final String HELPCMD_MOVE = "move";
private static final String HELPCMD_SYNTAX = "syntax";
private static final String HELPCMD_ALIAS = "alias";
private static final String HELPCMD_WIRE = "wire";
private static final String HELPCMD_ACCOUNTS = "accounts";
private static final String HELPCMD_ADMIN_BALANCE_CHANGE = "admin-set-balance";
private static final String HELPCMD_ADMIN_BALANCE_GET = "admin-get-balance";
private static final String HELPCMD_ADMIN_CREATE_BANK = "admin-create-bank";
private static final String HELPCMD_ADMIN_CLOSE_BANK = "admin-close-bank";
private static final String HELPCMD_ADMIN_FORCE_WIRE = "admin-force-wire";
private static final String HELPCMD_ADMIN_LOCK_BANK = "admin-lock-bank";
private static final String HELPCMD_SET_SERVER_ALLOWANCE = "admin-set-server-allowance";
private static final String HELPCMD_GET_SERVER_ALLOWANCE = "admin-get-server-allowance";
private static final String HELPCMD_ADMIN_COMMANDS_LIST = "admin-commands-list";
private static final String HELPCMD_ADMIN_ACCOUNTS = "admin-accounts";
private static final String HELPCMD_ADMIN_ACCOUNTS_LIST = "admin-accounts-list";
private static final String HELPCMD_ADMIN_ACCOUNTS_MOVE = "admin-accounts-move";
private static final String HELPCMD_ADMIN_ACCOUNTS_FORCE_CLOSE = "admin-accounts-force-close";
private static final String HELPCMD_ADMIN_ACCOUNTS_ADD = "admin-accounts-add";
private static final String HELPCMD_ADMIN_ACCOUNTS_TRANSACTIONS = "admin-accounts-transactions";
private static final String HELPCMD_ADMIN_ACCOUNTS_LOCK = "admin-accounts-lock";
ChatMsg msgFormatter = new ChatMsg();
private static Map<String, String> HELP_COMMANDS = Map.ofEntries(
private static final Map<String, String> 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 <command OR subcommand>. List of possible " +
@ -203,7 +200,9 @@ public class BankCommands {
// Bank help
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
var bankRoot = CommandManager.literal("bank").build();
var help = CommandManager.literal("help").build();
var help = CommandManager.literal("help")
.executes(context -> HelpCommand(context.getSource().getPlayer(), ""))
.build();
var helpTarget = CommandManager.argument("target", StringArgumentType.greedyString())
.executes(context -> HelpCommand(context.getSource().getPlayer(), StringArgumentType.getString(context, "target")))
.build();
@ -214,6 +213,11 @@ public class BankCommands {
bankRoot.addChild(info);
var balance = CommandManager.literal("balance")
.executes(context -> GetBalance(context.getSource().getPlayer()))
.build();
bankRoot.addChild(balance);
var create = CommandManager.literal("create").build();
var createAccount = CommandManager.literal("account").build();
@ -392,31 +396,31 @@ public class BankCommands {
bankRoot.addChild(help);
help.addChild(helpTarget);
});
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
var wire = CommandManager.literal("wire").build();
var account = CommandManager.argument("global_account_id", StringArgumentType.string()).build();
var amount = CommandManager.argument("amount", IntegerArgumentType.integer()).build();
var reason = CommandManager.argument("reason", StringArgumentType.greedyString())
.executes(context -> WireCommand(
context.getSource().getPlayer(),
IntegerArgumentType.getInteger(context, "amount"),
StringArgumentType.getString(context, "global_account_id"),
StringArgumentType.getString(context, "reason")
))
.build();
dispatcher.getRoot().addChild(wire);
wire.addChild(account);
});
}
public int SelectBank(ServerPlayerEntity player, String bank) {
System.out.println("Select bank called");
BankManager.GetInstance().ChangeDefaultSelectedBank(player, bank);
BankManager.GetInstance().ChangeDefaultSelectedBank(player, bank.toUpperCase());
return 0;
}
/////////////////////////////////////////////////////////////////////////////
/// @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;
}
}
public int AdminSubtractMoney(ServerPlayerEntity player, Integer amount, String account, String reason) {
AdminBalanceChange(player, account, amount, "subtract", reason);
return 0;
@ -432,10 +436,6 @@ public class BankCommands {
return 0;
}
public String GetServerAllowance() {
return "";
}
/////////////////////////////////////////////////////////////////////////////
/// @fn AdminBalanceChange
///
@ -456,41 +456,11 @@ public class BankCommands {
BankManager.GetInstance().AdminChangeFunds(player, accountId, amount, type, optionalReason);
}
public void AdminGetBalance(String accountId) {
public int GetBalance(ServerPlayerEntity player) {
BankManager.GetInstance().GetBalance(player);
return 0;
}
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
///
@ -501,44 +471,51 @@ public class BankCommands {
IndividualBank bank = BankManager.GetInstance().GetBankByName(bankName);
if (bank != null) {
System.out.println("Grabbing user account information");
List<IndividualAccount> 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<String> accountHolders = userAccounts.get(i).GetAccountHolders();
Integer accountBalance = userAccounts.get(i).GetAccountBalance();
for (IndividualAccount userAccount : userAccounts) {
String accountNumber = userAccount.GetAccountNumber();
String globalAccountNumber = userAccount.GetGlobalAccountNumber();
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);
List<String> accountHolders = userAccount.GetAccountHolders();
Integer accountBalance = userAccount.GetAccountBalance();
ACCOUNT_TYPE accountType = userAccount.GetAccountType();
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));
String l1 = "ACCOUNT NUMBER: " + ChatMsg.ColorMsg(accountNumber, COLOR_CODE.BLUE);
String l2 = "GLOBAL ACCOUNT NUMBER: " + ChatMsg.ColorMsg(globalAccountNumber, COLOR_CODE.BLUE);
String l3 = "HOLDERS: " + ChatMsg.ColorMsg(accountHolders, COLOR_CODE.GRAY);
String l4 = "ACCOUNT TYPE: " + ChatMsg.ColorMsg(accountType.name(), COLOR_CODE.GRAY);
String l5 = "BALANCE: " + ChatMsg.ColorMsg(accountBalance, COLOR_CODE.GREEN);
// If this is the default account of the player; we will append a "[SELECTED]" tag on it
boolean isDefaultAccount = BankManager.GetInstance().IsDefaultAccount(sourcePlayer.getUuidAsString(), globalAccountNumber);
if (isDefaultAccount) {
l2 = l2 + ChatMsg.ColorMsg(" [SELECTED]", COLOR_CODE.GREEN);
}
sourcePlayer.sendMessage((Text) ChatMsg.MakeCopyableTxt(l1, "Click to copy", accountNumber));
sourcePlayer.sendMessage((Text) ChatMsg.MakeCopyableTxt(l2, "Click to copy", globalAccountNumber));
sourcePlayer.sendMessage((Text) ChatMsg.MakeCopyableTxt(l3, "Click to copy", accountHolders));
sourcePlayer.sendMessage((Text) ChatMsg.MakeCopyableTxt(l4, "Click to copy", accountType.name()));
sourcePlayer.sendMessage((Text) ChatMsg.MakeCopyableTxt(l5, "Click to copy", accountBalance));
sourcePlayer.sendMessage(Text.of("\n"));
}
} else {
sourcePlayer.sendMessage(Text.of(msgFormatter.ColorMsg("That bank does not exist", COLOR_CODE.RED)));
sourcePlayer.sendMessage(Text.of(ChatMsg.ColorMsg("That bank does not exist", COLOR_CODE.RED)));
}
return 0;
}
// TODO: make prettier
public int ListAllBanks(ServerPlayerEntity sourcePlayer) {
sourcePlayer.sendMessage(Text.of("Here is a list of available banks on the server: " + BankManager.GetInstance().GetAllBankNames()));
// Lists out all the banks on the server in a format that the player can read and click to copy
public int ListAllBanks(ServerPlayerEntity player) {
for (String bank : BankManager.GetInstance().GetAllBankNames()) {
String formattedBankName = ChatMsg.ColorMsg(bank, ChatFormatting.COLOR_CODE.BLUE);
player.sendMessage((Text) ChatMsg.MakeCopyableTxt("BANK: " + formattedBankName, "Click to copy bank name", bank));
}
return 0;
}
// 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
///
@ -546,95 +523,15 @@ public class BankCommands {
///
/// @param[in] argList is the argument list to be parsed
///
/// @brief Command to move account. Read above comment for code paths
/// @brief Not finished in this version of the mod
/////////////////////////////////////////////////////////////////////////////
public int MoveCommand(ServerPlayerEntity sourcePlayer, Integer amount, String fromAccount, String toAccount) {
public int MoveCommand(ServerPlayerEntity player, Integer amount, String fromAccount, String toAccount) {
player.sendMessage(Text.of("This command is not supported in this version. You can accomplish the same thing with /wire though, just make sure you have a default account selected first!"));
return 0;
}
// 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<String> 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<String> 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<String> 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;
}
// Possible code paths:
// REQUIRED = {ACCOUNT ID|ALIAS}
// OPTIONAL = []
public int CloseCommand(ServerPlayerEntity sourcePlayer, String account) {
// 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."));
// }
public int CloseCommand(ServerPlayerEntity player, String account) {
BankManager.GetInstance().InitiateBankAccountClosure(player, account);
return 0;
}
@ -660,9 +557,6 @@ public class BankCommands {
return 0;
}
// Possible code paths:
// REQUIRED = {}
// OPTIONAL = [command|subcommand]
/////////////////////////////////////////////////////////////////////////////
/// @fn HelpCommand
///
@ -677,11 +571,11 @@ public class BankCommands {
System.out.println("Running help command");
List<String> helpCommand = new ArrayList<String>(Arrays.asList(helpCommandList.split(" ")));
if (helpCommand.size() == 0) {
if (helpCommand.isEmpty()) {
// General help command
for (Entry<String, String> 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);
String cmd = ChatMsg.ColorMsg(helpCmd.getKey(), COLOR_CODE.GOLD);
String details = ChatMsg.FormatMsg(helpCmd.getValue(), COLOR_CODE.BLUE, COLOR_CODE.GRAY);
sourcePlayer.sendMessage(Text.of(cmd + " --> " + details));
sourcePlayer.sendMessage(Text.of("\n"));
@ -689,31 +583,30 @@ public class BankCommands {
} else {
// Iterate over list; verifying what commands are found
List<String> unknownCmds = new ArrayList<String>();
for (int i = 0; i < helpCommand.size(); i++) {
String newHelpCmd = helpCommand.get(i);
for (String newHelpCmd : helpCommand) {
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);
String cmd = ChatMsg.ColorMsg(newHelpCmd, COLOR_CODE.GOLD);
String details = ChatMsg.FormatMsg(HELP_COMMANDS.get(newHelpCmd), COLOR_CODE.BLUE, COLOR_CODE.GRAY);
sourcePlayer.sendMessage(Text.of(cmd + " -> " + details));
} else {
} else if (!newHelpCmd.isEmpty()){
// Add to unknown list at end
unknownCmds.add(newHelpCmd);
} else {
sourcePlayer.sendMessage(Text.of(ChatMsg.ColorMsg("This is the generic help command for the banking system! You should read the dedicated discord channel to figure out how to setup an account. If you want more, you can do '/help {bank command 1} {bank command 2}' if you want a specific help message on that command. Happy taxing!", COLOR_CODE.BLUE)));
}
}
// 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);
if (!unknownCmds.isEmpty()) {
String msg = ChatMsg.ColorMsg("The following commands do not exist or were mis-pelt: ", COLOR_CODE.RED);
sourcePlayer.sendMessage(Text.of(msg + unknownCmds));
}
}
return 0;
}
// Possible args:
// /bank create {SAVINGS/CHECKING} [optional: alias]
/////////////////////////////////////////////////////////////////////////////
/// @fn CreateAccount
///
@ -727,35 +620,9 @@ public class BankCommands {
String bank = BankManager.GetInstance().GetPlayerSelectedBank(player.getUuidAsString());
System.out.println("Received bank: " + bank);
if (bank != "") {
if (!bank.isEmpty()) {
BankManager.GetInstance().InitiateBankAccountCreation(bank, player, accountType);
}
return 0;
}
// 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<String> 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"));
}
}
}

View File

@ -8,11 +8,13 @@ import com.mojang.brigadier.context.CommandContext;
import jesse.keeblarcraft.FactionMgr.FactionManager;
import jesse.keeblarcraft.FactionMgr.Callbacks.PlayerCommandFlightCallback;
import jesse.keeblarcraft.FactionMgr.FactionTier.FactionTierEnum;
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
import net.minecraft.command.argument.EntityArgumentType;
import net.minecraft.server.command.CommandManager;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.text.Text;
import net.minecraft.util.ActionResult;
@ -32,6 +34,10 @@ public class FactionCommands {
var promote = CommandManager.literal("promote").build();
var demote = CommandManager.literal("demote").build();
var kick = CommandManager.literal("kick").build();
var set = CommandManager.literal("set").build();
var get = CommandManager.literal("get").build();
var power = CommandManager.literal("power").build();
var join = CommandManager.literal("join").build();
var info = CommandManager.literal("info")
.executes(context -> GetFactionInformation(context.getSource().getPlayer()))
.build();
@ -56,6 +62,10 @@ public class FactionCommands {
)
).build();
var joinName = CommandManager.argument("faction_name", StringArgumentType.string())
.executes(context -> JoinFaction(context.getSource().getPlayer(), StringArgumentType.getString(context, "faction_name")))
.build();
var promoteName = CommandManager.argument("target_name", EntityArgumentType.player())
.executes(context -> PromotePlayerInFaction(context, EntityArgumentType.getPlayer(context, "target_name")))
.build();
@ -69,6 +79,15 @@ public class FactionCommands {
.executes(context -> InvitePlayerToFaction(context, EntityArgumentType.getPlayer(context, "target_name")))
.build();
var setPower = CommandManager.literal("power").build();
var setPowerAmnt = CommandManager.argument("power_amount", IntegerArgumentType.integer()).build();
var setPowerName = CommandManager.argument("set_power_name", StringArgumentType.string())
.executes(context -> SetFactionPower(context.getSource().getPlayer(), StringArgumentType.getString(context, "set_power_name"), IntegerArgumentType.getInteger(context, "power_amount")))
.build();
var getPowerName = CommandManager.argument("get_power_name", StringArgumentType.string())
.executes(context -> GetFactionPower(context.getSource().getPlayer(), StringArgumentType.getString(context, "get_power_name"))).build();
var leaveFaction = CommandManager.literal("leave").executes(context -> LeaveFaction(context)
).build();
@ -90,6 +109,18 @@ public class FactionCommands {
factionNode.addChild(info);
factionNode.addChild(invite);
factionNode.addChild(fly);
factionNode.addChild(set);
factionNode.addChild(get);
factionNode.addChild(join);
join.addChild(joinName);
get.addChild(power);
power.addChild(getPowerName);
set.addChild(setPower);
setPower.addChild(setPowerAmnt);
setPowerAmnt.addChild(setPowerName);
promote.addChild(promoteName);
demote.addChild(demoteName);
@ -125,13 +156,31 @@ public class FactionCommands {
private int ForwardFlightCallback(CommandContext<ServerCommandSource> context) {
if (context.getSource().isExecutedByPlayer()) {
ActionResult result = PlayerCommandFlightCallback.EVENT.invoker().interact(context.getSource().getPlayer(), context.getSource().getWorld());
ServerPlayerEntity player = context.getSource().getPlayer();
ServerWorld world = context.getSource().getWorld();
Integer fPower = FactionManager.GetInstance().GetFactionPower(player);
FactionTierEnum fTier = FactionManager.GetInstance().GetFactionTier(FactionManager.GetInstance().GetFactionOfPlayer(player.getUuidAsString()));
ActionResult result = PlayerCommandFlightCallback.EVENT.invoker().interact(player, world, fPower, fTier);
}
return 0;
}
public int SetFactionPower(ServerPlayerEntity caller, String faction, Integer amount) {
FactionManager.GetInstance().SetFactionPower(caller, faction, amount);
Boolean success = FactionManager.GetInstance().SetFactionPower(caller, faction, amount);
if (success) {
caller.sendMessage(Text.of("Successfully set the faction " + faction + " power to " + amount));
} else {
caller.sendMessage(Text.of("This is an operator only command!"));
}
return 0;
}
public int JoinFaction(ServerPlayerEntity player, String factionName) {
FactionManager.GetInstance().JoinFaction(player, factionName);
return 0;
}
@ -140,6 +189,12 @@ public class FactionCommands {
return 0;
}
public int GetFactionPower(ServerPlayerEntity player, String factionName) {
Integer amnt = FactionManager.GetInstance().GetFactionPower(factionName);
player.sendMessage(Text.of("[" + factionName + " - POWER]:" + amnt));
return 0;
}
/////////////////////////////////////////////////////////////////////////////
/// @fn CreateFaction
///
@ -202,7 +257,11 @@ public class FactionCommands {
return 0;
}
// Returns information on the players current faction
private int GetFactionInformation(ServerPlayerEntity player) {
System.out.println("GETTING FACTION INFO");
FactionManager.GetInstance().GetFactionInformation(player);
System.out.println("ENDING FACTION INFO");
return 0;
}
@ -236,13 +295,6 @@ public class FactionCommands {
return retValue;
}
// admin only
private int SetFactionPower() {
int retValue = -1;
return retValue;
}
private int DeclareFactionEvent() {
int retValue = -1;

View File

@ -45,9 +45,7 @@ public class ConfigManager {
// Get a File reference to a file that is created on disk
private File GetFile(String confFile) {
File file = null;
System.out.println("Get file called for " + GLOBAL_CONFIG + confFile);
try {
System.out.println("GetFile Cur Dir: " + Paths.get("").toAbsolutePath().toString());
file = new File(GLOBAL_CONFIG + confFile);
} catch (Exception e) {}
return file;
@ -273,6 +271,13 @@ public class ConfigManager {
public void WriteToJsonFile(String fileName, Object data) {
Gson gson = new GsonBuilder().setPrettyPrinting().create();
try {
// The FileWriter cannot create objects; so we create parent directories before writing. This may be
// changed in the future
File parent = GetFile(fileName).getParentFile();
if (!parent.exists()) {
parent.mkdirs();
}
FileWriter writer = new FileWriter(GetFile(fileName));
gson.toJson(data, writer);
writer.flush();
@ -305,7 +310,7 @@ public class ConfigManager {
}
public Boolean DoesFileExist(String fileName) {
return GetFile(fileName) != null;
return GetFile(fileName).exists();
}
public Boolean DoesDirectoryExist(String dirName) {

View File

@ -70,8 +70,6 @@ public class GeneralConfig {
/// set yet.
/////////////////////////////////////////////////////////////////////////////
public DirectionalVec GetSpawnCoords() {
System.out.println("Among us");
System.out.println("GetSpawnCoords called. is global_spawn null? " + (config.global_spawn == null ? "YES": "NO"));
return config.global_spawn;
}

View File

@ -1,17 +1,23 @@
package jesse.keeblarcraft.CustomBlocks.BlockEntities;
import java.util.ArrayList;
import java.util.HashMap;
import jesse.keeblarcraft.AttributeMgr.AttributeMgr;
import jesse.keeblarcraft.AttributeMgr.AttributeTree;
import jesse.keeblarcraft.Callbacks.MobSpawnCallback;
import jesse.keeblarcraft.FactionMgr.FactionConfig;
import jesse.keeblarcraft.FactionMgr.FactionManager;
import jesse.keeblarcraft.FactionMgr.Callbacks.PlayerEnteredBaseCallback;
import jesse.keeblarcraft.FactionMgr.Callbacks.PlayerExitedBaseCallback;
import jesse.keeblarcraft.FactionMgr.Callbacks.PlayerInBaseCallback;
import jesse.keeblarcraft.FactionMgr.FactionTier.FactionTierEnum;
import jesse.keeblarcraft.GuiMgr.FactionBlockScreenHandler;
import jesse.keeblarcraft.Utils.CommonStructures.Position3d;
import jesse.keeblarcraft.world.ImplementedInventory;
import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory;
import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.entity.mob.MobEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.inventory.Inventories;
@ -30,46 +36,76 @@ import net.minecraft.world.World;
public class FactionBlockEntity extends BlockEntity implements ExtendedScreenHandlerFactory, ImplementedInventory {
private final DefaultedList<ItemStack> inventory = DefaultedList.ofSize(7, ItemStack.EMPTY);
private static final int DEFENSE_SLOT_ONE = 0;
private static final int DEFENSE_SLOT_TWO = 1;
private static final int OFFENSE_SLOT_ONE = 2;
private static final int OFFENSE_SLOT_TWO = 3;
private String faction = null; // Faction this block belongs to
private static int factionPower = 0;
Boolean stopMobSpawn = true;
Boolean hasBuildFlight = true;
Boolean hasSuperBeacon = true;
private FactionTierEnum factionTier = FactionTierEnum.TIER_INVALID;
private Boolean hasStopMobSpawn = true;
private Boolean registeredMobSpawnCallback = false;
private Boolean hasBuildFlight = true;
private Boolean hasSuperBeacon = true;
private Position3d storedBlockPos;
private final double factionDefaultRadiusBlocks = 50; // 50 blocks
private ArrayList<String> playersInRadius = new ArrayList<>();
private HashMap<String, FactionConfig.VALID_FACTION_ROLES> factionPlayers;
protected final PropertyDelegate propertyDelegate;
public FactionBlockEntity(BlockPos pos, BlockState state, String faction) {
this(pos, state);
this.faction = faction;
RegisterMobSpawn();
}
public void SetFaction(String faction) {
this.faction = faction;
}
public String GetFaction() {
return this.faction;
}
public FactionBlockEntity(BlockPos pos, BlockState state) {
super(BlockEntityRegistration.FACTION_BLOCK_ENTITY, pos, state);
storedBlockPos = new Position3d(pos.getX(), pos.getY(), pos.getZ());
this.propertyDelegate = new PropertyDelegate() {
@Override
public int get(int index) {
// The only value we need to get/delegate is faction power
return switch(index) {
default -> factionPower;
};
return factionPower;
}
@Override
public void set(int index, int value) {
switch(index) {
default -> factionPower = value;
};
factionPower = value;
}
@Override
public int size() {
// We are only sync'ing 1 integer - faction power
// We are only syncing 1 integer - faction power
return 1;
}
};
}
private void RegisterMobSpawn() {
if (hasStopMobSpawn && !registeredMobSpawnCallback) {
MobSpawnCallback.EVENT.register((world, mob) -> {
HandleMobSpawn(world, mob);
return ActionResult.PASS;
});
}
}
// TODO: Make sure mobs are within range before targeting!
private void HandleMobSpawn(World world, MobEntity mob) {
if (world.isClient()) {
return;
}
mob.setDespawnCounter(0);
}
@Override
public Text getDisplayName() {
return Text.literal("Faction Home Base Station"); // Replace with proper en_us format later
@ -106,28 +142,67 @@ public class FactionBlockEntity extends BlockEntity implements ExtendedScreenHan
buf.writeBlockPos(this.pos);
}
private Boolean IsPlayerInBounds(PlayerEntity player, BlockPos pos) {
Boolean isNearBlock = false;
// This is uniquely only calculating the second coordinate on 'storedBlockPos' which is the center coordinate of the
// hypothetical sphere
private Boolean DistanceToCenterSphere(double x, double y, double z) {
// Distance between two points
double dist = Math.ceil(Math.sqrt(
Math.abs(Math.pow(Math.floor(x) - storedBlockPos.x, 2)) +
Math.abs(Math.pow(Math.floor(y) - storedBlockPos.y, 2)) +
Math.abs(Math.pow(Math.floor(z) - storedBlockPos.z, 2))));
// Will check in range - assumes same world! 50 is a temporary value at the moment
Boolean xBounds = player.getX() <= pos.getX() + 50 && player.getX() >= pos.getX() - 50;
Boolean yBounds = player.getY() <= pos.getY() + 50 && player.getY() >= pos.getY() - 50;
Boolean zBounds = player.getZ() <= pos.getZ() + 50 && player.getZ() >= pos.getZ() - 50;
if (xBounds && yBounds && zBounds) {
isNearBlock = true;
// Arbitrarily for now; each point of faction power increases the distance by 10. Testing will confirm if this
// is too much or too little. Making this configurable would probably be good to
// Default radius; increased by power
double factionBlockRadius = factionDefaultRadiusBlocks + (10 * factionPower);
return Math.ceil(dist) <= factionBlockRadius;
}
return isNearBlock;
private Boolean IsPlayerInBounds(PlayerEntity player, BlockPos pos) {
Boolean isNearBlock = false;
String playerFaction = FactionManager.GetInstance().GetFactionOfPlayer(player.getUuidAsString());
return playerFaction.equals(faction) && DistanceToCenterSphere(player.getX(), player.getY(), player.getZ());
}
// Call when the block attached to this entity is broken so we can send out our last messages to reset players correctly before perishing
public void ResetBlock() {
System.out.println("Reset block called. Is world null? " + (world == null ? "YES" : "NO"));
if (world != null) {
for (PlayerEntity player : world.getPlayers()) {
Boolean isPlayerInFactionRadius = IsPlayerInBounds(player, pos);
if (isPlayerInFactionRadius) {
ActionResult result = PlayerExitedBaseCallback.EVENT.invoker().interact(player, world, factionPower, factionTier);
}
}
} else {
System.out.println("Error, world is null and FactionBlockEntity cannot reset players!");
}
}
// TODO: There has GOT to be a better way of validating the inventory than this... but it's okay for now! *cries*
public void ValidateInventory() {
// Slots 1, 3, 5 are ATTACK/PASSIVE slots
// Slots 2, 4, 6 are DEFENSE/PASSIVE slots
// Slot 7 is the special slot reserved EXCLUSIVELY for LEGENDARY Tier only! Legendary CANNOT go in other slots!
for (ItemStack item : inventory) {
System.out.println("Item name: " + item.getName());
}
}
// Tick method is called 20 times a second
public void tick(World world, BlockPos pos, BlockState state) {
// For reasons unknown to me and only to Kaupenjoe (youtube video) - we never want to call this on a client.
if (world.isClient()) {
if (world.isClient() || faction == null) {
return;
}
// TODO: Optimize this block so that when it is placed the placers UUID is related to a faction and only pull from a list of those players not the entire server
this.world = world;
//TODO: The below values can ABSOLUTELY be moved to a one-time call-out when the block is created & when a player
// leaves or joins a faction with a simple callback subscriber. Leaving because not doing now, BUT REFACTOR
factionPlayers = FactionManager.GetInstance().GetFactionPlayers(faction);
factionPower = FactionManager.GetInstance().GetFactionPower(faction);
factionTier = FactionManager.GetInstance().GetFactionTier(faction);
for (PlayerEntity player : world.getPlayers()) {
Boolean isPlayerInFactionRadius = IsPlayerInBounds(player, pos);
if (isPlayerInFactionRadius) {
@ -135,13 +210,13 @@ public class FactionBlockEntity extends BlockEntity implements ExtendedScreenHan
// First time entry callback check
if (!playersInRadius.contains(player.getUuidAsString())) {
playersInRadius.add(player.getUuidAsString());
ActionResult result = PlayerEnteredBaseCallback.EVENT.invoker().interact(player, world);
ActionResult result = PlayerEnteredBaseCallback.EVENT.invoker().interact(player, world, factionPower, factionTier);
}
// Invoke the flight attribute on this player
if (hasBuildFlight) {
AttributeMgr.ApplyAttribute(player.getUuidAsString(), "faction_flight");
ActionResult result = PlayerInBaseCallback.EVENT.invoker().interact(player, world);
ActionResult result = PlayerInBaseCallback.EVENT.invoker().interact(player, world, factionPower, factionTier);
}
if (hasSuperBeacon) {
@ -150,28 +225,8 @@ public class FactionBlockEntity extends BlockEntity implements ExtendedScreenHan
}
} else if (!isPlayerInFactionRadius && playersInRadius.contains(player.getUuidAsString())) {
playersInRadius.remove(player.getUuidAsString());
ActionResult result = PlayerExitedBaseCallback.EVENT.invoker().interact(player, world);
ActionResult result = PlayerExitedBaseCallback.EVENT.invoker().interact(player, world, factionPower, factionTier);
}
}
// if (stopMobSpawn) {
// // Temporary for now
// // Sphere center point is going to be X,Y,Z
// Integer X = pos.getX();
// Integer y = pos.getY();
// Integer z = pos.getZ();
// Integer radius = 10;
// }
// if (hasBuildFlight) {
// for (PlayerEntity player : world.getPlayers()) {
// if (IsPlayerInBounds(player, pos)) {
// // Notify the attribute tree to enable this attribute!
// }
// }
// world.getBlockEntity(pos.east());
// }
}
}

View File

@ -19,7 +19,7 @@ public class BlockList {
public static void RegisterBlocks() {
BlockManager.RegisterBlock("example_block_ore", new Block(FabricBlockSettings.copyOf(Blocks.IRON_BLOCK).sounds(BlockSoundGroup.AMETHYST_BLOCK).requiresTool().breakInstantly()));
BlockManager.RegisterBlock("example_block", new ExperienceDroppingBlock(FabricBlockSettings.copyOf(Blocks.IRON_BLOCK).sounds(BlockSoundGroup.ANCIENT_DEBRIS).requiresTool(), UniformIntProvider.create(4, 20)));
BlockManager.RegisterBlock("example_statue", new Block(FabricBlockSettings.copyOf(Blocks.BELL)));
BlockManager.RegisterBlock("faction_base_block", new FactionBaseBlock(FabricBlockSettings.copyOf(Blocks.IRON_BLOCK).nonOpaque()));
BlockManager.RegisterBlock("example_statue", new Block(FabricBlockSettings.copyOf(Blocks.BELL).nonOpaque()));
BlockManager.RegisterBlock("faction_base_block", new FactionBaseBlock(FabricBlockSettings.copyOf(Blocks.COBBLESTONE).requiresTool().nonOpaque()));
jkibbels marked this conversation as resolved
Review

did nonOpaque fix the faces not rendering issue of blocks ajacent

did nonOpaque fix the faces not rendering issue of blocks ajacent
Review

yes

yes
}
}

View File

@ -1,23 +1,34 @@
package jesse.keeblarcraft.CustomBlocks.Blocks;
import jesse.keeblarcraft.ChatStuff.ChatFormatting;
import jesse.keeblarcraft.ChatStuff.ChatMsg;
import jesse.keeblarcraft.FactionMgr.FactionConfig;
import jesse.keeblarcraft.Utils.CommonStructures.Position3d;
import org.jetbrains.annotations.Nullable;
import jesse.keeblarcraft.CustomBlocks.BlockEntities.BlockEntityRegistration;
import jesse.keeblarcraft.CustomBlocks.BlockEntities.FactionBlockEntity;
import jesse.keeblarcraft.FactionMgr.FactionManager;
import net.minecraft.block.*;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.entity.BlockEntityTicker;
import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.screen.NamedScreenHandlerFactory;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.Text;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.ItemScatterer;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.world.World;
public class FactionBaseBlock extends BlockWithEntity implements BlockEntityProvider {
// public static final VoxelShape SHAPE = Block.createCuboidShape(0, 0, 0, 16, 12, 16);
private String faction; // Faction attached to this block
public FactionBaseBlock(Settings settings) {
super(settings);
@ -33,9 +44,52 @@ public class FactionBaseBlock extends BlockWithEntity implements BlockEntityProv
return BlockRenderType.MODEL;
}
@Override
public void onPlaced(World world, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack itemStack) {
if (world.isClient()) {
return;
}
if (placer != null && placer.isPlayer()) {
// We need to run faction checks here and make sure this player owns a faction otherwise they are NOT allowed to place it!
ServerPlayerEntity player = (ServerPlayerEntity) placer;
String fac = FactionManager.GetInstance().GetFactionOfPlayer(player.getUuidAsString());
// We need to verify the faction does not already have a block placed in the world; and make sure the placer
// is the owner of the faction.
Boolean canPlaceFactionBlock = FactionManager.GetInstance().CanPlaceFactionBlock(fac);
System.out.println("hasFacBlock: " + canPlaceFactionBlock);
FactionConfig.VALID_FACTION_ROLES role = FactionManager.GetInstance().GetPlayerRole(fac, placer.getUuidAsString());
System.out.println("Can place block?: " + canPlaceFactionBlock);
System.out.println("Role: " + role.name());
if (canPlaceFactionBlock && role == FactionConfig.VALID_FACTION_ROLES.OWNER) {
FactionBlockEntity bEntity = (FactionBlockEntity) world.getBlockEntity(pos);
// Update block entity - this is the "ultimate success" portion
if (bEntity != null) {
bEntity.SetFaction(fac);
// Enable chunk loading
world.getChunkManager().setChunkForced(world.getChunk(pos).getPos(), true);
faction = fac;
FactionManager.GetInstance().SetFactionBlock(faction, new Position3d(pos.getX(), pos.getY(), pos.getZ()));
player.sendMessage(Text.of(ChatMsg.ColorMsg("This block now begins to the " + fac + " faction!", ChatFormatting.COLOR_CODE.GOLD)));
}
} else if (canPlaceFactionBlock) {
player.sendMessage(Text.of(ChatMsg.ColorMsg("You cannot place more than one faction block per faction!", ChatFormatting.COLOR_CODE.RED)));
world.breakBlock(pos, true);
} else {
player.sendMessage(Text.of(ChatMsg.ColorMsg("You do not appear to be in a faction or are not the leader of this faction. You cannot place this block!", ChatFormatting.COLOR_CODE.RED)));
world.breakBlock(pos, true);
}
} else {
// Only a player should be able to place the block in order to set faction appropriately. Destroy!
world.breakBlock(pos, true);
}
}
@Override
public BlockEntity createBlockEntity(BlockPos pos, BlockState state) {
return new FactionBlockEntity(pos, state);
return new FactionBlockEntity(pos, state, faction);
}
// If block is destroyed; drop inventory
@ -43,10 +97,23 @@ public class FactionBaseBlock extends BlockWithEntity implements BlockEntityProv
public void onStateReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean moved) {
if (state.getBlock() != newState.getBlock()) {
BlockEntity blockEntity = world.getBlockEntity(pos);
if (blockEntity != null && blockEntity instanceof FactionBlockEntity) {
if (blockEntity instanceof FactionBlockEntity) {
ItemScatterer.spawn(world, pos, (FactionBlockEntity) blockEntity);
world.updateComparators(pos, this);
}
// This is pulled directly from #AbstractBlock$AbstractBlockState.class:onStateReplaced
// Catch if the block is being broken. Update our block entity to reset all
if (state.hasBlockEntity() && !state.isOf(newState.getBlock())) {
FactionBlockEntity bEntity = (FactionBlockEntity) world.getBlockEntity(pos);
if (bEntity != null) {
bEntity.ResetBlock();
}
}
// Disable chunk loading
world.getChunkManager().setChunkForced(world.getChunk(pos).getPos(), false);
FactionManager.GetInstance().RemoveFactionBlock(faction, new Position3d(pos.getX(), pos.getY(), pos.getZ()));
super.onStateReplaced(state, world, pos, newState, moved);
}
}
@ -55,7 +122,7 @@ public class FactionBaseBlock extends BlockWithEntity implements BlockEntityProv
// Calls ScreenHandler inside createMenu of entity class
@Override
public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
// Server side handling is different than that of client side handling; we MUST check if we are on a server first because then we must
// Server side handling is different from that of client side handling; we MUST check if we are on a server first because then we must
// request information about this block entity from the server
System.out.println("onUse of faction base block called");
if (!world.isClient()) {

View File

@ -13,7 +13,10 @@ package jesse.keeblarcraft.CustomItems;
import java.util.ArrayList;
import java.util.List;
import jesse.keeblarcraft.CustomItems.Items.FactionBeaconItem;
import jesse.keeblarcraft.CustomItems.Items.FactionFlightItem;
import jesse.keeblarcraft.Keeblarcraft;
import net.fabricmc.fabric.api.item.v1.FabricItemSettings;
import net.minecraft.item.Item;
import net.minecraft.registry.Registries;
import net.minecraft.registry.Registry;
@ -34,7 +37,8 @@ public class ItemManager {
/// 1. The name provided here must match these names:
/// * This items models/item name
/// * This items textures/item name
/// 2 Name must be lowercase & no special characters besides '_'
/// 2. Name must be lowercase & no special characters besides '_'
/// 3. Do NOT provide the Mod ID inside the name part
///
/// @arg[in] item is the item to be added to the item list
///
@ -62,7 +66,7 @@ public class ItemManager {
CustomItemGroups.RegisterGroups();
// The example item provides a demo of how you could make an item in your class
// Item exampleItem = new Item(new FabricItemSettings());
// RegisterItem("metaljacket_helmet", exampleItem);
RegisterItem("faction_upgrade_flight", new FactionFlightItem(new FabricItemSettings().maxCount(1)));
RegisterItem("faction_upgrade_beacon", new FactionBeaconItem(new FabricItemSettings().maxCount(1)));
}
}

View File

@ -0,0 +1,28 @@
package jesse.keeblarcraft.CustomItems.Items;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.text.Text;
import net.minecraft.util.Hand;
import net.minecraft.util.TypedActionResult;
import net.minecraft.world.World;
public class FactionBeaconItem extends Item {
public FactionBeaconItem(Settings settings) {
super(settings);
}
@Override
public TypedActionResult<ItemStack> use(World world, PlayerEntity user, Hand hand) {
if (world.isClient()) {
user.sendMessage(Text.of("This item can only be placed inside the faction home block!"));
}
return super.use(world, user, hand);
}
@Override
public boolean isDamageable() {
return false;
}
}

View File

@ -0,0 +1,28 @@
package jesse.keeblarcraft.CustomItems.Items;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.text.Text;
import net.minecraft.util.Hand;
import net.minecraft.util.TypedActionResult;
import net.minecraft.world.World;
public class FactionFlightItem extends Item {
public FactionFlightItem(Settings settings) {
super(settings);
}
@Override
public TypedActionResult<ItemStack> use(World world, PlayerEntity user, Hand hand) {
if (world.isClient()) {
user.sendMessage(Text.of("This item can only be placed inside the faction home block!"));
}
return super.use(world, user, hand);
}
@Override
public boolean isDamageable() {
return false;
}
}

View File

@ -0,0 +1,22 @@
package jesse.keeblarcraft.Entities;
import jesse.keeblarcraft.Keeblarcraft;
import net.fabricmc.fabric.api.object.builder.v1.entity.FabricDefaultAttributeRegistry;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.SpawnGroup;
import net.minecraft.registry.Registries;
import net.minecraft.registry.Registry;
import net.minecraft.util.Identifier;
public class EntityRegistration {
public static final EntityType<ShopKeeper> SHOP_KEEPER_ENTITY_TYPE = Registry.register(
Registries.ENTITY_TYPE,
Identifier.of(Keeblarcraft.MOD_ID, "shop_keeper"),
EntityType.Builder.create(ShopKeeper::new, SpawnGroup.MISC).setDimensions(1.0f, 1.0f).build("shop_keeper")
);
public static void RegisterEntities() {
Keeblarcraft.LOGGER.info("Registering custom entities...");
FabricDefaultAttributeRegistry.register(SHOP_KEEPER_ENTITY_TYPE, ShopKeeper.createMobAttributes());
}
}

View File

@ -0,0 +1,30 @@
package jesse.keeblarcraft.Entities;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.passive.MerchantEntity;
import net.minecraft.entity.passive.PassiveEntity;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.village.TradeOffer;
import net.minecraft.world.World;
import org.jetbrains.annotations.Nullable;
public class ShopKeeper extends MerchantEntity {
public ShopKeeper(EntityType<? extends MerchantEntity> entityType, World world) {
super(entityType, world);
}
@Override
protected void afterUsing(TradeOffer offer) {
}
@Override
protected void fillRecipes() {
}
@Override
public @Nullable PassiveEntity createChild(ServerWorld world, PassiveEntity entity) {
return null;
}
}

View File

@ -4,7 +4,6 @@ import java.util.HashMap;
import java.util.Map.Entry;
import jesse.keeblarcraft.ConfigMgr.ConfigManager;
import jesse.keeblarcraft.ChatStuff.ChatMsg;
import jesse.keeblarcraft.world.dimension.ModDimensions;
import net.minecraft.nbt.NbtElement;
import net.minecraft.nbt.NbtList;

View File

@ -1,5 +1,6 @@
package jesse.keeblarcraft.FactionMgr.Callbacks;
import jesse.keeblarcraft.FactionMgr.FactionTier.FactionTierEnum;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
import net.minecraft.entity.player.PlayerEntity;
@ -8,9 +9,9 @@ import net.minecraft.world.World;
public interface PlayerCommandFlightCallback {
Event<PlayerCommandFlightCallback> EVENT = EventFactory.createArrayBacked(PlayerCommandFlightCallback.class,
(listeners) -> (player, world) -> {
(listeners) -> (player, world, power, factionTier) -> {
for (PlayerCommandFlightCallback listener : listeners) {
ActionResult result = listener.interact(player, world);
ActionResult result = listener.interact(player, world, power, factionTier);
if (result != ActionResult.PASS) {
return result;
@ -20,5 +21,5 @@ public interface PlayerCommandFlightCallback {
return ActionResult.PASS;
});
ActionResult interact(PlayerEntity player, World world);
ActionResult interact(PlayerEntity player, World world, Integer factionPower, FactionTierEnum factionTier);
}

View File

@ -1,5 +1,6 @@
package jesse.keeblarcraft.FactionMgr.Callbacks;
import jesse.keeblarcraft.FactionMgr.FactionTier.FactionTierEnum;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
import net.minecraft.entity.player.PlayerEntity;
@ -8,9 +9,9 @@ import net.minecraft.world.World;
public interface PlayerEnteredBaseCallback {
Event<PlayerEnteredBaseCallback> EVENT = EventFactory.createArrayBacked(PlayerEnteredBaseCallback.class,
(listeners) -> (player, world) -> {
(listeners) -> (player, world, power, factionTier) -> {
for (PlayerEnteredBaseCallback listener : listeners) {
ActionResult result = listener.interact(player, world);
ActionResult result = listener.interact(player, world, power, factionTier);
if (result != ActionResult.PASS) {
return result;
@ -20,5 +21,5 @@ public interface PlayerEnteredBaseCallback {
return ActionResult.PASS;
});
ActionResult interact(PlayerEntity player, World world);
ActionResult interact(PlayerEntity player, World world, Integer factionPower, FactionTierEnum factionTier);
}

View File

@ -1,5 +1,6 @@
package jesse.keeblarcraft.FactionMgr.Callbacks;
import jesse.keeblarcraft.FactionMgr.FactionTier.FactionTierEnum;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
import net.minecraft.entity.player.PlayerEntity;
@ -8,9 +9,9 @@ import net.minecraft.world.World;
public interface PlayerExitedBaseCallback {
Event<PlayerExitedBaseCallback> EVENT = EventFactory.createArrayBacked(PlayerExitedBaseCallback.class,
(listeners) -> (player, world) -> {
(listeners) -> (player, world, power, factionTier) -> {
for (PlayerExitedBaseCallback listener : listeners) {
ActionResult result = listener.interact(player, world);
ActionResult result = listener.interact(player, world, power, factionTier);
if (result != ActionResult.PASS) {
return result;
@ -20,5 +21,5 @@ public interface PlayerExitedBaseCallback {
return ActionResult.PASS;
});
ActionResult interact(PlayerEntity player, World world);
ActionResult interact(PlayerEntity player, World world, Integer factionPower, FactionTierEnum factionTier);
}

View File

@ -1,5 +1,6 @@
package jesse.keeblarcraft.FactionMgr.Callbacks;
import jesse.keeblarcraft.FactionMgr.FactionTier.FactionTierEnum;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
import net.minecraft.entity.player.PlayerEntity;
@ -8,9 +9,9 @@ import net.minecraft.world.World;
public interface PlayerInBaseCallback {
Event<PlayerInBaseCallback> EVENT = EventFactory.createArrayBacked(PlayerInBaseCallback.class,
(listeners) -> (player, world) -> {
(listeners) -> (player, world, power, factionTier) -> {
for (PlayerInBaseCallback listener : listeners) {
ActionResult result = listener.interact(player, world);
ActionResult result = listener.interact(player, world, power, factionTier);
if (result != ActionResult.PASS) {
return result;
@ -20,5 +21,5 @@ public interface PlayerInBaseCallback {
return ActionResult.PASS;
});
ActionResult interact(PlayerEntity player, World world);
ActionResult interact(PlayerEntity player, World world, Integer factionPower, FactionTierEnum factionTier);
}

View File

@ -0,0 +1,24 @@
package jesse.keeblarcraft.FactionMgr;
import java.util.Map;
import static java.util.Map.entry;
// This class is going to keep track of everything related to items that the faction block is allowed to accept and
// information regarding those items.
public class FactionBlockItems {
public static enum ITEM_TIER {
COMMON,
UNCOMMON,
RARE,
VERY_RARE,
LEGENDARY
}
// TODO: Need to add the Item information for these down below; but I haven't made them yet! The string should
// make it obvious what needs to go here though.
public static Map<String, ITEM_TIER> FACTION_UPGRADES = Map.ofEntries(
entry("keeblarcraft:faction_flight", ITEM_TIER.UNCOMMON),
entry("keeblarcraft:faction_beacon", ITEM_TIER.RARE)
);
}

View File

@ -8,6 +8,9 @@
package jesse.keeblarcraft.FactionMgr;
import jesse.keeblarcraft.Utils.CommonStructures.Pair;
import jesse.keeblarcraft.Utils.CommonStructures.Position3d;
import static java.util.Map.entry;
import java.util.ArrayList;
@ -28,7 +31,8 @@ public class FactionConfig {
OWNER,
COOWNER,
MANAGEMENT,
EMPLOYEE
EMPLOYEE,
INVALID
}
private static Map<VALID_FACTION_ROLES, Integer> ROLE_LEVELS = Map.ofEntries
@ -48,7 +52,8 @@ public class FactionConfig {
entry (3, VALID_FACTION_ROLES.OWNER)
);
public class WriteableFaction {
// This is the actual faction configuration object that is written to a json file
public static class WriteableFaction {
// Key = Player UUID
// Val = Faction role of player
HashMap<String, VALID_FACTION_ROLES> factionPlayerList = new HashMap<String, VALID_FACTION_ROLES>();
@ -57,8 +62,12 @@ public class FactionConfig {
HashMap<String, VALID_FACTION_ROLES> DISPLAY_ONLY_LIST = new HashMap<String, VALID_FACTION_ROLES>();
// List contains UUID of players who are openly invited to this faction
// TODO: Refactor to map so players can un-invite by name not UUID...
List<String> openInvites = new ArrayList<String>();
Position3d factionBlockLocation; // May be null until faction places it; but only one can be placed!
int numFactionBlocks = 0;
Integer factionBankBalance;
Integer factionPower;
String factionName;
@ -91,6 +100,38 @@ public class FactionConfig {
return success;
}
public void SetFactionBlock(String factionName, Position3d blockPos) {
if (IsValid(factionName) && blockPos != null) {
allFactions.get(factionName).numFactionBlocks++;
allFactions.get(factionName).factionBlockLocation = blockPos;
}
}
public void RemoveFactionBlock(String factionName) {
if (IsValid(factionName)) {
allFactions.get(factionName).factionBlockLocation = null;
allFactions.get(factionName).numFactionBlocks--;
}
}
public Position3d GetFactionBlock(String factionName) {
Position3d blockLoc = null;
if (IsValid(factionName)){
blockLoc = allFactions.get(factionName).factionBlockLocation;
}
return blockLoc;
}
// Will return amount of faction blocks in a faction, where any number less than 0 should be treated
// as an invalid case where the faction may have not existed when this function was called.
public Integer GetNumberOfFactionBlocks(String factionName) {
int amount = -1;
if (IsValid(factionName)) {
amount = allFactions.get(factionName).numFactionBlocks;
}
return amount;
}
// It is assumed that the person calling this function has verified that the person
// can in fact set faction power. This is generally just an admin command
public Boolean SetPower(String factionName, Integer amount) {
@ -112,6 +153,47 @@ public class FactionConfig {
return amount;
}
public Integer GetBankBalance(String factionName) {
Integer amount = 0;
if (IsValid(factionName)) {
amount = allFactions.get(factionName).factionBankBalance;
}
return amount;
}
// You should probably verify the player is in the faction before calling this so the object is not empty
public HashMap<String, VALID_FACTION_ROLES> GetMemberNames(String factionName) {
HashMap<String, VALID_FACTION_ROLES> members = new HashMap<String, VALID_FACTION_ROLES>();
if (IsValid(factionName)) {
members = allFactions.get(factionName).DISPLAY_ONLY_LIST;
}
return members;
}
// Gets faction members in a pair return; KEY = UUID values. PAIR = Ranks of each UUID
// Alternatively you could just call @see GetMemberNames(String) to get member names
// and their ranks.
public HashMap<String, VALID_FACTION_ROLES> GetFactionPlayers(String factionName) {
HashMap<String, VALID_FACTION_ROLES> players = null;
if (IsValid(factionName)) {
players = allFactions.get(factionName).factionPlayerList;
}
return players;
}
public VALID_FACTION_ROLES GetPlayerRole(String factionName, String playerUuid) {
VALID_FACTION_ROLES role = VALID_FACTION_ROLES.INVALID;
// Check to make sure faction exists & player is in faction
if (IsValid(factionName) && allFactions.get(factionName).factionPlayerList.containsKey(playerUuid)) {
role = allFactions.get(factionName).factionPlayerList.get(playerUuid);
}
return role;
}
/////////////////////////////////////////////////////////////////////////////
/// @fn DeleteFaction
///
@ -204,6 +286,7 @@ public class FactionConfig {
if (allFactions.containsKey(factionName)) {
allFactions.get(factionName).factionPlayerList.put(playerUuid, VALID_FACTION_ROLES.EMPLOYEE);
allFactions.get(factionName).DISPLAY_ONLY_LIST.put(playerDisplayName, VALID_FACTION_ROLES.EMPLOYEE);
allFactions.get(factionName).openInvites.remove(playerUuid); // Remove them from the invite list if they joined
}
}
@ -317,11 +400,7 @@ public class FactionConfig {
/// @return True if a faction exists with the specified name, false if not
/////////////////////////////////////////////////////////////////////////////
public Boolean IsValid(String factionName) {
if (allFactions.containsKey(factionName)) {
return true;
} else {
return false;
}
return allFactions.containsKey(factionName);
}
/////////////////////////////////////////////////////////////////////////////
@ -338,10 +417,8 @@ public class FactionConfig {
public String FindFactionOfPlayer(String playerUuid) {
String faction = "";
System.out.println("Attempting to find player factions with uuid " + playerUuid);
for (Entry<String, WriteableFaction> entry : allFactions.entrySet()) {
if (entry.getValue().factionPlayerList.containsKey(playerUuid)) {
System.out.println("FAC [" + entry.getKey() + "]: PLAY-LIST: " + entry.getValue().factionPlayerList);
faction = entry.getKey();
break;
}

View File

@ -9,13 +9,20 @@
package jesse.keeblarcraft.FactionMgr;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map.Entry;
import jesse.keeblarcraft.ConfigMgr.ConfigManager;
import jesse.keeblarcraft.FactionMgr.FactionConfig.VALID_FACTION_ROLES;
import jesse.keeblarcraft.FactionMgr.FactionTier.FactionTierEnum;
import jesse.keeblarcraft.MailSystem.MailMgr;
import jesse.keeblarcraft.Keeblarcraft;
import jesse.keeblarcraft.ChatStuff.ChatMenu;
import jesse.keeblarcraft.ChatStuff.ChatMsg;
import jesse.keeblarcraft.Utils.CustomExceptions.FILE_WRITE_EXCEPTION;
import jesse.keeblarcraft.ChatStuff.ChatFormatting.COLOR_CODE;
import jesse.keeblarcraft.Utils.CommonStructures.Position3d;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.Text;
@ -75,6 +82,81 @@ public class FactionManager {
factionConfig.factions = new FactionConfig();
FlashConfig();
}
FactionTier.InitializeFactionTiers();
}
// Returns true if the faction is allowed to place a faction block. False if not
public Boolean CanPlaceFactionBlock(String factionName) {
return factionConfig.factions.GetNumberOfFactionBlocks(factionName) == 0;
}
public void SetFactionBlock(String factionName, Position3d newPos) {
// Only consider the faction block now "placed" if we (the manager) agree there are no others
if (factionConfig.factions.GetNumberOfFactionBlocks(factionName) == 0) {
factionConfig.factions.SetFactionBlock(factionName, newPos);
}
FlashConfig();
}
public void RemoveFactionBlock(String factionName, Position3d blockPos) {
// In order to "remove" a block (NOT from the world, just the manager) - it must be the LAST remaining faction
// block. In general, it should NOT be possible (for now) to set more than one faction block in the world from
// the manager's perspective.
Position3d origBlock = factionConfig.factions.GetFactionBlock(factionName);
if (origBlock != null && origBlock.equals(blockPos)) {
factionConfig.factions.RemoveFactionBlock(factionName);
}
FlashConfig();
}
public int GetNumberOfFactionBlocks(String factionName) {
return factionConfig.factions.GetNumberOfFactionBlocks(factionName);
}
public VALID_FACTION_ROLES GetPlayerRole(String factionName, String uuid) {
return factionConfig.factions.GetPlayerRole(factionName, uuid);
}
// This is purely a chat-based call. Here to help with `/faction info` basically.
public void GetFactionInformation(ServerPlayerEntity player) {
String factionName = GetFactionOfPlayer(player.getUuidAsString());
if (!factionName.equals("")) {
Integer fPower = factionConfig.factions.GetPower(factionName);
HashMap<String, VALID_FACTION_ROLES> displayNames = factionConfig.factions.GetMemberNames(factionName);
Integer fBankBalance = factionConfig.factions.GetBankBalance(factionName);
System.out.println((fPower == null ? "YES":"NO") + " " + (displayNames == null ? "YES":"NO") + " " + (fBankBalance == null ? "YES":"NO"));
ArrayList<ChatMsg> chatPlayerList = new ArrayList<>();
for (Entry<String, VALID_FACTION_ROLES> entry : displayNames.entrySet()) {
ChatMsg temp = new ChatMsg();
temp.ColorMsg(entry.getKey() + " - " + entry.getValue().name(), COLOR_CODE.BLUE);
chatPlayerList.add(temp);
}
// Let's make our chat objects first so things are copyable and whatnot
ChatMsg chatHeader = new ChatMsg();
chatHeader.ColorMsg(Text.of("----[" + factionName + "]----"), COLOR_CODE.GOLD);
ChatMsg chatBalance = new ChatMsg();
chatBalance.ColorMsg(Text.of("Balance: " + Integer.toString(fBankBalance)), COLOR_CODE.GREEN);
ChatMsg chatPower = new ChatMsg();
chatPower.ColorMsg(Text.of("Power: " + Integer.toString(fPower)), COLOR_CODE.RED);
ChatMenu chatBlock = new ChatMenu();
chatBlock.SetHeader(chatHeader);
chatBlock.AddMsg(chatBalance);
chatBlock.AddMsg(chatPower);
chatBlock.SendMsg(player);
} else {
player.sendMessage(Text.of("You aren't in a faction!"));
}
}
/////////////////////////////////////////////////////////////////////////////
@ -118,10 +200,10 @@ public class FactionManager {
String facOfPlayer = factionConfig.factions.FindFactionOfPlayer(creator.getUuidAsString());
if (facOfPlayer == "") {
creator.sendMessage(Text.of("Your display name: " + creator.getDisplayName().toString()));
creator.sendMessage(Text.of("Your name: " + creator.getName()));
creator.sendMessage(Text.of("Your custom name: " + creator.getCustomName()));
creator.sendMessage(Text.of("Your entity name: " + creator.getEntityName()));
// creator.sendMessage(Text.of("Your display name: " + creator.getDisplayName().toString()));
// creator.sendMessage(Text.of("Your name: " + creator.getName()));
// creator.sendMessage(Text.of("Your custom name: " + creator.getCustomName()));
// creator.sendMessage(Text.of("Your entity name: " + creator.getEntityName()));
success = factionConfig.factions.CreateFaction(factionName, creator.getUuidAsString(), creator.getEntityName());
if (!success) {
@ -161,6 +243,18 @@ public class FactionManager {
return success;
}
public Boolean JoinFaction(ServerPlayerEntity player, String factionName) {
Boolean joinedFaction = factionConfig.factions.JoinFaction(factionName, player.getUuidAsString(), player.getEntityName());
if (joinedFaction) {
player.sendMessage(Text.of("Successfully joined the faction " + factionName));
} else {
player.sendMessage(Text.of("Failed to join faction - you were not on the invite list!"));
}
return joinedFaction;
}
/////////////////////////////////////////////////////////////////////////////
/// @fn ListOfFactions
///
@ -196,8 +290,9 @@ public class FactionManager {
}
if (success) {
String mailMsg = "You receive a faction invite from " + caller.getEntityName() + "! You can join with /faction join " + playerFaction;
String mailMsg = "You received a faction invite from " + caller.getEntityName() + "! You can join with /faction join " + playerFaction;
MailMgr.GetInstance().SendMail(inviteeUuid, mailMsg);
FlashConfig();
}
return success;
}
@ -206,7 +301,8 @@ public class FactionManager {
Boolean success = false;
if (caller.hasPermissionLevel(4)) {
factionConfig.factions.SetPower(factionName, amount);
success = factionConfig.factions.SetPower(factionName, amount);
FlashConfig();
} else {
caller.sendMessage(Text.of("You do not have permission to use this command"));
}
@ -214,6 +310,22 @@ public class FactionManager {
return success;
}
public HashMap<String, VALID_FACTION_ROLES> GetFactionPlayers(String factionName) {
return factionConfig.factions.GetFactionPlayers(factionName);
}
public Integer GetFactionPower(String factionName) {
int fPower = 0;
if (factionConfig.factions.IsValid(factionName)) {
fPower = factionConfig.factions.GetPower(factionName);
}
return fPower;
}
public FactionTierEnum GetFactionTier(String factionName) {
return FactionTier.GetFactionTier(factionConfig.factions.GetPower(factionName));
}
public Integer GetFactionPower(ServerPlayerEntity caller) {
Integer amount = 0;

View File

@ -0,0 +1,65 @@
package jesse.keeblarcraft.FactionMgr;
import com.google.common.collect.Range;
import com.google.common.collect.RangeMap;
import com.google.common.collect.TreeRangeMap;
public class FactionTier {
public static enum FactionTierEnum {
TIER_INVALID,
TIER_I,
TIER_II,
TIER_III,
TIER_IV,
TIER_V,
TIER_VI
}
private static RangeMap<Integer, FactionTierEnum> factionTiers = TreeRangeMap.create();
public static void InitializeFactionTiers() {
factionTiers.put(Range.closed(0, 29), FactionTierEnum.TIER_I);
factionTiers.put(Range.closed(30, 74), FactionTierEnum.TIER_II);
factionTiers.put(Range.closed(75, 99), FactionTierEnum.TIER_III);
factionTiers.put(Range.closed(100, 149), FactionTierEnum.TIER_IV);
factionTiers.put(Range.closed(150, 999), FactionTierEnum.TIER_V);
factionTiers.put(Range.closed(1000, Integer.MAX_VALUE), FactionTierEnum.TIER_VI);
}
// Tier 1 can never be greater than anything (and not itself, obviously)
public static Boolean IsGreaterThan(FactionTierEnum tierInQuestion, FactionTierEnum tierToCompareAgainst) {
Boolean isGreater = false;
if (tierInQuestion == FactionTierEnum.TIER_II && tierToCompareAgainst == FactionTierEnum.TIER_I) {
isGreater = true;
} else if (tierInQuestion == FactionTierEnum.TIER_III && (tierToCompareAgainst == FactionTierEnum.TIER_II || tierToCompareAgainst == FactionTierEnum.TIER_I)) {
isGreater = true;
} else if (tierInQuestion == FactionTierEnum.TIER_IV && (tierToCompareAgainst == FactionTierEnum.TIER_III || tierToCompareAgainst == FactionTierEnum.TIER_II || tierToCompareAgainst == FactionTierEnum.TIER_I)) {
isGreater = true;
} else if (tierInQuestion == FactionTierEnum.TIER_V && (tierToCompareAgainst == FactionTierEnum.TIER_IV || tierToCompareAgainst == FactionTierEnum.TIER_III || tierToCompareAgainst == FactionTierEnum.TIER_II || tierToCompareAgainst == FactionTierEnum.TIER_I)) {
isGreater = true;
} else if (tierInQuestion == FactionTierEnum.TIER_VI && (tierToCompareAgainst == FactionTierEnum.TIER_V || tierToCompareAgainst == FactionTierEnum.TIER_IV || tierToCompareAgainst == FactionTierEnum.TIER_III || tierToCompareAgainst == FactionTierEnum.TIER_II || tierToCompareAgainst == FactionTierEnum.TIER_I)) {
isGreater = true;
}
return isGreater;
}
public static Boolean IsEqualTo(FactionTierEnum tierInQuestion, FactionTierEnum tierToCompareAgainst) {
return tierInQuestion == tierToCompareAgainst;
}
public static Boolean IsGreaterOrEqualTo(FactionTierEnum tierInQuestion, FactionTierEnum tierToCompareAgainst) {
return IsEqualTo(tierInQuestion, tierToCompareAgainst) || IsGreaterThan(tierInQuestion, tierToCompareAgainst);
}
// Make sure you initialize tiers by calling the above function first!
public static FactionTierEnum GetFactionTier(Integer value) {
FactionTierEnum tier = factionTiers.get(value);
if (tier == null) {
tier = FactionTierEnum.TIER_INVALID;
}
return tier;
}
}

View File

@ -0,0 +1,10 @@
package jesse.keeblarcraft.GuiMgr.Entities;
import net.minecraft.client.render.entity.EntityRendererFactory;
import net.minecraft.client.render.entity.VillagerEntityRenderer;
public class ShopKeeperRenderer extends VillagerEntityRenderer {
public ShopKeeperRenderer(EntityRendererFactory.Context context) {
super(context);
}
}

View File

@ -11,6 +11,7 @@ import net.minecraft.screen.ArrayPropertyDelegate;
import net.minecraft.screen.PropertyDelegate;
import net.minecraft.screen.ScreenHandler;
import net.minecraft.screen.slot.Slot;
import org.jetbrains.annotations.Nullable;
public class FactionBlockScreenHandler extends ScreenHandler {
private final Inventory inventory;
@ -31,22 +32,19 @@ public class FactionBlockScreenHandler extends ScreenHandler {
this.blockEntity = (FactionBlockEntity) blockEntity;
// Need a better way of storing these coordinates...
this.addSlot(new Slot(inventory, 0, 20, 11)); // top row
this.addSlot(new Slot(inventory, 1, 20, 39));
this.addSlot(new Slot(inventory, 2, 49, 11));
this.addSlot(new Slot(inventory, 3, 49, 39));
this.addSlot(new Slot(inventory, 4, 78, 11));
this.addSlot(new Slot(inventory, 5, 78, 39));
this.addSlot(new Slot(inventory, 0, -1, 2)); // top row
this.addSlot(new Slot(inventory, 2, 35, 2));
this.addSlot(new Slot(inventory, 4, 71, 2));
this.addSlot(new Slot(inventory, 6, 128, 26));
this.addSlot(new Slot(inventory, 1, 17, 36));
this.addSlot(new Slot(inventory, 3, 54, 36));
this.addSlot(new Slot(inventory, 5, 90, 36));
this.addSlot(new Slot(inventory, 6, 148, 20));
addPlayerInventory(playerInventory);
addPlayerHotbar(playerInventory);
// Need to reference Kaupendim tutorial again; but we could theoretically just add the player inventory
// right here so that they can drag items in and whatnot (I assume). I am unsure if I am taking that
// direction with this block RIGHT NOW - so for now I am NOT doing that
// Remainder stuff
addProperties(arrayPropertyDelegate);
}
@ -59,9 +57,10 @@ public class FactionBlockScreenHandler extends ScreenHandler {
// This is just for SHIFT+CLICK moving
@Override
public ItemStack quickMove(PlayerEntity player, int invSlot) {
System.out.println("Is client: " + player.getWorld().isClient());
ItemStack newStack = ItemStack.EMPTY;
Slot slot = this.slots.get(invSlot);
if (slot != null && slot.hasStack()) {
if (slot.hasStack()) {
ItemStack originalStack = slot.getStack();
newStack = originalStack.copy();
@ -82,12 +81,12 @@ public class FactionBlockScreenHandler extends ScreenHandler {
// From Kaupenjoe video
private void addPlayerInventory(PlayerInventory playerInventory) {
int spacing = -8;
for (int i = 0; i < 3; ++i) { // Rows
for (int l = 0; l < 9; ++l) { // Columns
// The fancy math (expanded from kaupen video for clarity for me for later) seems to just specify a few things
int index = l + i * 9 + 9; // l = col, i*9 = the row to be on (scaling by 9 bc slots are 1-(9*3) in amount), +9 = where on that row to be!
int x = 8 + l * 18; // Texture draw position on image
int y = 84 + i * 18; // Texture draw position on image
int x = l * 22 + spacing; // Texture draw position on image
int y = 89 + i * 22; // Texture draw position on image
this.addSlot(new Slot(playerInventory, index, x, y));
}
}
@ -95,10 +94,12 @@ public class FactionBlockScreenHandler extends ScreenHandler {
// From Kaupenjoe video
private void addPlayerHotbar(PlayerInventory playerInventory) {
int spacing = -8;
for (int i = 0; i < 9; ++i) {
int index = i; // Index of hotbar (only 9 slots long in vanilla)
int x = 8 + i * 18; // Texture draw position
int y = 142; // Texture draw position
// int x = (8 + i * 18) + spacing; // Texture draw position
int x = i * 22 + spacing; // Texture draw position
int y = 162; // Texture draw position
this.addSlot(new Slot(playerInventory, index, x, y));
}
}

View File

@ -7,8 +7,6 @@
*
*/
// color colour
package jesse.keeblarcraft;
import net.fabricmc.api.ModInitializer;
@ -18,7 +16,6 @@ import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
import net.kyrptonaught.customportalapi.api.CustomPortalBuilder;
import net.minecraft.block.Blocks;
import net.minecraft.entity.mob.HostileEntity;
import net.minecraft.item.Items;
import net.minecraft.registry.Registries;
import net.minecraft.registry.Registry;

View File

@ -7,6 +7,19 @@ public class Position3d {
this.z = z;
}
@Override
public boolean equals(Object obj) {
boolean isEqual = false;
if (this == obj) {
isEqual = true;
} else if (obj instanceof Position3d castedObj) {
if (castedObj.x == this.x && castedObj.y == this.y && castedObj.z == this.z) {
isEqual = true;
}
}
return isEqual;
}
public int x;
public int y;
public int z;

View File

@ -29,7 +29,6 @@ import jesse.keeblarcraft.Utils.CustomExceptions.SETUP_FAILED_EXCEPTION;
// If we do not have these, or only partial - then functionality may be disabled for runtime performance
public final class Setup {
private static Setup static_inst;
private static String GLOBAL_CONFIG = "config/keeblarcraft/";
public Setup() {}

View File

@ -0,0 +1,33 @@
package jesse.keeblarcraft.mixin;
import net.minecraft.entity.mob.MobEntity;
// import javax.annotation.Nullable;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import com.llamalad7.mixinextras.injector.ModifyReceiver;
import jesse.keeblarcraft.Callbacks.MobSpawnCallback;
import net.minecraft.entity.EntityData;
import net.minecraft.entity.SpawnReason;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.util.ActionResult;
import net.minecraft.world.LocalDifficulty;
import net.minecraft.world.ServerWorldAccess;
import net.minecraft.world.SpawnHelper;
@Mixin(SpawnHelper.class)
public class EntitySpawnMixin {
@ModifyReceiver(
method = "spawnEntitiesInChunk(Lnet/minecraft/entity/SpawnGroup;Lnet/minecraft/server/world/ServerWorld;Lnet/minecraft/world/chunk/Chunk;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/world/SpawnHelper$Checker;Lnet/minecraft/world/SpawnHelper$Runner;)V",
at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/mob/MobEntity;initialize(Lnet/minecraft/world/ServerWorldAccess;Lnet/minecraft/world/LocalDifficulty;Lnet/minecraft/entity/SpawnReason;Lnet/minecraft/entity/EntityData;Lnet/minecraft/nbt/NbtCompound;)Lnet/minecraft/entity/EntityData;")
)
private static MobEntity mobEntity(MobEntity instance, ServerWorldAccess world, LocalDifficulty difficulty, SpawnReason spawnReason, EntityData entityData, NbtCompound entityNbt) {
// Do stuff
ActionResult action = MobSpawnCallback.EVENT.invoker().interact(instance.getWorld(), instance);
return instance;
}
}

View File

@ -3,6 +3,8 @@
"item.keeblarcraft.metaljacket_chestplate": "MetalJacket Chestplate",
"item.keeblarcraft.metaljacket_leggings": "MetalJacket Leggings",
"item.keeblarcraft.metaljacket_boots": "MetalJacket Booties",
"item.keeblarcraft.faction_upgrade_flight": "Faction Flight Upgrade",
"item.keeblarcraft.faction_upgrade_beacon": "Faction Beacon Upgrade",
"itemgroup.keeblarcraft": "Keeblarcraft Modded Items",

View File

@ -0,0 +1,6 @@
{
"parent": "item/generated",
"textures": {
"layer0": "keeblarcraft:item/faction_upgrade_beacon"
}
}

View File

@ -0,0 +1,6 @@
{
"parent": "item/generated",
"textures": {
"layer0": "keeblarcraft:item/faction_upgrade_flight"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 669 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 610 KiB

View File

@ -1,6 +1,7 @@
{
"replace": false,
"values": [
"keeblarcraft:example_block_ore"
"keeblarcraft:example_block_ore",
"keeblarcraft:faction_base_block"
]
}

View File

@ -0,0 +1,20 @@
{
"type": "minecraft:block",
"pools": [
{
"bonus_rolls": 0.0,
"conditions": [
{
"condition": "minecraft:survives_explosion"
}
],
"entries": [
{
"type": "minecraft:item",
"name": "keeblarcraft:faction_base_block"
}
],
"rolls": 1.0
}
]
}

View File

@ -0,0 +1,27 @@
{
"type": "minecraft:crafting_shaped",
"category": "misc",
"pattern": [
"#E#",
"#T#",
"#G#"
],
"key": {
"#": {
"item": "minecraft:netherite_block"
},
"T": {
"item": "minecraft:totem_of_undying"
},
"E": {
"item": "minecraft:elytra"
},
"G": {
"item": "minecraft:golden_apple"
}
},
"result": {
"item": "keeblarcraft:faction_base_block",
"count": 1
}
}

View File

@ -2,6 +2,7 @@
"replace": false,
"values": [
"keeblarcraft:example_block",
"keeblarcraft:example_block_ore"
"keeblarcraft:example_block_ore",
"keeblarcraft:faction_base_block"
]
}

View File

@ -1,6 +1,7 @@
{
"replace": false,
"values": [
"keeblarcraft:example_block"
"keeblarcraft:example_block",
"keeblarcraft:faction_base_block"
]
}

View File

@ -7,7 +7,8 @@
"PlayerMixin",
"ServerPlayNetworkHandlerMixin",
"PlayerEntityInteractionHandler",
"ServerPlayerInteractionManagerMixin"
"ServerPlayerInteractionManagerMixin",
"EntitySpawnMixin"
],
"client": [
"ClientPlayerInteractionManagerMixin"