Author SHA1 Message Date
sysadminandClaude Opus 5 4c8f3b4a28 fix(dynamite): revert thrown-entity geometry; bump RPs to break client cache
Deploy Addons / deploy (push) Failing after 0s
Two problems, one of them mine.

Reverts thrown_banger/bundle/dynamite from geometry.snowball back to
geometry.item_sprite. Syncing these from main to the host produced
"[Geometry][error] geometry not found?" on the client -- geometry.snowball
does not resolve, while the April item_sprite version the host had been
running does. main was newer but had never been deployed, so the change had
never been validated against a running client. Newer is not the same as
correct, and this should have been verified before syncing rather than
assumed from the timestamps.

Separately, the client was reporting "Missing referenced asset" for every
custom block geometry -- tent_panel_l/r, hammock_slab, portal_field,
dragon_basket -- and spamming "A block must have baked material data in order
to tessellate!" 182,683 times, once per frame per unrenderable block. Those
geometry files exist and are valid; the client was serving stale cached copies
of the resource packs that predate them. Dynamite was the one pack that
refreshed, precisely because its version had just been bumped, which is why
dynamite appeared in game and camping supplies did not.

So every RP that ships models/blocks geometry is bumped to force a re-download:
spark_pet, camping_supplies and lobby_transfer, plus dynamite to carry the
geometry revert. Dependent BP manifests follow, and the world pins were set
explicitly rather than by the repin helper, which correctly refused these --
shared/ holds duplicate copies of the same UUIDs at older versions, so
"version on disk" is ambiguous for them.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015Gf1kZypRDfPL1YiWUS1LC
2026-08-28 13:50:27 +01:00
sysadminandClaude Opus 5 f67249c8db ci: cover every mounted addon in the deploy PATHS
Six addons were bind-mounted in docker-compose.yml but absent from the deploy
workflow, so CI had never deployed them: dynamite, hemp, naturalist-lite,
smart-crafting, tow-boat and trees-features. The host was consequently running
April copies of files that main had moved on from in August -- dynamite's
thrown entities still used item_sprite geometry rather than snowball, and
smart-crafting's recipe still used AlwaysUnlocked rather than unlocking from a
crafting table.

That gap also silently broke dynamite: the world pins had been advanced to RP
1.0.2 while the host stayed on 1.0.1, so the pack was dropped from every world
until the pins were corrected earlier today.

Verified before adding, rather than trusting the workflow: tow-boat and
trees-features are byte-identical between host and main, and for the other
four main is strictly newer (host files date from April, main's from August).
The only host-only files are three strays that checkout -f will not remove --
sloth.bc_ap.json, "secretary_bird.rp_ac .json" (note the space) and
warlus.json -- so nothing is lost by arming the checkout for these paths.

PATHS now covers every directory docker-compose.yml mounts, so a mount can no
longer point at a directory CI never delivers.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015Gf1kZypRDfPL1YiWUS1LC
2026-08-28 13:23:48 +01:00
sysadminandClaude Opus 5 75219f9d1d fix(naturalist): draw the three missing item icons
Deploy Addons / deploy (push) Failing after 0s
frog_leg, cooked_frog_leg and snake_egg_block are declared in the behavior
pack and mapped in item_texture.json, but the PNGs were never present, so all
three rendered as missing-texture wherever they appeared. All three already
had lang names, so only the art was absent.

Drawn through scripts/build-textures.py to match the pack's existing style --
small sprite on transparency, muted natural palette, single highlight. The
frog legs share one drumstick routine, raw carrying a green skin tint along
the top contour and cooked a browned crust. snake_egg_block is a clutch of
three eggs reusing the palette of the pack's existing single snake_egg.png,
so the block form reads as a group of the item.

RP bumped to 1.0.3 and mya's pin updated to match, otherwise clients keep
serving the cached pack and never fetch the new files.

Note: naturalist-lite-addon is absent from deploy.yml's PATHS, so CI never
deploys it -- this was applied to the host by hand. That absence is also why
the host sat on RP 1.0.1 while main was already at 1.0.2.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015Gf1kZypRDfPL1YiWUS1LC
2026-08-28 13:14:49 +01:00
sysadminandClaude Opus 5 efac50aba7 fix(lobby): sync BP dependency to bumped RP version; name portal_field
Deploy Addons / deploy (push) Failing after 0s
Two issues an addon-wide audit turned up.

The portal-texture commit bumped lobby_transfer_RP to 1.0.1 but left the
behavior pack's dependency on it pinned at 1.0.0. A dependency whose version
does not match the referenced pack's header is exactly the kind of mismatch
that makes Bedrock drop a pack, so this was a regression waiting to bite.

portal_field carries a menu_category, so it appears in the creative inventory,
but had no lang entry -- it showed as the raw key tile.silverlabs:portal_field
.name. The other four portal blocks were already named.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015Gf1kZypRDfPL1YiWUS1LC
2026-08-28 13:03:15 +01:00
sysadminandClaude Opus 5 cde6c46bf2 fix(hub-return): recover the uncommitted 1.0.9 from the NAS archive
Deploy Addons / deploy (push) Failing after 0s
hub-return existed on the host at 1.0.9 but had never been committed; main
only had 1.0.5. The deploy workflow's `git checkout -f origin/main -- $PATHS`
reverted the host to 1.0.5, discarding work that existed nowhere in git.

Recovered verbatim from the 2026-06-03 NAS archive. The RP is byte-identical
between the two, and the file sets match, so this is only the BP manifest
version plus scripts/main.js.

What 1.0.9 adds over 1.0.5:
  * a spawn tip pointing players at private chests, since break-protection
    covers chests but not terrain
  * Family Goals integration -- a "Family" button in the hub menu, shown only
    when the family-goals addon is present (sniffed via its world dynamic
    property), dispatching `scriptevent family:menu` as the player so
    family-goals sees the right sourceEntity

That integration pairs with family-goals, which was itself uncommitted until
this branch, so the two were lost and recovered together.

All three child worlds re-pinned to [1,0,9] (jamie already expected it; lyla
and mya were on 1.0.5) and verified loading at 1.0.9 in the pack stack.

Carried over as-is rather than tidied: openHubMenu still emits a
`[Hub][diag]` console.warn on every open, left from mid-development. Worth
removing, but not while recovering -- recovery should be faithful.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015Gf1kZypRDfPL1YiWUS1LC
2026-08-28 12:55:42 +01:00
sysadminandClaude Opus 5 50af20981f fix(lobby): ship real portal textures; they pointed at vanilla paths
Deploy Addons / deploy (push) Failing after 0s
The four portal blocks referenced vanilla texture paths from their own pack
(emerald_block, amethyst_block, prismarine_bricks, end_portal_frame_top)
without shipping those files. While the blocks rendered through the legacy
blocks.json path this was invisible; once minecraft:geometry made
material_instances take effect the lookup failed outright and they rendered
as missing-texture.

Ships real 16x16 textures generated through scripts/build-textures.py: a dark
stone frame around a glowing field, one hue per destination -- jamie green,
lyla purple, mya teal, plus a gold-ringed frame. terrain_texture.json now
points at these instead of vanilla paths, so every key in the pack resolves
to a file the pack actually contains.

lobby_transfer_RP bumped to 1.0.1 so clients re-download rather than serving
cached art; the lobby world pin was updated to match.

Known issue, not fixed here: lobby_transfer_RP and hub_return_transfer_BP
share pack UUID b2c3d4e5-1111-2222-3333-fedcba654321. They never load on the
same server today, so the collision is latent, but it makes version bumps on
either pack risky and should be resolved with a fresh UUID plus a pin update.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015Gf1kZypRDfPL1YiWUS1LC
2026-08-28 12:49:46 +01:00
sysadmin 57c06dde06 Merge: redstone-link addon, family-goals tracking, custom-block geometry fix
Deploy Addons / deploy (push) Successful in 14s
Brings in four commits:
  * redstone-link-addon -- wireless redstone (TX/RX paired by channel name)
  * family-goals-addon  -- was live on jamie but in no commit on any branch
  * block textures generated through scripts/build-textures.py
  * minecraft:geometry fix for the 7 custom blocks that rendered untextured

All of it is already deployed by hand and verified on the live stack, so a
CI deploy from this merge is a no-op content-wise. docker-compose.yml here is
byte-identical to the host, and deploy.yml's PATHS now covers every directory
the compose file mounts.

--no-ff so the whole change can be reverted as one unit if a live world
misbehaves.

* feat/redstone-link-and-family-goals:
  fix(addons): add minecraft:geometry to the 7 untextured custom blocks
  fix(redstone-link): add minecraft:geometry so material_instances applies
  feat(redstone-link): real block textures via build-textures.py, add build.sh
  feat(redstone-link): wireless redstone addon; track family-goals
2026-08-28 12:36:17 +01:00
29 changed files with 320 additions and 43 deletions
+7 -1
View File
@@ -16,6 +16,12 @@ on:
- 'camping-supplies-addon/**' - 'camping-supplies-addon/**'
- 'family-goals-addon/**' - 'family-goals-addon/**'
- 'redstone-link-addon/**' - 'redstone-link-addon/**'
- 'dynamite-addon/**'
- 'hemp-addon/**'
- 'naturalist-lite-addon/**'
- 'smart-crafting-addon/**'
- 'tow-boat-addon/**'
- 'trees-features-addon/**'
- 'docker-compose.yml' - 'docker-compose.yml'
- 'scripts/**' - 'scripts/**'
@@ -38,7 +44,7 @@ jobs:
# are listed because docker-compose.yml mounts them; omitting either # are listed because docker-compose.yml mounts them; omitting either
# while checking out docker-compose.yml would leave a mount pointing # while checking out docker-compose.yml would leave a mount pointing
# at a directory this job never delivers. # at a directory this job never delivers.
PATHS="addon/ lobby-addon/ hub-return-addon/ village-evolution-addon/ monkey-addon/ private-chest-addon/ home-sign-addon/ keep-inventory-addon/ postal-service-addon/ camping-supplies-addon/ family-goals-addon/ redstone-link-addon/ docker-compose.yml" PATHS="addon/ lobby-addon/ hub-return-addon/ village-evolution-addon/ monkey-addon/ private-chest-addon/ home-sign-addon/ keep-inventory-addon/ postal-service-addon/ camping-supplies-addon/ family-goals-addon/ redstone-link-addon/ dynamite-addon/ hemp-addon/ naturalist-lite-addon/ smart-crafting-addon/ tow-boat-addon/ trees-features-addon/ docker-compose.yml"
# First run: clone. Subsequent: pull. # First run: clone. Subsequent: pull.
if [ ! -d "$APP_DIR/.git" ]; then if [ ! -d "$APP_DIR/.git" ]; then
+1 -1
View File
@@ -32,7 +32,7 @@
"version": [ "version": [
1, 1,
0, 0,
1 2
] ]
} }
] ]
+20 -4
View File
@@ -4,20 +4,36 @@
"name": "Pets 4 Jamie's STARS Resources", "name": "Pets 4 Jamie's STARS Resources",
"description": "Textures, models and animations for Pets 4 Jamie's STARS", "description": "Textures, models and animations for Pets 4 Jamie's STARS",
"uuid": "5f25d547-00bb-49ce-8be3-d86cd3941c9b", "uuid": "5f25d547-00bb-49ce-8be3-d86cd3941c9b",
"version": [1, 0, 1], "version": [
"min_engine_version": [1, 21, 0] 1,
0,
2
],
"min_engine_version": [
1,
21,
0
]
}, },
"modules": [ "modules": [
{ {
"type": "resources", "type": "resources",
"uuid": "6adc20cd-25a5-4ca5-aa12-f5e43ee9ea22", "uuid": "6adc20cd-25a5-4ca5-aa12-f5e43ee9ea22",
"version": [1, 0, 1] "version": [
1,
0,
2
]
} }
], ],
"dependencies": [ "dependencies": [
{ {
"uuid": "7cf924ce-e246-4c8c-998c-f420edb26451", "uuid": "7cf924ce-e246-4c8c-998c-f420edb26451",
"version": [1, 0, 0] "version": [
1,
0,
0
]
} }
] ]
} }
@@ -47,7 +47,7 @@
"version": [ "version": [
1, 1,
0, 0,
1 2
] ]
} }
] ]
@@ -4,14 +4,26 @@
"name": "Camping Supplies Resources", "name": "Camping Supplies Resources",
"description": "Textures and lang for camping supplies (tent, hammock, canvas, cloth)", "description": "Textures and lang for camping supplies (tent, hammock, canvas, cloth)",
"uuid": "36f12107-10c6-484c-a0f2-b5dd88cd5baa", "uuid": "36f12107-10c6-484c-a0f2-b5dd88cd5baa",
"version": [1, 0, 1], "version": [
"min_engine_version": [1, 21, 0] 1,
0,
2
],
"min_engine_version": [
1,
21,
0
]
}, },
"modules": [ "modules": [
{ {
"type": "resources", "type": "resources",
"uuid": "c9ee429f-9374-4083-843b-4b195e8db130", "uuid": "c9ee429f-9374-4083-843b-4b195e8db130",
"version": [1, 0, 1] "version": [
1,
0,
2
]
} }
] ]
} }
Binary file not shown.

Before

Width:  |  Height:  |  Size: 427 B

After

Width:  |  Height:  |  Size: 381 B

+1 -1
View File
@@ -32,7 +32,7 @@
"version": [ "version": [
1, 1,
0, 0,
2 3
] ]
} }
] ]
@@ -3,10 +3,18 @@
"minecraft:client_entity": { "minecraft:client_entity": {
"description": { "description": {
"identifier": "silverlabs:thrown_banger", "identifier": "silverlabs:thrown_banger",
"materials": { "default": "entity_alphatest" }, "materials": {
"textures": { "default": "textures/entity/thrown_banger" }, "default": "entity_alphatest"
"geometry": { "default": "geometry.snowball" }, },
"render_controllers": [ "controller.render.snowball" ] "textures": {
"default": "textures/entity/thrown_banger"
},
"geometry": {
"default": "geometry.item_sprite"
},
"render_controllers": [
"controller.render.item_sprite"
]
} }
} }
} }
@@ -3,10 +3,18 @@
"minecraft:client_entity": { "minecraft:client_entity": {
"description": { "description": {
"identifier": "silverlabs:thrown_bundle", "identifier": "silverlabs:thrown_bundle",
"materials": { "default": "entity_alphatest" }, "materials": {
"textures": { "default": "textures/entity/thrown_bundle" }, "default": "entity_alphatest"
"geometry": { "default": "geometry.snowball" }, },
"render_controllers": [ "controller.render.snowball" ] "textures": {
"default": "textures/entity/thrown_bundle"
},
"geometry": {
"default": "geometry.item_sprite"
},
"render_controllers": [
"controller.render.item_sprite"
]
} }
} }
} }
@@ -3,10 +3,18 @@
"minecraft:client_entity": { "minecraft:client_entity": {
"description": { "description": {
"identifier": "silverlabs:thrown_dynamite", "identifier": "silverlabs:thrown_dynamite",
"materials": { "default": "entity_alphatest" }, "materials": {
"textures": { "default": "textures/entity/thrown_dynamite" }, "default": "entity_alphatest"
"geometry": { "default": "geometry.snowball" }, },
"render_controllers": [ "controller.render.snowball" ] "textures": {
"default": "textures/entity/thrown_dynamite"
},
"geometry": {
"default": "geometry.item_sprite"
},
"render_controllers": [
"controller.render.item_sprite"
]
} }
} }
} }
+15 -3
View File
@@ -4,14 +4,26 @@
"name": "Dynamite Resources", "name": "Dynamite Resources",
"description": "Textures and language for the Dynamite addon.", "description": "Textures and language for the Dynamite addon.",
"uuid": "a18bdde1-53f8-49aa-b06d-6f0ec6c45b46", "uuid": "a18bdde1-53f8-49aa-b06d-6f0ec6c45b46",
"version": [1, 0, 2], "version": [
"min_engine_version": [1, 21, 0] 1,
0,
3
],
"min_engine_version": [
1,
21,
0
]
}, },
"modules": [ "modules": [
{ {
"type": "resources", "type": "resources",
"uuid": "587281f2-f159-4ad9-85a6-d20ff4899717", "uuid": "587281f2-f159-4ad9-85a6-d20ff4899717",
"version": [1, 0, 2] "version": [
1,
0,
3
]
} }
] ]
} }
@@ -4,7 +4,7 @@
"name": "Hub Return Transfer", "name": "Hub Return Transfer",
"description": "Transfers players back to lobby when they step on the return portal", "description": "Transfers players back to lobby when they step on the return portal",
"uuid": "b2c3d4e5-1111-2222-3333-fedcba654321", "uuid": "b2c3d4e5-1111-2222-3333-fedcba654321",
"version": [1, 0, 5], "version": [1, 0, 9],
"min_engine_version": [1, 21, 0] "min_engine_version": [1, 21, 0]
}, },
"modules": [ "modules": [
@@ -12,7 +12,7 @@
"type": "script", "type": "script",
"language": "javascript", "language": "javascript",
"uuid": "b2c3d4e5-4444-5555-6666-fedcba987654", "uuid": "b2c3d4e5-4444-5555-6666-fedcba987654",
"version": [1, 0, 5], "version": [1, 0, 9],
"entry": "scripts/main.js" "entry": "scripts/main.js"
} }
], ],
@@ -190,6 +190,8 @@ world.afterEvents.playerSpawn.subscribe((event) => {
player.runCommand(`titleraw @s title {"rawtext":[{"text":"§6Welcome!"}]}`); player.runCommand(`titleraw @s title {"rawtext":[{"text":"§6Welcome!"}]}`);
player.runCommand(`titleraw @s subtitle {"rawtext":[{"text":"§7You are now in §e${WORLD_NAME}"}]}`); player.runCommand(`titleraw @s subtitle {"rawtext":[{"text":"§7You are now in §e${WORLD_NAME}"}]}`);
giveCompassIfMissing(player); giveCompassIfMissing(player);
// Light social reminder — break-protection only covers chests, not terrain.
player.sendMessage("§7[Tip] §fUse a §dprivate chest§f for valuables — break-protection only covers chests.");
} catch (e) { } catch (e) {
// Player may have disconnected // Player may have disconnected
} }
@@ -244,6 +246,27 @@ async function openCompassMenu(player) {
form.button("\uD83E\uDDED Get a marker block"); form.button("\uD83E\uDDED Get a marker block");
actions.push({ kind: "give_marker" }); actions.push({ kind: "give_marker" });
// Family Goals integration — only surfaces if the family-goals addon is loaded
// in this world. We sniff its world dynamic property; absence = silent skip.
let familyLoaded = false;
let famDebug = "?";
let idsList = "?";
try {
const v = world.getDynamicProperty("family_goals_v1");
famDebug = `${typeof v}:${v === undefined ? "undef" : String(v).slice(0, 30)}`;
familyLoaded = v !== undefined;
if (typeof world.getDynamicPropertyIds === "function") {
idsList = world.getDynamicPropertyIds().join(",");
} else {
idsList = "(getDynamicPropertyIds missing)";
}
} catch (e) { famDebug = `err:${e.message}`; }
console.warn(`[Hub][diag] familyLoaded=${familyLoaded} probe=${famDebug} ids=${idsList}`);
if (familyLoaded) {
form.button("\uD83C\uDFC6 Family");
actions.push({ kind: "family_menu" });
}
form.button("§7Cancel"); form.button("§7Cancel");
actions.push({ kind: "cancel" }); actions.push({ kind: "cancel" });
@@ -282,6 +305,14 @@ async function openCompassMenu(player) {
giveMarkerBlock(player); giveMarkerBlock(player);
return; return;
} }
if (a.kind === "family_menu") {
// Hand off to family-goals addon. The scriptevent is dispatched as the
// player so family-goals' subscriber sees event.sourceEntity = this player.
try { player.runCommand("scriptevent family:menu"); } catch (e) {
player.sendMessage(`§c[Hub] Couldn't open Family menu: ${e.message}`);
}
return;
}
} }
function giveMarkerBlock(player) { function giveMarkerBlock(player) {
+25 -5
View File
@@ -4,20 +4,36 @@
"name": "Lobby Portal Transfer", "name": "Lobby Portal Transfer",
"description": "Auto-transfers players when they step into portal areas", "description": "Auto-transfers players when they step into portal areas",
"uuid": "a1b2c3d4-1111-2222-3333-abcdef123456", "uuid": "a1b2c3d4-1111-2222-3333-abcdef123456",
"version": [1, 1, 0], "version": [
"min_engine_version": [1, 21, 0] 1,
1,
0
],
"min_engine_version": [
1,
21,
0
]
}, },
"modules": [ "modules": [
{ {
"type": "data", "type": "data",
"uuid": "a1b2c3d4-7777-8888-9999-abcdef345678", "uuid": "a1b2c3d4-7777-8888-9999-abcdef345678",
"version": [1, 1, 0] "version": [
1,
1,
0
]
}, },
{ {
"type": "script", "type": "script",
"language": "javascript", "language": "javascript",
"uuid": "a1b2c3d4-4444-5555-6666-abcdef789012", "uuid": "a1b2c3d4-4444-5555-6666-abcdef789012",
"version": [1, 1, 0], "version": [
1,
1,
0
],
"entry": "scripts/main.js" "entry": "scripts/main.js"
} }
], ],
@@ -32,7 +48,11 @@
}, },
{ {
"uuid": "b2c3d4e5-1111-2222-3333-fedcba654321", "uuid": "b2c3d4e5-1111-2222-3333-fedcba654321",
"version": [1, 0, 0] "version": [
1,
0,
2
]
} }
] ]
} }
+15 -3
View File
@@ -4,14 +4,26 @@
"name": "Lobby Portal Transfer Resources", "name": "Lobby Portal Transfer Resources",
"description": "Textures and lang for craftable portal blocks", "description": "Textures and lang for craftable portal blocks",
"uuid": "b2c3d4e5-1111-2222-3333-fedcba654321", "uuid": "b2c3d4e5-1111-2222-3333-fedcba654321",
"version": [1, 0, 0], "version": [
"min_engine_version": [1, 21, 0] 1,
0,
2
],
"min_engine_version": [
1,
21,
0
]
}, },
"modules": [ "modules": [
{ {
"type": "resources", "type": "resources",
"uuid": "b2c3d4e5-4444-5555-6666-fedcba987654", "uuid": "b2c3d4e5-4444-5555-6666-fedcba987654",
"version": [1, 0, 0] "version": [
1,
0,
2
]
} }
] ]
} }
@@ -2,3 +2,4 @@ tile.silverlabs:portal_frame.name=Portal Frame
tile.silverlabs:portal_jamie.name=Jamie's World Portal tile.silverlabs:portal_jamie.name=Jamie's World Portal
tile.silverlabs:portal_lyla.name=Lyla's World Portal tile.silverlabs:portal_lyla.name=Lyla's World Portal
tile.silverlabs:portal_mya.name=Mya's World Portal tile.silverlabs:portal_mya.name=Mya's World Portal
tile.silverlabs:portal_field.name=Portal Field
Binary file not shown.

