Compare commits

..

No commits in common. "main" and "Create_modded_currency_items" have entirely different histories.

108 changed files with 900 additions and 4789 deletions

4
.gitignore vendored
View File

@ -9,10 +9,6 @@ classes/
*.launch
# Doxygen ignores
**html/*
**latex/*
# idea
.idea/

2658
Doxyfile

File diff suppressed because it is too large Load Diff

View File

@ -16,12 +16,6 @@ repositories {
// Loom adds the essential maven repositories to download Minecraft and libraries from automatically.
// See https://docs.gradle.org/current/userguide/declaring_repositories.html
// for more information about repositories.
// maven {
// url "https://maven.squiddev.cc"
// content {
// includeGroup("cc.tweaked")
// }
// }
}
loom {
@ -44,8 +38,7 @@ dependencies {
// Fabric API. This is technically optional, but you probably want it anyway.
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
//modCompileOnly "cc.tweaked:cc-tweaked-1.20-fabric-api:1.105.0"
//modRuntimeOnly "cc.tweaked:cc-tweaked-1.20-fabric-api:1.105.0"
}
processResources {
@ -57,7 +50,7 @@ processResources {
}
tasks.withType(JavaCompile).configureEach {
it.options.release = 17
it.options.release = 21
}
java {
@ -66,8 +59,8 @@ java {
// If you remove this line, sources will not be generated.
withSourcesJar()
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
sourceCompatibility = JavaVersion.VERSION_21
targetCompatibility = JavaVersion.VERSION_21
}
jar {

View File

@ -9,7 +9,7 @@ yarn_mappings=1.20+build.1
loader_version=0.15.11
# Mod Properties
mod_version=0.0.1
mod_version=1.0.0
maven_group=jesse.keeblarcraft
archives_base_name=keeblarcraft

View File

@ -1,4 +0,0 @@
#!/bin/bash
rm ~/.minecraft/mods/keeblarcraft* # What else could be named this? Really now?
cp build/devlibs/*sources.jar ~/.minecraft/mods
echo Moved minecraft to mods dir

View File

@ -1,21 +1,10 @@
package jesse.keeblarcraft;
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;
public class KeeblarcraftClient implements ClientModInitializer {
@Override
public void onInitializeClient() {
ShortcutManager.RegisterKeybinds();
ClientHandlers.RegisterHandlers();
ScreenManager.GetInstance();
ScreenManager.AddWidget(TreeWidget.class, 10);
}
}
@Override
public void onInitializeClient() {
// This entrypoint is suitable for setting up client-specific logic, such as rendering.
}
}

View File

@ -1,97 +0,0 @@
/*
*
* ShortcutManager
*
* This is the client-side shortcut keybind manager
*
*
*/
package jesse.keeblarcraft.Shortcuts;
import org.lwjgl.glfw.GLFW;
// import jesse.keeblarcraft.Keeblarcraft;
import jesse.keeblarcraft.gui.ScreenManager;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.option.KeyBinding;
import net.minecraft.client.util.InputUtil;
import net.minecraft.text.Text;
public class ShortcutManager {
private static KeyBinding skillTreeShortcut;
private static KeyBinding globalConfig;
private static Boolean toggleTreeGui = true; // Initialized to true for first time pressing keybind to actually display gui
// private static ScreenManager treeGui = null;
/////////////////////////////////////////////////////////////////////////////
/// @fn RegisterKeybinds
///
/// @brief Registers all player keybinds and callbacks to them
/////////////////////////////////////////////////////////////////////////////
// All callbacks for keyboard shortcuts are put here
public static void RegisterKeybinds() {
// Keybindings are registered here
skillTreeShortcut = KeyBindingHelper.registerKeyBinding(new KeyBinding(
"key.keeblarcraft.treemap",
InputUtil.Type.KEYSYM,
GLFW.GLFW_KEY_K,
"category.keeblarcraft.test"
));
globalConfig = KeyBindingHelper.registerKeyBinding(new KeyBinding(
"key.keeblarcraft.globalconfig",
InputUtil.Type.KEYSYM,
GLFW.GLFW_KEY_M,
"category.keeblarcraft.test"
));
/// Callbacks are down here
ClientTickEvents.END_CLIENT_TICK.register(client -> {
// The keybinding util does 2 things in one, if I check the state of the key press it flips a bit and deducts from
// the actual pressed amount - which we don't want to do. We will call the callbacks for keybinding functions here,
// and let them check the keybind themselves. NOTE: These functions are called at the end of every tick! Future us
// should see if there is a less expensive way to check this on just the keybind itself being flipped
DrawTreeGui(client);
if (globalConfig.wasPressed()) {
client.player.sendMessage(Text.of("Keeblarcraft recognizes you pressed the config button, but this option doesn't do anything yet"), false);
}
});
}
/////////////////////////////////////////////////////////////////////////////
/// @fn DrawTreeGui
///
/// @arg[in] client is the minecraft client instance that is passed in
/// so we have context of the client itself
///
/// @brief Draws the attribute tree GUI
/////////////////////////////////////////////////////////////////////////////
@SuppressWarnings("resource")
public static void DrawTreeGui(MinecraftClient client) {
while (skillTreeShortcut.wasPressed()) { // Constant loop required to redraw screen continuously
System.out.println("Key pressed detected"); /// TODO: When we figure out how to get key presses to still work when a screen opens; then we can toggle menus with buttons...
if (toggleTreeGui) {
// There is a technical resource leak that current screen is never closed when defining it here; which is ok I think because we want to return to it anyways
Screen currentScreen = MinecraftClient.getInstance().currentScreen;
client.player.sendMessage(Text.of("You pressed the GUI key!"));
// treeGui = new ScreenManager(Keeblarcraft.TREE_HANDLER.create(0, client.player.getInventory()), client.player.getInventory(), Text.of("Test"));
// treeGui.AddParent(currentScreen); ///TODO: Put this in the constructor when you figure out how the hell the magic is happening with registration
ScreenManager treeGui = ScreenManager.GetInstance();
treeGui.AddParent(currentScreen);
MinecraftClient.getInstance().setScreen(treeGui);
// toggleTreeGui intentionally never bit-flipped to false as a slight implementation bug exists such that pressing the keybind again
// does NOT call this callback function until the previous screen is CLOSED (which is why this isn't resource leaking...). This will
// need a slight rework or an extra subcall - but is fine for now since this is just how screens work.
}
}
}
}

View File

@ -1,14 +0,0 @@
/*
*
* IndividualAttribute
*
* This will be the handler class for each little attribute on the attribute tree itself.
* It will be fully implemented in the ticket that finishes the TreeWidget ticket (NOT GuiMgr)
*/
package jesse.keeblarcraft.gui.AttributeTree;
// This represents a single node in the tree of attributes drawn to the gui!!!
public class IndividualAttribute {
}

View File

@ -1,11 +0,0 @@
package jesse.keeblarcraft.gui;
import jesse.keeblarcraft.Keeblarcraft;
import net.minecraft.client.gui.screen.ingame.HandledScreens;
public class ClientHandlers {
public static void RegisterHandlers() {
System.out.println("Registering tree handler screen");
HandledScreens.register(Keeblarcraft.TREE_HANDLER, ScreenManager::new);
}
}

View File

@ -1,74 +0,0 @@
/*
*
* GenericLayerT
*
* GenericLayerT is the class that all layers must inherit from in order to be drawn. This allows for the GUI to properly
* draw the layers on which you want your canvas to exist!
*
*
*/
package jesse.keeblarcraft.gui;
import jesse.keeblarcraft.Utils.CommonStructures.Position2d;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder;
import net.minecraft.client.gui.widget.ClickableWidget;
import net.minecraft.text.Text;
abstract public class GenericLayerT extends ClickableWidget {
// These are the box bounds of the widget
public int startX;
public int startY;
public int endX;
public int endY;
public GenericLayerT() {
// default constructor
super(0, 0, 0, 0, Text.of(""));
}
/////////////////////////////////////////////////////////////////////////////
/// @fn GenericLayerT
///
/// @brief Constructor for class. This is setup directly by the screen
/// manager object and it is not recommended to change the x/y
/// positions or you may break the relation of your widget to
/// others on the screen at the same time!
/////////////////////////////////////////////////////////////////////////////
public GenericLayerT(int x, int y, int width, int height, Text message) {
super(x, y, width, height, message);
}
/////////////////////////////////////////////////////////////////////////////
/// @fn DrawLayer
///
/// @brief Draw on a layer! This is an early implementation of being
/// able to choose the layer you are drawing on and making sure
/// you can customize which layer your context will draw on.
/// This will be called by the overall screen manager so the
/// layer id will be passed in. You will need to handle the layer
/// id yourself.
///
/// @note It is possible to get passed any layer id and you handle each
/// layer respectively; however, it is possible to draw on the
/// wrong layer if handled wrong. For example, you could be
/// passed layer '3' but this function is called for every layer
/// drawn on screen; so you must handle this to only draw on a
/// specific layer. Be careful!
/////////////////////////////////////////////////////////////////////////////
public abstract void DrawLayer(DrawContext context, int layer);
public void UpdateAnchorValues(int x, int y) {
this.startX = x;
this.startY = y;
}
// Calculated based on center of box values
public Position2d GetScreenCenter() {
return new Position2d((this.endX - this.startX) / 2, (this.endY - this.startY) / 2);
}
public abstract void renderButton(DrawContext context, int mouseX, int mouseY, float delta);
protected abstract void appendClickableNarrations(NarrationMessageBuilder builder);
}

View File

@ -1,381 +0,0 @@
/*
*
* ScreenManager
*
* This is the screen manager for the global screen handler of `TreeHandler` type
* Please note: `TreeHandler` is suited for a more broad range of things; however
* its initial implementation is for the skill tree. It will be renamed to a more
* generic name so this class is more obviously re-usable after its implementation
* is complete AND we verify this class can be made more generic for it. Since this
* is unknown, it will remain the name it has currently.
*
*
*/
package jesse.keeblarcraft.gui;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map.Entry;
import jesse.keeblarcraft.Keeblarcraft;
import jesse.keeblarcraft.GuiMgr.TreeHandler;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.screen.ingame.HandledScreen;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.text.Text;
// Client side renderer
public class ScreenManager extends HandledScreen<TreeHandler> {
private static ScreenManager static_inst;
@SuppressWarnings("resource")
private static PlayerInventory static_inventory = new PlayerInventory(null);// = MinecraftClient.getInstance().player.getInventory();
public static ScreenManager GetInstance() {
if (static_inst == null) {
static_inst = new ScreenManager(Keeblarcraft.TREE_HANDLER.create(0, static_inventory), static_inventory, Text.of("Test"));
}
return static_inst;
}
private static HashMap<Integer, ArrayList<Class<? extends GenericLayerT>>> layerMap = new HashMap<Integer, ArrayList<Class<? extends GenericLayerT>>>();
private static HashMap<Integer, ArrayList<GenericLayerT>> layers = new HashMap<Integer, ArrayList<GenericLayerT>>(); // key: layer id; value: list of classes to draw
// private TreeWidget treeWidget = null;
private Screen parent;
/////////////////////////////////////////////////////////////////////////////
/// @fn ScreenManager
///
/// @arg[in] handler is the TreeHandler (ScreenHandler) object
///
/// @arg[in] inventory is the players inventory. Required by HandledScreen
/// object however is unused currently in this Screen
///
/// @arg[in] title is the title of the screen window
///
/// @brief Class constructor
/////////////////////////////////////////////////////////////////////////////
public ScreenManager(TreeHandler handler, PlayerInventory inventory, Text title) {
super(handler, inventory, title);
System.out.println("Called constructor of screen manager!");
// Initialize layers in map
// for (int i = 0; i < NUMBER_DRAW_LAYERS; i++) {
// layers.put(i, new ArrayList<Class<? extends GenericLayerT>>());
// }
}
/////////////////////////////////////////////////////////////////////////////
/// @fn AddParent
///
/// @arg[in] parent is the parent screen object
///
/// @brief Add a parent screen to the screen object. This is useful if
/// you want to return to the previous screen when this one gets
/// closed by the user
/////////////////////////////////////////////////////////////////////////////
public void AddParent(Screen parent) {
this.parent = parent;
}
public static void AddWidget(Class<? extends GenericLayerT> widget, int drawLayer) {
if (layerMap.containsKey(drawLayer)) {
// Just append the widget to the draw layer
var layerList = layerMap.get(drawLayer);
layerList.add(widget);
} else {
// Brand new layer!
layerMap.put(drawLayer, new ArrayList<>(List.of(widget)));
}
}
/////////////////////////////////////////////////////////////////////////////
/// @fn init
///
/// @brief Initialize method; called one-time to setup class variables
/////////////////////////////////////////////////////////////////////////////
@Override
public void init() {
// initialize screen size to the global background picture
this.width = MinecraftClient.getInstance().getWindow().getScaledWidth();
this.height = MinecraftClient.getInstance().getWindow().getScaledHeight();
// Let's go through and initialize all the screen types now in our active memory
for (Entry<Integer, ArrayList<Class<? extends GenericLayerT>>> layerEntry : layerMap.entrySet()) {
var layerList = layerEntry.getValue();
layers.put(layerEntry.getKey(), new ArrayList<>());
var activeLayerList = layers.get(layerEntry.getKey());
for (int i = 0; i < layerList.size(); i++) {
try {
System.out.println("Attempting to initialize widget with information: LAYER I-VAL W H: " + layerEntry.getKey() + " " + i + " " + this.width + " " + this.height);
GenericLayerT initializedWidget = layerList.get(i).getDeclaredConstructor(int.class, int.class, int.class, int.class, Text.class).newInstance(0, 0, this.width, this.height, Text.of(""));
activeLayerList.add(initializedWidget);
} catch (InstantiationException e) {
System.out.println("Could not initialize GenericLayerT class (" + layerList.get(i).getClass().toString() + ") because of IntantiationException");
e.printStackTrace();
} catch (IllegalAccessException e) {
System.out.println("Could not initialize GenericLayerT class (" + layerList.get(i).getClass().toString() + ") because of IllegalAccessException");
e.printStackTrace();
} catch (IllegalArgumentException e) {
System.out.println("Could not initialize GenericLayerT class (" + layerList.get(i).getClass().toString() + ") because of IllegalArgumentException");
e.printStackTrace();
} catch (InvocationTargetException e) {
System.out.println("Could not initialize GenericLayerT class (" + layerList.get(i).getClass().toString() + ") because of InvocationTargetException");
e.printStackTrace();
} catch (NoSuchMethodException e) {
System.out.println("Could not initialize GenericLayerT class (" + layerList.get(i).getClass().toString() + ") because of NoSuchMethodException");
e.printStackTrace();
} catch (SecurityException e) {
System.out.println("Could not initialize GenericLayerT class (" + layerList.get(i).getClass().toString() + ") because of SecurityException");
e.printStackTrace();
}
}
}
// Initialize child widgets with correct screen values so they can draw themselves in the right area on the screen (duh!)
// treeWidget = new TreeWidget(GLOBAL_SCREEN_START_X + 24, GLOBAL_SCREEN_START_Y + 24, GLOBAL_SCREEN_WIDTH - 24, GLOBAL_SCREEN_HEIGHT - 24);
// this.addDrawableChild(treeWidget);
}
/////////////////////////////////////////////////////////////////////////////
/// @fn render
///
/// @arg[in] context is the drawing context of super class
///
/// @arg[in] mouseX is passed to parent class but unused here
///
/// @arg[in] mouseY is passed to parent class but unused here
///
/// @brief Render is called every frame while the screen is open
///
/// @note This is a pure abstract in parent and is required
/////////////////////////////////////////////////////////////////////////////
@Override
public void render(DrawContext context, int mouseX, int mouseY, float delta) {
super.render(context, mouseX, mouseY, delta); // This takes care of calling drawBackground which calls DrawMainScreen
}
/////////////////////////////////////////////////////////////////////////////
/// @fn drawForeground
///
/// @arg[in] context is the drawing context of super class
///
/// @arg[in] mouseX is unused
///
/// @arg[in] mouseY is unused
///
/// @brief Draw foreground exists to draw the titles; however we
/// intentionally override it so the superclass object does not
/// draw the overlay over the background screen
/////////////////////////////////////////////////////////////////////////////
@Override
public void drawForeground(DrawContext context, int mouseX, int mouseY) {
// We override this function to intentionally do nothing
// If in the future we want, we would draw the foreground and TITLES with this!
}
/////////////////////////////////////////////////////////////////////////////
/// @fn close
///
/// @brief Called when the screen closes
///
/// @note This is a pure abstract in parent and is required
/////////////////////////////////////////////////////////////////////////////
@Override
public void close() {
this.client.setScreen(parent); // return to previous screen or null
}
/////////////////////////////////////////////////////////////////////////////
/// @fn mouseDragged
///
/// @arg[in] mouseX is x-axis position of original mouse click
///
/// @arg[in] mouseY is y-axis position of original mouse click
///
/// @arg[in] button is the int value of button pressed for mouse dragging
///
/// @arg[in] deltaX is the change in the X position from the previous
/// mouse click
///
/// @arg[in] deltaY is the change in the Y position from the previous
/// mouse click
///
/// @brief The drag event is called on all widgets on the screen so
/// long as the initial position of the drag is within the
/// bounds of the widget box itself. Widgets themselves will need
/// to handle any sub-widgets since the bound check is only
/// there to verify if the event happened ANYWHERE within a
/// widget box
/////////////////////////////////////////////////////////////////////////////
@Override
public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) {
super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY);
// UpdateAnchorValues();
for (Entry<Integer, ArrayList<GenericLayerT>> layerEntry : layers.entrySet()) {
var layerList = layerEntry.getValue();
for (var layerListIterator = 0; layerListIterator < layerList.size(); layerListIterator++) {
var layer = layerList.get(layerListIterator);
// Check to make sure scroll is within the context of the widget then deliver information
if (InBounds(layer.startX, layer.startY, layer.endX, layer.endY, (int) mouseX, (int) mouseY)) {
layer.mouseDragged(mouseX, mouseY, button, deltaX, deltaY);
}
}
}
return true;
}
/////////////////////////////////////////////////////////////////////////////
/// @fn mouseScrolled
///
/// @arg[in] mouseX is the initial X position of the cursor on a scroll
///
/// @arg[in] mouseY is the initial Y position of the cursor on a scroll
///
/// @arg[in] amount is a normalized value that indicates scroll direction
///
/// @brief The scroll event is called on all widgets on the screen so
/// long as the initial position of the scroll is within the
/// bounds of the widget box itself. Widgets themselves will need
/// to handle any sub-widgets since the bound check is only
/// there to verify if the event happened ANYWHERE within a
/// widget box
///
/////////////////////////////////////////////////////////////////////////////
@Override
public boolean mouseScrolled(double mouseX, double mouseY, double amount) {
super.mouseScrolled(mouseX, mouseY, amount);
for (Entry<Integer, ArrayList<GenericLayerT>> layerEntry : layers.entrySet()) {
var layerList = layerEntry.getValue();
for (var layerListIterator = 0; layerListIterator < layerList.size(); layerListIterator++) {
var layer = layerList.get(layerListIterator);
// Check to make sure scroll is within the context of the widget then deliver information
if (InBounds(layer.startX, layer.startY, layer.endX, layer.endY, (int) mouseX, (int) mouseY)) {
layer.mouseScrolled(mouseX, mouseY, amount);
}
}
}
return true; // The parent function defines this to be boolean; but I have no idea when I would want to return false from this
}
/////////////////////////////////////////////////////////////////////////////
/// @fn mouseClicked
///
/// @arg[in] mouseX is the initial X position of the mouse click event
///
/// @arg[in] mouseY is the initial Y position of the mouse click event
///
/// @arg[in] button is the mouse click button (left/right click value)
///
/// @brief The mouse click is called on all widgets on the screen so
/// long as the initial position of the click is within the
/// bounds of the widget box itself. Widgets themselves will need
/// to handle any sub-widgets since the bound check is only
/// there to verify if the event happened ANYWHERE within a
/// widget box
///
/////////////////////////////////////////////////////////////////////////////
@Override
public boolean mouseClicked(double mouseX, double mouseY, int button) {
super.mouseClicked(mouseX, mouseY, button);
for (Entry<Integer, ArrayList<GenericLayerT>> layerEntry : layers.entrySet()) {
var layerList = layerEntry.getValue();
for (var layerListIterator = 0; layerListIterator < layerList.size(); layerListIterator++) {
var layer = layerList.get(layerListIterator);
// Check to make sure scroll is within the context of the widget then deliver information
if (InBounds(layer.startX, layer.startY, layer.endX, layer.endY, (int) mouseX, (int) mouseY)) {
layer.mouseClicked(mouseX, mouseY, button);
}
}
}
return true;
}
/////////////////////////////////////////////////////////////////////////////
/// @fn DrawLayers
///
/// @arg[in] context is the global drawing context for the screen
///
/// @arg[in] delta is passed in from background draw
///
/// @brief This is the primary drawing function so that all the texture
/// draws can be done in one place in this class. We want as
/// little distance as possible between redraws when possible!
///
/// @note Currently the foreground is not drawn in the custom screen
/// manager. This is because the foreground features the general
/// inventory manager that this screen handler is based on and we
/// do not want to see those text pop ups.
/////////////////////////////////////////////////////////////////////////////
public void DrawLayers(DrawContext context, float delta) {
for (Entry<Integer, ArrayList<GenericLayerT>> layerEntry : layers.entrySet()) {
var layerList = layerEntry.getValue();
for (var layerListIterator = 0; layerListIterator < layerList.size(); layerListIterator++) {
var layer = layerList.get(layerListIterator);
System.out.println("Drawing layer " + layerEntry.getKey() + " for class type " + layer.getClass().toString());
layer.DrawLayer(context, layerEntry.getKey());
}
}
}
/////////////////////////////////////////////////////////////////////////////
/// @fn InBounds
///
/// @arg[in] initX is initial position of X axis
///
/// @arg[in] initY is initial position of Y axis
///
/// @arg[in] endX is the end position of X axis
///
/// @arg[in] endY is the end position of Y axis
///
/// @arg[in] x is the current X value we are comparing in the X axis
///
/// @arg[in] y is the current Y value we are comparing in the Y axis
///
/// @brief Checks if an x,y coordinate position falls within the bounds
/// of a bounded box
/////////////////////////////////////////////////////////////////////////////
private boolean InBounds(int initX, int initY, int endX, int endY, int x, int y) {
return (x >= initX && x <= endX) && (y >= initY && y <= endY);
}
/////////////////////////////////////////////////////////////////////////////
/// @fn drawBackground
///
/// @arg[in] context is the drawing context of super class
///
/// @arg[in] delta is the change in background draw
///
/// @arg[in] mouseX is the mouse x-axis position
///
/// @arg[in] mouseY is the mouse y-axis position
///
/// @brief This function is an abstract parent class and must be
/// implemented. This is "hijacked" and just being used as our
/// main drawing method of all the background images. There isn't
/// a huge difference of drawing our stuff in background vs the
/// foreground - except possibly foreground is drawn first.
/////////////////////////////////////////////////////////////////////////////
@Override
protected void drawBackground(DrawContext context, float delta, int mouseX, int mouseY) {
DrawLayers(context, delta);
}
}

View File

@ -1,165 +0,0 @@
/*
*
* TreeWidget
*
* Handles the skill tree widget
*
*
*/
package jesse.keeblarcraft.gui.widgets;
import jesse.keeblarcraft.Keeblarcraft;
import jesse.keeblarcraft.Utils.CommonStructures.Position2d;
import jesse.keeblarcraft.gui.GenericLayerT;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
public class TreeWidget extends GenericLayerT {
private static Identifier BACKGROUND_TEXTURE = new Identifier(Keeblarcraft.MOD_ID + ":" + "textures/gui/attribute_tree_background.png");
private static int maxHeight = 320;
private static int maxLength = 640;
private int zoomScale = 1;
// private static Identifier FLIGHT_ATTRIBUTE = new Identifier(Keeblarcraft.MOD_ID + ":" + "textures/gui/attribute_flight.png");
///TODO: Make this THE root node in the attribute tree! Rename in future
// private static Identifier EXAMPLE_NODE = new Identifier(Keeblarcraft.MOD_ID + ":" + "textures/gui/attribute_tree_example_node.png"); ///TODO: Make a way to make this programmatic (Proabably extend AbstractNode to carry this var)
/////////////////////////////////////////////////////////////////////////////
/// @fn TreeWidget
///
/// @brief Class constructor for constructing a tree widget. This will
/// be deprecated in a future version but exists for testing
/////////////////////////////////////////////////////////////////////////////
public TreeWidget() {
this(0, 0, 0, 0, Text.of("Test"));
System.out.println("Calling empty tree constructor");
}
/////////////////////////////////////////////////////////////////////////////
/// @fn TreeWidget
///
/// @brief Class constructor for constructing a tree widget
/////////////////////////////////////////////////////////////////////////////
public TreeWidget(int x, int y, int width, int height, Text message) {
super(x, y, width, height, message);
this.startX = x;
this.startY = y;
this.endX = x + width;
this.endY = y + height;
}
/////////////////////////////////////////////////////////////////////////////
/// @fn renderButton
///
/// @param[in] context is the drawing pane
///
/// @param[in] x is the X position to draw at
///
/// @param[in] y is the Y position to draw at
///
/// @param[in] delta is unused in this version
///
/// @brief Primary call to draw the GUI for this widget
/////////////////////////////////////////////////////////////////////////////
@Override
public void renderButton(DrawContext context, int x, int y, float delta) {
context.drawTexture(BACKGROUND_TEXTURE, x, y, 0, 0, maxLength, maxHeight, maxLength, maxHeight);
}
/////////////////////////////////////////////////////////////////////////////
/// @fn appendClickableNarrations
///
/// @param[in] builder is the narration builder. This is pure virtual in
/// the parent but is unused in this widget currently
///
/// @brief Handles the narrator
/////////////////////////////////////////////////////////////////////////////
@Override
protected void appendClickableNarrations(NarrationMessageBuilder builder) {
return;
}
/////////////////////////////////////////////////////////////////////////////
/// @fn mouseClicked
///
/// @param[in] mouseX is where on the x-axis the mouse was clicked
///
/// @param[in] mouseY is where on the y-axis the mouse was clicked
///
/// @param[in] button is the button clicked with (think of a mouse...)
///
/// @brief Handler for mouse click events
/////////////////////////////////////////////////////////////////////////////
@Override
public boolean mouseClicked(double mouseX, double mouseY, int button) {
return true;
}
/////////////////////////////////////////////////////////////////////////////
/// @fn mouseDragged
///
/// @param[in] mouseX is where on the x-axis the mouse was dragged
///
/// @param[in] mouseY is where on the y-axis the mouse was dragged
///
/// @param[in] button is the button dragged with (think of a mouse...)
///
/// @brief Handler for mouse drag events. delta's unused currently
/////////////////////////////////////////////////////////////////////////////
@Override
public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) {
boolean ret = false;
if (this.isValidClickButton(button)) {
// Do camera panning magic stuff here
ret = true;
}
return ret;
}
/////////////////////////////////////////////////////////////////////////////
/// @fn mouseDragged
///
/// @param[in] mouseX is where on the x-axis the mouse was dragged
///
/// @param[in] mouseY is where on the y-axis the mouse was dragged
///
/// @param[in] amount represents scroll direction. If the value is negative
/// we scale out. If positive, we scale in
///
/// @brief Handler for mouse scroll events
/////////////////////////////////////////////////////////////////////////////
@Override
public boolean mouseScrolled(double mouseX, double mouseY, double amount) {
// Zooming INWARDS on scroll wheel produces 1.0 (which means zoom in)
// Zooming BACKWARDS on scroll wheel produces -1.0 (which means zoom out)
// We enforce a max scroll of 10 in either direction here
if (amount > 0 && zoomScale <= 10) {
// Zoom in
zoomScale++;
} else if (amount < 0 && zoomScale >= -10) {
// Zoom out
zoomScale--;
}
return true;
}
/////////////////////////////////////////////////////////////////////////////
/// @fn DrawLayer
///
/// @param[in] context is the drawing pane
///
/// @param[in] layer is the layer in which this widget is being drawn in
///
/// @brief This calls renderButton and gives it the valid drawing
/// context to use. This function is called by a ScreenManager<T>
/////////////////////////////////////////////////////////////////////////////
@Override
public void DrawLayer(DrawContext context, int layer) {
Position2d pos = GetScreenCenter();
this.renderButton(context, pos.x - (maxLength / 2), pos.y - (maxHeight / 2), 0);
}
}

View File

@ -0,0 +1,15 @@
package jesse.keeblarcraft.mixin.client;
import net.minecraft.client.MinecraftClient;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(MinecraftClient.class)
public class ExampleClientMixin {
@Inject(at = @At("HEAD"), method = "run")
private void init(CallbackInfo info) {
// This code is injected into the start of MinecraftClient.run()V
}
}

View File

@ -0,0 +1,11 @@
{
"required": true,
"package": "jesse.keeblarcraft.mixin.client",
"compatibilityLevel": "JAVA_21",
"client": [
"ExampleClientMixin"
],
"injectors": {
"defaultRequire": 1
}
}

View File

@ -25,11 +25,11 @@ public class MetalJacketArmor implements ArmorMaterial {
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) { // All from ArmorItem.Type
case BOOTS -> Integer.MAX_VALUE;
case LEGGINGS -> Integer.MAX_VALUE;
case CHESTPLATE -> Integer.MAX_VALUE;
case HELMET -> Integer.MAX_VALUE;
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;
};
}
@ -40,10 +40,10 @@ public class MetalJacketArmor implements ArmorMaterial {
// 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 BOOTS -> defaultArmorModifier;
case HELMET -> defaultArmorModifier;
case LEGGINGS -> defaultArmorModifier;
case CHESTPLATE -> defaultArmorModifier;
case ArmorItem.Type.BOOTS -> defaultArmorModifier;
case ArmorItem.Type.HELMET -> defaultArmorModifier;
case ArmorItem.Type.LEGGINGS -> defaultArmorModifier;
case ArmorItem.Type.CHESTPLATE -> defaultArmorModifier;
};
}

View File

@ -17,69 +17,44 @@ import jesse.keeblarcraft.AttributeMgr.AttributeNodes.AttributeFlight;
import jesse.keeblarcraft.AttributeMgr.AttributeNodes.AttributeMetalJacket;
import jesse.keeblarcraft.ConfigMgr.ConfigManager;
import jesse.keeblarcraft.Utils.ChatUtil;
import net.minecraft.server.network.ServerPlayerEntity;
public class AttributeMgr {
ConfigManager config;
// Global list of attributes
// Key: node title
// Val: The node class itself
public static final HashMap<String, Class<? extends AbstractNode>> attributes = new HashMap<String, Class<? extends AbstractNode>>();
public static final HashMap<String, AbstractNode> attributes = new HashMap<String, 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;
AbstractNode test;
ChatUtil.LoggerColored("Registring attribute called", ChatUtil.CONSOLE_COLOR.CYAN, Keeblarcraft.LOGGER);
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");
test = classObj.newInstance();
if (attributes.containsKey(test.GetNodeTitle())) {
Keeblarcraft.LOGGER.warn("Could not register attribute with duplicate name '" + test.GetNodeTitle() + "'");
} else {
ChatUtil.LoggerColored("REGISTERING ATTRIBUTE " + test.GetNodeTitle(), ChatUtil.CONSOLE_COLOR.YELLOW, Keeblarcraft.LOGGER);
attributes.put(test.GetNodeTitle(), test);
}
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
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");
}
AbstractNode node = attributes.get(attributeName);
if (playerTree != null && node != null) {
if (playerTree != null) {
///////////
// debug testing
String isNull = (node == null ? "NULL" : "NOT NULL");
@ -99,18 +74,9 @@ public class AttributeMgr {
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
/// hint: make it an API for other modders to add to
RegisterAttributeClass(AttributeFlight.class);
RegisterAttributeClass(AttributeMetalJacket.class);

View File

@ -13,6 +13,7 @@ import java.util.HashMap;
import java.util.List;
abstract public class AbstractNode {
/////////////////////////////////////////////////////////////////////////////
/// @fn GetNodeTitle
///

View File

@ -12,14 +12,13 @@ package jesse.keeblarcraft.AttributeMgr.AttributeNodes;
import java.util.HashMap;
import java.util.List;
import jesse.keeblarcraft.Keeblarcraft;
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() {
}
@ -49,20 +48,16 @@ public class AttributeFlight extends AbstractNode {
@Override
public void RegisterCallbacks() {
// Register events here
if (registeredHitCallback == false) {
AttackBlockCallback.EVENT.register((player, world, hand, pos, direction) -> {
BlockState state = world.getBlockState(pos);
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);
}
Keeblarcraft.LOGGER.info("Callback for AttackBlockCallback called");
// 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;
return ActionResult.PASS;
});
}
}

View File

@ -27,13 +27,8 @@ public class AttributeTree {
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;
@ -53,13 +48,24 @@ public class AttributeTree {
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
/////////////////////////////////////////////////////////////////////////////
// This will enable the node registration of callbacks on any nodes thats level is not 0
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");
}
}
}
}
// Separate structure as this is written to the config file
private class PlayerTree {
String uuid;
// Key = name of AbstractNode
@ -67,12 +73,6 @@ public class AttributeTree {
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() {
@ -98,52 +98,14 @@ public class AttributeTree {
}
}
/////////////////////////////////////////////////////////////////////////////
/// @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
/////////////////////////////////////////////////////////////////////////////
// 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)
//
// 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());
@ -173,7 +135,6 @@ 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();
}
} else {
@ -190,16 +151,6 @@ public class AttributeTree {
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);
@ -212,13 +163,6 @@ public class AttributeTree {
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()) {
@ -228,13 +172,6 @@ public class AttributeTree {
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;
@ -247,24 +184,11 @@ public class AttributeTree {
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
// Returns the player's attribute tree
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
@ -303,15 +227,8 @@ public class AttributeTree {
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);

View File

@ -0,0 +1,44 @@
/*
*
* AbstractNode
*
* This is the general definition of everything that is allowed inside a node and is called by our system
*
*
*/
package jesse.keeblarcraft.AttributeMgr.Nodes;
import java.util.HashMap;
import java.util.List;
abstract public class AbstractNode {
/////////////////////////////////////////////////////////////////////////////
/// @fn GetNodeTitle
///
/// @brief The title of your node/skill!
/////////////////////////////////////////////////////////////////////////////
abstract String GetNodeTitle();
/////////////////////////////////////////////////////////////////////////////
/// @fn GetNodeDescription
///
/// @brief This will become the hover-over text display of a skill in
/// the skill tree
/////////////////////////////////////////////////////////////////////////////
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
/////////////////////////////////////////////////////////////////////////////
abstract HashMap<String, List<String>> GetDetails();
}

View File

@ -0,0 +1,51 @@
package jesse.keeblarcraft.AttributeMgr.Nodes;
import java.util.HashMap;
import java.util.List;
import jesse.keeblarcraft.Armor.MetalJacketArmor;
import jesse.keeblarcraft.CustomItems.ItemManager;
import net.minecraft.item.ArmorItem;
import net.minecraft.item.Item;
public final class MetalJacket_Node 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 MetalJacket_Node() {
// Finally register items with game
ItemManager.RegisterItem("metaljacket_helmet",jacketHelm);
ItemManager.RegisterItem("metaljacket_chestplate",jacketChest);
ItemManager.RegisterItem("metaljacket_leggings",jacketLegs);
ItemManager.RegisterItem("metaljacket_boots",jacketBoots);
}
@Override
String GetNodeTitle() {
return "MetalJacket";
}
// Short description of node on hover-event in GUI
@Override
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
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;
}
}

View File

@ -0,0 +1,4 @@
package jesse.keeblarcraft.AttributeMgr;
public class SkillTree {
}

View File

@ -1,5 +0,0 @@
package jesse.keeblarcraft.CCTweakedExtension;
public class CCTweakedTest {
}

View File

@ -27,49 +27,66 @@ import net.minecraft.text.Text;
public class AttributeCommands {
public void RegisterCommands() {
// Command Root: "/attributes"
// Subcommands: "apply <name> <attributename>", "remove <name> <attributename>"
// Command Root: "/attributes apply <username> <attribute name>"
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 applySubnode = CommandManager.literal("apply").build();
var playerArgAdd = CommandManager.argument("targetPlayer", EntityArgumentType.player()).build();
var playerArgRemove = CommandManager.argument("targetPlayer", EntityArgumentType.player()).build();
var playerArg = CommandManager.argument("targetPlayer", EntityArgumentType.player()).build();
var attributeNameAdd = CommandManager.argument("attributeName", StringArgumentType.greedyString())
var attributeNameArg = 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)
)
(
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);
attributeNode.addChild(applySubnode);
applySubnode.addChild(playerArg);
playerArg.addChild(attributeNameArg);
});
// Subcommands "/apply playerArg", "/remove playerArg"
applyNode.addChild(playerArgAdd);
removeNode.addChild(playerArgRemove);
// Command Root: "/attributes remove <username> <attribute name>"
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
var attributeNode = CommandManager.literal("attributes").build();
// name argument
playerArgAdd.addChild(attributeNameAdd);
playerArgRemove.addChild(attributeNameDelete);
var applySubnode = CommandManager.literal("delete").build();
var playerArg = CommandManager.argument("targetPlayer", EntityArgumentType.player()).build();
var attributeNameArg = 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(applySubnode);
applySubnode.addChild(playerArg);
playerArg.addChild(attributeNameArg);
});
// Command Root: "/attribute-test <attribute_name>"
/// TODO: Remove this in final version. This is purely debug
// CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
// dispatcher.register(CommandManager.literal("attribute-test")
// .then(CommandManager.argument("value", StringArgumentType.greedyString())
// .executes(context -> ApplyAttribute(StringArgumentType.getString(context, "value"), context))));
// });
// Command Root: "/list-attributes"
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
dispatcher.register(CommandManager.literal("list-attributes")
.executes(context -> ListAttributes(context)));
});
}
@ -79,7 +96,8 @@ public class AttributeCommands {
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(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;
@ -102,8 +120,8 @@ public class AttributeCommands {
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());
for (Entry<String, AbstractNode> entry : AttributeMgr.attributes.entrySet()) {
Keeblarcraft.LOGGER.debug("ATTR-LIST: " + entry.getKey() + " LINKS " + entry.getValue().GetNodeTitle());
player.sendMessage(Text.of(entry.getKey()));
}
}

View File

@ -1,8 +1,12 @@
package jesse.keeblarcraft.Commands;
import java.util.UUID;
import com.mojang.brigadier.arguments.ArgumentType;
import com.mojang.brigadier.arguments.IntegerArgumentType;
import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.datafixers.Products.P1;
import jesse.keeblarcraft.ConfigMgr.ConfigManager;
import jesse.keeblarcraft.JsonClassObjects.PlayerNote;
@ -15,16 +19,13 @@ import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.server.network.ServerPlayerEntity;
public class NoteCommands {
/// Class Variables
// IMPORTANT NOTE:
//
// Each player will retain their own private file of notes inside a "notes" directory inside the overall mod config directory
ConfigManager notesConfig = new ConfigManager();
String NOTES_GLOBAL_DIRECTORY = "notes"; // The overall "notes" dir inside cfg folder
/////////////////////////////////////////////////////////////////////////////
/// @fn NoteCommands
///
/// @brief This classes non-trivial constructor. Ensures creation
// of notes directory exists before commands can be ran
/////////////////////////////////////////////////////////////////////////////
public NoteCommands() {
// Check if directory exists
if (notesConfig.DoesDirectoryExist(NOTES_GLOBAL_DIRECTORY) == false) {
@ -43,11 +44,6 @@ public class NoteCommands {
}
}
/////////////////////////////////////////////////////////////////////////////
/// @fn RegisterNoteCommands
///
/// @brief Registers all the commands for this class
/////////////////////////////////////////////////////////////////////////////
public void RegisterNoteCommands() {
// Command: "/addnote note goes here"
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
@ -66,21 +62,15 @@ public class NoteCommands {
// Command: "/purgenotes"
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
dispatcher.register(CommandManager.literal("purgenotes")
.executes(context -> PurgeAllNotes(context)));
.then(CommandManager.argument("value", StringArgumentType.greedyString())
.executes(context -> PurgeAllNotes(StringArgumentType.getString(context, "value"), context))));
});
// Command: "/modifynote noteIdHere new_note_string_here"
// Alises: "/editnote"
// Command: "/modifynote noteIdHere"
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
final var mNote = dispatcher.register(CommandManager.literal("editnote")
.then(CommandManager.argument("note_id", IntegerArgumentType.integer())
.then(CommandManager.argument("new_note", StringArgumentType.string())
.executes(context -> ModifyNote(
IntegerArgumentType.getInteger(context, "note_id"),
StringArgumentType.getString(context, "new_note"),
context)))));
dispatcher.register(CommandManager.literal("editnote").redirect(mNote));
dispatcher.register(CommandManager.literal("editnote")
.then(CommandManager.argument("value", IntegerArgumentType.integer())
.executes(context -> ModifyNote(IntegerArgumentType.getInteger(context, "value"), context))));
});
// Command Root: "/delnote noteIdHere"
@ -94,39 +84,14 @@ public class NoteCommands {
dispatcher.register(CommandManager.literal("rmnote").redirect(rootDeleteCmd));
dispatcher.register(CommandManager.literal("deletenote").redirect(rootDeleteCmd));
});
// Command Root: "/notegui"
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
dispatcher.register(CommandManager.literal("notegui")
.executes(context -> { OpenNoteGui(context);
return 0;
}));
});
// Command Root: "/notelist"
// Aliases: "/listnotes"
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
final var rootListNotes = dispatcher.register(CommandManager.literal("notelist")
.executes(context -> { ListNotes(context);
return 0;
}));
dispatcher.register(CommandManager.literal("listnotes").redirect(rootListNotes));
});
}
/////////////////////////////////////////////////////////////////////////////
/// @fn AddNote
///
/// @brief Adds a new note to the players notebook
///
/// @arg[in] value is the new note to be added
///
/// @arg[in] context is the context of the ServerCommandSource object
/// the command was run with
///
/// @return 0 if success, -1 if not
/////////////////////////////////////////////////////////////////////////////
/// COMMAND HANDLERS BELOW
// AddNote
//
// Adds a new note based on the string value provided by the player. The note is labeled in the background based on the portion
// of the story they are currently in as well to help provide filtering methods later on
private Integer AddNote(String value, CommandContext<ServerCommandSource> context) {
Integer ret = -1;
@ -146,156 +111,39 @@ public class NoteCommands {
return ret;
}
/////////////////////////////////////////////////////////////////////////////
/// @fn DeleteNote
///
/// @brief Deletes a note by id
///
/// @arg[in] value is the integer ID of the note to be deleted
///
/// @arg[in] context is the context of the ServerCommandSource object
/// the command was run with
///
/// @return 0 if success, -1 if not
/////////////////////////////////////////////////////////////////////////////
private int DeleteNote(int value, CommandContext<ServerCommandSource> context) {
int ret = -1;
if (context.getSource().isExecutedByPlayer()) {
ServerPlayerEntity player = context.getSource().getPlayer();
return ret;
}
PlayerNote note = new PlayerNote(player.getUuidAsString());
ChatUtil.SendPlayerMsg(player, "Deleted note entry. View notes any time with /notegui");
ret = 0;
note.DeleteNote(value);
} else {
System.out.println("Only a player can execute this command!");
}
private int ModifyNote(int value, CommandContext<ServerCommandSource> context) {
int ret = -1;
return ret;
}
/////////////////////////////////////////////////////////////////////////////
/// @fn ModifyNote
///
/// @brief Modifies a single note by id value
///
/// @arg[in] value is the integer ID of the note to be modified
///
/// @arg[in] newNote is the new version of the edited note
///
/// @arg[in] context is the context of the ServerCommandSource object
/// the command was run with
///
/// @return 0 if success, -1 if not
/////////////////////////////////////////////////////////////////////////////
private int ModifyNote(Integer value, String newNote, CommandContext<ServerCommandSource> context) {
private int PurgeAllNotes(String value, CommandContext<ServerCommandSource> context) {
int ret = -1;
if (context.getSource().isExecutedByPlayer() && value > 0) {
ServerPlayerEntity player = context.getSource().getPlayer();
PlayerNote note = new PlayerNote(player.getUuidAsString());
long time = context.getSource().getWorld().getTime();
// long day = ; ///TODO: Docs lack this for some reason? Add in future
long epochTime = System.currentTimeMillis();
long storyChapter = -1; // Intentional garbage until story is fleshed out later (TODO)
long storyPart = -1; // Intentional garbage until story is fleshed out later (TODO)
note.ModifyNote(value, newNote, epochTime, storyChapter, storyPart);
ChatUtil.SendPlayerMsg(player, "Modified note entry. View notes any time with /notegui");
ret = 0;
}
return ret;
}
/////////////////////////////////////////////////////////////////////////////
/// @fn PurgeAllNotes
///
/// @brief Removes all notes from a players note file
///
/// @arg[in] context is the context of the ServerCommandSource object
/// the command was run with
///
/// @return 0 if success, -1 if not
/////////////////////////////////////////////////////////////////////////////
private int PurgeAllNotes(CommandContext<ServerCommandSource> context) {
private int ListNotes(String value, CommandContext<ServerCommandSource> context) {
int ret = -1;
if (context.getSource().isExecutedByPlayer()) {
ServerPlayerEntity player = context.getSource().getPlayer();
PlayerNote note = new PlayerNote(player.getUuidAsString());
note.PurgeAllNotes();
ChatUtil.SendPlayerMsg(player, "Purged all notes. View notes any time with /notegui");
ret = 0;
} else {
System.out.println("Only a player can execute this command!");
}
return ret;
}
/////////////////////////////////////////////////////////////////////////////
/// @fn ListNotes
///
/// @brief Lists notes in pages in the players active chat
///
/// @arg[in] context is the context of the ServerCommandSource object
/// the command was run with
///
/// @return 0 if success, -1 if not
/////////////////////////////////////////////////////////////////////////////
private int ListNotes(CommandContext<ServerCommandSource> context) {
private int OpenNoteGui(String value, CommandContext<ServerCommandSource> context) {
int ret = -1;
if (context.getSource().isExecutedByPlayer()) {
ServerPlayerEntity player = context.getSource().getPlayer();
PlayerNote notes = new PlayerNote(player.getUuidAsString());
ChatUtil.SendPlayerMsg(player, "Listing all notes...");
for (int i = 0; i <= notes.GetNotebookSize(); i++) {
String individualNote = notes.GetNoteString(i);
if (individualNote != "") {
ChatUtil.SendPlayerMsg(player, "Note " + i + ": " + individualNote);
}
}
ret = 0;
} else {
System.out.println("Only a player can execute this command!");
}
return ret;
}
///TODO: Blocked until GUI manager is available
/////////////////////////////////////////////////////////////////////////////
/// @fn OpenNoteGui
///
/// @brief Opens up the graphical display of the note manager
///
/// @arg[in] context is the context of the ServerCommandSource object
/// the command was run with
///
/// @return 0 if success, -1 if not
/////////////////////////////////////////////////////////////////////////////
private int OpenNoteGui(CommandContext<ServerCommandSource> context) {
private int FilterForNote(String value, CommandContext<ServerCommandSource> context) {
int ret = -1;
if (context.getSource().isExecutedByPlayer()) {
ServerPlayerEntity player = context.getSource().getPlayer();
ret = 0;
} else {
System.out.println("Only a player can execute this command!");
}
return ret;
}
}

View File

@ -19,7 +19,6 @@ import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
import net.minecraft.entity.player.PlayerAbilities;
import net.minecraft.server.command.CommandManager;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.server.command.TimeCommand;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.Text;
@ -65,20 +64,6 @@ public class ShortcutCommands {
return 0;
}));
});
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
dispatcher.register(CommandManager.literal("day")
.executes(context -> { DayShortcut(context);
return 0;
}));
});
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
dispatcher.register(CommandManager.literal("night")
.executes(context -> { NightShortcut(context);
return 0;
}));
});
}
/// Command handlers below
@ -225,35 +210,4 @@ public class ShortcutCommands {
return retValue;
}
private int DayShortcut(CommandContext<ServerCommandSource> context) {
int retValue = -1;
if (context.getSource().isExecutedByPlayer()) {
ServerPlayerEntity player = context.getSource().getPlayer();
if (player.hasPermissionLevel(4)) {
retValue=0;
TimeCommand.executeSet(context.getSource(), retValue);
} else {
player.sendMessage(Text.literal("You do not have permission for this command"));
}
}
return retValue;
}
private int NightShortcut(CommandContext<ServerCommandSource> context) {
int retValue = -1;
if (context.getSource().isExecutedByPlayer()) {
ServerPlayerEntity player = context.getSource().getPlayer();
if (player.hasPermissionLevel(4)) {
retValue=13000;
TimeCommand.executeSet(context.getSource(), retValue);
} else {
player.sendMessage(Text.literal("You do not have permission for this command"));
}
}
return retValue;
}
}

View File

@ -171,11 +171,15 @@ public class ConfigManager {
}
public Boolean DoesFileExist(String fileName) {
return new File(fileName).exists(); // untested
Boolean ret = false;
return ret;
}
public Boolean DoesDirectoryExist(String dirName) {
return new File(dirName).isDirectory(); // untested
Boolean ret = false;
return ret;
}
public Boolean CreateDirectory(String dirName) throws DIRECTORY_CREATE_EXCEPTION {

View File

@ -1,24 +0,0 @@
package jesse.keeblarcraft.CustomBlocks;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import net.minecraft.block.AbstractBlock;
import net.minecraft.block.Block;
import net.minecraft.block.Blocks;
import net.minecraft.block.ExperienceDroppingBlock;
import net.minecraft.sound.BlockSoundGroup;
import net.minecraft.util.math.intprovider.UniformIntProvider;
// Put all your blocks here
public class BlockList {
/////////////////////////////////////////////////////////////////////////////
/// @fn RegisterBlocks
///
/// @brief This function is called by the main thread to register all
/// block objects. Please register your blocks here
/////////////////////////////////////////////////////////////////////////////
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)));
}
}

View File

@ -9,23 +9,29 @@
package jesse.keeblarcraft.CustomBlocks;
import java.util.HashMap;
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.MapColor;
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>();
public static final HashMap<String, Block> blockList = new HashMap<String, Block>();
public static final List<Block> blockList = new ArrayList<Block>();
/////////////////////////////////////////////////////////////////////////////
/// @fn RegisterBlock
@ -51,18 +57,105 @@ public class BlockManager {
Block newBlock = Registry.register(Registries.BLOCK, new Identifier(Keeblarcraft.MOD_ID, name), block);
// Add the block to the block list
blockList.put(name, newBlock);
blockList.add(newBlock);
}
/////////////////////////////////////////////////////////////////////////////
/// @fn GetBlock
/// @fn RegisterBlocks
///
/// @brief Gets a block from the block list by name
///
/// @return Returns a block from the blockList object if name is found,
/// will return null if not found
/// @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 Block GetBlock(String name) {
return blockList.get(name);
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);
RegisterBlock("money_block", MONEY_BLOCK);
RegisterBlock("cent_coin", CENT_COIN);
RegisterBlock("5_cent_coin", FIVE_CENT_COIN);
RegisterBlock("10_cent_coin", TEN_CENT_COIN);
RegisterBlock("25_cent_coin", TWENTY_FIVE_CENT_COIN);
RegisterBlock("1_dollar", ONE_DOLLAR);
RegisterBlock("5_dollar", FIVE_DOLLAR);
RegisterBlock("10_dollar", TEN_DOLLAR);
RegisterBlock("20_dollar", TWENTY_DOLLAR);
}
////CUSTOM BLOCKS BELOW
public static final Block MONEY_BLOCK = new MoneyBlock(FabricBlockSettings.create()
.mapColor(MapColor.GOLD)
.requiresTool()
.strength(5.0F, 6.0F)
.sounds(BlockSoundGroup.METAL)
.luminance(100));
////CENT COIN
public static final Block CENT_COIN = new Block(FabricBlockSettings.create()
.mapColor(MapColor.GOLD)
.breakInstantly()
.noCollision()
.nonOpaque()
.sounds(BlockSoundGroup.METAL));
////5_CENT_COIN
public static final Block FIVE_CENT_COIN = new Block(FabricBlockSettings.create()
.mapColor(MapColor.GOLD)
.breakInstantly()
.noCollision()
.nonOpaque()
.sounds(BlockSoundGroup.METAL));
////10_CENT_COIN
public static final Block TEN_CENT_COIN = new Block(FabricBlockSettings.create()
.mapColor(MapColor.GOLD)
.breakInstantly()
.noCollision()
.nonOpaque()
.sounds(BlockSoundGroup.METAL));
////25_CENT_COIN
public static final Block TWENTY_FIVE_CENT_COIN = new Block(FabricBlockSettings.create()
.mapColor(MapColor.GOLD)
.breakInstantly()
.noCollision()
.nonOpaque()
.sounds(BlockSoundGroup.METAL));
////25_CENT_COIN
public static final Block ONE_DOLLAR = new Block(FabricBlockSettings.create()
.mapColor(MapColor.GOLD)
.breakInstantly()
.noCollision()
.nonOpaque()
.sounds(BlockSoundGroup.METAL));
////25_CENT_COIN
public static final Block FIVE_DOLLAR = new Block(FabricBlockSettings.create()
.mapColor(MapColor.GOLD)
.breakInstantly()
.noCollision()
.nonOpaque()
.sounds(BlockSoundGroup.METAL));
////25_CENT_COIN
public static final Block TEN_DOLLAR = new Block(FabricBlockSettings.create()
.mapColor(MapColor.GOLD)
.breakInstantly()
.noCollision()
.nonOpaque()
.sounds(BlockSoundGroup.METAL));
////25_CENT_COIN
public static final Block TWENTY_DOLLAR = new Block(FabricBlockSettings.create()
.mapColor(MapColor.GOLD)
.breakInstantly()
.noCollision()
.nonOpaque()
.sounds(BlockSoundGroup.METAL));
}

View File

@ -0,0 +1,13 @@
package jesse.keeblarcraft.CustomBlocks;
import net.minecraft.block.Block;
//Testing to make a money block the idea is to be able to put the money in your bank at somepoint
public class MoneyBlock extends Block {
// CommonServerUtils commonServerUtils = new CommonServerUtils();
public MoneyBlock(Settings sett) {
super(sett);
}
}

View File

@ -1,11 +1,8 @@
package jesse.keeblarcraft.CustomItems;
import java.util.Map.Entry;
import jesse.keeblarcraft.Keeblarcraft;
import jesse.keeblarcraft.CustomBlocks.BlockManager;
import net.fabricmc.fabric.api.itemgroup.v1.FabricItemGroup;
import net.minecraft.block.Block;
import net.minecraft.item.ItemGroup;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
@ -27,8 +24,8 @@ public class CustomItemGroups {
}
// We iterate through all the modded blocks and add them to the custom block group here
for(Entry<String, Block> blocks : BlockManager.blockList.entrySet()) {
entries.add(blocks.getValue());
for (int i = 0; i < BlockManager.blockList.size(); i++) {
entries.add(BlockManager.blockList.get(i));
}
}).build());

View File

@ -14,6 +14,10 @@ import java.util.ArrayList;
import java.util.List;
import jesse.keeblarcraft.Keeblarcraft;
import jesse.keeblarcraft.CustomBlocks.MoneyBlock;
import net.fabricmc.fabric.api.item.v1.FabricItemSettings;
import net.minecraft.block.Block;
import net.minecraft.item.BlockItem;
import net.minecraft.item.Item;
import net.minecraft.registry.Registries;
import net.minecraft.registry.Registry;
@ -47,6 +51,11 @@ public class ItemManager {
itemList.add(newItem);
}
public static void RegisterBlockItem(String name, BlockItem blockitem) {
Item newItem = Registry.register(Registries.ITEM, new Identifier(Keeblarcraft.MOD_ID, name), blockitem);
itemList.add(newItem);
}
/////////////////////////////////////////////////////////////////////////////
/// @fn RegisterAllItems
///
@ -65,5 +74,4 @@ public class ItemManager {
// Item exampleItem = new Item(new FabricItemSettings());
// RegisterItem("metaljacket_helmet", exampleItem);
}
}

View File

@ -1,3 +1,4 @@
package jesse.keeblarcraft.EventMgr;
import jesse.CommonServerUtils;

View File

@ -0,0 +1,13 @@
/*
*
* GuiMgr
*
* Handles everything related to in-game gui environments
*
*/
package jesse.keeblarcraft.GuiMgr;
public class GuiMgr {
}

View File

@ -1,86 +0,0 @@
package jesse.keeblarcraft.GuiMgr;
import jesse.keeblarcraft.Keeblarcraft;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.inventory.Inventory;
import net.minecraft.inventory.SimpleInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.screen.ScreenHandler;
// Server side screen handler for the attribute tree
public class TreeHandler extends ScreenHandler {
/////////////////////////////////////////////////////////////////////////////
/// @fn TreeHandler
///
/// @arg[in] syncId is SUPPOSED to be some sync identifier between the
/// server and client. This isn't being used yet, so there isn't
/// enough knowledge to make a good documentation note on it.
/// Coming soon!
///
/// @arg[in] inventory is the players inventory. Required by HandledScreen
/// object however is unused currently so we make the size 0. As
/// needs and use-cases change; this may be reworked in the future
///
/// @brief Class constructor
/////////////////////////////////////////////////////////////////////////////
public TreeHandler(int syncId, PlayerInventory inventory) {
// Call the constructor below
this(syncId, inventory, new SimpleInventory(0));
}
/////////////////////////////////////////////////////////////////////////////
/// @fn TreeHandler
///
/// @arg[in] syncId is SUPPOSED to be some sync identifier between the
/// server and client. This isn't being used yet, so there isn't
/// enough knowledge to make a good documentation note on it.
/// Coming soon!
///
/// @arg[in] inventory is the players inventory. Required by HandledScreen
/// object however is unused currently so we make the size 0. As
/// needs and use-cases change; this may be reworked in the future
///
/// @arg[in] inventory is the SERVER's inventory - which is what syncId
/// would likely be useful for. Once I (Jesse) get the screen stuff
/// more sorted out - a more useful doxygen comment will be applied
/// here in this class. Coming soon!
///
/// @brief Class constructor
/////////////////////////////////////////////////////////////////////////////
public TreeHandler(int syncId, PlayerInventory playerInventory, Inventory inventory) {
super(Keeblarcraft.TREE_HANDLER, syncId);
System.out.println("Created tree handler");
System.out.println("Is static var null? " + Keeblarcraft.TREE_HANDLER == null ? "YES":"NO");
}
/////////////////////////////////////////////////////////////////////////////
/// @fn quickMove
///
/// @arg[in] player is the player entity moving an item
///
/// @arg[in] slot is the inventory slot to quick move to (shift+click)
///
/// @brief Required by parent class; currently do nothing as we aren't
/// using inventories in the gui's!
/////////////////////////////////////////////////////////////////////////////
@Override
public ItemStack quickMove(PlayerEntity player, int slot) {
return ItemStack.EMPTY;
}
/////////////////////////////////////////////////////////////////////////////
/// @fn canUse
///
/// @arg[in] player is the player entity moving an item
///
/// @brief Returns whether the screen handler can be used. Required by
/// parent class as its abstract; but for now players can always
/// use GUI's and need no confirmation!
/////////////////////////////////////////////////////////////////////////////
@Override
public boolean canUse(PlayerEntity player) {
return true;
}
}

View File

@ -16,25 +16,13 @@ import jesse.keeblarcraft.Utils.ChatUtil.CONSOLE_COLOR;
import jesse.keeblarcraft.Utils.CustomExceptions.FILE_WRITE_EXCEPTION;
public class PlayerNote {
/// Class variables
NoteFile thisNote = new NoteFile();
ConfigManager config = new ConfigManager();
/////////////////////////////////////////////////////////////////////////////
/// @class NoteMetadata
///
/// @brief The metadata that is attached to each entry in the notebook.
/// This includes not just the note itself, but other important
/// factors that can be characteristic to each note and useful
///
/// @note You can picture this as each page in the notebook if it's
/// an easier mental image
/////////////////////////////////////////////////////////////////////////////
// Internal class structure that defines a blank note. It represents the overall loaded json object
private class NoteMetadata {
public NoteMetadata(String note, long id, /*long mcday,*/ long sysTime, long chapter, long part) {
public NoteMetadata(String note, long id, long mcday, long sysTime, long chapter, long part) {
this.note = note;
this.noteId = id;
// this.minecraftDay = mcday;
this.minecraftDay = mcday;
this.systemTime = sysTime;
this.storyChapter = chapter;
this.storyPart = part;
@ -43,32 +31,50 @@ public class PlayerNote {
String note; // The note itself
long noteId; // Copied in from the file name, noteId
// long minecraftDay; // The minecraft day the note was taken on
long minecraftDay; // The minecraft day the note was taken on
long systemTime; // The current system time of the server
long storyChapter; // The chapter of the story the player is in
long storyPart; // Every event in a story is one part
}
/////////////////////////////////////////////////////////////////////////////
/// @class NoteFile
///
/// @brief This is the notebook
/////////////////////////////////////////////////////////////////////////////
public class NoteFile {
// the uuid is the name of the file written to disk
// Players uuid is the name of the file
String uuid;
// Contents of file
/*
* Example:
* player_uuid_here:
* {
* "1":
* {
* "note": "this is the players first note";
* "noteId": "1";
* "minecraftDay": "443";
* "systemTime": "4849892839823";
* "storyChapter": "3";
* "storyPart": "2";
* }
* "2":
* {
* Etc.
* }
* }
*/
public HashMap<Integer, NoteMetadata> noteMap = new HashMap<Integer, NoteMetadata>();
}
/////////////////////////////////////////////////////////////////////////////
/// @fn PlayerNote
///
/// @brief This class's non-trivial constructor. Grabs a handle on the
/// server-side file that is the players notebook at object
/// creation. If one does not exist, one is created
///
/// @arg[in] uuid is the players uuid value
/////////////////////////////////////////////////////////////////////////////
NoteFile thisNote = new NoteFile();
ConfigManager config = new ConfigManager();
class TestClass {
String testString;
}
// PlayerNote
//
// String uuid - The uuid of the player (used in searching for existing notes file and writing to it)
public PlayerNote(String uuid) {
// DEVELOPER NOTE:
@ -105,114 +111,23 @@ public class PlayerNote {
}
}
/////////////////////////////////////////////////////////////////////////////
/// @fn AddNote
///
/// @brief Adds a new note to the notebook
///
/// @arg[in] newNote is the new string value of the note
///
/// @arg[in] minecraftDay is currently unsupported but will be the day of
/// the minecraft world when it is implemented
///
/// @arg[in] systemTime is the epoch time in milliseconds
///
/// @arg[in] storyChapter is the chapter in the story this note was taken
///
/// @arg[in] storyPart is the part in the chapter the note was taken
/////////////////////////////////////////////////////////////////////////////
public void AddNote(String newNote, long minecraftDay, long systemTime, long storyChapter, long storyPart) {
Integer noteKey = thisNote.noteMap.size() + 1;
thisNote.noteMap.put(noteKey, new NoteMetadata(newNote, noteKey, /*minecraftDay,*/ systemTime, storyChapter, storyPart));
thisNote.noteMap.put(noteKey, new NoteMetadata(newNote, noteKey, minecraftDay, systemTime, storyChapter, storyPart));
FlashConfig(); ///TODO: This might be really unnecessary and may only be required on clean up as opposed to everytime the command is run
}
/////////////////////////////////////////////////////////////////////////////
/// @fn DeleteNote
///
/// @brief Deletes a note in the notebook
///
/// @arg[in] noteId is the id to delete
/////////////////////////////////////////////////////////////////////////////
public void DeleteNote(Integer noteId) {
thisNote.noteMap.remove(noteId);
FlashConfig();
}
/////////////////////////////////////////////////////////////////////////////
/// @fn ModifyNote
///
/// @brief Modifies a note at noteId entry OR creates new note at that
/// entry if the id didn't exist previously
///
/// @arg[in] noteId is the id we wish to modify the note of
///
/// @arg[in] newNote is the new string value of the note
///
/// @arg[in] minecraftDay is currently unsupported but will be the day of
/// the minecraft world when it is implemented
///
/// @arg[in] systemTime is the epoch time in milliseconds
///
/// @arg[in] storyChapter is the chapter in the story this note was taken
///
/// @arg[in] storyPart is the part in the chapter the note was taken
///
/// @return 0 if success, -1 if not
/////////////////////////////////////////////////////////////////////////////
public void ModifyNote(Integer noteId, String newNote, /*long minecraftDay,*/ long systemTime, long storyChapter, long storyPart) {
thisNote.noteMap.put(noteId, new NoteMetadata(newNote, noteId, /*minecraftDay,*/ systemTime, storyChapter, storyPart));
FlashConfig();
public void ModifyNote(Integer noteId, String newNote, long minecraftDay, long systemTime, long storyChapter, long storyPart) {
thisNote.noteMap.put(noteId, new NoteMetadata(newNote, noteId, minecraftDay, systemTime, storyChapter, storyPart));
}
/////////////////////////////////////////////////////////////////////////////
/// @fn PurgeAllNotes
///
/// @brief Wipes the players notebook clean
/////////////////////////////////////////////////////////////////////////////
public void PurgeAllNotes() {
thisNote.noteMap.clear();
FlashConfig();
}
/////////////////////////////////////////////////////////////////////////////
/// @fn GetNoteString
///
/// @brief Gets the note string in the map by identifier. NOT metadata
///
/// @arg[in] key is the map key we wish to return
///
/// @return Empty string if that ID contains no note, or string with note
/////////////////////////////////////////////////////////////////////////////
public String GetNoteString(Integer key) {
if (thisNote.noteMap.containsKey(key)) {
return thisNote.noteMap.get(key).note;
} else {
return "";
}
}
/////////////////////////////////////////////////////////////////////////////
/// @fn GetNotebookSize
///
/// @brief Returns the size of the notebook object
///
/// @return Size of notebook
/////////////////////////////////////////////////////////////////////////////
public Integer GetNotebookSize() {
return thisNote.noteMap.size();
}
/////////////////////////////////////////////////////////////////////////////
/// @fn GetNoteKey
///
/// @brief Returns the key identifier of a note by the value in the map
///
/// @arg[in] currentNote is the string note that we wish to see if exists
///
/// @return 0 or positive number if key found, negative number if not
/////////////////////////////////////////////////////////////////////////////
// Find the key of a note if it exists (O(n) search time)
// Returns -1 on failure to find note key
public Integer GetNoteKey(String currentNote) {
Integer ret = -1;
for (Entry<Integer, NoteMetadata> entry : thisNote.noteMap.entrySet()) {
@ -220,18 +135,13 @@ public class PlayerNote {
ret = entry.getKey();
}
}
FlashConfig();
return ret;
}
/////////////////////////////////////////////////////////////////////////////
/// @fn FlashConfig
///
/// @brief Writes to the configuration file
/////////////////////////////////////////////////////////////////////////////
public void FlashConfig() {
try {
config.WriteToJsonFile("notes/" + thisNote.uuid + ".json", thisNote);
config.WriteToJsonFile("notes/" + thisNote.uuid.toString() + ".json", thisNote);
} catch (FILE_WRITE_EXCEPTION e) {
System.out.println(ChatUtil.ColoredString("Could not flash notes configuration file", CONSOLE_COLOR.RED));
}

View File

@ -7,17 +7,11 @@
*
*/
// color colour
package jesse.keeblarcraft;
import net.fabricmc.api.ModInitializer;
// import net.minecraft.server.command.ServerCommandSource;
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
import net.minecraft.registry.Registries;
import net.minecraft.registry.Registry;
import net.minecraft.resource.featuretoggle.FeatureSet;
import net.minecraft.screen.ScreenHandlerType;
import net.minecraft.util.Identifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -25,26 +19,22 @@ import org.slf4j.LoggerFactory;
import jesse.keeblarcraft.AttributeMgr.AttributeMgr;
import jesse.keeblarcraft.AttributeMgr.AttributeTree;
import jesse.keeblarcraft.Commands.CustomCommandManager;
import jesse.keeblarcraft.CustomBlocks.BlockList;
import jesse.keeblarcraft.CustomBlocks.BlockManager;
import jesse.keeblarcraft.CustomItems.ItemManager;
import jesse.keeblarcraft.EventMgr.ServerTickListener;
import jesse.keeblarcraft.GuiMgr.TreeHandler;
import jesse.keeblarcraft.Utils.CustomExceptions.SETUP_FAILED_EXCEPTION;
import jesse.keeblarcraft.Utils.ChatUtil;
import jesse.keeblarcraft.Utils.Setup;
import jesse.keeblarcraft.Utils.ChatUtil.CONSOLE_COLOR;
// import com.mojang.brigadier.Command;
public class Keeblarcraft implements ModInitializer {
public static String MOD_ID = "keeblarcraft";
public static final Logger LOGGER = LoggerFactory.getLogger("keeblarcraft");
// May be moved in future; but is the universal TREE_HANDLER call for at least the tree gui. It's possible it can get a more
// generic name in the future after the tree gui is done; however until then it will remain TREE_HANDLER.
public static final ScreenHandlerType<TreeHandler> TREE_HANDLER = Registry.register(Registries.SCREEN_HANDLER,
Identifier.of(Keeblarcraft.MOD_ID, "tree_gui"),
new ScreenHandlerType<>(TreeHandler::new, FeatureSet.empty()));
CustomCommandManager cmdMgr = new CustomCommandManager();
Setup setup = Setup.GetInstance();
@Override
@ -96,7 +86,7 @@ public class Keeblarcraft implements ModInitializer {
ItemManager.RegisterAllItems();
// Register blocks
BlockList.RegisterBlocks();
BlockManager.RegisterBlocks();
} catch (SETUP_FAILED_EXCEPTION e) {

View File

@ -11,35 +11,30 @@ package jesse.keeblarcraft.Utils;
import org.slf4j.Logger;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.MutableText;
import net.minecraft.text.Text;
import java.util.HashMap;
import java.util.List;
import java.util.ArrayList;
import java.util.Map.Entry;
public class ChatUtil {
//This is a private class only used internally to get ANSI colors
private static class ConsoleColor {
private static class ConsoleColor {
public static String getColor(CONSOLE_COLOR color) {
String ret = "";
switch(color) {
case RED:
case CONSOLE_COLOR.RED:
ret = "31";
break;
case GREEN:
case CONSOLE_COLOR.GREEN:
ret = "32";
break;
case YELLOW:
case CONSOLE_COLOR.YELLOW:
ret = "33";
break;
case BLUE:
case CONSOLE_COLOR.BLUE:
ret = "34";
break;
case MAGENTA:
case CONSOLE_COLOR.MAGENTA:
ret = "35";
break;
case CYAN:
case CONSOLE_COLOR.CYAN:
ret = "36";
break;
}
@ -56,95 +51,11 @@ public class ChatUtil {
CYAN;
}
static int CHATBOX_WIDTH_CHARS = 80; // Maximum length of the textbox in individual characters
// Helpful print wrapper function
static public void SendPlayerMsg(ServerPlayerEntity player, String text) {
player.sendMessage(Text.literal(text));
}
/// TODO: Add this back in later under a chat ticket
// Prints a table of data in chat
// static public void ChatBlock(ServerPlayerEntity player, HashMap<Text, List<Text>> table) {
// ///DEBUG
// for (Entry<Text, List<Text>> entry : table.entrySet()) {
// for (int debug = 0; debug < entry.getValue().size(); debug++) {
// System.out.println("KEY: " + entry.getKey().toString() + " VALUE: " + entry.getValue().get(debug).toString());
// }
// }
// // The user will likely pass in text strings longer than the character limit for num of columns; therefore
// // we are required to split these into this finalPrintList structure
// HashMap<Text, ArrayList<Text>> finalPrintList = new HashMap<Text, ArrayList<Text>>();
// int maxColumnWidth = CHATBOX_WIDTH_CHARS / table.size(); // Represents max char allowance per data column
// maxColumnWidth -= table.size(); // Represents a separating '|' between each column
// // This first behemoth of a loop is to take the given table hashmap and look at
// // the Text values & split them
// // should their size exceed the maxColumnWidth given for each entry key
// System.out.println("Entry data is size " + table.size());
// for (Entry<Text, List<Text>> entry : table.entrySet()) {
// // Each text line found cannot be longer than "maxColumnWidth" or else it must
// // wrap which splits it
// // into two texts; thus adding an additional row that is required for iteration.
// // Each split text must
// // maintain the same formatting as the root text it is split from
// finalPrintList.put(entry.getKey(), new ArrayList<Text>()); // Instantiate the key & array
// System.out.println("Map size is " + finalPrintList.size());
// System.out.println("Entry value size is " + entry.getValue().size());
// for (Text item : entry.getValue()) {
// int numItems = (int) Math.ceil((item.getString().length() / maxColumnWidth));
// int strOffset = numItems; // Represents number of items per string
// System.out.println("numItems: " + numItems);
// System.out.println("strOffset: " + strOffset);
// for (int offset = 0; offset <= numItems; offset++) { /// TODO: might need to be <=
// int start = strOffset * offset; // Multiple from start of string to needed point
// int end = start + strOffset; // The original start offset + the width spacer
// String substr = item.toString().substring(start, end); // Contains the string to be Textified
// MutableText newText = Text.literal(substr).setStyle(item.getStyle());
// finalPrintList.get(entry.getKey()).add(newText); // Add back into list
// System.out.println("SPLIT DEBUG: " + newText.toString());
// }
// }
// }
// // This loop does the printing of the table in chat
// int tempPreventInfiniteLoops = 10;
// while (finalPrintList.size() != 0) {
// // This is a one time print
// MutableText line = Text.literal("");
// for (Entry<Text, ArrayList<Text>> entry : finalPrintList.entrySet()) {
// if (entry.getValue().size() != 0) {
// line.append(entry.getValue().get(0));
// System.out.println("new line is now " + line.toString());
// line.append("|");
// } else {
// finalPrintList.remove(entry.getKey()); // Clear the key; as we are done with this column for
// // printing
// }
// player.sendMessage(line);
// String debugPrint = line.toString();
// System.out.println("Debug line to be printed: " + debugPrint);
// line = Text.literal("");
// break;
// }
// tempPreventInfiniteLoops--;
// if (tempPreventInfiniteLoops <= 0) {
// return;
// }
// }
// }
// Returns a string with the proper ANSI encoding for the specified CONSOLE_COLOR
static public String ColoredString(String msg, CONSOLE_COLOR color) {
return "\033[" + ConsoleColor.getColor(color) + "m" + msg + "\033[0m";

View File

@ -1,11 +0,0 @@
package jesse.keeblarcraft.Utils.CommonStructures;
public class Position2d {
public Position2d(int x, int y) {
this.x = x;
this.y = y;
}
public int x;
public int y;
}

View File

@ -1,13 +0,0 @@
package jesse.keeblarcraft.Utils.CommonStructures;
public class Position3d {
public Position3d(int x, int y, int z) {
this.x = x;
this.y = y;
this.z = z;
}
public int x;
public int y;
public int z;
}

View File

@ -15,6 +15,7 @@ import java.util.List;
import java.util.ArrayList;
import jesse.keeblarcraft.ConfigMgr.ConfigManager;
import jesse.keeblarcraft.EventMgr.ServerTickListener;
import jesse.keeblarcraft.Utils.ChatUtil.CONSOLE_COLOR;
import jesse.keeblarcraft.Utils.CustomExceptions.DIRECTORY_CREATE_EXCEPTION;
import jesse.keeblarcraft.Utils.CustomExceptions.SETUP_FAILED_EXCEPTION;

View File

@ -0,0 +1,15 @@
package jesse.keeblarcraft.mixin;
import net.minecraft.server.MinecraftServer;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(MinecraftServer.class)
public class ExampleMixin {
@Inject(at = @At("HEAD"), method = "loadWorld")
private void init(CallbackInfo info) {
// This code is injected into the start of MinecraftServer.loadWorld()V
}
}

View File

@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "keeblarcraft:block/10_cent_coin"
}
}
}

View File

@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "keeblarcraft:block/10_dollar"
}
}
}

View File

@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "keeblarcraft:block/1_dollar"
}
}
}

View File

@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "keeblarcraft:block/20_dollar"
}
}
}

View File

@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "keeblarcraft:block/25_cent_coin"
}
}
}

View File

@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "keeblarcraft:block/5_cent_coin"
}
}
}

View File

@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "keeblarcraft:block/5_dollar"
}
}
}

View File

@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "keeblarcraft:block/cent_coin"
}
}
}

View File

@ -1,7 +0,0 @@
{
"variants": {
"": {
"model": "keeblarcraft:block/example_statue"
}
}
}

View File

@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "keeblarcraft:block/money_block"
}
}
}

View File

@ -7,10 +7,14 @@
"itemgroup.keeblarcraft": "Keeblarcraft Modded Items",
"block.keeblarcraft.example_block": "Keeblarcraft example block",
"block.keeblarcraft.money_block": "Money! Money! Money!",
"block.keeblarcraft.example_block_ore": "Keeblarcraft example block ore",
"block.keeblarcraft.example_statue": "Keeblarcraft example statue",
"category.keeblarcraft.test": "Keeblarcraft bindings",
"key.keeblarcraft.treemap": "Tree GUI",
"key.keeblarcraft.globalconfig": "Config menu"
"block.keeblarcraft.cent_coin": "Cent Coin",
"block.keeblarcraft.5_cent_coin": "5 Cent Coin",
"block.keeblarcraft.10_cent_coin": "10 Cent Coin",
"block.keeblarcraft.25_cent_coin": "25 Cent Coin",
"block.keeblarcraft.1_dollar": "$1",
"block.keeblarcraft.5_dollar": "$5",
"block.keeblarcraft.10_dollar": "$10",
"block.keeblarcraft.20_dollar": "$20"
}

View File

@ -0,0 +1,22 @@
{
"credit": "Made with Blockbench",
"textures": {
"0": "keeblarcraft:block/10_cent_coin",
"particle": "keeblarcraft:block/10_cent_coin"
},
"elements": [
{
"from": [7, 0, 7],
"to": [9, 1, 9],
"rotation": {"angle": 0, "axis": "y", "origin": [7, 0, 7]},
"faces": {
"north": {"uv": [2, 0, 4, 1], "texture": "#0"},
"east": {"uv": [2, 1, 4, 2], "texture": "#0"},
"south": {"uv": [2, 2, 4, 3], "texture": "#0"},
"west": {"uv": [2, 3, 4, 4], "texture": "#0"},
"up": {"uv": [2, 2, 0, 0], "texture": "#0"},
"down": {"uv": [2, 2, 0, 4], "texture": "#0"}
}
}
]
}

View File

@ -0,0 +1,23 @@
{
"credit": "Made with Blockbench",
"texture_size": [32, 32],
"textures": {
"0": "keeblarcraft:block/10_dollar",
"particle": "keeblarcraft:block/10_dollar"
},
"elements": [
{
"from": [3, 0, 6],
"to": [13, 1, 11],
"rotation": {"angle": 0, "axis": "y", "origin": [3, 0, 6]},
"faces": {
"north": {"uv": [0, 5, 5, 5.5], "texture": "#0"},
"east": {"uv": [5, 0.5, 7.5, 1], "texture": "#0"},
"south": {"uv": [5, 0, 10, 0.5], "texture": "#0"},
"west": {"uv": [5, 1, 7.5, 1.5], "texture": "#0"},
"up": {"uv": [5, 2.5, 0, 0], "texture": "#0"},
"down": {"uv": [5, 2.5, 0, 5], "texture": "#0"}
}
}
]
}

View File

@ -0,0 +1,23 @@
{
"credit": "Made with Blockbench",
"texture_size": [32, 32],
"textures": {
"0": "keeblarcraft:block/1_dollar",
"particle": "keeblarcraft:block/1_dollar"
},
"elements": [
{
"from": [3, 0, 5],
"to": [13, 1, 10],
"rotation": {"angle": 0, "axis": "y", "origin": [3, 0, 5]},
"faces": {
"north": {"uv": [0, 5, 5, 5.5], "texture": "#0"},
"east": {"uv": [5, 0.5, 7.5, 1], "texture": "#0"},
"south": {"uv": [5, 0, 10, 0.5], "texture": "#0"},
"west": {"uv": [5, 1, 7.5, 1.5], "texture": "#0"},
"up": {"uv": [5, 2.5, 0, 0], "texture": "#0"},
"down": {"uv": [5, 2.5, 0, 5], "texture": "#0"}
}
}
]
}

View File

@ -0,0 +1,23 @@
{
"credit": "Made with Blockbench",
"texture_size": [32, 32],
"textures": {
"0": "keeblarcraft:block/20_dollar",
"particle": "keeblarcraft:block/20_dollar"
},
"elements": [
{
"from": [3, 0, 6],
"to": [13, 1, 11],
"rotation": {"angle": 0, "axis": "y", "origin": [3, 0, 6]},
"faces": {
"north": {"uv": [0, 5, 5, 5.5], "texture": "#0"},
"east": {"uv": [5, 0.5, 7.5, 1], "texture": "#0"},
"south": {"uv": [5, 0, 10, 0.5], "texture": "#0"},
"west": {"uv": [5, 1, 7.5, 1.5], "texture": "#0"},
"up": {"uv": [5, 2.5, 0, 0], "texture": "#0"},
"down": {"uv": [5, 2.5, 0, 5], "texture": "#0"}
}
}
]
}

View File

@ -0,0 +1,22 @@
{
"credit": "Made with Blockbench",
"textures": {
"0": "keeblarcraft:block/25_cent_coin",
"particle": "keeblarcraft:block/25_cent_coin"
},
"elements": [
{
"from": [6, 0, 6],
"to": [10, 1, 10],
"rotation": {"angle": 0, "axis": "y", "origin": [6, 0, 6]},
"faces": {
"north": {"uv": [4, 0, 8, 1], "texture": "#0"},
"east": {"uv": [4, 1, 8, 2], "texture": "#0"},
"south": {"uv": [4, 2, 8, 3], "texture": "#0"},
"west": {"uv": [4, 3, 8, 4], "texture": "#0"},
"up": {"uv": [4, 4, 0, 0], "texture": "#0"},
"down": {"uv": [4, 4, 0, 8], "texture": "#0"}
}
}
]
}

View File

@ -0,0 +1,22 @@
{
"credit": "Made with Blockbench",
"textures": {
"0": "keeblarcraft:block/5_cent_coin",
"particle": "keeblarcraft:block/5_cent_coin"
},
"elements": [
{
"from": [7, 0, 7],
"to": [10, 1, 10],
"rotation": {"angle": 0, "axis": "y", "origin": [7, 0, 7]},
"faces": {
"north": {"uv": [3, 0, 6, 1], "texture": "#0"},
"east": {"uv": [3, 1, 6, 2], "texture": "#0"},
"south": {"uv": [3, 2, 6, 3], "texture": "#0"},
"west": {"uv": [3, 3, 6, 4], "texture": "#0"},
"up": {"uv": [3, 3, 0, 0], "texture": "#0"},
"down": {"uv": [3, 3, 0, 6], "texture": "#0"}
}
}
]
}

View File

@ -0,0 +1,22 @@
{
"credit": "Made with Blockbench",
"texture_size": [32, 32],
"textures": {
"1": "keeblarcraft:block/5_dollar"
},
"elements": [
{
"from": [3, 0, 5],
"to": [13, 1, 10],
"rotation": {"angle": 0, "axis": "y", "origin": [3, 0, 5]},
"faces": {
"north": {"uv": [0, 5, 5, 5.5], "texture": "#1"},
"east": {"uv": [5, 0.5, 7.5, 1], "texture": "#1"},
"south": {"uv": [5, 0, 10, 0.5], "texture": "#1"},
"west": {"uv": [5, 1, 7.5, 1.5], "texture": "#1"},
"up": {"uv": [5, 2.5, 0, 0], "texture": "#1"},
"down": {"uv": [5, 2.5, 0, 5], "texture": "#1"}
}
}
]
}

View File

@ -0,0 +1,22 @@
{
"credit": "Made with Blockbench",
"textures": {
"0": "keeblarcraft:block/cent_coin",
"particle": "keeblarcraft:block/cent_coin"
},
"elements": [
{
"from": [7, 0, 7],
"to": [9, 1, 9],
"rotation": {"angle": 0, "axis": "y", "origin": [7, 0, 7]},
"faces": {
"north": {"uv": [2, 0, 4, 1], "texture": "#0"},
"east": {"uv": [2, 1, 4, 2], "texture": "#0"},
"south": {"uv": [2, 2, 4, 3], "texture": "#0"},
"west": {"uv": [2, 3, 4, 4], "texture": "#0"},
"up": {"uv": [2, 2, 0, 0], "texture": "#0"},
"down": {"uv": [2, 2, 0, 4], "texture": "#0"}
}
}
]
}

View File

@ -1,481 +0,0 @@
{
"credit": "Made with Blockbench",
"texture_size": [64, 64],
"textures": {
"0": "keeblarcraft:block/example_statue",
"particle": "keeblarcraft:block/example_statue"
},
"elements": [
{
"name": "platform",
"from": [0, 0, 0],
"to": [16, 1, 16],
"rotation": {"angle": 0, "axis": "y", "origin": [5, 0, 3]},
"faces": {
"north": {"uv": [4, 2.5, 8, 2.75], "texture": "#0"},
"east": {"uv": [4, 2.75, 8, 3], "texture": "#0"},
"south": {"uv": [4, 3, 8, 3.25], "texture": "#0"},
"west": {"uv": [4, 3.25, 8, 3.5], "texture": "#0"},
"up": {"uv": [4, 4, 0, 0], "texture": "#0"},
"down": {"uv": [4, 4, 0, 8], "texture": "#0"}
}
},
{
"name": "left_leg",
"from": [7, 1, 3],
"to": [9, 5, 5],
"rotation": {"angle": 0, "axis": "y", "origin": [7, 0, 2]},
"faces": {
"north": {"uv": [5.5, 5.5, 6, 6.75], "texture": "#0"},
"east": {"uv": [6, 0, 6.5, 1.25], "texture": "#0"},
"south": {"uv": [6, 1.25, 6.5, 2.5], "texture": "#0"},
"west": {"uv": [6, 3.5, 6.5, 4.75], "texture": "#0"},
"up": {"uv": [6.75, 7.75, 6.25, 7.25], "texture": "#0"},
"down": {"uv": [7.75, 7, 7.25, 7.5], "texture": "#0"}
}
},
{
"name": "right_leg",
"from": [7, 1, 11],
"to": [9, 5, 13],
"rotation": {"angle": 0, "axis": "y", "origin": [7, 0, 11]},
"faces": {
"north": {"uv": [6, 4.75, 6.5, 6], "texture": "#0"},
"east": {"uv": [6, 6, 6.5, 7.25], "texture": "#0"},
"south": {"uv": [6.5, 0, 7, 1.25], "texture": "#0"},
"west": {"uv": [6.5, 1.25, 7, 2.5], "texture": "#0"},
"up": {"uv": [8, 0.5, 7.5, 0], "texture": "#0"},
"down": {"uv": [8, 0.5, 7.5, 1], "texture": "#0"}
}
},
{
"from": [7, 5, 5],
"to": [9, 10, 11],
"rotation": {"angle": 0, "axis": "y", "origin": [7, 5, 7]},
"faces": {
"north": {"uv": [6.5, 3.5, 7, 4.75], "texture": "#0"},
"east": {"uv": [4, 0, 5.5, 1.25], "texture": "#0"},
"south": {"uv": [6.5, 4.75, 7, 6], "texture": "#0"},
"west": {"uv": [4, 1.25, 5.5, 2.5], "texture": "#0"},
"up": {"uv": [6, 1.5, 5.5, 0], "texture": "#0"},
"down": {"uv": [4.5, 5.5, 4, 7], "texture": "#0"}
}
},
{
"from": [7, 8, 10],
"to": [9, 10, 12],
"rotation": {"angle": 0, "axis": "y", "origin": [7, 8, 10]},
"faces": {
"north": {"uv": [7.5, 1, 8, 1.5], "texture": "#0"},
"east": {"uv": [7.5, 1.5, 8, 2], "texture": "#0"},
"south": {"uv": [7.5, 2, 8, 2.5], "texture": "#0"},
"west": {"uv": [7.5, 3.5, 8, 4], "texture": "#0"},
"up": {"uv": [8, 4.5, 7.5, 4], "texture": "#0"},
"down": {"uv": [8, 5, 7.5, 5.5], "texture": "#0"}
}
},
{
"from": [7, 10, 11],
"to": [9, 11, 13],
"rotation": {"angle": 0, "axis": "y", "origin": [7, 10, 11]},
"faces": {
"north": {"uv": [8, 2.75, 8.5, 3], "texture": "#0"},
"east": {"uv": [8, 3, 8.5, 3.25], "texture": "#0"},
"south": {"uv": [8, 3.25, 8.5, 3.5], "texture": "#0"},
"west": {"uv": [3.5, 8, 4, 8.25], "texture": "#0"},
"up": {"uv": [8, 6, 7.5, 5.5], "texture": "#0"},
"down": {"uv": [8, 6, 7.5, 6.5], "texture": "#0"}
}
},
{
"from": [7, 10, 13],
"to": [9, 11, 14],
"rotation": {"angle": 0, "axis": "y", "origin": [7, 10, 12]},
"faces": {
"north": {"uv": [8, 3.5, 8.5, 3.75], "texture": "#0"},
"east": {"uv": [7.5, 8.5, 7.75, 8.75], "texture": "#0"},
"south": {"uv": [8, 3.75, 8.5, 4], "texture": "#0"},
"west": {"uv": [8.75, 8.75, 9, 9], "texture": "#0"},
"up": {"uv": [8.5, 4.25, 8, 4], "texture": "#0"},
"down": {"uv": [8.5, 4.25, 8, 4.5], "texture": "#0"}
}
},
{
"from": [7, 11, 14],
"to": [9, 13, 15],
"rotation": {"angle": 0, "axis": "y", "origin": [7, 11, 13]},
"faces": {
"north": {"uv": [7.5, 6.5, 8, 7], "texture": "#0"},
"east": {"uv": [8, 5, 8.25, 5.5], "texture": "#0"},
"south": {"uv": [7.25, 7.5, 7.75, 8], "texture": "#0"},
"west": {"uv": [5.5, 8, 5.75, 8.5], "texture": "#0"},
"up": {"uv": [8.5, 5.75, 8, 5.5], "texture": "#0"},
"down": {"uv": [8.5, 5.75, 8, 6], "texture": "#0"}
}
},
{
"from": [7, 14, 12],
"to": [9, 15, 14],
"rotation": {"angle": 0, "axis": "y", "origin": [7, 14, 12]},
"faces": {
"north": {"uv": [8, 6, 8.5, 6.25], "texture": "#0"},
"east": {"uv": [8, 6.25, 8.5, 6.5], "texture": "#0"},
"south": {"uv": [8, 6.5, 8.5, 6.75], "texture": "#0"},
"west": {"uv": [8, 6.75, 8.5, 7], "texture": "#0"},
"up": {"uv": [4.5, 8.25, 4, 7.75], "texture": "#0"},
"down": {"uv": [5, 7.75, 4.5, 8.25], "texture": "#0"}
}
},
{
"from": [7, 14, 11],
"to": [9, 15, 12],
"rotation": {"angle": 0, "axis": "y", "origin": [7, 13, 10]},
"faces": {
"north": {"uv": [7.25, 8, 7.75, 8.25], "texture": "#0"},
"east": {"uv": [0, 9, 0.25, 9.25], "texture": "#0"},
"south": {"uv": [7.75, 8, 8.25, 8.25], "texture": "#0"},
"west": {"uv": [9, 0, 9.25, 0.25], "texture": "#0"},
"up": {"uv": [8.75, 0.75, 8.25, 0.5], "texture": "#0"},
"down": {"uv": [8.75, 0.75, 8.25, 1], "texture": "#0"}
}
},
{
"from": [7, 14, 10],
"to": [9, 15, 11],
"rotation": {"angle": 0, "axis": "y", "origin": [7, 13, 9]},
"faces": {
"north": {"uv": [8.25, 1, 8.75, 1.25], "texture": "#0"},
"east": {"uv": [0.25, 9, 0.5, 9.25], "texture": "#0"},
"south": {"uv": [8.25, 1.25, 8.75, 1.5], "texture": "#0"},
"west": {"uv": [9, 0.25, 9.25, 0.5], "texture": "#0"},
"up": {"uv": [8.75, 1.75, 8.25, 1.5], "texture": "#0"},
"down": {"uv": [8.75, 1.75, 8.25, 2], "texture": "#0"}
}
},
{
"from": [7, 13, 9],
"to": [9, 14, 10],
"rotation": {"angle": 0, "axis": "y", "origin": [7, 13, 9]},
"faces": {
"north": {"uv": [8.25, 2, 8.75, 2.25], "texture": "#0"},
"east": {"uv": [0.5, 9, 0.75, 9.25], "texture": "#0"},
"south": {"uv": [8.25, 2.25, 8.75, 2.5], "texture": "#0"},
"west": {"uv": [0.75, 9, 1, 9.25], "texture": "#0"},
"up": {"uv": [3.25, 8.5, 2.75, 8.25], "texture": "#0"},
"down": {"uv": [3.75, 8.25, 3.25, 8.5], "texture": "#0"}
}
},
{
"from": [7, 11, 8],
"to": [9, 13, 9],
"rotation": {"angle": 0, "axis": "y", "origin": [7, 11, 7]},
"faces": {
"north": {"uv": [5, 7.75, 5.5, 8.25], "texture": "#0"},
"east": {"uv": [5.75, 8, 6, 8.5], "texture": "#0"},
"south": {"uv": [6.25, 7.75, 6.75, 8.25], "texture": "#0"},
"west": {"uv": [3.75, 8.25, 4, 8.75], "texture": "#0"},
"up": {"uv": [4.5, 8.5, 4, 8.25], "texture": "#0"},
"down": {"uv": [5, 8.25, 4.5, 8.5], "texture": "#0"}
}
},
{
"from": [7, 10, 9],
"to": [9, 11, 11],
"rotation": {"angle": 0, "axis": "y", "origin": [7, 9, 8]},
"faces": {
"north": {"uv": [5, 8.25, 5.5, 8.5], "texture": "#0"},
"east": {"uv": [8.25, 5, 8.75, 5.25], "texture": "#0"},
"south": {"uv": [8.25, 5.25, 8.75, 5.5], "texture": "#0"},
"west": {"uv": [6.25, 8.25, 6.75, 8.5], "texture": "#0"},
"up": {"uv": [8.25, 7.5, 7.75, 7], "texture": "#0"},
"down": {"uv": [8.25, 7.5, 7.75, 8], "texture": "#0"}
}
},
{
"from": [7, 13, 14],
"to": [9, 14, 15],
"rotation": {"angle": 0, "axis": "y", "origin": [7, 13, 14]},
"faces": {
"north": {"uv": [6.75, 8.25, 7.25, 8.5], "texture": "#0"},
"east": {"uv": [1, 9, 1.25, 9.25], "texture": "#0"},
"south": {"uv": [8.25, 7, 8.75, 7.25], "texture": "#0"},
"west": {"uv": [1.25, 9, 1.5, 9.25], "texture": "#0"},
"up": {"uv": [7.75, 8.5, 7.25, 8.25], "texture": "#0"},
"down": {"uv": [8.75, 7.25, 8.25, 7.5], "texture": "#0"}
}
},
{
"from": [7, 7, 4],
"to": [9, 9, 5],
"rotation": {"angle": 0, "axis": "y", "origin": [7, 7, 4]},
"faces": {
"north": {"uv": [0, 8, 0.5, 8.5], "texture": "#0"},
"east": {"uv": [8.25, 7.5, 8.5, 8], "texture": "#0"},
"south": {"uv": [8, 0, 8.5, 0.5], "texture": "#0"},
"west": {"uv": [7.75, 8.25, 8, 8.75], "texture": "#0"},
"up": {"uv": [8.5, 8.5, 8, 8.25], "texture": "#0"},
"down": {"uv": [8.75, 8, 8.25, 8.25], "texture": "#0"}
}
},
{
"from": [7, 8, 3],
"to": [9, 9, 4],
"rotation": {"angle": 0, "axis": "y", "origin": [7, 7, 2]},
"faces": {
"north": {"uv": [0, 8.5, 0.5, 8.75], "texture": "#0"},
"east": {"uv": [1.5, 9, 1.75, 9.25], "texture": "#0"},
"south": {"uv": [8.5, 0, 9, 0.25], "texture": "#0"},
"west": {"uv": [1.75, 9, 2, 9.25], "texture": "#0"},
"up": {"uv": [9, 0.5, 8.5, 0.25], "texture": "#0"},
"down": {"uv": [3.25, 8.5, 2.75, 8.75], "texture": "#0"}
}
},
{
"from": [7, 9, 2],
"to": [9, 12, 3],
"rotation": {"angle": 0, "axis": "y", "origin": [7, 9, 1]},
"faces": {
"north": {"uv": [4, 7, 4.5, 7.75], "texture": "#0"},
"east": {"uv": [2.25, 8, 2.5, 8.75], "texture": "#0"},
"south": {"uv": [4.5, 7, 5, 7.75], "texture": "#0"},
"west": {"uv": [2.5, 8, 2.75, 8.75], "texture": "#0"},
"up": {"uv": [9, 3, 8.5, 2.75], "texture": "#0"},
"down": {"uv": [9, 3, 8.5, 3.25], "texture": "#0"}
}
},
{
"from": [7, 12, 3],
"to": [9, 13, 4],
"rotation": {"angle": 0, "axis": "y", "origin": [7, 12, 3]},
"faces": {
"north": {"uv": [3.25, 8.5, 3.75, 8.75], "texture": "#0"},
"east": {"uv": [2, 9, 2.25, 9.25], "texture": "#0"},
"south": {"uv": [8.5, 3.25, 9, 3.5], "texture": "#0"},
"west": {"uv": [2.25, 9, 2.5, 9.25], "texture": "#0"},
"up": {"uv": [9, 3.75, 8.5, 3.5], "texture": "#0"},
"down": {"uv": [9, 3.75, 8.5, 4], "texture": "#0"}
}
},
{
"from": [7, 13, 4],
"to": [9, 14, 5],
"rotation": {"angle": 0, "axis": "y", "origin": [7, 13, 4]},
"faces": {
"north": {"uv": [4, 8.5, 4.5, 8.75], "texture": "#0"},
"east": {"uv": [2.5, 9, 2.75, 9.25], "texture": "#0"},
"south": {"uv": [8.5, 4, 9, 4.25], "texture": "#0"},
"west": {"uv": [2.75, 9, 3, 9.25], "texture": "#0"},
"up": {"uv": [9, 4.5, 8.5, 4.25], "texture": "#0"},
"down": {"uv": [5, 8.5, 4.5, 8.75], "texture": "#0"}
}
},
{
"from": [7, 10, 5],
"to": [9, 14, 6],
"rotation": {"angle": 0, "axis": "y", "origin": [7, 10, 5]},
"faces": {
"north": {"uv": [5.5, 1.5, 6, 2.5], "texture": "#0"},
"east": {"uv": [6.75, 7.25, 7, 8.25], "texture": "#0"},
"south": {"uv": [7, 3.5, 7.5, 4.5], "texture": "#0"},
"west": {"uv": [0.5, 8, 0.75, 9], "texture": "#0"},
"up": {"uv": [9, 4.75, 8.5, 4.5], "texture": "#0"},
"down": {"uv": [9, 4.75, 8.5, 5], "texture": "#0"}
}
},
{
"from": [7, 10, 6],
"to": [9, 15, 7],
"rotation": {"angle": 0, "axis": "y", "origin": [7, 14, 6]},
"faces": {
"north": {"uv": [6.5, 6, 7, 7.25], "texture": "#0"},
"east": {"uv": [7, 5.75, 7.25, 7], "texture": "#0"},
"south": {"uv": [5.5, 6.75, 6, 8], "texture": "#0"},
"west": {"uv": [7, 7, 7.25, 8.25], "texture": "#0"},
"up": {"uv": [5.5, 8.75, 5, 8.5], "texture": "#0"},
"down": {"uv": [6, 8.5, 5.5, 8.75], "texture": "#0"}
}
},
{
"from": [7, 10, 7],
"to": [9, 15, 8],
"rotation": {"angle": 0, "axis": "y", "origin": [7, 14, 7]},
"faces": {
"north": {"uv": [7, 0, 7.5, 1.25], "texture": "#0"},
"east": {"uv": [7.25, 5.75, 7.5, 7], "texture": "#0"},
"south": {"uv": [7, 1.25, 7.5, 2.5], "texture": "#0"},
"west": {"uv": [6, 7.25, 6.25, 8.5], "texture": "#0"},
"up": {"uv": [9, 8, 8.5, 7.75], "texture": "#0"},
"down": {"uv": [8.5, 8.5, 8, 8.75], "texture": "#0"}
}
},
{
"from": [7, 15, 6],
"to": [9, 16, 7],
"rotation": {"angle": 0, "axis": "y", "origin": [7, 15, 6]},
"faces": {
"north": {"uv": [8.5, 5.5, 9, 5.75], "texture": "#0"},
"east": {"uv": [9, 2.75, 9.25, 3], "texture": "#0"},
"south": {"uv": [8.5, 5.75, 9, 6], "texture": "#0"},
"west": {"uv": [3, 9, 3.25, 9.25], "texture": "#0"},
"up": {"uv": [6.5, 8.75, 6, 8.5], "texture": "#0"},
"down": {"uv": [9, 6, 8.5, 6.25], "texture": "#0"}
}
},
{
"from": [7, 15, 13],
"to": [9, 16, 14],
"rotation": {"angle": 0, "axis": "y", "origin": [7, 15, 13]},
"faces": {
"north": {"uv": [8.5, 6.5, 9, 6.75], "texture": "#0"},
"east": {"uv": [9, 3, 9.25, 3.25], "texture": "#0"},
"south": {"uv": [8.5, 6.75, 9, 7], "texture": "#0"},
"west": {"uv": [3.25, 9, 3.5, 9.25], "texture": "#0"},
"up": {"uv": [7.5, 8.75, 7, 8.5], "texture": "#0"},
"down": {"uv": [9, 7.5, 8.5, 7.75], "texture": "#0"}
}
},
{
"from": [7, 10, 8],
"to": [9, 11, 9],
"rotation": {"angle": 0, "axis": "y", "origin": [7, 10, 8]},
"faces": {
"north": {"uv": [8.5, 8.25, 9, 8.5], "texture": "#0"},
"east": {"uv": [9, 3.25, 9.25, 3.5], "texture": "#0"},
"south": {"uv": [8.5, 8.5, 9, 8.75], "texture": "#0"},
"west": {"uv": [3.5, 9, 3.75, 9.25], "texture": "#0"},
"up": {"uv": [0.5, 9, 0, 8.75], "texture": "#0"},
"down": {"uv": [9.25, 0.5, 8.75, 0.75], "texture": "#0"}
}
},
{
"from": [7, 14, 8],
"to": [9, 15, 9],
"rotation": {"angle": 0, "axis": "y", "origin": [7, 14, 8]},
"faces": {
"north": {"uv": [8.75, 0.75, 9.25, 1], "texture": "#0"},
"east": {"uv": [9, 3.5, 9.25, 3.75], "texture": "#0"},
"south": {"uv": [8.75, 1, 9.25, 1.25], "texture": "#0"},
"west": {"uv": [3.75, 9, 4, 9.25], "texture": "#0"},
"up": {"uv": [9.25, 1.5, 8.75, 1.25], "texture": "#0"},
"down": {"uv": [9.25, 1.5, 8.75, 1.75], "texture": "#0"}
}
},
{
"from": [7, 13, 8],
"to": [9, 14, 9],
"rotation": {"angle": 0, "axis": "y", "origin": [7, 13, 8]},
"faces": {
"north": {"uv": [8.75, 1.75, 9.25, 2], "texture": "#0"},
"east": {"uv": [9, 3.75, 9.25, 4], "texture": "#0"},
"south": {"uv": [8.75, 2, 9.25, 2.25], "texture": "#0"},
"west": {"uv": [4, 9, 4.25, 9.25], "texture": "#0"},
"up": {"uv": [2.75, 9, 2.25, 8.75], "texture": "#0"},
"down": {"uv": [9.25, 2.25, 8.75, 2.5], "texture": "#0"}
}
},
{
"from": [7, 15, 8],
"to": [9, 16, 9],
"rotation": {"angle": 0, "axis": "y", "origin": [7, 15, 8]},
"faces": {
"north": {"uv": [8.75, 2.5, 9.25, 2.75], "texture": "#0"},
"east": {"uv": [9, 4, 9.25, 4.25], "texture": "#0"},
"south": {"uv": [2.75, 8.75, 3.25, 9], "texture": "#0"},
"west": {"uv": [4.25, 9, 4.5, 9.25], "texture": "#0"},
"up": {"uv": [3.75, 9, 3.25, 8.75], "texture": "#0"},
"down": {"uv": [4.25, 8.75, 3.75, 9], "texture": "#0"}
}
},
{
"from": [7, 15, 7],
"to": [9, 16, 8],
"rotation": {"angle": 0, "axis": "y", "origin": [7, 15, 7]},
"faces": {
"north": {"uv": [4.25, 8.75, 4.75, 9], "texture": "#0"},
"east": {"uv": [9, 4.25, 9.25, 4.5], "texture": "#0"},
"south": {"uv": [4.75, 8.75, 5.25, 9], "texture": "#0"},
"west": {"uv": [4.5, 9, 4.75, 9.25], "texture": "#0"},
"up": {"uv": [9.25, 5.25, 8.75, 5], "texture": "#0"},
"down": {"uv": [5.75, 8.75, 5.25, 9], "texture": "#0"}
}
},
{
"from": [7, 15, 9],
"to": [9, 16, 10],
"rotation": {"angle": 0, "axis": "y", "origin": [7, 15, 9]},
"faces": {
"north": {"uv": [8.75, 5.25, 9.25, 5.5], "texture": "#0"},
"east": {"uv": [9, 4.5, 9.25, 4.75], "texture": "#0"},
"south": {"uv": [5.75, 8.75, 6.25, 9], "texture": "#0"},
"west": {"uv": [4.75, 9, 5, 9.25], "texture": "#0"},
"up": {"uv": [6.75, 9, 6.25, 8.75], "texture": "#0"},
"down": {"uv": [7.25, 8.75, 6.75, 9], "texture": "#0"}
}
},
{
"from": [7, 14, 9],
"to": [9, 15, 10],
"rotation": {"angle": 0, "axis": "y", "origin": [7, 14, 9]},
"faces": {
"north": {"uv": [8.75, 7, 9.25, 7.25], "texture": "#0"},
"east": {"uv": [9, 4.75, 9.25, 5], "texture": "#0"},
"south": {"uv": [7.25, 8.75, 7.75, 9], "texture": "#0"},
"west": {"uv": [5, 9, 5.25, 9.25], "texture": "#0"},
"up": {"uv": [9.25, 7.5, 8.75, 7.25], "texture": "#0"},
"down": {"uv": [8.25, 8.75, 7.75, 9], "texture": "#0"}
}
},
{
"from": [7, 15, 10],
"to": [9, 16, 13],
"rotation": {"angle": 0, "axis": "y", "origin": [7, 15, 10]},
"faces": {
"north": {"uv": [8.75, 8, 9.25, 8.25], "texture": "#0"},
"east": {"uv": [8, 2.5, 8.75, 2.75], "texture": "#0"},
"south": {"uv": [8.25, 8.75, 8.75, 9], "texture": "#0"},
"west": {"uv": [2.75, 8, 3.5, 8.25], "texture": "#0"},
"up": {"uv": [5.5, 7.75, 5, 7], "texture": "#0"},
"down": {"uv": [7.5, 5, 7, 5.75], "texture": "#0"}
}
},
{
"from": [7, 16, 7],
"to": [9, 17, 13],
"rotation": {"angle": 0, "axis": "y", "origin": [7, 16, 7]},
"faces": {
"north": {"uv": [8.5, 6.25, 9, 6.5], "texture": "#0"},
"east": {"uv": [7, 4.5, 8.5, 4.75], "texture": "#0"},
"south": {"uv": [6.5, 8.5, 7, 8.75], "texture": "#0"},
"west": {"uv": [7, 4.75, 8.5, 5], "texture": "#0"},
"up": {"uv": [5, 7, 4.5, 5.5], "texture": "#0"},
"down": {"uv": [5.5, 5.5, 5, 7], "texture": "#0"}
}
},
{
"from": [6, 6, 6],
"to": [7, 10, 10],
"rotation": {"angle": 0, "axis": "y", "origin": [5, 6, 6]},
"faces": {
"north": {"uv": [8, 0.5, 8.25, 1.5], "texture": "#0"},
"east": {"uv": [4, 3.5, 5, 4.5], "texture": "#0"},
"south": {"uv": [0.75, 8, 1, 9], "texture": "#0"},
"west": {"uv": [4, 4.5, 5, 5.5], "texture": "#0"},
"up": {"uv": [1.25, 9, 1, 8], "texture": "#0"},
"down": {"uv": [1.5, 8, 1.25, 9], "texture": "#0"}
}
},
{
"from": [9, 6, 6],
"to": [10, 10, 10],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 6, 6]},
"faces": {
"north": {"uv": [1.5, 8, 1.75, 9], "texture": "#0"},
"east": {"uv": [5, 3.5, 6, 4.5], "texture": "#0"},
"south": {"uv": [8, 1.5, 8.25, 2.5], "texture": "#0"},
"west": {"uv": [5, 4.5, 6, 5.5], "texture": "#0"},
"up": {"uv": [2, 9, 1.75, 8], "texture": "#0"},
"down": {"uv": [2.25, 8, 2, 9], "texture": "#0"}
}
}
]
}

