▶️ ЗАБЕРИ СВОИ 8 ПОДАРКОВ 🎁 ПРИ СОЗДАНИИ СВОЕГО МАЙНКРАФТ СЕРВЕРА
Emage

Emage

A Minecraft plugin that displays images and GIFs on item frames.

269
2

Emage 1.4

release26 февраля 2026 г.

⚡ Smoother & Smarter GIFs

Previously, GIF playback was tied to the server's tick rate and sent full image updates to everyone nearby. Now, Emage sends map data directly to players using the PacketEvents library. This hugely improves overall server performance and makes applying large images and GIFs much faster. It also allows GIFs to play smoothly up to 60 FPS, completely independent of server lag.

  • Delta Updates: When a GIF plays, the plugin calculates exactly which pixels changed between frames and only sends those specific pixels over the network. This drastically reduces server bandwidth.
  • Field of View Culling: GIF frames are now only sent to players who are actually looking toward the map. If the map is behind them, the server saves bandwidth by skipping the update entirely.

SQLite Storage & Map ID Recycling

Emage now stores all map data in a centralized SQLite database instead of generating hundreds of individual custom files. This prevents file system clutter, improves chunk loading speeds, and makes backups much simpler. Your existing maps will automatically migrate to the new database the first time you start the server.

  • Zstandard Compression: Switched to Zstd for saving images, resulting in significantly smaller storage sizes and faster loading times.
  • Map ID Recycling: When an image is removed, its internal Bukkit map ID is returned to a pool and reused for future images. This prevents your server from permanently running out of available map IDs over time.

Better Image Processing & Colors

Images no longer stretch or squish to fit the item frame grid. The plugin now preserves the original aspect ratio of your image by padding any extra space with a black background.

  • Dynamic Color Palette: The plugin synchronizes its color palette directly with your server's specific Minecraft version. This means new block colors added in recent Minecraft updates are automatically recognized to make your images look more accurate.
  • Unified Dithering: Consolidated all color-matching algorithms into a single, highly optimized method. It automatically provides the highest quality colors without requiring manual tweaking.
  • Color Sync Command: Added the /emage synccolors command for server admins to manually rebuild the color palette cache if needed.

Configuration & Admin Tools

Managing the plugin is easier with an automatic configuration migration system. When you update Emage, it securely backs up your old config.yml into a backups folder and safely merges your previous settings into the new format.

  • Increased Limits: Raised default limits for a better out-of-the-box experience (Max FPS from 30 to 60, GIF frames from 200 to 240, Image grid size from 10 to 16).
  • Easy Removals: Added /emage remove to quickly delete an image from the specific item frame grid you are looking at, and /emage remove all to wipe all Emage maps server-wide.
  • Auto-Cleanup on Break: If an item frame containing an Emage map is broken by a player or explosion, the plugin instantly deletes the associated map data from the database to keep storage clean.

⚠️ Breaking Changes & Removals

  • Quality Flags Removed: The --fast, --balanced, and --high flags have been removed from the /emage command. Processing quality is now handled entirely automatically.
  • Memory Pool Configs Removed: The custom byte array memory pool system was removed in favor of standard Java garbage collection. The memory.use-pool and memory.pool-size config keys no longer exist and will be removed from your config.

Other Changes

  • Fixed potential out-of-memory crashes by storing cached GIF data in soft memory references, allowing the server to automatically clear them if it runs dangerously low on RAM.
  • Fixed the update checker failing to read the GitHub API properly by switching to a strict JSON parser.
  • Switched cache hashing from MD5 to SHA-256 to prevent potential cryptographic errors on certain host systems.

Emage 1.3.1

release20 февраля 2026 г.

Better Color Accuracy on Modern Servers

The color matching system now detects your server version and uses the full map color palette available on Minecraft 1.17+. Previously, the palette was capped at 220 colors regardless of version. Servers on 1.17 or newer will now use up to 236 colors, which means slightly more accurate color reproduction - especially for browns, dark reds, and similar tones that were added in newer versions. Older servers continue to work as before.

Lower Default Performance Settings

The default configuration has been tuned down to be more conservative out of the box. This should result in less bandwidth usage and fewer lag spikes on typical servers without any manual tweaking.

  • Max FPS default lowered from 60 to 30. The old recommendation of "values above 60 are NOT recommended" has been tightened - values above 30 are now discouraged.
  • Max render distance default lowered from 64 to 32 blocks.
  • Max packets per tick default lowered from 60 to 32.
  • Max redirects default changed from 1 to 5, which better matches the actual code behavior and avoids issues with URLs that redirect multiple times (e.g., image hosting services).

If you've already customized these values in your config, your settings won't change - these only affect new installs or newly generated config entries.

Smarter Animation Tick Rate

The GIF animation renderer previously ticked every single server tick (every 50ms). It now ticks every other tick and also respects the configured FPS limit and adaptive update interval directly inside the tick loop. Before, the FPS setting only affected packet sending - now it also skips unnecessary frame calculations entirely. This means less CPU work when animations don't need to update that frequently.

A global packet budget has also been added on top of the per-player budget to prevent total packet output from scaling linearly with player count. The distance check now also handles null worlds safely to avoid potential errors.

Reusing Existing Maps

When you apply a new image or GIF to an item frame that already has a map in it, Emage now reuses that existing map ID instead of always creating a brand new one. This prevents map ID "leaks" where repeatedly re-applying images to the same frames would consume new map IDs each time.

GIF Memory Safety

Large GIFs could previously consume unbounded memory during decoding. The GIF reader now tracks how much decoded pixel data it has produced and stops reading frames if it exceeds the configured memory limit (memory.max-usage-mb). It also rejects GIFs with canvas dimensions larger than 4096×4096 before attempting to decode them. If a GIF is truncated due to memory limits, a warning is logged with the frame number where it stopped.

Configurable Cache at Runtime

The GIF cache (max entries, max memory, expiration time) was previously hardcoded. These values are now read from your config and applied on startup. Running /emage reload also updates the cache settings live - previously a reload would update the config object but the cache itself kept using its original hardcoded limits.

Safer Image Downloads

The image download system has been reworked to pull its limits (timeouts, max file size, redirect count, internal URL blocking) from the config rather than using hardcoded constants. This means changes to the downloads section of your config now actually take effect.

Additionally, the SSRF protection (blocking requests to internal networks) now also checks for IPv6-mapped IPv4 addresses. Previously, an attacker could potentially bypass the internal URL block by using an IPv6-mapped address like ::ffff:127.0.0.1. The internal URL blocking can also now be toggled off via downloads.block-internal-urls if your setup requires accessing local resources.

Static image downloads now go through the same secured download pipeline (with size limits, SSRF checks, and timeouts) as GIF downloads. Previously, static images were fetched with ImageIO.read(url) directly, which bypassed all of these protections.

bStats Metrics

The plugin now reports anonymous usage statistics via bStats. This includes things like how many maps and animations are active, whether animations are in use, the configured dither quality, and whether adaptive performance is enabled. This helps the developer understand how the plugin is being used. No personal or server-identifying data is collected.

Better Config Validation

All config values are now clamped to sensible minimums after loading. For example, FPS can't go below 1, render distance can't go below 8, download size can't go below 1MB, and so on. Previously, setting a value to 0 or a negative number in the config could cause division-by-zero errors or other unexpected behavior.

Safer Cleanup

Running /emage cleanup now properly removes map renderers from the server when deleting unused files. Before, the files were deleted and the internal tracking was cleared, but the actual map renderers (especially GIF renderers) were left attached to their MapView objects, potentially causing errors or orphaned animations.

Other Changes

  • The transparent pixel index for Fast and Balanced dithering modes was changed from 4 to 0. This fixes how fully transparent pixels are represented in the map data.
  • Thread-local buffers used during dithering are now lazily allocated instead of eagerly created, reducing memory footprint when processing threads are idle.
  • Thread-local buffers are explicitly cleaned up during shutdown to prevent potential memory leaks in environments that reuse classloaders.
  • The mapInitTaskScheduled flag in the map manager now uses AtomicBoolean with compareAndSet instead of a plain volatile boolean, fixing a potential race condition where multiple map init tasks could be scheduled simultaneously.
  • The pending save logic for static and animation grids now correctly handles the case where a save is already in progress and new data arrives - it creates a fresh pending entry instead of trying to add to one that's mid-save.
  • URL validation in the command now explicitly checks that the scheme is http or https before proceeding, rather than just checking if the URI parses successfully. This prevents file:// or other unexpected schemes from reaching the download code.
  • Shutdown order changed: the manager now shuts down before the processing executor, ensuring pending saves complete before the thread pool is terminated.
  • The render method in GifRenderer no longer checks the needsRender flag - it just compares frame indices. This simplifies the logic and avoids an edge case where a frame could be skipped.
  • Added removeByMapId and removeMap methods for cleaner programmatic removal of maps and their associated renderers.
  • The palette data in EmageColors was extended with additional color entries at the end of the table for 1.17+ support.
  • Legacy animation decompression now handles more edge cases, including data that was stored as a single static frame in the EM format.

Emage 1.3

release18 февраля 2026 г.

Better Color Matching

The color lookup cache has been reduced from 8-bit to 7-bit resolution (CACHE_BITS changed from 8 to 7). This cuts the memory used by the color cache significantly, from 16 MB down to around 2 MB, while still providing fast color lookups. In practice, the visual difference is negligible since the CIEDE2000 matching still runs for any edge cases.

The pre-filtering threshold used when searching for the closest palette color has also been tightened (from bestLabEuc * 6.0 + 200.0 down to bestLabEuc * 3.0 + 100.0). This means fewer candidate colors are evaluated with the expensive CIEDE2000 formula, speeding up uncached lookups without meaningfully affecting accuracy. Colors that were far off were never going to win anyway.

Better Transparency Handling

Transparent pixels in all three dithering modes (Fast, Balanced, and High) now map to color index 4 instead of 0. Previously, transparent areas would render as whatever color index 0 happened to be (black), which could cause visual artifacts. Index 4 is the first valid map color, which produces more predictable results when transparency is present in an image.

Better GIF Rendering

GIF processing no longer resizes the entire frame at once and then slices it into grid cells. Instead, each grid cell is extracted from the source frame at its native resolution and resized individually to 128x128. This avoids allocating one large pixel array for the full composite image on every frame, which reduces memory pressure especially for large grids.

The GIF reader now properly reads the background color from the GIF's global color table. When a frame uses the "restore to background color" disposal method, the canvas is now filled with the actual background color specified in the file rather than just clearing to transparent. This fixes rendering glitches on certain GIFs where frames would show holes or incorrect colors between transitions.

Faster Item Frame Detection

The frame grid detection (finding connected item frames for multi-map displays) has been completely rewritten. Before, it searched for neighboring frames by scanning all nearby entities at each BFS step, which could be slow when many entities were in the area. Now, it does a single entity query up front, builds a position lookup map, and then walks the grid using direct coordinate lookups. This is noticeably faster on servers with lots of entities near the item frames.

Smarter GIF Compression

Animation grid compression now uses BEST_SPEED instead of BEST_COMPRESSION for the deflate step. GIF animation data can be very large, and the difference in final file size between the two levels is usually small, while the speed improvement during save is significant. Static map and grid compression still use DEFAULT_COMPRESSION, which is a reasonable middle ground (changed from the previous BEST_COMPRESSION).

Safer Network Requests

DNS resolution for image downloads now runs with a 5-second timeout. Previously, if a hostname took a long time to resolve (or hung indefinitely), the download thread would block with no upper bound. This applies to both the initial URL and any redirect targets. Interrupted and failed DNS lookups now produce clear error messages instead of generic connection failures.

Better Caching Internals

The GIF cache has been switched from a ConcurrentHashMap to a synchronized LinkedHashMap with access-order tracking. This means eviction of the oldest entry is now O(1) instead of requiring a full scan of all entries to find the least-recently-used one. All cache operations are properly synchronized, and the eviction logic is cleaner. The external behavior and limits (20 entries, 100 MB cap, 30-minute expiry) are unchanged.

Smoother Map Initialization

When multiple maps initialize at the same time (common during server startup or world loading), the plugin previously scheduled a separate delayed task for each one. Now, it batches them. Map IDs are collected into a pending set, and a single task applies all of them on the next tick. This reduces scheduler overhead when loading large numbers of saved maps.

Delayed Update Checker Startup

The update checker no longer fires immediately on plugin enable. It now waits 5 seconds (100 ticks) before initializing, which avoids adding network requests to the server's startup sequence. The periodic re-check also guards against overlapping checks with a checkInProgress flag.

Cooldown Map Cleanup

The per-player command cooldown map now periodically prunes expired entries. Previously, cooldown timestamps accumulated forever (one entry per player UUID that ever ran a command). Now, stale entries are cleaned up roughly every 5 minutes, keeping the map small on busy servers.

Other Changes

  • The GIF animation tick now skips all work when no players are online, avoiding unnecessary frame calculations on empty servers.
  • The DIRTY_BUFFER static list in GifRenderer was replaced with a local list created each tick, removing shared mutable state between ticks.
  • The render() method in GifRenderer now delegates to setMapView() instead of duplicating the map registration logic inline.
  • The shutdown sequence in EmageManager now shuts down the scheduler before the IO executor, ensuring no new tasks are scheduled while draining.
  • The High quality dithering mode no longer uses serpentine (alternating left-to-right) scanning. It now always scans left-to-right. This is a subtle behavioral change that may slightly affect the appearance of high-quality dithered images.
  • The GitHub owner in the update checker URL changed from EdithyLikesToCode to Ed1thy.

Emage 1.2

release14 февраля 2026 г.

Emage 1.2 - Changelog

Better Color Accuracy

Colors now look significantly closer to the original image. The old system used a basic color distance formula that often picked slightly "off" colors. The new one uses a proper perceptual color model (CIEDE2000) that matches how human eyes actually see color differences. The cache used for fast lookups has also been made more precise, and initialization is faster thanks to parallel processing.

Improved Dithering

  • Balanced mode now produces cleaner images with less visible banding and fewer stripe-like artifacts.
  • High quality mode uses a more advanced algorithm that spreads color blending over a larger area, giving smoother gradients.
  • Fast mode has been upgraded for slightly better pattern quality while staying fast.
  • GIF animations now look more stable — areas of the image that don't change between frames are preserved as-is instead of being reprocessed, which cuts down on visual flickering.

Faster GIF Processing

GIF frames are now processed across multiple CPU cores at once instead of one at a time. You'll also see a progress bar in your action bar while a GIF is being processed so you know it's working.

Large images are now downscaled in steps instead of all at once, which makes them look noticeably sharper.

Smoother Animations

  • Animations update every tick instead of every other tick, so playback feels smoother.
  • Frame timing is more accurate internally.
  • Map updates are only sent to players who are actually close enough to see the animation and in the same world, which saves a lot of bandwidth.
  • You can now configure how many map packets are sent per tick to keep things smooth without overloading the connection.

Security

  • The plugin now blocks URLs that point to internal/local networks to prevent server-side request abuse.
  • Downloads are limited to 50MB by default and will cut off if exceeded.
  • Redirects are followed safely with a max hop limit, and each redirect is checked for safety.
  • Only HTTP and HTTPS URLs are allowed.

Rate Limiting

  • Players now have a cooldown (default 5 seconds) between image commands to prevent spam.
  • There's a global limit on how many images can be processed at the same time (default 3). If the server is busy, players are told to wait.
  • If the plugin is still starting up, commands will let you know instead of failing silently.

More Config Options

A bunch of things that were previously hardcoded are now configurable:

  • Max packets per tick for animations
  • Separate grid size limits for GIFs and static images
  • Download limits (file size, timeouts, redirect count, internal URL blocking)
  • GIF cache settings (max entries, memory limit, expiry time)
  • Rate limits (cooldown, max concurrent tasks)

If you're upgrading from v1.x, any new config options will be added to your existing config automatically. nothing will break.

Map Management

  • Maps that were already loaded won't get duplicate renderers applied anymore.
  • When a world loads, only maps belonging to that world are restored instead of everything.
  • Pending saves are flushed immediately on world save to prevent data loss.
  • Map and animation counts are tracked correctly and no longer double-count on re-registration.

Other Changes

  • Base command now requires emage.use permission.
  • Frame detection (the BFS that finds connected item frames) is now capped at 225 to prevent lag on huge frame walls.
  • Cleaned up memory handling: buffers and resources are released properly, removed leftover debug output.
  • Removed several unused internal methods and features that weren't doing anything.

Emage 1.1.1

release4 декабря 2025 г.

🎨 Emage 1.1.1

🎉 Major Release - Custom Color Engine, GIF Caching & Stability Overhaul

This release introduces a completely custom color matching system, GIF processing cache, improved stability, and a complete code reorganization for better maintainability.


⚠️ Breaking Changes

  • Maximum GIF grid size reduced from unlimited to 4x4
  • Maximum static image grid size set to 10x10
  • Minimum frame delay increased to 50ms (20 FPS max)

✨ New Features

Custom Color System

  • Replaced Bukkit's MapPalette with custom EmageColors class
  • Perceptually-weighted color matching (green-biased for human vision)
  • Pre-computed 262,144 entry color cache for instant lookups
  • Full Minecraft 1.17+ palette with all 248 map colors
  • Fixed dark colors appearing as yellow/banana or transparent

GIF Caching System

  • Processed GIFs are cached to avoid reprocessing
  • Cache key based on URL + grid size + quality
  • Maximum 20 entries or 100MB memory
  • Auto-expires after 30 minutes of no use
  • LRU (Least Recently Used) eviction when full
  • Second use of same GIF is instant

New Commands

CommandDescription
/emage cacheView GIF cache statistics (hit rate, memory, count)
/emage clearcacheClear all cached GIF data

New Flags

FlagAliasesDescription
--nocache--nc, --freshForce reprocess GIF, ignore cache

Grid Size Limits

Content TypeMaximumRecommended
Static Images10x10 (100 maps)Any size
Animated GIFs4x4 (16 maps)2x2 or smaller

User Warnings

  • Warning displayed for GIF grids of 3x3 or larger
  • Error displayed when exceeding maximum grid sizes
  • Help text updated with limits and recommendations

🚀 Performance Improvements

Lag Fixes

  • Fixed player timeout issues with large GIF grids
  • Fixed 40%+ CPU usage spikes during GIF playback
  • Removed aggressive parallel processing that flooded network
  • Single-threaded processing prevents system overload

Animation System

  • Animation tick runs every 2 ticks (100ms) instead of every tick
  • Only sends map updates when frames actually change
  • All maps in sync group update together efficiently
  • needsRender flag prevents redundant canvas updates
  • Animation starts only after all maps are applied

Memory Management

  • Sequential frame processing reduces memory usage
  • Reusable pixel buffers across frames
  • Frame references cleared immediately after processing
  • Efficient buffer reuse throughout processing pipeline

Processing

  • Proper frame disposal handling (restoreToPrevious, restoreToBackgroundColor)
  • Correct metadata extraction for delays and positions
  • Better handling of 0-delay frames (defaults to 100ms)

🐛 Bug Fixes

Color Issues

  • Fixed dark colors appearing as banana/yellow color
  • Fixed very dark areas appearing as transparent
  • Fixed COLOR_BLACK palette entries being skipped incorrectly

GIF Playback

  • Fixed GIFs running at 5 FPS instead of correct speed
  • Fixed frame skipping in first few seconds of playback
  • Fixed maps showing different frames (desync issues)
  • Fixed animation starting before all maps were ready

Stability

  • Fixed player timeout issues with large GIF grids
  • Fixed CPU spikes during GIF playback
  • Fixed memory leaks from unreleased frame data
  • Fixed network flooding from excessive map updates

Совместимость

Minecraft: Java Edition

1.21.x1.20.x1.19.x1.18.x

Платформы

Поддерживаемые окружения

Сервер

Создатели

Детали

Лицензия:GPL-3.0-or-later
Опубликован:4 месяца назад
Обновлён:1 месяц назад
Главная