Skip to content

Commit

Permalink
node replicator
Browse files Browse the repository at this point in the history
  • Loading branch information
wyb10a10 committed Aug 6, 2023
1 parent b356a48 commit 8431d2b
Show file tree
Hide file tree
Showing 12 changed files with 128 additions and 6 deletions.
4 changes: 2 additions & 2 deletions assets/Script/example/sync/SyncUI.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { _decorator, Component, Button } from 'cc';
import { ServerReplicator } from '../../sync/ServerReplicator';
import { ClientReplicator } from '../../sync/ClientReplicator';
import { ServerReplicator } from '../../sync/components/ServerReplicator';
import ClientReplicator from '../../sync/components/ClientReplicator';
const { ccclass, property } = _decorator;

@ccclass('SyncUI')
Expand Down
92 changes: 92 additions & 0 deletions assets/Script/sync/NodeReplicator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import { Node, Component } from 'cc';
import { IReplicator } from './SyncUtil';
import { createReplicator } from './ReplicatorFactory';
import { getReplicateMark } from './ReplicateMark';

class NodeReplicator implements IReplicator {
private target: Node;
private replicators: Map<string, IReplicator> = new Map();
private version: number = 0;

constructor(target: Node) {
this.target = target;
this.scanNode(target);
}

private scanNode(node: Node): void {
for (const component of node.components) {
if (this.isReplicated(component)) {
const key = this.getComponentKey(node, component);
const replicator = createReplicator(component);
if (replicator) {
this.replicators.set(key, replicator);
} else {
console.error(`NodeReplicator scanNode error, key: ${key}`);
}
}
}

for (const child of node.children) {
this.scanNode(child);
}
}

private isReplicated(component: Component): boolean {
if (getReplicateMark(component.constructor, false)) {
return true;
}
return false;
}

private getComponentKey(node: Node, component: Component): string {
return `${this.getNodePath(node)}:${component.constructor.name}`;
}

private getNodePath(node: Node): string {
let path = node.name;
let current = node.parent;

while (current) {
path = `${current.name}/${path}`;
current = current.parent;
}

return path;
}

genDiff(fromVersion: number, toVersion: number): any {
const diff: any = {};

for (const [key, replicator] of this.replicators) {
const componentDiff = replicator.genDiff(fromVersion, toVersion);
if (componentDiff) {
diff[key] = componentDiff;
}
}

return Object.keys(diff).length > 0 ? diff : false;
}

applyDiff(diff: any): void {
for (const key in diff) {
const replicator = this.replicators.get(key);
if (replicator) {
replicator.applyDiff(diff[key]);
} else {
console.error(`NodeReplicator applyDiff error, key: ${key}`);
}
}
}

getVersion(): number {
return this.version;
}

getTarget(): Node {
return this.target;
}

setTarget(target: Node): void {
this.target = target;
}
}
9 changes: 9 additions & 0 deletions assets/Script/sync/NodeReplicator.ts.meta
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"ver": "4.0.23",
"importer": "typescript",
"imported": true,
"uuid": "0d64f4ba-955d-4b1d-84c0-e4a3890cf27a",
"files": [],
"subMetas": {},
"userData": {}
}
4 changes: 2 additions & 2 deletions assets/Script/sync/ReplicateMark.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,8 @@ export interface ReplicateMarkInfo {
* @param target 要修饰的类对象
* @returns ReplicateMark
*/
export function getReplicateMark(target: any, autoCreator: boolean = true, option?: ObjectReplicatedOption): ReplicateMark {
let ret: ReplicateMark = target[REPLICATE_MARK_INDEX];
export function getReplicateMark(target: any, autoCreator: boolean = true, option?: ObjectReplicatedOption): ReplicateMark | undefined {
let ret: ReplicateMark | undefined = target[REPLICATE_MARK_INDEX];
if (!ret && autoCreator) {
ret = new ReplicateMark(target, option);
Object.defineProperty(target, REPLICATE_MARK_INDEX, {
Expand Down
13 changes: 11 additions & 2 deletions assets/Script/sync/SyncUtil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,12 @@ export function getReplicator(target: any, autoCreator: boolean = false, mark?:
if (!mark) {
mark = getReplicateMark(target.constructor, true);
// 当类装饰器作用时,如果属性还未生成,则需要使用类的实例进行初始化
mark.initMark(target);
if (mark) {
mark.initMark(target);
} else {
console.warn(`getReplicator error, ${target.constructor.name} not found in ReplicateMark`);
return null;
}
}
ret = createReplicator(target, mark);
if (ret) {
Expand All @@ -77,6 +82,10 @@ function makePropertyReplicatedMark(cls: any, propertyKey: string, descriptor?:
if (descriptor) {
// 获取这个类的同步标记
let markObj = getReplicateMark(cls, true);
if (!markObj) {
console.warn(`makePropertyReplicatedMark error, ${cls} not found in ReplicateMark`);
return;
}
// 初始化默认值def
if ('initializer' in descriptor && typeof descriptor['initializer'] == 'function') {
let def = (descriptor as any).initializer();
Expand All @@ -97,7 +106,7 @@ function makePropertyReplicatedMark(cls: any, propertyKey: string, descriptor?:
* @param cls
* @param option
*/
function makeObjectReplicatedMark(cls: any, option?: ObjectReplicatedOption): ReplicateMark {
function makeObjectReplicatedMark(cls: any, option?: ObjectReplicatedOption): ReplicateMark | undefined {
return getReplicateMark(cls, true, option);
}

Expand Down
12 changes: 12 additions & 0 deletions assets/Script/sync/components.meta
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"ver": "1.1.0",
"importer": "directory",
"imported": true,
"uuid": "9fcf55da-4c89-422b-883b-0131dc4e1360",
"files": [],
"subMetas": {},
"userData": {
"compressionType": {},
"isRemoteBundle": {}
}
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

0 comments on commit 8431d2b

Please sign in to comment.