fix(camping): tent clearance + real hammock lie-in behavior
All checks were successful
Deploy Addons / deploy (push) Successful in 15s
All checks were successful
Deploy Addons / deploy (push) Successful in 15s
Three fixes for feedback from live testing: 1) Tent pitch check required 3 blocks of air above the footprint but the tent is only 2 blocks tall. Relaxed clearance to match the actual structure height (h <= 1). 2) Hammock block had a 4px-tall collision box which pushed the player on TOP of the cloth. Reduced collision to 1px so the player stands inside the hammock cell. Selection box stays at 4px for easy click. 3) Climbing in now actually locks the player: applies slowness 255, weakness, mining_fatigue for the duration, saves the anchor point in a dynamic property, and the upkeep loop re-teleports them if they drift off. Sneak-exit nudges them ~1.2 blocks forward of the cradle so they don't immediately re-enter. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -20,7 +20,7 @@
|
|||||||
},
|
},
|
||||||
"minecraft:collision_box": {
|
"minecraft:collision_box": {
|
||||||
"origin": [-8, 0, -8],
|
"origin": [-8, 0, -8],
|
||||||
"size": [16, 4, 16]
|
"size": [16, 1, 16]
|
||||||
},
|
},
|
||||||
"minecraft:selection_box": {
|
"minecraft:selection_box": {
|
||||||
"origin": [-8, 0, -8],
|
"origin": [-8, 0, -8],
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ function tryPlaceTent(player) {
|
|||||||
const cx = ox + l * fx + w * rx;
|
const cx = ox + l * fx + w * rx;
|
||||||
const cz = oz + l * fz + w * rz;
|
const cz = oz + l * fz + w * rz;
|
||||||
groundCells.push({ x: cx, y: oy - 1, z: cz });
|
groundCells.push({ x: cx, y: oy - 1, z: cz });
|
||||||
for (let h = 0; h <= 2; h++) clearCells.push({ x: cx, y: oy + h, z: cz });
|
for (let h = 0; h <= 1; h++) clearCells.push({ x: cx, y: oy + h, z: cz });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -310,31 +310,81 @@ function sleepInTent(player) {
|
|||||||
player.sendMessage("§a[Camping] §7You rest until dawn. §8Spawn point unchanged.");
|
player.sendMessage("§a[Camping] §7You rest until dawn. §8Spawn point unchanged.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const HAMMOCK_ANCHOR_PROP = "camping_hammock_anchor";
|
||||||
|
|
||||||
function toggleHammock(player, loc) {
|
function toggleHammock(player, loc) {
|
||||||
if (player.hasTag(HAMMOCK_TAG)) {
|
if (player.hasTag(HAMMOCK_TAG)) {
|
||||||
player.removeTag(HAMMOCK_TAG);
|
exitHammock(player);
|
||||||
player.sendMessage("§7[Camping] You climb out of the hammock.");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
player.addTag(HAMMOCK_TAG);
|
player.addTag(HAMMOCK_TAG);
|
||||||
|
const anchor = { x: loc.x + 0.5, y: loc.y + 0.1, z: loc.z + 0.5 };
|
||||||
try {
|
try {
|
||||||
player.teleport(
|
player.setDynamicProperty(HAMMOCK_ANCHOR_PROP, JSON.stringify(anchor));
|
||||||
{ x: loc.x + 0.5, y: loc.y + 0.4, z: loc.z + 0.5 },
|
} catch (_) {}
|
||||||
{ dimension: player.dimension }
|
try {
|
||||||
);
|
player.teleport(anchor, { dimension: player.dimension });
|
||||||
|
} catch (_) {}
|
||||||
|
// Slowness 255 + weakness + mining_fatigue make the player effectively immobile while
|
||||||
|
// still conscious; saturation + regen are the "rest" payoff.
|
||||||
|
try {
|
||||||
|
player.addEffect("slowness", 100000, { amplifier: 255, showParticles: false });
|
||||||
|
player.addEffect("weakness", 100000, { amplifier: 255, showParticles: false });
|
||||||
|
player.addEffect("mining_fatigue", 100000, { amplifier: 255, showParticles: false });
|
||||||
|
player.addEffect("saturation", 40, { amplifier: 0, showParticles: false });
|
||||||
|
player.addEffect("regeneration", 200, { amplifier: 1, showParticles: false });
|
||||||
} catch (_) {}
|
} catch (_) {}
|
||||||
player.sendMessage("§a[Camping] §7You settle into the hammock. Wild creatures don't notice you. §8(Sneak to climb out.)");
|
player.sendMessage("§a[Camping] §7You settle into the hammock. Wild creatures don't notice you. §8(Sneak to climb out.)");
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─── Hammock upkeep loop: mob repulsion + sneak-exit ────────
|
function exitHammock(player) {
|
||||||
|
player.removeTag(HAMMOCK_TAG);
|
||||||
|
try {
|
||||||
|
player.removeEffect("slowness");
|
||||||
|
player.removeEffect("weakness");
|
||||||
|
player.removeEffect("mining_fatigue");
|
||||||
|
} catch (_) {}
|
||||||
|
// Nudge player one block off the hammock so the next tick doesn't re-teleport them
|
||||||
|
// back into the cradle.
|
||||||
|
try {
|
||||||
|
const raw = player.getDynamicProperty(HAMMOCK_ANCHOR_PROP);
|
||||||
|
if (raw && typeof raw === "string") {
|
||||||
|
const a = JSON.parse(raw);
|
||||||
|
const yaw = player.getRotation().y;
|
||||||
|
const rad = (yaw * Math.PI) / 180;
|
||||||
|
const dx = -Math.sin(rad);
|
||||||
|
const dz = Math.cos(rad);
|
||||||
|
player.teleport(
|
||||||
|
{ x: a.x + dx * 1.2, y: a.y + 0.3, z: a.z + dz * 1.2 },
|
||||||
|
{ dimension: player.dimension }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch (_) {}
|
||||||
|
try { player.setDynamicProperty(HAMMOCK_ANCHOR_PROP, undefined); } catch (_) {}
|
||||||
|
player.sendMessage("§7[Camping] You climb out of the hammock.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─── Hammock upkeep loop: position lock + mob repulsion + sneak-exit ────────
|
||||||
system.runInterval(() => {
|
system.runInterval(() => {
|
||||||
for (const player of world.getAllPlayers()) {
|
for (const player of world.getAllPlayers()) {
|
||||||
if (!player.hasTag(HAMMOCK_TAG)) continue;
|
if (!player.hasTag(HAMMOCK_TAG)) continue;
|
||||||
if (player.isSneaking) {
|
if (player.isSneaking) {
|
||||||
player.removeTag(HAMMOCK_TAG);
|
exitHammock(player);
|
||||||
player.sendMessage("§7[Camping] You climb out of the hammock.");
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
// Pin the player to the hammock anchor so they can't drift off even with slowness
|
||||||
|
try {
|
||||||
|
const raw = player.getDynamicProperty(HAMMOCK_ANCHOR_PROP);
|
||||||
|
if (raw && typeof raw === "string") {
|
||||||
|
const a = JSON.parse(raw);
|
||||||
|
const dx = player.location.x - a.x;
|
||||||
|
const dy = player.location.y - a.y;
|
||||||
|
const dz = player.location.z - a.z;
|
||||||
|
if (dx * dx + dy * dy + dz * dz > 0.25) {
|
||||||
|
player.teleport(a, { dimension: player.dimension });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (_) {}
|
||||||
let hostiles = [];
|
let hostiles = [];
|
||||||
try {
|
try {
|
||||||
hostiles = player.dimension.getEntities({
|
hostiles = player.dimension.getEntities({
|
||||||
|
|||||||
Reference in New Issue
Block a user