Patchnote
Complete changelog of new features, changes, and bug fixes for each EriAPI release.
v1.6.8 May 07, 2026
Critical fix — EventBuilder.filter() overwrote previous filters
Each call to .filter(...) on an EventBuilder replaced
the previous filter outright instead of combining them. As a result, listeners
configured with multiple chained .filter(...) calls only honored
the last one, leaking events that should have been rejected by
earlier filters.
Real-world example: a PlayerTickEvent handler scoped to a specific
dimension, configured like this:
EriEvents.on(TickEvent.PlayerTickEvent.class)
.filter(e -> e.phase == TickEvent.Phase.END)
.filter(e -> e.player.world.provider.getDimension() == TARGET_DIM)
.filter(e -> !e.player.world.isRemote) // this filter OVERWROTE the previous ones
.handle(e -> applyEffect(e.player));
The dimension check was lost, and the effect was applied across every dimension on the server side.
Fixed: successive calls to filter(...) are now combined with
logical AND via Predicate.and(). All predicates must return
true for the handler to be invoked. The expected and natural behavior
is restored, with no impact on listeners that used a single filter.
v1.6.7 May 05, 2026
Fix — 3D animated models offset from their hitbox
Blockbench models rendered by AnimatedEntityRenderer appeared visually
shifted by half a block on X and Z compared to the entity hitbox.
Cause: Blockbench centers models on (8, 0, 8) in pixels (= 0.5, 0, 0.5 in GL units),
but the entity origin (posX/posY/posZ) is the bottom-center
of the bounding box. Without an offset, the model's (0,0,0) corner is rendered at the
hitbox center.
Fixed in doRender(): a GlStateManager.translate(-0.5f, 0.0f, -0.5f)
is now applied right after the yaw rotation to recenter the model. Yaw rotation now
happens around the model's actual vertical axis (its center) instead of an off-center
pivot. Cascade-fixes movement animations that looked buggy — they were
simply applied around the wrong pivot.
Fix — Hostile mobs targeting Creative / Spectator players
The HOSTILE_MELEE, HOSTILE_RANGED and BOSS presets
of EriEntity created EntityAINearestAttackableTarget tasks
without any predicate. Result: staff/admins in creative mode were targeted by mobs
like any survival player.
EriEntityBase,GeneratedEntityandPathfinderBuilder.targetPlayers()— all target tasks aimed atEntityPlayer.classnow use the 6-arg constructor with aPredicate<EntityPlayer>that rejects players inisCreative()orisSpectator().- The predicate is stored as a static singleton per class to avoid one lambda allocation per spawned entity — critical at 500-1000 concurrent players.
Perf — AnimatedEntityRenderer: per-texture draw call batching
The previous implementation called buffer.begin() + tessellator.draw()
per face. A model with 200 elements and 6 faces per element therefore
issued 1200 GPU draw calls per entity per frame — catastrophic
FPS drop with even a handful of visible entities.
Refactor of renderElement(): faces of the same element are now grouped by
texture into a single begin() / draw() pair. Most elements
only use one or two textures — the reduction is typically 6x to 12x
depending on the model. For a complex 200-element single-texture mob:
1200 draw calls -> 200.
- New internal methods:
resolveTexture(String) -> ResourceLocation(resolution without binding) andappendFaceVertices(buffer, ...)(appends a face's 4 vertices into an already-open buffer). - The old
drawFace()method was replaced — no public API change, only the internal pipeline. - Compatible with all existing animations (translation, rotation, scale, cumulativeRotation, texture overrides). Matrix transforms are unchanged; only the draw-flushing is batched.
100% backward compatible — no public API change.
v1.6.6 May 05, 2026
Fix — EriEntityBase: eriDef resolved before AI / attribute setup
The EntityLiving constructor calls applyEntityAttributes() and
initEntityAI() via super(world) before the
EriEntityBase subclass can assign this.eriDef. Result: mobs
spawned with no AI and vanilla default stats, regardless of what was declared via
EriEntity.create(...).
Restructured: the applyEntityAttributes() and initEntityAI()
overrides are now no-ops, and the constructor calls applyEriAttributes() +
setupEriAI() after resolving eriDef via DEF_BY_CLASS.
Subclasses of EriEntityBase (used for custom Java logic) now correctly
receive their stats, AI and hitbox.
v1.6.5 May 02, 2026
Java animations on the builder — .javaAnimation()
The EriAnimBlock and EriEntity builders now expose
.javaAnimation(String name, EriAnimJava anim) to register a Java animation
directly on the fluent builder — no more need to create a custom
TileEntity subclass nor to call addJavaAnimation() manually
in the constructor. Anims are stored in the BlockDefinition /
EntityDefinition and retrievable via the matching helpers.
EriAnimBlock.javaAnimation(name, anim)— appends to theAnimBlockDefinition.javaAnimationsmap.GeneratedBlock.createTileEntity()now callsconfigure()and loops to wire the anims onto the auto-generatedAnimatedBlockTileEntityGeneric.EriEntity.javaAnimation(name, anim)— appends to theEntityDefinition.javaAnimationsmap. Retrievable viaContentRegistry.getEntityDef(modId, name).getJavaAnimation("idle")in the entity constructor.- Coexists with
.animation()—.erianimfiles andEriAnimJavaclasses can be mixed on the same builder. - New helper
ContentRegistry.getEntityDef(modId, registryName)— direct lookup by name (previously you had to iterategetEntityDefs()).
Fix — AnimatedBlockTileEntityGeneric.configure() never called
Latent bug since v1.6.4: the no-arg constructor + configure() pattern of
AnimatedBlockTileEntityGeneric was never invoked — animated
blocks generated by EriAnimBlock without a custom .tileEntity(MyTE.class)
had no modelId, no animFileId, and no defaultAnimation.
Resolved in GeneratedBlock.createTileEntity(): configuration is now applied at
TE creation, alongside the Java anims declared on the builder.
100% backward compatible — existing .erianim files and
custom TEs continue to work unchanged.
v1.6.4 May 02, 2026
Java Animation API — write animations in pure Java
New API to write animations directly in Java, bypassing .erianim files.
Ideal for procedural animations (sin/cos oscillations, reactions to entity state, parametric movements)
impossible or tedious to express in JSON. Coexists with .erianim via the same
te.playAnimation("name") API.
EriAnimJava— abstract class to extend. Two methods:defineKeyframes(ctx)(declarative, cached) andcompute(ctx, pose)(procedural, per-frame).duration()required,endBehavior()optional.AnimContext— context withanimTick,partial,worldTick,target, helpersasEntity()/asTileEntity(), and DSLat(tick).group(name)....GroupPoseBuilder— fluent API accessible viapose.group("name").add*methods (additive on keyframes) andset*(replace).- Overlay —
te.playOverlay("name", anim)plays a second Java anim on top of the main one (overlay wins on touched groups). Client-local, never goes through packets. - Registration —
te.addJavaAnimation("walk", new WalkAnim())in the TileEntity constructor. Registry shared server+client.
See the full documentation in Animation System — Java Animation API.
No bug fixes — additions only, 100% backward compatible. Existing .erianim
files continue to work unchanged.
v1.6.1 April 28, 2026
ListRenderContext — Proportional vertical offset (drawTextProp)
New method ListRenderContext.drawTextProp(String, int offsetX, int offsetYPermil, int maxWidth, int color).
Unlike drawText() where offsetY is in raw screen pixels,
drawTextProp expresses the vertical offset in permil of the row height
(1/1000) — the layout stays correct at every window size.
Symptom before: a fixed -14 px offset that correctly placed the name above the center
at fullscreen (itemHeight ~96 px) pushed the text out of the row bounds in a smaller
window when the row was resized. drawTextProp(text, x, -150, w, color) places the
text ~15% of the row height above the center, regardless of the actual row height.
// BEFORE — offsetY in screen pixels (breaks in small windows)
ctx.drawText(name, textX, -14, textMaxW, 0xFFFFFFFF);
ctx.drawText(cost, textX, +14, textMaxW, 0xFF4ADE80);
ctx.drawText(status, statusOffsetX, -14, statusW + gap, 0xFFBB55FF);
// AFTER — offset in permil of the row height (correct at every resolution)
ctx.drawTextProp(name, textX, -150, textMaxW, 0xFFFFFFFF);
ctx.drawTextProp(cost, textX, +150, textMaxW, 0xFF4ADE80);
ctx.drawTextProp(status, statusOffsetX, -150, statusW + gap, 0xFFBB55FF);
The original drawText method is preserved — no breaking change.
v1.6.0 April 24, 2026
EriBlock — Block variants and entity callbacks
The EriBlock builder gains six new methods that cover most vanilla patterns
(logs, leaves, plants) and expose entity walk/collision callbacks.
No more custom BlockRotatedPillar or BlockLeaves subclasses:
a simple .logLike() or .leavesLike(sapling) is enough.
.renderLayer(BlockRenderLayer)— sets the client render layer (SOLID, CUTOUT, CUTOUT_MIPPED, TRANSLUCENT). Required for leaves, plants, glass..onEntityWalk(TriConsumer<World, BlockPos, Entity>)— low-level callback when an entity walks on top of the block..onEntityCollision(TriConsumer<World, BlockPos, Entity>)— callback when an entity passes through the block (useful for traps / toxic plants)..logLike()— generates aBlockRotatedPillar(AXIS property) for orientable logs..leavesLike(Block sapling)— generates a fullBlockLeaves(CHECK_DECAY + DECAYABLE, natural decay, 5% sapling drop). Forces CUTOUT_MIPPED automatically..plantLike()— decorative plant: reduced hitbox, no collision, CUTOUT. The blockstate must point toblock/cross.
TriConsumer — New functional interface
Java 8 does not provide a native TriConsumer<A, B, C>. EriAPI adds this interface
in fr.eri.eriapi.content.TriConsumer for 3-parameter callbacks (used by
onEntityWalk / onEntityCollision and available for your own builders).
Internal refactor — GeneratedBlockCommons
To avoid duplication between the 4 generated block variants (GeneratedBlock,
GeneratedLogBlock, GeneratedLeavesBlock, GeneratedPlantBlock),
shared logic (drops, hitbox, callbacks, TileEntity) has been extracted into
GeneratedBlockCommons. No visible API change for users.
Full example
// Custom tree log (automatic X/Y/Z axis)
Block ERINA_LOG = EriBlock.create("mymod", "erina_log")
.material(Material.WOOD)
.hardness(2.0f)
.harvestTool("axe", 0)
.soundType(SoundType.WOOD)
.logLike()
.register();
// Leaves that decay + 5% sapling drop
Block ERINA_LEAVES = EriBlock.create("mymod", "erina_leaves")
.material(Material.LEAVES)
.hardness(0.2f)
.soundType(SoundType.PLANT)
.leavesLike(ERINA_SAPLING)
.register();
// Toxic plant that damages on contact
Block TOXIC_PLANT = EriBlock.create("mymod", "toxic_plant")
.material(Material.PLANTS)
.hardness(0.0f)
.soundType(SoundType.PLANT)
.plantLike()
.onEntityCollision((world, pos, entity) -> {
if (entity instanceof EntityLivingBase && !world.isRemote) {
((EntityLivingBase) entity).addPotionEffect(
new PotionEffect(MobEffects.POISON, 60, 0)
);
}
})
.register();
v1.5.2 April 22, 2026
EriBlock — Custom hitboxes (.hitbox / .hitboxes)
EriBlock now supports custom collision and selection boxes directly in the builder,
without manually subclassing Block.
-
.hitbox(AxisAlignedBB)— Replaces the default full-block hitbox with a single custom box. Automatically setsisFullCubeandisOpaquetofalse. Unit:1.0 = 1 block = 16 pixels. -
.hitboxes(AxisAlignedBB...)— Defines multiple independent collision boxes. Each box is tested separately during entity collision viaaddCollisionBoxToList. The selection outline (hover highlight) shows the union of all boxes. Automatically setsisFullCubeandisOpaquetofalse.
// Single hitbox — half-block height (1.0 = 1 block = 16 pixels)
EriBlock.create("mymod", "half_slab")
.material(Material.ROCK)
.hardness(2.0f)
.hitbox(new AxisAlignedBB(0, 0, 0, 1, 0.5, 1))
.register();
// Multiple hitboxes — flat base + central pillar
EriBlock.create("mymod", "machine")
.material(Material.IRON)
.hardness(4.0f)
.hitboxes(
new AxisAlignedBB(0, 0, 0, 1, 0.25, 1),
new AxisAlignedBB(0.25, 0.25, 0.25, 0.75, 1, 0.75)
)
.register();
v1.5.1 April 18, 2026
Element-level animation (elementTracks)
.erianim.json animations can now target individual elements inside a
Blockbench group, not only the group as a whole. Each element has its own
rotationOrigin (pivot) defined in the model, and animations can apply
rotation, translation, scale, visibility and spin around that pivot.
Fully backward compatible: existing animations without elementTracks
render exactly as before.
- JSON format — New optional
"elementTracks"field alongside"tracks"in eachAnimationDef. Keys use the"groupName:elementIndex"format (e.g."body:2"). The structure of an element track is identical to a group track (rotation,rotate,translation,scale,visible,spin). - AnimationDef — New
getElementTracks()getter,hasElementTracks()helper, shortcutgetElementTrack(String groupName, int elementIndex), and static utilityelementTrackKey(String, int)to format the canonical key. - AnimationPose — New
elementPosesmap parallel to the existinggroupPoses, withgetElement(groupName, elementIndex)andgetOrCreateElement(...). The methodsreset(),copyFrom()andlerpToward()now include element poses. - AnimationController — The sampler iterates
elementTracksafter the group tracks and populates element poses via a factored helperpopulatePoseFromTrack(...). Animation-to-animation blending (START / END) also applies to element poses. - AnimatedBlockTESR / AnimatedEntityRenderer — Both renderers read the element pose and apply a local OpenGL matrix around each element's
rotationOriginbefore rendering its faces. Static JSON rotation is preserved and applied first; the animated pose is applied on top.
{
"formatVersion": 1,
"modelId": "mymod:block/turret",
"animations": {
"idle": {
"length": 40,
"loop": true,
"tracks": {
"base": { }
},
"elementTracks": {
"body:2": {
"rotation": [
{ "tick": 0, "value": [0, 0, 0] },
{ "tick": 20, "value": [0, 180, 0] },
{ "tick": 40, "value": [0, 360, 0] }
]
}
}
}
}
}
AnimationPose pose = controller.getCurrentPose(partialTicks);
AnimationPose.GroupPose bodyPose = pose.getGroup("body");
AnimationPose.GroupPose elemPose = pose.getElement("body", 2);
if (elemPose != null && !elemPose.visible) return;
Bug fixes
- No bug fixes in this release — additions only, 100% backward compatible.
v1.4.2 April 17, 2026
EriProjectile — custom projectile builder
New fluent builder for declaring custom projectiles (thrown entities) without Forge
boilerplate. Supports velocity, direct damage and area-of-effect (AOE) damage, physics
(gravity, drag), hit effects, and lifecycle callbacks. Projectiles are generated at
runtime via GeneratedProjectile and allocated a slot in
GeneratedProjectileSlots (pool of 32 static subclasses) — CleanRoom
compatible, no ASM.
- EriProjectile — Fluent builder:
model(),texture(),velocity(),gravity(),drag(),damage(),aoe(),effectOnHit(),onHitBlock(),onHitEntity(),onTick(),register(). - ProjectileDefinition — Configuration POJO containing all projectile parameters.
- GeneratedProjectile / GeneratedProjectileSlots — Entities generated dynamically from the definition, each in its own slot to respect Forge's "one Class per EntityEntry" constraint.
- ContentRegistry — Automatic registration of projectiles during the
RegistryEvent.Register<EntityEntry>event.
Bug fixes
- No bug fixes in this release — additions only.
v1.4.1 April 17, 2026
PathfinderBuilder — custom AI tasks for EriEntity
Fluent builder to configure an EriEntity's AI tasks beyond the presets
(PASSIVE, HOSTILE_MELEE, ...). Lets you add fine-grained
behaviors (swim, melee attack, wander, panic, open doors, leap at target, etc.) in
a single chain. Tasks are stored as factories
(Function<EntityLiving, EntityAIBase>) to defer instantiation
until the entity exists.
- API —
EriEntity.ai(ai -> ai.swim().meleeAttack(1.0, false).wander(1.0).watchPlayers(12f).lookIdle().targetPlayers().hurtByTarget(true)) - Goals available —
swim,meleeAttack,wander,watchClosest,watchPlayers,lookIdle,panicOnHurt,leapAtTarget,avoidEntity,openDoors,task(...)(custom). - Target goals available —
targetPlayers,targetClass,hurtByTarget,targetTask(...)(custom).
Bug fixes
- No bug fixes in this release — additions only.
v1.4.0 April 17, 2026
Full Entity Framework — stats, AI presets, drops, spawn rules, callbacks
Major extension of EriEntity (39 fluent methods) to declare a full entity
in a single chain: stats (health/armor/damage/speed/range), sounds, AI preset
(PASSIVE / HOSTILE_MELEE / HOSTILE_RANGED /
NEUTRAL / BOSS), drops, spawn rules (biomes/light/height/dimension),
and lifecycle callbacks (onSpawn, onDeath, onUpdate,
onAttack, onHurt, onInteract).
- EntityDefinition — Extended with all the new fields + inner class
EntityDrop. - AiPreset / EriSpawner — New configuration types for behavior and spawning.
- GeneratedEntity — Generic entity (extends
EntityMob) that applies the definition:applyEntityAttributes,initEntityAI(switches on preset),dropLoot,getExperiencePoints, sounds.onSpawnuses an NBT-persisted flag to avoid re-fires on chunk reload. - GeneratedEntitySlots — Pool of 32 static subclasses (
Slot0..Slot31) to respect Forge 1.12.2's "one Class per EntityEntry" constraint without ASM (CleanRoom compatible). - ContentRegistry.onRegisterEntities — Automatic registration (egg, tracker, spawn rules) and client-side wiring of
AnimatedEntityRenderer.
Bug fixes
- No bug fixes in this release — additions only.
v1.3.2 April 16, 2026
AnimatedItemController: animation playback for animated items
Items created with EriItem.animatedModel() can now play
.erianim.json animations in real time. The new
AnimatedItemController exposes a simple static API
(play / stop / isPlaying) and shares playback
state per modelId for every item using the same model.
- AnimatedItemController — New client-only controller in
fr.eri.eriapi.anim. Handles looping (EndBehavior LOOP), one-shot playback, and per-modelId state. - AnimatedBlockItemRenderer — The renderer now queries the controller every frame and feeds the pose to the TESR pipeline through a proxy TileEntity. No more static pose.
EriItem.create("mymod", "sword")
.animatedModel("mymod:item/sword")
.onRightClick(ctx -> {
if (ctx.world.isRemote) {
AnimatedItemController.play("mymod:item/sword", "swing");
}
})
.register();
Bug fixes
- Documentation
animation.html— removed the “no animation playback” warning and replaced it with documentation for the new controller.
v1.3.1 April 16, 2026
EriItem: .animatedModel() support for items with Blockbench 3D rendering
Items created via EriItem can now use an animated 3D Blockbench model
when held or displayed in inventory, using the new .animatedModel(String modelId) method.
Rendering is delegated to the same AnimatedBlockItemRenderer used for animated blocks.
- EriItem.animatedModel(String) — New fluent method that configures an item to use a Blockbench model in
"modid:item/name"format. - ContentRegistry — Automatically wires the TEISR (TileEntityItemStackRenderer) on animated items client-side, and registers the
builtin/entitymodel so Forge delegates rendering. - ItemDefinition — New
animatedModelIdfield to store the model identifier.
EriItem.create("eriniumfaction", "faction_sword")
.maxStackSize(1)
.rarity(EnumRarity.EPIC)
.animatedModel("eriniumfaction:item/faction_sword")
.register();
Bug fixes
- No bug fixes in this release — additions only.
v1.3.0 April 16, 2026
New: AnimatedEntityRenderer — animated rendering for entities
Extension of the Blockbench rendering pipeline to entities. The renderer uses exactly the same
pipeline as AnimatedBlockTESR (groups, elements, faces, UV, animated textures).
- AnimatedEntityRenderer<T> —
RenderLivingthat renders a Blockbench model with animations. Static factory methods for registration viaRenderingRegistry. - IAnimatedEntity — Interface that entities implement to provide their animation pose to the renderer. Methods
getCurrentPose(partialTicks)andgetAnimState().
New: EriEntity builder
Fluent builder to define custom entities with Blockbench model, textures, animations, hitbox,
passenger seats, and spawn eggs. Definitions are stored in ContentRegistry for
the mod to register in Forge manually.
- EriEntity — Fluent builder:
model(),texture(),animation(),hitbox(),seat()(3 overloads),spawnEgg(),creativeTab(),register(). - EntityDefinition — Configuration POJO containing all entity parameters.
- EntitySeat — Passenger seat definition with Blockbench position, yaw offset, attached group, and camera lock.
- ContentRegistry.registerEntity() /
getEntityDefs()— Storage and access for entity definitions.
Category field in AnimationFile
.erianim.json files now support an optional "category" field
("block", "item", or "entity"). This field is informational
and indicates which renderer type expects this animation file. Backwards compatible — defaults to "block".
Bug fixes
- No bug fixes in this release — additions only.
v1.2.1 March 26, 2026
Label: new scaleToFit() and wrapped() modes
- scaleToFit(boolean) — Instead of truncating text with "...", automatically reduces the text scale so it fits exactly within the component width. Mutually exclusive with
wrapped()(wrapped takes priority). - wrapped(boolean) — Text wraps to multiple lines at word boundaries. If the wrapped content exceeds the component height, vertical mouse scroll is enabled (scissor clipped). Mutually exclusive with
scaleToFit()(wrapped wins).
Tooltip: literal \n support from .lang files
Tooltip.render() now normalizes literal \\n (from .lang files) to real newlines before splitting. Both \n in Java strings and \\n from .lang files now work.
Dropdown: deferred rendering (always on top)
- The drop-down list is now rendered AFTER all other components (deferred rendering), ensuring it always appears on top.
- Click handling works even when the Dropdown is inside a
ScrollPanel. - New static methods:
Dropdown.renderDeferredDropdown(),Dropdown.handleDeferredClick(),Dropdown.resetState(). EriGuiScreencalls these methods automatically — no action needed for standard screens.
ItemStackRenderer: separate showDurability() from showCount()
New method showDurability(boolean) independent from showCount(boolean). Allows rendering the durability bar without the count text, or vice versa. Both default to true.
Bug fixes
- No bug fixes in this release — additions and improvements only.
v1.2.0 March 22, 2026
Overlay editor: auto-snap alignment system
The in-game overlay editor now features an auto-snap system. When dragging an overlay in edit mode, it automatically snaps to the edges and centers of other overlays as well as to screen reference points, enabling precise positioning without manually entering coordinates.
- Overlay edge snapping — The left, right, top and bottom edges of an overlay snap to the corresponding edges of neighboring overlays when within 5 design pixels. 10 snap types are supported: edge-to-edge and center-to-center alignment on both axes.
- Screen edge snapping — The overlay snaps to all four screen borders (x = 0, x = 1920, y = 0, y = 1080) when approaching within 5 design pixels.
- Screen center snapping — The overlay can align to the absolute center of the screen (960, 540), both horizontally and vertically.
- Center-to-center alignment — The horizontal and vertical centers of two overlays can align with each other for symmetric layouts.
- Cyan guide lines — When a snap is active, a semi-transparent cyan guide line appears on the snap axis to visualize the alignment.
- Red overlap indicator — If an overlay overlaps another during dragging, it turns red to signal the overlap.
- Hold Shift to bypass snap — Hold Shift while dragging to disable snapping and move the overlay freely pixel by pixel.
Bug fixes
- No bug fixes in this release — additions only.
v1.1.0 March 22, 2026
New module: Security Framework
Added the fr.eri.eriapi.security package — a complete server-side anti-duplication
and exploit prevention toolkit. Designed for high-player-count servers (500-1000 players).
- GuiRateLimiter — Per-player action throttling with configurable sliding window. Prevents container click spam.
- ItemIntegrityValidator — Snapshot/validate/rollback system to verify that the total item count doesn't change after a container operation. Automatically detects duplication attempts.
- ContainerLock — Synchronized per-key locks to prevent concurrent access to shared containers (e.g. faction chest).
- DupeAlertManager — Real-time alerts sent to all online operators via EriChat when a duplication attempt is detected.
New documentation: Network GUI
Added the Network GUI page documenting the client-server communication
system for GUI interactions: GuiNetworkHandler, IGuiDataReceiver, packet formats,
and complete examples.
GUI documentation expanded
- Added visual effect components:
GradientRectangle,Aurora,Starfield,ParticleSystem,SmokeFog - Network section moved to the dedicated Network GUI page
- Sidebar links updated with Security and Network
Bug fixes
- No bug fixes in this release — additions only.
v1.0.0 Initial release
Included modules
- GUI Framework — Complete UI toolkit in 1920x1080 design pixels with 30+ components, animations, sounds, and automatic scaling.
- Overlay HUD — Draggable overlay system with design-pixel positioning, anchoring, and in-game editor.
- Config System — Annotation-based configuration with auto-generated GUI, client-server sync, and validation.
- Command Framework — Command builder with auto-completion, typed arguments, permissions, cooldowns, and sub-commands.
- Content Builder — Create items, blocks, recipes and entities via fluent API without Forge boilerplate.
- Data & Storage — Persistent storage via annotated POJOs with automatic client sync via
@Sync. - Scheduler — Schedule delayed, repeating, chained, and async tasks.
- Chat Builder — Rich chat messages with colors, clicks, hover, and pagination.
- Capability Helpers — Simplified Forge capabilities via annotations with auto-attach and auto-sync.
- Event Simplifier — One-line Forge event subscriptions with filters, priority, and expiration.
- Keybinding Manager — Fluent keyboard shortcuts with combos, double-tap, hold, and contexts.
- Network GUI — Client-server communication for GUI interactions.