Craft Dynamic Upgrades in Minecraft

CardEngine is a premium developer-friendly library that implements an interactive card-selection upgrade system. Players level up through custom actions or vanilla XP and choose from randomly fanned-out upgrade cards to obtain permanent stats or special skills.

โœจ

Data-Driven Cards

Generate upgrade cards dynamically in Java or customize them via auto-generated JSON files.

๐Ÿ“Š

Scrollable Stats Screen

Aggregates stat values and displays them on a clean, scrollable 2-column list overlay (L-key).

โšก

Smooth Animations

Fade-in select transitions and reactive, prediction-backed button mechanics ensure no lag.

Live Playground

Try drawing upgrades!

Engine Level: 1 Rolls: 3
0 / 50 XP
Active Upgrade Stats
โค๏ธ HP: +0
๐Ÿ—ก๏ธ AD: +0
โšก AS: +0
๐Ÿ‘Ÿ MS: +0
๐Ÿงช XP Boost: +0
๐Ÿ’ฅ Crit: +0

Select an Upgrade Card

Remaining Rolls: 3

Developer Integration Guide

Follow this 3-step guide to integrate CardEngine and create your own modular upgrades.

1

Configure build.gradle

Add the CardEngine jar file to your project dependencies by configuring a flatDir repository.

repositories {
    flatDir {
        dir 'libs'
    }
}

dependencies {
    //fg.deobf is required to remap the jar correctly in your development environment
    implementation fg.deobf("card_engine:card_engine:1.0.0")
}
2

Register Cards & Mechanics

Inside your mod's initialization phase (FMLCommonSetupEvent), choose one of the options below to register your cards:

Option A: Quick Create (2 Lines)

Perfect for simple cards that link directly to vanilla Minecraft Attributes. CardEngine auto-generates JSON configurations and handles UI selection rendering automatically.

// Line 1: Register the mechanism (binds key to vanilla Attribute)
CardRegistry.registerCard("my_mod:attack_damage", Attributes.ATTACK_DAMAGE);

// Line 2: Register the card (CardEngine handles rendering & JSON generation!)
CardRegistry.register("my_mod:attack_damage_rare", "my_mod:attack_damage");

Option B: Custom Mechanism with @CardParam

For custom logic, create a class implementing CardEngine and declare fields with @CardParam. CardEngine automatically exports these parameters to the card's JSON file.

// 1. Write your custom class implementing CardEngine
public class VampirismUpgrade implements CardEngine {
    @CardParam(10.0) // Exports "heal_ratio" (default 10.0) to JSON config automatically!
    private double heal_ratio;

    @Override
    public void apply(ServerPlayer player) {
        // heal_ratio is automatically injected with the value configured in the JSON file
        player.heal((float) (player.getMaxHealth() * (heal_ratio / 100.0)));
    }
}

// 2. Register both the mechanism class and the card:
CardRegistry.registerCard("my_mod:vampirism", VampirismUpgrade.class);
CardRegistry.register("my_mod:vamp_card", "my_mod:vampirism");
3

Apply Active Upgrades in Forge Events

Retrieve player stats capability from the event listeners and apply custom gameplay scaling accordingly.

@SubscribeEvent
public static void onLivingHurt(LivingHurtEvent event) {
    if (event.getSource().getEntity() instanceof Player player) {
        player.getCapability(PlayerUpgradeProvider.PLAYER_UPGRADE).ifPresent(upgrade -> {
            // Read accumulated stats from the player
            double critChance = upgrade.getStats().getOrDefault("my_mod:crit_chance", 0.0);
            if (critChance > 0.0 && player.getRandom().nextFloat() < critChance) {
                event.setAmount(event.getAmount() * 2.0f); // Deal critical double damage!
            }
        });
    }
}

Agent System Prompt Context

Copy and paste this system prompt context directly into your AI coding assistant (like Claude, ChatGPT, Cursor, or GitHub Copilot) to instantly brief it on CardEngine's APIs, structures, and modding rules.

You are writing a Minecraft 1.20.1 Forge mod that integrates with the CardEngine library.
Follow these API specifications exactly:

1. Package Namespaces:
- net.com.cardengine.api.registries.CardRegistry
- net.com.cardengine.api.registries.CardParam
- net.com.cardengine.api.registries.CardEngine
- net.com.cardengine.capability.PlayerUpgradeProvider

2. Registering upgrade cards:
- Quick Register (Binds key to a Minecraft Attribute):
  CardRegistry.registerCard("modid:stat_key", Attributes.ATTACK_DAMAGE);
  CardRegistry.register("modid:card_id", "modid:stat_key");

- Custom class-based mechanics:
  CardRegistry.registerCard("modid:mech_key", YourClass.class);
  CardRegistry.register("modid:card_id", "modid:mech_key");
  
  YourClass must implement CardEngine. Use `@CardParam(double defaultValue)` on fields to export parameters to the JSON config. CardEngine automatically injects configured values back into these fields at runtime.

3. Reading active upgrade stats:
- Retrieve upgrade stats map:
  player.getCapability(PlayerUpgradeProvider.PLAYER_UPGRADE).ifPresent(upgrade -> {
      double value = upgrade.getStats().getOrDefault("modid:stat_key", 0.0);
  });

4. Critical Modding Caveats:
- The Mythic rarity tier is spelled "mysthic" (with an 'h' after 't' and 's' before 't') in all registration files and JSON config properties. Do not use "mythic".
- Sync player levels by listening to `PlayerXpEvent.XpChange` and respect `event.isCanceled()`.

Frequently Asked Questions

Once registered programmatically, CardEngine will automatically output card configurations as JSON files inside config/card_engine/cards/. Server admins can edit these files to modify icons, values, descriptions, and weights without rebuilding the code.

Yes, all stats and capability variables are tracked and handled entirely on the logical server, and packets are synchronized to clients dynamically to render overlays and indicators on screen accurately.

Admin operators can execute the game command /cardengine draw <player> to trigger a draft screen, or use the developer API upgrade.setPendingDraws(count) followed by upgrade.triggerPendingDraw(player) in code.

Have Questions or Custom Requests?

Fill out the form below, and we'll reply with integration tips!