Skip to content

Commit ace0c8a

Browse files
committed
feat: basic framework
1 parent 96521e7 commit ace0c8a

File tree

11 files changed

+271
-0
lines changed

11 files changed

+271
-0
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
dist
2+
node_modules
3+
yarn.lock

package.json

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"name": "netcode",
3+
"version": "1.0.0",
4+
"description": "A js game framework for state-synchronization.",
5+
"main": "dist/netcode.js",
6+
"types": "dist/index.d.ts",
7+
"repository": "https://github.com/netcodejs/netcode",
8+
"author": "moruiyi",
9+
"license": "GPL-3.0-or-later",
10+
"devDependencies": {
11+
"rollup": "^2.39.0",
12+
"rollup-plugin-typescript2": "^0.30.0",
13+
"tslib": "^2.1.0",
14+
"typescript": "^4.1.5"
15+
},
16+
"scripts": {
17+
"build": "yarn run rollup -c"
18+
}
19+
}

rollup.config.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import typescript from 'rollup-plugin-typescript2'
2+
3+
export default {
4+
input: "src/index.ts",
5+
output: {
6+
file: "dist/netcode.js",
7+
format: "es"
8+
},
9+
plugins: [typescript()]
10+
}

src/component.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { Macro } from "./macro";
2+
3+
export let ComponentClassType: any[] = []
4+
export function Component<T extends { new(): any }>(target: T) {
5+
target.prototype.__classId__ = ComponentClassType.push(target) - 1;
6+
}
7+
8+
export function Param(type: ParamType): PropertyDecorator {
9+
return function(target: any, propertyKey: string | symbol) {
10+
if (!target.__schema__)
11+
target.__schema__ = { count: 0, props: {} }
12+
const s = target.__schema__;
13+
14+
const paramIndex = s.count++;
15+
const v = { propertyKey, type, paramIndex };
16+
s.props[paramIndex] = v
17+
s.props[propertyKey] = v
18+
}
19+
}
20+
21+
export enum ParamType {
22+
i8, u8, i16, u16, i32, u32, i64, u64, int, long, float, double, string, bool, f32, f64
23+
}
24+
25+
export interface IComponent {
26+
owner?:number;
27+
__schema__?: Record<string | number, string | number>
28+
29+
onLoad?(): void;
30+
onStart?(): void;
31+
onDestroy?(): void;
32+
33+
update?(): void;
34+
fixedUpdate?(): void;
35+
lateUpdate?(): void;
36+
}

src/data/serializable.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
export interface Serializable<T extends String | ArrayBuffer> {
2+
ser(buffer: DataBuffer<T>): void;
3+
deser(buffer: DataBuffer<T>): void;
4+
}
5+
6+
export interface DataBuffer<T extends String | ArrayBuffer> {
7+
8+
}

src/domain.ts

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import { Entity } from "./entity";
2+
import { Macro } from "./macro";
3+
4+
class EntityNotValidError extends Error {}
5+
class EntityRepeatRegisteredError extends Error {}
6+
class EntityGroupOutOfRangeYouCanOpenAutoResize extends Error {}
7+
class DomainDefinition {
8+
private _entities: (Entity | null)[]
9+
private _entityVersion: number[]
10+
private _destroyEntityId: number[]
11+
private _entityIdCursor = 0;
12+
13+
constructor(public capacity = 50, public autoResize = true) {
14+
this._entities = new Array<Entity>(capacity);
15+
this._entityVersion = new Array<number>(capacity);
16+
this._entityVersion.fill(0);
17+
this._destroyEntityId = new Array<number>(capacity);
18+
}
19+
20+
reg(entity: Entity) {
21+
if (this.isValid(entity))
22+
throw new EntityRepeatRegisteredError(entity.toString());
23+
if (this._entityIdCursor == this.capacity && this.autoResize)
24+
this.resize(Math.ceil(this.capacity * 1.5))
25+
else
26+
throw new EntityGroupOutOfRangeYouCanOpenAutoResize(
27+
`Domain: capacity: ${this.capacity}; ` + entity.toString());
28+
this._unlockEntity(entity);
29+
entity.id = this._getEntityId();
30+
entity.version = this._entityVersion[entity.id];
31+
this._lockEntity(entity);
32+
this._entities[entity.id] = entity;
33+
}
34+
35+
unreg(entity: Entity) {
36+
if (!this.isValid(entity))
37+
throw new EntityNotValidError(entity.toString());
38+
this._entityVersion[entity.id]++;
39+
this._destroyEntityId.push(entity.id);
40+
this._entities[entity.id] = null;
41+
}
42+
43+
resize(newSize: number) {
44+
const oldSize = this.capacity;
45+
this._entities.length = newSize;
46+
this._entityVersion.length = newSize;
47+
this._entityVersion.fill(0, oldSize, newSize);
48+
this.capacity = newSize;
49+
}
50+
51+
isValid(entity: Entity) {
52+
return entity.id != Macro.NULL_NUM
53+
&& entity.version != Macro.NULL_NUM
54+
&& entity.version == this._entityVersion[entity.id]
55+
}
56+
57+
private _getEntityId() {
58+
return this._destroyEntityId.length > 0
59+
? this._destroyEntityId.unshift()
60+
: this._entityIdCursor++;
61+
}
62+
63+
private _lockEntity(entity: Entity) {
64+
Object.defineProperties(entity, {
65+
"id": { writable: false },
66+
"version": { writable: false }
67+
})
68+
}
69+
70+
private _unlockEntity(entity: Entity) {
71+
Object.defineProperties(entity, {
72+
"id": { writable: true },
73+
"version": { writable: true }
74+
})
75+
}
76+
}
77+
78+
export const Domain = new DomainDefinition();

src/entity.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { Macro } from "./macro";
2+
3+
export class Entity {
4+
id = Macro.NULL_NUM
5+
version = Macro.NULL_NUM
6+
constructor() {
7+
Object.seal(this);
8+
}
9+
10+
toString() {
11+
return `Entity: id=${this.id},version=${this.version}`
12+
}
13+
}

src/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export * from './component';
2+
export * from './entity';
3+
4+
import './test'

src/macro.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export const Macro = {
2+
NULL_NUM: -1,
3+
NULL_STR: "NULL"
4+
}

src/test.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { Component, IComponent, Param, ParamType, ComponentClassType } from "./component";
2+
3+
@Component
4+
export class ViewComponrnt implements IComponent {
5+
@Param(ParamType.int)
6+
width: number = 0;
7+
@Param(ParamType.int)
8+
height: number = 0;
9+
10+
onLoad() {
11+
12+
}
13+
}
14+
15+
@Component
16+
export class LogicComponent {
17+
@Param(ParamType.bool)
18+
alive: boolean = false
19+
}
20+
21+
let v1 = new ViewComponrnt();
22+
let v2 = new ViewComponrnt();
23+
24+
let l1 = new LogicComponent();
25+
// @ts-ignore
26+
console.log(v1.__schema__, v2.__schema__, v1.__schema__ === v2.__schema__, l1.__schema__, ComponentClassType);

0 commit comments

Comments
 (0)