View File

@ -0,0 +1,21 @@
{
"credit": "Made with Blockbench",
"texture_size": [64, 64],
"textures": {
"1": "keeblarcraft:block/money_block"
},
"elements": [
{
"from": [0, 0, 0],
"to": [16, 16, 16],
"faces": {
"north": {"uv": [0, 0, 4, 4], "texture": "#1"},
"east": {"uv": [0, 0, 4, 4], "texture": "#1"},
"south": {"uv": [0, 0, 4, 4], "texture": "#1"},
"west": {"uv": [0, 0, 4, 4], "texture": "#1"},
"up": {"uv": [0, 0, 4, 4], "texture": "#1"},
"down": {"uv": [0, 0, 4, 4], "texture": "#1"}
}
}
]
}

View File

@ -0,0 +1,3 @@
{
"parent": "keeblarcraft:block/10_cent_coin"
}

View File

@ -0,0 +1,3 @@
{
"parent": "keeblarcraft:block/10_dollar"
}

View File

@ -0,0 +1,3 @@
{
"parent": "keeblarcraft:block/1_dollar"
}

View File

@ -0,0 +1,3 @@
{
"parent": "keeblarcraft:block/20_dollar"
}

View File

@ -0,0 +1,3 @@
{
"parent": "keeblarcraft:block/25_cent_coin"
}

View File

@ -0,0 +1,3 @@
{
"parent": "keeblarcraft:block/5_cent_coin"
}

View File

@ -0,0 +1,3 @@
{
"parent": "keeblarcraft:block/5_dollar"
}

View File

@ -0,0 +1,3 @@
{
"parent": "keeblarcraft:block/cent_coin"
}

View File

@ -1,3 +0,0 @@
{
"parent": "keeblarcraft:block/example_statue"
}

View File

@ -0,0 +1,3 @@
{
"parent": "keeblarcraft:block/money_block"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 267 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 291 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 198 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 782 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 154 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1012 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 791 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 267 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 291 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 198 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 782 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

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:cent_coin"
}
],
"rolls": 1.0
}
]
}

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:money_block"
}
],
"rolls": 1.0
}
]
}

Some files were not shown because too many files have changed in this diff Show More