Skip to content

Fix resource pack loading - #457

Merged
RaphiMC merged 1 commit into
mainfrom
fix/resourcepack
Oct 18, 2026
Merged

RaphiMC merged 1 commit into
mainfrom
fix/resourcepack

Conversation

@Exterminate5573

Copy link
Copy Markdown
Collaborator

No description provided.

@Exterminate5573
Exterminate5573 marked this pull request as ready for review October 18, 2026 12:16
@RaphiMC
RaphiMC merged commit 5587fd0 into main Oct 18, 2026
2 checks passed
@RaphiMC
RaphiMC deleted the fix/resourcepack branch October 18, 2026 12:30
AlexProgrammerDE added a commit to StackAnvil/ViaBedrock that referenced this pull request Oct 18, 2026
Converting a resource-pack stack on every join repeats expensive ZIP work and can advertise stale output when the pack content changes. Cache conversions by the effective pack stack and content hash, and verify cached ZIPs before reuse.

Write converted packs and their index atomically, give identical content a stable advertised hash and ID, and make ZIP entry order deterministic. Add focused cache, load-state, and resource negotiation tests. Build on the resource loading changes merged in upstream PR ViaVersionAddons#457. The current cache proposal is ViaVersionAddons#430.

Store typed converter metadata inside the cached ZIP and restore it for
each connection on disk, memory and shared in-flight cache hits. Entity
scales, attachable readiness and unresolved model diagnostics otherwise
disappear when conversion is skipped. Tests compare miss and hit metadata
and isolate the restored map from other connections.

Refresh the conversion fingerprint when block particle bindings change so
previously cached models are not reused without their particle sprite.

Refresh the fingerprint for composed block bones and expanded carrier
definitions so cached packs retain the correct geometry and state selectors.

Refresh the fingerprint when the converter omits elements without rendered
faces. Existing cached packs retain the invalid empty face objects and
must rebuild with valid invisible Java elements and remapped groups.

Include a resource-format revision independently of the selected conversion
profile. Native caption translations add a separate resource archive; older
converted packs must not survive this emitted-resource change merely because
their source files and converter profile are unchanged. Advance this revision
when shared output formats change, including for profiles selected by later
features in the patch stack.

Advance the resource-format revision for the new native particle archive.
Cached conversions produced before particle transport must rebuild even
when the source pack contents and selected converter profile are unchanged.

Advance the emitted-resource epoch for the native actor archive. Cached
packs from older converters lack graphs and pack provenance required by
proxy client rendering, even when their input resource hashes still match.

Keep converter metadata from the completed conversion instead of inflating
the entire ZIP to recover it. Reuse the calculated hash and descriptor
after atomic disk writes, while still verifying persisted cache hits.
Rebuild truncated ZIPs or malformed cached metadata from source so cache
corruption cannot repeatedly reject joins. Preserve archive bytes and
normalized immutable metadata across memory and disk results.

Stream disk-cache misses into a temporary ZIP while computing its hash.
Publish the completed archive atomically before its index, and remove
partial staging files on failure. Avoid allocating the complete ZIP in
heap memory while retaining identical archive bytes and descriptors.

Restore entity scales as finite floats, matching the converter producer
and entity renderer. Reject numbers outside the float domain so persisted
metadata cannot disconnect a connection during custom actor spawning.

Compress large converted ZIPs with Apache Commons Compress scatter/gather
workers. Cap each archive at four workers and use temporary disk storage
instead of buffering every compressed entry on the heap. Preserve sorted
entry order, UTF-8 names, timestamps, file bytes, and deterministic output
across worker counts. Small archives retain the existing sequential writer.

Wait for all workers before closing backing stores and removing the owned
temporary directory, including after interruption and failed writes. Keep
interrupt status and surface compression failures to the existing cache
retry path. Regression tests exercise ordering, content, cancellation,
cleanup, failed output, retry, and output ownership.

Cached older archives remain valid because their resources and metadata
have the same meanings. No resource-format revision is needed for this
packaging change. The parallel path consumes temporary disk space and has
more allocation than the sequential writer; it does not replace RakNet
liveness while acquisition, prompts, downloads, or client reloads are slow.

Expose the same bounded ZIP writer for ordered resource archives. Keep
caller ordering so embedded library headers precede indexed resources,
while ordinary converted packs retain sorted paths. Reuse failure cleanup
and worker ownership instead of maintaining another parallel compressor.

Make shared language parsing atomic for concurrent pack preparation.
Bundled Content instances are reused across connections; HashMap
computeIfAbsent races during concurrent cold definition loads and can
throw ConcurrentModificationException. Retain one immutable parsed table
per path without serializing unrelated language paths.

Use a segmented Commons IO buffer for memory archives, avoiding copies
of all preceding bytes each time the output grows. Keep disk streaming
and deterministic archive bytes unchanged. Verify equivalence across
buffer growth and the existing cache failure, retry and worker cases.

Allow producers to mark already compressed payloads for stored ZIP output.
Preserve that choice across content merges, reset it after ordinary writes,
and retain the previous choice when a replacement fails. Keep payload
writes behind one Content method so storage implementations cannot leave
stale compression metadata. Content subclasses now implement putBytes.

Sequential output calculates the required stored-entry size and CRC.
Scatter/gather output uses the same explicit method without another
deflation pass. Keep ordinary entries compressed, sorted and deterministic.
Older cached packs remain valid because only ZIP methods change.

Read converted entity scales through Number.floatValue(). Pack metadata can
contain boxed doubles, and casting them to Float disconnects clients while
spawning custom actors. The numeric conversion accepts both representations.

BREAKING CHANGE: Content subclasses implement protected putBytes instead
of overriding put. The public put method now maintains ZIP metadata.

Advance the emitted-resource format identity when sidebar image metadata gains source dimensions and its aspect-ratio setting. Rebuild cached packs so the add-on does not receive stale metadata.

Separate in-flight deduplication from completed conversion retention.
Keep at most four completed packs under a 64 MiB archive and serialized
metadata budget, evicting least recently used results. Remove completed
futures on success and failure; active HTTP clients retain their own pack
reference, and disk archives remain available after eviction. Clear both
maps on shutdown. Rejoining servers with distinct pack fingerprints must
not retain every converted ZIP and native metadata object indefinitely.
Regression tests cover LRU reuse, eviction, oversized archives and retry.

Move completed download verification, ZIP decoding and resource definition preparation onto bounded workers. Keep publication on the connection event loop with current-session guards. Complete outstanding work during shutdown and close ZIP inflater resources immediately. Preserve the four-entry, 64 MiB cache limit from the current stack. Count received download chunks without repeatedly scanning the receipt array.

Complete cache retention and eviction before exposing converted packs to callers.
Returning the worker future allowed caller continuations to reuse a pending
oversized result before cache bookkeeping ran. A gated regression reproduces
the ordering failure without sleeps and verifies a new conversion follows
when completed packs are not retained.

Co-authored-by: Miles Tech Studios <291174896+milesalexg-tech@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants