aaa
This commit is contained in:
parent
f1c3af2b89
commit
2636d580a8
75 changed files with 3890 additions and 1084 deletions
|
|
@ -52,6 +52,7 @@
|
|||
(worldRef.items || []).length,
|
||||
worldRef.itemBucketRebuildsTotal || 0,
|
||||
worldRef.itemBucketsDirty ? 1 : 0,
|
||||
global.TarinaiPerf?.simulationOptimizationTier?.() || "balanced",
|
||||
].join(":");
|
||||
}
|
||||
|
||||
|
|
@ -88,8 +89,9 @@
|
|||
reason,
|
||||
};
|
||||
for (const item of candidateItems(worldRef)) {
|
||||
item._schedulerLastAt = Number.isFinite(item._schedulerLastAt) ? item._schedulerLastAt : now;
|
||||
scheduleItem(state, item, now, itemUpdateInterval(item));
|
||||
const interval = itemUpdateInterval(item);
|
||||
if (interval > 0 && !Number.isFinite(item._schedulerLastAt)) item._schedulerLastAt = now;
|
||||
scheduleItem(state, item, now, interval);
|
||||
}
|
||||
worldRef._itemUpdateScheduler = state;
|
||||
worldRef._itemUpdateRealtime = state.realtime;
|
||||
|
|
@ -102,6 +104,10 @@
|
|||
return worldRef._itemUpdateScheduler;
|
||||
}
|
||||
|
||||
function scheduledBudgetFor() {
|
||||
return Math.max(1, Number(global.TarinaiPerf?.performanceProfile?.().scheduledItemBudget || 30));
|
||||
}
|
||||
|
||||
function runRealtime(worldRef, state, dt) {
|
||||
let ran = 0;
|
||||
const now = worldRef.time || 0;
|
||||
|
|
@ -128,10 +134,10 @@
|
|||
return ran;
|
||||
}
|
||||
|
||||
function runDue(worldRef, state) {
|
||||
function runDue(worldRef, state, budget = scheduledBudgetFor(worldRef, state)) {
|
||||
let ran = 0;
|
||||
const now = worldRef.time || 0;
|
||||
const maxDue = Math.max(24, Math.ceil((state.heap.length || 0) * 0.08));
|
||||
const maxDue = Math.max(1, Number(budget || 0) || 1);
|
||||
let dueRuns = 0;
|
||||
while (state.heap.length && state.heap[0].time <= now + 0.0001 && dueRuns < maxDue) {
|
||||
const entry = heapPop(state.heap);
|
||||
|
|
@ -150,16 +156,37 @@
|
|||
dueRuns += 1;
|
||||
scheduleItem(state, item, now, itemUpdateInterval(item));
|
||||
}
|
||||
state.lastBudgetDue = maxDue;
|
||||
state.lastDueSkipped = (state.heap.length && state.heap[0].time <= now + 0.0001) ? 1 : 0;
|
||||
return ran;
|
||||
}
|
||||
|
||||
function physicsBudgetFor(worldRef) {
|
||||
const itemCount = (worldRef?.items || []).length || 0;
|
||||
const mobile = Boolean(global.TarinaiInputMode.snapshot().touchFirst || (global.innerWidth || 9999) <= 760);
|
||||
if (mobile) return { maxPairs: 150, maxLinks: 96, postMaxPairs: 40, maxSubsteps: 2 };
|
||||
return itemCount > 80
|
||||
? { maxPairs: 240, maxLinks: 170, postMaxPairs: 78, maxSubsteps: 4 }
|
||||
: { maxPairs: 300, maxLinks: 210, postMaxPairs: 100, maxSubsteps: 5 };
|
||||
function physicsBudgetFor() {
|
||||
return { ...(global.TarinaiPerf?.performanceProfile?.().physicsBudget || {}) };
|
||||
}
|
||||
|
||||
function poisonContactBudgetFor(worldRef) {
|
||||
const possibleTargets =
|
||||
(worldRef?.itemCounts?.grass_bed || 0) +
|
||||
(worldRef?.itemCounts?.zunchi || 0) +
|
||||
(worldRef?.itemCounts?.water || 0) +
|
||||
(worldRef?.itemCounts?.grass || 0);
|
||||
if ((worldRef?.itemCounts?.poison_block || 0) <= 0 || possibleTargets <= 0) return { maxPoison: 0, maxTargets: 0, skip: true };
|
||||
return { ...(global.TarinaiPerf?.performanceProfile?.().poisonContactBudget || { maxPoison: 12, maxTargets: 42, skip: false }) };
|
||||
}
|
||||
|
||||
function wakeItem(worldRef, item, holdSeconds = 0.22) {
|
||||
if (!worldRef || !item || item.dead) return false;
|
||||
const state = ensure(worldRef);
|
||||
const now = worldRef.time || 0;
|
||||
item._activeUntil = Math.max(Number(item._activeUntil || -Infinity) || -Infinity, now + Math.max(0.05, Number(holdSeconds || 0.22) || 0.22));
|
||||
// Invalidate a pending heap entry and promote the item immediately. This is
|
||||
// used by continuous external forces such as fan wind.
|
||||
item._schedulerToken = (item._schedulerToken || 0) + 1;
|
||||
item._schedulerLastAt = now;
|
||||
if (!state.realtime.includes(item)) state.realtime.push(item);
|
||||
worldRef._itemUpdateRealtime = state.realtime;
|
||||
return true;
|
||||
}
|
||||
|
||||
function run(worldRef, dt) {
|
||||
|
|
@ -171,16 +198,19 @@
|
|||
let ran = realtimeRan;
|
||||
if (realtimeEnd) realtimeEnd();
|
||||
const dueEnd = global.TarinaiPerf.begin("update.items.scheduled");
|
||||
const dueRan = runDue(worldRef, state);
|
||||
const budgetDue = scheduledBudgetFor(worldRef, state);
|
||||
const dueRan = runDue(worldRef, state, budgetDue);
|
||||
ran += dueRan;
|
||||
if (dueEnd) dueEnd();
|
||||
global.TarinaiSignalSystem?.updateWorld?.(worldRef, dt);
|
||||
const physicsEnd = global.TarinaiPerf.begin("update.physicsWorld");
|
||||
const physicsBudget = physicsBudgetFor(worldRef);
|
||||
const physicsWorld = global.TarinaiPhysicsWorldSystem.updateWorld(worldRef, dt, physicsBudget);
|
||||
const mechanicalWorld = physicsWorld.mechanical || null;
|
||||
const constraintWorld = physicsWorld.constraintRan || 0;
|
||||
const postConstraintPairs = physicsWorld.postConstraintPairs || 0;
|
||||
const poisonContactRemoved = worldRef.resolvePoisonBlockItemContacts?.({ maxPoison: 24, maxTargets: 80 }) || 0;
|
||||
const poisonContactBudget = poisonContactBudgetFor(worldRef);
|
||||
const poisonContactRemoved = poisonContactBudget.skip ? 0 : (worldRef.resolvePoisonBlockItemContacts?.(poisonContactBudget) || 0);
|
||||
if (physicsEnd) physicsEnd();
|
||||
state.signature = schedulerSignature(worldRef);
|
||||
worldRef._itemUpdateSchedulerStats = {
|
||||
|
|
@ -191,16 +221,20 @@
|
|||
lastRan: ran,
|
||||
realtimeRan,
|
||||
dueRan,
|
||||
budgetDue,
|
||||
dueSkipped: state.lastDueSkipped || 0,
|
||||
sleeping: state.heap.length,
|
||||
activeRealtime: state.realtime.length,
|
||||
physicsBudget,
|
||||
poisonContactBudget,
|
||||
poisonContactRemoved,
|
||||
physics: physicsWorld || mechanicalWorld,
|
||||
constraints: constraintWorld,
|
||||
postConstraintPairs,
|
||||
mechanicalStats: worldRef._mechanicalWorldStats || null,
|
||||
constraintStats: worldRef._constraintWorldStats || null,
|
||||
};
|
||||
return ran + (physicsWorld.ran || mechanicalWorld?.ran || 0) + constraintWorld + poisonContactRemoved;
|
||||
return ran + (physicsWorld.ran || mechanicalWorld?.ran || 0) + poisonContactRemoved;
|
||||
} finally {
|
||||
if (end) end();
|
||||
}
|
||||
|
|
@ -210,5 +244,5 @@
|
|||
return worldRef?._itemUpdateRealtime || [];
|
||||
}
|
||||
|
||||
global.TarinaiItemUpdateScheduler = Object.freeze({ run, trackedDynamicItems });
|
||||
global.TarinaiItemUpdateScheduler = Object.freeze({ run, trackedDynamicItems, wakeItem });
|
||||
})(typeof window !== "undefined" ? window : globalThis);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue