fix(camping): half-slab hammock geometry + smarter tent grounding
All checks were successful
Deploy Addons / deploy (push) Successful in 15s
All checks were successful
Deploy Addons / deploy (push) Successful in 15s
- Hammock now uses a custom geometry.silverlabs.hammock_slab (8-voxel tall half-slab instead of a full cube), matching its thin collision box so the block reads visually as a hammock cradle, not a brick. - Tent placement now projects the player's feet down to the nearest solid block (up to 3 blocks) before picking the base Y, so mid-jump fractional positions or standing-on-slab cases don't mis-place the footprint one block too high. - Failure messages now include the exact failing cell coordinates and the block type that's in the way, so we can diagnose live pitch attempts without guesswork. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -26,7 +26,7 @@
|
|||||||
"origin": [-8, 0, -8],
|
"origin": [-8, 0, -8],
|
||||||
"size": [16, 4, 16]
|
"size": [16, 4, 16]
|
||||||
},
|
},
|
||||||
"minecraft:geometry": "minecraft:geometry.full_block",
|
"minecraft:geometry": "geometry.silverlabs.hammock_slab",
|
||||||
"minecraft:light_dampening": 0
|
"minecraft:light_dampening": 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -96,14 +96,26 @@ function tryPlaceTent(player) {
|
|||||||
const dim = player.dimension;
|
const dim = player.dimension;
|
||||||
const facing = cardinalFacing(player.getRotation().y);
|
const facing = cardinalFacing(player.getRotation().y);
|
||||||
const { fx, fz, rx, rz } = vecsForFacing(facing);
|
const { fx, fz, rx, rz } = vecsForFacing(facing);
|
||||||
const feet = {
|
// Use precise player position; floor X/Z but scan Y downward to find the actual
|
||||||
x: Math.floor(player.location.x),
|
// standing surface. player.location.y may be fractionally above the block you're
|
||||||
y: Math.floor(player.location.y),
|
// on (e.g. 87.01), so floor() alone is reliable, but if the player is in the
|
||||||
z: Math.floor(player.location.z),
|
// air (jumping / on a slab / flying) we want to project them down to solid ground
|
||||||
};
|
// so the tent doesn't try to sit on empty space.
|
||||||
const ox = feet.x + fx;
|
const feetX = Math.floor(player.location.x);
|
||||||
const oy = feet.y;
|
const feetZ = Math.floor(player.location.z);
|
||||||
const oz = feet.z + fz;
|
let feetY = Math.floor(player.location.y);
|
||||||
|
// If the block at feet level is air (player's mid-jump or location rounded up),
|
||||||
|
// scan downward up to 3 blocks to find the ground.
|
||||||
|
for (let probe = 0; probe < 4; probe++) {
|
||||||
|
const here = dim.getBlock({ x: feetX, y: feetY - 1, z: feetZ });
|
||||||
|
if (here && here.isSolid) break;
|
||||||
|
const onSolid = dim.getBlock({ x: feetX, y: feetY, z: feetZ });
|
||||||
|
if (onSolid && onSolid.isSolid) { feetY += 1; break; }
|
||||||
|
feetY -= 1;
|
||||||
|
}
|
||||||
|
const ox = feetX + fx;
|
||||||
|
const oy = feetY;
|
||||||
|
const oz = feetZ + fz;
|
||||||
|
|
||||||
const groundCells = [];
|
const groundCells = [];
|
||||||
const clearCells = [];
|
const clearCells = [];
|
||||||
@@ -119,18 +131,19 @@ function tryPlaceTent(player) {
|
|||||||
for (const g of groundCells) {
|
for (const g of groundCells) {
|
||||||
const b = dim.getBlock(g);
|
const b = dim.getBlock(g);
|
||||||
if (!b || !b.isSolid) {
|
if (!b || !b.isSolid) {
|
||||||
player.sendMessage("§c[Camping] §7Need a flat 2×3 patch of solid ground in front of you.");
|
const seen = b ? b.typeId : "unloaded";
|
||||||
|
player.sendMessage(`§c[Camping] §7Ground at §f${g.x},${g.y},${g.z}§7 is §f${seen}§7 — need solid ground there.`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const c of clearCells) {
|
for (const c of clearCells) {
|
||||||
const b = dim.getBlock(c);
|
const b = dim.getBlock(c);
|
||||||
if (!b) {
|
if (!b) {
|
||||||
player.sendMessage("§c[Camping] §7Can't reach that area (chunk unloaded).");
|
player.sendMessage(`§c[Camping] §7Can't reach §f${c.x},${c.y},${c.z}§7 (chunk unloaded).`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!b.isAir && !b.isLiquid) {
|
if (!b.isAir && !b.isLiquid) {
|
||||||
player.sendMessage("§c[Camping] §7The space above the tent footprint isn't clear.");
|
player.sendMessage(`§c[Camping] §7Space at §f${c.x},${c.y},${c.z}§7 is blocked by §f${b.typeId}§7.`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"format_version": "1.21.0",
|
||||||
|
"minecraft:geometry": [
|
||||||
|
{
|
||||||
|
"description": {
|
||||||
|
"identifier": "geometry.silverlabs.hammock_slab",
|
||||||
|
"texture_width": 16,
|
||||||
|
"texture_height": 16,
|
||||||
|
"visible_bounds_width": 2,
|
||||||
|
"visible_bounds_height": 1,
|
||||||
|
"visible_bounds_offset": [0, 0.25, 0]
|
||||||
|
},
|
||||||
|
"bones": [
|
||||||
|
{
|
||||||
|
"name": "root",
|
||||||
|
"pivot": [0, 0, 0],
|
||||||
|
"cubes": [
|
||||||
|
{
|
||||||
|
"origin": [-8, 0, -8],
|
||||||
|
"size": [16, 4, 16],
|
||||||
|
"uv": {
|
||||||
|
"north": { "uv": [0, 12], "uv_size": [16, 4] },
|
||||||
|
"south": { "uv": [0, 12], "uv_size": [16, 4] },
|
||||||
|
"east": { "uv": [0, 12], "uv_size": [16, 4] },
|
||||||
|
"west": { "uv": [0, 12], "uv_size": [16, 4] },
|
||||||
|
"up": { "uv": [0, 0], "uv_size": [16, 16] },
|
||||||
|
"down": { "uv": [0, 0], "uv_size": [16, 16] }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user