@inglorious/engine 0.11.0 → 1.1.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/package.json +3 -3
- package/src/core/engine.js +13 -31
- package/src/core/loops/{loops.js → index.js} +1 -1
- package/src/core/middlewares/entity-pool/entity-pool-middleware.js +12 -2
- package/src/core/middlewares/multiplayer-middleware.js +14 -10
- package/src/core/middlewares/middlewares.js +0 -32
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inglorious/engine",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "A JavaScript game engine written with global state, immutability, and pure functions in mind. Have fun(ctional programming) with it!",
|
|
5
5
|
"author": "IceOnFire <antony.mistretta@gmail.com> (https://ingloriouscoderz.it)",
|
|
6
6
|
"license": "MIT",
|
|
@@ -30,8 +30,8 @@
|
|
|
30
30
|
"access": "public"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@inglorious/store": "
|
|
34
|
-
"@inglorious/utils": "3.
|
|
33
|
+
"@inglorious/store": "4.0.0",
|
|
34
|
+
"@inglorious/utils": "3.2.0"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"prettier": "^3.5.3",
|
package/src/core/engine.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { audio } from "@inglorious/engine/behaviors/audio.js"
|
|
2
2
|
import { game } from "@inglorious/engine/behaviors/game.js"
|
|
3
|
-
import { createApi } from "@inglorious/store/api.js"
|
|
4
3
|
import { createStore } from "@inglorious/store/store.js"
|
|
5
4
|
import { augmentType } from "@inglorious/store/types.js"
|
|
6
5
|
import { isArray } from "@inglorious/utils/data-structures/array.js"
|
|
@@ -10,10 +9,8 @@ import { v } from "@inglorious/utils/v.js"
|
|
|
10
9
|
|
|
11
10
|
import { coreEvents } from "./core-events.js"
|
|
12
11
|
import { disconnectDevTools, initDevTools, sendAction } from "./dev-tools.js"
|
|
13
|
-
import {
|
|
12
|
+
import { Loop } from "./loops/index.js"
|
|
14
13
|
import { entityPoolMiddleware } from "./middlewares/entity-pool/entity-pool-middleware.js"
|
|
15
|
-
import { EntityPools } from "./middlewares/entity-pool/entity-pools.js"
|
|
16
|
-
import { applyMiddlewares } from "./middlewares/middlewares.js"
|
|
17
14
|
import { multiplayerMiddleware } from "./middlewares/multiplayer-middleware.js"
|
|
18
15
|
|
|
19
16
|
// Default game configuration
|
|
@@ -42,44 +39,29 @@ const ONE_SECOND = 1000 // Number of milliseconds in one second.
|
|
|
42
39
|
*/
|
|
43
40
|
export class Engine {
|
|
44
41
|
/**
|
|
45
|
-
* @param {Object}
|
|
46
|
-
* @param {Object} [renderer] - UI entity responsible for rendering. It must have a `render` method.
|
|
42
|
+
* @param {...Object} gameConfigs - Game-specific configurations.
|
|
47
43
|
*/
|
|
48
44
|
constructor(...gameConfigs) {
|
|
49
45
|
this._config = extendWith(merger, DEFAULT_GAME_CONFIG, ...gameConfigs)
|
|
50
46
|
|
|
51
|
-
// Determine devMode from the entities config
|
|
47
|
+
// Determine devMode from the entities config
|
|
52
48
|
const devMode = this._config.entities.game?.devMode
|
|
53
49
|
this._devMode = devMode
|
|
54
50
|
|
|
55
|
-
|
|
56
|
-
const systems = [...(this._config.systems ?? [])]
|
|
51
|
+
const middlewares = []
|
|
57
52
|
|
|
58
|
-
|
|
53
|
+
// Always add entity pool middleware
|
|
54
|
+
middlewares.push(entityPoolMiddleware())
|
|
59
55
|
|
|
60
|
-
//
|
|
61
|
-
this._api = createApi(this._store)
|
|
62
|
-
|
|
63
|
-
this._entityPools = new EntityPools()
|
|
64
|
-
this._api = applyMiddlewares(entityPoolMiddleware(this._entityPools))(
|
|
65
|
-
this._api,
|
|
66
|
-
)
|
|
67
|
-
this._api.getAllActivePoolEntities = () =>
|
|
68
|
-
this._entityPools.getAllActiveEntities()
|
|
69
|
-
|
|
70
|
-
if (this._devMode) {
|
|
71
|
-
this._api.getEntityPoolsStats = () => this._entityPools.getStats()
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// Apply multiplayer if specified.
|
|
56
|
+
// Add multiplayer middleware if needed
|
|
75
57
|
const multiplayer = this._config.entities.game?.multiplayer
|
|
76
58
|
if (multiplayer) {
|
|
77
|
-
|
|
78
|
-
this._api,
|
|
79
|
-
)
|
|
59
|
+
middlewares.push(multiplayerMiddleware(multiplayer))
|
|
80
60
|
}
|
|
81
61
|
|
|
82
|
-
this.
|
|
62
|
+
this._store = createStore({ ...this._config, middlewares })
|
|
63
|
+
this._api = this._store.getApi()
|
|
64
|
+
this._loop = new Loop[this._config.loop.type]()
|
|
83
65
|
|
|
84
66
|
if (this._devMode) {
|
|
85
67
|
initDevTools(this._store)
|
|
@@ -109,7 +91,7 @@ export class Engine {
|
|
|
109
91
|
*/
|
|
110
92
|
stop() {
|
|
111
93
|
this._api.notify("stop")
|
|
112
|
-
this._store.update(
|
|
94
|
+
this._store.update()
|
|
113
95
|
this._loop.stop()
|
|
114
96
|
}
|
|
115
97
|
|
|
@@ -119,7 +101,7 @@ export class Engine {
|
|
|
119
101
|
*/
|
|
120
102
|
update(dt) {
|
|
121
103
|
this._api.notify("update", dt)
|
|
122
|
-
const processedEvents = this._store.update(
|
|
104
|
+
const processedEvents = this._store.update()
|
|
123
105
|
const state = this._store.getState()
|
|
124
106
|
|
|
125
107
|
// Check for devMode changes and connect/disconnect dev tools accordingly.
|
|
@@ -1,10 +1,20 @@
|
|
|
1
1
|
import { EventMap } from "@inglorious/store/event-map.js"
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
import { EntityPools } from "./entity-pools"
|
|
4
|
+
|
|
5
|
+
export function entityPoolMiddleware() {
|
|
6
|
+
return (store, api) => {
|
|
7
|
+
const pools = new EntityPools()
|
|
5
8
|
const types = api.getTypes()
|
|
6
9
|
const eventMap = new EventMap()
|
|
7
10
|
|
|
11
|
+
api.getAllActivePoolEntities = () => pools.getAllActiveEntities()
|
|
12
|
+
|
|
13
|
+
const game = api.getEntity("game")
|
|
14
|
+
if (game.devMode) {
|
|
15
|
+
api.getEntityPoolsStats = () => pools.getStats()
|
|
16
|
+
}
|
|
17
|
+
|
|
8
18
|
return (next) => (event) => {
|
|
9
19
|
switch (event.type) {
|
|
10
20
|
case "spawn": {
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import {
|
|
2
|
+
deserialize,
|
|
3
|
+
serialize,
|
|
4
|
+
} from "@inglorious/utils/data-structures/object.js"
|
|
1
5
|
import { extend } from "@inglorious/utils/data-structures/objects.js"
|
|
2
6
|
|
|
3
7
|
import { coreEvents } from "../core-events.js"
|
|
@@ -19,21 +23,21 @@ export function multiplayerMiddleware(config = {}) {
|
|
|
19
23
|
const localQueue = []
|
|
20
24
|
|
|
21
25
|
// The middleware function that will be applied to the store.
|
|
22
|
-
return (
|
|
26
|
+
return (store) => (next) => (event) => {
|
|
23
27
|
if (coreEvents.includes(event.type)) {
|
|
24
28
|
return next(event)
|
|
25
29
|
}
|
|
26
30
|
|
|
27
31
|
// Establish the connection on the first event.
|
|
28
32
|
if (!ws) {
|
|
29
|
-
establishConnection(
|
|
33
|
+
establishConnection(store)
|
|
30
34
|
}
|
|
31
35
|
|
|
32
36
|
// Only send the event to the server if it didn't come from the server.
|
|
33
37
|
if (!event.fromServer) {
|
|
34
38
|
if (ws?.readyState === WebSocket.OPEN) {
|
|
35
39
|
// If the connection is open, send the event immediately.
|
|
36
|
-
ws.send(
|
|
40
|
+
ws.send(serialize(event))
|
|
37
41
|
} else {
|
|
38
42
|
// If the connection is not open, queue the event for later.
|
|
39
43
|
localQueue.push(event)
|
|
@@ -48,7 +52,7 @@ export function multiplayerMiddleware(config = {}) {
|
|
|
48
52
|
/**
|
|
49
53
|
* Attempts to establish a WebSocket connection to the server.
|
|
50
54
|
*/
|
|
51
|
-
function establishConnection(
|
|
55
|
+
function establishConnection(store) {
|
|
52
56
|
// If a connection already exists, close it first.
|
|
53
57
|
if (ws) {
|
|
54
58
|
ws.close()
|
|
@@ -62,26 +66,26 @@ export function multiplayerMiddleware(config = {}) {
|
|
|
62
66
|
ws.onopen = () => {
|
|
63
67
|
// Send any queued events to the server.
|
|
64
68
|
while (localQueue.length) {
|
|
65
|
-
ws.send(
|
|
69
|
+
ws.send(serialize(localQueue.shift()))
|
|
66
70
|
}
|
|
67
71
|
}
|
|
68
72
|
|
|
69
73
|
ws.onmessage = (event) => {
|
|
70
|
-
const serverEvent =
|
|
74
|
+
const serverEvent = deserialize(event.data)
|
|
71
75
|
|
|
72
76
|
if (serverEvent.type === "initialState") {
|
|
73
77
|
// Merge the server's initial state with the client's local state.
|
|
74
|
-
const nextState = extend(
|
|
75
|
-
|
|
78
|
+
const nextState = extend(store.getState(), serverEvent.payload)
|
|
79
|
+
store.setState(nextState)
|
|
76
80
|
} else {
|
|
77
81
|
// Dispatch the event to the local store to update the client's state.
|
|
78
|
-
|
|
82
|
+
store.dispatch({ ...serverEvent, fromServer: true })
|
|
79
83
|
}
|
|
80
84
|
}
|
|
81
85
|
|
|
82
86
|
ws.onclose = () => {
|
|
83
87
|
// Attempt to reconnect after a short delay.
|
|
84
|
-
setTimeout(() => establishConnection(
|
|
88
|
+
setTimeout(() => establishConnection(store), reconnectionDelay)
|
|
85
89
|
}
|
|
86
90
|
|
|
87
91
|
ws.onerror = () => {
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { compose } from "@inglorious/utils/functions/functions.js"
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Applies a list of middleware functions to a store's dispatch method.
|
|
5
|
-
*
|
|
6
|
-
* @param {...Function} middlewares The middleware functions to apply.
|
|
7
|
-
* @returns {Function} A store enhancer function.
|
|
8
|
-
*/
|
|
9
|
-
export function applyMiddlewares(...middlewares) {
|
|
10
|
-
return (store) => {
|
|
11
|
-
let dispatch = () => {
|
|
12
|
-
throw new Error(
|
|
13
|
-
"Dispatching while constructing your middleware is not allowed.",
|
|
14
|
-
)
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
// The middleware API that can be passed to each middleware function.
|
|
18
|
-
const api = {
|
|
19
|
-
...store,
|
|
20
|
-
dispatch: (...args) => dispatch(...args),
|
|
21
|
-
notify: (type, payload) => dispatch({ type, payload }),
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
// Create a chain of middleware functions.
|
|
25
|
-
const chain = middlewares.map((middleware) => middleware(api))
|
|
26
|
-
|
|
27
|
-
// Compose the middleware chain to create the final dispatch function.
|
|
28
|
-
dispatch = compose(...chain)(store.dispatch)
|
|
29
|
-
|
|
30
|
-
return api
|
|
31
|
-
}
|
|
32
|
-
}
|