duu
This commit is contained in:
parent
88f618cadf
commit
8f9f5b5100
108 changed files with 2139 additions and 1500 deletions
|
|
@ -47,34 +47,35 @@
|
|||
},
|
||||
|
||||
resolveOwnedBedSleepConflicts() {
|
||||
const alive = (this.tarinai || []).filter(t => t && !t.dead);
|
||||
if (alive.length < 2) return 0;
|
||||
const liveCount = (this.tarinai || []).reduce((count, t) => count + (t && !t.dead ? 1 : 0), 0);
|
||||
if (liveCount < 2) return 0;
|
||||
const friendThreshold = typeof FRIEND_AFFINITY_THRESHOLD === "number" ? FRIEND_AFFINITY_THRESHOLD : 14;
|
||||
const isFriendPair = (a, b) => {
|
||||
const relAB = a?.relationTo ? a.relationTo(b?.id) : null;
|
||||
const relBA = b?.relationTo ? b.relationTo(a?.id) : null;
|
||||
return Boolean((relAB && (relAB.affinity || 0) >= friendThreshold) || (relBA && (relBA.affinity || 0) >= friendThreshold));
|
||||
};
|
||||
const bedSleepers = new Map();
|
||||
for (const sleeper of alive) {
|
||||
if (!(sleeper.sleeping || sleeper.state === "sleep")) continue;
|
||||
const bed = sleeper.target;
|
||||
if (!bed || bed.dead || bed.type !== "grass_bed") continue;
|
||||
if (distXY(sleeper.x, sleeper.y, bed.x, bed.y) > Math.max((bed.r || 18) * 1.55, 32)) continue;
|
||||
if (!bedSleepers.has(bed.id)) bedSleepers.set(bed.id, []);
|
||||
bedSleepers.get(bed.id).push(sleeper);
|
||||
}
|
||||
const beds = typeof this.itemsOfType === "function" ? this.itemsOfType("grass_bed") : (this.items || []).filter(it => it && !it.dead && it.type === "grass_bed");
|
||||
let conflicts = 0;
|
||||
for (const intruder of alive) {
|
||||
if (!(intruder.state === "seek_bed" || intruder.state === "sleep")) continue;
|
||||
const bed = intruder.target;
|
||||
for (const bed of beds || []) {
|
||||
if (!bed || bed.dead || bed.type !== "grass_bed") continue;
|
||||
const sleepers = bedSleepers.get(bed.id) || [];
|
||||
if (!sleepers.length) continue;
|
||||
if (distXY(intruder.x, intruder.y, bed.x, bed.y) > Math.max((bed.r || 18) * 2.2, 54)) continue;
|
||||
const defender = sleepers.find(other => other && other !== intruder && !this.areParentChild?.(intruder, other) && !isFriendPair(intruder, other));
|
||||
if (!defender) continue;
|
||||
if (this.startForcedFight?.(defender, intruder)) conflicts += 1;
|
||||
const sleepReach = Math.max((bed.r || 18) * 1.55, 32);
|
||||
const intrudeReach = Math.max((bed.r || 18) * 2.2, 54);
|
||||
const candidates = typeof this.nearbyTarinai === "function" ? this.nearbyTarinai(bed.x, bed.y, intrudeReach + 16, true) : (this.tarinai || []);
|
||||
const sleepers = [];
|
||||
const intruders = [];
|
||||
for (const t of candidates || []) {
|
||||
if (!t || t.dead || t.target !== bed) continue;
|
||||
const d = distXY(t.x, t.y, bed.x, bed.y);
|
||||
if ((t.sleeping || t.state === "sleep") && d <= sleepReach) sleepers.push(t);
|
||||
if ((t.state === "seek_bed" || t.state === "sleep") && d <= intrudeReach) intruders.push(t);
|
||||
}
|
||||
if (!sleepers.length || !intruders.length) continue;
|
||||
for (const intruder of intruders) {
|
||||
const defender = sleepers.find(other => other && other !== intruder && !this.areParentChild?.(intruder, other) && !isFriendPair(intruder, other));
|
||||
if (!defender) continue;
|
||||
if (this.startForcedFight?.(defender, intruder)) conflicts += 1;
|
||||
}
|
||||
}
|
||||
return conflicts;
|
||||
},
|
||||
|
|
@ -114,11 +115,13 @@
|
|||
|
||||
sanitizeOutOfBounds() {
|
||||
const pad = Math.max(28, CONFIG.worldPadding || 30);
|
||||
const safeW = Math.max(pad * 2 + 1, Number(this.w || 1000) || 1000);
|
||||
const safeH = Math.max(pad * 2 + 1, Number(this.h || 720) || 720);
|
||||
let changedItems = false;
|
||||
let changedTarinai = false;
|
||||
let changedAnts = false;
|
||||
const repairPoint = (obj, radius = 12) => {
|
||||
if (!obj) return "missing";
|
||||
const safeW = Math.max(pad * 2 + 1, Number(this.w || 1000) || 1000);
|
||||
const safeH = Math.max(pad * 2 + 1, Number(this.h || 720) || 720);
|
||||
if (!Number.isFinite(obj.x)) obj.x = safeW * 0.5;
|
||||
if (!Number.isFinite(obj.y)) obj.y = safeH * 0.5;
|
||||
const minX = pad - radius;
|
||||
|
|
@ -132,15 +135,34 @@
|
|||
if (Number.isFinite(obj.vy)) obj.vy *= -0.18;
|
||||
return "moved";
|
||||
};
|
||||
for (const it of this.items || []) {
|
||||
const result = repairPoint(it, it.r || 12);
|
||||
const forEachMaintenanceSlice = (list, cursorKey, fullLimit, fn) => {
|
||||
const arr = Array.isArray(list) ? list : [];
|
||||
const len = arr.length;
|
||||
if (!len) {
|
||||
this[cursorKey] = 0;
|
||||
return;
|
||||
}
|
||||
const limit = Math.max(1, Number(fullLimit || len) || len);
|
||||
if (len <= limit) {
|
||||
for (let i = 0; i < len; i++) fn(arr[i], i);
|
||||
this[cursorKey] = 0;
|
||||
return;
|
||||
}
|
||||
let cursor = Math.max(0, Math.floor(Number(this[cursorKey] || 0) || 0)) % len;
|
||||
for (let n = 0; n < limit; n++) {
|
||||
const idx = (cursor + n) % len;
|
||||
fn(arr[idx], idx);
|
||||
}
|
||||
this[cursorKey] = (cursor + limit) % len;
|
||||
};
|
||||
|
||||
forEachMaintenanceSlice(this.items, "_sanitizeItemsCursor", 900, (it) => {
|
||||
const result = repairPoint(it, it?.r || 12);
|
||||
if (result === "moved") changedItems = true;
|
||||
}
|
||||
for (const ef of this.effects || []) {
|
||||
repairPoint(ef, ef.size || 12);
|
||||
}
|
||||
const safeW = Math.max(pad * 2 + 1, Number(this.w || 1000) || 1000);
|
||||
const safeH = Math.max(pad * 2 + 1, Number(this.h || 720) || 720);
|
||||
});
|
||||
forEachMaintenanceSlice(this.effects, "_sanitizeEffectsCursor", 900, (ef) => {
|
||||
repairPoint(ef, ef?.size || 12);
|
||||
});
|
||||
const repairTarinai = (t) => {
|
||||
t.x = clamp(Number.isFinite(t.x) ? t.x : safeW * 0.5, pad, safeW - pad);
|
||||
t.y = clamp(Number.isFinite(t.y) ? t.y : safeH * 0.5, pad, safeH - pad);
|
||||
|
|
@ -148,8 +170,8 @@
|
|||
t.vy = 0;
|
||||
t.entryTimer = 0;
|
||||
};
|
||||
for (const t of this.tarinai || []) {
|
||||
if (!t || t.dead) continue;
|
||||
forEachMaintenanceSlice(this.tarinai, "_sanitizeTarinaiCursor", 360, (t) => {
|
||||
if (!t || t.dead) return;
|
||||
if (t.state === "sunbath" || (t.sunbathTimer || 0) > 0.04) {
|
||||
if (!Number.isFinite(t.x)) t.x = Number.isFinite(t.sunbathAnchorX) ? t.sunbathAnchorX : pad;
|
||||
if (!Number.isFinite(t.y)) t.y = Number.isFinite(t.sunbathAnchorY) ? t.sunbathAnchorY : pad;
|
||||
|
|
@ -157,7 +179,10 @@
|
|||
t.sunbathAnchorY = clamp(t.y, pad, safeH - pad);
|
||||
}
|
||||
const result = repairPoint(t, t.radius || 22);
|
||||
if (result === "missing" || result === "moved") repairTarinai(t);
|
||||
if (result === "missing" || result === "moved") {
|
||||
repairTarinai(t);
|
||||
changedTarinai = true;
|
||||
}
|
||||
if (t.state === "sunbath" || (t.sunbathTimer || 0) > 0.04) {
|
||||
t.sunbathAnchorX = clamp(Number.isFinite(t.x) ? t.x : (Number.isFinite(t.sunbathAnchorX) ? t.sunbathAnchorX : pad), pad, safeW - pad);
|
||||
t.sunbathAnchorY = clamp(Number.isFinite(t.y) ? t.y : (Number.isFinite(t.sunbathAnchorY) ? t.sunbathAnchorY : pad), pad, safeH - pad);
|
||||
|
|
@ -168,12 +193,11 @@
|
|||
t._lastValidX = t.x;
|
||||
t._lastValidY = t.y;
|
||||
}
|
||||
}
|
||||
let changedAnts = false;
|
||||
for (const ant of this.ants || []) {
|
||||
if (!ant || ant.dead) continue;
|
||||
});
|
||||
forEachMaintenanceSlice(this.ants, "_sanitizeAntsCursor", 900, (ant) => {
|
||||
if (!ant || ant.dead) return;
|
||||
const result = repairPoint(ant, ant.kind === "queen" ? 18 : 10);
|
||||
if (result === "missing") continue;
|
||||
if (result === "missing") return;
|
||||
if (result === "moved") {
|
||||
ant.vx = 0;
|
||||
ant.vy = 0;
|
||||
|
|
@ -185,13 +209,15 @@
|
|||
}
|
||||
changedAnts = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
if (changedAnts) this.compactAnts?.();
|
||||
if (changedItems) {
|
||||
this.compactItems();
|
||||
this.updateItemCounts();
|
||||
this.markSpatialDirty?.("sanitize-out-of-bounds");
|
||||
this.ensureSpatial?.("sanitize-out-of-bounds");
|
||||
} else if (changedTarinai || changedAnts) {
|
||||
this.markSpatialDirty?.("sanitize-out-of-bounds-mobile");
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue