feat(textures): author seamless 3D cobblestone vector master (#28) - #195
feat(textures): author seamless 3D cobblestone vector master (#28)#195anjana005 wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
Thanks for pushing this one forward — the blockstate approach and the palette work are right, and the intent behind the design is clearly the correct one. Four things block merge, all reproduced locally against this branch (npm ci, node v24.11.1, @resvg/resvg-js ^2.6.2, base 1d99625).
The short version: the texture lands in a directory the pack never reads, the entire 3D bevel layer is silently discarded by resvg, and the new seam-audit harness fails on this file while its three sibling textures pass at Δ=0.
Blocking
1. Wrong directory — the texture is never applied in-game
textures/cobblestone.svg is at the top level. Every other block master lives in textures/block/, and CONTRIBUTING.md L163 specifies textures/block/*.svg.
tools/build.mjs L202-L203 mirrors the source directory verbatim:
const relDir = path.dirname(file.relPath);
const targetDir = relDir === "." ? ASSETS_TEXTURES_DIR : path.join(ASSETS_TEXTURES_DIR, relDir);relDir === ".", so the output is assets/minecraft/textures/cobblestone.png. Visible in the build log:
✓ block/tall_grass_top.png
✓ cobblestone.png <-- no block/ prefix
The vanilla block/cobblestone model resolves minecraft:block/cobblestone → assets/minecraft/textures/block/cobblestone.png, which the pack does not ship. The block renders vanilla, and the blockstate override added here is a no-op as a result.
Fix: git mv textures/cobblestone.svg textures/block/cobblestone.svg, rebuild, and confirm the log prints ✓ block/cobblestone.png.
2. The entire 3D bevel layer renders as nothing
The bevel group is wrapped in clip-path="url(#clip_lego_matrix)", and that clip path is:
<clipPath id="clip_lego_matrix">
<use href="#stone_lego_matrix" />
</clipPath>#stone_lego_matrix is a <g>. Per SVG 1.1, a <clipPath> child <use> must reference a shape or text element — referencing a group is not valid, and resvg resolves it to an empty clip. Both bevel strokes are therefore culled entirely.
Verified by rendering the file as-authored versus with the clip-path attribute stripped: the as-authored render contains zero #a4a7ae highlight pixels; the stripped render contains them. What ships today is flat two-tone plus a 3px drop shadow — no highlight rim, no undercut shadow.
3. Even with the clip fixed, the stroke is per-rect, not a union perimeter
stroke on <use href="#a-group"> is an inherited presentation attribute — it applies to each of the ~145 child <rect> elements individually, not to the silhouette of their union. Rendering with the clip removed confirms this: the result is a graph-paper grid of 32px outlined squares, with rims drawn along interior boundaries between adjacent plates of the same boulder. The interlocking matrix reads as a checkerboard rather than as merged stones.
Worth flagging together with #2, because fixing the clip alone makes the texture look worse, not better. A real union outline needs merged <path> silhouettes rather than per-cell rects.
4. Fails the toroidal seam gate; its three siblings pass
npm run test:tiling on this branch:
✓ PASS block/coal_ore.svg [X+Y] Seam Δ=0 (0 errors)
✓ PASS block/diamond_ore.svg [X+Y] Seam Δ=0 (0 errors)
✓ PASS block/stone.svg [X+Y] Seam Δ=0 (0 errors)
✗ FAIL cobblestone.svg [X+Y] X: 236 errs, Y: 352 errs (Max Δ=60)
Baseline main is 20 failures / 30 textures; this branch is 21 / 31. The suite is already red overall, so this isn't a new CI break — but the standard is clearly achievable and the other three textures in this same set meet it at Δ=0.
Underneath those counts sits one genuine, non-heuristic defect. The drop-shadow layer is <use ... y="3">, unclipped, so each plate's shadow occupies the 3px strip below it. For plates on the bottom row (y=480) that strip falls at y=512–515 and is clipped away by the viewBox — it never reappears at the top of the tile above:
| Location | Expected | Actual |
|---|---|---|
| Interior plate bottom edge (x=0, y=384–386) | #43454b shadow |
#43454b ✓ |
| Wrapped bottom edge (x=32/160/192/352, y=0–2) | #43454b shadow |
#5f6268 mortar ✗ |
Bottom-row boulders end up as the only ones in the pattern with no cast shadow — a systematic discontinuity when tiled.
In fairness to the numbers: analyzeSeams compares column 0 against column W−1 for pixel equality, which is stricter than true toroidal continuity — a design where a plate edge lands exactly on the boundary is visually fine but still fails. Much of the 236/352 count is that stricter criterion. The shadow-clipping defect above is the part that actually shows.
Non-blocking
5. The directional lighting isn't directional. The comments promise a "Sunlit Highlight Rim (Top-Left)" and "Undercut Crevice Shadow (Bottom-Right)", but both strokes are full closed outlines on all four sides. The only asymmetry is the shadow stroke's y="2" offset, which affects top/bottom only — nothing distinguishes left from right. And because the shadow is painted after the highlight, it overpaints all but ~2px at the top, so the net effect would be a mostly-dark outline rather than a top-left light catch.
6. stroke-width="4" yields a 2px rim. SVG strokes are centred on the path, so 2px falls outside the shape and is removed by the clip. The description calls it a "crisp 4px rim" twice.
7. Style divergence from stone.svg. textures/block/stone.svg uses rx="8" on every groove, which is where the rounded plate silhouette in the house style comes from. Cobblestone uses bare square rects with no rx, while the CHANGELOG entry added here describes "interlocking rounded 3D boulders". The palette itself (#7e8187 / #5f6268 / #a4a7ae / #3c3e44) matches stone exactly — that claim holds.
8. The CHANGELOG edit weakens an accurate entry. The rewrite appends "and 100% seamless toroidal tiling (#28)" to a bullet now covering stone, cobblestone, diamond_ore and coal_ore — not true for cobblestone per #4. It also drops "synchronized stone backgrounds", which documented the real invariant from CONTRIBUTING.md L77 that ore textures inherit stone's background. Suggest restoring the original wording and giving cobblestone its own bullet.
9. Blockstate formatting. stone.json and the other 15 files in that directory expand the model object across lines; the new cobblestone.json puts it inline. Cosmetic, but the directory is otherwise uniform.
10. Dead markup. xmlns:xlink is declared but never used (href is used throughout, which resvg supports). <g id="cobblestones"> has an id nothing references. id="clip_lego_matrix" is effectively dead given #2.
11. Maintainability of the geometry. The 145 hand-listed <rect> elements are hard to review and hard to modify — and #3 requires modifying them. A merged <path> with a compact d, or a small generation script committed alongside, would make both the audit and the fix tractable.
What's already right
- Blockstate JSON is structurally valid and matches the un-rotated single-variant pattern used by
stone.json/coal_ore.json/diamond_ore.json. The intent — suppressing random model rotation to preserve tiling continuity — is correct. - Palette is exactly synchronized with
stone.svg; all four hex values match. viewBox="0 0 512 512", 32px texel-grid alignment, no editor namespaces, no embedded raster, trailing newlines and 2-space indent per.editorconfig.npm run buildcompletes successfully.
Why nothing caught #1
Not a stale branch — the merge base here is 1d99625, the current tip of main, and author and commit timestamps are identical, so this is a fresh commit on an up-to-date tree. The directory convention simply moved recently:
| Date | Commit | Event |
|---|---|---|
| 2026-08-30 | dd538f4 (#39) |
textures/stone.svg, coal_ore.svg, diamond_ore.svg added at top level — correct at the time |
| 2026-08-31 | 0c62d0d (#189) |
All 29 masters renamed into textures/block/ (pure rename, no texture changes) |
| 2026-09-01 | e84b0a5 (this PR) |
textures/cobblestone.svg added following the pre-rename layout |
Three things meant nothing surfaced the mismatch:
- Rebasing can't help:
cobblestone.svgis a brand-new file, so there's no rename for git to follow and no conflict to raise. tools/build.mjsexplicitly accepts a top-level SVG and reports success, sonpm run buildpassing was accurate.CONTRIBUTING.mdL46 still says textures live intextures/, contradicting L163'stextures/block/*.svg.
Two follow-ups worth opening separately, independent of this PR: have the compiler reject or warn on SVGs sitting at the root of textures/, and reconcile those two CONTRIBUTING lines.
Suggested path to merge
git mv textures/cobblestone.svg textures/block/cobblestone.svg; rebuild and confirm✓ block/cobblestone.png.- Replace the per-cell
<rect>matrix with merged per-boulder<path>silhouettes sostrokeproduces a real perimeter bevel, and drop the invalid group-referencing<clipPath>. - Make the lighting genuinely directional — separate top-left highlight and bottom-right shadow geometry, the way
stone.svgdoes with its top cast-shadow / bottom highlight-rim rect pairs. - Wrap the drop shadow toroidally: draw it a second time at
y="3-512"so the bottom row's shadow reappears at the top edge. - Re-run
npm run test:tilingand getcobblestone.svgto Δ=0 alongside its three siblings. - Adjust the CHANGELOG bullet and the "4px rim" / "100% toroidal" claims in the description to match what the file does.
Happy to pair on the <path> merge in step 2 if that's useful — it's the fiddliest part of the list.
|
Moving it to Two smaller notes:
|
7c875d9 to
44a979e
Compare
Description
Author high-fidelity vector (SVG) master and un-rotated blockstate for Cobblestone matching the official cinematic Minecraft trailer aesthetic (#28):
textures/cobblestone.svg):textures/stone.svg:#7e8187#5f6268#a4a7ae(crisp 4px rim)#3c3e44(crisp 4px rim)#3c3e44(+3px Y offset into mortar bed)pack_template/assets/minecraft/blockstates/cobblestone.json):CHANGELOG.md[Unreleased]with cobblestone.Closes #28
Affected Assets
textures/cobblestone.svgpack_template/assets/minecraft/blockstates/cobblestone.jsonCHANGELOG.mdType of Change
feat: New vector texture master, blockstate, or compiler capabilityfix: Tiling fix, palette correction, or bugfixdocs: Documentation improvementchore/refactor: Maintenance, dependencies, or codebase cleanupContributor Checklist
Vector Texture Standards (if adding/modifying SVGs)
viewBox="0 0 512 512").textures/stone.svg.Build & Verification
npm run buildlocally and verified that the pack compiles successfully.dist/.Git Hygiene & Standards
feat(textures): ...).git commit -s).mainwith no merge commits..editorconfig(2-space indent, LF endings, trailing newline).