[5] Initial implementation of some attribute stuff. Nothing in this commit actually works but the game still launches! Will need to move item and armor stuff to a more generic file as well to make it less unique so it can be used broadly. Directory structure extended to add items and resources
[5] **WORKING** add custom item and item group to game. primarily metaljacket items not added yet - but example item works. [5] initial add of custom blocks [5] Made adding blocks more dynamic - tested to work [5] Fixed metal jacket armor & created correct texture files to not break game. TEXTURES ARE RANDOM ON WEARING AS I DONT HAVE AN ACTUAL TEXTURE YET [5] Started attribute tree stuff [5] end of day commit. **NOT WORKING** [5] First successful attribute write using test commandsgit br [5] one directory for you, and one for you, and one for... [5] Loot tables, dropping blocks, experience block, example ore block changes [5] Documentation. Small command patch to make command treegit br
81
src/main/java/jesse/keeblarcraft/Armor/MetalJacketArmor.java
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
package jesse.keeblarcraft.Armor;
|
||||||
|
|
||||||
|
import jesse.keeblarcraft.Keeblarcraft;
|
||||||
|
import net.minecraft.item.ArmorItem;
|
||||||
|
import net.minecraft.item.ArmorMaterial;
|
||||||
|
import net.minecraft.item.Items;
|
||||||
|
import net.minecraft.recipe.Ingredient;
|
||||||
|
import net.minecraft.sound.SoundEvent;
|
||||||
|
import net.minecraft.sound.SoundEvents;
|
||||||
|
|
||||||
|
public class MetalJacketArmor implements ArmorMaterial {
|
||||||
|
// All references to this class must refer to this
|
||||||
|
public static final MetalJacketArmor INSTANCE = new MetalJacketArmor();
|
||||||
|
|
||||||
|
int defaultArmorModifier = 3;
|
||||||
|
|
||||||
|
/// FUNCTIONS BELOW
|
||||||
|
|
||||||
|
public MetalJacketArmor() {
|
||||||
|
System.out.println("Constructor for armor called");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getDurability(ArmorItem.Type type) {
|
||||||
|
System.out.println("durability for armor called");
|
||||||
|
// Replace this multiplier by a constant value for the durability of the armor.
|
||||||
|
// For reference, diamond uses 33 for all armor pieces, whilst leather uses 5.
|
||||||
|
return switch (type) {
|
||||||
|
case ArmorItem.Type.BOOTS -> Integer.MAX_VALUE;
|
||||||
|
case ArmorItem.Type.LEGGINGS -> Integer.MAX_VALUE;
|
||||||
|
case ArmorItem.Type.CHESTPLATE -> Integer.MAX_VALUE;
|
||||||
|
case ArmorItem.Type.HELMET -> Integer.MAX_VALUE;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getProtection(ArmorItem.Type type) {
|
||||||
|
System.out.println("Protection called");
|
||||||
|
// Protection values for all the slots.
|
||||||
|
// For reference, diamond uses 3 for boots, 6 for leggings, 8 for chestplate, and 3 for helmet,
|
||||||
|
// whilst leather uses 1, 2, 3 and 1 respectively.
|
||||||
|
return switch (type) {
|
||||||
|
case ArmorItem.Type.BOOTS -> defaultArmorModifier;
|
||||||
|
case ArmorItem.Type.HELMET -> defaultArmorModifier;
|
||||||
|
case ArmorItem.Type.LEGGINGS -> defaultArmorModifier;
|
||||||
|
case ArmorItem.Type.CHESTPLATE -> defaultArmorModifier;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getEnchantability() {
|
||||||
|
return Integer.MAX_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SoundEvent getEquipSound() {
|
||||||
|
// Example for Iron Armor
|
||||||
|
return SoundEvents.ITEM_ARMOR_EQUIP_IRON;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Ingredient getRepairIngredient() {
|
||||||
|
return Ingredient.ofItems(Items.BEDROCK); // prayfully impossible repair or just not worth it
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return Keeblarcraft.MOD_ID + ":" + "metaljacket";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getToughness() {
|
||||||
|
// Toughness is the actual "resistance" the armor provides to HIGH damage attacks
|
||||||
|
return (float) defaultArmorModifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getKnockbackResistance() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
115
src/main/java/jesse/keeblarcraft/AttributeMgr/AttributeMgr.java
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* AttributeMgr
|
||||||
|
*
|
||||||
|
* Central point for the attribute skill system in the mod
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package jesse.keeblarcraft.AttributeMgr;
|
||||||
|
|
||||||
|
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.ConfigMgr.ConfigManager;
|
||||||
|
import jesse.keeblarcraft.Utils.ChatUtil;
|
||||||
|
|
||||||
|
public class AttributeMgr {
|
||||||
|
ConfigManager config;
|
||||||
|
|
||||||
|
// Global list of attributes
|
||||||
|
public static final HashMap<String, Class<? extends AbstractNode>> attributes = new HashMap<String, Class<? extends AbstractNode>>();
|
||||||
|
|
||||||
|
// This is a list of all logged in player tree's. These are kept in memory until either the mod is torn down or
|
||||||
|
// players log out for optimization reasons
|
||||||
|
public static final HashMap<String, AttributeTree> activeTrees = new HashMap<String, AttributeTree>();
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn RegisterAttributeClass
|
||||||
|
///
|
||||||
|
/// @brief All generic class objects for attributes should be
|
||||||
|
/// registered via this function
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
public static void RegisterAttributeClass(Class<? extends AbstractNode> classObj) {
|
||||||
|
AbstractNode verifyNode = null;
|
||||||
|
try {
|
||||||
|
// We spin up an instance of this node; but it will be dead after this function. We need this for name
|
||||||
|
verifyNode = classObj.newInstance();
|
||||||
|
} catch (Exception e) {
|
||||||
|
Keeblarcraft.LOGGER.error("Attempted to assign AbstractNode class type when registering object but could not call .newInstance()! Constructs must be empty");
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
ChatUtil.LoggerColored("Registring attribute called", ChatUtil.CONSOLE_COLOR.CYAN, Keeblarcraft.LOGGER);
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (attributes.containsKey(verifyNode.GetNodeTitle())) {
|
||||||
|
Keeblarcraft.LOGGER.warn("Could not register attribute with duplicate name '" + verifyNode.GetNodeTitle() + "'");
|
||||||
|
} else {
|
||||||
|
ChatUtil.LoggerColored("REGISTERING ATTRIBUTE " + verifyNode.GetNodeTitle(), ChatUtil.CONSOLE_COLOR.YELLOW, Keeblarcraft.LOGGER);
|
||||||
|
attributes.put(verifyNode.GetNodeTitle(), classObj);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {} // Left empty since previous try-catch will throw error-message
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn ApplyAttribute
|
||||||
|
///
|
||||||
|
/// @arg[in] uuid is the players uuid
|
||||||
|
///
|
||||||
|
/// @arg[in] attributeName is the node title of the attribute class object
|
||||||
|
///
|
||||||
|
/// @brief Used to apply an attribute to a player's attribute tree
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
public static String ApplyAttribute(String uuid, String attributeName) {
|
||||||
|
String msg = "";
|
||||||
|
if (attributes.containsKey(attributeName)) {
|
||||||
|
AttributeTree playerTree = activeTrees.get(uuid);
|
||||||
|
AbstractNode node = null;
|
||||||
|
try {
|
||||||
|
node = attributes.get(attributeName).newInstance();
|
||||||
|
} catch (Exception e) {
|
||||||
|
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) {
|
||||||
|
///////////
|
||||||
|
// debug testing
|
||||||
|
String isNull = (node == null ? "NULL" : "NOT NULL");
|
||||||
|
System.out.println("Node is " + isNull);
|
||||||
|
if (isNull.equals("NOT NULL")) { System.out.println("Node name: " + node.GetNodeTitle()); }
|
||||||
|
// end debug testing
|
||||||
|
///////////
|
||||||
|
|
||||||
|
playerTree.AddNewNode(node, 1, null, null);
|
||||||
|
msg = "Applied attribute '" + attributeName + "' successfully";
|
||||||
|
} else {
|
||||||
|
msg = "Player tree not found!";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
msg = "Could not apply attribute, attribute name does not exist!";
|
||||||
|
}
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn RegisterAttributes
|
||||||
|
///
|
||||||
|
/// @brief This registers all attribute classes to the global attribute
|
||||||
|
/// class. Individual classes can be added here that call the
|
||||||
|
/// more braod "RegisterAttributeClass"
|
||||||
|
/// @see RegisterAttributeClass
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public static void RegisterAttributes() {
|
||||||
|
// Manually register all attribute node classes here
|
||||||
|
/// TODO: Find a better way to do this more dynamically in the future
|
||||||
|
|
||||||
|
RegisterAttributeClass(AttributeFlight.class);
|
||||||
|
RegisterAttributeClass(AttributeMetalJacket.class);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* AbstractNode
|
||||||
|
*
|
||||||
|
* This is the general definition of everything that is allowed inside a node and is called by our system
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package jesse.keeblarcraft.AttributeMgr.AttributeNodes;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
abstract public class AbstractNode {
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn GetNodeTitle
|
||||||
|
///
|
||||||
|
/// @brief The title of your node/skill!
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public abstract String GetNodeTitle();
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn GetNodeDescription
|
||||||
|
///
|
||||||
|
/// @brief This will become the hover-over text display of a skill in
|
||||||
|
/// the skill tree
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public abstract String GetNodeDescription();
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn GetDetails
|
||||||
|
///
|
||||||
|
/// @brief This is the general details that may be displayed inside the
|
||||||
|
/// GUI when the skill tree becomes available to a player. The
|
||||||
|
/// object is suggested to be treated as such:
|
||||||
|
///
|
||||||
|
/// KEY (String) -> The title of an effect/attribute
|
||||||
|
/// VAL (List<String>) -> Treated as a list of description
|
||||||
|
/// attributes. 1 string per description
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public abstract HashMap<String, List<String>> GetDetails();
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn RegisterCallbacks
|
||||||
|
///
|
||||||
|
/// @brief If your node has responsive callbacks; then this is the area
|
||||||
|
/// you will register your callbacks for everything
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public abstract void RegisterCallbacks();
|
||||||
|
}
|
@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,56 @@
|
|||||||
|
package jesse.keeblarcraft.AttributeMgr.AttributeNodes;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import jesse.keeblarcraft.Keeblarcraft;
|
||||||
|
import jesse.keeblarcraft.Armor.MetalJacketArmor;
|
||||||
|
import jesse.keeblarcraft.CustomItems.ItemManager;
|
||||||
|
import net.minecraft.item.ArmorItem;
|
||||||
|
import net.minecraft.item.Item;
|
||||||
|
|
||||||
|
public final class AttributeMetalJacket extends AbstractNode {
|
||||||
|
// This is the custom armor set that players will receive if no armor is on & attribute is equipped
|
||||||
|
public final Item jacketHelm = new ArmorItem(MetalJacketArmor.INSTANCE, ArmorItem.Type.HELMET, new Item.Settings());
|
||||||
|
public final Item jacketChest = new ArmorItem(MetalJacketArmor.INSTANCE, ArmorItem.Type.CHESTPLATE, new Item.Settings());
|
||||||
|
public final Item jacketLegs = new ArmorItem(MetalJacketArmor.INSTANCE, ArmorItem.Type.LEGGINGS, new Item.Settings());
|
||||||
|
public final Item jacketBoots = new ArmorItem(MetalJacketArmor.INSTANCE, ArmorItem.Type.BOOTS, new Item.Settings());
|
||||||
|
|
||||||
|
public AttributeMetalJacket() {
|
||||||
|
// Finally register items with game
|
||||||
|
Keeblarcraft.LOGGER.debug("Registering metaljackets");
|
||||||
|
ItemManager.RegisterItem("metaljacket_helmet", jacketHelm);
|
||||||
|
ItemManager.RegisterItem("metaljacket_chestplate", jacketChest);
|
||||||
|
ItemManager.RegisterItem("metaljacket_leggings", jacketLegs);
|
||||||
|
ItemManager.RegisterItem("metaljacket_boots", jacketBoots);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String GetNodeTitle() {
|
||||||
|
return "MetalJacket";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Short description of node on hover-event in GUI
|
||||||
|
@Override
|
||||||
|
public String GetNodeDescription() {
|
||||||
|
return "MetalJacket affects armor value modifiers or gives player base armor when none is worn";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Detailed description of node on click-event in GUI
|
||||||
|
@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("durability", List.of (
|
||||||
|
"Gives player a base armor set with 3 protection and resistance",
|
||||||
|
"If armor is being worn, this attribute multiplies each pieces armor value by 120% (rounding up to nearest integer)"
|
||||||
|
));
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void RegisterCallbacks() {
|
||||||
|
}
|
||||||
|
}
|
322
src/main/java/jesse/keeblarcraft/AttributeMgr/AttributeTree.java
Normal file
@ -0,0 +1,322 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* AttributeTree
|
||||||
|
*
|
||||||
|
* Handles a players individual attribute tree
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package jesse.keeblarcraft.AttributeMgr;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
import jesse.keeblarcraft.Keeblarcraft;
|
||||||
|
import jesse.keeblarcraft.AttributeMgr.AttributeNodes.AbstractNode;
|
||||||
|
import jesse.keeblarcraft.ConfigMgr.ConfigManager;
|
||||||
|
import jesse.keeblarcraft.Utils.ChatUtil;
|
||||||
|
import jesse.keeblarcraft.Utils.ChatUtil.CONSOLE_COLOR;
|
||||||
|
import jesse.keeblarcraft.Utils.CustomExceptions.FILE_WRITE_EXCEPTION;
|
||||||
|
|
||||||
|
public class AttributeTree {
|
||||||
|
|
||||||
|
PlayerTree playerAttributeTree = new PlayerTree();
|
||||||
|
ConfigManager config = new ConfigManager();
|
||||||
|
private AbstractNode root = new RootNode();
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @class TreeNode
|
||||||
|
///
|
||||||
|
/// @brief This is an individual node that goes within the larger
|
||||||
|
/// PlayerTree class object
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
private class TreeNode {
|
||||||
|
public TreeNode(AbstractNode node, Integer maxLevel, List<String> parents, List<String> children) {
|
||||||
|
thisNode = node;
|
||||||
|
parentNodes = parents;
|
||||||
|
childrenNodes = children;
|
||||||
|
maxNodeLevel = maxLevel;
|
||||||
|
currentNodeLevel = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
AbstractNode thisNode;
|
||||||
|
Integer currentNodeLevel;
|
||||||
|
Integer maxNodeLevel;
|
||||||
|
|
||||||
|
// Store the names of the parent and children nodes; this lets a node have any number of parents and children
|
||||||
|
// NOTE TO DEVELOPERS: Be aware! The more nodes the harrier the tree will look in the GUI!!! Always test your
|
||||||
|
// code before just adding stuff willy-nilly!
|
||||||
|
List<String> parentNodes;
|
||||||
|
List<String> childrenNodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @class PlayerTree
|
||||||
|
///
|
||||||
|
/// @brief This is the tree object of a given player. It contains all
|
||||||
|
/// valid attribute information for a player that is statically
|
||||||
|
/// stored inside the AttributeMgr class
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
private class PlayerTree {
|
||||||
|
String uuid;
|
||||||
|
// Key = name of AbstractNode
|
||||||
|
// Val = The attribute itself
|
||||||
|
HashMap<String, TreeNode> tree = new HashMap<String, TreeNode>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @class RootNode
|
||||||
|
///
|
||||||
|
/// @brief This is the default root node of a tree. It is mostly left
|
||||||
|
/// blank and used to code around as an "anchor" object
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
private class RootNode extends AbstractNode {
|
||||||
|
@Override
|
||||||
|
public String GetNodeTitle() {
|
||||||
|
return "root";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String GetNodeDescription() {
|
||||||
|
return "This is the players tree root! All attributes extend from here";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HashMap<String, List<String>> GetDetails() {
|
||||||
|
HashMap<String, List<String>> ret = new HashMap<String, List<String>>();
|
||||||
|
|
||||||
|
ret.put("First Attribute", List.of("This is your skill tree", "All attributes grow from this root! Unlocking nodes requires all nodes connected to that previously to be unlocked first"));
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void RegisterCallbacks() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn RegisterActiveCallbacks
|
||||||
|
///
|
||||||
|
/// @brief This will register all the active callbacks on all nodes that
|
||||||
|
/// are unlocked within a players tree instance
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public void RegisterActiveCallbacks() {
|
||||||
|
for(Entry<String, TreeNode> tree : playerAttributeTree.tree.entrySet()) {
|
||||||
|
if (tree.getValue().currentNodeLevel != 0) {
|
||||||
|
|
||||||
|
// We need to construct the node object if it's null. If it's not null; we assume
|
||||||
|
// the callback registration process has already happened
|
||||||
|
if (tree.getValue().thisNode == null) {
|
||||||
|
System.out.println("REGISTERACTIVECALLBACKS - NULL NODE");
|
||||||
|
tree.getValue().thisNode.RegisterCallbacks();
|
||||||
|
} else {
|
||||||
|
System.out.println("REGISTERACTIVECALLBACKS - NOT NULL NODE");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn AddNewNode
|
||||||
|
///
|
||||||
|
/// @arg[in] newNode is the attribute node to be added to the player tree
|
||||||
|
///
|
||||||
|
/// @arg[in] maxNodeLevel is the max level of the node
|
||||||
|
///
|
||||||
|
/// @arg[in] parents is the list of parent attributes. If empty,
|
||||||
|
/// root is default
|
||||||
|
///
|
||||||
|
/// @arg[in] children is the list of children attributes.
|
||||||
|
/// Root cannot be child
|
||||||
|
///
|
||||||
|
/// @brief Add a new node to the tree arbitrarily. Root can never be a
|
||||||
|
/// child node parents can never be empty or null (null or empty
|
||||||
|
/// would imply you are adding root)
|
||||||
|
///
|
||||||
|
/// @note developer warning: you must personally verify your nodes are
|
||||||
|
/// in the tree. anywhere is fine, and the tree is very dynamic
|
||||||
|
/// (which is why self verification is required). When the tree
|
||||||
|
/// is drawn in the GUI, it starts from the root node. As long as
|
||||||
|
/// your node is attached to this node anywhere in the indirected
|
||||||
|
/// graph; then your attribute will be drawn in the gui
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public Boolean AddNewNode(AbstractNode newNode, Integer maxNodeLevel, List<String> parents, List<String> children) {
|
||||||
|
Boolean ret = false;
|
||||||
|
TreeNode nodeReference = playerAttributeTree.tree.get(newNode.GetNodeTitle());
|
||||||
|
|
||||||
|
System.out.println("Is node reference null? -> " + (nodeReference == null ? "YES":"NO"));
|
||||||
|
System.out.println("Is root reference null? -> " + (root == null ? "YES":"NO"));
|
||||||
|
System.out.println("Is parents null? -> " + (parents == null ? "YES":"NO"));
|
||||||
|
|
||||||
|
// Some special handling is required on checking child list in case it is null
|
||||||
|
Boolean validChildren = true;
|
||||||
|
if (children != null) {
|
||||||
|
validChildren = !children.contains(root.GetNodeTitle());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nodeReference == null && validChildren) {
|
||||||
|
// Since these values can be left as null, we want to guarentee they are at least initialized here
|
||||||
|
maxNodeLevel = (maxNodeLevel == null ? 1 : maxNodeLevel);
|
||||||
|
parents = (parents == null ? new ArrayList<String>() : parents);
|
||||||
|
children = (children == null ? new ArrayList<String>() : children);
|
||||||
|
|
||||||
|
if (parents.size() == 0) {
|
||||||
|
parents.add(root.GetNodeTitle()); // No disconnected nodes allowed! All parentless nodes are adopted by root by default
|
||||||
|
}
|
||||||
|
|
||||||
|
// Node implementation here
|
||||||
|
playerAttributeTree.tree.put(newNode.GetNodeTitle(), new TreeNode(newNode, maxNodeLevel, parents, children));
|
||||||
|
|
||||||
|
// 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();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Some fancy error handling for console log
|
||||||
|
if (nodeReference != null) {
|
||||||
|
Keeblarcraft.LOGGER.error("Attribute with name " + newNode.GetNodeTitle() + " was already found within the tree! Rename your node to add it");
|
||||||
|
} else {
|
||||||
|
Keeblarcraft.LOGGER.error("The attribute you attempted to add (name: " + newNode.GetNodeTitle() + "), has root in the children");
|
||||||
|
}
|
||||||
|
ret = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
FlashConfig();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn ChangeNodeLevel
|
||||||
|
///
|
||||||
|
/// @arg[in] nodeName is the attribute node title
|
||||||
|
///
|
||||||
|
/// @arg[in] newLevel is the new level you wish to grant the node
|
||||||
|
///
|
||||||
|
/// @brief If you wish to change the level of an attribute, you can use
|
||||||
|
/// this function to do so
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public void ChangeNodeLevel(String nodeName, Integer newLevel) {
|
||||||
|
TreeNode nodeReference = playerAttributeTree.tree.get(nodeName);
|
||||||
|
|
||||||
|
if (nodeReference != null) {
|
||||||
|
if (newLevel <= nodeReference.maxNodeLevel) {
|
||||||
|
nodeReference.currentNodeLevel = newLevel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FlashConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn DeleteNode
|
||||||
|
///
|
||||||
|
/// @arg[in] nodeName is the attribute node title
|
||||||
|
///
|
||||||
|
/// @brief Delete a node via the name
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public void DeleteNode(String nodeName) {
|
||||||
|
// Do not delete root!
|
||||||
|
if (nodeName != root.GetNodeTitle()) {
|
||||||
|
playerAttributeTree.tree.remove(nodeName);
|
||||||
|
}
|
||||||
|
|
||||||
|
FlashConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn GetNodeDetails
|
||||||
|
///
|
||||||
|
/// @arg[in] nodeName is the attribute node title
|
||||||
|
///
|
||||||
|
/// @brief Returns the detail map from the attribute if it has any
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public HashMap<String, List<String>> GetNodeDetails(String nodeName) {
|
||||||
|
HashMap<String, List<String>> ret = null;
|
||||||
|
|
||||||
|
TreeNode nodeReference = playerAttributeTree.tree.get(nodeName);
|
||||||
|
|
||||||
|
if (nodeReference != null) {
|
||||||
|
ret = nodeReference.thisNode.GetDetails();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn GetPlayerTree
|
||||||
|
///
|
||||||
|
/// @brief Returns the player tree. Will be deprecated in use of the
|
||||||
|
/// static active user map list instead for performance reasons
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
@Deprecated
|
||||||
|
public PlayerTree GetPlayerTree() {
|
||||||
|
return playerAttributeTree;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn AttributeTree
|
||||||
|
///
|
||||||
|
/// @arg[in] uuid is the player uuid
|
||||||
|
///
|
||||||
|
/// @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
|
||||||
|
Boolean existingFile = false;
|
||||||
|
try {
|
||||||
|
playerAttributeTree = config.GetJsonObjectFromFile("attributes/" + uuid + ".json", PlayerTree.class);
|
||||||
|
existingFile = true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
// Do nothing. This means the file does not exist
|
||||||
|
}
|
||||||
|
|
||||||
|
// In the event the above code failed out, this means a new file has to be created for the player's uuid
|
||||||
|
if (!existingFile)
|
||||||
|
{
|
||||||
|
System.out.println(ChatUtil.ColoredString("Trying to create new file", CONSOLE_COLOR.BLUE));
|
||||||
|
try {
|
||||||
|
playerAttributeTree.uuid = uuid;
|
||||||
|
FlashConfig();
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println(ChatUtil.ColoredString("Could not write to file", CONSOLE_COLOR.RED));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
System.out.println(ChatUtil.ColoredString("Moving on", CONSOLE_COLOR.BLUE));
|
||||||
|
}
|
||||||
|
|
||||||
|
// It's possible the above code will return a blank class if a file doesn't exist. This will make
|
||||||
|
// a new file with this players uuid
|
||||||
|
if ("".equals(playerAttributeTree.uuid)) {
|
||||||
|
System.out.println(ChatUtil.ColoredString("Assigning new config file for this uuid. No previous existing", CONSOLE_COLOR.BLUE));
|
||||||
|
playerAttributeTree.uuid = uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the tree is empty or missing root, add it!
|
||||||
|
if (playerAttributeTree.tree.size() == 0 || playerAttributeTree.tree.containsKey(root.GetNodeTitle()) == false) {
|
||||||
|
playerAttributeTree.tree.put(root.GetNodeTitle(), new TreeNode(root, 1, null, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
RegisterActiveCallbacks();
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn FlashConfig
|
||||||
|
///
|
||||||
|
/// @brief Flashes the config to the disk
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public void FlashConfig() {
|
||||||
|
try {
|
||||||
|
config.WriteToJsonFile("attributes/" + playerAttributeTree.uuid + ".json", playerAttributeTree);
|
||||||
|
} catch (FILE_WRITE_EXCEPTION e) {
|
||||||
|
System.out.println(ChatUtil.ColoredString("Could not flash notes configuration file", CONSOLE_COLOR.RED));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
115
src/main/java/jesse/keeblarcraft/Commands/AttributeCommands.java
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* AttributeCommands
|
||||||
|
*
|
||||||
|
* This class handles all the possible in-game commands for the attribute system
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package jesse.keeblarcraft.Commands;
|
||||||
|
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
|
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||||
|
import com.mojang.brigadier.context.CommandContext;
|
||||||
|
|
||||||
|
import jesse.keeblarcraft.Keeblarcraft;
|
||||||
|
import jesse.keeblarcraft.AttributeMgr.AttributeMgr;
|
||||||
|
import jesse.keeblarcraft.AttributeMgr.AttributeNodes.AbstractNode;
|
||||||
|
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.text.Text;
|
||||||
|
|
||||||
|
public class AttributeCommands {
|
||||||
|
public void RegisterCommands() {
|
||||||
|
|
||||||
|
// Command Root: "/attributes"
|
||||||
|
// Subcommands: "apply <name> <attributename>", "remove <name> <attributename>"
|
||||||
|
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
|
||||||
|
var attributeNode = CommandManager.literal("attributes").build();
|
||||||
|
|
||||||
|
var applyNode = CommandManager.literal("apply").build();
|
||||||
|
var removeNode = CommandManager.literal("delete").build();
|
||||||
|
var listNode = CommandManager.literal("list").executes(context -> ListAttributes(context)).build();
|
||||||
|
|
||||||
|
var playerArgAdd = CommandManager.argument("targetPlayer", EntityArgumentType.player()).build();
|
||||||
|
var playerArgRemove = CommandManager.argument("targetPlayer", EntityArgumentType.player()).build();
|
||||||
|
|
||||||
|
var attributeNameAdd = CommandManager.argument("attributeName", StringArgumentType.greedyString())
|
||||||
|
.executes(context -> ApplyAttribute
|
||||||
|
(
|
||||||
|
EntityArgumentType.getPlayer(context, "targetPlayer"),
|
||||||
|
StringArgumentType.getString(context, "attributeName"),
|
||||||
|
context)
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
var attributeNameDelete = CommandManager.argument("attributeName", StringArgumentType.greedyString())
|
||||||
|
.executes(context -> DeleteAttribute
|
||||||
|
(
|
||||||
|
EntityArgumentType.getPlayer(context, "targetPlayer"),
|
||||||
|
StringArgumentType.getString(context, "attributeName"),
|
||||||
|
context)
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// Build out the argument tree here
|
||||||
|
dispatcher.getRoot().addChild(attributeNode);
|
||||||
|
attributeNode.addChild(applyNode);
|
||||||
|
attributeNode.addChild(listNode);
|
||||||
|
attributeNode.addChild(removeNode);
|
||||||
|
|
||||||
|
// Subcommands "/apply playerArg", "/remove playerArg"
|
||||||
|
applyNode.addChild(playerArgAdd);
|
||||||
|
removeNode.addChild(playerArgRemove);
|
||||||
|
|
||||||
|
// name argument
|
||||||
|
playerArgAdd.addChild(attributeNameAdd);
|
||||||
|
playerArgRemove.addChild(attributeNameDelete);
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public int ApplyAttribute(ServerPlayerEntity targetPlayer, String attributeName, CommandContext<ServerCommandSource> context) {
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
System.out.println("Applying attribute");
|
||||||
|
if (context.getSource().isExecutedByPlayer()) {
|
||||||
|
System.out.println("Executed by player");
|
||||||
|
// String result = AttributeMgr.ApplyAttribute(targetPlayer.getUuidAsString(), attributeName);
|
||||||
|
String result = AttributeMgr.ApplyAttribute(context.getSource().getPlayer().getUuidAsString(), attributeName);
|
||||||
|
Keeblarcraft.LOGGER.info("[ApplyAttribute] -> " + result);
|
||||||
|
context.getSource().getPlayer().sendMessage(Text.of(result));
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int DeleteAttribute(ServerPlayerEntity username, String attributeName, CommandContext<ServerCommandSource> context) {
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int ListAttributes(CommandContext<ServerCommandSource> context) {
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
if (context.getSource().isExecutedByPlayer()) {
|
||||||
|
ServerPlayerEntity player = context.getSource().getPlayer();
|
||||||
|
|
||||||
|
for (Entry<String, Class<? extends AbstractNode>> entry : AttributeMgr.attributes.entrySet()) {
|
||||||
|
Keeblarcraft.LOGGER.debug("ATTR-LIST: " + entry.getKey() + " LINKS " + entry.getValue());
|
||||||
|
player.sendMessage(Text.of(entry.getKey()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
@ -21,12 +21,14 @@ public class CustomCommandManager {
|
|||||||
ShortcutCommands shortcuts = new ShortcutCommands();
|
ShortcutCommands shortcuts = new ShortcutCommands();
|
||||||
NoteCommands noteCommands = new NoteCommands();
|
NoteCommands noteCommands = new NoteCommands();
|
||||||
BankCommands bankCommands = new BankCommands();
|
BankCommands bankCommands = new BankCommands();
|
||||||
|
AttributeCommands attributeCommands = new AttributeCommands();
|
||||||
|
|
||||||
// REGISTER COMMANDS BELOW
|
// REGISTER COMMANDS BELOW
|
||||||
System.out.println(ChatUtil.ColoredString("REGISTERING CUSTOM COMMAND EXTENSIONS BELOW", CONSOLE_COLOR.BLUE));
|
System.out.println(ChatUtil.ColoredString("REGISTERING CUSTOM COMMAND EXTENSIONS BELOW", CONSOLE_COLOR.BLUE));
|
||||||
shortcuts.RegisterShortcutCommands();
|
shortcuts.RegisterShortcutCommands();
|
||||||
noteCommands.RegisterNoteCommands();
|
noteCommands.RegisterNoteCommands();
|
||||||
bankCommands.RegisterCommands();
|
bankCommands.RegisterCommands();
|
||||||
|
attributeCommands.RegisterCommands();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
*
|
*
|
||||||
* A class that simplifies some of the current vanilla commands with shortcut commands in the game. You may remember an old plugin
|
* A class that simplifies some of the current vanilla commands with shortcut commands in the game. You may remember an old plugin
|
||||||
* called "Essentials" (Or EssentialsEx in a later version) -> This file is re-creating a portion of that plugin but in mod-format
|
* called "Essentials" (Or EssentialsEx in a later version) -> This file is re-creating a portion of that plugin but in mod-format
|
||||||
|
*
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package jesse.keeblarcraft.Commands;
|
package jesse.keeblarcraft.Commands;
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
package jesse.keeblarcraft.ConfigMgr;
|
package jesse.keeblarcraft.ConfigMgr;
|
||||||
|
|
||||||
import java.io.FileWriter;
|
import java.io.FileWriter;
|
||||||
import java.io.FileReader;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -21,27 +20,19 @@ import com.google.common.base.Charsets;
|
|||||||
import com.google.common.io.Files;
|
import com.google.common.io.Files;
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.GsonBuilder;
|
import com.google.gson.GsonBuilder;
|
||||||
import com.google.gson.JsonArray;
|
|
||||||
import com.google.gson.JsonIOException;
|
import com.google.gson.JsonIOException;
|
||||||
import com.google.gson.JsonObject;
|
|
||||||
import com.google.gson.JsonParser;
|
|
||||||
import com.google.gson.JsonSyntaxException;
|
import com.google.gson.JsonSyntaxException;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
import org.spongepowered.asm.mixin.injection.struct.InjectorGroupInfo.Map;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import jesse.keeblarcraft.Utils.ChatUtil;
|
import jesse.keeblarcraft.Utils.ChatUtil;
|
||||||
import jesse.keeblarcraft.Utils.ChatUtil.CONSOLE_COLOR;
|
import jesse.keeblarcraft.Utils.ChatUtil.CONSOLE_COLOR;
|
||||||
// Import all custom exceptions
|
|
||||||
import jesse.keeblarcraft.Utils.CustomExceptions.*;
|
import jesse.keeblarcraft.Utils.CustomExceptions.*;
|
||||||
|
|
||||||
//minecraft server instance
|
|
||||||
import net.minecraft.server.MinecraftServer;
|
|
||||||
|
|
||||||
public class ConfigManager {
|
public class ConfigManager {
|
||||||
|
|
||||||
// Pedantic empty constructor
|
// Pedantic empty constructor
|
||||||
|
@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* BlockManager
|
||||||
|
*
|
||||||
|
* The mod block manager
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package jesse.keeblarcraft.CustomBlocks;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import jesse.keeblarcraft.Keeblarcraft;
|
||||||
|
import net.fabricmc.fabric.api.item.v1.FabricItemSettings;
|
||||||
|
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
|
||||||
|
import net.minecraft.block.Block;
|
||||||
|
import net.minecraft.block.Blocks;
|
||||||
|
import net.minecraft.block.ExperienceDroppingBlock;
|
||||||
|
import net.minecraft.item.BlockItem;
|
||||||
|
import net.minecraft.registry.Registries;
|
||||||
|
import net.minecraft.registry.Registry;
|
||||||
|
import net.minecraft.sound.BlockSoundGroup;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
import net.minecraft.util.math.intprovider.UniformIntProvider;
|
||||||
|
|
||||||
|
public class BlockManager {
|
||||||
|
|
||||||
|
/// The block list. DO NOT ADD TO THE LIST YOURSELF. USE
|
||||||
|
/// THE RegisterBlock(...) FUNCTION OTHERWISE YOUR BLOCK WILL
|
||||||
|
/// NOT BE REGISTERED PROPERLY AND MAY BREAK THE GAME
|
||||||
|
public static final List<Block> blockList = new ArrayList<Block>();
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn RegisterBlock
|
||||||
|
///
|
||||||
|
/// @arg[in] name is the block name. IMPORTANT: Name must adhere to rules:
|
||||||
|
/// 1. The name provided here must match these names:
|
||||||
|
/// * This blocks models/block name
|
||||||
|
/// * This blocks textures/block name
|
||||||
|
/// 2 Name must be lowercase & no special characters besides '_'
|
||||||
|
///
|
||||||
|
/// @arg[in] block is the block to be added to the block list
|
||||||
|
///
|
||||||
|
/// @brief This is the call to register your block to the game! Please
|
||||||
|
/// do not forget to update the models/block json file, the
|
||||||
|
/// textures/block png name, and finally the lang/en_us.json file
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public static void RegisterBlock(String name, Block block) {
|
||||||
|
|
||||||
|
// This call registers the block as an item in inventories
|
||||||
|
Registry.register(Registries.ITEM, new Identifier(Keeblarcraft.MOD_ID, name), new BlockItem(block, new FabricItemSettings()));
|
||||||
|
|
||||||
|
// This call registers the block as placed
|
||||||
|
Block newBlock = Registry.register(Registries.BLOCK, new Identifier(Keeblarcraft.MOD_ID, name), block);
|
||||||
|
|
||||||
|
// Add the block to the block list
|
||||||
|
blockList.add(newBlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn RegisterBlocks
|
||||||
|
///
|
||||||
|
/// @brief This function is only meant to be called by the main mod
|
||||||
|
/// execution path and should only be called once. This is a
|
||||||
|
/// glorified print statement - but also serves to add the
|
||||||
|
/// example block in the game
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public static void RegisterBlocks() {
|
||||||
|
Keeblarcraft.LOGGER.info("Registering modded blocks for " + Keeblarcraft.MOD_ID);
|
||||||
|
|
||||||
|
// Register example block to the mod
|
||||||
|
Block exampleBlock = new Block(FabricBlockSettings.copyOf(Blocks.IRON_BLOCK).sounds(BlockSoundGroup.AMETHYST_BLOCK).requiresTool().breakInstantly());
|
||||||
|
Block exampleBlockOre = new ExperienceDroppingBlock(FabricBlockSettings.copyOf(Blocks.IRON_BLOCK).sounds(BlockSoundGroup.ANCIENT_DEBRIS).requiresTool(), UniformIntProvider.create(4, 20));
|
||||||
|
RegisterBlock("example_block_ore", exampleBlockOre);
|
||||||
|
RegisterBlock("example_block", exampleBlock);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
package jesse.keeblarcraft.CustomItems;
|
||||||
|
|
||||||
|
import jesse.keeblarcraft.Keeblarcraft;
|
||||||
|
import jesse.keeblarcraft.CustomBlocks.BlockManager;
|
||||||
|
import net.fabricmc.fabric.api.itemgroup.v1.FabricItemGroup;
|
||||||
|
import net.minecraft.item.ItemGroup;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.item.Items;
|
||||||
|
import net.minecraft.registry.Registries;
|
||||||
|
import net.minecraft.registry.Registry;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
|
public class CustomItemGroups {
|
||||||
|
|
||||||
|
// This is the custom mod group for the mod
|
||||||
|
public static final ItemGroup MOD_GROUP = Registry.register(Registries.ITEM_GROUP,
|
||||||
|
new Identifier(Keeblarcraft.MOD_ID, "keeblarcraft"),
|
||||||
|
FabricItemGroup.builder().displayName(Text.translatable("itemgroup.keeblarcraft"))
|
||||||
|
.icon(() -> new ItemStack(Items.ANVIL)).entries((displayContext, entries) -> {
|
||||||
|
// We iterate through all the modded items and add them to the custom item group here
|
||||||
|
for (int i = 0; i < ItemManager.itemList.size(); i++) {
|
||||||
|
entries.add(ItemManager.itemList.get(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
// We iterate through all the modded blocks and add them to the custom block group here
|
||||||
|
for (int i = 0; i < BlockManager.blockList.size(); i++) {
|
||||||
|
entries.add(BlockManager.blockList.get(i));
|
||||||
|
}
|
||||||
|
}).build());
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn RegisterGroups
|
||||||
|
///
|
||||||
|
/// @brief Glorified print statement that the class has initialized
|
||||||
|
/// basically - meaning that all item groups have registered
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public static void RegisterGroups() {
|
||||||
|
Keeblarcraft.LOGGER.info("Registering item groups for " + Keeblarcraft.MOD_ID);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* ItemManager
|
||||||
|
*
|
||||||
|
* This is the general purpose item manager for the mod. All items will be registered through
|
||||||
|
* this class in order to make custom items a lot cleaner to make!
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package jesse.keeblarcraft.CustomItems;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
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;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
|
public class ItemManager {
|
||||||
|
|
||||||
|
/// The item list. DO NOT ADD TO THE LIST YOURSELF. USE
|
||||||
|
/// THE RegisterItem(...) FUNCTION OTHERWISE YOUR ITEM WILL
|
||||||
|
/// NOT BE REGISTERED PROPERLY AND MAY BREAK THE GAME
|
||||||
|
public static final List<Item> itemList = new ArrayList<Item>();
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn RegisterItem
|
||||||
|
///
|
||||||
|
/// @arg[in] name is the item name. IMPORTANT: Name must adhere to rules:
|
||||||
|
/// 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 '_'
|
||||||
|
///
|
||||||
|
/// @arg[in] item is the item to be added to the item list
|
||||||
|
///
|
||||||
|
/// @brief This is the call to register your item to the game! Please
|
||||||
|
/// do not forget to update the models/item json file, the
|
||||||
|
/// textures/item png name, and finally the lang/en_us.json file
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public static void RegisterItem(String name, Item item) {
|
||||||
|
Item newItem = Registry.register(Registries.ITEM, new Identifier(Keeblarcraft.MOD_ID, name), item);
|
||||||
|
itemList.add(newItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn RegisterAllItems
|
||||||
|
///
|
||||||
|
/// @brief This function is only meant to be called by the main mod
|
||||||
|
/// execution path and should only be called once. This is a
|
||||||
|
/// glorified print statement - but also serves to add the
|
||||||
|
/// example item in the game
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
public static void RegisterAllItems() {
|
||||||
|
Keeblarcraft.LOGGER.info("Registering mod items for " + Keeblarcraft.MOD_ID);
|
||||||
|
|
||||||
|
// Call the item group register function first
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
package jesse.keeblarcraft.EventMgr;
|
package jesse.keeblarcraft.EventMgr;
|
||||||
|
|
||||||
|
|
||||||
public class EventManager {
|
public class EventManager {
|
||||||
|
|
||||||
}
|
}
|
@ -1,20 +1,21 @@
|
|||||||
package jesse.keeblarcraft;
|
package jesse.keeblarcraft.EventMgr;
|
||||||
|
|
||||||
import jesse.CommonServerUtils;
|
import jesse.CommonServerUtils;
|
||||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
|
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
|
||||||
import net.minecraft.server.MinecraftServer;
|
import net.minecraft.server.MinecraftServer;
|
||||||
|
|
||||||
//this lets get the MinecraftServer instance and also do stuff on the end of the tick if we wanted to
|
// This interface is responsible for the end tick of a server world event tick
|
||||||
public class ServerTickListener implements ServerTickEvents.EndTick {
|
public class ServerTickListener implements ServerTickEvents.EndTick {
|
||||||
CommonServerUtils config = new CommonServerUtils();
|
CommonServerUtils config = new CommonServerUtils();
|
||||||
@Override
|
@Override
|
||||||
public void onEndTick(MinecraftServer server) {
|
public void onEndTick(MinecraftServer server) {
|
||||||
//Code that runs on end of each tick yes this actually works and tested
|
if (server != null) {
|
||||||
config.SetServerInstance(server);
|
config.SetServerInstance(server);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Static method to register the server tick listener
|
// Static method to register the server tick listener
|
||||||
public static void initialize() {
|
public static void InitializeServerTicks() {
|
||||||
ServerTickEvents.END_SERVER_TICK.register(new ServerTickListener());
|
ServerTickEvents.END_SERVER_TICK.register(new ServerTickListener());
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -12,23 +12,25 @@
|
|||||||
package jesse.keeblarcraft;
|
package jesse.keeblarcraft;
|
||||||
|
|
||||||
import net.fabricmc.api.ModInitializer;
|
import net.fabricmc.api.ModInitializer;
|
||||||
|
// import net.minecraft.server.command.ServerCommandSource;
|
||||||
|
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import jesse.keeblarcraft.AttributeMgr.AttributeMgr;
|
||||||
|
import jesse.keeblarcraft.AttributeMgr.AttributeTree;
|
||||||
import jesse.keeblarcraft.Commands.CustomCommandManager;
|
import jesse.keeblarcraft.Commands.CustomCommandManager;
|
||||||
|
import jesse.keeblarcraft.CustomBlocks.BlockManager;
|
||||||
|
import jesse.keeblarcraft.CustomItems.ItemManager;
|
||||||
|
import jesse.keeblarcraft.EventMgr.ServerTickListener;
|
||||||
import jesse.keeblarcraft.Utils.CustomExceptions.SETUP_FAILED_EXCEPTION;
|
import jesse.keeblarcraft.Utils.CustomExceptions.SETUP_FAILED_EXCEPTION;
|
||||||
import jesse.keeblarcraft.Utils.ChatUtil;
|
import jesse.keeblarcraft.Utils.ChatUtil;
|
||||||
import jesse.keeblarcraft.Utils.Setup;
|
import jesse.keeblarcraft.Utils.Setup;
|
||||||
import jesse.keeblarcraft.Utils.ChatUtil.CONSOLE_COLOR;
|
import jesse.keeblarcraft.Utils.ChatUtil.CONSOLE_COLOR;
|
||||||
|
|
||||||
// import com.mojang.brigadier.Command;
|
|
||||||
|
|
||||||
|
|
||||||
public class Keeblarcraft implements ModInitializer {
|
public class Keeblarcraft implements ModInitializer {
|
||||||
// This logger is used to write text to the console and the log file.
|
public static String MOD_ID = "keeblarcraft";
|
||||||
// It is considered best practice to use your mod id as the logger's name.
|
|
||||||
// That way, it's clear which mod wrote info, warnings, and errors.
|
|
||||||
public static final Logger LOGGER = LoggerFactory.getLogger("keeblarcraft");
|
public static final Logger LOGGER = LoggerFactory.getLogger("keeblarcraft");
|
||||||
CustomCommandManager cmdMgr = new CustomCommandManager();
|
CustomCommandManager cmdMgr = new CustomCommandManager();
|
||||||
|
|
||||||
@ -47,10 +49,45 @@ public class Keeblarcraft implements ModInitializer {
|
|||||||
LOGGER.info("\033[34m Running setup stage \033[0m");
|
LOGGER.info("\033[34m Running setup stage \033[0m");
|
||||||
setup.RunSetup();
|
setup.RunSetup();
|
||||||
|
|
||||||
|
// This is a very special case where this must be in this classes' initializer
|
||||||
|
// method
|
||||||
|
ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> {
|
||||||
|
var player = handler.player;
|
||||||
|
Keeblarcraft.LOGGER.info("Player " + player.getName() + " has logged in. Creating tree...");
|
||||||
|
|
||||||
|
if (AttributeMgr.activeTrees.containsKey(player.getUuidAsString()) == false) {
|
||||||
|
AttributeMgr.activeTrees.put(player.getUuidAsString(), new AttributeTree(player.getUuidAsString()));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ServerPlayConnectionEvents.DISCONNECT.register((handler, server) -> {
|
||||||
|
var player = handler.player;
|
||||||
|
Keeblarcraft.LOGGER.info("Player " + player.getName() + " has logged out. Deleting tree...");
|
||||||
|
|
||||||
|
if (AttributeMgr.activeTrees.containsKey(player.getUuidAsString()) == true) {
|
||||||
|
AttributeMgr.activeTrees.remove(player.getUuidAsString());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Initialize our ticks!!
|
||||||
|
ServerTickListener.InitializeServerTicks();
|
||||||
|
|
||||||
// Run command registrations from the command manager
|
// Run command registrations from the command manager
|
||||||
LOGGER.info("\033[34m Running command registration \033[0m");
|
LOGGER.info("\033[34m Running command registration \033[0m");
|
||||||
cmdMgr.RegisterCustomCommands();
|
cmdMgr.RegisterCustomCommands();
|
||||||
|
|
||||||
|
// Register attributes
|
||||||
|
AttributeMgr.RegisterAttributes();
|
||||||
|
|
||||||
|
|
||||||
|
/// THE BELOW ITEMS MUST BE DONE LAST IN THE STEPS
|
||||||
|
// Register items
|
||||||
|
ItemManager.RegisterAllItems();
|
||||||
|
|
||||||
|
// Register blocks
|
||||||
|
BlockManager.RegisterBlocks();
|
||||||
|
|
||||||
|
|
||||||
} catch (SETUP_FAILED_EXCEPTION e) {
|
} catch (SETUP_FAILED_EXCEPTION e) {
|
||||||
System.out.println(ChatUtil.ColoredString("ERROR. Setup failed to initialize environment. Mod likely does not have read/write permissions inside area. Mod will now close out.", CONSOLE_COLOR.RED));
|
System.out.println(ChatUtil.ColoredString("ERROR. Setup failed to initialize environment. Mod likely does not have read/write permissions inside area. Mod will now close out.", CONSOLE_COLOR.RED));
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
@ -12,17 +12,12 @@ package jesse.keeblarcraft.Utils;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.commons.io.FileUtils;
|
|
||||||
import org.spongepowered.include.com.google.common.io.Files;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import jesse.keeblarcraft.Keeblarcraft;
|
|
||||||
import jesse.keeblarcraft.ServerTickListener;
|
|
||||||
import jesse.keeblarcraft.ConfigMgr.ConfigManager;
|
import jesse.keeblarcraft.ConfigMgr.ConfigManager;
|
||||||
|
import jesse.keeblarcraft.EventMgr.ServerTickListener;
|
||||||
import jesse.keeblarcraft.Utils.ChatUtil.CONSOLE_COLOR;
|
import jesse.keeblarcraft.Utils.ChatUtil.CONSOLE_COLOR;
|
||||||
import jesse.keeblarcraft.Utils.CustomExceptions.DIRECTORY_CREATE_EXCEPTION;
|
import jesse.keeblarcraft.Utils.CustomExceptions.DIRECTORY_CREATE_EXCEPTION;
|
||||||
import jesse.keeblarcraft.Utils.CustomExceptions.DIRECTORY_DELETE_EXCEPTION;
|
|
||||||
import jesse.keeblarcraft.Utils.CustomExceptions.SETUP_FAILED_EXCEPTION;
|
import jesse.keeblarcraft.Utils.CustomExceptions.SETUP_FAILED_EXCEPTION;
|
||||||
|
|
||||||
// Singleton class is designed to help the mod set itself up and create all the important things. It does two things:
|
// Singleton class is designed to help the mod set itself up and create all the important things. It does two things:
|
||||||
@ -62,14 +57,16 @@ public final class Setup {
|
|||||||
add("commands"); // Expect 1 file per command that's configurable!
|
add("commands"); // Expect 1 file per command that's configurable!
|
||||||
add("events"); // Expect 1 file per event that is configurable!
|
add("events"); // Expect 1 file per event that is configurable!
|
||||||
add("bank");
|
add("bank");
|
||||||
|
add("attributes");
|
||||||
}};
|
}};
|
||||||
|
|
||||||
// These will be top-level config files above the directories this mod creates
|
// These will be top-level config files above the directories this mod creates
|
||||||
private static final List<String> FILE_LIST = new ArrayList<String>() {{
|
private static final List<String> FILE_LIST = new ArrayList<String>() {{
|
||||||
add("story/story.json"); // Big config file, determines when players can do certain things at different story levels
|
add("story/general_story_config.json"); // Big config file, determines when players can do certain things at different story levels
|
||||||
add("factions/factions.json"); // General configuration file for factions stuff
|
add("factions/general_factions_config.json"); // General configuration file for factions stuff
|
||||||
add("events/1events.json"); // General configuration file for story events!
|
add("events/general_event_config.json"); // General configuration file for story events!
|
||||||
add("general.json"); // The super general configuration file! (May be removed)
|
add("general.json"); // The super general configuration file! (May be removed)
|
||||||
|
add("attributes/general_attribute_config.json");
|
||||||
}};
|
}};
|
||||||
|
|
||||||
// RunChecks()
|
// RunChecks()
|
||||||
@ -159,21 +156,8 @@ public final class Setup {
|
|||||||
throw new SETUP_FAILED_EXCEPTION();
|
throw new SETUP_FAILED_EXCEPTION();
|
||||||
}
|
}
|
||||||
|
|
||||||
//testing for this
|
|
||||||
try {
|
|
||||||
onInitialize();
|
|
||||||
} catch (Exception e){
|
|
||||||
System.out.println(ChatUtil.ColoredString("servertick failed to inilize.", CONSOLE_COLOR.RED));
|
|
||||||
throw new SETUP_FAILED_EXCEPTION();
|
|
||||||
}
|
|
||||||
|
|
||||||
System.out.println(ChatUtil.ColoredString("DID SETUP COMPLETE SUCCESSFULLY? ", CONSOLE_COLOR.YELLOW) + (ret ? ChatUtil.ColoredString("YES", CONSOLE_COLOR.YELLOW) : ChatUtil.ColoredString("NO", CONSOLE_COLOR.YELLOW)));
|
System.out.println(ChatUtil.ColoredString("DID SETUP COMPLETE SUCCESSFULLY? ", CONSOLE_COLOR.YELLOW) + (ret ? ChatUtil.ColoredString("YES", CONSOLE_COLOR.YELLOW) : ChatUtil.ColoredString("NO", CONSOLE_COLOR.YELLOW)));
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onInitialize() {
|
|
||||||
// Call the setup file to register event listeners and other setup tasks
|
|
||||||
ServerTickListener.initialize();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"variants": {
|
||||||
|
"": {
|
||||||
|
"model": "keeblarcraft:block/example_block"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"variants": {
|
||||||
|
"": {
|
||||||
|
"model": "keeblarcraft:block/example_block_ore"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
11
src/main/resources/assets/keeblarcraft/lang/en_us.json
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"item.keeblarcraft.metaljacket_helmet": "MetalJacket Helmet",
|
||||||
|
"item.keeblarcraft.metaljacket_chestplate": "MetalJacket Chestplate",
|
||||||
|
"item.keeblarcraft.metaljacket_leggings": "MetalJacket Leggings",
|
||||||
|
"item.keeblarcraft.metaljacket_boots": "MetalJacket Booties",
|
||||||
|
|
||||||
|
"itemgroup.keeblarcraft": "Keeblarcraft Modded Items",
|
||||||
|
|
||||||
|
"block.keeblarcraft.example_block": "Keeblarcraft example block",
|
||||||
|
"block.keeblarcraft.example_block_ore": "Keeblarcraft example block ore"
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"parent": "block/cube_all",
|
||||||
|
"textures": {
|
||||||
|
"all": "keeblarcraft:block/example_block"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"parent": "block/cube_all",
|
||||||
|
"textures": {
|
||||||
|
"all": "keeblarcraft:block/example_block_ore"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"parent": "keeblarcraft:block/example_block"
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"parent": "keeblarcraft:block/example_block_ore"
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"parent": "item/generated",
|
||||||
|
"textures": {
|
||||||
|
"layer0": "keeblarcraft:item/metaljacket_boots"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"parent": "item/generated",
|
||||||
|
"textures": {
|
||||||
|
"layer0": "keeblarcraft:item/metaljacket_chestplate"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"parent": "item/generated",
|
||||||
|
"textures": {
|
||||||
|
"layer0": "keeblarcraft:item/metaljacket_helmet"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"parent": "item/generated",
|
||||||
|
"textures": {
|
||||||
|
"layer0": "keeblarcraft:item/metaljacket_leggings"
|
||||||
|
}
|
||||||
|
}
|
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 269 B |
After Width: | Height: | Size: 287 B |
After Width: | Height: | Size: 263 B |
After Width: | Height: | Size: 267 B |
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"replace": false,
|
||||||
|
"values": [
|
||||||
|
"keeblarcraft:example_block_ore"
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"type": "minecraft:block",
|
||||||
|
"pools": [
|
||||||
|
{
|
||||||
|
"bonus_rolls": 0.0,
|
||||||
|
"conditions": [
|
||||||
|
{
|
||||||
|
"condition": "minecraft:survives_explosion"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"entries": [
|
||||||
|
{
|
||||||
|
"type": "minecraft:item",
|
||||||
|
"name": "keeblarcraft:example_block"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"rolls": 1.0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"type": "minecraft:block",
|
||||||
|
"pools": [
|
||||||
|
{
|
||||||
|
"bonus_rolls": 0.0,
|
||||||
|
"conditions": [
|
||||||
|
{
|
||||||
|
"condition": "minecraft:survives_explosion"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"entries": [
|
||||||
|
{
|
||||||
|
"type": "minecraft:item",
|
||||||
|
"name": "keeblarcraft:example_block_ore"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"rolls": 1.0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"type": "minecraft:crafting_shaped",
|
||||||
|
"category": "misc",
|
||||||
|
"pattern": [
|
||||||
|
" # ",
|
||||||
|
"###",
|
||||||
|
" # "
|
||||||
|
],
|
||||||
|
"key": {
|
||||||
|
"#": {
|
||||||
|
"item": "keeblarcraft:example_block_ore"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"result": {
|
||||||
|
"item": "keeblarcraft:example_block",
|
||||||
|
"count": 8
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"type": "minecraft:crafting_shaped",
|
||||||
|
"category": "misc",
|
||||||
|
"pattern": [
|
||||||
|
"#C#",
|
||||||
|
"###",
|
||||||
|
"#C#"
|
||||||
|
],
|
||||||
|
"key": {
|
||||||
|
"#": {
|
||||||
|
"item": "keeblarcraft:example_block"
|
||||||
|
},
|
||||||
|
"C": {
|
||||||
|
"item": "minecraft:coal"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"result": {
|
||||||
|
"item": "keeblarcraft:example_block",
|
||||||
|
"count": 8
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"type": "minecraft:crafting_shapeless",
|
||||||
|
"category": "building",
|
||||||
|
"ingredients": [
|
||||||
|
{
|
||||||
|
"item": "keeblarcraft:example_block"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"result": {
|
||||||
|
"item": "keeblarcraft:example_block",
|
||||||
|
"count": 1
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"replace": false,
|
||||||
|
"values": [
|
||||||
|
"keeblarcraft:example_block",
|
||||||
|
"keeblarcraft:example_block_ore"
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"replace": false,
|
||||||
|
"values": [
|
||||||
|
"keeblarcraft:example_block"
|
||||||
|
]
|
||||||
|
}
|