lag r
This commit is contained in:
parent
d875df8600
commit
2741b93dea
31 changed files with 751 additions and 546 deletions
|
|
@ -12,25 +12,17 @@
|
|||
|
||||
Object.defineProperties(World.prototype, Object.getOwnPropertyDescriptors({
|
||||
performanceLevel() {
|
||||
if (window.TarinaiPerformance) return window.TarinaiPerformance.quality?.(this)?.level || window.TarinaiPerformance.level || 0;
|
||||
const fps = typeof window !== "undefined" ? Number(window.__tarinaiFps || 0) : 60;
|
||||
if (!fps || !Number.isFinite(fps)) return 0;
|
||||
if (fps < 22) return 3;
|
||||
if (fps < 34) return 2;
|
||||
if (fps < 48) return 1;
|
||||
return 0;
|
||||
},
|
||||
|
||||
performanceQuality() {
|
||||
return window.TarinaiPerformance?.quality?.(this) || { level: this.performanceLevel(), antStride: 1, effectLimit: CONFIG.effectLimit ?? 96 };
|
||||
return { level: 0, pressure: 0, effectDensity: 1, antStride: 2, effectLimit: CONFIG.effectLimit ?? 96, itemScanLimit: 16, socialScanLimit: 8, collisionInterval: 1.8, bedConflictInterval: 3.2, statsInterval: 1.2, maxDpr: 2 };
|
||||
},
|
||||
|
||||
beginFramePerformanceBudgets(quality = this.performanceQuality?.()) {
|
||||
const pressure = clamp(Number(quality?.pressure || 0) || 0, 0, 1);
|
||||
const density = clamp(Number(quality?.effectDensity || (1 - pressure)) || 0, 0.12, 1);
|
||||
beginFramePerformanceBudgets() {
|
||||
this.workBudget = {
|
||||
ai: Math.max(4, Math.round(4 + density * 24)),
|
||||
env: Math.max(3, Math.round(3 + density * 15)),
|
||||
ai: Math.max(1, Math.ceil(((this.tarinai || []).length || 1) / 2)),
|
||||
env: Math.max(1, Math.ceil(((this.tarinai || []).length || 1) / 3)),
|
||||
aiUsed: 0,
|
||||
envUsed: 0,
|
||||
};
|
||||
|
|
@ -106,11 +98,11 @@
|
|||
},
|
||||
performance: {
|
||||
liveTarinai,
|
||||
fps: window.TarinaiPerformance?.fps || window.__tarinaiFps || 0,
|
||||
pressure: this.performanceQuality?.().pressure || 0,
|
||||
level: this.performanceLevel?.() || 0,
|
||||
fps: window.__tarinaiFps || window.TarinaiPerformance?.fps || 0,
|
||||
pressure: 0,
|
||||
level: 0,
|
||||
dpr: (typeof uiCache !== "undefined" ? uiCache?.canvasDpr : window.uiCache?.canvasDpr) || 0,
|
||||
quality: this.performanceQuality?.() || null,
|
||||
quality: null,
|
||||
},
|
||||
work: {
|
||||
budget: this.workBudget || null,
|
||||
|
|
@ -121,10 +113,9 @@
|
|||
|
||||
grassLoadLevel() {
|
||||
const grass = this.itemCounts?.grass || 0;
|
||||
const perf = this.performanceLevel();
|
||||
if (perf >= 3 || grass >= 180) return 3;
|
||||
if (perf >= 2 || grass >= 120) return 2;
|
||||
if (perf >= 1 || grass >= 72) return 1;
|
||||
if (grass >= 180) return 3;
|
||||
if (grass >= 120) return 2;
|
||||
if (grass >= 72) return 1;
|
||||
return 0;
|
||||
},
|
||||
|
||||
|
|
@ -132,6 +123,29 @@
|
|||
return [1.0, 1.35, 1.85, 2.45][this.grassLoadLevel()] || 1.0;
|
||||
},
|
||||
|
||||
grassLimit() {
|
||||
const limit = Number(CONFIG.grassLimit ?? 360);
|
||||
return Number.isFinite(limit) && limit >= 0 ? Math.floor(limit) : Infinity;
|
||||
},
|
||||
|
||||
isGrassLimitExempt(item) {
|
||||
return Boolean(item && item.type === "grass" && (item.grassLimitExempt || item.manualGrass || item.placedByPlayer));
|
||||
},
|
||||
|
||||
liveGrassCount() {
|
||||
let total = 0;
|
||||
for (const it of this.items || []) {
|
||||
if (it && !it.dead && it.type === "grass" && !this.isGrassLimitExempt?.(it)) total += 1;
|
||||
}
|
||||
return total;
|
||||
},
|
||||
|
||||
canAddGrass(extra = 1) {
|
||||
const limit = this.grassLimit ? this.grassLimit() : (CONFIG.grassLimit ?? 360);
|
||||
if (!Number.isFinite(limit)) return true;
|
||||
return (this.liveGrassCount ? this.liveGrassCount() : 0) + Math.max(0, Number(extra) || 0) <= limit;
|
||||
},
|
||||
|
||||
sortedDrawList() {
|
||||
if (!this.drawList) this.drawList = [];
|
||||
const antCount = liveCount(this.ants);
|
||||
|
|
@ -149,6 +163,10 @@
|
|||
ensureSpatial(reason = "read") {
|
||||
if (!this.spatial) return false;
|
||||
if (!this.spatialDirty && (this.spatialVersion || 0) > 0) return false;
|
||||
// Rebuild at most once per frame. Queries after movement may use the previous
|
||||
// frame's grid until the next update-start; this is acceptable for this game
|
||||
// and avoids repeated full-grid rebuilds under dense scenes.
|
||||
if ((this.spatialRebuildsThisFrame || 0) > 0 && (this.spatialVersion || 0) > 0) return false;
|
||||
return this.rebuildSpatial(true, reason);
|
||||
},
|
||||
|
||||
|
|
@ -213,6 +231,9 @@
|
|||
|
||||
addItem(item, reason = "add-item", opts = {}) {
|
||||
if (!item) return null;
|
||||
const ignoreGrassLimit = Boolean(opts.ignoreGrassLimit || opts.manualGrass || item.grassLimitExempt || item.manualGrass || item.placedByPlayer);
|
||||
if (item.type === "grass" && !ignoreGrassLimit && !this.canAddGrass?.(1)) return null;
|
||||
if (item.type === "grass" && ignoreGrassLimit) item.grassLimitExempt = true;
|
||||
this.items.push(item);
|
||||
this.markItemBucketsDirty?.(reason);
|
||||
this.markSpatialDirty?.(reason);
|
||||
|
|
@ -273,7 +294,6 @@
|
|||
},
|
||||
|
||||
compactItems() {
|
||||
this.enforceItemBudget();
|
||||
const before = this.items.length;
|
||||
let write = 0;
|
||||
for (let read = 0; read < this.items.length; read++) {
|
||||
|
|
@ -291,48 +311,8 @@
|
|||
return changed;
|
||||
},
|
||||
|
||||
enforceItemBudget() {
|
||||
const pruneOldest = (type, limit) => {
|
||||
if (!Number.isFinite(limit) || limit < 0) return;
|
||||
const live = this.liveItemsOfType?.(type) || (this.items || []).filter(it => it && it.type === type && !it.dead);
|
||||
const count = live.length;
|
||||
if (count <= limit) return;
|
||||
const victims = live
|
||||
.slice()
|
||||
.sort((a, b) => (b.age || 0) - (a.age || 0))
|
||||
.slice(0, count - limit);
|
||||
for (const it of victims) it.amount = 0;
|
||||
};
|
||||
pruneOldest("zunchi", CONFIG.zunchiLimit ?? 56);
|
||||
pruneOldest("trace", CONFIG.traceLimit ?? 64);
|
||||
pruneOldest("splat", CONFIG.splatLimit ?? 48);
|
||||
pruneOldest("grass", this.grassLimit ? this.grassLimit() : (CONFIG.grassLimit ?? 96));
|
||||
const fenceLimit = this.fenceLimit ? this.fenceLimit() : (CONFIG.fenceLimit ?? 72);
|
||||
const liveFences = this.liveFenceCount ? this.liveFenceCount() : 0;
|
||||
if (liveFences > fenceLimit) {
|
||||
const victims = (this.items || [])
|
||||
.filter(it => it && this.isFenceType?.(it.type) && !it.dead)
|
||||
.sort((a, b) => (b.age || 0) - (a.age || 0))
|
||||
.slice(0, liveFences - fenceLimit);
|
||||
for (const it of victims) it.amount = 0;
|
||||
}
|
||||
|
||||
const limit = CONFIG.itemLimit ?? Infinity;
|
||||
if (!Number.isFinite(limit) || this.items.length <= limit) return;
|
||||
const priority = { trace: 1, splat: 2, zunchi: 3, water: 4, grass: 5, sweet: 6, firecracker: 7, fence_v: 8, fence_h: 8 };
|
||||
const removable = (this.items || [])
|
||||
.filter(it => it && !it.dead && (priority[it.type] || 99) < 99)
|
||||
.sort((a, b) => (priority[a.type] || 99) - (priority[b.type] || 99) || (b.age || 0) - (a.age || 0));
|
||||
let extra = this.items.length - limit;
|
||||
for (const it of removable) {
|
||||
if (extra <= 0) break;
|
||||
it.amount = 0;
|
||||
extra -= 1;
|
||||
}
|
||||
},
|
||||
|
||||
compactEffects() {
|
||||
const limit = this.performanceQuality?.().effectLimit ?? CONFIG.effectLimit ?? 96;
|
||||
const limit = CONFIG.effectLimit ?? 96;
|
||||
if (Number.isFinite(limit) && this.effects.length > limit) {
|
||||
this.effects.sort((a, b) => (a.life / Math.max(a.maxLife || 1, 0.001)) - (b.life / Math.max(b.maxLife || 1, 0.001)));
|
||||
const remove = this.effects.length - limit;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue