A client-side block and entity identification overlay mod for the Tapestry platform.
TWILA provides real-time identification of blocks and entities under your reticle using client-side raycasting. Built entirely on Tapestry's TypeScript-first modding framework with safe API boundaries and explicit lifecycle management.
- Real-time Target Identification: Shows block and entity names instantly as you look at them
- Entity Support: Detects both blocks and entities with position tracking
- Client-side Only: Zero server dependency, works in single-player and multiplayer
- Performance Optimized: Game tick-based raycasting with smart miss tracking
- Clean UI: Minimal text overlay at top-center of screen
- Robust Error Handling: Comprehensive diagnostics and graceful degradation
- Debug Mode: Enhanced logging and test overlays for troubleshooting
TWILA leverages Tapestry's core capabilities:
- Lifecycle Management: Uses
activate/deactivatehooks with deferred initialization - Type Safety: Full TypeScript definitions for all Tapestry APIs
- Client APIs: Uses
tapestry.client.players.raycastBlock()andtapestry.client.overlay - Scheduler: Game tick integration via
tapestry.scheduler.nextTick() - State Management: Internal state machine (INITIALIZING → RUNNING → DISABLED)
TWILA uses a deferred initialization pattern:
- Mod Registration:
tapestry.mod.define()registers the mod with Tapestry - Activation:
activate()function called by Tapestry, exposes global registration function - API Ready: Tapestry calls
twilaRegisterEvents()when client APIs are available - System Initialization: Overlay and raycasting systems start
- Runtime: Continuous raycasting loop with automatic target updates
This approach ensures all Tapestry APIs are fully available before TWILA attempts to use them.
- Java 21: Required for Tapestry and TWILA
- Fabric Loader: Minecraft mod loading system
- Tapestry Platform: Core framework dependency
- Build Both Projects: See BUILD.md for detailed build instructions
- Copy JARs: Place both
tapestry-*.jarandtwila-*.jarinmods/ - Launch: Start Minecraft with Fabric Loader
# Copy built JARs to Minecraft mods folder
cp twila/build/libs/twila-*.jar ~/.minecraft/mods/Note: This only installs TWILA. You'll also need to build and install the Tapestry platform separately.
twila/
├── mod.json # Tapestry mod metadata
├── fabric.mod.json # Fabric loader integration
├── src/
│ ├── index.ts # Main TypeScript entry point
│ ├── main/
│ │ ├── java/
│ │ │ └── com/twila/ # Java extension (minimal/empty)
│ │ └── resources/
│ │ ├── fabric.mod.json
│ │ └── assets/tapestry/
├── dist/ # Compiled TypeScript output
│ ├── index.js # Compiled mod code
│ ├── index.d.ts # Type definitions
│ └── index.js.map # Source maps
├── types/ # TypeScript type definitions
│ ├── index.d.ts
│ └── tapestry.d.ts # Tapestry API types
├── docs/ # Documentation
│ ├── events.md # Event system architecture notes
│ ├── banner.jpg
│ └── twila-logo.jpg
├── build/ # Gradle build output
│ └── libs/
│ └── twila-1.0.0.jar
├── build.gradle # Java/TypeScript build configuration
├── tsconfig.json # TypeScript compiler configuration
├── build-twila.bat/.sh # Quick build scripts
├── build-debug.bat/.sh # Debug build scripts
├── build-basic.bat # Minimal build script
└── README.md # This file
- Node.js 18+ for TypeScript compilation
- Gradle 8.0+ for Java build
- Global TypeScript compiler (
tsc) recommended
# Install dependencies (if using local npm)
npm install
# Build TypeScript (using global tsc)
tsc --project ./tsconfig.json
# Build JAR (includes TypeScript output)
./gradlew build
# Quick build (Windows)
./build-twila.bat
# Quick build (Linux/Mac)
chmod +x ./build-twila.sh && ./build-twila.sh
# Debug build with enhanced logging (Windows)
./build-debug.bat
# Debug build with enhanced logging (Linux/Mac)
chmod +x ./build-debug.sh && ./build-debug.sh
# Basic build without extras (Windows)
./build-basic.batFor troubleshooting mod loading and runtime issues, use debug builds which provide:
- Enhanced console logging with detailed execution traces
- API availability checks for all Tapestry components at startup
- Detailed error reporting with full stack traces
- Raycast result logging with JSON output for every hit/miss
- State transition tracking (INITIALIZING → RUNNING → DISABLED)
- Platform-level debugging for core Tapestry functionality
- Enhanced error reporting for mod loading issues
- Development logging for API interactions
- Normal builds:
twila-1.0.0.jar - Debug builds:
twila-1.0.0-debug.jar
Debug logs appear in Minecraft console with [TWILA] prefix. Look for startup diagnostics showing API availability and system initialization status.
Available build scripts:
- build-twila.bat/.sh - Standard release build
- build-debug.bat/.sh - Debug build with enhanced logging
- build-basic.bat - Minimal build without extras
- build-file-test.bat - Build with file verification
TWILA depends on the Tapestry platform JAR:
cd tapestry
./gradlew downloadMikel buildThis downloads the Mikel templating library and builds the core platform.
TWILA uses an internal state machine for robust lifecycle management:
enum TwilaState {
INITIALIZING = "INITIALIZING", // Mod loading, APIs not ready
RUNNING = "RUNNING", // Active raycasting and overlay
DISABLED = "DISABLED" // Fatal error or deactivated
}const result = tapestry.client.players.raycastBlock({
maxDistance: 32.0,
includeFluids: true
});
if (result.hit) {
// Block detection
if (result.blockName) {
console.log(`Block: ${result.blockName} (${result.blockId})`);
console.log(`Position: ${JSON.stringify(result.blockPos)}`);
}
// Entity detection
if (result.entityName) {
console.log(`Entity: ${result.entityName} (${result.entityId})`);
console.log(`Position: ${JSON.stringify(result.entityPos)}`);
}
}TWILA uses a simple object-based overlay definition:
const overlay = {
id: "twila-overlay",
anchor: "TOP_CENTER",
zIndex: 10,
visible: true,
render: function(ctx) {
if (currentTarget) {
return {
type: "text",
content: currentTarget.blockName,
x: 0,
y: 8,
color: "#FFFFFF"
};
}
return null;
}
};
tapestry.client.overlay.register(overlay);function raycastLoop() {
if (twilaState !== TwilaState.RUNNING) return;
// Perform raycast
const result = tapestry.client.players.raycastBlock({
maxDistance: 32.0,
includeFluids: true
});
// Process result
if (result.hit) {
currentTarget = {
blockName: result.blockName || result.entityName,
blockId: result.blockId || result.entityId,
targetType: result.entityId ? "entity" : "block",
position: result.blockPos || result.entityPos
};
}
// Schedule next tick
tapestry.scheduler.nextTick(raycastLoop);
}TWILA implements consecutive miss tracking to prevent flickering:
const MISS_CLEAR_THRESHOLD = 4;
let consecutiveMisses = 0;
if (!result.hit) {
consecutiveMisses++;
if (consecutiveMisses >= MISS_CLEAR_THRESHOLD) {
currentTarget = null; // Clear after 4 consecutive misses
}
} else {
consecutiveMisses = 0; // Reset on hit
}TWILA currently uses hardcoded configuration values:
- Update Rate: Every game tick (20Hz via scheduler)
- Max Distance: 32.0 blocks
- Include Fluids: true (water, lava detection enabled)
- UI Anchor: TOP_CENTER
- UI Offset: x: 0, y: 8 pixels
- Text Color: #FFFFFF (white)
- Miss Threshold: 4 consecutive misses before clearing target
- Z-Index: 10
For development, you can modify these flags in src/index.ts:
const DEBUG_DISABLE_RAYCAST = false; // Disable raycasting system
const DEBUG_DISABLE_OVERLAY = false; // Disable overlay systemFuture versions may include runtime configuration options.
- Game Tick Scheduling: Respects Minecraft's natural timing via
scheduler.nextTick() - Smart Miss Tracking: Prevents flickering with 4-tick threshold
- Conditional Rendering: Overlay returns null when no target
- Memory Efficient: Single target object, no persistent collections
- Client-Side Only: No network overhead
- Graceful Degradation: Fatal errors disable systems cleanly
- Raycast Cost: < 5ms per tick (client-side only)
- Memory Usage: Minimal (single TargetData object)
- UI Updates: Automatic via overlay render function
- State Transitions: Instant with fail-fast error handling
-
Mod Not Loading
- Verify Tapestry JAR is in mods folder
- Check Java 21 is being used
- Ensure Fabric Loader is up to date
- Look for
[TWILA] Starting activation...in console
-
No Overlay Displayed
- Check for
[TWILA] Overlay registration successfulin logs - Verify
[TWILA] All systems initialized successfully - Ensure raycasting is working (look for raycast result logs)
- Check that
twilaStateis RUNNING
- Check for
-
APIs Not Available
- Look for
[TWILA] Global registration function calledin logs - Check API availability diagnostics at startup
- Verify Tapestry version compatibility
- Ensure
twilaRegisterEvents()is being called
- Look for
-
Build Failures
- Install TypeScript globally:
npm install -g typescript - Clean with
./gradlew clean build - Verify TypeScript compiler:
tsc --version - Check that
dist/directory is created after tsc
- Install TypeScript globally:
TWILA logs comprehensive diagnostics to console:
Startup:
[TWILA] Starting activation...- Mod initialization begins[TWILA] === TWILA ENVIRONMENT ===- API availability check[TWILA] Global registration function called- APIs ready[TWILA] All systems initialized successfully- Ready to run
Runtime:
[TWILA] === RAYCAST LOOP ENTRY ===- Each tick (if verbose logging enabled)[TWILA] Raycast result: {...}- Hit/miss detection[TWILA] Target updated: {...}- New target acquired
Errors:
[TWILA:FATAL]- Critical error, mod disabled[TWILA] Error details:- Full error context with stack trace
Check current state in logs:
twilaState: INITIALIZING- Still loadingtwilaState: RUNNING- Operating normallytwilaState: DISABLED- Fatal error occurred
- Fork the repository
- Create a feature branch
- Follow the existing code structure and patterns
- Add comprehensive logging for debugging
- Test with both single-player and multiplayer
- Ensure TypeScript compiles without errors
- Submit a pull request
- Use TypeScript strict mode
- Add JSDoc comments for public functions
- Follow the state machine pattern for lifecycle
- Use adapter functions for all Tapestry API calls
- Implement fail-fast error handling with
fatal()
AGPL-3.0 License - see LICENSE file for details.
- Tapestry Platform: Core TypeScript-first modding framework
- Fabric Loader: Minecraft mod loading system