@lagless/create 0.0.33
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.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +123 -0
- package/dist/index.js.map +1 -0
- package/dist/tsconfig.lib.tsbuildinfo +1 -0
- package/package.json +59 -0
- package/templates/.nxignore +1 -0
- package/templates/pixi-react/AGENTS.md +41 -0
- package/templates/pixi-react/CLAUDE.md +79 -0
- package/templates/pixi-react/README.md +151 -0
- package/templates/pixi-react/__packageName__-backend/bunfig.toml +4 -0
- package/templates/pixi-react/__packageName__-backend/package.json +19 -0
- package/templates/pixi-react/__packageName__-backend/src/game-hooks.ts +47 -0
- package/templates/pixi-react/__packageName__-backend/src/main.ts +28 -0
- package/templates/pixi-react/__packageName__-backend/tsconfig.json +19 -0
- package/templates/pixi-react/__packageName__-frontend/index.html +23 -0
- package/templates/pixi-react/__packageName__-frontend/package.json +33 -0
- package/templates/pixi-react/__packageName__-frontend/src/app/app.tsx +7 -0
- package/templates/pixi-react/__packageName__-frontend/src/app/components/debug-panel.tsx +18 -0
- package/templates/pixi-react/__packageName__-frontend/src/app/game-view/game-scene.tsx +14 -0
- package/templates/pixi-react/__packageName__-frontend/src/app/game-view/game-view.tsx +46 -0
- package/templates/pixi-react/__packageName__-frontend/src/app/game-view/grid-background.tsx +33 -0
- package/templates/pixi-react/__packageName__-frontend/src/app/game-view/player-view.tsx +59 -0
- package/templates/pixi-react/__packageName__-frontend/src/app/game-view/runner-provider.tsx +180 -0
- package/templates/pixi-react/__packageName__-frontend/src/app/hooks/use-start-match.ts +53 -0
- package/templates/pixi-react/__packageName__-frontend/src/app/hooks/use-start-multiplayer-match.ts +138 -0
- package/templates/pixi-react/__packageName__-frontend/src/app/router.tsx +25 -0
- package/templates/pixi-react/__packageName__-frontend/src/app/screens/game.screen.tsx +6 -0
- package/templates/pixi-react/__packageName__-frontend/src/app/screens/title.screen.tsx +104 -0
- package/templates/pixi-react/__packageName__-frontend/src/main.tsx +7 -0
- package/templates/pixi-react/__packageName__-frontend/src/styles.css +24 -0
- package/templates/pixi-react/__packageName__-frontend/tsconfig.json +22 -0
- package/templates/pixi-react/__packageName__-frontend/vite.config.ts +37 -0
- package/templates/pixi-react/__packageName__-simulation/.swcrc +27 -0
- package/templates/pixi-react/__packageName__-simulation/package.json +23 -0
- package/templates/pixi-react/__packageName__-simulation/src/index.ts +4 -0
- package/templates/pixi-react/__packageName__-simulation/src/lib/arena.ts +8 -0
- package/templates/pixi-react/__packageName__-simulation/src/lib/schema/code-gen/GameState.ts +29 -0
- package/templates/pixi-react/__packageName__-simulation/src/lib/schema/code-gen/MoveInput.ts +23 -0
- package/templates/pixi-react/__packageName__-simulation/src/lib/schema/code-gen/MovingFilter.ts +15 -0
- package/templates/pixi-react/__packageName__-simulation/src/lib/schema/code-gen/PlayerBody.ts +55 -0
- package/templates/pixi-react/__packageName__-simulation/src/lib/schema/code-gen/PlayerFilter.ts +15 -0
- package/templates/pixi-react/__packageName__-simulation/src/lib/schema/code-gen/PlayerJoined.ts +24 -0
- package/templates/pixi-react/__packageName__-simulation/src/lib/schema/code-gen/PlayerLeft.ts +23 -0
- package/templates/pixi-react/__packageName__-simulation/src/lib/schema/code-gen/PlayerResource.ts +83 -0
- package/templates/pixi-react/__packageName__-simulation/src/lib/schema/code-gen/ReportHash.ts +23 -0
- package/templates/pixi-react/__packageName__-simulation/src/lib/schema/code-gen/Transform2d.ts +65 -0
- package/templates/pixi-react/__packageName__-simulation/src/lib/schema/code-gen/Velocity2d.ts +55 -0
- package/templates/pixi-react/__packageName__-simulation/src/lib/schema/code-gen/__ProjectName__.core.ts +22 -0
- package/templates/pixi-react/__packageName__-simulation/src/lib/schema/code-gen/__ProjectName__.runner.ts +16 -0
- package/templates/pixi-react/__packageName__-simulation/src/lib/schema/code-gen/__ProjectName__InputRegistry.ts +8 -0
- package/templates/pixi-react/__packageName__-simulation/src/lib/schema/code-gen/index.ts +16 -0
- package/templates/pixi-react/__packageName__-simulation/src/lib/schema/ecs.yaml +52 -0
- package/templates/pixi-react/__packageName__-simulation/src/lib/signals/index.ts +5 -0
- package/templates/pixi-react/__packageName__-simulation/src/lib/systems/apply-move-input.system.ts +23 -0
- package/templates/pixi-react/__packageName__-simulation/src/lib/systems/boundary.system.ts +34 -0
- package/templates/pixi-react/__packageName__-simulation/src/lib/systems/damping.system.ts +18 -0
- package/templates/pixi-react/__packageName__-simulation/src/lib/systems/hash-verification.system.ts +17 -0
- package/templates/pixi-react/__packageName__-simulation/src/lib/systems/index.ts +20 -0
- package/templates/pixi-react/__packageName__-simulation/src/lib/systems/integrate.system.ts +18 -0
- package/templates/pixi-react/__packageName__-simulation/src/lib/systems/player-connection.system.ts +47 -0
- package/templates/pixi-react/__packageName__-simulation/src/lib/systems/player-leave.system.ts +21 -0
- package/templates/pixi-react/__packageName__-simulation/src/lib/systems/save-prev-transform.system.ts +17 -0
- package/templates/pixi-react/__packageName__-simulation/tsconfig.json +22 -0
- package/templates/pixi-react/package.json +8 -0
- package/templates/pixi-react/pnpm-workspace.yaml +4 -0
- package/templates/pixi-react/tsconfig.base.json +21 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// Generated by @lagless/codegen. Do not edit manually.
|
|
2
|
+
import { MemoryTracker } from '@lagless/binary';
|
|
3
|
+
|
|
4
|
+
export class Velocity2d {
|
|
5
|
+
public static readonly ID = 2;
|
|
6
|
+
public static readonly schema = {
|
|
7
|
+
velocityX: Float32Array,
|
|
8
|
+
velocityY: Float32Array,
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
public readonly unsafe = {} as {
|
|
12
|
+
velocityX: Float32Array;
|
|
13
|
+
velocityY: Float32Array;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
private _cursorIndex = 0;
|
|
17
|
+
private readonly _cursor: {
|
|
18
|
+
readonly entity: number;
|
|
19
|
+
velocityX: number;
|
|
20
|
+
velocityY: number;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
public getCursor(index: number) {
|
|
24
|
+
this._cursorIndex = index;
|
|
25
|
+
return this._cursor;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
constructor(maxEntities: number, buffer: ArrayBuffer, memTracker: MemoryTracker) {
|
|
29
|
+
for (const [fieldName, TypedArrayConstructor] of Object.entries(Velocity2d.schema)) {
|
|
30
|
+
const typedArray = new TypedArrayConstructor(buffer, memTracker.ptr, maxEntities);
|
|
31
|
+
this.unsafe[fieldName as keyof typeof Velocity2d.schema] =
|
|
32
|
+
typedArray as Velocity2d['unsafe'][keyof Velocity2d['unsafe']];
|
|
33
|
+
memTracker.add(typedArray.byteLength);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
37
|
+
const self = this;
|
|
38
|
+
|
|
39
|
+
this._cursor = {
|
|
40
|
+
get entity(): number { return self._cursorIndex; },
|
|
41
|
+
get velocityX(): number { return self.unsafe.velocityX[self._cursorIndex]; },
|
|
42
|
+
set velocityX(value: number) { self.unsafe.velocityX[self._cursorIndex] = value; },
|
|
43
|
+
get velocityY(): number { return self.unsafe.velocityY[self._cursorIndex]; },
|
|
44
|
+
set velocityY(value: number) { self.unsafe.velocityY[self._cursorIndex] = value; },
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
public static calculateSize(maxEntities: number, memTracker: MemoryTracker): void {
|
|
49
|
+
for (const [, TypedArrayConstructor] of Object.entries(this.schema)) {
|
|
50
|
+
memTracker.add(maxEntities * TypedArrayConstructor.BYTES_PER_ELEMENT);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
Object.defineProperty(Velocity2d, 'name', { value: 'Velocity2d' });
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// Generated by @lagless/codegen. Do not edit manually.
|
|
2
|
+
import { ECSDeps } from '@lagless/core';
|
|
3
|
+
|
|
4
|
+
import { Transform2d } from './Transform2d.js';
|
|
5
|
+
import { Velocity2d } from './Velocity2d.js';
|
|
6
|
+
import { PlayerBody } from './PlayerBody.js';
|
|
7
|
+
import { GameState } from './GameState.js';
|
|
8
|
+
import { PlayerResource } from './PlayerResource.js';
|
|
9
|
+
import { PlayerFilter } from './PlayerFilter.js';
|
|
10
|
+
import { MovingFilter } from './MovingFilter.js';
|
|
11
|
+
import { PlayerJoined } from './PlayerJoined.js';
|
|
12
|
+
import { PlayerLeft } from './PlayerLeft.js';
|
|
13
|
+
import { MoveInput } from './MoveInput.js';
|
|
14
|
+
import { ReportHash } from './ReportHash.js';
|
|
15
|
+
|
|
16
|
+
export const <%= projectName %>Core: ECSDeps = {
|
|
17
|
+
components: [Transform2d, Velocity2d, PlayerBody],
|
|
18
|
+
singletons: [GameState],
|
|
19
|
+
playerResources: [PlayerResource],
|
|
20
|
+
filters: [PlayerFilter, MovingFilter],
|
|
21
|
+
inputs: [PlayerJoined, PlayerLeft, MoveInput, ReportHash],
|
|
22
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// Generated by @lagless/codegen. Do not edit manually.
|
|
2
|
+
import { AbstractInputProvider, ECSConfig, ECSRunner } from '@lagless/core';
|
|
3
|
+
import { IECSSystemConstructor, ISignalConstructor } from '@lagless/core';
|
|
4
|
+
|
|
5
|
+
import { <%= projectName %>Core } from './<%= projectName %>.core.js';
|
|
6
|
+
|
|
7
|
+
export class <%= projectName %>Runner extends ECSRunner {
|
|
8
|
+
constructor(
|
|
9
|
+
Config: ECSConfig,
|
|
10
|
+
InputProviderInstance: AbstractInputProvider,
|
|
11
|
+
Systems: Array<IECSSystemConstructor>,
|
|
12
|
+
Signals: Array<ISignalConstructor> = []
|
|
13
|
+
) {
|
|
14
|
+
super(Config, InputProviderInstance, Systems, Signals, <%= projectName %>Core);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// Generated by @lagless/codegen. Do not edit manually.
|
|
2
|
+
import { InputRegistry } from '@lagless/core';
|
|
3
|
+
import { PlayerJoined } from './PlayerJoined.js';
|
|
4
|
+
import { PlayerLeft } from './PlayerLeft.js';
|
|
5
|
+
import { MoveInput } from './MoveInput.js';
|
|
6
|
+
import { ReportHash } from './ReportHash.js';
|
|
7
|
+
|
|
8
|
+
export const <%= projectName %>InputRegistry = new InputRegistry([PlayerJoined, PlayerLeft, MoveInput, ReportHash]);
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// Generated by @lagless/codegen. Do not edit manually.
|
|
2
|
+
|
|
3
|
+
export * from './<%= projectName %>.core.js';
|
|
4
|
+
export * from './<%= projectName %>.runner.js';
|
|
5
|
+
export * from './<%= projectName %>InputRegistry.js';
|
|
6
|
+
export * from './Transform2d.js';
|
|
7
|
+
export * from './Velocity2d.js';
|
|
8
|
+
export * from './PlayerBody.js';
|
|
9
|
+
export * from './GameState.js';
|
|
10
|
+
export * from './PlayerResource.js';
|
|
11
|
+
export * from './PlayerFilter.js';
|
|
12
|
+
export * from './MovingFilter.js';
|
|
13
|
+
export * from './PlayerJoined.js';
|
|
14
|
+
export * from './PlayerLeft.js';
|
|
15
|
+
export * from './MoveInput.js';
|
|
16
|
+
export * from './ReportHash.js';
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Run codegen: npx @lagless/codegen -c <%= packageName %>-simulation/src/lib/schema/ecs.yaml
|
|
2
|
+
projectName: <%= projectName %>
|
|
3
|
+
|
|
4
|
+
components:
|
|
5
|
+
Transform2d:
|
|
6
|
+
positionX: float32
|
|
7
|
+
positionY: float32
|
|
8
|
+
prevPositionX: float32
|
|
9
|
+
prevPositionY: float32
|
|
10
|
+
Velocity2d:
|
|
11
|
+
velocityX: float32
|
|
12
|
+
velocityY: float32
|
|
13
|
+
PlayerBody:
|
|
14
|
+
playerSlot: uint8
|
|
15
|
+
radius: float32
|
|
16
|
+
|
|
17
|
+
singletons:
|
|
18
|
+
GameState:
|
|
19
|
+
gamePhase: uint8
|
|
20
|
+
|
|
21
|
+
playerResources:
|
|
22
|
+
PlayerResource:
|
|
23
|
+
id: uint8[16]
|
|
24
|
+
entity: uint32
|
|
25
|
+
connected: uint8
|
|
26
|
+
lastReportedHash: uint32
|
|
27
|
+
lastReportedHashTick: uint32
|
|
28
|
+
hashMismatchCount: uint16
|
|
29
|
+
|
|
30
|
+
inputs:
|
|
31
|
+
PlayerJoined:
|
|
32
|
+
slot: uint8
|
|
33
|
+
playerId: uint8[16]
|
|
34
|
+
PlayerLeft:
|
|
35
|
+
slot: uint8
|
|
36
|
+
reason: uint8
|
|
37
|
+
MoveInput:
|
|
38
|
+
directionX: float32
|
|
39
|
+
directionY: float32
|
|
40
|
+
ReportHash:
|
|
41
|
+
hash: uint32
|
|
42
|
+
atTick: uint32
|
|
43
|
+
|
|
44
|
+
filters:
|
|
45
|
+
PlayerFilter:
|
|
46
|
+
include:
|
|
47
|
+
- Transform2d
|
|
48
|
+
- PlayerBody
|
|
49
|
+
MovingFilter:
|
|
50
|
+
include:
|
|
51
|
+
- Transform2d
|
|
52
|
+
- Velocity2d
|
package/templates/pixi-react/__packageName__-simulation/src/lib/systems/apply-move-input.system.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ECSSystem, IECSSystem, InputProvider, PlayerResources } from '@lagless/core';
|
|
2
|
+
import { MoveInput, PlayerResource, Velocity2d } from '../schema/code-gen/index.js';
|
|
3
|
+
import { <%= projectName %>Arena } from '../arena.js';
|
|
4
|
+
|
|
5
|
+
@ECSSystem()
|
|
6
|
+
export class ApplyMoveInputSystem implements IECSSystem {
|
|
7
|
+
constructor(
|
|
8
|
+
private readonly _InputProvider: InputProvider,
|
|
9
|
+
private readonly _PlayerResources: PlayerResources,
|
|
10
|
+
private readonly _Velocity2d: Velocity2d,
|
|
11
|
+
) {}
|
|
12
|
+
|
|
13
|
+
public update(tick: number): void {
|
|
14
|
+
const rpcs = this._InputProvider.collectTickRPCs(tick, MoveInput);
|
|
15
|
+
|
|
16
|
+
for (const rpc of rpcs) {
|
|
17
|
+
const playerResource = this._PlayerResources.get(PlayerResource, rpc.meta.playerSlot);
|
|
18
|
+
const entity = playerResource.safe.entity;
|
|
19
|
+
this._Velocity2d.unsafe.velocityX[entity] = rpc.data.directionX * <%= projectName %>Arena.moveSpeed;
|
|
20
|
+
this._Velocity2d.unsafe.velocityY[entity] = rpc.data.directionY * <%= projectName %>Arena.moveSpeed;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { ECSSystem, IECSSystem } from '@lagless/core';
|
|
2
|
+
import { Transform2d, PlayerBody, PlayerFilter } from '../schema/code-gen/index.js';
|
|
3
|
+
import { <%= projectName %>Arena } from '../arena.js';
|
|
4
|
+
|
|
5
|
+
@ECSSystem()
|
|
6
|
+
export class BoundarySystem implements IECSSystem {
|
|
7
|
+
constructor(
|
|
8
|
+
private readonly _PlayerFilter: PlayerFilter,
|
|
9
|
+
private readonly _Transform2d: Transform2d,
|
|
10
|
+
private readonly _PlayerBody: PlayerBody,
|
|
11
|
+
) {}
|
|
12
|
+
|
|
13
|
+
public update(): void {
|
|
14
|
+
for (const entity of this._PlayerFilter) {
|
|
15
|
+
const radius = this._PlayerBody.unsafe.radius[entity];
|
|
16
|
+
const minX = radius;
|
|
17
|
+
const maxX = <%= projectName %>Arena.width - radius;
|
|
18
|
+
const minY = radius;
|
|
19
|
+
const maxY = <%= projectName %>Arena.height - radius;
|
|
20
|
+
|
|
21
|
+
let x = this._Transform2d.unsafe.positionX[entity];
|
|
22
|
+
let y = this._Transform2d.unsafe.positionY[entity];
|
|
23
|
+
|
|
24
|
+
if (x < minX) x = minX;
|
|
25
|
+
else if (x > maxX) x = maxX;
|
|
26
|
+
|
|
27
|
+
if (y < minY) y = minY;
|
|
28
|
+
else if (y > maxY) y = maxY;
|
|
29
|
+
|
|
30
|
+
this._Transform2d.unsafe.positionX[entity] = x;
|
|
31
|
+
this._Transform2d.unsafe.positionY[entity] = y;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { ECSSystem, IECSSystem } from '@lagless/core';
|
|
2
|
+
import { Velocity2d, MovingFilter } from '../schema/code-gen/index.js';
|
|
3
|
+
import { <%= projectName %>Arena } from '../arena.js';
|
|
4
|
+
|
|
5
|
+
@ECSSystem()
|
|
6
|
+
export class DampingSystem implements IECSSystem {
|
|
7
|
+
constructor(
|
|
8
|
+
private readonly _MovingFilter: MovingFilter,
|
|
9
|
+
private readonly _Velocity2d: Velocity2d,
|
|
10
|
+
) {}
|
|
11
|
+
|
|
12
|
+
public update(): void {
|
|
13
|
+
for (const entity of this._MovingFilter) {
|
|
14
|
+
this._Velocity2d.unsafe.velocityX[entity] *= <%= projectName %>Arena.damping;
|
|
15
|
+
this._Velocity2d.unsafe.velocityY[entity] *= <%= projectName %>Arena.damping;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
package/templates/pixi-react/__packageName__-simulation/src/lib/systems/hash-verification.system.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ECSConfig, ECSSystem, InputProvider, PlayerResources, AbstractHashVerificationSystem, DivergenceSignal } from '@lagless/core';
|
|
2
|
+
import { PlayerResource, ReportHash } from '../schema/code-gen/index.js';
|
|
3
|
+
|
|
4
|
+
@ECSSystem()
|
|
5
|
+
export class HashVerificationSystem extends AbstractHashVerificationSystem {
|
|
6
|
+
protected readonly _reportHashRpc = ReportHash;
|
|
7
|
+
protected readonly _playerResourceClass = PlayerResource;
|
|
8
|
+
|
|
9
|
+
constructor(
|
|
10
|
+
ecsConfig: ECSConfig,
|
|
11
|
+
inputProvider: InputProvider,
|
|
12
|
+
playerResources: PlayerResources,
|
|
13
|
+
divergenceSignal: DivergenceSignal,
|
|
14
|
+
) {
|
|
15
|
+
super(ecsConfig, inputProvider, playerResources, divergenceSignal);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { IECSSystemConstructor } from '@lagless/core';
|
|
2
|
+
import { SavePrevTransformSystem } from './save-prev-transform.system.js';
|
|
3
|
+
import { PlayerConnectionSystem } from './player-connection.system.js';
|
|
4
|
+
import { PlayerLeaveSystem } from './player-leave.system.js';
|
|
5
|
+
import { ApplyMoveInputSystem } from './apply-move-input.system.js';
|
|
6
|
+
import { IntegrateSystem } from './integrate.system.js';
|
|
7
|
+
import { DampingSystem } from './damping.system.js';
|
|
8
|
+
import { BoundarySystem } from './boundary.system.js';
|
|
9
|
+
import { HashVerificationSystem } from './hash-verification.system.js';
|
|
10
|
+
|
|
11
|
+
export const <%= projectName %>Systems: IECSSystemConstructor[] = [
|
|
12
|
+
SavePrevTransformSystem,
|
|
13
|
+
PlayerConnectionSystem,
|
|
14
|
+
PlayerLeaveSystem,
|
|
15
|
+
ApplyMoveInputSystem,
|
|
16
|
+
IntegrateSystem,
|
|
17
|
+
DampingSystem,
|
|
18
|
+
BoundarySystem,
|
|
19
|
+
HashVerificationSystem,
|
|
20
|
+
];
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { ECSSystem, IECSSystem } from '@lagless/core';
|
|
2
|
+
import { Transform2d, Velocity2d, MovingFilter } from '../schema/code-gen/index.js';
|
|
3
|
+
|
|
4
|
+
@ECSSystem()
|
|
5
|
+
export class IntegrateSystem implements IECSSystem {
|
|
6
|
+
constructor(
|
|
7
|
+
private readonly _MovingFilter: MovingFilter,
|
|
8
|
+
private readonly _Velocity2d: Velocity2d,
|
|
9
|
+
private readonly _Transform2d: Transform2d,
|
|
10
|
+
) {}
|
|
11
|
+
|
|
12
|
+
public update(): void {
|
|
13
|
+
for (const entity of this._MovingFilter) {
|
|
14
|
+
this._Transform2d.unsafe.positionX[entity] += this._Velocity2d.unsafe.velocityX[entity];
|
|
15
|
+
this._Transform2d.unsafe.positionY[entity] += this._Velocity2d.unsafe.velocityY[entity];
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
package/templates/pixi-react/__packageName__-simulation/src/lib/systems/player-connection.system.ts
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { ECSConfig, ECSSystem, EntitiesManager, IECSSystem, InputProvider, PlayerResources, Prefab } from '@lagless/core';
|
|
2
|
+
import { PlayerBody, PlayerJoined, PlayerResource, Transform2d, Velocity2d } from '../schema/code-gen/index.js';
|
|
3
|
+
import { <%= projectName %>Arena } from '../arena.js';
|
|
4
|
+
|
|
5
|
+
@ECSSystem()
|
|
6
|
+
export class PlayerConnectionSystem implements IECSSystem {
|
|
7
|
+
private readonly _playerPrefab = Prefab.create()
|
|
8
|
+
.with(Transform2d)
|
|
9
|
+
.with(Velocity2d)
|
|
10
|
+
.with(PlayerBody, { radius: <%= projectName %>Arena.playerRadius });
|
|
11
|
+
|
|
12
|
+
constructor(
|
|
13
|
+
private readonly _ECSConfig: ECSConfig,
|
|
14
|
+
private readonly _InputProvider: InputProvider,
|
|
15
|
+
private readonly _Transform2d: Transform2d,
|
|
16
|
+
private readonly _PlayerBody: PlayerBody,
|
|
17
|
+
private readonly _EntitiesManager: EntitiesManager,
|
|
18
|
+
private readonly _PlayerResources: PlayerResources,
|
|
19
|
+
) {}
|
|
20
|
+
|
|
21
|
+
public update(tick: number): void {
|
|
22
|
+
const rpcs = this._InputProvider.collectTickRPCs(tick, PlayerJoined);
|
|
23
|
+
const maxPlayers = this._ECSConfig.maxPlayers;
|
|
24
|
+
const spacing = <%= projectName %>Arena.width * 0.5 / Math.max(maxPlayers, 1);
|
|
25
|
+
|
|
26
|
+
for (const rpc of rpcs) {
|
|
27
|
+
const slot = rpc.data.slot;
|
|
28
|
+
const entity = this._EntitiesManager.createEntity(this._playerPrefab);
|
|
29
|
+
|
|
30
|
+
this._PlayerBody.unsafe.playerSlot[entity] = slot;
|
|
31
|
+
|
|
32
|
+
const spawnX = <%= projectName %>Arena.width * 0.25 + slot * spacing;
|
|
33
|
+
const spawnY = <%= projectName %>Arena.height * 0.5;
|
|
34
|
+
this._Transform2d.unsafe.positionX[entity] = spawnX;
|
|
35
|
+
this._Transform2d.unsafe.positionY[entity] = spawnY;
|
|
36
|
+
this._Transform2d.unsafe.prevPositionX[entity] = spawnX;
|
|
37
|
+
this._Transform2d.unsafe.prevPositionY[entity] = spawnY;
|
|
38
|
+
|
|
39
|
+
const playerResource = this._PlayerResources.get(PlayerResource, slot);
|
|
40
|
+
playerResource.safe.entity = entity;
|
|
41
|
+
playerResource.safe.connected = 1;
|
|
42
|
+
for (let i = 0; i < rpc.data.playerId.length; i++) {
|
|
43
|
+
playerResource.unsafe.id[i] = rpc.data.playerId[i];
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
package/templates/pixi-react/__packageName__-simulation/src/lib/systems/player-leave.system.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { ECSSystem, EntitiesManager, IECSSystem, InputProvider, PlayerResources } from '@lagless/core';
|
|
2
|
+
import { PlayerLeft, PlayerResource } from '../schema/code-gen/index.js';
|
|
3
|
+
|
|
4
|
+
@ECSSystem()
|
|
5
|
+
export class PlayerLeaveSystem implements IECSSystem {
|
|
6
|
+
constructor(
|
|
7
|
+
private readonly _InputProvider: InputProvider,
|
|
8
|
+
private readonly _EntitiesManager: EntitiesManager,
|
|
9
|
+
private readonly _PlayerResources: PlayerResources,
|
|
10
|
+
) {}
|
|
11
|
+
|
|
12
|
+
public update(tick: number): void {
|
|
13
|
+
const rpcs = this._InputProvider.collectTickRPCs(tick, PlayerLeft);
|
|
14
|
+
|
|
15
|
+
for (const rpc of rpcs) {
|
|
16
|
+
const player = this._PlayerResources.get(PlayerResource, rpc.data.slot);
|
|
17
|
+
player.safe.connected = 0;
|
|
18
|
+
this._EntitiesManager.removeEntity(player.safe.entity);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ECSSystem, IECSSystem } from '@lagless/core';
|
|
2
|
+
import { Transform2d, PlayerFilter } from '../schema/code-gen/index.js';
|
|
3
|
+
|
|
4
|
+
@ECSSystem()
|
|
5
|
+
export class SavePrevTransformSystem implements IECSSystem {
|
|
6
|
+
constructor(
|
|
7
|
+
private readonly _PlayerFilter: PlayerFilter,
|
|
8
|
+
private readonly _Transform2d: Transform2d,
|
|
9
|
+
) {}
|
|
10
|
+
|
|
11
|
+
public update(): void {
|
|
12
|
+
for (const entity of this._PlayerFilter) {
|
|
13
|
+
this._Transform2d.unsafe.prevPositionX[entity] = this._Transform2d.unsafe.positionX[entity];
|
|
14
|
+
this._Transform2d.unsafe.prevPositionY[entity] = this._Transform2d.unsafe.positionY[entity];
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"moduleResolution": "bundler",
|
|
6
|
+
"lib": ["ES2022"],
|
|
7
|
+
"strict": true,
|
|
8
|
+
"esModuleInterop": true,
|
|
9
|
+
"skipLibCheck": true,
|
|
10
|
+
"forceConsistentCasingInFileNames": true,
|
|
11
|
+
"experimentalDecorators": true,
|
|
12
|
+
"emitDecoratorMetadata": true,
|
|
13
|
+
"resolveJsonModule": true,
|
|
14
|
+
"isolatedModules": true,
|
|
15
|
+
"noEmit": true,
|
|
16
|
+
"jsx": "react-jsx",
|
|
17
|
+
"baseUrl": ".",
|
|
18
|
+
"rootDir": "src",
|
|
19
|
+
"outDir": "dist"
|
|
20
|
+
},
|
|
21
|
+
"include": ["src/**/*.ts"]
|
|
22
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"private": true,
|
|
3
|
+
"scripts": {
|
|
4
|
+
"dev:frontend": "pnpm --filter <%= packageName %>-frontend dev",
|
|
5
|
+
"dev:backend": "pnpm --filter <%= packageName %>-backend dev",
|
|
6
|
+
"codegen": "npx @lagless/codegen -c <%= packageName %>-simulation/src/lib/schema/ecs.yaml"
|
|
7
|
+
}
|
|
8
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"moduleResolution": "bundler",
|
|
6
|
+
"lib": ["ES2022"],
|
|
7
|
+
"strict": true,
|
|
8
|
+
"esModuleInterop": true,
|
|
9
|
+
"skipLibCheck": true,
|
|
10
|
+
"forceConsistentCasingInFileNames": true,
|
|
11
|
+
"experimentalDecorators": true,
|
|
12
|
+
"emitDecoratorMetadata": true,
|
|
13
|
+
"resolveJsonModule": true,
|
|
14
|
+
"isolatedModules": true,
|
|
15
|
+
"noEmit": true,
|
|
16
|
+
"declaration": true,
|
|
17
|
+
"declarationMap": true,
|
|
18
|
+
"sourceMap": true,
|
|
19
|
+
"composite": true
|
|
20
|
+
}
|
|
21
|
+
}
|