Internal Documentation

MCCraft System Logic

A deep dive into the custom crafting engine, explaining the async database architecture, memory caching, and event-driven GUI interactions.

Async SQLite/MySQL
Base64 Serialization
Event Listeners
In-Memory Cache

System Overview

MCCraft creates specific "Station Types" (e.g., a Magic Bench). Each station has a unique "Head Item". When a player interacts with this item, a custom GUI opens. The system matches the player's 3x3 grid against a loaded cache of recipes to produce a result.

1. Data Persistence & Caching

To ensure server performance, the plugin avoids querying the database during gameplay events.

  1. Startup Logic: When the plugin enables, MCCraftProvider initializes the database (MySQL or SQLite) and immediately runs populateCache(). This pulls every registered recipe and station type into the RAM (Heap).
  2. The Recipe Cache: The RecipeCache singleton stores data in a ConcurrentHashMap.
    Key: Station Type string.
    Value: A list of CachedRecipe objects (which contain the pre-parsed ItemStacks).
  3. Saving (Upsert): When an admin saves a recipe, it is written Asynchronously to the DB to prevent lag, but the Cache is updated Synchronously immediately. This ensures the recipe works instantly without waiting for the DB write to finish.
  4. Serialization: Items are not stored as JSON. The entire 3x3 grid + Result item (10 items total) are serialized into a binary byte array and converted to a Base64 string. This string is what is stored in the contents column of the database.

2. Owner / Admin Workflow

How new stations and recipes are managed.

Step A: Define a Type

Command: /craft type create <name> <hand|base64>

This registers a "Category". You must provide a specific item (texture) that represents this station. This is saved to the mccraft_type table.

Step B: Create Recipe

Command: /craft create <type> <id>

This opens the Editor GUI. The plugin recognizes this GUI because the window title contains the Recipe ID in brackets (e.g., [my_sword]).

Step C: The Save Logic

There is no "Save" button. The CraftingGUIListener listens for the InventoryCloseEvent. If the closed inventory is an Editor:
1. It scans the 3x3 grid and the Result slot.
2. Serializes them to Base64.
3. Pushes to DB and Cache automatically.

Step D: Bulk Editing (The Editor List)

Command: /craft editor <type>

Purpose: Lists all registered recipes for a specific station type in a GUI.
Logic:
1. EditorListGUI queries the DB for all recipes of that type.
2. It displays the Result Item of each recipe as a clickable icon.
3. Listener: EditorListGUIListener detects clicks on these icons.
4. Action: It fetches the full recipe data and re-opens the Editor GUI (from Step B) pre-filled with that recipe's grid.
5. Closing this new window saves any edits back to the existing ID.

3. Player Workflow

How players interact with the system.

Step A: Getting the Station

Players obtain the station item (usually distributed by admins via /craft get).
Logic: This item has a hidden NBT tag (PersistentDataContainer) storing the mccraft_type key.

Step B: Opening the Interface

Listener: HeadItemInteractListener.
When a player Right Clicks holding the station item:
1. The event cancels (block is not placed).
2. The system checks if recipes exist for this type.
3. CraftingGUI.openCraftingView is triggered.

Step C: Crafting Logic

Listener: CraftingGUIListener (Click/Drag events).
Every time the player places an item in the grid, the plugin runs a Matrix Match against cached recipes.
If Match: The result slot is populated visually.
If Pickup: Ingredients are decremented.
Consumption Rule: If the station type is default, the station item is not consumed. For all other types, one unit of the station item is consumed from the player's inventory each time they craft a result item.

4. Security & Validation Listeners

  • ItemDropProtectionListener: Blocks Q-drop / drag-drop of station items with the mccraft_type key only while the crafting GUI is open (non-editor). Outside the crafting view (and inside the editor), drops are allowed. This keeps the crafting tool safe without blocking normal gameplay.
  • HeadItemInteractListener (BlockPlace): Ensures that if a player tries to place the Head Item against a wall or floor, the action is cancelled. The item is meant to be a handheld "key" to open the GUI, not a physical block in the world.
  • Inventory Permissions: The Editor GUI fills unused slots with Red Stained Glass. The Listener cancels any click on these filler items to prevent players from stealing GUI elements.