tarinai/js/item_runtime.js
2026-06-26 12:46:32 +09:00

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);