Add basic multiplayer
This commit is contained in:
parent
0f0a1eaf67
commit
46a48e7c15
46 changed files with 1361 additions and 753 deletions
1
shared/.eslintignore
Normal file
1
shared/.eslintignore
Normal file
|
|
@ -0,0 +1 @@
|
|||
**/*.js
|
||||
29
shared/.eslintrc.json
Normal file
29
shared/.eslintrc.json
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
"root": true,
|
||||
"env": {
|
||||
"browser": true,
|
||||
"es2020": true
|
||||
},
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/eslint-recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"prettier",
|
||||
"prettier/@typescript-eslint"
|
||||
],
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 11,
|
||||
"sourceType": "module"
|
||||
},
|
||||
"plugins": ["unused-imports", "@typescript-eslint", "prettier"],
|
||||
"rules": {
|
||||
"prettier/prettier": "error",
|
||||
"no-unused-vars": "off",
|
||||
"unused-imports/no-unused-imports-ts": "error",
|
||||
"@typescript-eslint/no-unused-vars": ["warn", { "argsIgnorePattern": "^_" }],
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
"@typescript-eslint/explicit-module-boundary-types": "off",
|
||||
"@typescript-eslint/no-non-null-assertion": "off"
|
||||
}
|
||||
}
|
||||
4
shared/.gitignore
vendored
Normal file
4
shared/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
dist
|
||||
node_modules
|
||||
package-lock.json
|
||||
.firebase
|
||||
7
shared/.prettierrc
Normal file
7
shared/.prettierrc
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"trailingComma": "es5",
|
||||
"printWidth": 90,
|
||||
"tabWidth": 2,
|
||||
"singleQuote": true,
|
||||
"endOfLine": "lf"
|
||||
}
|
||||
16
shared/firebase.json
Normal file
16
shared/firebase.json
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"hosting": {
|
||||
"public": "dist",
|
||||
"ignore": [
|
||||
"firebase.json",
|
||||
"**/.*",
|
||||
"**/node_modules/**"
|
||||
],
|
||||
"rewrites": [
|
||||
{
|
||||
"source": "**",
|
||||
"destination": "/index.html"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
17
shared/package.json
Normal file
17
shared/package.json
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"name": "shared",
|
||||
"version": "0.0.0",
|
||||
"description": "Shared library between backend and frontend",
|
||||
"main": "src/main.ts",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"@types/gl-matrix": "^3.2.0",
|
||||
"@types/uuid": "^8.0.0",
|
||||
"gl-matrix": "^3.3.0",
|
||||
"uuid": "^8.2.0"
|
||||
}
|
||||
}
|
||||
7
shared/src/commands/broadcast-commands.ts
Normal file
7
shared/src/commands/broadcast-commands.ts
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
import { CommandReceiver } from './command-receiver';
|
||||
import { CommandGenerator } from './command-generator';
|
||||
|
||||
export const broadcastCommands = (
|
||||
commandGenerators: Array<CommandGenerator>,
|
||||
commandReceivers: Array<CommandReceiver>
|
||||
) => commandReceivers.forEach((r) => commandGenerators.forEach((g) => g.subscribe(r)));
|
||||
14
shared/src/commands/command-generator.ts
Normal file
14
shared/src/commands/command-generator.ts
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
import { CommandReceiver } from './command-receiver';
|
||||
import { Command } from './command';
|
||||
|
||||
export class CommandGenerator {
|
||||
private subscribers: Array<CommandReceiver> = [];
|
||||
|
||||
public subscribe(subscriber: CommandReceiver): void {
|
||||
this.subscribers.push(subscriber);
|
||||
}
|
||||
|
||||
protected sendCommandToSubcribers(command: Command): void {
|
||||
this.subscribers.forEach((s) => s.sendCommand(command));
|
||||
}
|
||||
}
|
||||
25
shared/src/commands/command-receiver.ts
Normal file
25
shared/src/commands/command-receiver.ts
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
import { Command } from './command';
|
||||
|
||||
export type CommandExecutors = {
|
||||
[type: string]: (command: Command) => void;
|
||||
};
|
||||
|
||||
export abstract class CommandReceiver {
|
||||
protected commandExecutors: CommandExecutors = {};
|
||||
|
||||
protected defaultCommandExecutor(command: Command) {}
|
||||
|
||||
public reactsToCommand(commandType: string): boolean {
|
||||
return Object.prototype.hasOwnProperty.call(this.commandExecutors, commandType);
|
||||
}
|
||||
|
||||
public sendCommand(command: Command) {
|
||||
const commandType = command.type;
|
||||
|
||||
if (Object.prototype.hasOwnProperty.call(this.commandExecutors, commandType)) {
|
||||
this.commandExecutors[commandType](command);
|
||||
} else {
|
||||
this.defaultCommandExecutor(command);
|
||||
}
|
||||
}
|
||||
}
|
||||
7
shared/src/commands/command.ts
Normal file
7
shared/src/commands/command.ts
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
import { Id } from '../transport/identity';
|
||||
|
||||
export abstract class Command {
|
||||
public get type(): string {
|
||||
return (this as any).constructor.type;
|
||||
}
|
||||
}
|
||||
13
shared/src/commands/types/create-objects.ts
Normal file
13
shared/src/commands/types/create-objects.ts
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
import { Command } from '../command';
|
||||
|
||||
export class CreateObjectsCommand extends Command {
|
||||
public static readonly type = 'CreateObjectsCommand';
|
||||
|
||||
public constructor(public readonly serializedObjects: string) {
|
||||
super();
|
||||
}
|
||||
|
||||
public toJSON(): any {
|
||||
return [this.type, this.serializedObjects];
|
||||
}
|
||||
}
|
||||
13
shared/src/commands/types/create-player.ts
Normal file
13
shared/src/commands/types/create-player.ts
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
import { Command } from '../command';
|
||||
|
||||
export class CreatePlayerCommand extends Command {
|
||||
public static readonly type = 'CreatePlayerCommand';
|
||||
|
||||
public constructor(public readonly serializedPlayer: string) {
|
||||
super();
|
||||
}
|
||||
|
||||
public toJSON(): any {
|
||||
return [this.type, this.serializedPlayer];
|
||||
}
|
||||
}
|
||||
14
shared/src/commands/types/delete-objects.ts
Normal file
14
shared/src/commands/types/delete-objects.ts
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
import { Id } from '../../transport/identity';
|
||||
import { Command } from '../command';
|
||||
|
||||
export class DeleteObjectsCommand extends Command {
|
||||
public static readonly type = 'DeleteObjectsCommand';
|
||||
|
||||
public constructor(public readonly ids: Array<Id>) {
|
||||
super();
|
||||
}
|
||||
|
||||
public toJSON(): any {
|
||||
return [this.type, this.ids];
|
||||
}
|
||||
}
|
||||
14
shared/src/commands/types/move-action.ts
Normal file
14
shared/src/commands/types/move-action.ts
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
import { vec2 } from 'gl-matrix';
|
||||
import { Command } from '../command';
|
||||
|
||||
export class MoveActionCommand extends Command {
|
||||
public static readonly type = 'MoveActionCommand';
|
||||
|
||||
public constructor(public readonly delta: vec2) {
|
||||
super();
|
||||
}
|
||||
|
||||
public toJSON(): any {
|
||||
return [this.type, this.delta];
|
||||
}
|
||||
}
|
||||
14
shared/src/commands/types/primary-action.ts
Normal file
14
shared/src/commands/types/primary-action.ts
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
import { vec2 } from 'gl-matrix';
|
||||
import { Command } from '../command';
|
||||
|
||||
export class PrimaryActionCommand extends Command {
|
||||
public static readonly type = 'PrimaryActionCommand';
|
||||
|
||||
public constructor(public readonly position: vec2) {
|
||||
super();
|
||||
}
|
||||
|
||||
public toJSON(): any {
|
||||
return [this.type, this.position];
|
||||
}
|
||||
}
|
||||
14
shared/src/commands/types/secondary-action.ts
Normal file
14
shared/src/commands/types/secondary-action.ts
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
import { vec2 } from 'gl-matrix';
|
||||
import { Command } from '../command';
|
||||
|
||||
export class SecondaryActionCommand extends Command {
|
||||
public static readonly type = 'SecondaryActionCommand';
|
||||
|
||||
public constructor(public readonly position: vec2) {
|
||||
super();
|
||||
}
|
||||
|
||||
public toJSON(): any {
|
||||
return [this.type, this.position];
|
||||
}
|
||||
}
|
||||
14
shared/src/commands/types/set-view-area-action.ts
Normal file
14
shared/src/commands/types/set-view-area-action.ts
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
import { Rectangle } from '../../helper/rectangle';
|
||||
import { Command } from '../command';
|
||||
|
||||
export class SetViewAreaActionCommand extends Command {
|
||||
public static readonly type = 'SetViewAreaAction';
|
||||
|
||||
public constructor(public readonly viewArea: Rectangle) {
|
||||
super();
|
||||
}
|
||||
|
||||
public toJSON(): any {
|
||||
return [this.type, this.viewArea];
|
||||
}
|
||||
}
|
||||
14
shared/src/commands/types/ternary-action.ts
Normal file
14
shared/src/commands/types/ternary-action.ts
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
import { vec2 } from 'gl-matrix';
|
||||
import { Command } from '../command';
|
||||
|
||||
export class TernaryActionCommand extends Command {
|
||||
public static readonly type = 'TernaryActionCommand';
|
||||
|
||||
public constructor(public readonly position: vec2) {
|
||||
super();
|
||||
}
|
||||
|
||||
public toJSON(): any {
|
||||
return [this.type, this.position];
|
||||
}
|
||||
}
|
||||
13
shared/src/commands/types/update-objects.ts
Normal file
13
shared/src/commands/types/update-objects.ts
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
import { Command } from '../command';
|
||||
|
||||
export class UpdateObjectsCommand extends Command {
|
||||
public static readonly type = 'UpdateObjectsCommand';
|
||||
|
||||
public constructor(public readonly serializedObjects: string) {
|
||||
super();
|
||||
}
|
||||
|
||||
public toJSON(): any {
|
||||
return [this.type, this.serializedObjects];
|
||||
}
|
||||
}
|
||||
31
shared/src/helper/array.ts
Normal file
31
shared/src/helper/array.ts
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
declare global {
|
||||
interface Array<T> {
|
||||
x: number;
|
||||
y: number;
|
||||
}
|
||||
|
||||
interface Float32Array {
|
||||
x: number;
|
||||
y: number;
|
||||
}
|
||||
}
|
||||
|
||||
const setIndexAlias = (name: string, index: number, type: any) => {
|
||||
if (!Object.prototype.hasOwnProperty.call(type.prototype, name)) {
|
||||
Object.defineProperty(type.prototype, name, {
|
||||
get() {
|
||||
return this[index];
|
||||
},
|
||||
set(value) {
|
||||
this[index] = value;
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export const applyArrayPlugins = () => {
|
||||
setIndexAlias('x', 0, Array);
|
||||
setIndexAlias('y', 1, Array);
|
||||
setIndexAlias('x', 0, Float32Array);
|
||||
setIndexAlias('y', 1, Float32Array);
|
||||
};
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue