This commit is contained in:
33333-33333 2026-07-18 13:06:02 +09:00
commit f657b6a4a4
94 changed files with 3970 additions and 1241 deletions

View file

@ -4,11 +4,12 @@
const World = global.World;
if (!World) throw new Error("World is not available for mixin: world_view.js");
const BASE_ZOOM_MIN = 0.42;
const BASE_ZOOM_MAX = 2.45;
const BASE_ZOOM_MAX = 4.5;
function terrainSignature(worldRef) {
const counts = worldRef.itemCounts || {};
return `${worldRef.fieldType || "garden"}:${worldRef.groundType || "soil"}:${counts.grass || 0}:${counts.trace || 0}:${counts.splat || 0}:${counts.zunchi || 0}:${worldRef.weather || "sunny"}`;
// Terrain item additions/removals already invalidate only their affected chunks.
// Keep the global signature limited to changes that truly require every chunk.
return `${worldRef.fieldType || "garden"}:${worldRef.groundType || "soil"}`;
}
function maxCameraX(worldRef) {
@ -62,10 +63,14 @@
markSpatialDirty(reason = "manual") {
this.spatialDirty = true;
this.spatialDirtyReason = reason;
if (!this.spatialDirtyReasonCountsThisFrame) this.spatialDirtyReasonCountsThisFrame = {};
this.spatialDirtyReasonCountsThisFrame[String(reason || "manual")] = (this.spatialDirtyReasonCountsThisFrame[String(reason || "manual")] || 0) + 1;
this.spatialDirtyMarksThisFrame = (this.spatialDirtyMarksThisFrame || 0) + 1;
this.spatialDirtyMarksTotal = (this.spatialDirtyMarksTotal || 0) + 1;
if (this.spatialDirtyReasonCountsThisFrame) {
const key = String(reason || "manual");
this.spatialDirtyReasonCountsThisFrame[key] = (this.spatialDirtyReasonCountsThisFrame[key] || 0) + 1;
}
if (this.spatialDirtyReasonCountsThisFrame) {
this.spatialDirtyMarksThisFrame = (this.spatialDirtyMarksThisFrame || 0) + 1;
this.spatialDirtyMarksTotal = (this.spatialDirtyMarksTotal || 0) + 1;
}
this.lastSpatialDirtyReason = reason;
const r = String(reason || "manual");
if (/tarinai-moved|post-tarinai|creature/i.test(r)) {
@ -74,22 +79,28 @@
this.spatialAntDirty = true;
} else if (/items?-moved|ball-ball|mobile|kinematic|pushpin|oshibyo|firecracker|genkotsu|zunchi|mechanical|rotator|reciprocator|poison-block|constraint|rod-/i.test(r)) {
this.spatialDynamicItemsDirty = true;
// Ordinary moving items are not routing obstacles. Only explicit fence,
// gate, or nest geometry changes invalidate obstacle-route caches.
if (/fence|gate|nest-box|pipe/i.test(r)) this.routingObstacleVersion = (this.routingObstacleVersion || 0) + 1;
} else {
this.spatialStaticItemsDirty = true;
this.spatialDynamicItemsDirty = true;
this.spatialTarinaiDirty = true;
this.spatialAntDirty = true;
this.routingObstacleVersion = (this.routingObstacleVersion || 0) + 1;
}
},
markTerrainDirty(reason = "manual") {
const reasonKey = String(reason || "manual");
if (!this.terrainDirtyStatsThisFrame) this.terrainDirtyStatsThisFrame = { raw: 0, global: 0, chunk: 0, coalesced: 0, reasons: {} };
this.terrainDirtyStatsThisFrame.raw += 1;
this.terrainDirtyStatsThisFrame.global += 1;
this.terrainDirtyStatsThisFrame.reasons[reasonKey] = (this.terrainDirtyStatsThisFrame.reasons[reasonKey] || 0) + 1;
const terrainStats = this.terrainDirtyStatsThisFrame;
if (terrainStats) {
terrainStats.raw += 1;
terrainStats.global += 1;
terrainStats.reasons[reasonKey] = (terrainStats.reasons[reasonKey] || 0) + 1;
}
if (this.terrainDirtyGlobal && this.terrainDirtyReason === reasonKey) {
this.terrainDirtyStatsThisFrame.coalesced += 1;
terrainStats && (terrainStats.coalesced += 1);
this.terrainDirty = true;
this.terrainLastDirtyAt = this.time || 0;
return;
@ -106,10 +117,12 @@
const cx = Math.floor((Number(x) || 0) / 256);
const cy = Math.floor((Number(y) || 0) / 256);
const cr = Math.max(0, Math.ceil((Number(radius) || 0) / 256));
if (!this.terrainDirtyStatsThisFrame) this.terrainDirtyStatsThisFrame = { raw: 0, global: 0, chunk: 0, coalesced: 0, reasons: {} };
this.terrainDirtyStatsThisFrame.raw += 1;
this.terrainDirtyStatsThisFrame.chunk += 1;
this.terrainDirtyStatsThisFrame.reasons[reasonKey] = (this.terrainDirtyStatsThisFrame.reasons[reasonKey] || 0) + 1;
const terrainStats = this.terrainDirtyStatsThisFrame;
if (terrainStats) {
terrainStats.raw += 1;
terrainStats.chunk += 1;
terrainStats.reasons[reasonKey] = (terrainStats.reasons[reasonKey] || 0) + 1;
}
if (!this.terrainDirtyChunks) this.terrainDirtyChunks = new Set();
let added = 0;
for (let yy = cy - cr; yy <= cy + cr; yy++) {
@ -123,7 +136,7 @@
this.terrainDirtyReason = reasonKey;
this.terrainLastDirtyAt = this.time || 0;
if (added <= 0) {
this.terrainDirtyStatsThisFrame.coalesced += 1;
terrainStats && (terrainStats.coalesced += 1);
return true;
}
this.terrainVersion = (this.terrainVersion || 0) + 1;
@ -136,10 +149,7 @@
if (signature !== this.lastTerrainSignature) {
this.lastTerrainSignature = signature;
this.markTerrainDirty("terrain-signature");
return;
}
const interval = 3.0;
if ((this.time || 0) - (this.terrainLastDirtyAt || 0) >= interval) this.markTerrainDirty("terrain-periodic");
},
phaseName() {