diff --git a/module.json b/module.json index 36b9f35..67ca169 100644 --- a/module.json +++ b/module.json @@ -8,7 +8,7 @@ "email": "dev7355608@gmail.com" } ], - "version": "2.0.3", + "version": "2.0.4", "compatibility": { "minimum": "12", "verified": "13" @@ -43,8 +43,8 @@ ], "url": "https://github.com/dev7355608/limits", "manifest": "https://github.com/dev7355608/limits/releases/latest/download/module.json", - "download": "https://github.com/dev7355608/limits/releases/download/v2.0.3/module.zip", - "changelog": "https://github.com/dev7355608/limits/releases/tag/v2.0.3", + "download": "https://github.com/dev7355608/limits/releases/download/v2.0.4/module.zip", + "changelog": "https://github.com/dev7355608/limits/releases/tag/v2.0.4", "bugs": "https://github.com/dev7355608/limits/issues", "readme": "https://raw.githubusercontent.com/dev7355608/limits/main/README.md", "license": "https://raw.githubusercontent.com/dev7355608/limits/main/LICENSE" diff --git a/scripts/_index.mjs b/scripts/_index.mjs index d52fa99..09790cf 100644 --- a/scripts/_index.mjs +++ b/scripts/_index.mjs @@ -1,4 +1,5 @@ import LimitRangeRegionBehaviorConfig from "./apps/region-behavior.mjs"; +import { DetectionModeMixin } from "./canvas/perception/detection-mode.mjs"; import { PointDarknessSourceMixin, PointLightSourceMixin, PointSoundSourceMixin, PointVisionSourceMixin } from "./canvas/sources/_module.mjs"; import LimitRangeRegionBehaviorType from "./data/region-behavior.mjs"; @@ -11,79 +12,36 @@ Hooks.once("init", () => { Hooks.once("setup", () => { Hooks.once("canvasInit", () => { - CONFIG.Canvas.visionSourceClass = PointVisionSourceMixin(CONFIG.Canvas.visionSourceClass); - CONFIG.Canvas.lightSourceClass = PointLightSourceMixin(CONFIG.Canvas.lightSourceClass); - CONFIG.Canvas.darknessSourceClass = PointDarknessSourceMixin(CONFIG.Canvas.darknessSourceClass); - CONFIG.Canvas.soundSourceClass = PointSoundSourceMixin(CONFIG.Canvas.soundSourceClass); - - if (game.release.generation >= 13) { - if (game.modules.get("lib-wrapper")?.active) { - libWrapper.register( - "limits", - "foundry.canvas.perception.DetectionMode.prototype._testPoint", - function (wrapped, visionSource, mode, target, test) { - return wrapped(visionSource, mode, target, test) - && visionSource._testLimit(mode, test.point); - }, - libWrapper.WRAPPER, - { perf_mode: libWrapper.PERF_FAST }, - ); - } else { - const DetectionMode = foundry.canvas.perception.DetectionMode; - const testPoint = DetectionMode.prototype._testPoint; - - DetectionMode.prototype._testPoint = function (visionSource, mode, target, test) { - return testPoint.call(this, visionSource, mode, target, test) - && visionSource._testLimit(mode, test.point); - }; - } - } else { - const TEST_POINT = { x: 0.0, y: 0.0, elevation: 0.0 }; - - if (game.modules.get("lib-wrapper")?.active) { - libWrapper.register( - "limits", - "DetectionMode.prototype._testPoint", - function (wrapped, visionSource, mode, target, test) { - if (!wrapped(visionSource, mode, target, test)) { - return false; - } - - const { x, y } = test.point; - - TEST_POINT.x = x; - TEST_POINT.y = y; - TEST_POINT.elevation = test.elevation; - - return visionSource._testLimit(mode, TEST_POINT); - }, - libWrapper.WRAPPER, - { perf_mode: libWrapper.PERF_FAST }, - ); - } else { - const testPoint = DetectionMode.prototype._testPoint; - - DetectionMode.prototype._testPoint = function (visionSource, mode, target, test) { - if (!testPoint.call(this, visionSource, mode, target, test)) { - return false; - } - - const { x, y } = test.point; - - TEST_POINT.x = x; - TEST_POINT.y = y; - TEST_POINT.elevation = test.elevation; - - return visionSource._testLimit(mode, TEST_POINT); - }; - } - } + mixinDetectionModes(); + mixinPointSources(); }); }); -}); -Hooks.once("ready", () => { if (game.release.generation < 13) { - CONFIG.RegionBehavior.sheetClasses[TYPE]["core.RegionBehaviorConfig"].cls = LimitRangeRegionBehaviorConfig; + Hooks.once("ready", () => { + CONFIG.RegionBehavior.sheetClasses[TYPE]["core.RegionBehaviorConfig"].cls = LimitRangeRegionBehaviorConfig; + }); } }); + +function mixinDetectionModes() { + const cache = new Map(); + + for (const mode of Object.values(CONFIG.Canvas.detectionModes)) { + let prototype = cache.get(mode.constructor); + + if (!prototype) { + prototype = DetectionModeMixin(mode.constructor).prototype; + cache.set(mode.constructor, prototype); + } + + Object.setPrototypeOf(mode, prototype); + } +} + +function mixinPointSources() { + CONFIG.Canvas.visionSourceClass = PointVisionSourceMixin(CONFIG.Canvas.visionSourceClass); + CONFIG.Canvas.lightSourceClass = PointLightSourceMixin(CONFIG.Canvas.lightSourceClass); + CONFIG.Canvas.darknessSourceClass = PointDarknessSourceMixin(CONFIG.Canvas.darknessSourceClass); + CONFIG.Canvas.soundSourceClass = PointSoundSourceMixin(CONFIG.Canvas.soundSourceClass); +} diff --git a/scripts/canvas/_module.mjs b/scripts/canvas/_module.mjs index 2f6b687..b12b644 100644 --- a/scripts/canvas/_module.mjs +++ b/scripts/canvas/_module.mjs @@ -1,2 +1,3 @@ export * as geometry from "./geometry/_module.mjs"; +export * as perception from "./perception/_module.mjs"; export * as sources from "./sources/_module.mjs"; diff --git a/scripts/canvas/perception/_module.mjs b/scripts/canvas/perception/_module.mjs new file mode 100644 index 0000000..eac9de4 --- /dev/null +++ b/scripts/canvas/perception/_module.mjs @@ -0,0 +1 @@ +export { default as DetectionModeMixin } from "./detection-mode.mjs"; diff --git a/scripts/canvas/perception/detection-mode.mjs b/scripts/canvas/perception/detection-mode.mjs new file mode 100644 index 0000000..06d5025 --- /dev/null +++ b/scripts/canvas/perception/detection-mode.mjs @@ -0,0 +1,32 @@ +/** + * @param {typeof foundry.canvas.perception.DetectionMode} DetectionMode + * @returns {typeof foundry.canvas.perception.DetectionMode} + */ +export const DetectionModeMixin = (DetectionMode) => class extends DetectionMode { + /** @override */ + _testPoint(visionSource, mode, target, test) { + if (!super._testPoint(visionSource, mode, target, test)) { + return false; + } + + let point; + + if (game.release.generation >= 13) { + point = test.point; + } else { + const { x, y } = test.point; + + point = TEMP_POINT; + point.x = x; + point.y = y; + point.elevation = test.elevation; + } + + return visionSource._testLimit(mode, point); + } +}; + +export default DetectionModeMixin; + +/** @type {foundry.types.ElevatedPoint} */ +const TEMP_POINT = { x: 0.0, y: 0.0, elevation: 0.0 };