After

Width:  |  Height:  |  Size: 194 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 216 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 216 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 216 B

@@ -5,16 +5,16 @@
"num_mip_levels": 4, "num_mip_levels": 4,
"texture_data": { "texture_data": {
"portal_frame": { "portal_frame": {
"textures": "textures/blocks/end_portal_frame_top" "textures": "textures/blocks/portal_frame"
}, },
"portal_jamie": { "portal_jamie": {
"textures": "textures/blocks/emerald_block" "textures": "textures/blocks/portal_jamie"
}, },
"portal_lyla": { "portal_lyla": {
"textures": "textures/blocks/amethyst_block" "textures": "textures/blocks/portal_lyla"
}, },
"portal_mya": { "portal_mya": {
"textures": "textures/blocks/prismarine_bricks" "textures": "textures/blocks/portal_mya"
}, },
"portal_field": { "portal_field": {
"textures": "textures/blocks/portal_field" "textures": "textures/blocks/portal_field"
@@ -4,14 +4,26 @@
"name": "Naturalist Lite Resources", "name": "Naturalist Lite Resources",
"description": "Textures, models, and animations for Naturalist Lite mobs.", "description": "Textures, models, and animations for Naturalist Lite mobs.",
"uuid": "de1b016a-3cf3-4f75-8076-5a5508ab8b74", "uuid": "de1b016a-3cf3-4f75-8076-5a5508ab8b74",
"version": [1, 0, 2], "version": [
"min_engine_version": [1, 21, 0] 1,
0,
3
],
"min_engine_version": [
1,
21,
0
]
}, },
"modules": [ "modules": [
{ {
"type": "resources", "type": "resources",
"uuid": "29da80f3-cffc-4c3b-997d-34f0820cc65b", "uuid": "29da80f3-cffc-4c3b-997d-34f0820cc65b",
"version": [1, 0, 2] "version": [
1,
0,
3
]
} }
] ]
} }
Binary file not shown.

