80 lines
2.8 KiB
JavaScript
80 lines
2.8 KiB
JavaScript
"use strict";
|
|
|
|
// Layer: entity-runtime/items
|
|
// Owns the public item update boundary. Item.prototype.update remains available
|
|
// for legacy callers, but it now routes through TarinaiItemRuntime so callers do
|
|
// not need to know where the lifecycle implementation lives.
|
|
(function (global) {
|
|
let lifecycleUpdate = null;
|
|
|
|
function installPrototypeBoundary() {
|
|
const proto = global.Item?.prototype;
|
|
if (!proto || proto._tarinaiItemRuntimeInstalled) return false;
|
|
lifecycleUpdate = proto.update || lifecycleUpdate;
|
|
if (typeof lifecycleUpdate === "function" && !proto._tarinaiLifecycleUpdate) {
|
|
Object.defineProperty(proto, "_tarinaiLifecycleUpdate", {
|
|
value: lifecycleUpdate,
|
|
configurable: true,
|
|
writable: true,
|
|
});
|
|
}
|
|
proto.update = function update(dt, worldRef = global.world) {
|
|
return global.TarinaiItemRuntime.updateOne(this, dt, worldRef);
|
|
};
|
|
Object.defineProperty(proto, "_tarinaiItemRuntimeInstalled", {
|
|
value: true,
|
|
configurable: true,
|
|
writable: true,
|
|
});
|
|
return true;
|
|
}
|
|
|
|
function lifecycleFor(item) {
|
|
return item?._tarinaiLifecycleUpdate || lifecycleUpdate;
|
|
}
|
|
|
|
function updateOne(item, dt, worldRef = global.world) {
|
|
const fn = lifecycleFor(item);
|
|
if (!item || item.dead || typeof fn !== "function") return false;
|
|
if (global.TarinaiItemLifecyclePipeline?.updateOne) {
|
|
return global.TarinaiItemLifecyclePipeline.updateOne(item, dt, worldRef, { legacyUpdate: fn }) !== false;
|
|
}
|
|
fn.call(item, dt, worldRef);
|
|
return true;
|
|
}
|
|
|
|
function updateScheduled(worldRef, dt) {
|
|
if (global.TarinaiItemUpdateScheduler?.run) return global.TarinaiItemUpdateScheduler.run(worldRef, dt);
|
|
const helpers = global.TarinaiSimulationRuntime?.helpers;
|
|
if (!helpers?.forScheduledItems || !helpers?.itemUpdateInterval) return 0;
|
|
let ran = 0;
|
|
helpers.forScheduledItems(worldRef, (item) => {
|
|
const interval = helpers.itemUpdateInterval(item);
|
|
if (!Number.isFinite(interval)) return;
|
|
if (interval <= 0) {
|
|
if (updateOne(item, dt, worldRef)) ran += 1;
|
|
return;
|
|
}
|
|
item._scheduledUpdateDt = Math.min(10, (item._scheduledUpdateDt || 0) + dt);
|
|
if (item._scheduledUpdateDt < interval) return;
|
|
const scheduledDt = item._scheduledUpdateDt;
|
|
item._scheduledUpdateDt = 0;
|
|
if (updateOne(item, scheduledDt, worldRef)) ran += 1;
|
|
});
|
|
return ran;
|
|
}
|
|
|
|
function trackedDynamicItems(worldRef) {
|
|
return global.TarinaiItemUpdateScheduler?.trackedDynamicItems?.(worldRef) || worldRef?._itemUpdateRealtime || [];
|
|
}
|
|
|
|
const api = Object.freeze({
|
|
installPrototypeBoundary,
|
|
updateOne,
|
|
updateScheduled,
|
|
trackedDynamicItems,
|
|
});
|
|
|
|
global.TarinaiItemRuntime = api;
|
|
installPrototypeBoundary();
|
|
})(typeof window !== "undefined" ? window : globalThis);
|