@inglorious/engine 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +76 -75
- package/package.json +14 -25
- package/src/{engine/ai → ai}/movement/dynamic/align.js +63 -63
- package/src/{engine/ai → ai}/movement/dynamic/arrive.js +42 -42
- package/src/{engine/ai → ai}/movement/dynamic/evade.js +38 -38
- package/src/{engine/ai → ai}/movement/dynamic/face.js +19 -19
- package/src/{engine/ai → ai}/movement/dynamic/flee.js +45 -45
- package/src/{engine/ai → ai}/movement/dynamic/look-where-youre-going.js +16 -16
- package/src/{engine/ai → ai}/movement/dynamic/match-velocity.js +51 -51
- package/src/{engine/ai → ai}/movement/dynamic/pursue.js +38 -38
- package/src/{engine/ai → ai}/movement/dynamic/seek.js +44 -44
- package/src/{engine/ai → ai}/movement/dynamic/wander.js +31 -31
- package/src/{engine/ai → ai}/movement/kinematic/align.js +37 -37
- package/src/{engine/ai → ai}/movement/kinematic/arrive.js +42 -42
- package/src/{engine/ai → ai}/movement/kinematic/face.js +19 -19
- package/src/{engine/ai → ai}/movement/kinematic/flee.js +26 -26
- package/src/{engine/ai → ai}/movement/kinematic/seek.js +26 -26
- package/src/{engine/ai → ai}/movement/kinematic/seek.test.js +42 -42
- package/src/{engine/ai → ai}/movement/kinematic/wander-as-seek.js +31 -31
- package/src/{engine/ai → ai}/movement/kinematic/wander.js +27 -27
- package/src/{engine/animation → animation}/sprite.js +101 -101
- package/src/{engine/animation → animation}/ticker.js +38 -38
- package/src/{engine/behaviors → behaviors}/camera.js +68 -68
- package/src/{engine/behaviors → behaviors}/controls/dynamic/modern.js +76 -76
- package/src/{engine/behaviors → behaviors}/controls/dynamic/shooter.js +84 -84
- package/src/{engine/behaviors → behaviors}/controls/dynamic/tank.js +69 -69
- package/src/{engine/behaviors → behaviors}/controls/event-handlers.js +17 -17
- package/src/{engine/behaviors → behaviors}/controls/kinematic/modern.js +76 -76
- package/src/{engine/behaviors → behaviors}/controls/kinematic/shooter.js +82 -82
- package/src/{engine/behaviors → behaviors}/controls/kinematic/tank.js +67 -67
- package/src/behaviors/debug/collision.js +29 -0
- package/src/{engine/behaviors → behaviors}/fps.js +29 -29
- package/src/{engine/behaviors → behaviors}/fsm.js +33 -33
- package/src/{engine/behaviors → behaviors}/fsm.test.js +49 -49
- package/src/{engine/behaviors → behaviors}/game.js +15 -15
- package/src/{engine/behaviors → behaviors}/input/controls.js +37 -37
- package/src/{engine/behaviors → behaviors}/input/gamepad.js +114 -114
- package/src/{engine/behaviors → behaviors}/input/input.js +48 -48
- package/src/{engine/behaviors → behaviors}/input/keyboard.js +64 -64
- package/src/{engine/behaviors → behaviors}/input/mouse.js +91 -91
- package/src/{engine/behaviors → behaviors}/physics/bouncy.js +25 -25
- package/src/{engine/behaviors → behaviors}/physics/clamped.js +36 -36
- package/src/{engine/behaviors → behaviors}/physics/collidable.js +20 -20
- package/src/{engine/behaviors → behaviors}/physics/jumpable.js +145 -145
- package/src/{engine/behaviors → behaviors}/ui/button.js +17 -17
- package/src/{engine/collision → collision}/detection.js +110 -110
- package/src/{engine/core → core}/dev-tools.js +135 -135
- package/src/{engine/core → core}/engine.js +119 -119
- package/src/{engine/core → core}/loop.js +15 -15
- package/src/{engine/core → core}/loops/animation-frame.js +25 -25
- package/src/{engine/core → core}/loops/elapsed.js +22 -22
- package/src/{engine/core → core}/loops/fixed.js +27 -27
- package/src/{engine/core → core}/loops/flash.js +13 -13
- package/src/{engine/core → core}/loops/lag.js +26 -26
- package/src/main.js +10 -10
- package/src/{engine/movement → movement}/dynamic/modern.js +21 -21
- package/src/{engine/movement → movement}/dynamic/tank.js +43 -43
- package/src/{engine/movement → movement}/kinematic/modern.js +16 -16
- package/src/{engine/movement → movement}/kinematic/modern.test.js +27 -27
- package/src/{engine/movement → movement}/kinematic/tank.js +27 -27
- package/src/{engine/physics → physics}/bounds.js +138 -138
- package/src/{engine/physics → physics}/position.js +43 -43
- package/src/{engine/physics → physics}/position.test.js +80 -80
- package/src/{engine/systems → systems}/sprite-animation.js +27 -27
- package/src/engine/behaviors/debug/collision.js +0 -35
- package/src/engine/core/api.js +0 -34
- package/src/engine/core/select.js +0 -26
- package/src/engine/core/store.js +0 -178
- package/src/engine/core/store.test.js +0 -110
- package/src/renderers/canvas/absolute-position.js +0 -18
- package/src/renderers/canvas/camera.js +0 -13
- package/src/renderers/canvas/canvas-renderer.js +0 -68
- package/src/renderers/canvas/character.js +0 -38
- package/src/renderers/canvas/form/button.js +0 -25
- package/src/renderers/canvas/fps.js +0 -18
- package/src/renderers/canvas/image/hitmask.js +0 -51
- package/src/renderers/canvas/image/image.js +0 -34
- package/src/renderers/canvas/image/sprite.js +0 -49
- package/src/renderers/canvas/image/tilemap.js +0 -66
- package/src/renderers/canvas/mouse.js +0 -37
- package/src/renderers/canvas/rendering-system.js +0 -79
- package/src/renderers/canvas/shapes/circle.js +0 -29
- package/src/renderers/canvas/shapes/rectangle.js +0 -27
- package/src/renderers/react/game/character/character.module.scss +0 -17
- package/src/renderers/react/game/character/index.jsx +0 -20
- package/src/renderers/react/game/cursor/cursor.module.scss +0 -47
- package/src/renderers/react/game/cursor/index.jsx +0 -20
- package/src/renderers/react/game/form/fields/field/field.module.scss +0 -5
- package/src/renderers/react/game/form/fields/field/index.jsx +0 -56
- package/src/renderers/react/game/form/fields/fields.module.scss +0 -48
- package/src/renderers/react/game/form/fields/index.jsx +0 -12
- package/src/renderers/react/game/form/form.module.scss +0 -18
- package/src/renderers/react/game/form/index.jsx +0 -22
- package/src/renderers/react/game/fps/index.jsx +0 -16
- package/src/renderers/react/game/game.jsx +0 -72
- package/src/renderers/react/game/index.jsx +0 -29
- package/src/renderers/react/game/platform/index.jsx +0 -30
- package/src/renderers/react/game/platform/platform.module.scss +0 -7
- package/src/renderers/react/game/scene/index.jsx +0 -27
- package/src/renderers/react/game/scene/scene.module.scss +0 -9
- package/src/renderers/react/game/sprite/index.jsx +0 -60
- package/src/renderers/react/game/sprite/sprite.module.css +0 -3
- package/src/renderers/react/game/stats/index.jsx +0 -22
- package/src/renderers/react/hocs/with-absolute-position/index.jsx +0 -20
- package/src/renderers/react/hocs/with-absolute-position/with-absolute-position.module.scss +0 -5
- package/src/renderers/react/index.jsx +0 -9
- package/src/utils/algorithms/decision-tree.js +0 -24
- package/src/utils/algorithms/decision-tree.test.js +0 -153
- package/src/utils/algorithms/path-finding.js +0 -155
- package/src/utils/algorithms/path-finding.test.js +0 -151
- package/src/utils/algorithms/types.d.ts +0 -28
- package/src/utils/data-structures/array.js +0 -83
- package/src/utils/data-structures/array.test.js +0 -173
- package/src/utils/data-structures/board.js +0 -159
- package/src/utils/data-structures/board.test.js +0 -242
- package/src/utils/data-structures/boolean.js +0 -9
- package/src/utils/data-structures/heap.js +0 -164
- package/src/utils/data-structures/heap.test.js +0 -103
- package/src/utils/data-structures/object.js +0 -138
- package/src/utils/data-structures/object.test.js +0 -218
- package/src/utils/data-structures/objects.js +0 -66
- package/src/utils/data-structures/objects.test.js +0 -99
- package/src/utils/data-structures/tree.js +0 -36
- package/src/utils/data-structures/tree.test.js +0 -33
- package/src/utils/data-structures/types.d.ts +0 -4
- package/src/utils/functions/functions.js +0 -19
- package/src/utils/functions/functions.test.js +0 -23
- package/src/utils/math/geometry/circle.js +0 -70
- package/src/utils/math/geometry/circle.test.js +0 -97
- package/src/utils/math/geometry/hitmask.js +0 -70
- package/src/utils/math/geometry/hitmask.test.js +0 -155
- package/src/utils/math/geometry/line.js +0 -35
- package/src/utils/math/geometry/line.test.js +0 -49
- package/src/utils/math/geometry/point.js +0 -78
- package/src/utils/math/geometry/point.test.js +0 -81
- package/src/utils/math/geometry/rectangle.js +0 -76
- package/src/utils/math/geometry/rectangle.test.js +0 -42
- package/src/utils/math/geometry/segment.js +0 -80
- package/src/utils/math/geometry/segment.test.js +0 -183
- package/src/utils/math/geometry/triangle.js +0 -15
- package/src/utils/math/geometry/triangle.test.js +0 -11
- package/src/utils/math/geometry/types.d.ts +0 -23
- package/src/utils/math/linear-algebra/2d.js +0 -28
- package/src/utils/math/linear-algebra/2d.test.js +0 -17
- package/src/utils/math/linear-algebra/quaternion.js +0 -22
- package/src/utils/math/linear-algebra/quaternion.test.js +0 -25
- package/src/utils/math/linear-algebra/quaternions.js +0 -20
- package/src/utils/math/linear-algebra/quaternions.test.js +0 -29
- package/src/utils/math/linear-algebra/types.d.ts +0 -4
- package/src/utils/math/linear-algebra/vector.js +0 -327
- package/src/utils/math/linear-algebra/vector.test.js +0 -265
- package/src/utils/math/linear-algebra/vectors.js +0 -122
- package/src/utils/math/linear-algebra/vectors.test.js +0 -65
- package/src/utils/math/linear-interpolation.js +0 -9
- package/src/utils/math/numbers.js +0 -90
- package/src/utils/math/numbers.test.js +0 -137
- package/src/utils/math/rng.js +0 -44
- package/src/utils/math/rng.test.js +0 -39
- package/src/utils/math/statistics.js +0 -43
- package/src/utils/math/statistics.test.js +0 -47
- package/src/utils/math/trigonometry.js +0 -89
- package/src/utils/math/trigonometry.test.js +0 -52
- package/src/utils/physics/acceleration.js +0 -61
- package/src/utils/physics/friction.js +0 -28
- package/src/utils/physics/friction.test.js +0 -42
- package/src/utils/physics/gravity.js +0 -69
- package/src/utils/physics/gravity.test.js +0 -77
- package/src/utils/physics/jump.js +0 -31
- package/src/utils/physics/velocity.js +0 -36
|
@@ -1,110 +1,110 @@
|
|
|
1
|
-
import { filter } from "@inglorious/utils/data-structures/object.js"
|
|
2
|
-
import * as circle from "@inglorious/utils/math/geometry/circle.js"
|
|
3
|
-
import * as hitmask from "@inglorious/utils/math/geometry/hitmask.js"
|
|
4
|
-
import * as line from "@inglorious/utils/math/geometry/line.js"
|
|
5
|
-
import * as point from "@inglorious/utils/math/geometry/point.js"
|
|
6
|
-
import * as rectangle from "@inglorious/utils/math/geometry/rectangle.js"
|
|
7
|
-
import * as segment from "@inglorious/utils/math/geometry/segment.js"
|
|
8
|
-
import { zero } from "@inglorious/utils/math/linear-algebra/vector.js"
|
|
9
|
-
import { add } from "@inglorious/utils/math/linear-algebra/vectors.js"
|
|
10
|
-
|
|
11
|
-
const Z = 2 // Z-axis index.
|
|
12
|
-
|
|
13
|
-
const Shape = {
|
|
14
|
-
circle,
|
|
15
|
-
line,
|
|
16
|
-
point,
|
|
17
|
-
rectangle,
|
|
18
|
-
segment,
|
|
19
|
-
hitmask,
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Finds the first collision between a point and a list of entities.
|
|
24
|
-
*
|
|
25
|
-
* @param {Point} entity - The point to check for collisions.
|
|
26
|
-
* @param {Options} options - Options for collision detection.
|
|
27
|
-
* @returns {Entity | undefined} The first entity that collides with the point, or undefined if none are found.
|
|
28
|
-
*/
|
|
29
|
-
export function findCollision(entity, entities, collisionGroup = "hitbox") {
|
|
30
|
-
const otherEntities = filter(
|
|
31
|
-
entities,
|
|
32
|
-
(id, { collisions }) => id !== entity.id && collisions?.[collisionGroup],
|
|
33
|
-
)
|
|
34
|
-
|
|
35
|
-
return Object.values(otherEntities)
|
|
36
|
-
.toSorted((a, b) => a.position[Z] - b.position[Z])
|
|
37
|
-
.find((target) => collidesWith(entity, target, collisionGroup))
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export function collidesWith(entity, target, collisionGroup = "hitbox") {
|
|
41
|
-
const entityShape = getCollisionShape(entity, collisionGroup)
|
|
42
|
-
const targetShape = getCollisionShape(target, collisionGroup)
|
|
43
|
-
|
|
44
|
-
if (!entityShape || !targetShape) {
|
|
45
|
-
return false
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
return shapeCollidesWith(entityShape, targetShape)
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
function shapeCollidesWith(entity, target) {
|
|
52
|
-
const shapeFns = Shape[entity.shape]
|
|
53
|
-
|
|
54
|
-
switch (target.shape) {
|
|
55
|
-
case "circle":
|
|
56
|
-
return shapeFns.intersectsCircle(entity, target)
|
|
57
|
-
|
|
58
|
-
case "line":
|
|
59
|
-
return shapeFns.intersectsLine(entity, target)
|
|
60
|
-
|
|
61
|
-
case "point":
|
|
62
|
-
return shapeFns.intersectsPoint(entity, target)
|
|
63
|
-
|
|
64
|
-
case "rectangle":
|
|
65
|
-
return shapeFns.intersectsRectangle(entity, target)
|
|
66
|
-
|
|
67
|
-
case "segment":
|
|
68
|
-
return shapeFns.intersectsSegment(entity, target)
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
export function findCollisions(entity, target, collisionGroup = "hitbox") {
|
|
73
|
-
const entityShape = getCollisionShape(entity, collisionGroup)
|
|
74
|
-
const targetShape = getCollisionShape(target, collisionGroup)
|
|
75
|
-
|
|
76
|
-
if (!entityShape || !targetShape) {
|
|
77
|
-
return false
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
const shapeFns = Shape[entityShape.shape]
|
|
81
|
-
if (!shapeFns || !shapeFns.findCollisions) {
|
|
82
|
-
return false
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
return shapeFns.findCollisions(entityShape, targetShape)
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Correctly calculates the absolute position and size of an entity's
|
|
90
|
-
* collision shape, including any offsets.
|
|
91
|
-
*/
|
|
92
|
-
function getCollisionShape(entity, collisionGroup = "hitbox") {
|
|
93
|
-
const collision = entity.collisions[collisionGroup]
|
|
94
|
-
if (!collision) {
|
|
95
|
-
return null
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
const position = add(
|
|
99
|
-
entity.position,
|
|
100
|
-
collision.offset ?? zero(),
|
|
101
|
-
entity.offset ?? zero(),
|
|
102
|
-
)
|
|
103
|
-
|
|
104
|
-
return {
|
|
105
|
-
...collision,
|
|
106
|
-
position,
|
|
107
|
-
size: collision.size ?? entity.size,
|
|
108
|
-
radius: collision.radius ?? entity.radius,
|
|
109
|
-
}
|
|
110
|
-
}
|
|
1
|
+
import { filter } from "@inglorious/utils/data-structures/object.js"
|
|
2
|
+
import * as circle from "@inglorious/utils/math/geometry/circle.js"
|
|
3
|
+
import * as hitmask from "@inglorious/utils/math/geometry/hitmask.js"
|
|
4
|
+
import * as line from "@inglorious/utils/math/geometry/line.js"
|
|
5
|
+
import * as point from "@inglorious/utils/math/geometry/point.js"
|
|
6
|
+
import * as rectangle from "@inglorious/utils/math/geometry/rectangle.js"
|
|
7
|
+
import * as segment from "@inglorious/utils/math/geometry/segment.js"
|
|
8
|
+
import { zero } from "@inglorious/utils/math/linear-algebra/vector.js"
|
|
9
|
+
import { add } from "@inglorious/utils/math/linear-algebra/vectors.js"
|
|
10
|
+
|
|
11
|
+
const Z = 2 // Z-axis index.
|
|
12
|
+
|
|
13
|
+
const Shape = {
|
|
14
|
+
circle,
|
|
15
|
+
line,
|
|
16
|
+
point,
|
|
17
|
+
rectangle,
|
|
18
|
+
segment,
|
|
19
|
+
hitmask,
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Finds the first collision between a point and a list of entities.
|
|
24
|
+
*
|
|
25
|
+
* @param {Point} entity - The point to check for collisions.
|
|
26
|
+
* @param {Options} options - Options for collision detection.
|
|
27
|
+
* @returns {Entity | undefined} The first entity that collides with the point, or undefined if none are found.
|
|
28
|
+
*/
|
|
29
|
+
export function findCollision(entity, entities, collisionGroup = "hitbox") {
|
|
30
|
+
const otherEntities = filter(
|
|
31
|
+
entities,
|
|
32
|
+
(id, { collisions }) => id !== entity.id && collisions?.[collisionGroup],
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
return Object.values(otherEntities)
|
|
36
|
+
.toSorted((a, b) => a.position[Z] - b.position[Z])
|
|
37
|
+
.find((target) => collidesWith(entity, target, collisionGroup))
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function collidesWith(entity, target, collisionGroup = "hitbox") {
|
|
41
|
+
const entityShape = getCollisionShape(entity, collisionGroup)
|
|
42
|
+
const targetShape = getCollisionShape(target, collisionGroup)
|
|
43
|
+
|
|
44
|
+
if (!entityShape || !targetShape) {
|
|
45
|
+
return false
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return shapeCollidesWith(entityShape, targetShape)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function shapeCollidesWith(entity, target) {
|
|
52
|
+
const shapeFns = Shape[entity.shape]
|
|
53
|
+
|
|
54
|
+
switch (target.shape) {
|
|
55
|
+
case "circle":
|
|
56
|
+
return shapeFns.intersectsCircle(entity, target)
|
|
57
|
+
|
|
58
|
+
case "line":
|
|
59
|
+
return shapeFns.intersectsLine(entity, target)
|
|
60
|
+
|
|
61
|
+
case "point":
|
|
62
|
+
return shapeFns.intersectsPoint(entity, target)
|
|
63
|
+
|
|
64
|
+
case "rectangle":
|
|
65
|
+
return shapeFns.intersectsRectangle(entity, target)
|
|
66
|
+
|
|
67
|
+
case "segment":
|
|
68
|
+
return shapeFns.intersectsSegment(entity, target)
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function findCollisions(entity, target, collisionGroup = "hitbox") {
|
|
73
|
+
const entityShape = getCollisionShape(entity, collisionGroup)
|
|
74
|
+
const targetShape = getCollisionShape(target, collisionGroup)
|
|
75
|
+
|
|
76
|
+
if (!entityShape || !targetShape) {
|
|
77
|
+
return false
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const shapeFns = Shape[entityShape.shape]
|
|
81
|
+
if (!shapeFns || !shapeFns.findCollisions) {
|
|
82
|
+
return false
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return shapeFns.findCollisions(entityShape, targetShape)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Correctly calculates the absolute position and size of an entity's
|
|
90
|
+
* collision shape, including any offsets.
|
|
91
|
+
*/
|
|
92
|
+
function getCollisionShape(entity, collisionGroup = "hitbox") {
|
|
93
|
+
const collision = entity.collisions[collisionGroup]
|
|
94
|
+
if (!collision) {
|
|
95
|
+
return null
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const position = add(
|
|
99
|
+
entity.position,
|
|
100
|
+
collision.offset ?? zero(),
|
|
101
|
+
entity.offset ?? zero(),
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
return {
|
|
105
|
+
...collision,
|
|
106
|
+
position,
|
|
107
|
+
size: collision.size ?? entity.size,
|
|
108
|
+
radius: collision.radius ?? entity.radius,
|
|
109
|
+
}
|
|
110
|
+
}
|
|
@@ -1,135 +1,135 @@
|
|
|
1
|
-
export const ACTION_BLACKLIST = [
|
|
2
|
-
"update",
|
|
3
|
-
"gamepadAxis",
|
|
4
|
-
"gamepadPress",
|
|
5
|
-
"gamepadRelease",
|
|
6
|
-
"keyboardKeyDown",
|
|
7
|
-
"keyboardKeyUp",
|
|
8
|
-
"inputAxis",
|
|
9
|
-
"inputPress",
|
|
10
|
-
"inputRelease",
|
|
11
|
-
"mouseMove",
|
|
12
|
-
"mouseClick",
|
|
13
|
-
"spriteAnimationEnd",
|
|
14
|
-
]
|
|
15
|
-
|
|
16
|
-
const LAST_STATE = 1
|
|
17
|
-
|
|
18
|
-
let devToolsInstance = null
|
|
19
|
-
let unsubscribe = null
|
|
20
|
-
|
|
21
|
-
export function initDevTools(store) {
|
|
22
|
-
// Prevent multiple connections
|
|
23
|
-
if (devToolsInstance) {
|
|
24
|
-
return
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
if (typeof window === "undefined" || !window.__REDUX_DEVTOOLS_EXTENSION__) {
|
|
28
|
-
return
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
devToolsInstance = window.__REDUX_DEVTOOLS_EXTENSION__.connect({
|
|
32
|
-
name: "Inglorious Engine",
|
|
33
|
-
predicate: (state, action) => !ACTION_BLACKLIST.includes(action.type),
|
|
34
|
-
actionCreators: {
|
|
35
|
-
jump: () => ({ type: "jump", payload: { inputId: "input0" } }),
|
|
36
|
-
},
|
|
37
|
-
// @see https://github.com/reduxjs/redux-devtools/blob/main/extension/docs/API/Arguments.md#features
|
|
38
|
-
features: {
|
|
39
|
-
pause: true, // start/pause recording of dispatched actions
|
|
40
|
-
lock: true, // lock/unlock dispatching actions and side effects
|
|
41
|
-
persist: true, // persist states on page reloading
|
|
42
|
-
export: true, // export history of actions in a file
|
|
43
|
-
import: "custom", // import history of actions from a file
|
|
44
|
-
jump: false, // jump back and forth (time travelling)
|
|
45
|
-
skip: false, // skip (cancel) actions
|
|
46
|
-
reorder: false, // drag and drop actions in the history list
|
|
47
|
-
dispatch: true, // dispatch custom actions or action creators
|
|
48
|
-
test: false, // generate tests for the selected actions
|
|
49
|
-
},
|
|
50
|
-
})
|
|
51
|
-
|
|
52
|
-
unsubscribe = devToolsInstance.subscribe((message) => {
|
|
53
|
-
switch (message.type) {
|
|
54
|
-
case "DISPATCH":
|
|
55
|
-
handleDispatch(message, store)
|
|
56
|
-
break
|
|
57
|
-
|
|
58
|
-
case "ACTION":
|
|
59
|
-
handleAction(message, store)
|
|
60
|
-
break
|
|
61
|
-
}
|
|
62
|
-
})
|
|
63
|
-
|
|
64
|
-
devToolsInstance.init(store.getState())
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
export function disconnectDevTools() {
|
|
68
|
-
// The `disconnect` method on the devToolsInstance is not available in all
|
|
69
|
-
// environments or versions of the extension.
|
|
70
|
-
// The safest way to "disconnect" is to unsubscribe from any listeners
|
|
71
|
-
// and release our reference to the instance, which prevents any further
|
|
72
|
-
// actions from being sent.
|
|
73
|
-
if (unsubscribe) {
|
|
74
|
-
unsubscribe()
|
|
75
|
-
unsubscribe = null
|
|
76
|
-
devToolsInstance = null
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
export function sendAction(action, state) {
|
|
81
|
-
if (devToolsInstance) {
|
|
82
|
-
devToolsInstance.send(action, state)
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
function handleDispatch(message, store) {
|
|
87
|
-
switch (message.payload.type) {
|
|
88
|
-
// reset button
|
|
89
|
-
case "RESET": {
|
|
90
|
-
store.reset()
|
|
91
|
-
devToolsInstance.init(store.getState())
|
|
92
|
-
break
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// revert button
|
|
96
|
-
case "ROLLBACK": {
|
|
97
|
-
const newState = JSON.parse(message.state)
|
|
98
|
-
store.setState(newState)
|
|
99
|
-
break
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// commit button
|
|
103
|
-
case "COMMIT": {
|
|
104
|
-
devToolsInstance.init(store.getState())
|
|
105
|
-
break
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
// import from file button
|
|
109
|
-
case "IMPORT_STATE": {
|
|
110
|
-
const { computedStates, actionsById } = message.payload.nextLiftedState
|
|
111
|
-
|
|
112
|
-
const [firstComputedState] = computedStates
|
|
113
|
-
const lastComputedState =
|
|
114
|
-
computedStates[computedStates.length - LAST_STATE]
|
|
115
|
-
if (lastComputedState) {
|
|
116
|
-
store.setState(lastComputedState.state)
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
const flattenedActions = Object.values(actionsById)
|
|
120
|
-
.flatMap(({ action }) => action.payload ?? action)
|
|
121
|
-
.map((action, index) => [index, action])
|
|
122
|
-
|
|
123
|
-
devToolsInstance.init(
|
|
124
|
-
firstComputedState.state,
|
|
125
|
-
Object.fromEntries(flattenedActions),
|
|
126
|
-
)
|
|
127
|
-
break
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
function handleAction(message, store) {
|
|
133
|
-
const action = JSON.parse(message.payload)
|
|
134
|
-
store.dispatch(action)
|
|
135
|
-
}
|
|
1
|
+
export const ACTION_BLACKLIST = [
|
|
2
|
+
"update",
|
|
3
|
+
"gamepadAxis",
|
|
4
|
+
"gamepadPress",
|
|
5
|
+
"gamepadRelease",
|
|
6
|
+
"keyboardKeyDown",
|
|
7
|
+
"keyboardKeyUp",
|
|
8
|
+
"inputAxis",
|
|
9
|
+
"inputPress",
|
|
10
|
+
"inputRelease",
|
|
11
|
+
"mouseMove",
|
|
12
|
+
"mouseClick",
|
|
13
|
+
"spriteAnimationEnd",
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
const LAST_STATE = 1
|
|
17
|
+
|
|
18
|
+
let devToolsInstance = null
|
|
19
|
+
let unsubscribe = null
|
|
20
|
+
|
|
21
|
+
export function initDevTools(store) {
|
|
22
|
+
// Prevent multiple connections
|
|
23
|
+
if (devToolsInstance) {
|
|
24
|
+
return
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (typeof window === "undefined" || !window.__REDUX_DEVTOOLS_EXTENSION__) {
|
|
28
|
+
return
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
devToolsInstance = window.__REDUX_DEVTOOLS_EXTENSION__.connect({
|
|
32
|
+
name: "Inglorious Engine",
|
|
33
|
+
predicate: (state, action) => !ACTION_BLACKLIST.includes(action.type),
|
|
34
|
+
actionCreators: {
|
|
35
|
+
jump: () => ({ type: "jump", payload: { inputId: "input0" } }),
|
|
36
|
+
},
|
|
37
|
+
// @see https://github.com/reduxjs/redux-devtools/blob/main/extension/docs/API/Arguments.md#features
|
|
38
|
+
features: {
|
|
39
|
+
pause: true, // start/pause recording of dispatched actions
|
|
40
|
+
lock: true, // lock/unlock dispatching actions and side effects
|
|
41
|
+
persist: true, // persist states on page reloading
|
|
42
|
+
export: true, // export history of actions in a file
|
|
43
|
+
import: "custom", // import history of actions from a file
|
|
44
|
+
jump: false, // jump back and forth (time travelling)
|
|
45
|
+
skip: false, // skip (cancel) actions
|
|
46
|
+
reorder: false, // drag and drop actions in the history list
|
|
47
|
+
dispatch: true, // dispatch custom actions or action creators
|
|
48
|
+
test: false, // generate tests for the selected actions
|
|
49
|
+
},
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
unsubscribe = devToolsInstance.subscribe((message) => {
|
|
53
|
+
switch (message.type) {
|
|
54
|
+
case "DISPATCH":
|
|
55
|
+
handleDispatch(message, store)
|
|
56
|
+
break
|
|
57
|
+
|
|
58
|
+
case "ACTION":
|
|
59
|
+
handleAction(message, store)
|
|
60
|
+
break
|
|
61
|
+
}
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
devToolsInstance.init(store.getState())
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export function disconnectDevTools() {
|
|
68
|
+
// The `disconnect` method on the devToolsInstance is not available in all
|
|
69
|
+
// environments or versions of the extension.
|
|
70
|
+
// The safest way to "disconnect" is to unsubscribe from any listeners
|
|
71
|
+
// and release our reference to the instance, which prevents any further
|
|
72
|
+
// actions from being sent.
|
|
73
|
+
if (unsubscribe) {
|
|
74
|
+
unsubscribe()
|
|
75
|
+
unsubscribe = null
|
|
76
|
+
devToolsInstance = null
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export function sendAction(action, state) {
|
|
81
|
+
if (devToolsInstance) {
|
|
82
|
+
devToolsInstance.send(action, state)
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function handleDispatch(message, store) {
|
|
87
|
+
switch (message.payload.type) {
|
|
88
|
+
// reset button
|
|
89
|
+
case "RESET": {
|
|
90
|
+
store.reset()
|
|
91
|
+
devToolsInstance.init(store.getState())
|
|
92
|
+
break
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// revert button
|
|
96
|
+
case "ROLLBACK": {
|
|
97
|
+
const newState = JSON.parse(message.state)
|
|
98
|
+
store.setState(newState)
|
|
99
|
+
break
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// commit button
|
|
103
|
+
case "COMMIT": {
|
|
104
|
+
devToolsInstance.init(store.getState())
|
|
105
|
+
break
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// import from file button
|
|
109
|
+
case "IMPORT_STATE": {
|
|
110
|
+
const { computedStates, actionsById } = message.payload.nextLiftedState
|
|
111
|
+
|
|
112
|
+
const [firstComputedState] = computedStates
|
|
113
|
+
const lastComputedState =
|
|
114
|
+
computedStates[computedStates.length - LAST_STATE]
|
|
115
|
+
if (lastComputedState) {
|
|
116
|
+
store.setState(lastComputedState.state)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const flattenedActions = Object.values(actionsById)
|
|
120
|
+
.flatMap(({ action }) => action.payload ?? action)
|
|
121
|
+
.map((action, index) => [index, action])
|
|
122
|
+
|
|
123
|
+
devToolsInstance.init(
|
|
124
|
+
firstComputedState.state,
|
|
125
|
+
Object.fromEntries(flattenedActions),
|
|
126
|
+
)
|
|
127
|
+
break
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function handleAction(message, store) {
|
|
133
|
+
const action = JSON.parse(message.payload)
|
|
134
|
+
store.dispatch(action)
|
|
135
|
+
}
|