### Complete Sprite Sheet Extraction Workflow (JavaScript) Source: https://context7.com/tibiajs/spritesheet-extractor/llms.txt An end-to-end example demonstrating the complete process of loading game files, retrieving asset metadata, and generating a sprite sheet with proper sprite arrangement. It utilizes helper functions for calculating texture and sprite indices, and for creating the sprite sheet bitmap. ```javascript const fs = require('fs'); const PNGImage = require('pngjs-image'); const Metadata = require('./src/Metadata'); const Sprites = require('./src/Sprites'); // Helper function to calculate texture index function getTextureIndex(group, l, x, y, z, f) { return (((f % group.frames * group.patternZ + z) * group.patternY + y) * group.patternX + x) * group.layers + l; } // Helper function to calculate sprite index function getSpriteIndex(group, w, h, l, x, y, z, f) { return ((((((f % group.frames) * group.patternZ + z) * group.patternY + y) * group.patternX + x) * group.layers + l) * group.height + h) * group.width + w; } // Create sprite sheet from frame group function createSpriteSheet(frameGroup, spr) { const size = 32; // Each sprite is 32x32 pixels const totalX = frameGroup.patternZ * frameGroup.patternX * frameGroup.layers; const totalY = frameGroup.frames * frameGroup.patternY; const bitmapWidth = (totalX * frameGroup.width) * size; const bitmapHeight = (totalY * frameGroup.height) * size; const image = PNGImage.createImage(bitmapWidth, bitmapHeight); // Iterate through all frame/pattern/layer combinations for (let f = 0; f < frameGroup.frames; f++) { for (let z = 0; z < frameGroup.patternZ; z++) { for (let y = 0; y < frameGroup.patternY; y++) { for (let x = 0; x < frameGroup.patternX; x++) { for (let l = 0; l < frameGroup.layers; l++) { const index = getTextureIndex(frameGroup, l, x, y, z, f); const fx = (index % totalX) * frameGroup.width * size; const fy = Math.floor(index / totalX) * frameGroup.height * size; // Copy each sprite tile for (let w = 0; w < frameGroup.width; w++) { for (let h = 0; h < frameGroup.height; h++) { const spriteIdx = getSpriteIndex(frameGroup, w, h, l, x, y, z, f); const px = ((frameGroup.width - w - 1) * size); const py = ((frameGroup.height - h - 1) * size); spr.copyPixels(frameGroup.sprites[spriteIdx], image, px + fx, py + fy); } } } } } } } return image; } // Extract sprite sheet const metadata = new Metadata(); metadata.load('Tibia.dat', function(dat) { if (!dat.hasThingType('outfit', 128)) { console.log('Invalid ID'); return; } const sprites = new Sprites(); sprites.load('Tibia.spr', function(spr) { const thing = dat.getThingType('outfit', 128); // Process each frame group (outfits have idle and walking) for (let i = 0; i < thing.groups.length; i++) { const group = thing.getFrameGroup(i); if (group) { const fileName = (i === 0) ? 'idle_outfit_128.png' : 'walking_outfit_128.png'; const image = createSpriteSheet(group, spr); // Ensure output directory exists if (!fs.existsSync('./out/')) { fs.mkdirSync('./out/'); } image.writeImage('./out/' + fileName); console.log('Created:', fileName); } } }); }); ``` -------------------------------- ### Run CLI Tool to Extract Tibia Sprites Source: https://context7.com/tibiajs/spritesheet-extractor/llms.txt Command-line interface for extracting sprite sheets from Tibia game files. Accepts input files, asset category, ID, and output directory. Validates file existence and extensions before processing. ```bash # Extract item sprite with ID 2160 (gold coin) node index.js Tibia.dat Tibia.spr item 2160 ./output/ # Extract outfit sprite with ID 128 (citizen) node index.js Tibia.dat Tibia.spr outfit 128 ./output/ # Extract effect sprite with ID 1 node index.js Tibia.dat Tibia.spr effect 1 # Extract missile sprite with ID 5 node index.js Tibia.dat Tibia.spr missile 5 ./sprites/ # Output will be saved to ./out/ by default if no output directory specified node index.js Tibia.dat Tibia.spr item 100 ``` -------------------------------- ### Load and Parse Tibia .dat Metadata Source: https://context7.com/tibiajs/spritesheet-extractor/llms.txt The Metadata class reads binary .dat files containing game asset information such as dimensions, layers, patterns, and sprite references. It supports items, outfits, effects, and missiles, and provides methods to access counts, check for asset existence, and retrieve detailed asset properties. ```javascript const Metadata = require('./src/Metadata'); // Load metadata file const metadata = new Metadata(); metadata.load('Tibia.dat', function(dat) { // Get signature version const signature = dat.getSignature(); console.log('Signature:', signature.toString(16)); // Get counts for each category console.log('Item count:', dat.getItemCount()); // e.g., 30000 console.log('Outfit count:', dat.getOutfitCount()); // e.g., 500 console.log('Effect count:', dat.getEffectCount()); // e.g., 200 console.log('Missile count:', dat.getMissileCount()); // e.g., 50 // Check if specific ID exists if (dat.hasThingType('item', 2160)) { // Get item details const thing = dat.getThingType('item', 2160); console.log('Item ID:', thing.id); console.log('Category:', thing.category); console.log('Groups:', thing.groups.length); // Get frame group (for items, usually only group 0) const group = thing.getFrameGroup(0); if (group) { console.log('Dimensions:', group.width + 'x' + group.height); console.log('Layers:', group.layers); console.log('Patterns X/Y/Z:', group.patternX, group.patternY, group.patternZ); console.log('Frames:', group.frames); console.log('Sprite IDs:', group.sprites); // Array of sprite references } } // Get max ID for validation const maxItemId = dat.getMaxId('item'); console.log('Valid item IDs: 100 to', maxItemId); }); ``` -------------------------------- ### Load and Extract Tibia .spr Sprite Data Source: https://context7.com/tibiajs/spritesheet-extractor/llms.txt The Sprites class reads binary .spr files containing compressed sprite data using a proprietary run-length encoding format for transparency and RGB color. It provides methods to decode this data and copy sprite pixels into an image buffer. ```javascript const Sprites = require('./src/Sprites'); const PNGImage = require('pngjs-image'); // Load sprites file const sprites = new Sprites(); sprites.load('Tibia.spr', function(spr) { // Get sprite metadata console.log('Signature:', spr.getSignature().toString(16)); console.log('Sprite count:', spr.getSpriteCount()); // e.g., 50000 // Create image to draw onto const image = PNGImage.createImage(32, 32); // Copy sprite pixels to image at position (0, 0) // Sprite IDs from metadata.groups[0].sprites array const spriteId = 1234; spr.copyPixels(spriteId, image, 0, 0); // Save extracted sprite image.writeImage('./sprite_1234.png'); // Copy multiple sprites to create a sprite sheet const sheetImage = PNGImage.createImage(64, 64); spr.copyPixels(1234, sheetImage, 0, 0); // Top-left spr.copyPixels(1235, sheetImage, 32, 0); // Top-right spr.copyPixels(1236, sheetImage, 0, 32); // Bottom-left spr.copyPixels(1237, sheetImage, 32, 32); // Bottom-right sheetImage.writeImage('./sprite_sheet.png'); }); ``` -------------------------------- ### ThingType Class for Game Assets (JavaScript) Source: https://context7.com/tibiajs/spritesheet-extractor/llms.txt Represents a single game asset, storing its ID, category, and frame group data. Frame groups contain dimensional and sprite reference information. Typically instantiated by a Metadata class, it allows direct instantiation and manipulation of asset properties. ```javascript const ThingType = require('./src/ThingType'); // Typically created by Metadata class, but can be instantiated directly const thing = new ThingType(2160, 'item'); // Add frame group data (normally populated by Metadata parser) thing.groups[0] = { width: 1, height: 1, layers: 1, patternX: 1, patternY: 1, patternZ: 1, frames: 1, sprites: [1234] // Sprite ID reference }; // Access properties console.log('Asset ID:', thing.id); console.log('Category:', thing.category); // Get specific frame group const frameGroup = thing.getFrameGroup(0); if (frameGroup) { console.log('Sprite dimensions:', frameGroup.width + 'x' + frameGroup.height); console.log('Animation frames:', frameGroup.frames); console.log('Sprite references:', frameGroup.sprites); } // Outfits have multiple groups (idle and walking) const outfit = new ThingType(128, 'outfit'); outfit.groups[0] = { /* idle animation data */ }; outfit.groups[1] = { /* walking animation data */ }; const idleGroup = outfit.getFrameGroup(0); const walkingGroup = outfit.getFrameGroup(1); ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.