[factions-banking] Initial somewhat-functional system for the faction block radius detection
Some checks are pending
build / build (21) (push) Waiting to run

This commit is contained in:
Jkibbels 2025-01-18 03:10:58 -05:00
parent f22da92cab
commit bcbd481fcf
13 changed files with 215 additions and 106 deletions

View File

@ -13,10 +13,9 @@ import java.util.HashMap;
import jesse.keeblarcraft.Keeblarcraft;
import jesse.keeblarcraft.AttributeMgr.AttributeNodes.AbstractNode;
import jesse.keeblarcraft.AttributeMgr.AttributeNodes.AttributeFlight;
import jesse.keeblarcraft.AttributeMgr.AttributeNodes.AttributeMetalJacket;
import jesse.keeblarcraft.AttributeMgr.AttributeNodes.FactionNodes.FactionFlight;
import jesse.keeblarcraft.ConfigMgr.ConfigManager;
import jesse.keeblarcraft.ChatStuff.ChatMsg;
public class AttributeMgr {
ConfigManager config;
@ -78,7 +77,8 @@ public class AttributeMgr {
Keeblarcraft.LOGGER.error("Could not successfully apply attribute. String of attribute name could not be successfully cast to actual java object");
}
if (playerTree != null && node != null) {
// Ensure player tree isn't null; node isn't null; and the player doesn't already have this attribute
if (playerTree != null && node != null && !playerTree.ContainsAttribute(attributeName)) {
///////////
// debug testing
String isNull = (node == null ? "NULL" : "NOT NULL");
@ -91,13 +91,26 @@ public class AttributeMgr {
msg = "Applied attribute '" + attributeName + "' successfully";
} else {
msg = "Player tree not found!";
String debug = "PlayerTree is null";
if (playerTree != null) {
debug = playerTree.ContainsAttribute(attributeName) ? "YES":"NO";
}
System.out.println("APPLY ATTRIBUTE FAIL: TREE NULL, NODE NULL, OR PLAYER ALREADY HAS THIS ATTRIBUTE (DO THEY? " + debug + ")");
}
} else {
msg = "Could not apply attribute, attribute name does not exist!";
System.out.println("Attribute does not exist!");
}
return msg;
}
// Deletes an attribute from the node tree
public static void DisableAttribute(String uuid, String attributeName) {
if (activeTrees.containsKey(uuid) && activeTrees.get(uuid).ContainsAttribute(attributeName)) {
activeTrees.get(uuid).DeleteNode(attributeName);
}
}
/////////////////////////////////////////////////////////////////////////////
/// @fn RegisterAttributes
///
@ -111,7 +124,7 @@ public class AttributeMgr {
/// TODO: Find a better way to do this more dynamically in the future
/// hint: make it an API for other modders to add to
RegisterAttributeClass(AttributeFlight.class);
RegisterAttributeClass(AttributeMetalJacket.class);
RegisterAttributeClass(FactionFlight.class);
}
}

View File

@ -12,6 +12,9 @@ package jesse.keeblarcraft.AttributeMgr.AttributeNodes;
import java.util.HashMap;
import java.util.List;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.world.ServerWorld;
abstract public class AbstractNode {
/////////////////////////////////////////////////////////////////////////////
/// @fn GetNodeTitle
@ -47,5 +50,5 @@ abstract public class AbstractNode {
/// @brief If your node has responsive callbacks; then this is the area
/// you will register your callbacks for everything
/////////////////////////////////////////////////////////////////////////////
public abstract void RegisterCallbacks();
public abstract void RegisterCallbacks(ServerPlayerEntity player, ServerWorld world);
}

View File

@ -1,68 +0,0 @@
/*
*
* AttributeFlight
*
* The flight attribute
*
*
*/
package jesse.keeblarcraft.AttributeMgr.AttributeNodes;
import java.util.HashMap;
import java.util.List;
import net.fabricmc.fabric.api.event.player.AttackBlockCallback;
import net.minecraft.block.BlockState;
import net.minecraft.util.ActionResult;
public class AttributeFlight extends AbstractNode {
Boolean registeredHitCallback = false;
public AttributeFlight() {
}
@Override
public String GetNodeTitle() {
return "attribute_low_health_flight";
}
@Override
public String GetNodeDescription() {
return "Gives player flight with low health";
}
@Override
public HashMap<String, List<String>> GetDetails() {
HashMap<String, List<String>> ret = new HashMap<String, List<String>>();
// Filling out description item stuff here
ret.put("Flight", List.of (
"Gives a player natural flight if they have less than or equal to two hearts remaining"
));
return ret;
}
@Override
public void RegisterCallbacks() {
// Register events here
if (registeredHitCallback == false) {
AttackBlockCallback.EVENT.register((player, world, hand, pos, direction) -> {
BlockState state = world.getBlockState(pos);
// Manual spectator check is necessary because AttackBlockCallbacks fire before the spectator check
if (!player.isSpectator() && player.getMainHandStack().isEmpty() && state.isToolRequired()) {
player.damage(world.getDamageSources().generic(), 1.0F);
}
return ActionResult.PASS;
});
}
registeredHitCallback = true;
}
}

View File

@ -8,6 +8,8 @@ import jesse.keeblarcraft.Armor.MetalJacketArmor;
import jesse.keeblarcraft.CustomItems.ItemManager;
import net.minecraft.item.ArmorItem;
import net.minecraft.item.Item;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.world.ServerWorld;
public final class AttributeMetalJacket extends AbstractNode {
// This is the custom armor set that players will receive if no armor is on & attribute is equipped
@ -51,6 +53,6 @@ public final class AttributeMetalJacket extends AbstractNode {
}
@Override
public void RegisterCallbacks() {
public void RegisterCallbacks(ServerPlayerEntity player, ServerWorld world) {
}
}

View File

@ -0,0 +1,43 @@
package jesse.keeblarcraft.AttributeMgr.AttributeNodes.FactionNodes;
import java.util.HashMap;
import java.util.List;
import jesse.keeblarcraft.AttributeMgr.AttributeNodes.AbstractNode;
import jesse.keeblarcraft.FactionMgr.Callbacks.PlayerInBaseCallback;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.text.Text;
import net.minecraft.util.ActionResult;
public class FactionFlight extends AbstractNode {
private final int flightSpeed = 1;
private ServerPlayerEntity player;
@Override
public String GetNodeTitle() {
return "faction_flight";
}
@Override
public String GetNodeDescription() {
return "This is a temporary-unlock value when you are around your factions home base block and it has flight unlocked for members!";
}
@Override
public HashMap<String, List<String>> GetDetails() {
HashMap<String, List<String>> ret = new HashMap<String, List<String>>();
ret.put("Faction Flight", List.of("Grants flight when near faction base if faction has it unlocked"));
return ret;
}
@Override
public void RegisterCallbacks(ServerPlayerEntity playerObj, ServerWorld worldObj) {
PlayerInBaseCallback.EVENT.register((player, world) -> {
player.sendMessage(Text.of("Welcome home! Feel free to fly around!"));
return ActionResult.SUCCESS;
});
}
}

View File

@ -17,13 +17,16 @@ import java.util.HashMap;
import jesse.keeblarcraft.Keeblarcraft;
import jesse.keeblarcraft.AttributeMgr.AttributeNodes.AbstractNode;
import jesse.keeblarcraft.ConfigMgr.ConfigManager;
import jesse.keeblarcraft.ChatStuff.ChatMsg;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.world.ServerWorld;
public class AttributeTree {
PlayerTree playerAttributeTree = new PlayerTree();
ConfigManager config = new ConfigManager();
private AbstractNode root = new RootNode();
private ServerPlayerEntity player;
/////////////////////////////////////////////////////////////////////////////
/// @class TreeNode
@ -92,7 +95,7 @@ public class AttributeTree {
}
@Override
public void RegisterCallbacks() {
public void RegisterCallbacks(ServerPlayerEntity player, ServerWorld world) {
}
}
@ -110,7 +113,7 @@ public class AttributeTree {
// the callback registration process has already happened
if (tree.getValue().thisNode == null) {
System.out.println("REGISTERACTIVECALLBACKS - NULL NODE");
tree.getValue().thisNode.RegisterCallbacks();
tree.getValue().thisNode.RegisterCallbacks(player, player.getServerWorld());
} else {
System.out.println("REGISTERACTIVECALLBACKS - NOT NULL NODE");
}
@ -172,7 +175,7 @@ public class AttributeTree {
// if the new nodes level is not 0 we need to manually register the callbacks
if (playerAttributeTree.tree.get(newNode.GetNodeTitle()).currentNodeLevel != 0) {
System.out.println("Registering new callback for new node");
playerAttributeTree.tree.get(newNode.GetNodeTitle()).thisNode.RegisterCallbacks();
playerAttributeTree.tree.get(newNode.GetNodeTitle()).thisNode.RegisterCallbacks(player, player.getServerWorld());
}
} else {
// Some fancy error handling for console log
@ -210,6 +213,18 @@ public class AttributeTree {
FlashConfig();
}
/////////////////////////////////////////////////////////////////////////////
/// @fn public Boolean ContainsAttribute(String nodeName) {
///
/// @arg[in] nodeName is the attribute node title
///
/// @brief Returns true if this player presently has the 'nodeName'
/// attribute unlocked
/////////////////////////////////////////////////////////////////////////////
public Boolean ContainsAttribute(String nodeName) {
return playerAttributeTree.tree.containsKey(nodeName);
}
/////////////////////////////////////////////////////////////////////////////
/// @fn DeleteNode
///
@ -263,16 +278,16 @@ public class AttributeTree {
///
/// @brief Constructor for class
/////////////////////////////////////////////////////////////////////////////
public AttributeTree(String uuid) {
// DEVELOPER NOTE:
// If you are testing this part of the code, please be reminded that anonymous testing starts a new
// player instance everytime you launch. This means the UUID CAN CHANGE when you launch the
// game! This is not an issue with proper registered accounts in production
public AttributeTree(ServerPlayerEntity p) {
this.player = p;
String uuid = player.getUuidAsString();
Boolean existingFile = false;
try {
playerAttributeTree = config.GetJsonObjectFromFile("attributes/" + uuid + ".json", PlayerTree.class);
existingFile = true;
existingFile = playerAttributeTree != null;
} catch (Exception e) {
System.out.println("Attribute tree file does not exist for this player");
// Do nothing. This means the file does not exist
}
@ -281,6 +296,7 @@ public class AttributeTree {
{
System.out.println("Trying to create new file");
try {
playerAttributeTree = new PlayerTree();
playerAttributeTree.uuid = uuid;
FlashConfig();
} catch (Exception e) {

View File

@ -292,6 +292,7 @@ public class ConfigManager {
ret = FileUtils.readFileToString(file, "UTF-8");
} catch (Exception e) {
System.out.println("Caught an exception in retrieving JSON Object from file " + fileName);
// throw new JsonSyntaxException("");
}
return gson.fromJson(ret, classToConvertTo);

View File

@ -9,15 +9,43 @@ public class SQLInitServer {
SetupTables();
}
@SuppressWarnings("unchecked")
private void SetupTables() {
// These are all hard coded and non-changeable in this version of the mod
// TABLE NAMES
String accountsTable = "ACCOUNTS";
String banksTable = "BANKS";
String customerTable = "CUSTOMER";
String transactionTable = "TRANSACTION";
Pair<String, VALID_SQL_TYPE> pairOne = new Pair<>("name", VALID_SQL_TYPE.VARCHAR);
Pair<String, VALID_SQL_TYPE> pairTwo = new Pair<>("address", VALID_SQL_TYPE.BIGINT);
Pair<String, VALID_SQL_TYPE> pairThree = new Pair<>("email", VALID_SQL_TYPE.TEXT);
// Create the ACCOUNTS table
Pair<String, VALID_SQL_TYPE> accountsGlobalId = new Pair<>("global_account_id", VALID_SQL_TYPE.VARCHAR);
Pair<String, VALID_SQL_TYPE> userUuid = new Pair<>("address", VALID_SQL_TYPE.VARCHAR);
Pair<String, VALID_SQL_TYPE> accountType = new Pair<>("account_type", VALID_SQL_TYPE.VARCHAR);
Pair<String, VALID_SQL_TYPE> balance = new Pair<>("balance", VALID_SQL_TYPE.BIGINT);
Pair<String, VALID_SQL_TYPE> openDate = new Pair<>("open_date", VALID_SQL_TYPE.VARCHAR);
SQLConfig.GetInstance().CreateTable(accountsTable, accountsGlobalId, userUuid, accountType, balance, openDate);
// Create the CUSTOMER table
Pair<String, VALID_SQL_TYPE> playerUuid = new Pair<>("player_uuid", VALID_SQL_TYPE.VARCHAR);
Pair<String, VALID_SQL_TYPE> playerName = new Pair<>("player_entity_name", VALID_SQL_TYPE.VARCHAR);
SQLConfig.GetInstance().CreateTable(customerTable, playerUuid, playerName);
// Create the BANKS table
Pair<String, VALID_SQL_TYPE> bankRouting = new Pair<>("routing", VALID_SQL_TYPE.BIGINT);
Pair<String, VALID_SQL_TYPE> bankName = new Pair<>("bank_name", VALID_SQL_TYPE.VARCHAR);
Pair<String, VALID_SQL_TYPE> bankSymbol = new Pair<>("bank_symbol", VALID_SQL_TYPE.VARCHAR);
Pair<String, VALID_SQL_TYPE> bankDateOpened = new Pair<>("date_opened", VALID_SQL_TYPE.VARCHAR);
SQLConfig.GetInstance().CreateTable(banksTable, bankRouting, bankName, bankSymbol, bankDateOpened);
// Create the TRANSACTION table
Pair<String, VALID_SQL_TYPE> transactionId = new Pair<>("transaction_id", VALID_SQL_TYPE.VARCHAR);
Pair<String, VALID_SQL_TYPE> transactionDate = new Pair<>("transaction_date", VALID_SQL_TYPE.VARCHAR);
Pair<String, VALID_SQL_TYPE> transactionType = new Pair<>("transaction_type", VALID_SQL_TYPE.VARCHAR);
Pair<String, VALID_SQL_TYPE> transactionAmount = new Pair<>("amount", VALID_SQL_TYPE.BIGINT);
Pair<String, VALID_SQL_TYPE> transactionFromAccount = new Pair<>("account_id", VALID_SQL_TYPE.VARCHAR);
Pair<String, VALID_SQL_TYPE> transactionDescription = new Pair<>("description", VALID_SQL_TYPE.TEXT);
Pair<String, VALID_SQL_TYPE> transactionDestination = new Pair<>("destination", VALID_SQL_TYPE.VARCHAR);
SQLConfig.GetInstance().CreateTable(transactionTable, transactionId, transactionDate, transactionType, transactionAmount,
transactionFromAccount, transactionDescription, transactionDestination);
}
}

View File

@ -5,11 +5,11 @@ import jesse.keeblarcraft.Utils.CommonStructures.Pair;
// Random commands to run to test the SQL class
public class SQLUnitTest {
public void RunTests() {
CreateTableTest();
ForeignKeyTest();
}
public void CreateTableTest() {
String tableName = "test_table";
Pair<String, VALID_SQL_TYPE> pairOne = new Pair<>("name", VALID_SQL_TYPE.VARCHAR);

View File

@ -1,5 +1,8 @@
package jesse.keeblarcraft.CustomBlocks.BlockEntities;
import jesse.keeblarcraft.AttributeMgr.AttributeMgr;
import jesse.keeblarcraft.AttributeMgr.AttributeTree;
import jesse.keeblarcraft.FactionMgr.Callbacks.PlayerInBaseCallback;
import jesse.keeblarcraft.GuiMgr.FactionBlockScreenHandler;
import jesse.keeblarcraft.world.ImplementedInventory;
import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory;
@ -15,6 +18,7 @@ import net.minecraft.screen.PropertyDelegate;
import net.minecraft.screen.ScreenHandler;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.Text;
import net.minecraft.util.ActionResult;
import net.minecraft.util.collection.DefaultedList;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
@ -27,6 +31,8 @@ public class FactionBlockEntity extends BlockEntity implements ExtendedScreenHan
private static final int OFFENSE_SLOT_ONE = 2;
private static final int OFFENSE_SLOT_TWO = 3;
private static int factionPower = 0;
Boolean stopMobSpawn = true;
Boolean hasBuildFlight = true;
protected final PropertyDelegate propertyDelegate;
@ -94,6 +100,21 @@ public class FactionBlockEntity extends BlockEntity implements ExtendedScreenHan
buf.writeBlockPos(this.pos);
}
private Boolean IsPlayerInBounds(PlayerEntity player, BlockPos pos) {
Boolean isNearBlock = false;
// 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) {
System.out.println("PLAYER IN BOUNDS");
isNearBlock = true;
}
return isNearBlock;
}
// 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.
@ -104,5 +125,31 @@ public class FactionBlockEntity extends BlockEntity implements ExtendedScreenHan
// Do stuff here that we need to do on a per tick basis. Probably check the items inside the slots and do stuff?
// Maybe something with callback handlers might be done here? Like the temp flight within bounds of the faction block if that powerup is
// active, etc?
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) {
int worldX = pos.east().getX();
int worldY = pos.getY();
int worldZ = pos.east().getZ();
System.out.println("FACTION BLOCK DEBUG INFO: " + worldX + " " + worldY + " " + worldZ);
for (PlayerEntity player : world.getPlayers()) {
if (IsPlayerInBounds(player, pos)) {
// Notify the attribute tree to enable this attribute!
AttributeMgr.ApplyAttribute(player.getUuidAsString(), "factions_flight");
ActionResult result = PlayerInBaseCallback.EVENT.invoker().interact(player, world);
}
}
world.getBlockEntity(pos.east());
}
}
}

View File

@ -68,10 +68,9 @@ public class PlayerJoinListener {
var player = handler.player;
// Handle skill tree map instance
/// TODO: Turning this off for now because it's not out yet and breaking!
// if (AttributeMgr.activeTrees.containsKey(player.getUuidAsString()) == false) {
// AttributeMgr.activeTrees.put(player.getUuidAsString(), new AttributeTree(player.getUuidAsString()));
// }
if (AttributeMgr.activeTrees.containsKey(player.getUuidAsString()) == false) {
AttributeMgr.activeTrees.put(player.getUuidAsString(), new AttributeTree(player));
}
// Handle first time joining events (world spawn teleport, MOTD, etc)
System.out.println("Running first time login stuff");

View File

@ -0,0 +1,25 @@
package jesse.keeblarcraft.FactionMgr.Callbacks;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
import net.minecraft.entity.player.PlayerEntity;
// import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.util.ActionResult;
import net.minecraft.world.World;
public interface PlayerInBaseCallback {
Event<PlayerInBaseCallback> EVENT = EventFactory.createArrayBacked(PlayerInBaseCallback.class,
(listeners) -> (player, world) -> {
for (PlayerInBaseCallback listener : listeners) {
ActionResult result = listener.interact(player, world);
if (result != ActionResult.PASS) {
return result;
}
}
return ActionResult.PASS;
});
ActionResult interact(PlayerEntity player, World world);
}

View File

@ -13,34 +13,25 @@ package jesse.keeblarcraft;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.entity.event.v1.ServerEntityWorldChangeEvents;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerEntityEvents;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents.ServerStopping;
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
import net.kyrptonaught.customportalapi.api.CustomPortalBuilder;
import net.minecraft.block.AbstractBlock;
import net.minecraft.block.Block;
import net.minecraft.block.Blocks;
import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.entity.EntityDimensions;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.entity.mob.HostileEntity;
import net.minecraft.item.Items;
import net.minecraft.registry.Registries;
import net.minecraft.registry.Registry;
import net.minecraft.resource.featuretoggle.FeatureSet;
import net.minecraft.screen.ScreenHandlerType;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jesse.keeblarcraft.AttributeMgr.AttributeMgr;
import jesse.keeblarcraft.AttributeMgr.AttributeTree;
import jesse.keeblarcraft.BankMgr.BankManager;
import jesse.keeblarcraft.Commands.CustomCommandManager;
import jesse.keeblarcraft.ConfigMgr.SQLConfig;
import jesse.keeblarcraft.ConfigMgr.SQLUnitTest;
import jesse.keeblarcraft.CustomBlocks.BlockList;
import jesse.keeblarcraft.CustomBlocks.BlockEntities.BlockEntityRegistration;
@ -51,7 +42,6 @@ import jesse.keeblarcraft.EventMgr.ServerTickListener;
import jesse.keeblarcraft.GuiMgr.ScreenHandlerRegistration;
import jesse.keeblarcraft.GuiMgr.TreeHandler;
import jesse.keeblarcraft.Utils.CustomExceptions.SETUP_FAILED_EXCEPTION;
import jesse.keeblarcraft.ChatStuff.ChatMsg;
import jesse.keeblarcraft.Utils.Setup;
public class Keeblarcraft implements ModInitializer {
@ -107,6 +97,16 @@ public class Keeblarcraft implements ModInitializer {
DimensionLoadingEvent.GetInstance().SaveInventories();
});
ServerEntityEvents.ENTITY_LOAD.register((entity, world) -> {
// System.out.println("ENTITY LOAD EVENT INFORMATION");
// System.out.println("Name: " + entity.getEntityName());
// System.out.println("World: " + world.asString());
// System.out.println("COORDS: " + entity.getX() + " " + entity.getY() + " " + entity.getZ());
// System.out.println("TYPE: " + entity.getType());
// System.out.println("SPAWN GROUP: " + entity.getType().getSpawnGroup().asString());
// System.out.println("Is hostile? " + (entity instanceof HostileEntity ? "YES":"NO"));
});
// Initialize our ticks!!
ServerTickListener.InitializeServerTicks();