@rpgjs/common 4.3.0 → 5.0.0-alpha.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/dist/Physic.d.ts +619 -0
- package/dist/Player.d.ts +198 -0
- package/{lib → dist}/Utils.d.ts +19 -2
- package/dist/database/Item.d.ts +10 -0
- package/dist/database/index.d.ts +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +16741 -0
- package/dist/index.js.map +1 -0
- package/dist/modules.d.ts +92 -0
- package/dist/movement/MovementManager.d.ts +84 -0
- package/dist/movement/MovementStrategy.d.ts +39 -0
- package/dist/movement/index.d.ts +12 -0
- package/dist/movement/strategies/CompositeMovement.d.ts +76 -0
- package/dist/movement/strategies/Dash.d.ts +52 -0
- package/dist/movement/strategies/IceMovement.d.ts +87 -0
- package/dist/movement/strategies/Knockback.d.ts +50 -0
- package/dist/movement/strategies/LinearMove.d.ts +43 -0
- package/dist/movement/strategies/LinearRepulsion.d.ts +55 -0
- package/dist/movement/strategies/Oscillate.d.ts +60 -0
- package/dist/movement/strategies/PathFollow.d.ts +78 -0
- package/dist/movement/strategies/ProjectileMovement.d.ts +138 -0
- package/dist/movement/strategies/SeekAvoid.d.ts +27 -0
- package/dist/rooms/Map.d.ts +109 -0
- package/dist/services/updateMap.d.ts +7 -0
- package/package.json +17 -17
- package/src/Physic.ts +1644 -0
- package/src/Player.ts +262 -26
- package/src/{gui/PrebuiltGui.ts → PrebuiltGui.ts} +1 -1
- package/src/Utils.ts +184 -123
- package/src/database/Item.ts +19 -0
- package/src/database/index.ts +1 -0
- package/src/index.ts +9 -25
- package/src/modules.ts +230 -0
- package/src/movement/MovementManager.ts +142 -0
- package/src/movement/MovementStrategy.ts +42 -0
- package/src/movement/index.ts +15 -0
- package/src/movement/strategies/CompositeMovement.ts +173 -0
- package/src/movement/strategies/Dash.ts +82 -0
- package/src/movement/strategies/IceMovement.ts +158 -0
- package/src/movement/strategies/Knockback.ts +81 -0
- package/src/movement/strategies/LinearMove.ts +58 -0
- package/src/movement/strategies/LinearRepulsion.ts +128 -0
- package/src/movement/strategies/Oscillate.ts +144 -0
- package/src/movement/strategies/PathFollow.ts +156 -0
- package/src/movement/strategies/ProjectileMovement.ts +322 -0
- package/src/movement/strategies/SeekAvoid.ts +123 -0
- package/src/rooms/Map.ts +272 -0
- package/src/services/updateMap.ts +9 -0
- package/tests/physic.spec.ts +454 -0
- package/tsconfig.json +8 -3
- package/vite.config.ts +21 -0
- package/CHANGELOG.md +0 -160
- package/LICENSE +0 -19
- package/browser/manifest.json +0 -7
- package/browser/rpg.common.js +0 -11357
- package/browser/rpg.common.umd.cjs +0 -11358
- package/lib/AbstractObject.d.ts +0 -322
- package/lib/AbstractObject.js +0 -872
- package/lib/AbstractObject.js.map +0 -1
- package/lib/Color.d.ts +0 -1
- package/lib/Color.js +0 -25
- package/lib/Color.js.map +0 -1
- package/lib/DefaultInput.d.ts +0 -2
- package/lib/DefaultInput.js +0 -26
- package/lib/DefaultInput.js.map +0 -1
- package/lib/Event.d.ts +0 -3
- package/lib/Event.js +0 -4
- package/lib/Event.js.map +0 -1
- package/lib/EventEmitter.d.ts +0 -10
- package/lib/EventEmitter.js +0 -61
- package/lib/EventEmitter.js.map +0 -1
- package/lib/Game.d.ts +0 -28
- package/lib/Game.js +0 -127
- package/lib/Game.js.map +0 -1
- package/lib/Hit.d.ts +0 -16
- package/lib/Hit.js +0 -65
- package/lib/Hit.js.map +0 -1
- package/lib/Inject.d.ts +0 -9
- package/lib/Inject.js +0 -17
- package/lib/Inject.js.map +0 -1
- package/lib/Logger.d.ts +0 -2
- package/lib/Logger.js +0 -7
- package/lib/Logger.js.map +0 -1
- package/lib/Map.d.ts +0 -174
- package/lib/Map.js +0 -263
- package/lib/Map.js.map +0 -1
- package/lib/Module.d.ts +0 -16
- package/lib/Module.js +0 -139
- package/lib/Module.js.map +0 -1
- package/lib/Player.d.ts +0 -26
- package/lib/Player.js +0 -19
- package/lib/Player.js.map +0 -1
- package/lib/Plugin.d.ts +0 -67
- package/lib/Plugin.js +0 -92
- package/lib/Plugin.js.map +0 -1
- package/lib/Scheduler.d.ts +0 -26
- package/lib/Scheduler.js +0 -90
- package/lib/Scheduler.js.map +0 -1
- package/lib/Shape.d.ts +0 -127
- package/lib/Shape.js +0 -261
- package/lib/Shape.js.map +0 -1
- package/lib/Utils.js +0 -181
- package/lib/Utils.js.map +0 -1
- package/lib/Vector2d.d.ts +0 -20
- package/lib/Vector2d.js +0 -63
- package/lib/Vector2d.js.map +0 -1
- package/lib/VirtualGrid.d.ts +0 -26
- package/lib/VirtualGrid.js +0 -68
- package/lib/VirtualGrid.js.map +0 -1
- package/lib/Worker.d.ts +0 -7
- package/lib/Worker.js +0 -13
- package/lib/Worker.js.map +0 -1
- package/lib/WorldMaps.d.ts +0 -105
- package/lib/WorldMaps.js +0 -184
- package/lib/WorldMaps.js.map +0 -1
- package/lib/gui/PrebuiltGui.js +0 -29
- package/lib/gui/PrebuiltGui.js.map +0 -1
- package/lib/index.d.ts +0 -25
- package/lib/index.js +0 -26
- package/lib/index.js.map +0 -1
- package/lib/transports/io.d.ts +0 -22
- package/lib/transports/io.js +0 -82
- package/lib/transports/io.js.map +0 -1
- package/lib/workers/move.d.ts +0 -1
- package/lib/workers/move.js +0 -57
- package/lib/workers/move.js.map +0 -1
- package/rpg.toml +0 -11
- package/src/AbstractObject.ts +0 -973
- package/src/Color.ts +0 -29
- package/src/DefaultInput.ts +0 -26
- package/src/Event.ts +0 -3
- package/src/EventEmitter.ts +0 -65
- package/src/Game.ts +0 -159
- package/src/Hit.ts +0 -70
- package/src/Inject.ts +0 -22
- package/src/Logger.ts +0 -7
- package/src/Map.ts +0 -335
- package/src/Module.ts +0 -144
- package/src/Plugin.ts +0 -100
- package/src/Scheduler.ts +0 -95
- package/src/Shape.ts +0 -302
- package/src/Vector2d.ts +0 -70
- package/src/VirtualGrid.ts +0 -78
- package/src/Worker.ts +0 -17
- package/src/WorldMaps.ts +0 -204
- package/src/transports/io.ts +0 -91
- package/src/workers/move.ts +0 -61
- /package/{lib/gui → dist}/PrebuiltGui.d.ts +0 -0
package/src/Map.ts
DELETED
|
@@ -1,335 +0,0 @@
|
|
|
1
|
-
import { HitObject } from './Hit'
|
|
2
|
-
import SAT from 'sat'
|
|
3
|
-
import Utils, { random, intersection, generateUID, isString } from './Utils'
|
|
4
|
-
import { RpgShape } from './Shape'
|
|
5
|
-
import { Hit } from './Hit'
|
|
6
|
-
import { VirtualGrid } from './VirtualGrid'
|
|
7
|
-
import { RpgCommonWorldMaps } from './WorldMaps'
|
|
8
|
-
import { TiledLayer, TiledLayerType, TiledMap, Layer, Tileset, Tile, TiledObject, TiledObjectClass, MapClass } from '@rpgjs/tiled'
|
|
9
|
-
import { Vector2d } from './Vector2d'
|
|
10
|
-
import { AbstractObject } from './AbstractObject'
|
|
11
|
-
import { RpgCommonGame } from './Game'
|
|
12
|
-
import { Observable, map, Subject, takeUntil, mergeMap, from, filter } from 'rxjs'
|
|
13
|
-
import { HitBox, MovingHitbox, Tick } from '@rpgjs/types'
|
|
14
|
-
|
|
15
|
-
const buffer = new Map()
|
|
16
|
-
const bufferClient = new Map()
|
|
17
|
-
|
|
18
|
-
export interface TileInfo {
|
|
19
|
-
tiles: Tile[]
|
|
20
|
-
hasCollision: boolean | undefined
|
|
21
|
-
isClimbable?: boolean | undefined
|
|
22
|
-
isOverlay: boolean | undefined
|
|
23
|
-
objectGroups: TiledObjectClass[],
|
|
24
|
-
tileIndex: number
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export interface LayerInfo {
|
|
28
|
-
type: string,
|
|
29
|
-
name: string,
|
|
30
|
-
opacity: number,
|
|
31
|
-
visible: boolean,
|
|
32
|
-
properties: any,
|
|
33
|
-
objects: HitObject[]
|
|
34
|
-
tiles: Tile[]
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
export class RpgCommonMap extends MapClass {
|
|
39
|
-
/**
|
|
40
|
-
* @title map id
|
|
41
|
-
* @readonly
|
|
42
|
-
* @prop {string} [id]
|
|
43
|
-
* @memberof Map
|
|
44
|
-
* */
|
|
45
|
-
readonly id: string
|
|
46
|
-
|
|
47
|
-
grid: VirtualGrid
|
|
48
|
-
gridShapes: VirtualGrid
|
|
49
|
-
gridTiles: VirtualGrid
|
|
50
|
-
|
|
51
|
-
get tileWidth() {
|
|
52
|
-
return this.tilewidth
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
get tileHeight() {
|
|
56
|
-
return this.tileheight
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* @title Layers of map
|
|
61
|
-
* @prop {object[]} [layers]
|
|
62
|
-
* @readonly
|
|
63
|
-
* @memberof Map
|
|
64
|
-
* @memberof RpgSceneMap
|
|
65
|
-
* */
|
|
66
|
-
|
|
67
|
-
/** @internal */
|
|
68
|
-
shapes: {
|
|
69
|
-
[shapeName: string]: RpgShape
|
|
70
|
-
} = {}
|
|
71
|
-
|
|
72
|
-
private worldMapParent: RpgCommonWorldMaps | undefined
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Retrieves the X position of the map in the world (0 if no world assigned)
|
|
76
|
-
*
|
|
77
|
-
* @title World X Position
|
|
78
|
-
* @prop {number} [worldX]
|
|
79
|
-
* @readonly
|
|
80
|
-
* @since 3.0.0-beta.8
|
|
81
|
-
* @memberof Map
|
|
82
|
-
* */
|
|
83
|
-
get worldX() {
|
|
84
|
-
return this.getInWorldMaps()?.getMapInfo(this.id)?.x || 0
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Retrieves the Y position of the map in the world (0 if no world assigned)
|
|
89
|
-
*
|
|
90
|
-
* @title World Y Position
|
|
91
|
-
* @prop {number} [worldY]
|
|
92
|
-
* @readonly
|
|
93
|
-
* @since 3.0.0-beta.8
|
|
94
|
-
* @memberof Map
|
|
95
|
-
* */
|
|
96
|
-
get worldY() {
|
|
97
|
-
return this.getInWorldMaps()?.getMapInfo(this.id)?.y || 0
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* Memorize the maps so you don't have to make a new request or open a file each time you load a map
|
|
102
|
-
*/
|
|
103
|
-
static get buffer() {
|
|
104
|
-
return buffer
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* In RPG mode, to avoid confusion with buffer, we have a new variable to memorize the maps
|
|
109
|
-
*/
|
|
110
|
-
static get bufferClient() {
|
|
111
|
-
return bufferClient
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
load(data: TiledMap) {
|
|
115
|
-
super.load(data)
|
|
116
|
-
this.gridTiles = new VirtualGrid(this.width, this.tileWidth, this.tileHeight)
|
|
117
|
-
this.grid = new VirtualGrid(this.width, this.tileWidth, this.tileHeight).zoom(10)
|
|
118
|
-
this.gridShapes = new VirtualGrid(this.width, this.tileWidth, this.tileHeight).zoom(20)
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* Create a shape dynamically on the map
|
|
123
|
-
*
|
|
124
|
-
* Object:
|
|
125
|
-
* - (number) x: Position X
|
|
126
|
-
* - (number) y: Position Y
|
|
127
|
-
* - (number) width: Width
|
|
128
|
-
* - (number) height: Height
|
|
129
|
-
* - (object) properties (optionnal):
|
|
130
|
-
* - (number) z: Position Z
|
|
131
|
-
* - (hexadecimal) color: Color (shared with client)
|
|
132
|
-
* - (boolean) collision
|
|
133
|
-
* - You can your own properties
|
|
134
|
-
*
|
|
135
|
-
* @title Create Shape
|
|
136
|
-
* @since 3.0.0-beta.3
|
|
137
|
-
* @method map.createShape(obj)
|
|
138
|
-
* @param {object} obj
|
|
139
|
-
* @returns {RpgShape}
|
|
140
|
-
* @memberof Map
|
|
141
|
-
*/
|
|
142
|
-
createShape(obj: HitObject): RpgShape {
|
|
143
|
-
const id = obj.name = (obj.name || generateUID()) as string
|
|
144
|
-
const shape = new RpgShape(obj as TiledObjectClass)
|
|
145
|
-
this.shapes[id] = shape
|
|
146
|
-
if (!shape.isShapePosition()) {
|
|
147
|
-
this.gridShapes.insertInCells(id, shape.getSizeBox(this.tileWidth))
|
|
148
|
-
}
|
|
149
|
-
// trick to sync with client
|
|
150
|
-
return this.shapes[id]
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
/**
|
|
154
|
-
* Delete a shape
|
|
155
|
-
*
|
|
156
|
-
* @title Delete Shape
|
|
157
|
-
* @method map.removeShape(name)
|
|
158
|
-
* @param {string} name Name of shape
|
|
159
|
-
* @returns {void}
|
|
160
|
-
* @memberof Map
|
|
161
|
-
*/
|
|
162
|
-
removeShape(name: string) {
|
|
163
|
-
// TODO: out players after delete shape
|
|
164
|
-
//this.shapes = this.shapes.filter(shape => shape.name != name)
|
|
165
|
-
delete this.shapes[name]
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
clearShapes() {
|
|
169
|
-
this.shapes = {}
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
/**
|
|
173
|
-
* Return all shapes on the map
|
|
174
|
-
*
|
|
175
|
-
* @title Get Shapes
|
|
176
|
-
* @method map.getShapes()
|
|
177
|
-
* @returns {RpgShape[]}
|
|
178
|
-
* @memberof Map
|
|
179
|
-
* @memberof RpgSceneMap
|
|
180
|
-
*/
|
|
181
|
-
getShapes(): RpgShape[] {
|
|
182
|
-
return Object.values(this.shapes)
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
/**
|
|
186
|
-
* Returns a shape by its name. Returns undefined is nothing is found
|
|
187
|
-
*
|
|
188
|
-
* @title Get Shape by name
|
|
189
|
-
* @method map.getShape(name)
|
|
190
|
-
* @param {string} name Name of shape
|
|
191
|
-
* @returns {RpgShape[] | undefined}
|
|
192
|
-
* @memberof Map
|
|
193
|
-
* @memberof RpgSceneMap
|
|
194
|
-
*/
|
|
195
|
-
getShape(name: string): RpgShape | undefined {
|
|
196
|
-
return this.getShapes().find(shape => shape.name == name)
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
getPositionByShape(filter: (shape: RpgShape) => {}): { x: number, y: number, z: number } | null {
|
|
200
|
-
const startsFind = this.getShapes().filter(filter)
|
|
201
|
-
if (startsFind.length) {
|
|
202
|
-
const start = startsFind[random(0, startsFind.length-1)]
|
|
203
|
-
return { x: start.hitbox.x, y: start.hitbox.y, z: start.properties.z * this.zTileHeight || 0 }
|
|
204
|
-
}
|
|
205
|
-
return null
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
/**
|
|
209
|
-
* Get tile and verify collision with hitbox
|
|
210
|
-
* @param hitbox
|
|
211
|
-
* @param x
|
|
212
|
-
* @param y
|
|
213
|
-
* @param z
|
|
214
|
-
* @returns TileInfo
|
|
215
|
-
*/
|
|
216
|
-
getTile(hitbox, x: number, y: number, z: [number, number] = [0, 0]): TileInfo {
|
|
217
|
-
const tile = {...this.getTileByPosition(x, y, z)}
|
|
218
|
-
const tilePos = this.getTileOriginPosition(x, y)
|
|
219
|
-
if (tile.objectGroups) {
|
|
220
|
-
for (let object of tile.objectGroups) {
|
|
221
|
-
const hit = Hit.getHitbox(object, {
|
|
222
|
-
x: tilePos.x,
|
|
223
|
-
y: tilePos.y
|
|
224
|
-
})
|
|
225
|
-
if (hit.type) {
|
|
226
|
-
const collided = Hit.testPolyCollision(hit.type, hit.hitbox, hitbox)
|
|
227
|
-
if (collided) {
|
|
228
|
-
tile.hasCollision = true
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
return tile
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
/**
|
|
237
|
-
* Assign the map to a world
|
|
238
|
-
|
|
239
|
-
* @title Assign the map to a world
|
|
240
|
-
* @method map.setInWorldMaps(name)
|
|
241
|
-
* @param {RpgWorldMaps} worldMap world maps
|
|
242
|
-
* @since 3.0.0-beta.8
|
|
243
|
-
* @memberof Map
|
|
244
|
-
*/
|
|
245
|
-
setInWorldMaps(worldMap: RpgCommonWorldMaps) {
|
|
246
|
-
this.worldMapParent = worldMap
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
/**
|
|
250
|
-
* Remove this map from the world
|
|
251
|
-
* @title Remove this map from the world
|
|
252
|
-
* @method map.removeFromWorldMaps()
|
|
253
|
-
* @returns {boolean | undefined}
|
|
254
|
-
* @since 3.0.0-beta.8
|
|
255
|
-
* @memberof Map
|
|
256
|
-
*/
|
|
257
|
-
removeFromWorldMaps(): boolean | undefined {
|
|
258
|
-
return this.worldMapParent?.removeMap(this.id)
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
/**
|
|
262
|
-
* Recover the world attached to this map (`undefined` if no world attached)
|
|
263
|
-
|
|
264
|
-
* @title Get attached World
|
|
265
|
-
* @method map.getInWorldMaps()
|
|
266
|
-
* @return {RpgCommonWorldMaps | undefined}
|
|
267
|
-
* @since 3.0.0-beta.8
|
|
268
|
-
* @memberof Map
|
|
269
|
-
*/
|
|
270
|
-
getInWorldMaps(): RpgCommonWorldMaps | undefined {
|
|
271
|
-
return this.worldMapParent
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
boundingMap(nextPosition: Vector2d, hitbox: SAT): { bounding: boolean, nextPosition: Vector2d } | null {
|
|
275
|
-
let bounding = false
|
|
276
|
-
if (nextPosition.x < 0) {
|
|
277
|
-
nextPosition.x = 0
|
|
278
|
-
bounding = true
|
|
279
|
-
}
|
|
280
|
-
else if (nextPosition.y < 0) {
|
|
281
|
-
nextPosition.y = 0
|
|
282
|
-
bounding = true
|
|
283
|
-
}
|
|
284
|
-
else if (nextPosition.x > this.widthPx - hitbox.w) {
|
|
285
|
-
nextPosition.x = this.widthPx - hitbox.w
|
|
286
|
-
bounding = true
|
|
287
|
-
}
|
|
288
|
-
else if (nextPosition.y > this.heightPx - hitbox.h) {
|
|
289
|
-
nextPosition.y = this.heightPx - hitbox.h
|
|
290
|
-
bounding = true
|
|
291
|
-
}
|
|
292
|
-
return {
|
|
293
|
-
bounding,
|
|
294
|
-
nextPosition
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
_createMovingHitbox<T extends RpgCommonGame>(
|
|
299
|
-
gameEngine: T,
|
|
300
|
-
tick$: Observable<Tick>,
|
|
301
|
-
mapId: string,
|
|
302
|
-
hitboxes: Pick<HitBox, 'width' | 'height' | 'x' | 'y'>[],
|
|
303
|
-
options: MovingHitbox = {}
|
|
304
|
-
): Observable<AbstractObject> {
|
|
305
|
-
const object = new AbstractObject(gameEngine, Utils.generateUID())
|
|
306
|
-
object.disableVirtualGrid = true
|
|
307
|
-
object.map = mapId
|
|
308
|
-
object.speed = options.speed ?? 1
|
|
309
|
-
let i = 0
|
|
310
|
-
let frame = 0
|
|
311
|
-
const destroyHitbox$ = new Subject<AbstractObject>()
|
|
312
|
-
return tick$.pipe(
|
|
313
|
-
takeUntil(destroyHitbox$),
|
|
314
|
-
filter(() => {
|
|
315
|
-
frame++
|
|
316
|
-
return frame % object.speed == 0
|
|
317
|
-
}),
|
|
318
|
-
map(() => {
|
|
319
|
-
const hitbox = hitboxes[i]
|
|
320
|
-
if (!hitbox) {
|
|
321
|
-
destroyHitbox$.next(object)
|
|
322
|
-
destroyHitbox$.complete()
|
|
323
|
-
return object
|
|
324
|
-
}
|
|
325
|
-
object.position.x = hitbox.x
|
|
326
|
-
object.position.y = hitbox.y
|
|
327
|
-
object.setHitbox(hitbox.width, hitbox.height)
|
|
328
|
-
i++
|
|
329
|
-
return object
|
|
330
|
-
}),
|
|
331
|
-
mergeMap((object) => from(object.isCollided(object.position, { allSearch: true }))),
|
|
332
|
-
map(() => object)
|
|
333
|
-
)
|
|
334
|
-
}
|
|
335
|
-
}
|
package/src/Module.ts
DELETED
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
import { RpgPlugin, HookServer, HookClient } from './Plugin'
|
|
2
|
-
import { isArray, isClass, isFunction, isPromise } from './Utils'
|
|
3
|
-
import { warning } from './Logger'
|
|
4
|
-
|
|
5
|
-
enum Side {
|
|
6
|
-
Server = 'server',
|
|
7
|
-
Client = 'client'
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
type ModuleSide = {
|
|
11
|
-
client?: any,
|
|
12
|
-
server?: any
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export type ModuleType = ModuleSide | [ModuleSide, {
|
|
16
|
-
client?: any,
|
|
17
|
-
server?: any
|
|
18
|
-
}]
|
|
19
|
-
|
|
20
|
-
export function RpgModule<T>(options: T) {
|
|
21
|
-
return (target) => {
|
|
22
|
-
if ((options as any).hooks) {
|
|
23
|
-
target.hooks = (options as any).hooks
|
|
24
|
-
}
|
|
25
|
-
for (let key in options) {
|
|
26
|
-
target.prototype[key] = options[key]
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export async function loadModules(modules, obj, middleware?: Function): Promise<{ playerProps: any }> {
|
|
32
|
-
const { side, relations } = obj
|
|
33
|
-
let playerProps = {}
|
|
34
|
-
let hooks = {}
|
|
35
|
-
|
|
36
|
-
const getModuleClass = (module) => {
|
|
37
|
-
if (!module) return null
|
|
38
|
-
let plug: any = []
|
|
39
|
-
if (!isArray(module)) {
|
|
40
|
-
plug = [module]
|
|
41
|
-
}
|
|
42
|
-
else {
|
|
43
|
-
plug = module
|
|
44
|
-
}
|
|
45
|
-
const [moduleClassSides, options] = plug
|
|
46
|
-
const moduleClass = moduleClassSides[side]
|
|
47
|
-
if (!moduleClass) return null
|
|
48
|
-
return {
|
|
49
|
-
moduleClass,
|
|
50
|
-
options
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
for (let module of modules) {
|
|
55
|
-
const moduleObject = getModuleClass(module)
|
|
56
|
-
if (!moduleObject) continue
|
|
57
|
-
const { moduleClass } = moduleObject
|
|
58
|
-
if (moduleClass.hooks) {
|
|
59
|
-
for (let key in moduleClass.hooks) {
|
|
60
|
-
if (!hooks[key]) hooks[key] = []
|
|
61
|
-
hooks[key] = [
|
|
62
|
-
...hooks[key],
|
|
63
|
-
...moduleClass.hooks[key]
|
|
64
|
-
]
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
for (let module of modules) {
|
|
70
|
-
const moduleObject = getModuleClass(module)
|
|
71
|
-
if (!moduleObject) continue
|
|
72
|
-
const { moduleClass, options } = moduleObject
|
|
73
|
-
let mod
|
|
74
|
-
if (options && side == Side.Client && options[Side.Server]) {
|
|
75
|
-
warning(`Data that may be sensitive (normally visible only on the server side) are made optional and visible on the client side.\nInstead, import the configuration with the server! flag into an import. Example: \n\nimport config from 'server!./config\n\n'`, options[Side.Server])
|
|
76
|
-
}
|
|
77
|
-
if (options && !isClass(moduleClass) && isFunction(moduleClass)) {
|
|
78
|
-
mod = new (moduleClass(options[side]))()
|
|
79
|
-
}
|
|
80
|
-
else if (isClass(moduleClass)) {
|
|
81
|
-
mod = new moduleClass()
|
|
82
|
-
}
|
|
83
|
-
else {
|
|
84
|
-
mod = moduleClass
|
|
85
|
-
}
|
|
86
|
-
if (middleware) {
|
|
87
|
-
mod = middleware(mod)
|
|
88
|
-
if (isPromise(mod)) {
|
|
89
|
-
mod = await mod
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
const { imports, maps, spritesheets, sounds, gui, scenes, engine, database, worldMaps, scalability, events } = mod
|
|
93
|
-
if (imports) {
|
|
94
|
-
await loadModules(imports, obj)
|
|
95
|
-
}
|
|
96
|
-
if (maps) {
|
|
97
|
-
RpgPlugin.on(HookServer.AddMap, () => maps)
|
|
98
|
-
}
|
|
99
|
-
if (events) {
|
|
100
|
-
RpgPlugin.on(HookServer.AddEvent, () => events)
|
|
101
|
-
}
|
|
102
|
-
if (worldMaps) {
|
|
103
|
-
RpgPlugin.on(HookServer.AddWorldMaps, () => worldMaps)
|
|
104
|
-
}
|
|
105
|
-
if (database) {
|
|
106
|
-
RpgPlugin.on(HookServer.AddDatabase, () => database)
|
|
107
|
-
}
|
|
108
|
-
if (spritesheets) {
|
|
109
|
-
RpgPlugin.on(HookClient.AddSpriteSheet, () => spritesheets)
|
|
110
|
-
}
|
|
111
|
-
if (sounds) {
|
|
112
|
-
RpgPlugin.on(HookClient.AddSound, () => sounds)
|
|
113
|
-
}
|
|
114
|
-
if (gui) {
|
|
115
|
-
RpgPlugin.on(HookClient.AddGui, () => gui)
|
|
116
|
-
}
|
|
117
|
-
const player = side == Side.Server ? mod.player : mod.sprite
|
|
118
|
-
const loadRelations = (hook, relationName) => {
|
|
119
|
-
if (!hook) return
|
|
120
|
-
for (let method in relations[relationName]) {
|
|
121
|
-
const hookName = relations[relationName][method]
|
|
122
|
-
if (hook[method]) RpgPlugin.on(hookName, hook[method])
|
|
123
|
-
}
|
|
124
|
-
if (hooks[relationName]) {
|
|
125
|
-
for (let methodName of hooks[relationName]) {
|
|
126
|
-
const hookName = side + '.' + relationName + '.' + methodName
|
|
127
|
-
RpgPlugin.customHooks[hookName] = true
|
|
128
|
-
if (hook[methodName]) RpgPlugin.on(hookName, hook[methodName])
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
loadRelations(player, 'player')
|
|
133
|
-
if (player && player.props) {
|
|
134
|
-
playerProps = Object.assign(playerProps, player.props)
|
|
135
|
-
}
|
|
136
|
-
loadRelations(engine, 'engine')
|
|
137
|
-
if (scalability) loadRelations(scalability._hooks, 'scalability')
|
|
138
|
-
if (scenes) loadRelations(scenes.map, 'sceneMap')
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
return {
|
|
142
|
-
playerProps
|
|
143
|
-
}
|
|
144
|
-
}
|
package/src/Plugin.ts
DELETED
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
import { EventEmitter } from './EventEmitter'
|
|
2
|
-
import { isArray } from './Utils'
|
|
3
|
-
|
|
4
|
-
type PluginFunction = (obj: any, options?: any) => void
|
|
5
|
-
type PluginSides = { client: null | PluginFunction, server: null | PluginFunction }
|
|
6
|
-
export type Plugin = PluginSides | [PluginSides, any]
|
|
7
|
-
|
|
8
|
-
export enum HookServer {
|
|
9
|
-
Start = 'Server.Start',
|
|
10
|
-
Step = "Server.Step",
|
|
11
|
-
Auth = "Server.Auth",
|
|
12
|
-
PlayerConnected = 'Server.onConnected',
|
|
13
|
-
PlayerDisconnected = 'Server.onDisconnected',
|
|
14
|
-
AddMap = 'Server.AddMap',
|
|
15
|
-
AddEvent = 'Server.AddEvent',
|
|
16
|
-
AddWorldMaps = 'Server.AddWorldMaps',
|
|
17
|
-
AddDatabase = 'Server.AddDatabase',
|
|
18
|
-
PlayerInput = 'Server.onInput',
|
|
19
|
-
PlayerJoinMap = 'Server.onJoinMap',
|
|
20
|
-
PlayerLeaveMap = 'Server.onLeaveMap',
|
|
21
|
-
PlayerLevelUp = 'Server.onLevelUp',
|
|
22
|
-
PlayerDead = 'Server.onDead',
|
|
23
|
-
PlayerInShape = 'Server.onInShape',
|
|
24
|
-
PlayerOutShape = 'Server.onOutShape',
|
|
25
|
-
PlayerMove = 'Server.PlayerMove',
|
|
26
|
-
PlayerCanChangeMap = 'Server.PlayerCanChangeMap',
|
|
27
|
-
ScalabilityPlayerConnected = 'Server.ScalabilityPlayerConnected',
|
|
28
|
-
ScalabilityChangeServer = 'Server.ScalabilityChangeServer'
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export enum HookClient {
|
|
32
|
-
Start = 'Client.Start',
|
|
33
|
-
Step = 'Client.Step',
|
|
34
|
-
Connected = 'Client.Connected',
|
|
35
|
-
Disconnect = 'Client.Disconnect',
|
|
36
|
-
ConnectedError = 'Client.ConnectedError',
|
|
37
|
-
|
|
38
|
-
AddSpriteSheet = 'Client.AddSpriteSheet',
|
|
39
|
-
AddGui = 'Client.AddGui',
|
|
40
|
-
AddSound = 'Client.AddSound',
|
|
41
|
-
SendInput = 'Client.SendInput',
|
|
42
|
-
|
|
43
|
-
BeforeSceneLoading = 'Client.BeforeSceneLoading',
|
|
44
|
-
AfterSceneLoading = 'Client.AfterSceneLoading',
|
|
45
|
-
SceneMapLoading = 'Client.SceneMapLoading',
|
|
46
|
-
SceneAddSprite = 'Client.SceneAddSprite',
|
|
47
|
-
SceneOnChanges = 'Client.SceneOnChanges',
|
|
48
|
-
SceneDraw = 'Client.SceneDraw',
|
|
49
|
-
SceneRemoveSprite = 'Client.SceneRemoveSprite',
|
|
50
|
-
|
|
51
|
-
AddSprite = 'Client.AddSprite',
|
|
52
|
-
RemoveSprite = 'Client.RemoveSprite',
|
|
53
|
-
UpdateSprite = 'Client.UpdateSprite',
|
|
54
|
-
ChangesSprite = 'Client.ChangesSprite',
|
|
55
|
-
WindowResize = 'Client.WindowResize',
|
|
56
|
-
SpriteMove = 'Client.SpriteMove'
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* @deprecated
|
|
61
|
-
*/
|
|
62
|
-
export class PluginSystem extends EventEmitter {
|
|
63
|
-
customHooks: {
|
|
64
|
-
[key: string]: boolean
|
|
65
|
-
} = {}
|
|
66
|
-
|
|
67
|
-
customHookExists(name: string): boolean {
|
|
68
|
-
return this.customHooks[name]
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
private loadPlugins(plugins: Plugin[], shared: any, type: string) {
|
|
72
|
-
if (!plugins) return
|
|
73
|
-
for (let plugin of plugins) {
|
|
74
|
-
if (!plugin) continue
|
|
75
|
-
let plug: any = []
|
|
76
|
-
if (!isArray(plugin)) {
|
|
77
|
-
plug = [plugin]
|
|
78
|
-
}
|
|
79
|
-
else {
|
|
80
|
-
plug = plugin
|
|
81
|
-
}
|
|
82
|
-
const [side, options] = plug
|
|
83
|
-
if (!side[type]) continue
|
|
84
|
-
side[type]({
|
|
85
|
-
RpgPlugin,
|
|
86
|
-
...shared
|
|
87
|
-
}, options)
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
loadServerPlugins(plugins, shared) {
|
|
92
|
-
this.loadPlugins(plugins, shared, 'server')
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
loadClientPlugins(plugins, shared) {
|
|
96
|
-
this.loadPlugins(plugins, shared, 'client')
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
export const RpgPlugin = new PluginSystem()
|
package/src/Scheduler.ts
DELETED
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
import { Tick } from '@rpgjs/types';
|
|
2
|
-
import { BehaviorSubject, Observable } from 'rxjs';
|
|
3
|
-
import { EventEmitter } from './EventEmitter';
|
|
4
|
-
import Utils from './Utils';
|
|
5
|
-
|
|
6
|
-
export class Scheduler extends EventEmitter {
|
|
7
|
-
private maxFps?: number
|
|
8
|
-
private fps: number = 60
|
|
9
|
-
private deltaTime: number = 0
|
|
10
|
-
public frame: number = 0
|
|
11
|
-
private timestamp: number = 0
|
|
12
|
-
private requestedDelay: number = 0
|
|
13
|
-
private lastTimestamp: number = 0
|
|
14
|
-
private _tick: BehaviorSubject<Tick> = new BehaviorSubject({
|
|
15
|
-
timestamp: 0,
|
|
16
|
-
deltaTime: 0,
|
|
17
|
-
frame: 0,
|
|
18
|
-
deltaRatio: 0
|
|
19
|
-
})
|
|
20
|
-
private _stop: boolean = false
|
|
21
|
-
|
|
22
|
-
get tick(): Observable<Tick> {
|
|
23
|
-
return this._tick.asObservable()
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
nextTick(timestamp: number) {
|
|
27
|
-
this.lastTimestamp = this.lastTimestamp || this.timestamp // first
|
|
28
|
-
this.deltaTime = Utils.preciseNow() - this.timestamp
|
|
29
|
-
this.timestamp = timestamp
|
|
30
|
-
this._tick.next({
|
|
31
|
-
timestamp: this.timestamp,
|
|
32
|
-
deltaTime: this.deltaTime,
|
|
33
|
-
frame: this.frame,
|
|
34
|
-
deltaRatio: ~~this.deltaTime / ~~Utils.fps2ms(this.fps)
|
|
35
|
-
})
|
|
36
|
-
this.lastTimestamp = this.timestamp
|
|
37
|
-
this.frame++
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* start the schedule
|
|
42
|
-
* @return {Scheduler} returns this scheduler instance
|
|
43
|
-
*/
|
|
44
|
-
start(options: {
|
|
45
|
-
maxFps?: number
|
|
46
|
-
fps?: number,
|
|
47
|
-
delay?: number
|
|
48
|
-
}) {
|
|
49
|
-
if (options.maxFps) this.maxFps = options.maxFps
|
|
50
|
-
if (options.fps) this.fps = options.fps
|
|
51
|
-
if (options.delay) this.requestedDelay = options.delay
|
|
52
|
-
const requestAnimationFrame = (fn: (timestamp: number) => void) => {
|
|
53
|
-
if (Utils.isBrowser()) {
|
|
54
|
-
window.requestAnimationFrame(fn.bind(this))
|
|
55
|
-
}
|
|
56
|
-
else {
|
|
57
|
-
setTimeout(() => {
|
|
58
|
-
this.requestedDelay = 0
|
|
59
|
-
fn(Utils.preciseNow())
|
|
60
|
-
}, Utils.fps2ms(this.fps) + this.requestedDelay)
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
if (!this.maxFps) {
|
|
65
|
-
const loop = (timestamp: number) => {
|
|
66
|
-
requestAnimationFrame(loop)
|
|
67
|
-
this.nextTick(timestamp)
|
|
68
|
-
}
|
|
69
|
-
requestAnimationFrame(loop)
|
|
70
|
-
}
|
|
71
|
-
else {
|
|
72
|
-
const msInterval = Utils.fps2ms(this.maxFps)
|
|
73
|
-
let now = Utils.preciseNow()
|
|
74
|
-
let then = Utils.preciseNow()
|
|
75
|
-
const loop = (timestamp: number) => {
|
|
76
|
-
if (this._stop) return
|
|
77
|
-
requestAnimationFrame(loop)
|
|
78
|
-
now = Utils.preciseNow()
|
|
79
|
-
const elapsed = now - then
|
|
80
|
-
if (elapsed > msInterval) {
|
|
81
|
-
then = now - (elapsed % msInterval)
|
|
82
|
-
this.nextTick(timestamp)
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
requestAnimationFrame(loop)
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
return this;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
stop() {
|
|
92
|
-
this._stop = true
|
|
93
|
-
this._tick.complete()
|
|
94
|
-
}
|
|
95
|
-
}
|