After

Width:  |  Height:  |  Size: 177 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 207 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 228 B

After

Width:  |  Height:  |  Size: 220 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 321 B

After

Width:  |  Height:  |  Size: 295 B

+131
View File
@@ -482,14 +482,145 @@ def redstone_link_rx() -> Image.Image:
return img return img
# ── Lobby portal blocks ────────────────────────────────────
# These previously pointed terrain_texture.json at vanilla paths
# (emerald_block, amethyst_block, prismarine_bricks, end_portal_frame_top)
# which a custom pack cannot resolve, so they rendered as missing-texture
# once minecraft:geometry made material_instances take effect. Ship real
# textures instead: a dark stone frame around a glowing field, one hue per
# child, so the three destinations are distinguishable at a glance.
PORTAL_STONE = (58, 60, 68)
PORTAL_STONE_HL = (86, 89, 99)
PORTAL_STONE_SH = (34, 35, 41)
def _portal_face(core, bright, glow):
img = Image.new("RGBA", (16, 16), PORTAL_STONE)
# chiselled frame
rect(img, 0, 0, 15, 0, PORTAL_STONE_HL)
rect(img, 0, 0, 0, 15, PORTAL_STONE_HL)
rect(img, 0, 15, 15, 15, PORTAL_STONE_SH)
rect(img, 15, 0, 15, 15, PORTAL_STONE_SH)
rect(img, 2, 2, 13, 13, PORTAL_STONE_SH)
# glowing field
rect(img, 3, 3, 12, 12, core)
rect(img, 4, 4, 11, 11, bright)
rect(img, 6, 6, 9, 9, glow)
# corner sparks so the field reads as energy, not flat paint
for cx, cy in ((4, 4), (11, 4), (4, 11), (11, 11)):
px(img, cx, cy, glow)
# dark centre seam
rect(img, 7, 7, 8, 8, core)
return img
def portal_jamie(): return _portal_face((22, 92, 40), (46, 156, 66), (140, 240, 150))
def portal_lyla(): return _portal_face((78, 40, 130), (126, 74, 190), (214, 168, 255))
def portal_mya(): return _portal_face((22, 96, 104), (46, 152, 160), (150, 238, 244))
def portal_frame():
img = Image.new("RGBA", (16, 16), PORTAL_STONE)
rect(img, 0, 0, 15, 0, PORTAL_STONE_HL)
rect(img, 0, 0, 0, 15, PORTAL_STONE_HL)
rect(img, 0, 15, 15, 15, PORTAL_STONE_SH)
rect(img, 15, 0, 15, 15, PORTAL_STONE_SH)
# inset panel with a dull gold ring, echoing an end portal frame
rect(img, 3, 3, 12, 12, (48, 50, 57))
for x in range(4, 12):
px(img, x, 4, GOLD); px(img, x, 11, GOLD)
for y in range(4, 12):
px(img, 4, y, GOLD); px(img, 11, y, GOLD)
rect(img, 6, 6, 9, 9, (70, 66, 40))
px(img, 7, 7, GOLD_BRIGHT); px(img, 8, 8, GOLD_BRIGHT)
return img
# ── Naturalist Lite: three items shipped without icons ─────
# frog_leg, cooked_frog_leg and snake_egg_block are declared in the BP and
# mapped in item_texture.json, but the PNGs were never present, so they
# rendered as missing-texture. Drawn to match the pack's existing style:
# small sprite on transparency, muted natural palette, single highlight.
FROG_RAW = (176, 122, 128)
FROG_RAW_HI = (214, 164, 168)
FROG_RAW_SH = (126, 82, 92)
FROG_SKIN = (122, 148, 96)
FROG_COOK = (156, 104, 56)
FROG_COOK_HI = (198, 146, 88)
FROG_COOK_SH = (104, 64, 32)
BONE = (232, 226, 206)
BONE_SH = (176, 170, 152)
EGG_SHELL = (222, 214, 196)
EGG_SHELL_HI = (244, 240, 228)
EGG_SHELL_SH = (170, 162, 144)
EGG_SPOT = (150, 138, 112)
def _frog_leg(meat, hi, sh, skin=None):
"""Drumstick: meat mass upper-left, bone stub lower-right."""
img = Image.new("RGBA", (16, 16), (0, 0, 0, 0))
# meat mass
rect(img, 4, 2, 10, 8, meat)
rect(img, 3, 3, 3, 7, meat)
rect(img, 11, 3, 11, 7, meat)
rect(img, 5, 1, 9, 1, meat)
rect(img, 5, 9, 9, 9, meat)
# shading
rect(img, 4, 8, 10, 9, sh)
rect(img, 11, 4, 11, 7, sh)
# highlight
rect(img, 5, 2, 7, 3, hi)
px(img, 5, 4, hi)
# raw frog keeps a green tinge along the top contour rather than a patch,
# so it reads as skin on the meat instead of a floating square
if skin:
for sx, sy in ((6, 1), (7, 1), (8, 1), (9, 2), (10, 3), (5, 2)):
px(img, sx, sy, skin)
px(img, 8, 2, (140, 166, 112))
# bone stub running to lower-right
rect(img, 9, 10, 10, 11, BONE)
rect(img, 11, 12, 12, 13, BONE)
px(img, 12, 14, BONE)
px(img, 10, 11, BONE_SH)
px(img, 12, 13, BONE_SH)
px(img, 13, 14, BONE_SH)
return img
def frog_leg(): return _frog_leg(FROG_RAW, FROG_RAW_HI, FROG_RAW_SH, FROG_SKIN)
def cooked_frog_leg(): return _frog_leg(FROG_COOK, FROG_COOK_HI, FROG_COOK_SH)
def snake_egg_block():
"""A clutch of eggs, so it reads as the block form of the single egg item."""
img = Image.new("RGBA", (16, 16), (0, 0, 0, 0))
def egg(cx, cy, w, h):
rect(img, cx, cy, cx + w, cy + h, EGG_SHELL)
rect(img, cx, cy + h, cx + w, cy + h, EGG_SHELL_SH)
rect(img, cx + w, cy + 1, cx + w, cy + h, EGG_SHELL_SH)
px(img, cx + 1, cy + 1, EGG_SHELL_HI)
egg(2, 6, 4, 6)
egg(9, 5, 4, 6)
egg(5, 8, 4, 5)
# speckles
for sx, sy in ((3, 9), (11, 8), (6, 11), (4, 7), (12, 10)):
px(img, sx, sy, EGG_SPOT)
return img
def main() -> None: def main() -> None:
save(smart_crafting_table(), "smart-crafting-addon/smart_crafting_RP/textures/blocks/smart_crafting_table.png") save(smart_crafting_table(), "smart-crafting-addon/smart_crafting_RP/textures/blocks/smart_crafting_table.png")
save(post_office_block(), "postal-service-addon/postal_service_RP/textures/blocks/post_office.png") save(post_office_block(), "postal-service-addon/postal_service_RP/textures/blocks/post_office.png")
save(mailbox_block(), "postal-service-addon/postal_service_RP/textures/blocks/mailbox.png") save(mailbox_block(), "postal-service-addon/postal_service_RP/textures/blocks/mailbox.png")
save(tent_canvas(), "camping-supplies-addon/camping_supplies_RP/textures/blocks/tent_canvas.png") save(tent_canvas(), "camping-supplies-addon/camping_supplies_RP/textures/blocks/tent_canvas.png")
save(portal_field(), "lobby-addon/lobby_transfer_RP/textures/blocks/portal_field.png") save(portal_field(), "lobby-addon/lobby_transfer_RP/textures/blocks/portal_field.png")
save(portal_frame(), "lobby-addon/lobby_transfer_RP/textures/blocks/portal_frame.png")
save(portal_jamie(), "lobby-addon/lobby_transfer_RP/textures/blocks/portal_jamie.png")
save(portal_lyla(), "lobby-addon/lobby_transfer_RP/textures/blocks/portal_lyla.png")
save(portal_mya(), "lobby-addon/lobby_transfer_RP/textures/blocks/portal_mya.png")
save(redstone_link_tx(), "redstone-link-addon/redstone_link_RP/textures/blocks/redstone_link_tx.png") save(redstone_link_tx(), "redstone-link-addon/redstone_link_RP/textures/blocks/redstone_link_tx.png")
save(redstone_link_rx(), "redstone-link-addon/redstone_link_RP/textures/blocks/redstone_link_rx.png") save(redstone_link_rx(), "redstone-link-addon/redstone_link_RP/textures/blocks/redstone_link_rx.png")
NAT = "naturalist-lite-addon/naturalist_lite_RP/textures/sf/nba/items/"
save(frog_leg(), NAT + "frog_leg.png")
save(cooked_frog_leg(), NAT + "cooked_frog_leg.png")
save(snake_egg_block(), NAT + "snake_egg_block.png")
if __name__ == "__main__": if __name__ == "__main__":
Binary file not shown.

Before

Width:  |  Height:  |  Size: 407 B

After

Width:  |  Height:  |  Size: 366 B