@draug/engine 1.0.0 → 1.0.2
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/index.cjs +946 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +373 -0
- package/dist/index.d.ts +373 -0
- package/dist/index.js +883 -0
- package/dist/index.js.map +1 -0
- package/package.json +20 -6
- package/ecs/command.ts +0 -44
- package/ecs/components/component-storage.ts +0 -86
- package/ecs/components/index.ts +0 -12
- package/ecs/components/manager.ts +0 -91
- package/ecs/components/singleton-storage.ts +0 -51
- package/ecs/components/types.ts +0 -14
- package/ecs/components/utils.ts +0 -18
- package/ecs/constant.ts +0 -3
- package/ecs/entity.ts +0 -44
- package/ecs/events-buffer.ts +0 -62
- package/ecs/query.ts +0 -169
- package/ecs/resources/index.ts +0 -1
- package/ecs/resources/resources.ts +0 -28
- package/ecs/system.ts +0 -214
- package/ecs/world.ts +0 -99
- package/index.ts +0 -74
- package/plugin/index.ts +0 -15
- package/plugin/plugin.ts +0 -200
- package/runtime/clock.ts +0 -31
- package/runtime/game-loop.ts +0 -32
- package/runtime/runtime.ts +0 -12
- package/tsconfig.json +0 -24
package/plugin/plugin.ts
DELETED
|
@@ -1,200 +0,0 @@
|
|
|
1
|
-
import type { ClassType, ComponentType } from "@draug/types/class";
|
|
2
|
-
import { SystemBase } from "../ecs/system";
|
|
3
|
-
import type { World } from "../ecs/world";
|
|
4
|
-
import { DAGNode, topologicalSort, ErrDAGCycleDetected } from '@draug/core/graph/dag';
|
|
5
|
-
|
|
6
|
-
export type PluginID = string;
|
|
7
|
-
|
|
8
|
-
export type PluginDependencies = {
|
|
9
|
-
components?: ComponentType[];
|
|
10
|
-
resources?: ClassType<any>[];
|
|
11
|
-
systems?: ClassType<SystemBase>[];
|
|
12
|
-
plugins?: Array<{ id: PluginID; version?: string }>;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export interface PluginMetadata {
|
|
16
|
-
id: PluginID;
|
|
17
|
-
version: string;
|
|
18
|
-
name: string;
|
|
19
|
-
dependencies?: PluginDependencies;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
const PluginMetadataSymbol = Symbol("plugin");
|
|
23
|
-
|
|
24
|
-
export function Plugin(metadata: PluginMetadata): ClassDecorator {
|
|
25
|
-
return (target: Function) => {
|
|
26
|
-
if ('__proto__' in target && target.__proto__ !== PluginBase)
|
|
27
|
-
throw new ErrNotAPlugin(target);
|
|
28
|
-
|
|
29
|
-
(target as FunctionWithMetadata)[PluginMetadataSymbol] = metadata;
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export function getPluginMetadata(plugin: ClassType<PluginBase>): PluginMetadata {
|
|
34
|
-
if (hasMetadata(plugin)) {
|
|
35
|
-
return plugin[PluginMetadataSymbol] as PluginMetadata;
|
|
36
|
-
}
|
|
37
|
-
throw new ErrMissingPluginMetadata(plugin);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
type FunctionWithMetadata = Function & { [PluginMetadataSymbol]: PluginMetadata };
|
|
41
|
-
|
|
42
|
-
export function hasMetadata(ctor: Function): ctor is FunctionWithMetadata {
|
|
43
|
-
return PluginMetadataSymbol in ctor;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export function isPlugin(ctor: Function): boolean {
|
|
47
|
-
return hasMetadata(ctor);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export abstract class PluginBase {
|
|
51
|
-
public onPluginLoad?: (world: World) => void;
|
|
52
|
-
public onPluginUnload?: (world: World) => void;
|
|
53
|
-
public onAfterWorldInit?: (world: World) => void;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
type PluginManagerInternalPluginStorageItem<T extends ClassType<PluginBase>> = {
|
|
57
|
-
ctor: T;
|
|
58
|
-
ctorParams: ConstructorParameters<T>;
|
|
59
|
-
instance?: InstanceType<T>;
|
|
60
|
-
metadata: PluginMetadata;
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
export class PluginError extends Error {
|
|
64
|
-
constructor(pluginId: string) {
|
|
65
|
-
super(`Plugin error! Plugin [${pluginId}]`);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
export class ErrNotAPlugin extends Error {
|
|
70
|
-
constructor(target: Function) {
|
|
71
|
-
super(`Provided class ${target.name} is not a Plugin! Every plugin must extends of PluginBase class.`);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
export class ErrMissingPluginMetadata extends Error {
|
|
76
|
-
constructor(plugin: ClassType<PluginBase>) {
|
|
77
|
-
super(`Provided class ${plugin.name}: Missing plugin metadata! Define plugin class with @Plugin decorator.`);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
export class ErrUnknownPlugin extends PluginError {
|
|
82
|
-
constructor(pluginId: string) {
|
|
83
|
-
super(pluginId);
|
|
84
|
-
this.message = `${super.message}: Plugin not found in manager.`;
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
export class ErrPluginNotInit extends PluginError {
|
|
89
|
-
constructor(pluginId: string) {
|
|
90
|
-
super(pluginId);
|
|
91
|
-
this.message = `${super.message}: Plugin not initiated yet. You must use PluginsManager.build() before getting instance.`;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
export class ErrMissingPluginDependency extends PluginError {
|
|
96
|
-
constructor(pluginId: string, missingDepId: string) {
|
|
97
|
-
super(pluginId);
|
|
98
|
-
this.message = `${super.message}: Missing required dependency [${missingDepId}]. Install it first.`;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
export class ErrDAGCycleDetectedPlugin extends Error {
|
|
103
|
-
constructor() {
|
|
104
|
-
super(`Cycle detected in plugin dependencies!`);
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
export class PluginsManager {
|
|
109
|
-
private plugins_: Map<PluginID, PluginManagerInternalPluginStorageItem<any>> = new Map();
|
|
110
|
-
private isInitiated_ = false;
|
|
111
|
-
|
|
112
|
-
public install<T extends ClassType<PluginBase>>(plugin: T, ...constructorProps: ConstructorParameters<T>): void {
|
|
113
|
-
if (!isPlugin(plugin))
|
|
114
|
-
throw new ErrMissingPluginMetadata(plugin);
|
|
115
|
-
|
|
116
|
-
const metadata = getPluginMetadata(plugin);
|
|
117
|
-
|
|
118
|
-
if (this.plugins_.has(metadata.id))
|
|
119
|
-
return;
|
|
120
|
-
|
|
121
|
-
const entry: PluginManagerInternalPluginStorageItem<T> = {
|
|
122
|
-
ctor: plugin,
|
|
123
|
-
ctorParams: constructorProps,
|
|
124
|
-
metadata,
|
|
125
|
-
};
|
|
126
|
-
|
|
127
|
-
this.plugins_.set(metadata.id, entry);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
public build(): void {
|
|
131
|
-
const nodes = new Map<PluginID, DAGNode<PluginID>>();
|
|
132
|
-
for (const id of this.plugins_.keys()) {
|
|
133
|
-
nodes.set(id, new DAGNode(id));
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
for (const [id, entry] of this.plugins_) {
|
|
137
|
-
const node = nodes.get(id)!;
|
|
138
|
-
const depPlugins = entry.metadata.dependencies?.plugins ?? [];
|
|
139
|
-
|
|
140
|
-
for (const dep of depPlugins) {
|
|
141
|
-
const depNode = nodes.get(dep.id);
|
|
142
|
-
if (!depNode) {
|
|
143
|
-
throw new ErrMissingPluginDependency(id, dep.id);
|
|
144
|
-
}
|
|
145
|
-
node.vertices.push(depNode);
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
let sortedNodes: DAGNode<PluginID>[];
|
|
150
|
-
try {
|
|
151
|
-
sortedNodes = topologicalSort(nodes.values());
|
|
152
|
-
} catch (e) {
|
|
153
|
-
if (e instanceof ErrDAGCycleDetected) {
|
|
154
|
-
throw new ErrDAGCycleDetectedPlugin();
|
|
155
|
-
}
|
|
156
|
-
throw e;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
for (const node of sortedNodes) {
|
|
160
|
-
const entry = this.plugins_.get(node.data)!;
|
|
161
|
-
const { ctor, ctorParams } = entry;
|
|
162
|
-
entry.instance = new ctor(...ctorParams);
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
this.isInitiated_ = true;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
public getPluginMetadata(pluginOrId: ClassType<PluginBase> | PluginID): PluginMetadata {
|
|
169
|
-
const id = this.resolveId(pluginOrId);
|
|
170
|
-
const entry = this.plugins_.get(id);
|
|
171
|
-
if (!entry) throw new ErrUnknownPlugin(id);
|
|
172
|
-
return entry.metadata;
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
public getPluginInstance<T extends PluginBase>(pluginOrId: ClassType<T> | PluginID): T {
|
|
176
|
-
if (!this.isInitiated_) {
|
|
177
|
-
throw new Error("Plugin instance is not initiated yet. Use PluginManager.build() before use plugins.");
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
const id = this.resolveId(pluginOrId);
|
|
181
|
-
|
|
182
|
-
const entry = this.plugins_.get(id);
|
|
183
|
-
if (!entry) throw new ErrUnknownPlugin(id);
|
|
184
|
-
if (!entry.instance) throw new ErrPluginNotInit(id);
|
|
185
|
-
|
|
186
|
-
return entry.instance as T;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
private resolveId(pluginOrId: ClassType<PluginBase> | PluginID): PluginID {
|
|
190
|
-
if (typeof pluginOrId === 'string') {
|
|
191
|
-
return pluginOrId;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
if (!isPlugin(pluginOrId)) {
|
|
195
|
-
throw new ErrMissingPluginMetadata(pluginOrId);
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
return getPluginMetadata(pluginOrId).id;
|
|
199
|
-
}
|
|
200
|
-
};
|
package/runtime/clock.ts
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
export interface TimeSource {
|
|
2
|
-
now(): number;
|
|
3
|
-
}
|
|
4
|
-
|
|
5
|
-
export class Clock {
|
|
6
|
-
private lastTimeMs_: number;
|
|
7
|
-
private elapsedTime_: number = 0;
|
|
8
|
-
private dt_: number = 0;
|
|
9
|
-
|
|
10
|
-
public constructor(
|
|
11
|
-
private readonly timeSource_: TimeSource,
|
|
12
|
-
) {
|
|
13
|
-
this.lastTimeMs_ = timeSource_.now();
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
public get dt(): number {
|
|
18
|
-
return this.dt_;
|
|
19
|
-
}
|
|
20
|
-
public get ellapsedTime(): number {
|
|
21
|
-
return this.elapsedTime_;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
public tick(): void {
|
|
25
|
-
const now = this.timeSource_.now();
|
|
26
|
-
const dt = now - this.lastTimeMs_;
|
|
27
|
-
this.dt_ = dt;
|
|
28
|
-
this.elapsedTime_ += dt;
|
|
29
|
-
this.lastTimeMs_ = now;
|
|
30
|
-
}
|
|
31
|
-
};
|
package/runtime/game-loop.ts
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { Clock } from "./clock";
|
|
2
|
-
|
|
3
|
-
export type StepFunction = (dt: number) => void;
|
|
4
|
-
|
|
5
|
-
export class GameLoop {
|
|
6
|
-
private running = false;
|
|
7
|
-
|
|
8
|
-
constructor(
|
|
9
|
-
private clock: Clock,
|
|
10
|
-
private stepFn: StepFunction,
|
|
11
|
-
) { };
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
public start(platformLoop: (callback: () => void) => void) {
|
|
15
|
-
this.running = true;
|
|
16
|
-
|
|
17
|
-
const loop = () => {
|
|
18
|
-
if (!this.running) return;
|
|
19
|
-
|
|
20
|
-
this.clock.tick();
|
|
21
|
-
this.stepFn(this.clock.dt);
|
|
22
|
-
|
|
23
|
-
platformLoop(loop);
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
platformLoop(loop);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
public stop() {
|
|
30
|
-
this.running = false;
|
|
31
|
-
}
|
|
32
|
-
};
|
package/runtime/runtime.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import type { AssetsManager } from "../../assets/assets";
|
|
2
|
-
import type { World } from "../ecs/world";
|
|
3
|
-
|
|
4
|
-
export class Runtime {
|
|
5
|
-
constructor(
|
|
6
|
-
public readonly world: World,
|
|
7
|
-
public readonly assets: AssetsManager,
|
|
8
|
-
){};
|
|
9
|
-
public update(dt: number) {
|
|
10
|
-
this.world.update(dt);
|
|
11
|
-
};
|
|
12
|
-
};
|
package/tsconfig.json
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"module": "esnext",
|
|
4
|
-
"moduleResolution": "bundler",
|
|
5
|
-
"target": "es2022",
|
|
6
|
-
|
|
7
|
-
"lib": ["ES2022"],
|
|
8
|
-
"types": [],
|
|
9
|
-
|
|
10
|
-
"sourceMap": true,
|
|
11
|
-
"declaration": true,
|
|
12
|
-
"declarationMap": true,
|
|
13
|
-
"experimentalDecorators": true,
|
|
14
|
-
|
|
15
|
-
"noUncheckedIndexedAccess": true,
|
|
16
|
-
"exactOptionalPropertyTypes": true,
|
|
17
|
-
|
|
18
|
-
"strict": true,
|
|
19
|
-
"verbatimModuleSyntax": true,
|
|
20
|
-
"isolatedModules": true,
|
|
21
|
-
"moduleDetection": "force",
|
|
22
|
-
"skipLibCheck": true
|
|
23
|
-
}
|
|
24
|
-
}
|