0.10.11
Curse Maven Snippet
What's new
CatFrame - 0.10.11
What is changed?
Change version number from previous to 0.10.11
➕Add:
- Implement blockstate uvlock. Parse path already existed (BlockstateJson.Variant.uvlock); now threaded through the bake pipeline. JsonModelBake.applyUvLock re-derives each rotated quad's UV from its world position per the final facing (mirrors vanilla FaceBakery.lockVertexUv), so geometry turns but the texture stays world-locked. UnbakedModel gains a default bake(…,uvlock) overload; ModelJsonUnbakedAdapter applies the lock only when a non-zero rotation is present. uvlock is plumbed through ModelBaker/BakingCore and encoded into the BakedModelCache key via a trailing '!' marker (lazy-baked; async pre-bake keeps plain keys). Consumers (ResidentStateModel, RenderDispatcher, StateProviderBlockModel) pass variant.uvlock.
- Add chunk-boundary render refresh on chunk load (IWorldAccess notification bypass). Vanilla 1.7.10 only re-marks neighbour sections on chunk UNLOAD (WorldClient.doPreChunk false branch); both client chunk handlers (NetHandlerPlayClient.handleChunkData S21 / handleMapChunkBulk S26) mark only the received chunk's own range after fillChunk, so connection geometry across chunk seams stays stale until an unrelated block update. New client-only MixinNetHandlerPlayClient injects at the handler TAILs (block data already filled, deferred rebuild reads it next render pass) and emits four one-block-wide World.markBlockRangeForRenderUpdate strips hugging the loaded column; the +/-1 section dilation is vanilla's own RenderGlobal.markBlocksForUpdate behaviour, and the unload path is skipped. Registered under Mixins.RENDERING.
- Add unit tests for the joinCode staticization work: stateIndexOf injectivity/domain/-1 bypass and static-property participation, MultipartWhen precomputed split with fallback equivalence, BakedModelCache generation bump, ResidentStateModel memo identity/exclusion/rebuild; set compileTestJava UTF-8 encoding
- Memoize merged blockstate parts by full cartesian-product state index (joinCode): add BlockStateDefinition.stateIndexOf with -1 bypass, ResidentStateModel per-target part memo with weighted-array exclusion, and BakedModelCache generation counter to invalidate memos on reload
- WorldTranslucentPasses (new): marks blocks whose BLOCK_WORLD part contains force-translucent quads, maintains a per-thread chunk-tessellation scope, sequence-pairs getRenderBlockPass -> canRenderInPass -> render to carry the current tessellation pass (0 solid / 1 alpha), and coalesces first-time discoveries into a deferred loadRenderers rebuild on client tick end. clear() drops marks on model re-registration so a hijack never outlives its model.
- MixinBlock (new): base-only, narrow-gate injections. getRenderBlockPass returns 1 for marked blocks (so the pass loop compiles an alpha mesh); canRenderInPass(opts the solid pass 0 back in for the paired block). Blocks overriding these themselves (native glass, GTNH-style multi-pass) dispatch to their subclass body first and stay untouched. canRenderInPass is a Forge-patched method (no SRG name in prod), so it is targeted with remap=false rather than an extraMappings srg entry.
- JsonModelBake: add per-quad BakedQuad.forceTranslucent; new bakeElement overload taking a force-variable set; an element is force-translucent as a whole when any face references a flagged variable (element granularity per spec). deepCopyQuad copies the flag.
- BlockStateModelPart: add translucentSplit() (solid vs force-translucent sub-parts, zero-allocation when homogeneous), mirroring atlasSplit.
- Add canonicalKey(): bare paths default to the minecraft namespace, builtin/ passes through.
🔧Fix:
- Fix StateProviderBlockModel.collectPartsWithProps ignoring blockstate rotation. Both the variants and multipart paths now resolve via BakedModelCache.buildKey(model, x, y, z, uvlock) instead of ModelBaker.bake(model), so variant.x/y/z and uvlock take effect and results are cached (previously re-baked identity model every call). Removed the now-unused ModelBaker import.
- Add compile-window neighbor probe reuse (B1 scratch, never a store). ChunkProbeCache is a ThreadLocal-gated IBlockAccess decorator over a hand-rolled open-addressing long[]/Block[]/byte[] table (no fastutil in the baseline): getBlock and getBlockMetadata dedupe per cell inside one WorldRenderer.updateRenderer pass, where client chunk compilation sees an immutable world. Meta lines fill lazily so block-only probes cost a single delegate read. begin/end ride the existing MixinWorldRenderer HEAD/TAIL next to BlockModelLighter (no new mixin class, no new injection point); ResidentStateModel wraps the world only when a dynamic resolver is present, so GUI/held/particle paths get the untouched reference and zero overhead. Adds ChunkProbeCacheTest (4 cases: wrap no-op outside windows, mutual pane probe dedup, cached identity, no cross-window residue).
- Switch the static-layer memo to canonical interned BlockState keys. DynamicPropertyResolver gains a default resolveState that folds its string output back onto the definition via getPropertyByName + getValueByName + O(1) setValue neighbor jumps, returning null (legacy string-code lane) on any out-of-domain name/value. ResidentStateModel tries this typed identity-memo first (hit builds no props map), keeping partMemo/stateIndexOf untouched as fallback. BlockStateDefinition exposes getPropertyByName from a name index built in create(). Six built-in resolvers unchanged; lambda SAM compatibility preserved. Adds ResidentStateModelTypedMemoTest (5 cases: shared snapshot on hit, cross-meta convergence, value/name downgrades, generation clear).
- Fix two runClient-reported rendering bugs. Stairs: computeShape used parity ((a & 1) != (b & 1)) to test perpendicular facings, but STAIR_FACINGS order {east,west,south,north} groups axes by the high bit, so east-south corners were missed and east-west pairs produced false corners (visible as broken 3x3 stair rings); now compares (a >> 1) != (b >> 1), matching vanilla 1.7.10 func_150145_f/func_150144_g neighbor sets. Torch/redstone torch: Property.getNames() returned value.toString() (uppercase enum names) instead of the StringRepresentable serialized form, so BlockstateKeyValidator rejected every facing=* variant key of torch blockstates and fell back to builtin/missing; getNames now goes through getName(value), also reviving all EnumMetaProperty<Direction> blocks (lever/ladder/hopper/dispenser/furnace/comparator facings). Adds StairsCornerShapeTest (8 cases over a fake IBlockAccess with a standalone BlockStairs instance) and PropertyNamesSerializedTest (3 cases).
- Wire force_translucent end-to-end: ModelResolver, baking and render stages.
- ModelResolver.merge/deepCopy: propagate the per-texture-variable textureForceTranslucent map (child overrides parent, same policy as textures).
- ModelResolver.resolveTextureVariables: expand force_translucent along the #reference chain, so a variable that (transitively) references a force_translucent leaf is itself marked translucent; adds a null-value guard for object-form entries without a sprite.
- ModelJson: support extended texture-variable object form under 'textures'. Each texture variable may now be declared either as a plain string (direct form) or as a JSON object with "sprite" and optional "force_translucent" (default false). The deserializer stores the sprite into the existing Map<String,String> textures (keeping the ModelResolver/TextureSlots pipeline untouched) and records explicit force_translucent=true into a new side map textureForceTranslucent keyed by variable name (null when no variable opts in; absence means default false). Added JavaDoc documenting both forms, #ref resolution and child-overrides-parent semantics.
- Fix sandstone inner/outer stairs face textures.
- Add element-level light_emission (int 0-15) to JSON models, aligned with 26.1.2 CuboidModelElement: parse and range-validate in ModelJson (reject non-number/out-of-range), propagate via ModelResolver.deepCopyElement and JsonModelBake (bakeElement/emitFaceFromCorners/deepCopyQuad) into BakedQuad.lightEmission; AOShadeExtension floors sky/block light components on the AO or uniform brightness channel via LightCoordsUtil.lightCoordsWithEmission without touching AO dispatch or directional shade; add ModelJsonParseTest cases for default/range/rejection/truncation
- ModelResolver: drop the redundant depth limit, thread the cycle chain explicitly, canonicalize model keys
- ModelResolver.java
- Both stack.clear() calls in resolve() are gone, so a nested resolve() can no longer clobber an
- unreachable via resolve() but kept for direct loader invocation, noted at each site.
- ModelResolverCanonicalKeyTest.java (new)
❗❗❗Deprecated:
- Revert chunk-boundary render refresh (ba0f8bd9). Misread of the intended bypass: the goal is hash-table-lookup rendering for the dynamic connection types, not an extra World.markBlockRangeForRenderUpdate notification on chunk load. Removes MixinNetHandlerPlayClient and its Mixins.RENDERING entry.
- UniformRenderPipeline.renderBlockQuads: on BLOCK_WORLD, split the part by translucentSplit() according to the paired tessellation pass (pass0 -> non-forced quads, pass1 -> forced quads, unpaired -> whole part, never drop faces). Rewrote the stale limitation comment.
- UniformRenderPipeline.renderItemQuads: route the force-translucent sub-part to a blend-enabled render group on the item/GUI/hand/dropped batched path; skip splitting when the phase already blends (zero regression). World block path documents why per-quad translucency cannot apply (vanilla chunk pass owns blend).
- Remove MAX_DEPTH (16) and the depth parameter. ModelJson.parent is a single value, so resolution
Notes
Full Changelog: https://github.com/song682/CatFrame/commits/v0.10.11
All Relations
- All Relations
- Embedded Library
- Optional Dependency
- Required Dependency
- Tool
- Incompatible
- Include

