A puzzle mod that adds word creation and number guessing to Minecraft gameplay.
CharmedChars Version History
Version 1.4.1 - Colored Glass & Safety Enhancements
Release Date
2026-01-19
Overview
Enhancement release adding colored glass support to the Glassing Beds feature and comprehensive safety documentation. The glass color now matches the bed color used for the explosion, allowing decorative builds with colored glass "paintings" in lava lakes.
Changes
New Features ⭐
Colored Glass Creation
- Bed Color Mapping: Glass color matches the bed color used for explosion
- WHITE beds → Clear glass (Material.GLASS, unstained)
- RED beds → Red stained glass (Material.RED_STAINED_GLASS)
- BLUE beds → Blue stained glass (Material.BLUE_STAINED_GLASS)
- All 16 Minecraft bed colors supported
- String Parsing Logic: Extracts color from bed Material name (e.g., "RED_BED" → "RED")
- Material Mapping: Constructs stained glass material name (e.g., "RED" → "RED_STAINED_GLASS")
- Fallback Safety: Falls back to clear glass if Material.getMaterial() returns null
- Decorative Builds: Allows "painting" lava lakes with multicolored glass patterns
Documentation Enhancements 📚
Safety Warnings Added (PLAY_INSTRUCTIONS.md)
- Overlapping Explosions:
- Warning that multiple bed explosions can destroy previously-created glass
- Explosions destroy blocks before converting lava
- Plan bed placements carefully to avoid overlap
- Lava Flow Limitations:
- Not all lava flows guaranteed to stop
- Only converts lava within 5-block radius
- Hidden sources outside radius continue flowing
- Broken glass from overlapping explosions allows new flows
- Underground Lava Discovery:
- Use same caution as without glassing beds
- Feature converts existing lava but doesn't prevent new flows
- Always mine carefully around suspected lava lakes
- Maintain fire resistance potions and escape routes
- Ancient Debris Mining:
- Consider mining in different, safer areas
- Don't rely on glassing beds as only safety measure
- Use traditional safety methods (fire resistance, careful digging, escape routes)
New FAQ Entries
- "Why does lava keep flowing even after I use glassing beds?"
- "Is it safe to do ancient debris mining with glassing beds?"
- "What colors of glass can I create?"
- "Can I get clear glass instead of colored?"
- "Can I mix colors in one lava lake?"
Example Updates
- Added Example 4: Colored Glass demonstration in PLAY_INSTRUCTIONS.md
- Shows creating RED, BLUE, and clear glass in same lava lake
Configuration Documentation
- Updated config.yml with colored glass feature comment
- Explains white → clear, other colors → matching stained glass
Code Changes 🔧
Modified: GlassingBedsListener.kt
- Lines 133-143: Added bed color detection and glass type determination
val bedType = explodedBlock.type val glassType = if (bedType == Material.WHITE_BED) { Material.GLASS // White beds create clear glass } else { val bedColor = bedType.name.removeSuffix("_BED") Material.getMaterial("${bedColor}_STAINED_GLASS") ?: Material.GLASS } - Line 153: Changed
block.type = Material.GLASStoblock.type = glassType - Lines 162-165: Updated logging to show glass type created
Technical Details
Compatibility
- ✅ 100% Backward Compatible - No breaking changes
- ✅ Works with ItemsAdder, Oraxen, and Nexo
- ✅ No configuration changes required (feature automatic)
- ✅ No database changes
Material System
- Uses Minecraft's Material enum for all bed and glass types
- Supports all 16 bed colors: WHITE, ORANGE, MAGENTA, LIGHT_BLUE, YELLOW, LIME, PINK, GRAY, LIGHT_GRAY, CYAN, PURPLE, BLUE, BROWN, GREEN, RED, BLACK
- 1:1 mapping to stained glass materials
Performance
- No performance impact - single Material lookup per explosion
- String manipulation is trivial (suffix removal + concatenation)
- Glass type determined once per explosion, applied to all converted blocks
Upgrade Instructions
From v1.4.0:
- Stop server
- Replace CharmedChars-1.4.0.jar with CharmedChars-1.4.1.jar
- Start server
- No configuration changes needed - colored glass works automatically
- Feature is automatic - all players can use it immediately
From v1.3.2 or earlier:
- Follow standard upgrade to v1.4.0 first (see v1.4.0 changelog)
- Then upgrade to v1.4.1 as above
Testing
Verified Scenarios:
- ✅ WHITE beds create clear glass
- ✅ RED beds create red stained glass
- ✅ BLUE beds create blue stained glass
- ✅ All 16 bed colors map correctly
- ✅ Fallback to clear glass if Material.getMaterial() fails
- ✅ Logging shows correct glass type name
- ✅ Mixed colors work in same lava lake
Known Issues
None currently reported.
Credits
Development: StephanosBad AI-Assisted Development: Claude Sonnet 4.5 (Anthropic)
- Colored glass feature design and implementation
- Safety documentation enhancements
- FAQ additions and example updates
All AI contributions include Co-Authored-By attribution in git commits.
Version 1.4.0 - Glassing Beds Feature
Release Date
2026-01-16
Overview
Major feature release introducing the Glassing Beds system - a unique Nether mechanic where bed explosions convert nearby lava to glass, gated behind an operator sequence activation requirement. Adds strategic resource gathering and dimension control to enhance Nether gameplay.
Changes
New Features ⭐
Glassing Beds System
- Bed Explosion Mechanic: Bed explosions in Nether or End convert lava blocks to glass within 5-block cubic radius
- Feature Control: Disabled by default, enabled per-server via
/glassingbeds enablecommand - Admin Command:
/glassingbeds enable/disable/statuswith tab completion for operators - Lava Conversion: Replaces both source and flowing lava blocks with glass blocks
- Y-Level Restriction: Only converts lava at or below Y=28 (configurable) to prevent lava ocean surface abuse
- Radius: 5-block cubic radius from explosion center (11x11x11 cube total)
- Dimension Check: Only works in Nether and End dimensions where beds naturally explode
Operator Activation System 🎯
- Activation Requirement: Players must activate glassing beds each time they enter the Nether
- Sequence Detection: Hit a line of 4 operator blocks (+, -, ×, ÷) with gold/pyrite tool
- Validation Rules:
- Exactly 4 operators in a straight line (horizontal only)
- All 4 must be different operators
- All 4 must be the same color (cyan, magenta, or yellow)
- Any order accepted ("+−×÷" or "÷×−+" both work)
- Must be in Nether dimension
- Requires gold or pyrite tool to activate
- Block Consumption: Successfully activated sequences consume all 4 operator blocks
- Failure Behavior: Invalid sequences break blocks naturally (drop as items if eligible per provider rules)
- Visual Feedback:
- Success: Green bordered message "✦ Glassing Beds ACTIVATED! ✦"
- Failure: Red error messages explaining validation failure reason
- Session Reset: Activation resets when player enters Nether (via portal, teleport, or respawn)
- Per-Player Tracking: Each player has independent activation status
Bed Player Tracking 🛏️
- Two-Block Structure Handling: Tracks both halves of bed structure when clicked
- Reliable Identification: Successfully identifies which player triggered bed explosion
- Safety Fallback: Prevents lava conversion if player cannot be identified
- Location Key System: Uses world name and block coordinates for tracking
- Cleanup: Automatically cleans up tracking data on player disconnect
Event Detection Architecture 🔧
- Dual Event Handlers: Uses both PlayerInteractEvent and BlockDamageEvent for maximum compatibility
- PlayerInteractEvent (LOWEST priority):
- Primary detection method for Oraxen compatibility
- Fires immediately on LEFT_CLICK_BLOCK action
- Used for operator sequence detection
- BlockDamageEvent (LOWEST priority):
- Fallback for Nexo compatibility when Paper block updates disabled
- Same logic as PlayerInteractEvent handler
- Oraxen/Nexo Compatible: Works with all three custom item providers (ItemsAdder, Oraxen, Nexo)
Configuration 📝
New Config Section (config.yml):
# Glassing Beds Feature
glassing-beds:
# Enable/disable the glassing beds feature
enabled: false
# Maximum Y-level for lava-to-glass conversion
# Only lava blocks at or below this Y-level will be converted to glass
# Recommended: 28 (allows underground lava but not ocean surface at Y=31)
max-y: 28
ConfigManager Accessors:
glassingBedsEnabled: Boolean- Feature toggle (default: false)glassingBedsMaxY: Int- Y-level cap (default: 28)
Commands 💬
New Command: /glassingbeds <subcommand>
- Subcommands:
enable- Enable lava-to-glass conversion on bed explosionsdisable- Disable the glassing beds featurestatus- Check if feature is enabled or disabled
- Permission:
charmedchars.admin(operators only) - Aliases: None
- Tab Completion: Suggests subcommands for operators with permission
- Feedback: Colored bordered messages with clear status updates
- Config Persistence: Changes saved to config.yml automatically
Technical Implementation 🔧
File Structure:
GlassingBedsListener.kt(156 lines) - Main feature logic- Bed interaction tracking
- Player identification
- Activation checking
- Lava conversion
OperatorActivationListener.kt(355 lines) - Activation system- Operator sequence detection
- Direction scanning (4 cardinal directions)
- Sequence validation
- Block consumption
- Session reset handling
GlassingBedsCommand.kt(214 lines) - Admin command- Enable/disable/status subcommands
- Tab completion
- Config modification
Sequence Detection Algorithm:
- Player hits operator block with gold/pyrite tool
- Scan 4 cardinal directions (±X, ±Z) for adjacent operator blocks
- If adjacent found, scan bidirectionally along that axis
- Collect all operator blocks and their colors in line
- Validate: exactly 4, all different, same color, in Nether
- Success: Remove blocks, set activation flag, send message
- Failure: Send error message, blocks break naturally
Session Reset Logic:
- PlayerChangedWorldEvent (MONITOR priority) - Primary reset mechanism
- Fires reliably for portal travel between dimensions
- Checks if player entered Nether (any environment change TO Nether)
- Removes player activation status immediately
- PlayerMoveEvent (MONITOR priority) - Fallback for non-portal entry
- Detects dimension change from non-Nether to Nether
- Handles teleport, command-based entry
- PlayerQuitEvent - Memory leak prevention
- Cleans up activation state on disconnect
- PlayerRespawnEvent - Death handling
- Always resets activation on death (new session)
Impact
Compatibility
- 100% Backward Compatible: Existing servers work without changes
- No Database Changes: Structure database format unchanged
- Feature Opt-In: Disabled by default, no gameplay changes unless enabled
- No Breaking Changes: All existing commands and features unchanged
Gameplay Impact
- New Nether Strategy: Bed-based lava removal becomes viable with activation cost
- Resource Sink: Requires operator blocks to activate each Nether visit
- Risk/Reward: Bed explosions still dangerous, activation adds strategic layer
- Dimension Control: Only works in dimensions where beds naturally explode
Server Owner Benefits
- Optional Feature: Can be left disabled for vanilla-like gameplay
- Configurable Y-Level: Adjust max-y to control lava ocean abuse
- Admin Control: Enable/disable via command without restart
- Clear Permissions: charmedchars.admin for full control
Files Modified
Core Listeners:
GlassingBedsListener.kt- NEW: Bed explosion and lava conversionOperatorActivationListener.kt- NEW: Activation sequence system
Commands:
GlassingBedsCommand.kt- NEW: Admin control command
Configuration:
ConfigManager.kt- Added glassingBedsEnabled and glassingBedsMaxY accessorsconfig.yml- Added glassing-beds configuration section
Plugin Registration:
CharmedChars.kt- Registered both listeners and command with tab completionplugin.yml- Added glassingbeds command definition with permission
Upgrade Notes
From v1.3.2:
- Download CharmedChars-1.4.0.jar
- Replace old JAR in
plugins/folder - Restart server
- Feature is disabled by default - no gameplay changes
- Run
/glassingbeds enableto activate feature - Configure max-y in config.yml if desired
For Server Admins:
- Feature is opt-in - no automatic changes to gameplay
- Test activation system with operator blocks first
- Consider Y-level restriction for your world height
- Educate players about activation requirement
For Players:
- Feature requires server admin to enable first
- Must activate by hitting 4 different operator blocks each Nether visit
- Activation resets when leaving and re-entering Nether
- Works with gold or pyrite tools
Known Issues
None currently reported.
Development Notes
AI-Assisted Development:
- Glassing Beds feature developed with assistance from Claude (Anthropic)
- Operator activation system designed with AI guidance
- Bed tracking logic and event priority fixes implemented with AI
- All AI contributions include Co-Authored-By attribution in git commits
Testing:
- Tested on Oraxen server with full portal cycle
- Verified bed tracking with two-block structure
- Confirmed activation reset on dimension change
- Validated Y-level restriction behavior
Version 1.3.2 - Oraxen Compatibility & Behavior Consistency
Release Date
2026-01-13
Overview
Compatibility release adding Oraxen support for number scoring and ensuring consistent block behavior across all three providers. Number blocks now work identically to letter blocks, with proper tool checking and item dropping in all dimensions.
Changes
Critical Fixes 🐛
Fixed Number Scoring on Oraxen (PlayerInteractEvent Support)
- Problem: Number scoring only used BlockDamageEvent, but Oraxen works better with PlayerInteractEvent for custom NoteBlocks
- Impact: Number blocks didn't score on Oraxen servers while letter blocks worked fine
- Root Cause: Letter spelling used BOTH PlayerInteractEvent and BlockDamageEvent, but number scoring only used BlockDamageEvent
- Fix: Added PlayerInteractEvent handler to both number game listeners matching letter system
- Changes:
- Added
onInteractNumberBlock()method handling LEFT_CLICK_BLOCK (primary, Oraxen-compatible) - Kept
onNumberBlockDamage()method for Nexo compatibility (Paper block updates disabled) - Extracted shared logic into
processNumberSequenceScoring()method
- Added
- Files:
FortressNumberGameListener.kt,BastionNumberGameListener.kt - Result: Number scoring now works on all three providers (ItemsAdder, Oraxen, Nexo)
Number Blocks Drop in Overworld/End
- Problem: Number blocks only functioned in the Nether, causing confusion in other dimensions
- Impact: Players hitting 3-digit sequences in Overworld/End would see no feedback
- Fix: Added dimension check AFTER sequence detection to drop blocks as items with feedback message
- Behavior:
- Overworld/End: "Number blocks can only be used in the Nether! Blocks dropped."
- Nether (outside fortress/bastion): "Number sequence detected, but you're not in a fortress or bastion! Blocks dropped."
- Nether (in fortress/bastion): Normal game mechanics (rewards/explosion/feedback)
- Files:
FortressNumberGameListener.kt:130-156 - Result: Number blocks now recoverable like letter blocks when used outside intended location
Consistent Block Breaking Behavior Across Providers
- Problem: Number blocks always cancelled BlockBreakEvent, making them unbreakable with non-gold tools
- Impact: Players couldn't break misplaced number blocks with correct tools (pickaxe/axe) like they could with letter blocks
- Fix: Removed
event.isCancelled = trueto match letter block behavior - Behavior by Provider:
- ItemsAdder: Purple warning, prevents breaking with wrong tools (protected)
- Oraxen: Block breaks according to tool whitelist (drops if correct tool, vanishes if wrong)
- Nexo: Block breaks according to tool whitelist (drops if correct tool, vanishes if wrong)
- Files:
FortressNumberGameListener.kt:333-350,BastionNumberGameListener.kt:290-307 - Result: Number blocks behave identically to letter blocks across all providers
Code Quality 📝
Event Handler Architecture Matches Letter System
- Both number listeners now use dual event handlers like letter spelling
- Shared scoring logic in
processNumberSequenceScoring()method - Consistent debug logging across all event handlers
- Provider abstraction layer used consistently
Comprehensive Debug Logging
- Added event fire detection logs to diagnose provider-specific issues
- Logs show which event triggered (PlayerInteractEvent vs BlockDamageEvent)
- Tool and block type logged at event entry points
- Sequence detection progress logged
Impact
Compatibility
- 100% Backward Compatible: Existing servers work without changes
- No Database Changes: Structure database format unchanged
- No Config Changes: Existing config.yml files remain valid
- No Breaking Changes: All commands and features unchanged
Gameplay Improvements
- Number scoring now works on Oraxen servers (previously broken)
- Number blocks recoverable in Overworld/End (no permanent loss)
- Consistent breaking behavior with correct tools (pickaxe/axe)
- Identical user experience between letter and number systems
Files Modified
Number Game Listeners:
FortressNumberGameListener.kt- PlayerInteractEvent support, dimension handling, break behaviorBastionNumberGameListener.kt- PlayerInteractEvent support, dimension handling, break behavior
Version & Deployment:
gradle.properties- Version bump to 1.3.2DEPLOY_CLEAN_JAR.bat- Updated version and release notesREADME.md- Updated version referenceVERSION.md- This file
Upgrade Notes
From v1.3.1:
- Download CharmedChars-1.3.2.jar
- Replace old JAR in
plugins/folder - Restart server
- Number scoring will now work on Oraxen
- Number blocks can be broken with correct tools
Oraxen Users:
- Critical fix - number scoring now works identically to letter spelling
- Use PlayerInteractEvent (left-click) for immediate scoring
- Blocks drop as items in Overworld/End for recovery
All Providers:
- Number blocks can now be broken with correct tools per provider config
- Matches letter block behavior exactly
Development Notes
AI-Assisted Development:
- All compatibility fixes developed with assistance from Claude (Anthropic)
- Event handler architecture improvements guided by AI analysis
- All AI contributions include Co-Authored-By attribution in git commits
Version 1.3.1 - Critical Number Scoring Fix
Release Date
2026-01-12
Overview
Critical bug fix release resolving number game scoring issues with Nexo provider. Changes number scoring to execute on hit (BlockDamageEvent) instead of break, matching the letter spelling system. Fixes hardcoded namespace bug that prevented number recognition with non-charmedchars namespaces.
Changes
Bug Fixes 🐛
Fixed NoClassDefFoundError with Nexo Provider
- Problem: Number game listeners directly called ItemsAdder API even when Nexo was installed
- Impact: Game crashed when hitting/breaking number blocks with Nexo:
java.lang.NoClassDefFoundError: dev/lone/itemsadder/api/CustomStack - Fix: Updated both listeners to use
CustomItemProviderManagerabstraction layer - Files:
FortressNumberGameListener.kt,BastionNumberGameListener.kt - Result: Number games now work correctly with all three providers (ItemsAdder, Oraxen, Nexo)
Fixed Hardcoded Namespace Bug in Number Recognition
- Problem: Number block recognition hardcoded "charmedchars:" namespace check
- Impact: Number blocks wouldn't work with Oraxen (uses "oraxen:" namespace) or ItemsAdder (might use "itemsadder:")
- Fix: Changed to namespace-agnostic parsing like letter block system
- Before:
if (!namespacedId.startsWith("charmedchars:")) return null - After:
val parts = namespacedId.split(":")(works with any namespace) - Files:
FortressNumberGameListener.kt:456-475,BastionNumberGameListener.kt:320-345 - Result: Number blocks now work identically to letter blocks across all providers
CRITICAL: Number Scoring Now Happens on Hit (Not Break)
- Problem: Number scoring used BlockBreakEvent (break) while letter scoring used BlockDamageEvent (hit)
- Impact: Scoring didn't trigger on hit, inconsistent behavior between systems
- Fix: Moved ALL scoring logic from BlockBreakEvent to BlockDamageEvent in both listeners
- Changes:
BlockDamageEvent(on hit): Now executes full scoring logic (rewards, explosions, feedback)BlockBreakEvent(on break): Now only prevents breaking to avoid item duplication
- Files:
FortressNumberGameListener.kt,BastionNumberGameListener.kt - Result: Number scoring now works identically to letter spelling - immediate execution on hit
Prevents Item Duplication from Breaking Number Blocks
- Problem: Players could break number blocks to get items instead of scoring
- Fix: BlockBreakEvent now cancels if block is a number block
- Result: Number blocks can only be removed via proper scoring with valid tools
Code Quality 📝
Consistent Behavior Between Letter and Number Systems
- Both systems now use BlockDamageEvent for scoring
- Both systems use BlockBreakEvent to prevent normal breaking
- Both systems use provider abstraction layer consistently
- Namespace-agnostic block recognition in both systems
Impact
Compatibility
- 100% Backward Compatible: Existing servers work without changes
- No Database Changes: Structure database format unchanged
- No Config Changes: Existing config.yml files remain valid
- No Breaking Changes: All commands and features unchanged
Gameplay Improvements
- Number scoring now responds immediately on hit (like letters)
- Consistent experience between letter spelling and number guessing
- Works correctly with all three providers (ItemsAdder, Oraxen, Nexo)
- No more crashes with Nexo provider
Files Modified
Number Game Listeners:
FortressNumberGameListener.kt- Provider abstraction, namespace fix, scoring on hitBastionNumberGameListener.kt- Provider abstraction, namespace fix, scoring on hit
Version & Deployment:
gradle.properties- Version bump to 1.3.1DEPLOY_CLEAN_JAR.bat- Updated version and release notesREADME.md- Added Nexo to all documentation, updated versionVERSION.md- This file
Upgrade Notes
From v1.3.0:
- Download CharmedChars-1.3.1.jar
- Replace old JAR in
plugins/folder - Restart server
- Number scoring will now work on hit (not break)
- All three providers now fully supported
Nexo Users:
- Critical fix - this version resolves all Nexo compatibility issues
- Number games now work correctly without crashes
- No manual configuration changes needed
Development Notes
AI-Assisted Development:
- All bug fixes developed with assistance from Claude (Anthropic)
- Provider abstraction consistency improvements guided by AI
- All AI contributions include Co-Authored-By attribution in git commits
Version 1.3.0 - Nexo Integration & Fortune Enchantment Support
Release Date
2026-01-01
Overview
Major feature release adding full Nexo integration as a third custom item provider option, Fortune enchantment support for drop rate bonuses, copper tool compatibility for Oraxen, and universal 256x256 texture support for all providers.
Changes
New Features ⭐
Nexo Support - Third Custom Item Provider Option
- Full Nexo Integration: Complete support for Nexo as an alternative to ItemsAdder or Oraxen
- Paper Configuration Requirements: Automatically generates Paper-compatible configuration files
- Auto-Setup Command:
/nexosetupautomatically configures all 128 custom items - Block Model Generation: Generates proper Nexo block model configurations
- Texture Management: Automatically copies all 128 texture files to Nexo's resource pack folder
- Recipe Generation: Creates all pyrite crafting recipes in Nexo format
- Force Flag:
/nexosetup forceoverwrites existing configurations - File:
src/main/kotlin/org/stephanosbad/charmedChars/integration/NexoSetup.kt - Command:
src/main/kotlin/org/stephanosbad/charmedChars/commands/SetupNexoCommand.kt - Provider:
src/main/kotlin/org/stephanosbad/charmedChars/integration/NexoProvider.kt
Fortune Enchantment Support 🎯
- Critical Fix: Fortune enchantment now correctly increases letter block drop rates
- Drop Rate Scaling: Fortune I/II/III now properly applies multipliers to drop chances
- Compatibility: Works alongside existing Looting enchantment bonuses
- File:
src/main/kotlin/org/stephanosbad/charmedChars/items/ItemManager.kt
Copper Tool Support for Oraxen 🔧
- Minecraft 1.21.9+ Support: Added copper tools to Oraxen break whitelist
- Tool Types: All copper pickaxes and axes now work with letter blocks
- Documentation: Updated README and setup guides with copper tool information
- Provider Behavior Differences: Comprehensive documentation of ItemsAdder vs Oraxen vs Nexo behavior
Universal 256x256 Texture System 🎨
- Cross-Provider Compatibility: All textures downscaled to 256x256 for universal support
- Oraxen 1.203+ Compatibility: Meets Oraxen's texture resolution requirements
- Consistent Experience: Same visual quality across all three providers
- Python Script:
downscale_textures_for_oraxen.pyfor automated texture conversion - Dual Texture Sets: Maintains both 512x512 (ItemsAdder/Nexo) and 256x256 (Oraxen) versions
Bug Fixes 🐛
Fixed Fortune Enchantment Detection
- Problem: Fortune enchantment on tools was not being detected, so drop rates weren't increased
- Impact: Players using Fortune tools received standard drop rates instead of boosted rates
- Fix: Added proper Fortune enchantment detection in drop calculation logic
- File:
src/main/kotlin/org/stephanosbad/charmedChars/items/ItemManager.kt - Result: Fortune I/II/III now correctly apply their respective multipliers
Fixed Oraxen Invisible Block Issue
- Problem: Breaking Oraxen letter blocks could sometimes result in invisible blocks
- Impact: Players experienced visual glitches after breaking blocks
- Fix: Improved block break event handling for Oraxen provider
- Note: This commit was later reverted and fixed with a different approach
Fixed Config Generation
- Problem: Plugin wasn't generating complete default config on first run
- Impact: New installations had incomplete configuration files
- Fix: ConfigManager now properly copies full default config from resources
- File:
src/main/kotlin/org/stephanosbad/charmedChars/utility/ConfigManager.kt - Result: First-time setup now generates complete config.yml with all default values
Documentation Updates 📝
Comprehensive Multi-Provider Documentation
- NEXO_SETUP.md: NEW - Complete Nexo setup guide with installation instructions
- README.md: Updated with Nexo references and copper tool information
- HANGAR_SHOWCASE.md: Updated with three-provider support details
- ORAXEN_SETUP.md: Added copper tool support information
- PLAY_INSTRUCTIONS.md: Updated with Fortune enchantment information
New Documentation Files:
NEXO_SETUP.md- Complete Nexo setup guideDEPLOY_AND_TEST.md- Development deployment workflow
Impact
Compatibility
- 100% Backward Compatible: Existing ItemsAdder and Oraxen servers work without changes
- No Breaking Changes: All existing commands, features, and APIs unchanged
- No Database Changes: Structure database format unchanged
- No Config Changes: Existing config.yml files remain valid
Server Owner Benefits
- Three Provider Options: Choose between ItemsAdder, Oraxen, or Nexo
- Fortune Enchantment: Players can now use Fortune tools for better drop rates
- Copper Tools: Minecraft 1.21.9+ servers can use new copper tools (Oraxen)
- Consistent Textures: All providers now use compatible texture resolutions
Files Modified
Core Integration Layer:
NexoProvider.kt- NEW: Nexo implementationNexoSetup.kt- NEW: Nexo setup commandSetupNexoCommand.kt- NEW: Command handlerCustomItemProviderManager.kt- Updated for NexoOraxenSetup.kt- Copper tool support
Gameplay Systems:
ItemManager.kt- Fortune enchantment supportBastionNumberGameListener.kt- Enhanced validationFortressNumberGameListener.kt- Enhanced validation
Configuration:
ConfigManager.kt- Improved config generationConfigDataHandler.kt- Enhanced data handlingconfig.yml- Updated default configuration
Documentation:
NEXO_SETUP.md- NEW: Nexo setup guideDEPLOY_AND_TEST.md- NEW: Development workflowVERSION.md- This file
Upgrade Notes
From v1.2.0:
- Download CharmedChars-1.3.0.jar
- Replace old JAR in
plugins/folder - Restart server
- Fortune enchantment will now work on tools
Switching to Nexo:
- Remove existing provider plugin
- Install Nexo plugin
- Install CharmedChars-1.3.0.jar
- Run
/nexosetup - Run
/nexo reload - Restart server
Development Notes
AI-Assisted Development:
- Nexo integration developed with assistance from Claude (Anthropic)
- Fortune enchantment fix implemented with AI guidance
- All AI contributions include Co-Authored-By attribution in git commits
Version 1.2.0 - Oraxen Compatibility
Release Date
2025-12-14
Overview
Major feature release adding full support for Oraxen as an alternative to ItemsAdder. Introduces a custom item provider abstraction layer that allows server owners to choose between two premium custom item providers: ItemsAdder or Oraxen (both require purchase, though Oraxen has public source code).
Changes
New Features ⭐
Oraxen Support - Alternative to ItemsAdder
- IMPORTANT: Both ItemsAdder and Oraxen are premium plugins requiring purchase for server use
- Custom Item Provider Abstraction Layer: Complete abstraction separating core plugin logic from custom item provider implementation
- Dual Provider Support: Works with either ItemsAdder OR Oraxen (not both, not neither)
- Automatic Provider Detection: Plugin automatically detects which custom item provider is installed at runtime
- Safety Checks: Refuses to load if both providers are installed or neither is installed, with clear error messages
- File:
src/main/kotlin/org/stephanosbad/charmedChars/integration/CustomItemProvider.kt
New Command: /oraxensetup
- Automatic Oraxen Configuration: One-command setup for Oraxen integration
- Generates 128 Items: Automatically creates all 123 letter/number blocks + 5 pyrite items
- Block Model JSON Generation: Generates proper Oraxen block model JSONs for all items
- Texture Copying: Automatically copies all 128 texture files to Oraxen's pack folder
- Recipe Generation: Creates all pyrite crafting recipes in Oraxen format
- Force Flag:
/oraxensetup forceoverwrites existing configurations - File:
src/main/kotlin/org/stephanosbad/charmedChars/integration/OraxenSetup.kt
Abstraction Layer Architecture
- CustomItemProvider Interface: Unified interface for all custom item operations
getCustomItem()- Retrieve custom item by namespaced IDgetNamespacedId()- Get custom item ID from ItemStackgetProviderName()- Get provider name ("ItemsAdder" or "Oraxen")
- CustomItemProviderManager: Singleton managing provider lifecycle
- Auto-detects installed provider during plugin initialization
- Validates only one provider is present
- Provides global access to provider instance
- ItemsAdderProvider: Implementation for ItemsAdder API
- OraxenProvider: Implementation for Oraxen API
Technical Implementation Details
Block Model Generation (Oraxen):
// Oraxen requires explicit block model JSONs
// CharmedChars auto-generates these during /oraxensetup
{
"parent": "block/cube_all",
"textures": {
"all": "charmedchars:block/cyan/a"
}
}
Provider Detection Logic:
// Checks for both providers at startup
val hasItemsAdder = Bukkit.getPluginManager().getPlugin("ItemsAdder") != null
val hasOraxen = Bukkit.getPluginManager().getPlugin("Oraxen") != null
// Validates exactly one provider
if (hasItemsAdder && hasOraxen) {
error("Both ItemsAdder and Oraxen detected - install only ONE")
}
if (!hasItemsAdder && !hasOraxen) {
error("No custom item provider found - install ItemsAdder OR Oraxen")
}
Documentation Updates 📝
Comprehensive Documentation Overhaul
ORAXEN_SETUP.md: New complete setup guide for Oraxen users
- Step-by-step installation instructions
- Command reference and troubleshooting
- Configuration examples
- Comparison with ItemsAdder workflow
HANGAR_SHOWCASE.md: Updated showcase documentation
- Dual provider setup instructions
- Clear choice between two premium providers (ItemsAdder and Oraxen)
- Updated commands table with /oraxensetup
- Abstraction layer technical details
- Updated version history with v1.2.0 features
README.md: Updated main documentation
- Provider selection guidance
- Installation steps for both providers
- Updated technical details section
Test Documentation: Updated test comments
- WordValidationTest: Updated to reflect custom item provider abstraction
- SequenceDetectionTest: Updated block identification documentation
New Documentation Files:
ORAXEN_SETUP.md- Complete Oraxen setup guide- Integration test suite documentation
Impact
Compatibility
- 100% Backward Compatible: Existing ItemsAdder servers work without changes
- No Breaking Changes: All existing commands, features, and APIs unchanged
- No Database Changes: Structure database format unchanged
- No Config Changes: config.yml format unchanged
Server Owner Benefits
- Choice: Server owners can choose between two premium custom item providers
- Flexibility: Both providers are premium but offer different features and pricing
- Migration Path: Can switch between providers by changing plugin + running setup command
- Same Features: All CharmedChars features work identically with both providers
- Public Source: Oraxen has public source code (though still requires purchase for use)
Technical Quality
- Clean Abstraction: Provider-specific code isolated in dedicated classes
- Easy Maintenance: Future provider support can be added without core changes
- Comprehensive Tests: New integration test suite for both providers
- Robust Error Handling: Clear error messages for misconfiguration
Files Modified
Core Integration Layer:
src/main/kotlin/org/stephanosbad/charmedChars/integration/CustomItemProvider.kt- NEW: Provider interfacesrc/main/kotlin/org/stephanosbad/charmedChars/integration/CustomItemProviderManager.kt- NEW: Provider managersrc/main/kotlin/org/stephanosbad/charmedChars/integration/ItemsAdderProvider.kt- NEW: ItemsAdder implementationsrc/main/kotlin/org/stephanosbad/charmedChars/integration/OraxenProvider.kt- NEW: Oraxen implementationsrc/main/kotlin/org/stephanosbad/charmedChars/integration/OraxenSetup.kt- NEW: Oraxen setup commandsrc/main/kotlin/org/stephanosbad/charmedChars/commands/OraxenSetupCommand.kt- NEW: Command handler
Plugin Initialization:
src/main/kotlin/org/stephanosbad/charmedChars/CharmedChars.kt- Provider detection and initialization
Documentation:
ORAXEN_SETUP.md- NEW: Oraxen setup guideHANGAR_SHOWCASE.md- Updated with dual provider supportREADME.md- Updated installation instructionsVERSION.md- This file (added v1.2.0 release notes)gradle.properties- Version bump to 1.2.0BUILD.md- Updated JAR filename referencesTROUBLESHOOTING.md- Updated JAR filename referencesDEPLOY_CLEAN_JAR.bat- Updated deployment scriptverify_jar.bat- Updated JAR filenameverify_jar_correct.bat- Updated JAR filenamecleanup_uppercase.bat- Updated JAR filename
Test Suite:
src/test/kotlin/org/stephanosbad/charmedChars/integration/CustomItemProviderTest.kt- NEW: Provider interface testssrc/test/kotlin/org/stephanosbad/charmedChars/integration/CustomItemProviderManagerTest.kt- NEW: Manager testssrc/test/kotlin/org/stephanosbad/charmedChars/integration/OraxenSetupTest.kt- NEW: Oraxen setup testssrc/test/kotlin/org/stephanosbad/charmedChars/items/WordValidationTest.kt- Updated commentssrc/test/kotlin/org/stephanosbad/charmedChars/listeners/SequenceDetectionTest.kt- Updated comments
Upgrade Notes
From v1.1.5 (ItemsAdder Users):
- No Changes Required: Drop-in replacement
- Download CharmedChars-1.2.0.jar
- Replace old JAR in
plugins/folder - Restart server
- Plugin will auto-detect ItemsAdder and work normally
- All existing data, configs, and resource packs unchanged
From v1.1.5 (Switching to Oraxen):
- Remove ItemsAdder from
plugins/folder - Install Oraxen plugin
- Install CharmedChars-1.2.0.jar
- Start server
- Run
/oraxensetupto configure Oraxen - Run
/oraxen reload allto load items - Restart server for full effect
- Players will receive new resource pack
New Installations:
- Choose ONE custom item provider:
- ItemsAdder (premium plugin): Purchase from SpigotMC
- Oraxen (premium plugin with public source): Purchase from SpigotMC
- IMPORTANT: Both are premium plugins requiring purchase for server use
- Install chosen provider + CharmedChars
- Run setup command:
- ItemsAdder:
/iasetupthen/iazip - Oraxen:
/oraxensetupthen/oraxen reload all
- ItemsAdder:
- Restart server
Important Notes:
- Do NOT install both ItemsAdder and Oraxen - plugin will refuse to load
- Must install one - plugin requires a custom item provider
- Resource pack regeneration: Switching providers requires new resource pack generation
- No data loss: Structure database and player data preserved during provider switch
Known Issues
None currently reported.
Development Notes
Architecture Design:
- Provider abstraction pattern separates concerns cleanly
- Each provider implementation encapsulates provider-specific API calls
- Manager pattern provides global access point while controlling lifecycle
- Interface-based design allows easy addition of future providers
Testing Strategy:
- Integration tests mock provider behavior
- Test both ItemsAdder and Oraxen code paths
- Verify provider detection logic
- Validate configuration generation
AI-Assisted Development:
- Oraxen compatibility feature developed with assistance from Claude (Anthropic)
- Custom item provider abstraction architecture designed with AI guidance
- All AI contributions include Co-Authored-By attribution in git commits
- Comprehensive documentation generated with AI assistance
Version 1.1.5 - Bug Fix Release
Release Date
2025-12-07
Overview
Bug fix release addressing ItemsAdder setup failure and comprehensive documentation updates.
Changes
Bug Fixes 🐛
Fixed: ItemsAdder Data folder creation failure
- Problem:
/iasetupcommand would fail if ItemsAdder'sdatafolder didn't exist - Impact: Users had to manually create the folder before running setup
- Fix: Added automatic
datafolder creation inItemsAdderSetup.enableNamespace() - File:
src/main/kotlin/org/stephanosbad/charmedChars/integration/ItemsAdderSetup.kt:290-293 - Result: Setup now works on first run without manual intervention
Technical Details:
// Added before writing items_packs.yml:
if (!itemsAdderDataFolder.exists()) {
itemsAdderDataFolder.mkdirs()
}
Documentation Updates 📝
Comprehensive documentation review and updates to accurately reflect all gameplay features:
-
- Added pyrite tools to "How to Play" section
- Added minimum word lengths (3 same-color, 4 multi-color)
- Added Nether Challenge section
- Added missing commands (
/structurecode,/structuredb list,/structuredb purge) - Updated Technical section with accurate counts (128 items: 123 blocks + 5 pyrite items)
- Added SQLite database mention
HANGAR_SHOWCASE.md:
- Updated "Custom Blocks" to "Custom Blocks & Items"
- Added 5 pyrite items to technical details
- Clarified total: 128 custom items
QUICK_SETUP.md:
- Updated
/iasetupdescription to mention pyrite.yml - Corrected texture count: 128 files (123 blocks + 5 pyrite items)
- Added "Enables charmedchars namespace" step
- Updated
/iazipdescription to mention item models
- Updated
PLAY_INSTRUCTIONS.md:
- Added comprehensive "Nether Structure Number Guessing Game" section (232 lines)
- Covers gameplay mechanics, strategy tips, commands, rewards, FAQ
- Updated "Getting Started Checklist" with correct minimum word sizes
Impact
- Setup Process: Now fully automated - no manual folder creation needed
- Documentation: All files now accurately represent complete feature set
- Compatibility: 100% backward compatible with v1.1.4
- No Database Changes: All player data preserved
- No Config Changes: All settings remain the same
Files Modified
ItemsAdderSetup.kt- Bug fix (4 lines added)VERSION.md- This fileREADME.md- Complete feature documentationHANGAR_SHOWCASE.md- Accurate item counts and featuresQUICK_SETUP.md- Correct setup step descriptionsPLAY_INSTRUCTIONS.md- Added Nether game section, updated checklist
Upgrade Notes
- From v1.1.4: Drop-in replacement, no changes needed
- Setup Improvement:
/iasetupnow creates necessary folders automatically - Documentation: All gameplay features now properly documented
- No Breaking Changes: Full backward compatibility
Version 1.1.4 - Code Cleanup & Refactoring
Release Date
2025-12-01
Overview
Internal code cleanup release removing dead code and improving code clarity. No functional changes or new features.
Changes
Dead Code Removal 🧹
Removed unused functions, imports, and empty structures to improve maintainability.
Removed Functions (6 total):
ItemManager.getNoteblockNumber()- Legacy note block method (replaced by getCustomVariation)ItemManager.checkLateralBlocks()- Refactored inline into letterBlockBreak methodStructureDatabase.deleteStructureById()- Unused public API (deleteStructureByNumber used instead)StructureData.getLocationKey()- Unused utility functionStructureType.fromString()- Kotlin stdlib valueOf() used insteadItemManagerempty companion object - Leftover from refactoring
Removed Imports:
BlockColor.kt- Unusedkotlin.random.Randomimport
Code Clarity Improvements 📝
Renamed 23 unused interface parameters with underscore prefix for clarity.
Affected Commands:
- CharBlock, ReloadCommand, VersionCommand
- ItemsAdderStatusCommand, SetupItemsAdderCommand
- StructureCodeCommand, StructureDatabaseCommand
Example:
// Before:
override fun onCommand(sender: CommandSender, command: Command, label: String, args: Array<out String>)
// After:
override fun onCommand(sender: CommandSender, _command: Command, _label: String, _args: Array<out String>)
Impact
- Lines Removed: 113 lines
- Lines Added: 18 lines
- Net Reduction: 95 lines of code
- Files Modified: 12 files
- Tests: All 131 tests passing ✅
- Build: Successful ✅
Upgrade Notes
- From v1.1.3: Drop-in replacement, no changes needed
- Compatibility: 100% backward compatible
- No Database Changes: All player data preserved
- No Config Changes: All settings remain the same
Version 1.1.3 - Brass-Colored Pyrite Textures
Release Date
2025-11-21
Overview
Minor visual update improving the pyrite textures to better distinguish them from vanilla gold items.
Changes
Updated Pyrite Textures 🎨
Pyrite items now feature a brass-like metal color instead of bright gold.
- Color: Warmer, coppery-golden brass tone (hue shifted to 88%)
- Saturation: Slightly reduced (95%) for a more subdued appearance
- Visual Identity: Better represents "fool's gold" (pyrite) vs real gold
- Affected Items:
- pyrite_ingot.png - Brass-colored ingot
- pyrite_pickaxe.png - Warmer metal head
- pyrite_axe.png - Coppery-golden blade
- pyrite_shovel.png - Brass-colored spade
- pyrite_hoe.png - Warmer brass tone
Technical Details
- Applied ImageMagick color transformation:
-modulate 100,95,88 - Textures auto-copied by
/iasetupcommand - Resource pack regeneration required with
/iazip
Upgrade Notes
- From v1.1.2: Drop-in replacement, no config changes needed
- Resource Pack: Regenerate with
/iazipafter update to see new textures - Existing Items: Already placed pyrite tools will show new textures automatically
Version 1.1.2 - Pyrite (Fool's Gold) System & Gameplay Improvements
Release Date
2025-11-20
Overview
Major feature release introducing the Pyrite material system - an iron-tier alternative to gold tools with identical CharmedChars functionality. Includes word length validation rules to improve gameplay balance.
New Features
Pyrite (Fool's Gold) Material System ⭐
A craftable alternative to gold tools with better durability but same CharmedChars functionality.
Crafting:
- Pyrite Ingot: 1 Iron Ingot + 1 Redstone (shapeless)
- Tools: Standard recipes using Pyrite Ingots + Sticks (same patterns as vanilla tools)
Items:
charmedchars:pyrite_ingot- Crafting materialcharmedchars:pyrite_pickaxe- 250 durability, iron-tier statscharmedchars:pyrite_axe- 250 durability, iron-tier statscharmedchars:pyrite_shovel- 250 durability, iron-tier statscharmedchars:pyrite_hoe- 250 durability, iron-tier stats
Functionality:
- Works like gold for mining logs → letter block drops
- Works like gold for breaking letter blocks → word scoring
- Works like gold for breaking number sequences → fortress/bastion rewards
- Iron-tier durability (250 uses vs gold's 32)
- Iron-tier mining speed and enchantability
Minimum Word Length Rules ⭐
Prevents scoring of very short words to improve game balance.
- Single-color words: Minimum 3 letters (e.g., "CAT" in all cyan)
- Multi-color words: Minimum 4 letters (e.g., "CATS" in cyan+magenta)
- Clear feedback messages when words are too short
- Example: Breaking "IN" (2 letters) shows "Miss: single-color words must be at least 3 letters long"
Tool Validation for Number Sequences ⭐
Number sequences now require gold or pyrite tools to prevent unintended triggers.
- Only gold or pyrite tools can break number sequences in fortresses/bastions
- Prevents netherite, diamond, and other tools from accidentally triggering games
- Consistent with letter block and word scoring tool requirements
Bug Fixes
Fixed Pyrite Tool Detection
- Changed from
displayName()to ItemsAdder'sCustomStack.byItemStack()API - Pyrite tools now properly recognized for all CharmedChars features
- Added fallback to plain text display name serialization for compatibility
Fixed ItemsAdder Block Breaking Warnings
- Added pyrite tools to
break_tools_whitelistfor all 123 character blocks - Eliminated false "cannot use tool to break item" messages
- Updated blocks.yml with
charmedchars:pyrite_axeandcharmedchars:pyrite_pickaxe
Fixed Pyrite Recipe Format
- Moved recipes from item-nested structure to global
recipes:section - Added
crafting_table:parent key as required by ItemsAdder - Fixed shapeless recipe format (changed from list to letter mapping)
- Removed durability from pyrite_ingot to prevent spurious repair recipes
Configuration Changes
ItemsAdder Integration
- New file:
src/main/resources/itemsadder/pyrite.yml - Auto-copied by
/iasetupcommand - 5 items + 5 crafting recipes
- Texture files included in resource pack
Build System
- Added
processResourcestask to substitute version in plugin.yml - Version now correctly shows "1.1.2" instead of "${version}"
Technical Details
Tool Validation Logic (ItemManager.kt:223-252):
private fun isValidTool(item: ItemStack): Boolean {
// 1. Check vanilla gold tools
if (item.type.name.lowercase().contains("gold")) return true
// 2. Check pyrite tools via ItemsAdder API
val customStack = CustomStack.byItemStack(item)
if (customStack?.namespacedID?.lowercase()?.contains("pyrite") == true) {
return true
}
// 3. Fallback to display name check
// ...
}
Word Length Validation (ItemManager.kt:477-486):
val minimumLength = if (isSameColor) 3 else 4
if (wordLength < minimumLength) {
e.player.sendMessage("Miss: $colorType words must be at least $minimumLength letters long")
e.isCancelled = true
return
}
Pyrite Recipe Structure:
recipes:
crafting_table:
pyrite_ingot_recipe:
enabled: true
shapeless: true
ingredients:
I: IRON_INGOT
R: REDSTONE
result:
item: charmedchars:pyrite_ingot
amount: 1
Files Changed
gradle.properties- Version bump to 1.1.2src/main/resources/itemsadder/pyrite.yml- New pyrite item definitions and recipessrc/main/resources/itemsadder/blocks.yml- Added pyrite tools to break_tools_whitelist (123 blocks)src/main/kotlin/org/stephanosbad/charmedChars/items/ItemManager.kt- Tool validation + word length rulessrc/main/kotlin/org/stephanosbad/charmedChars/listeners/FortressNumberGameListener.kt- Tool validationsrc/main/kotlin/org/stephanosbad/charmedChars/listeners/BastionNumberGameListener.kt- Tool validationsrc/main/kotlin/org/stephanosbad/charmedChars/integration/ItemsAdderSetup.kt- Pyrite texture copyingbuild.gradle.kts- Added processResources for version substitutionDEPLOY_CLEAN_JAR.bat- Version updateVERSION.md- This filePLAY_INSTRUCTIONS.md- Added pyrite system documentation
Upgrade Notes
For Server Admins:
- Replace JAR with CharmedChars-1.1.2.jar
- Run
/iasetup forceto regenerate ItemsAdder configs - Run
/iazipto rebuild resource pack - Restart server completely (important for recipe cache)
- Pyrite recipes will be available in crafting tables
For Players:
- New pyrite tools available via crafting (cheaper than gold!)
- Words shorter than 3-4 letters no longer score
- Number sequences require gold/pyrite tools (prevents accidents)
Known Issues
None
Version 1.1.1 - Critical Coordinate Bug Fix & Test Coverage
Release Date
2025-11-19
Overview
Critical bug fix release addressing a serious coordinate calculation bug affecting structures at negative coordinates in the Nether. Includes comprehensive unit test coverage to prevent future regressions.
Bug Fixes
Fixed Critical Negative Coordinate Calculation Bug ⭐
- Problem: Java/Kotlin integer division truncates toward ZERO, not floor
- Before:
-1 / 16 = 0(INCORRECT!) - After:
Math.floorDiv(-1, 16) = -1(CORRECT!)
- Before:
- Impact: Structures at negative coordinates near zero (very common in Nether) were incorrectly identified
- Fix: Replaced
(boundingBox.minX / 16).toInt()withMath.floorDiv(boundingBox.minX.toInt(), 16)in all listeners and commands - Example: A bastion at block coordinates (-50, -600) was mapped to wrong chunk origin
- Before: Chunk (0, 0) - WRONG!
- After: Chunk (-4, -38) - CORRECT!
Files Fixed
FortressNumberGameListener.kt- Origin calculation (lines 136-137)BastionNumberGameListener.kt- Origin calculation (lines 114-115)StructureListener.kt- Origin calculation (lines 117-118)StructureCodeCommand.kt- Origin calculation (2 locations: lines 106-107, 162-163)
Testing & Quality Assurance
Comprehensive Unit Test Suite Added
SequenceDetectionTest (279 lines) - Documents 3-digit sequence detection logic
- Tests valid directions (4 cardinal, horizontal only)
- Tests invalid sequences (diagonal, vertical, gaps)
- Tests number formation (hundreds-tens-ones)
- Tests ItemsAdder block identification
ListenerConflictTest (307 lines) - Verifies listener priority fixes from v1.1.0
- Documents fortress listener checking for bastion first
- Documents bastion listener early return behavior
- Verifies only fortress listener handles "not in structure" case
DiscoveryMessageTest (337 lines) - Verifies discovery notification fixes from v1.1.0
- Documents that discovery messages do not reveal assigned numbers
- Tests structure tracking key consistency across chunks
- Tests prevention of message spam when moving within same structure
CoordinateCalculationTest - Updated with Math.floorDiv expectations
- All 12+ test cases updated to reflect proper floor division
- Comprehensive documentation of negative coordinate handling
- Tests edge cases including Int.MIN_VALUE and Int.MAX_VALUE
StructureDatabaseTest - 26 existing tests (created in v1.1.0-dev)
- Database CRUD operations
- Unique number generation
- Multi-chunk structure handling
Test Coverage Infrastructure
- Added JaCoCo 0.8.12 for test coverage reporting
- Configured 80% minimum coverage threshold
- Fixed Java 23 compatibility with updated JaCoCo version
- All 41+ tests passing
Technical Details
Coordinate Conversion Formula (OLD - INCORRECT):
val originChunkX = (boundingBox.minX / 16).toInt()
val originChunkZ = (boundingBox.minZ / 16).toInt()
Coordinate Conversion Formula (NEW - CORRECT):
val originChunkX = Math.floorDiv(boundingBox.minX.toInt(), 16)
val originChunkZ = Math.floorDiv(boundingBox.minZ.toInt(), 16)
Why This Matters: Minecraft's Nether commonly generates structures at negative coordinates. The old truncating division would incorrectly map:
- Blocks -1 to -15 → Chunk 0 (should be Chunk -1)
- Blocks -16 to -31 → Chunk -1 (should be Chunk -2)
- And so on...
This caused different structures to share the same database entry or the same structure to have multiple entries.
Development Notes
- Bug discovered through comprehensive unit testing
- All fixes developed with assistance from Claude (Anthropic AI)
- Git commits include Co-Authored-By attribution for AI contributions
- Test-driven approach prevents future regressions
Upgrade Notes
- Highly Recommended: This fix corrects structure identification in the Nether
- Existing databases may contain incorrect entries for structures at negative coordinates
- Consider purging and rediscovering Nether structures:
/structuredb purge <world> - No breaking changes to API or configuration
Version 1.1.0 - Structure Number Game Bug Fixes
Release Date
2025-11-19
Overview
Critical bug fix release addressing multiple issues with the Nether structure number guessing game introduced in 1.0.0. Fixes problems with multi-chunk structure detection, listener conflicts, and message spam.
Bug Fixes
Fixed Structure Discovery Message Spam
- Discovery announcements no longer repeat when moving between chunks within the same structure
- Changed player tracking from chunk-specific to structure-type-only
- Players now see "New Structure Discovered" only once per structure instance
Fixed Listener Conflict Causing Wrong Messages
- Resolved issue where FortressNumberGameListener would fire in bastions
- Players in bastions no longer see "you're not in a fortress!" message
- Each listener now checks for the OTHER structure type first and returns early
- Only fortress listener handles "not in any structure" message
Fixed Multi-Chunk Structures Getting Separate Numbers ⭐
- Critical Fix: Structures spanning multiple chunks now share ONE database entry
- Uses structure's bounding box origin coordinates instead of player's current chunk
- All chunks within the same fortress/bastion now use the same 3-digit number
- Prevents database pollution with duplicate entries for the same physical structure
- Implementation: Convert block coordinates to chunk via
(boundingBox.minX / 16).toInt()
Fixed /structurecode Command Not Finding Structures
- Command now uses structure origin coordinates matching database storage
- Works correctly from any chunk within a fortress or bastion
- Updated display to show "Origin:" instead of "Location:" for clarity
Technical Details
All fixes use structure bounding box origin as the unique identifier:
val boundingBox = structure.boundingBox
val originChunkX = (boundingBox.minX / 16).toInt()
val originChunkZ = (boundingBox.minZ / 16).toInt()
Files Modified
BastionNumberGameListener.kt- Origin-based lookup, listener priorityFortressNumberGameListener.kt- Origin-based lookup, listener priorityStructureListener.kt- Origin-based tracking and database queriesStructureCodeCommand.kt- Origin-based database queries
Database Compatibility
- Existing structure databases will work but may contain duplicate entries
- Consider purging old entries:
/structuredb purge <all|fortress|bastion> - New structures will be tracked correctly using origin coordinates
Commands
| Command | Description | Permission |
|---|---|---|
/structurecode |
View structure's 3-digit code | charmedchars.blocks |
/structuredb list [world] |
List all tracked structures | charmedchars.blocks |
/structuredb purge <all|world|fortress|bastion> |
Remove structure entries | charmedchars.blocks |
Development Notes
- All bug fixes developed with assistance from Claude (Anthropic AI)
- Git commits include Co-Authored-By attribution for AI contributions
- Comprehensive testing of multi-chunk structure behavior
Version 1.0.0 - Initial Release
Release Date
2025-11-17
Overview
Initial release of CharmedChars - A word-forming puzzle game for Minecraft where players collect letter blocks from logs, arrange them into words, and earn rewards based on word scores.
Recent Changes
Latest (Development Build)
New Features
Nether Structure Number Guessing Game - Added mini-game for Bastion Remnants and Nether Fortresses
- Each structure assigned unique 3-digit number (100-999)
- Players break number block sequences to guess the structure's code
- Correct guess: Configurable rewards (default: 12 blaze rods for fortress, 16 ender pearls for bastion)
- Wrong guess (too high): Bed-like explosion (power 5.0)
- Wrong guess (too low): Blocks drop as items (recoverable)
- Sequence outside structure: Blocks drop as items with warning
- One-time rewards per structure with database tracking
- SQLite database with Exposed ORM for persistent tracking
- Structure discovery notifications when entering for first time
Git Version Tagging Scripts - Cross-platform scripts for semantic versioning
- Shell script (tag-version.sh) for Linux/Mac
- Batch script (tag-version.bat) for Windows
- Auto-increment version support (--major, --minor, --patch)
- Integration with gradle.properties
- Annotated and lightweight tag support
Configurable Structure Rewards - Server admins can customize number game rewards
- Configure material type and quantity in config.yml
- Supports any valid Minecraft material
- Separate configs for fortress and bastion rewards
Bug Fixes
- Fixed letter block item drop after scoring - Cancelled BlockBreakEvent to prevent the first letter from dropping as an item when a word is scored
- Fixed color randomization - Replaced Math.random() with Kotlin's .random() to ensure all three colors (cyan, magenta, yellow) drop with equal probability
- Fixed hardcoded drop rates - Updated ItemManager to read drop rates from config instead of using hardcoded values
Code Quality
- Comprehensive KDoc documentation - Added detailed documentation to all classes
- LGPL v3 license compliance - Added proper license headers to all source files
- Removed diagnostic logging - Cleaned up verbose console logging during gameplay to reduce spam
- Deleted diagnostic files - Removed 11 obsolete diagnostic/troubleshooting files and scripts
- Better randomization - Using Kotlin's idiomatic random functions instead of Java's Math.random()
Development Notes
- Number guessing game system developed with assistance from Claude (Anthropic AI)
- Database architecture, game logic, and explosion mechanics implemented using AI-assisted development
- Cross-platform version tagging scripts created with AI assistance
- All git commits include Co-Authored-By attribution for AI contributions
Version Numbering Scheme
CharmedChars follows Semantic Versioning:
- MAJOR.MINOR.PATCH format (e.g., 1.0.0)
- MAJOR: Incompatible API changes or major feature overhauls
- MINOR: New features added in a backward-compatible manner
- PATCH: Backward-compatible bug fixes
Development Builds
- Development builds may include
-SNAPSHOTsuffix (e.g., 1.0.0-SNAPSHOT) - Pre-release versions may use
-beta,-alpha, or-rcsuffixes
System Requirements
Minecraft Server
- Minecraft Version: 1.21.10+
- Server Type: Paper or Paper-based (Purpur, Pufferfish, etc.)
- Java Version: Java 21+
Required Dependencies
- ItemsAdder: 3.6.3-beta-14 or higher
⚠️ IMPORTANT - ItemsAdder Licensing Notice:
ItemsAdder is a proprietary/commercial plugin and is NOT included with CharmedChars. You must:
- Purchase and download ItemsAdder separately from SpigotMC or the official source
- Comply with ItemsAdder's own license terms
- ItemsAdder is required for CharmedChars to function - it is a runtime dependency only
CharmedChars itself is open source, but it requires ItemsAdder (a proprietary plugin) to operate. CharmedChars only interfaces with ItemsAdder's public API and does not bundle or redistribute any ItemsAdder code.
Optional Dependencies
The plugin works perfectly without these! They are soft dependencies only.
- WorldGuard: 7.0.14+ (for region protection - can be disabled in config)
- GriefPrevention: 16.15.0+ (for claim protection - can be disabled in config)
- ProtocolLib: 5.3.0+ (for advanced features)
Note: Protection plugins are completely optional. If not installed, the plugin functions normally. If installed, they can be enabled/disabled via the protection section in config.yml.
Key Features
Gameplay
- Letter Block Collection: Mine wood logs with gold tools to get random letter blocks
- Word Formation: Place blocks in straight lines to form words
- Dictionary Validation: ~173,500 English words from ENABLE word list (public domain)
- Scoring System: Frequency-based scoring with color bonuses (3x multiplier for same-color words)
- Configurable Rewards: Drop items based on word scores with customizable thresholds
Technical
- ItemsAdder Integration: Custom blocks with 512x512 textures
- Three Block Colors: Cyan, Magenta, Yellow
- 26 Letters + Numbers + Operators: Full alphabet plus 0-9 and +, -, *, /
- Optional Protection Support: Optional integration with WorldGuard and GriefPrevention (soft dependencies)
- Configurable Drop Rates: Adjustable via config with Looting enchantment support
Administration
- Easy Setup: Auto-configuration commands for ItemsAdder
- Flexible Rewards: Multiple reward tiers with configurable formulas
- Resource Pack Hosting: Built-in HTTP server for resource pack delivery
- Comprehensive Config: All gameplay values configurable
Installation
- Download CharmedChars-1.0.0.jar
- Place in
plugins/folder - Install ItemsAdder (required dependency)
- (Optional) Install WorldGuard and/or GriefPrevention for protection support
- Start server to generate config
- Run
/iasetupto auto-configure ItemsAdder - Run
/iazipto generate resource pack - Restart server
- Players automatically receive resource pack on join
Note: The plugin works without WorldGuard or GriefPrevention. Protection integrations can be enabled/disabled in config.yml under the protection section.
See QUICK_SETUP.md for detailed installation instructions.
Configuration
See REWARD_CONFIG.md for complete configuration documentation.
Quick Config Examples
Drop Rates (config.yml):
letter-blocks:
drop-chance: 0.06 # 6% base
looting-multipliers:
1: 1.67 # 10% with Looting I
2: 2.67 # 16% with Looting II
3: 3.33 # 20% with Looting III
Rewards (config.yml):
Drop:
- materialName: "IRON_INGOT"
minimumRewardCount: 1.0
multiplier: 0.01
minimumThreshold: 100.0
maximumRewardCap: 20.0
Commands
| Command | Description | Permission |
|---|---|---|
/charblock <player> <color> <text> |
Give letter blocks to a player | charmedchars.blocks |
/reload |
Reload plugin configuration | charmedchars.admin |
/iastatus |
Check ItemsAdder integration status | charmedchars.admin |
/iasetup [force] |
Auto-setup ItemsAdder configuration | charmedchars.admin |
Known Issues
None currently reported.
Support & Documentation
- Play Instructions: See
PLAY_INSTRUCTIONS.md - Reward Configuration: See
REWARD_CONFIG.md - Setup Guide: See
QUICK_SETUP.md - Troubleshooting: See
TROUBLESHOOTING.md - Build Instructions: See
BUILD.md
Credits
Author: StephanosBad Built with: Kotlin, Paper API, ItemsAdder Artwork: Block textures by Gaia Temperini Letter Frequencies: Based on Oxford Concise Dictionary (9th edition, 1995)
License
Proprietary - All rights reserved
Changelog Format
Each version entry includes:
- Release Date: When the version was published
- Bug Fixes: Issues resolved in this version
- Features: New functionality added
- Breaking Changes: Incompatible changes requiring migration
- Deprecations: Features marked for removal in future versions
- Internal: Code quality improvements not affecting gameplay
Last Updated: 2025-11-19
Information
| Published on | January 19, 2026 |
|---|---|
| Downloads | 6 |