@antha/entity-2d 0.17.0 → 0.18.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 +3 -3
- package/dist/antha-entity-2d.mod.d.ts +182 -12
- package/dist/antha-entity-2d.mod.js +79 -38
- package/dist/entity.d.ts +46 -4
- package/dist/entity.js +48 -3
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/package.json +10 -7
- package/dist/entity-suite.d.ts +0 -228
- package/dist/entity-suite.js +0 -79
package/README.md
CHANGED
|
@@ -15,13 +15,13 @@ npm i @antha/entity-2d
|
|
|
15
15
|
```TypeScript
|
|
16
16
|
import {AnthaEngine, defineAnthaMod} from '@antha/engine';
|
|
17
17
|
import {createAnthaGraphics2dMod} from '@antha/graphics-2d';
|
|
18
|
-
import {type AnthaEntity2dModState,
|
|
18
|
+
import {type AnthaEntity2dModState, createAnthaEntity2dSuite} from '@antha/entity-2d';
|
|
19
19
|
|
|
20
20
|
type GameState = AnthaEntity2dModState<{
|
|
21
21
|
hasCreatedScoreEntity: boolean;
|
|
22
22
|
}>;
|
|
23
23
|
|
|
24
|
-
const {defineLogicEntity,
|
|
24
|
+
const {defineLogicEntity, updateEntitiesMod} = createAnthaEntity2dSuite<{
|
|
25
25
|
hasCreatedScoreEntity: boolean;
|
|
26
26
|
}>();
|
|
27
27
|
|
|
@@ -38,7 +38,7 @@ const engine = new AnthaEngine<GameState>({
|
|
|
38
38
|
},
|
|
39
39
|
mods: [
|
|
40
40
|
createAnthaGraphics2dMod(),
|
|
41
|
-
|
|
41
|
+
updateEntitiesMod,
|
|
42
42
|
defineAnthaMod<GameState>({
|
|
43
43
|
modName: 'game-logic',
|
|
44
44
|
async execute({state}) {
|
|
@@ -1,36 +1,206 @@
|
|
|
1
1
|
import { type AnthaAssetModState } from '@antha/asset';
|
|
2
|
-
import { type
|
|
2
|
+
import { type ModTrigger } from '@antha/engine';
|
|
3
3
|
import { type AnthaGraphics2dModState } from '@antha/graphics-2d';
|
|
4
|
-
import { type AnyObject, type PartialWithUndefined } from '@augment-vir/common';
|
|
5
|
-
import { type
|
|
4
|
+
import { type AnyObject, type Constructor, type PartialWithUndefined } from '@augment-vir/common';
|
|
5
|
+
import { type Shape } from 'object-shape-tester';
|
|
6
|
+
import { BaseEntity2d, EntityStore2d, ViewEntity2d, type BaseEntityAssetDefinitions, type EntityCollisionDefinition, type EntityStore2dConstructorParams, type ParamsMap, type StaticEntity2dParts } from './entity.js';
|
|
6
7
|
/**
|
|
7
|
-
*
|
|
8
|
+
* Params for both `defineEntity` and `defineLogicEntity`.
|
|
9
|
+
*
|
|
10
|
+
* @category Internal
|
|
11
|
+
*/
|
|
12
|
+
export type DefineEntity2dArgs<ParamsShape extends Shape | undefined, EntityAssets extends BaseEntityAssetDefinitions | undefined> = {
|
|
13
|
+
/** Entity classes this entity observes collisions with. Omit to observe none. */
|
|
14
|
+
collidesWith?: EntityCollisionDefinition | undefined;
|
|
15
|
+
/**
|
|
16
|
+
* This key is used for deserialization of entities to track which class needs to be
|
|
17
|
+
* constructed. Do not use duplicate key strings across multiple entity classes.
|
|
18
|
+
*/
|
|
19
|
+
key: string;
|
|
20
|
+
/**
|
|
21
|
+
* This should contain all parameters necessary to reconstruct this entity from scratch so it
|
|
22
|
+
* can be serialized, sent across the network in JSON format, then reconstructed on another
|
|
23
|
+
* device (for multiplayer support).
|
|
24
|
+
*
|
|
25
|
+
* Make sure to include {@link entityPositionParamsShape} as part of the shape if you want to
|
|
26
|
+
* include entity position parameters.
|
|
27
|
+
*/
|
|
28
|
+
paramsShape?: ParamsShape;
|
|
29
|
+
/**
|
|
30
|
+
* A mapping of the entity's params object (defined by {@link DefineEntity2dArgs.paramsShape})
|
|
31
|
+
* keys to hitbox and/or view properties.
|
|
32
|
+
*
|
|
33
|
+
* Use `standardParamsMap` to automatically map the params `x` and `y` in `paramsShape` to both
|
|
34
|
+
* the entity's hitbox x/y and the entity's view x/y.
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
*
|
|
38
|
+
* ```ts
|
|
39
|
+
* const customMapping = {
|
|
40
|
+
* paramsShape: defineShape({
|
|
41
|
+
* left: -1,
|
|
42
|
+
* top: -1,
|
|
43
|
+
* }),
|
|
44
|
+
* paramsMap: {
|
|
45
|
+
* hitbox: {
|
|
46
|
+
* x: 'left', // maps `left` from `paramsShape` to the entity's hitbox.x
|
|
47
|
+
* y: 'top', // maps `top` from `paramsShape` to the entity's hitbox.y
|
|
48
|
+
* },
|
|
49
|
+
* view: {
|
|
50
|
+
* x: 'left', // maps `left` from `paramsShape` to the entity's view.x
|
|
51
|
+
* y: 'top', // maps `top` from `paramsShape` to the entity's view.y
|
|
52
|
+
* },
|
|
53
|
+
* },
|
|
54
|
+
* };
|
|
55
|
+
* ```
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
*
|
|
59
|
+
* ```ts
|
|
60
|
+
* const standardMapping = {
|
|
61
|
+
* paramsShape: defineShape({
|
|
62
|
+
* left: -1,
|
|
63
|
+
* top: -1,
|
|
64
|
+
* }),
|
|
65
|
+
* paramsMap: standardParamsMap, // use the standard x/y mapping
|
|
66
|
+
* };
|
|
67
|
+
* ```
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
*
|
|
71
|
+
* ```ts
|
|
72
|
+
* const undefinedMapping = {
|
|
73
|
+
* paramsShape: defineShape({
|
|
74
|
+
* left: -1,
|
|
75
|
+
* top: -1,
|
|
76
|
+
* }),
|
|
77
|
+
* paramsMap: undefined, // no mapping at all
|
|
78
|
+
* };
|
|
79
|
+
* ```
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
*
|
|
83
|
+
* ```ts
|
|
84
|
+
* const omittedMapping = {
|
|
85
|
+
* paramsShape: defineShape({
|
|
86
|
+
* left: -1,
|
|
87
|
+
* top: -1,
|
|
88
|
+
* }),
|
|
89
|
+
* // no mapping at all
|
|
90
|
+
* };
|
|
91
|
+
* ```
|
|
92
|
+
*
|
|
93
|
+
* @default undefined // no mapping
|
|
94
|
+
*/
|
|
95
|
+
paramsMap?: ParamsMap<NoInfer<ParamsShape> extends Shape ? NoInfer<ParamsShape>['runtimeType'] : undefined> | undefined;
|
|
96
|
+
assets?: EntityAssets;
|
|
97
|
+
};
|
|
98
|
+
/**
|
|
99
|
+
* ========================
|
|
100
|
+
*
|
|
101
|
+
* # View Entity
|
|
102
|
+
*
|
|
103
|
+
* Types for entity definitions that have a view.
|
|
104
|
+
*
|
|
105
|
+
* ========================
|
|
106
|
+
*/
|
|
107
|
+
/**
|
|
108
|
+
* The constructor output of {@link DefinedViewEntity2dConstructor}.
|
|
109
|
+
*
|
|
110
|
+
* @category Internal
|
|
111
|
+
*/
|
|
112
|
+
export type DefinedViewEntity2dInstance<State extends AnyObject, ParamsShape extends Shape<Record<string, any>> | undefined, EntityAssets extends BaseEntityAssetDefinitions | undefined> = ViewEntity2d<State, ParamsShape extends Shape ? ParamsShape['runtimeType'] : undefined, EntityAssets>;
|
|
113
|
+
/**
|
|
114
|
+
* Output of {@link DefineViewEntity2d}.
|
|
115
|
+
*
|
|
116
|
+
* @category Internal
|
|
117
|
+
*/
|
|
118
|
+
export type DefinedViewEntity2dConstructor<State extends AnyObject, ParamsShape extends Shape | undefined, EntityAssets extends BaseEntityAssetDefinitions | undefined> = Constructor<DefinedViewEntity2dInstance<State, ParamsShape, EntityAssets>, ConstructorParameters<typeof ViewEntity2d<State, ParamsShape extends Shape ? ParamsShape['runtimeType'] : undefined>>> & StaticEntity2dParts<State, ParamsShape>;
|
|
119
|
+
/**
|
|
120
|
+
* Type for `defineEntity`.
|
|
121
|
+
*
|
|
122
|
+
* @category Internal
|
|
123
|
+
*/
|
|
124
|
+
export type DefineViewEntity2d<State extends AnyObject> = <const ParamsShape extends Shape | undefined, const EntityAssets extends BaseEntityAssetDefinitions | undefined>(params: DefineEntity2dArgs<ParamsShape, EntityAssets>) => DefinedViewEntity2dConstructor<State, NoInfer<ParamsShape>, NoInfer<EntityAssets>> & StaticEntity2dParts<NoInfer<State>, NoInfer<ParamsShape>>;
|
|
125
|
+
/**
|
|
126
|
+
* ========================
|
|
127
|
+
*
|
|
128
|
+
* # Logic Entity
|
|
129
|
+
*
|
|
130
|
+
* Types for entity definitions that don't have a view. The only difference between these types and
|
|
131
|
+
* the view types are that this uses `BaseEntity2d` instead of `ViewEntity2d`.
|
|
132
|
+
*
|
|
133
|
+
* ========================
|
|
134
|
+
*/
|
|
135
|
+
/**
|
|
136
|
+
* The constructor output of {@link DefinedLogicEntity2dConstructor}.
|
|
137
|
+
*
|
|
138
|
+
* @category Internal
|
|
139
|
+
*/
|
|
140
|
+
export type DefinedLogicEntity2dInstance<State extends AnyObject, ParamsShape extends Shape | undefined> = BaseEntity2d<State, ParamsShape extends Shape ? ParamsShape['runtimeType'] : undefined>;
|
|
141
|
+
/**
|
|
142
|
+
* Output of {@link DefineLogicEntity2d}.
|
|
143
|
+
*
|
|
144
|
+
* @category Internal
|
|
145
|
+
*/
|
|
146
|
+
export type DefinedLogicEntity2dConstructor<State extends AnyObject, ParamsShape extends Shape | undefined> = Constructor<DefinedLogicEntity2dInstance<State, ParamsShape>, ConstructorParameters<typeof BaseEntity2d<State, ParamsShape extends Shape ? ParamsShape['runtimeType'] : undefined>>> & StaticEntity2dParts<State, ParamsShape>;
|
|
147
|
+
/**
|
|
148
|
+
* Type for `defineLogicEntity`.
|
|
149
|
+
*
|
|
150
|
+
* @category Internal
|
|
151
|
+
*/
|
|
152
|
+
export type DefineLogicEntity2d<State extends AnyObject> = <const ParamsShape extends Shape | undefined, const EntityAssets extends BaseEntityAssetDefinitions | undefined>(params: DefineEntity2dArgs<ParamsShape, EntityAssets>) => DefinedLogicEntity2dConstructor<NoInfer<State>, NoInfer<ParamsShape>>;
|
|
153
|
+
/**
|
|
154
|
+
* State for {@link createAnthaEntity2dSuite}.
|
|
8
155
|
*
|
|
9
156
|
* @category Internal
|
|
10
157
|
*/
|
|
11
158
|
export type AnthaEntity2dModState<State extends AnyObject = AnyObject> = {
|
|
12
159
|
entityStore: EntityStore2d<Partial<AnthaEntity2dModState<State>>>;
|
|
13
160
|
/** If true, entity updates and collision checks are skipped. */
|
|
14
|
-
|
|
161
|
+
disableEntityUpdate: boolean;
|
|
162
|
+
/** If true, entity renders are skipped. */
|
|
163
|
+
disableEntityRender: boolean;
|
|
15
164
|
/** If `true`, hit boxes are visually rendered for debugging purposes. */
|
|
16
|
-
|
|
165
|
+
showHitboxDebug: boolean;
|
|
17
166
|
} & State & AnthaGraphics2dModState & AnthaAssetModState;
|
|
18
167
|
/**
|
|
19
|
-
* Options for {@link
|
|
168
|
+
* Options for {@link createAnthaEntity2dSuite}.
|
|
20
169
|
*
|
|
21
170
|
* @category Internal
|
|
22
171
|
*/
|
|
23
172
|
export type AnthaEntity2dModOptions = PartialWithUndefined<EntityStore2dConstructorParams & {
|
|
24
173
|
debug: boolean;
|
|
174
|
+
/**
|
|
175
|
+
* The entity update mod's trigger. If left undefined, enabled entity updates will run on
|
|
176
|
+
* every engine tick.
|
|
177
|
+
*/
|
|
178
|
+
updateTrigger: ModTrigger;
|
|
179
|
+
/**
|
|
180
|
+
* If `true`, the `updateEntitiesMod` does not update entity data and collision state.
|
|
181
|
+
*
|
|
182
|
+
* @default false
|
|
183
|
+
*/
|
|
184
|
+
disableEntityUpdate: boolean;
|
|
185
|
+
/**
|
|
186
|
+
* If `true`, the `updateEntitiesMod` does not update transient entity render state.
|
|
187
|
+
*
|
|
188
|
+
* @default false
|
|
189
|
+
*/
|
|
190
|
+
disableEntityRender: boolean;
|
|
25
191
|
}>;
|
|
26
192
|
/**
|
|
27
|
-
*
|
|
193
|
+
* Creates an entity update mod and entity factories.
|
|
28
194
|
*
|
|
29
195
|
* @category Pre-built Mods
|
|
30
196
|
*/
|
|
31
|
-
export declare function
|
|
32
|
-
|
|
33
|
-
|
|
197
|
+
export declare function createAnthaEntity2dSuite<ExtraState extends AnyObject>(options?: Readonly<AnthaEntity2dModOptions>): {
|
|
198
|
+
/**
|
|
199
|
+
* Updates entity data an/or transient render state, depending on the options you provided
|
|
200
|
+
* to `createAnthaEntity2dSuite`.
|
|
201
|
+
*/
|
|
202
|
+
updateEntitiesMod: import("@antha/engine").AnthaMod<NoInfer<AnthaEntity2dModState<ExtraState>>>;
|
|
203
|
+
defineEntity: DefineViewEntity2d<AnthaEntity2dModState<ExtraState>>;
|
|
204
|
+
defineLogicEntity: DefineLogicEntity2d<AnthaEntity2dModState<ExtraState>>;
|
|
34
205
|
entityKeys: Set<string>;
|
|
35
|
-
mod: AnthaMod<AnthaEntity2dModState<ExtraState>>;
|
|
36
206
|
};
|
|
@@ -1,60 +1,101 @@
|
|
|
1
|
-
import { anthaAssetModName, AssetLoader } from '@antha/asset';
|
|
2
1
|
import { defineAnthaMod, SkipExecution } from '@antha/engine';
|
|
3
|
-
import {
|
|
2
|
+
import { assertWrap } from '@augment-vir/assert';
|
|
3
|
+
import { getObjectTypedEntries, mergeDefinedProperties, } from '@augment-vir/common';
|
|
4
4
|
import { html } from 'element-vir';
|
|
5
|
-
import {
|
|
5
|
+
import { BaseEntity2d, EntityStore2d, reverseParamsMap, ViewEntity2d, } from './entity.js';
|
|
6
|
+
function ensureEntityStore({ state, options, }) {
|
|
7
|
+
if (!state.pixi?.pixiApplication || !state.assetLoader) {
|
|
8
|
+
return false;
|
|
9
|
+
}
|
|
10
|
+
if (!state.entityStore) {
|
|
11
|
+
state.entityStore = new EntityStore2d(mergeDefinedProperties({
|
|
12
|
+
pixi: state.pixi.pixiApplication,
|
|
13
|
+
state,
|
|
14
|
+
assetLoader: state.assetLoader,
|
|
15
|
+
}, options));
|
|
16
|
+
}
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
6
19
|
/**
|
|
7
|
-
*
|
|
20
|
+
* Creates an entity update mod and entity factories.
|
|
8
21
|
*
|
|
9
22
|
* @category Pre-built Mods
|
|
10
23
|
*/
|
|
11
|
-
export function
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
24
|
+
export function createAnthaEntity2dSuite(options = {}) {
|
|
25
|
+
const entityKeys = new Set();
|
|
26
|
+
function createDefiner(entityParent) {
|
|
27
|
+
return (params) => {
|
|
28
|
+
if (params.assets) {
|
|
29
|
+
getObjectTypedEntries(params.assets).forEach(([key, rawAsset,]) => {
|
|
30
|
+
rawAsset.assetName = [
|
|
31
|
+
params.key,
|
|
32
|
+
key,
|
|
33
|
+
].join(':');
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
return defineEntity(entityParent, params);
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function defineEntity(entityParent, { collidesWith, key, paramsShape, paramsMap, assets }) {
|
|
40
|
+
if (entityKeys.has(key)) {
|
|
41
|
+
throw new Error(`Entity key '${key}' has already been attached to an entity class.`);
|
|
42
|
+
}
|
|
43
|
+
entityKeys.add(key);
|
|
44
|
+
const classWrapper = {
|
|
45
|
+
// @ts-expect-error: abstract methods are intentionally not implemented here
|
|
46
|
+
[key]: class extends entityParent {
|
|
47
|
+
static collidesWith = collidesWith;
|
|
48
|
+
static collidesWithSet = new Set(collidesWith?.collidesWithOtherEntities);
|
|
49
|
+
static entityKey = key;
|
|
50
|
+
static paramsShape = paramsShape;
|
|
51
|
+
static assets = assets || {};
|
|
52
|
+
static paramsMap = paramsMap;
|
|
53
|
+
static reverseParamsMap = reverseParamsMap(paramsMap);
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
return assertWrap.isDefined(classWrapper[key]);
|
|
57
|
+
}
|
|
58
|
+
const updateEntitiesMod = defineAnthaMod({
|
|
59
|
+
modName: 'antha-entity-2d-update',
|
|
15
60
|
initState: {
|
|
16
|
-
|
|
61
|
+
showHitboxDebug: !!options.debug,
|
|
62
|
+
disableEntityRender: !!options.disableEntityRender,
|
|
63
|
+
disableEntityUpdate: !!options.disableEntityUpdate,
|
|
17
64
|
},
|
|
18
65
|
cleanup({ state }) {
|
|
19
66
|
state.entityStore?.destroy();
|
|
20
67
|
},
|
|
68
|
+
trigger: options.updateTrigger,
|
|
21
69
|
async execute(executeParams) {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
if (!executeParams.state.assetLoader &&
|
|
27
|
-
!executeParams.engine.currentMods.some((mod) => mod.modName === anthaAssetModName)) {
|
|
28
|
-
executeParams.state.assetLoader = new AssetLoader();
|
|
29
|
-
}
|
|
30
|
-
const pixiApplication = executeParams.state.pixi?.pixiApplication;
|
|
31
|
-
if (!pixiApplication) {
|
|
70
|
+
if (!ensureEntityStore({
|
|
71
|
+
options,
|
|
72
|
+
state: executeParams.state,
|
|
73
|
+
})) {
|
|
32
74
|
return SkipExecution;
|
|
33
75
|
}
|
|
34
|
-
if (executeParams.state.entityStore) {
|
|
35
|
-
if (!executeParams.state.
|
|
76
|
+
else if (executeParams.state.entityStore) {
|
|
77
|
+
if (!executeParams.state.disableEntityUpdate) {
|
|
36
78
|
await executeParams.state.entityStore.updateAllEntities(executeParams);
|
|
37
79
|
}
|
|
80
|
+
if (!executeParams.state.disableEntityRender) {
|
|
81
|
+
await executeParams.state.entityStore.renderAllEntities(executeParams);
|
|
82
|
+
}
|
|
38
83
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}, options));
|
|
45
|
-
}
|
|
46
|
-
if (executeParams.state.debugHitboxes) {
|
|
47
|
-
return html `
|
|
48
|
-
<canvas class="hitbox-debug-canvas"></canvas>
|
|
49
|
-
`;
|
|
50
|
-
}
|
|
51
|
-
else {
|
|
52
|
-
return undefined;
|
|
53
|
-
}
|
|
84
|
+
return executeParams.state.showHitboxDebug
|
|
85
|
+
? html `
|
|
86
|
+
<canvas class="hitbox-debug-canvas"></canvas>
|
|
87
|
+
`
|
|
88
|
+
: undefined;
|
|
54
89
|
},
|
|
55
90
|
});
|
|
56
91
|
return {
|
|
57
|
-
|
|
58
|
-
|
|
92
|
+
/**
|
|
93
|
+
* Updates entity data an/or transient render state, depending on the options you provided
|
|
94
|
+
* to `createAnthaEntity2dSuite`.
|
|
95
|
+
*/
|
|
96
|
+
updateEntitiesMod,
|
|
97
|
+
defineEntity: createDefiner(ViewEntity2d),
|
|
98
|
+
defineLogicEntity: createDefiner(BaseEntity2d),
|
|
99
|
+
entityKeys,
|
|
59
100
|
};
|
|
60
101
|
}
|
package/dist/entity.d.ts
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import { type Asset, type AssetLoader, type AssetValue } from '@antha/asset';
|
|
2
2
|
import { type ModExecuteParams } from '@antha/engine';
|
|
3
3
|
import { type PixiApplication } from '@antha/graphics-2d';
|
|
4
|
-
import { ConstructorInstanceMap, type AbstractConstructor, type AnyObject, type Constructor, type EmptyObject, type ExtractKeysWithMatchingValues, type IsEqual, type IsNever, type MaybePromise, type PartialWithUndefined, type WritableKeysOf } from '@augment-vir/common';
|
|
4
|
+
import { ConstructorInstanceMap, type AbstractConstructor, type AnyObject, type Constructor, type EmptyObject, type ExtractKeysWithMatchingValues, type IsAny, type IsEqual, type IsNever, type MaybePromise, type PartialWithUndefined, type WritableKeysOf } from '@augment-vir/common';
|
|
5
5
|
import { System as HitboxSystem, type Response as Collision, type Body as Hitbox } from 'detect-collisions';
|
|
6
6
|
import { type Shape } from 'object-shape-tester';
|
|
7
7
|
import { type Container, type ViewContainer } from 'pixi.js';
|
|
8
8
|
import { GenericListenTarget } from 'typed-event-target';
|
|
9
|
-
import { type StaticEntity2dParts } from './entity-suite.js';
|
|
10
9
|
export { System as HitboxSystem, type Response as Collision } from 'detect-collisions';
|
|
11
10
|
/**
|
|
12
11
|
* Definition of entity assets used when defining an entity.
|
|
@@ -74,6 +73,37 @@ export type EntityStore2dConstructorParams<State extends AnyObject = any> = {
|
|
|
74
73
|
* @category Internal
|
|
75
74
|
*/
|
|
76
75
|
export type Entity2dConstructor = Constructor<BaseEntity2d> & StaticEntity2dParts<any, any, BaseEntityAssetDefinitions>;
|
|
76
|
+
/**
|
|
77
|
+
* Static members of both view and logic entity constructors.
|
|
78
|
+
*
|
|
79
|
+
* @category Internal
|
|
80
|
+
*/
|
|
81
|
+
export type StaticEntity2dParts<State extends AnyObject = any, ParamsShape extends Shape | undefined = any, EntityAssets extends BaseEntityAssetDefinitions | undefined = any> = {
|
|
82
|
+
/** Entity classes this entity observes collisions with. Omit to observe none. */
|
|
83
|
+
collidesWith: EntityCollisionDefinition | undefined;
|
|
84
|
+
/** Cached entity classes this entity observes collisions with. */
|
|
85
|
+
collidesWithSet: ReadonlySet<Entity2dConstructor>;
|
|
86
|
+
/**
|
|
87
|
+
* This key is used for deserialization of entities to track which class needs to be
|
|
88
|
+
* constructed. You cannot have duplicate keys loaded at the same time.
|
|
89
|
+
*
|
|
90
|
+
* This is used instead of inferring the entity key from the class name so that you can still
|
|
91
|
+
* minify your class names without making debugging nigh impossible (you'll still know which
|
|
92
|
+
* entities are being serialized and deserialized even if your class names are minified).
|
|
93
|
+
*/
|
|
94
|
+
entityKey: string;
|
|
95
|
+
/** Shape definition of this entity's parameters. */
|
|
96
|
+
paramsShape: ParamsShape;
|
|
97
|
+
/**
|
|
98
|
+
* Defines which properties from {@link BaseEntity2d.params} will be mapped to hitbox and/or view
|
|
99
|
+
* properties.
|
|
100
|
+
*/
|
|
101
|
+
paramsMap: IsAny<ParamsShape> extends true ? any : ParamsMap<ParamsShape extends Shape ? ParamsShape['runtimeType'] : undefined>;
|
|
102
|
+
/** Parses the serialized params generated by {@link BaseEntity2d.serialize}. */
|
|
103
|
+
deserialize(serialized: string | undefined): AnyObject | undefined;
|
|
104
|
+
assets: MappedEntityAssets<EntityAssets>;
|
|
105
|
+
ConstructorArgsType: Entity2dConstructorParams<State, ParamsShape extends Shape ? ParamsShape['runtimeType'] : undefined>;
|
|
106
|
+
};
|
|
77
107
|
/**
|
|
78
108
|
* Defines which entity classes this entity observes collisions with.
|
|
79
109
|
*
|
|
@@ -139,10 +169,10 @@ export declare class EntityStore2d<State extends AnyObject = any> {
|
|
|
139
169
|
* Runs `.update()` on all current entities and runs collision detection for all hitboxes. If
|
|
140
170
|
* any entities get marked as destroyed during their update, then they will be removed from the
|
|
141
171
|
* set of entities.
|
|
142
|
-
*
|
|
143
|
-
* @returns All detected hitbox collisions (if any).
|
|
144
172
|
*/
|
|
145
173
|
updateAllEntities(updateParams: Readonly<ModExecuteParams<NoInfer<State>>>): Promise<void>;
|
|
174
|
+
/** Runs presentation-only updates for every entity without simulating collisions. */
|
|
175
|
+
renderAllEntities(renderParams: Readonly<ModExecuteParams<NoInfer<State>>>): Promise<void>;
|
|
146
176
|
/** Get all current instances of the given entity class constructor. */
|
|
147
177
|
getEntities<T>(entityClassConstructor: AbstractConstructor<T> | Constructor<T>): Set<T>;
|
|
148
178
|
/** Remove an entity from the store. */
|
|
@@ -299,6 +329,12 @@ export declare const position2dParamsMap: {
|
|
|
299
329
|
* @category Internal
|
|
300
330
|
*/
|
|
301
331
|
export type ReverseParamsMap = Record<string, Partial<Record<'hitbox' | 'view', string[]>>>;
|
|
332
|
+
/**
|
|
333
|
+
* Converts {@link ParamsMap} to {@link ReverseParamsMap}.
|
|
334
|
+
*
|
|
335
|
+
* @category Internal
|
|
336
|
+
*/
|
|
337
|
+
export declare function reverseParamsMap(paramsMap: ParamsMap | undefined): ReverseParamsMap | undefined;
|
|
302
338
|
/**
|
|
303
339
|
* Base entity class, types, and functionality.
|
|
304
340
|
*
|
|
@@ -357,6 +393,12 @@ export declare abstract class BaseEntity2d<State extends AnyObject = any, Params
|
|
|
357
393
|
* entity definition classes.
|
|
358
394
|
*/
|
|
359
395
|
abstract update(updateParams: Readonly<ModExecuteParams<NoInfer<State>>>): MaybePromise<void>;
|
|
396
|
+
/**
|
|
397
|
+
* This is meant to be used to update transient render state without changing the authoritative
|
|
398
|
+
* entity state or logic. This is optional. `updateEntitiesMod` calls it (if it exists) after
|
|
399
|
+
* each entity data update unless `disableEntityRender` is `true`.
|
|
400
|
+
*/
|
|
401
|
+
render(_renderParams: Readonly<ModExecuteParams<NoInfer<State>>>): MaybePromise<void>;
|
|
360
402
|
/** Called after construction to perform async initialization (e.g. creating views). */
|
|
361
403
|
initInstance(): MaybePromise<void>;
|
|
362
404
|
/** The game's current state. */
|
package/dist/entity.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { assert, check } from '@augment-vir/assert';
|
|
2
|
-
import { ConstructorInstanceMap, getObjectTypedEntries, makeWritable, mapObjectValues, } from '@augment-vir/common';
|
|
2
|
+
import { ConstructorInstanceMap, getObjectTypedEntries, getOrSet, makeWritable, mapObjectValues, } from '@augment-vir/common';
|
|
3
3
|
import { System as HitboxSystem, Response, } from 'detect-collisions';
|
|
4
4
|
import { assertValidShape, defineShape } from 'object-shape-tester';
|
|
5
5
|
import { ParticleContainer } from 'pixi.js';
|
|
@@ -174,8 +174,6 @@ export class EntityStore2d {
|
|
|
174
174
|
* Runs `.update()` on all current entities and runs collision detection for all hitboxes. If
|
|
175
175
|
* any entities get marked as destroyed during their update, then they will be removed from the
|
|
176
176
|
* set of entities.
|
|
177
|
-
*
|
|
178
|
-
* @returns All detected hitbox collisions (if any).
|
|
179
177
|
*/
|
|
180
178
|
async updateAllEntities(updateParams) {
|
|
181
179
|
if (this.isDestroyed) {
|
|
@@ -229,6 +227,18 @@ export class EntityStore2d {
|
|
|
229
227
|
});
|
|
230
228
|
await Promise.all(collisionPromises);
|
|
231
229
|
}
|
|
230
|
+
/** Runs presentation-only updates for every entity without simulating collisions. */
|
|
231
|
+
async renderAllEntities(renderParams) {
|
|
232
|
+
if (this.isDestroyed) {
|
|
233
|
+
throw new Error('Cannot operate on a destroyed entity store.');
|
|
234
|
+
}
|
|
235
|
+
for (const entity of this.currentEntityInstances) {
|
|
236
|
+
if (entity.isDestroyed) {
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
await entity.render(renderParams);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
232
242
|
/** Get all current instances of the given entity class constructor. */
|
|
233
243
|
getEntities(entityClassConstructor) {
|
|
234
244
|
return this.entityInstanceMap.getInstances(entityClassConstructor);
|
|
@@ -361,6 +371,34 @@ export const position2dParamsMap = {
|
|
|
361
371
|
y: true,
|
|
362
372
|
},
|
|
363
373
|
};
|
|
374
|
+
/**
|
|
375
|
+
* Converts {@link ParamsMap} to {@link ReverseParamsMap}.
|
|
376
|
+
*
|
|
377
|
+
* @category Internal
|
|
378
|
+
*/
|
|
379
|
+
export function reverseParamsMap(paramsMap) {
|
|
380
|
+
if (!paramsMap) {
|
|
381
|
+
return undefined;
|
|
382
|
+
}
|
|
383
|
+
const reverseParamsMap = {};
|
|
384
|
+
getObjectTypedEntries(paramsMap).forEach(([topKey, mappings,]) => {
|
|
385
|
+
getObjectTypedEntries(mappings).forEach(([mapToKey, mapFromKey,]) => {
|
|
386
|
+
if (!mapFromKey) {
|
|
387
|
+
return;
|
|
388
|
+
}
|
|
389
|
+
const paramMapping = getOrSet(reverseParamsMap, check.isString(mapFromKey) ? mapFromKey : mapToKey, () => {
|
|
390
|
+
return {};
|
|
391
|
+
});
|
|
392
|
+
const mapToArray = getOrSet(paramMapping, topKey, () => {
|
|
393
|
+
return [];
|
|
394
|
+
});
|
|
395
|
+
if (!mapToArray.includes(mapToKey)) {
|
|
396
|
+
mapToArray.push(mapToKey);
|
|
397
|
+
}
|
|
398
|
+
});
|
|
399
|
+
});
|
|
400
|
+
return reverseParamsMap;
|
|
401
|
+
}
|
|
364
402
|
/**
|
|
365
403
|
* Base entity class, types, and functionality.
|
|
366
404
|
*
|
|
@@ -438,6 +476,13 @@ export class BaseEntity2d {
|
|
|
438
476
|
entityAssets: assets,
|
|
439
477
|
});
|
|
440
478
|
}
|
|
479
|
+
/**
|
|
480
|
+
* This is meant to be used to update transient render state without changing the authoritative
|
|
481
|
+
* entity state or logic. This is optional. `updateEntitiesMod` calls it (if it exists) after
|
|
482
|
+
* each entity data update unless `disableEntityRender` is `true`.
|
|
483
|
+
*/
|
|
484
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
485
|
+
render(_renderParams) { }
|
|
441
486
|
/** Called after construction to perform async initialization (e.g. creating views). */
|
|
442
487
|
initInstance() {
|
|
443
488
|
return;
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@antha/entity-2d",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.18.0",
|
|
4
4
|
"description": "An Antha mod for handling 2D entities.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"vir",
|
|
@@ -39,8 +39,11 @@
|
|
|
39
39
|
"@augment-vir/common": "^32.3.0"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@antha/
|
|
43
|
-
"@antha/
|
|
42
|
+
"@antha/asset": "^0.18.0",
|
|
43
|
+
"@antha/audio": "^0.18.0",
|
|
44
|
+
"@antha/engine": "^0.18.0",
|
|
45
|
+
"@antha/graphics-2d": "^0.18.0",
|
|
46
|
+
"@antha/web-test-runner-plugin-pixi": "^0.18.0",
|
|
44
47
|
"@augment-vir/test": "^32.3.0",
|
|
45
48
|
"@web/dev-server-esbuild": "^2.0.0",
|
|
46
49
|
"@web/test-runner": "^1.0.0",
|
|
@@ -52,10 +55,10 @@
|
|
|
52
55
|
"typed-event-target": "^4.3.3"
|
|
53
56
|
},
|
|
54
57
|
"peerDependencies": {
|
|
55
|
-
"@antha/asset": "^0.
|
|
56
|
-
"@antha/audio": "^0.
|
|
57
|
-
"@antha/engine": "^0.
|
|
58
|
-
"@antha/graphics-2d": "^0.
|
|
58
|
+
"@antha/asset": "^0.18.0",
|
|
59
|
+
"@antha/audio": "^0.18.0",
|
|
60
|
+
"@antha/engine": "^0.18.0",
|
|
61
|
+
"@antha/graphics-2d": "^0.18.0",
|
|
59
62
|
"detect-collisions": "^10",
|
|
60
63
|
"element-vir": "^27",
|
|
61
64
|
"object-shape-tester": "^6",
|
package/dist/entity-suite.d.ts
DELETED
|
@@ -1,228 +0,0 @@
|
|
|
1
|
-
import { type AnyObject, type Constructor, type IsAny } from '@augment-vir/common';
|
|
2
|
-
import { type Shape } from 'object-shape-tester';
|
|
3
|
-
import { BaseEntity2d, type BaseEntityAssetDefinitions, type Entity2dConstructor, type Entity2dConstructorParams, type EntityCollisionDefinition, EntityStore2d, type EntityStore2dConstructorParams, type MappedEntityAssets, type ParamsMap, type ReverseParamsMap, ViewEntity2d } from './entity.js';
|
|
4
|
-
/**
|
|
5
|
-
* Params for both {@link EntitySuite2d.defineEntity} and {@link EntitySuite2d.defineLogicEntity}.
|
|
6
|
-
*
|
|
7
|
-
* @category Internal
|
|
8
|
-
*/
|
|
9
|
-
export type DefineEntity2dArgs<ParamsShape extends Shape | undefined, EntityAssets extends BaseEntityAssetDefinitions | undefined> = {
|
|
10
|
-
/** Entity classes this entity observes collisions with. Omit to observe none. */
|
|
11
|
-
collidesWith?: EntityCollisionDefinition | undefined;
|
|
12
|
-
/**
|
|
13
|
-
* This key is used for deserialization of entities to track which class needs to be
|
|
14
|
-
* constructed. Do not use duplicate key strings across multiple entity classes.
|
|
15
|
-
*/
|
|
16
|
-
key: string;
|
|
17
|
-
/**
|
|
18
|
-
* This should contain all parameters necessary to reconstruct this entity from scratch so it
|
|
19
|
-
* can be serialized, sent across the network in JSON format, then reconstructed on another
|
|
20
|
-
* device (for multiplayer support).
|
|
21
|
-
*
|
|
22
|
-
* Make sure to include {@link entityPositionParamsShape} as part of the shape if you want to
|
|
23
|
-
* include entity position parameters.
|
|
24
|
-
*/
|
|
25
|
-
paramsShape?: ParamsShape;
|
|
26
|
-
/**
|
|
27
|
-
* A mapping of the entity's params object (defined by {@link DefineEntity2dArgs.paramsShape})
|
|
28
|
-
* keys to hitbox and/or view properties.
|
|
29
|
-
*
|
|
30
|
-
* Use `standardParamsMap` to automatically map the params `x` and `y` in `paramsShape` to both
|
|
31
|
-
* the entity's hitbox x/y and the entity's view x/y.
|
|
32
|
-
*
|
|
33
|
-
* @example
|
|
34
|
-
*
|
|
35
|
-
* ```ts
|
|
36
|
-
* const customMapping = {
|
|
37
|
-
* paramsShape: defineShape({
|
|
38
|
-
* left: -1,
|
|
39
|
-
* top: -1,
|
|
40
|
-
* }),
|
|
41
|
-
* paramsMap: {
|
|
42
|
-
* hitbox: {
|
|
43
|
-
* x: 'left', // maps `left` from `paramsShape` to the entity's hitbox.x
|
|
44
|
-
* y: 'top', // maps `top` from `paramsShape` to the entity's hitbox.y
|
|
45
|
-
* },
|
|
46
|
-
* view: {
|
|
47
|
-
* x: 'left', // maps `left` from `paramsShape` to the entity's view.x
|
|
48
|
-
* y: 'top', // maps `top` from `paramsShape` to the entity's view.y
|
|
49
|
-
* },
|
|
50
|
-
* },
|
|
51
|
-
* };
|
|
52
|
-
* ```
|
|
53
|
-
*
|
|
54
|
-
* @example
|
|
55
|
-
*
|
|
56
|
-
* ```ts
|
|
57
|
-
* const standardMapping = {
|
|
58
|
-
* paramsShape: defineShape({
|
|
59
|
-
* left: -1,
|
|
60
|
-
* top: -1,
|
|
61
|
-
* }),
|
|
62
|
-
* paramsMap: standardParamsMap, // use the standard x/y mapping
|
|
63
|
-
* };
|
|
64
|
-
* ```
|
|
65
|
-
*
|
|
66
|
-
* @example
|
|
67
|
-
*
|
|
68
|
-
* ```ts
|
|
69
|
-
* const undefinedMapping = {
|
|
70
|
-
* paramsShape: defineShape({
|
|
71
|
-
* left: -1,
|
|
72
|
-
* top: -1,
|
|
73
|
-
* }),
|
|
74
|
-
* paramsMap: undefined, // no mapping at all
|
|
75
|
-
* };
|
|
76
|
-
* ```
|
|
77
|
-
*
|
|
78
|
-
* @example
|
|
79
|
-
*
|
|
80
|
-
* ```ts
|
|
81
|
-
* const omittedMapping = {
|
|
82
|
-
* paramsShape: defineShape({
|
|
83
|
-
* left: -1,
|
|
84
|
-
* top: -1,
|
|
85
|
-
* }),
|
|
86
|
-
* // no mapping at all
|
|
87
|
-
* };
|
|
88
|
-
* ```
|
|
89
|
-
*
|
|
90
|
-
* @default undefined // no mapping
|
|
91
|
-
*/
|
|
92
|
-
paramsMap?: ParamsMap<NoInfer<ParamsShape> extends Shape ? NoInfer<ParamsShape>['runtimeType'] : undefined> | undefined;
|
|
93
|
-
assets?: EntityAssets;
|
|
94
|
-
};
|
|
95
|
-
/**
|
|
96
|
-
* Static members of both view and logic entity constructors.
|
|
97
|
-
*
|
|
98
|
-
* @category Internal
|
|
99
|
-
*/
|
|
100
|
-
export type StaticEntity2dParts<State extends AnyObject = any, ParamsShape extends Shape | undefined = any, EntityAssets extends BaseEntityAssetDefinitions | undefined = any> = {
|
|
101
|
-
/** Entity classes this entity observes collisions with. Omit to observe none. */
|
|
102
|
-
collidesWith: EntityCollisionDefinition | undefined;
|
|
103
|
-
/** Cached entity classes this entity observes collisions with. */
|
|
104
|
-
collidesWithSet: ReadonlySet<Entity2dConstructor>;
|
|
105
|
-
/**
|
|
106
|
-
* This key is used for deserialization of entities to track which class needs to be
|
|
107
|
-
* constructed. You cannot have duplicate keys loaded at the same time.
|
|
108
|
-
*
|
|
109
|
-
* This is used instead of inferring the entity key from the class name so that you can still
|
|
110
|
-
* minify your class names without making debugging nigh impossible (you'll still know which
|
|
111
|
-
* entities are being serialized and deserialized even if your class names are minified).
|
|
112
|
-
*/
|
|
113
|
-
entityKey: string;
|
|
114
|
-
/** Shape definition of this entity's parameters. */
|
|
115
|
-
paramsShape: ParamsShape;
|
|
116
|
-
/**
|
|
117
|
-
* Defines which properties from {@link BaseEntity2d.params} will be mapped to hitbox and/or view
|
|
118
|
-
* properties.
|
|
119
|
-
*/
|
|
120
|
-
paramsMap: IsAny<ParamsShape> extends true ? any : ParamsMap<ParamsShape extends Shape ? ParamsShape['runtimeType'] : undefined>;
|
|
121
|
-
/** Parses the serialized params generated by {@link BaseEntity2d.serialize}. */
|
|
122
|
-
deserialize(serialized: string | undefined): AnyObject | undefined;
|
|
123
|
-
assets: MappedEntityAssets<EntityAssets>;
|
|
124
|
-
ConstructorArgsType: Entity2dConstructorParams<State, ParamsShape extends Shape ? ParamsShape['runtimeType'] : undefined>;
|
|
125
|
-
};
|
|
126
|
-
/**
|
|
127
|
-
* ========================
|
|
128
|
-
*
|
|
129
|
-
* # View Entity
|
|
130
|
-
*
|
|
131
|
-
* Types for entity definitions that have a view.
|
|
132
|
-
*
|
|
133
|
-
* ========================
|
|
134
|
-
*/
|
|
135
|
-
/**
|
|
136
|
-
* The constructor output of {@link DefinedViewEntity2dConstructor}.
|
|
137
|
-
*
|
|
138
|
-
* @category Internal
|
|
139
|
-
*/
|
|
140
|
-
export type DefinedViewEntity2dInstance<State extends AnyObject, ParamsShape extends Shape<Record<string, any>> | undefined, EntityAssets extends BaseEntityAssetDefinitions | undefined> = ViewEntity2d<State, ParamsShape extends Shape ? ParamsShape['runtimeType'] : undefined, EntityAssets>;
|
|
141
|
-
/**
|
|
142
|
-
* Output of {@link DefineViewEntity2d}.
|
|
143
|
-
*
|
|
144
|
-
* @category Internal
|
|
145
|
-
*/
|
|
146
|
-
export type DefinedViewEntity2dConstructor<State extends AnyObject, ParamsShape extends Shape | undefined, EntityAssets extends BaseEntityAssetDefinitions | undefined> = Constructor<DefinedViewEntity2dInstance<State, ParamsShape, EntityAssets>, ConstructorParameters<typeof ViewEntity2d<State, ParamsShape extends Shape ? ParamsShape['runtimeType'] : undefined>>> & StaticEntity2dParts<State, ParamsShape>;
|
|
147
|
-
/**
|
|
148
|
-
* Type for {@link EntitySuite2d.defineEntity}.
|
|
149
|
-
*
|
|
150
|
-
* @category Internal
|
|
151
|
-
*/
|
|
152
|
-
export type DefineViewEntity2d<State extends AnyObject> = <const ParamsShape extends Shape | undefined, const EntityAssets extends BaseEntityAssetDefinitions | undefined>(params: DefineEntity2dArgs<ParamsShape, EntityAssets>) => DefinedViewEntity2dConstructor<State, NoInfer<ParamsShape>, NoInfer<EntityAssets>> & StaticEntity2dParts<NoInfer<State>, NoInfer<ParamsShape>>;
|
|
153
|
-
/**
|
|
154
|
-
* ========================
|
|
155
|
-
*
|
|
156
|
-
* # Logic Entity
|
|
157
|
-
*
|
|
158
|
-
* Types for entity definitions that don't have a view. The only difference between these types and
|
|
159
|
-
* the view types are that this uses `BaseEntity2d` instead of `ViewEntity2d`.
|
|
160
|
-
*
|
|
161
|
-
* ========================
|
|
162
|
-
*/
|
|
163
|
-
/**
|
|
164
|
-
* The constructor output of {@link DefinedLogicEntity2dConstructor}.
|
|
165
|
-
*
|
|
166
|
-
* @category Internal
|
|
167
|
-
*/
|
|
168
|
-
export type DefinedLogicEntity2dInstance<State extends AnyObject, ParamsShape extends Shape | undefined> = BaseEntity2d<State, ParamsShape extends Shape ? ParamsShape['runtimeType'] : undefined>;
|
|
169
|
-
/**
|
|
170
|
-
* Output of {@link DefineLogicEntity2d}.
|
|
171
|
-
*
|
|
172
|
-
* @category Internal
|
|
173
|
-
*/
|
|
174
|
-
export type DefinedLogicEntity2dConstructor<State extends AnyObject, ParamsShape extends Shape | undefined> = Constructor<DefinedLogicEntity2dInstance<State, ParamsShape>, ConstructorParameters<typeof BaseEntity2d<State, ParamsShape extends Shape ? ParamsShape['runtimeType'] : undefined>>> & StaticEntity2dParts<State, ParamsShape>;
|
|
175
|
-
/**
|
|
176
|
-
* Type for `EntitySuite.defineEntity`.
|
|
177
|
-
*
|
|
178
|
-
* @category Internal
|
|
179
|
-
*/
|
|
180
|
-
export type DefineLogicEntity2d<State extends AnyObject> = <const ParamsShape extends Shape | undefined, const EntityAssets extends BaseEntityAssetDefinitions | undefined>(params: DefineEntity2dArgs<ParamsShape, EntityAssets>) => DefinedLogicEntity2dConstructor<NoInfer<State>, NoInfer<ParamsShape>>;
|
|
181
|
-
/**
|
|
182
|
-
* ========================
|
|
183
|
-
*
|
|
184
|
-
* # Entity Suite
|
|
185
|
-
*
|
|
186
|
-
* ========================
|
|
187
|
-
*/
|
|
188
|
-
/**
|
|
189
|
-
* Output of {@link defineEntitySuite2d}, used to defining and creating entities.
|
|
190
|
-
*
|
|
191
|
-
* @category Internal
|
|
192
|
-
*/
|
|
193
|
-
export type EntitySuite2d<State extends AnyObject> = {
|
|
194
|
-
/**
|
|
195
|
-
* The suite's entity store constructor. Instantiate this and to add your first entities.
|
|
196
|
-
*
|
|
197
|
-
* All defined entities will also have a reference to this store so they can add additional
|
|
198
|
-
* entities by themselves.
|
|
199
|
-
*/
|
|
200
|
-
EntityStore: new (params: Readonly<EntityStore2dConstructorParams>) => EntityStore2d<State>;
|
|
201
|
-
/**
|
|
202
|
-
* Define a standard entity (with a view). This is intended to be extended from your entity
|
|
203
|
-
* class.
|
|
204
|
-
*/
|
|
205
|
-
defineEntity: DefineViewEntity2d<State>;
|
|
206
|
-
/** Define an entity that doesn't have an attached view. These are likely to be rare. */
|
|
207
|
-
defineLogicEntity: DefineLogicEntity2d<State>;
|
|
208
|
-
/**
|
|
209
|
-
* A set of entity keys used within this entity suite. This will only be populated by all
|
|
210
|
-
* classes that are defined with `defineEntity` or `defineLogicEntity` (so this will miss any
|
|
211
|
-
* not-yet-resolved dynamic imports). This will be populated even before the classes are ever
|
|
212
|
-
* instantiated.
|
|
213
|
-
*/
|
|
214
|
-
entityKeys: Set<string>;
|
|
215
|
-
};
|
|
216
|
-
/**
|
|
217
|
-
* This is the starting point of the @game-vir/entity package. Call this to produce the function
|
|
218
|
-
* needed to define new entities and the store needed to add entity instances.
|
|
219
|
-
*
|
|
220
|
-
* @category Main
|
|
221
|
-
*/
|
|
222
|
-
export declare function defineEntitySuite2d<State extends AnyObject>(): EntitySuite2d<State>;
|
|
223
|
-
/**
|
|
224
|
-
* Converts {@link ParamsMap} to {@link ReverseParamsMap}.
|
|
225
|
-
*
|
|
226
|
-
* @category Internal
|
|
227
|
-
*/
|
|
228
|
-
export declare function reverseParamsMap(paramsMap: ParamsMap | undefined): ReverseParamsMap | undefined;
|
package/dist/entity-suite.js
DELETED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import { check } from '@augment-vir/assert';
|
|
2
|
-
import { getObjectTypedEntries, getOrSet, } from '@augment-vir/common';
|
|
3
|
-
import { BaseEntity2d, EntityStore2d, ViewEntity2d, } from './entity.js';
|
|
4
|
-
/**
|
|
5
|
-
* This is the starting point of the @game-vir/entity package. Call this to produce the function
|
|
6
|
-
* needed to define new entities and the store needed to add entity instances.
|
|
7
|
-
*
|
|
8
|
-
* @category Main
|
|
9
|
-
*/
|
|
10
|
-
export function defineEntitySuite2d() {
|
|
11
|
-
const entityKeys = new Set();
|
|
12
|
-
function createDefiner(entityParent) {
|
|
13
|
-
return (params) => {
|
|
14
|
-
if (params.assets) {
|
|
15
|
-
getObjectTypedEntries(params.assets).forEach(([key, rawAsset,]) => {
|
|
16
|
-
rawAsset.assetName = [
|
|
17
|
-
params.key,
|
|
18
|
-
key,
|
|
19
|
-
].join(':');
|
|
20
|
-
});
|
|
21
|
-
}
|
|
22
|
-
return defineEntity(entityParent, params);
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
function defineEntity(entityParent, { collidesWith, key, paramsShape, paramsMap, assets }) {
|
|
26
|
-
if (entityKeys.has(key)) {
|
|
27
|
-
throw new Error(`Entity key '${key}' has already been attached to an entity class.`);
|
|
28
|
-
}
|
|
29
|
-
entityKeys.add(key);
|
|
30
|
-
const classWrapper = {
|
|
31
|
-
// @ts-expect-error: abstract methods are intentionally not implemented here
|
|
32
|
-
[key]: class extends entityParent {
|
|
33
|
-
static collidesWith = collidesWith;
|
|
34
|
-
static collidesWithSet = new Set(collidesWith?.collidesWithOtherEntities);
|
|
35
|
-
static entityKey = key;
|
|
36
|
-
static paramsShape = paramsShape;
|
|
37
|
-
static assets = assets || {};
|
|
38
|
-
static paramsMap = paramsMap;
|
|
39
|
-
static reverseParamsMap = reverseParamsMap(paramsMap);
|
|
40
|
-
},
|
|
41
|
-
};
|
|
42
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
43
|
-
return classWrapper[key];
|
|
44
|
-
}
|
|
45
|
-
return {
|
|
46
|
-
EntityStore: EntityStore2d,
|
|
47
|
-
defineEntity: createDefiner(ViewEntity2d),
|
|
48
|
-
defineLogicEntity: createDefiner(BaseEntity2d),
|
|
49
|
-
entityKeys,
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* Converts {@link ParamsMap} to {@link ReverseParamsMap}.
|
|
54
|
-
*
|
|
55
|
-
* @category Internal
|
|
56
|
-
*/
|
|
57
|
-
export function reverseParamsMap(paramsMap) {
|
|
58
|
-
if (!paramsMap) {
|
|
59
|
-
return undefined;
|
|
60
|
-
}
|
|
61
|
-
const reverseParamsMap = {};
|
|
62
|
-
getObjectTypedEntries(paramsMap).forEach(([topKey, mappings,]) => {
|
|
63
|
-
getObjectTypedEntries(mappings).forEach(([mapToKey, mapFromKey,]) => {
|
|
64
|
-
if (!mapFromKey) {
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
67
|
-
const paramMapping = getOrSet(reverseParamsMap, check.isString(mapFromKey) ? mapFromKey : mapToKey, () => {
|
|
68
|
-
return {};
|
|
69
|
-
});
|
|
70
|
-
const mapToArray = getOrSet(paramMapping, topKey, () => {
|
|
71
|
-
return [];
|
|
72
|
-
});
|
|
73
|
-
if (!mapToArray.includes(mapToKey)) {
|
|
74
|
-
mapToArray.push(mapToKey);
|
|
75
|
-
}
|
|
76
|
-
});
|
|
77
|
-
});
|
|
78
|
-
return reverseParamsMap;
|
|
79
|
-
}
|