feat(nitro): normalise hotel and uploaded bundles to WebP Lossless
Gitea Actions Runner Test / test-job (push) Successful in 0s
CI / check (push) Successful in 31s
CI / tests-integration (push) Successful in 2m17s
CI / tests-unit (push) Failing after 2m29s
CI / tests-ui (push) Successful in 3m17s
CI / preflight (push) Skipped
CI / deploy (push) Skipped
Gitea Actions Runner Test / test-job (push) Successful in 0s
CI / check (push) Successful in 31s
CI / tests-integration (push) Successful in 2m17s
CI / tests-unit (push) Failing after 2m29s
CI / tests-ui (push) Successful in 3m17s
CI / preflight (push) Skipped
CI / deploy (push) Skipped
Importing from a hotel wrote the downloaded .nitro to disk untouched, so official PNG textures stayed PNG and only SWF imports ended up as WebP. Every Studio import should produce the same format regardless of where the bytes came from, so both clone and upload paths now run the bundle through toWebpLosslessBundle. The helper decodes the texture and re-encodes it with the same VP8L options the SWF importer uses, so the artwork round-trips bit-for-bit, and lets createNitroBundle relabel the member and repair the meta.image pointer. A bundle that is already lossless WebP is returned untouched, making the operation idempotent and safe to run on re-import. A colour variant that shares a library keeps the member base name it arrived with. A texture that cannot be decoded keeps its original format with a warning instead of failing the import: the bundle is valid, and losing a furniture item over a codec edge case is worse than a slightly larger texture.
This commit is contained in:
1 parent
306e209e29
commit
b26e2e0de4
5 files changed
+174
-36
No files matched your search
@@ -18,8 +18,9 @@ import {
|
||||
} from "@/lib/services/furni-import";
|
||||
import { nitroAnimationStatesCount } from "@/lib/services/furni-real-interaction";
|
||||
import {
|
||||
createNitroBundle,
|
||||
isLosslessWebp,
|
||||
parseNitroBundle,
|
||||
toWebpLosslessBundle,
|
||||
} from "@/lib/services/swf/nitro-builder";
|
||||
import { getRuntimePath, getRuntimeResolve } from "@/lib/utils/runtime-path";
|
||||
|
||||
@@ -278,19 +279,19 @@ export async function uploadSingleFurni(params: {
|
||||
}
|
||||
|
||||
let nitroMeta: Record<string, unknown> | null = null;
|
||||
// The client resolves the spritesheet through `spritesheet.meta.image`, so
|
||||
// that pointer must name the member we actually ship. A bundle from a
|
||||
// third-party tool can arrive with a stale pointer (say `.png` next to a
|
||||
// WebP member), which stores fine and then renders nothing. Re-writing
|
||||
// through the builder repairs it without touching a single texture byte.
|
||||
// The member keeps its own base name, so `chair*2` colour variants that
|
||||
// share the `chair` library are not renamed.
|
||||
// Studio imports always land as WebP Lossless, whatever the uploaded
|
||||
// bundle carried, so a hotel-supplied PNG and an SWF import end up
|
||||
// identical on disk. Re-encoding also repairs a `meta.image` pointer that
|
||||
// disagrees with the texture member, which would otherwise store fine and
|
||||
// then render nothing. The member keeps its own base name, so `chair*2`
|
||||
// colour variants that share the `chair` library are not renamed.
|
||||
let storedNitro = nitroBuffer;
|
||||
try {
|
||||
const parsed = parseNitroBundle(nitroBuffer);
|
||||
nitroMeta = parsed.json;
|
||||
const memberBase = parsed.textureFileName.replace(/\.(?:png|webp)$/i, "");
|
||||
storedNitro = createNitroBundle(parsed.json, parsed.texture, memberBase);
|
||||
storedNitro = await toWebpLosslessBundle(nitroBuffer);
|
||||
if (!isLosslessWebp(parsed.texture))
|
||||
warnings.push("texture converted to WebP Lossless");
|
||||
} catch {
|
||||
return { ok: false, classname, warnings, error: "invalid .nitro bundle" };
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user