[add] Engine

This commit is contained in:
2022-08-26 16:48:17 +08:00
parent f67e566f2a
commit d9c19f096c
197 changed files with 10626 additions and 0 deletions

View File

@@ -0,0 +1,43 @@
const CANCEL = Symbol();
export interface CancellationToken {
readonly IsCancellationRequested: boolean;
ThrowIfCancellationRequested(): void;
}
export class CancellationTokenSource {
readonly Token: CancellationToken;
constructor() {
this.Token = new CancellationTokenImpl();
}
Cancel() {
this.Token[CANCEL]();
}
}
export class TaskCancelledException extends Error {
constructor() {
super("Task Cancelled");
Reflect.setPrototypeOf(this, TaskCancelledException.prototype);
}
}
class CancellationTokenImpl implements CancellationToken {
IsCancellationRequested: boolean;
constructor() {
this.IsCancellationRequested = false;
}
ThrowIfCancellationRequested() {
if (this.IsCancellationRequested) {
throw new TaskCancelledException();
}
}
[CANCEL]() {
this.IsCancellationRequested = true;
}
}

View File

@@ -0,0 +1,10 @@
{
"ver": "1.1.0",
"uuid": "9a414131-91a8-4d02-9921-9d1ee01764c3",
"importer": "typescript",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View File

@@ -0,0 +1,13 @@
{
"ver": "1.1.3",
"uuid": "fbfe97a8-24ca-4f67-b049-323652c7194b",
"importer": "folder",
"isBundle": false,
"bundleName": "",
"priority": 1,
"compressionType": {},
"optimizeHotUpdate": {},
"inlineSpriteFrames": {},
"isRemoteBundle": {},
"subMetas": {}
}

View File

@@ -0,0 +1,17 @@
import { BaseEnumerator } from "./BaseEnumerator";
export class ActionEnumerator extends BaseEnumerator {
private _action: Function;
constructor(action: Function) {
super();
this._action = action;
}
next(value?: any): IteratorResult<any> {
if (this._action) {
this._action();
}
return { done: true, value: undefined };
}
}

View File

@@ -0,0 +1,10 @@
{
"ver": "1.1.0",
"uuid": "3cf9e5c3-520f-48a9-8821-9be76d519765",
"importer": "typescript",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View File

@@ -0,0 +1,87 @@
import { IEnumeratorV2, IEnumeratorV2Started } from "../IEnumeratorV2";
import { CoroutineExecutor } from "./CoroutineExecutor";
export abstract class BaseEnumerator implements IEnumeratorV2 {
public nextEnumerator: BaseEnumerator;
abstract next(value?: any): IteratorResult<any>;
Start(target?: any): IEnumeratorV2Started {
let executor = LazyLoad.EnumeratorExecutor(this, target);
CoroutineExecutor.instance.StartCoroutine(executor);
return executor;
}
Then(iterator: Iterator<any>): IEnumeratorV2 {
if (!iterator) return this;
if (iterator instanceof BaseEnumerator) {
BaseEnumerator.getLastEnumerator(this).nextEnumerator = iterator;
return this;
} else {
let enumerator = LazyLoad.SingleEnumerator(iterator);
BaseEnumerator.getLastEnumerator(this).nextEnumerator = enumerator;
return this;
}
}
ThenSerial(...iterators: Iterator<any>[]): IEnumeratorV2 {
let last = BaseEnumerator.getLastEnumerator(this);
for (let iterator of iterators) {
if (iterator instanceof BaseEnumerator) {
last.nextEnumerator = iterator;
} else {
let enumerator = LazyLoad.SingleEnumerator(iterator);
last.nextEnumerator = enumerator;
}
last = last.nextEnumerator;
}
return this;
}
ThenParallel(...iterators: Iterator<any>[]): IEnumeratorV2 {
return this.Then(LazyLoad.ParallelEnumerator(...iterators));
}
ThenAction(action: Function, delaySeconds?:number): IEnumeratorV2 {
if (delaySeconds > 0) {
return this.ThenSerial(LazyLoad.WaitTimeEnumerator(delaySeconds), LazyLoad.ActionEnumerator(action));
} else {
return this.Then(LazyLoad.ActionEnumerator(action));
}
}
ThenWaitTime(seconds: number): IEnumeratorV2 {
return this.Then(LazyLoad.WaitTimeEnumerator(seconds));
}
static getLastEnumerator(enumerator: BaseEnumerator): BaseEnumerator {
let next = enumerator;
while (next.nextEnumerator) {
next = next.nextEnumerator;
}
return next;
}
}
module LazyLoad {
export function EnumeratorExecutor(enumerator: BaseEnumerator, target: any) {
return new (require("./EnumeratorExecutor") as typeof import("./EnumeratorExecutor")).EnumeratorExecutor(enumerator, target);
}
export function SingleEnumerator(iterator: Iterator<any>) {
return new (require("./SingleEnumerator") as typeof import("./SingleEnumerator")).SingleEnumerator(iterator);
}
export function ParallelEnumerator(...iterators: Iterator<any>[]) {
return new (require("./ParallelEnumerator") as typeof import("./ParallelEnumerator")).ParallelEnumerator(iterators);
}
export function WaitTimeEnumerator(seconds: number) {
return new (require("./WaitTimeEnumerator") as typeof import("./WaitTimeEnumerator")).WaitTimeEnumerator(seconds);
}
export function ActionEnumerator(action: Function) {
return new (require("./ActionEnumerator") as typeof import("./ActionEnumerator")).ActionEnumerator(action);
}
}

View File

@@ -0,0 +1,10 @@
{
"ver": "1.1.0",
"uuid": "4084537c-c7e8-4d47-b283-39be77ef9685",
"importer": "typescript",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View File

@@ -0,0 +1,95 @@
import { EnumeratorExecutor } from "./EnumeratorExecutor";
export class CoroutineExecutor {
private static _instance: CoroutineExecutor;
static get instance() {
return CoroutineExecutor._instance = CoroutineExecutor._instance || new CoroutineExecutor();
}
private _executors: EnumeratorExecutor[] = [];
private _nextExecutors: EnumeratorExecutor[] = [];
private _isRunning: boolean = false;
private _cleanRemoved: boolean = false;
private _scheduler: cc.Scheduler;
constructor() {
this._scheduler = cc.director.getScheduler();
this._scheduler.enableForTarget(this);
this._scheduler.scheduleUpdate(this, 0, true);
}
StartCoroutine(executor: EnumeratorExecutor) {
executor.next(0);
//TODO: 這邊要考量next後馬上接BaseEnumerator/Iterator的情形
if (!this._isRunning) {
this._executors.push(executor);
if (this._scheduler.isTargetPaused(this)) {
this._scheduler.resumeTarget(this);
}
} else {
this._nextExecutors.push(executor);
}
}
StopCoroutineBy(target: any) {
if (!target) return;
for (let r of this._executors) {
if (target === r.target) {
r.Stop();
}
}
for (let r of this._nextExecutors) {
if (target === r.target) {
r.Stop();
}
}
}
update(delta: number) {
if (this._nextExecutors.length) {
this._executors.push(...this._nextExecutors);
this._nextExecutors.length = 0;
}
if (this._cleanRemoved) {
// 移除[doneFlag=true]的協程
let index = this._executors.length;
while (index--) {
let r = this._executors[index];
if (r.doneFlag) {
this._executors.splice(index, 1);
}
}
this._cleanRemoved = false;
}
if (this._executors.length == 0) {
if (CC_DEBUG) {
cc.log("[CoroutineV2] All coroutines done");
}
this._scheduler.pauseTarget(this);
return;
}
this._isRunning = true;
// 執行協程
for (let r of this._executors) {
if (r.doneFlag || r.pauseFlag || r.childFlag)
{
if (r.doneFlag) {
this._cleanRemoved = true;
}
continue;
}
r.next(delta);
}
this._isRunning = false;
}
}

View File

@@ -0,0 +1,10 @@
{
"ver": "1.1.0",
"uuid": "f25b1e42-90d8-4fc0-9925-6e7e92296d57",
"importer": "typescript",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View File

@@ -0,0 +1,169 @@
import { IEnumeratorV2Started } from "../IEnumeratorV2";
import { BaseEnumerator } from "./BaseEnumerator";
import { SingleEnumerator } from "./SingleEnumerator";
export class EnumeratorExecutor implements IEnumeratorV2Started {
public Current: any;
public target: any;
public pauseFlag: boolean;
public doneFlag: boolean;
public childFlag: boolean;
public asyncFlag: boolean;
public error: any;
private _executor: EnumeratorExecutor;
private _enumerator: BaseEnumerator;
constructor(enumerator: BaseEnumerator, target: any) {
this.target = target;
this._enumerator = enumerator;
}
next(delta?: any): IteratorResult<any> {
if (this._executor && this._executor.doneFlag) {
this._executor = null;
}
if (this.doneFlag || (!this._enumerator && !this._executor)) {
this.doneFlag = true;
return { done: true, value: undefined };
}
if (this.asyncFlag || this.pauseFlag) return { done: false, value: undefined };
let result: IteratorResult<any>;
if (this._executor) {
result = this._executor.next(delta);
this.Current = this._executor.Current;
if (this._executor.doneFlag) {
this._executor = null;
} else {
result.done = false;
return result;
}
}
if (!this._enumerator) {
this.doneFlag = true;
return { done: true, value: undefined };
}
try {
result = this._enumerator.next(delta);
let value = result.value;
let done = result.done;
if (value) {
// Iterator
if (typeof value[Symbol.iterator] === 'function') {
value = new SingleEnumerator(<Iterator<any>>value);
}
if (value instanceof BaseEnumerator) {
if (!done) {
BaseEnumerator.getLastEnumerator(value).nextEnumerator = this._enumerator;
}
this._enumerator = value;
result = this._enumerator.next(delta);
value = result.value;
done = result.done;
if (value) {
// Iterator again
if (typeof value[Symbol.iterator] === 'function') {
value = new SingleEnumerator(<Iterator<any>>value);
}
if (value instanceof BaseEnumerator) {
if (!done) {
BaseEnumerator.getLastEnumerator(value).nextEnumerator = this._enumerator;
}
this._enumerator = value;
result.done = false;
done = false;
}
}
}
if (value instanceof EnumeratorExecutor) {
if (done) {
this._enumerator = this._enumerator.nextEnumerator;
}
value.childFlag = true;
result.done = false;
done = false;
this._executor = value;
} else if (Promise.resolve(value) === value) {
this.asyncFlag = true;
result.done = false;
done = false;
(<Promise<any>>value)
.then(v => {
this.asyncFlag = false;
this.Current = v;
if (done) {
this._enumerator = this._enumerator.nextEnumerator;
}
})
.catch(e => {
this.asyncFlag = false;
this.doneFlag = true;
this._enumerator = null;
this.error = e;
if (e instanceof Error) {
cc.error(e.stack);
} else {
cc.error(`Error: ${JSON.stringify(e)}`);
}
});
}
this.Current = value;
}
if (done) {
this._enumerator = this._enumerator.nextEnumerator;
if (this._enumerator) {
result.done = false;
}
}
}
catch (e)
{
this.doneFlag = true;
this.error = e;
if (e instanceof Error) {
cc.error(e.stack);
} else {
cc.error(`Error: ${JSON.stringify(e)}`);
}
result = { done: true, value: e };
}
return result;
}
Stop(): void {
this.doneFlag = true;
if (this._executor) {
this._executor.Stop();
}
}
Pause(): void {
this.pauseFlag = true;
if (this._executor) {
this._executor.Pause();
}
}
Resume(): void {
this.pauseFlag = false;
if (this._executor) {
this._executor.Resume();
}
}
}

View File

@@ -0,0 +1,10 @@
{
"ver": "1.1.0",
"uuid": "91cb70ed-e6f9-4ce0-b7c5-1720087b3bd7",
"importer": "typescript",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View File

@@ -0,0 +1,46 @@
import { BaseEnumerator } from "./BaseEnumerator";
import { EnumeratorExecutor } from "./EnumeratorExecutor";
import { SingleEnumerator } from "./SingleEnumerator";
export class ParallelEnumerator extends BaseEnumerator {
private _executors: EnumeratorExecutor[] = [];
constructor(iterators: Iterator<any>[]) {
super();
if (iterators && iterators.length) {
for (let iterator of iterators) {
if (iterator instanceof BaseEnumerator) {
this._executors.push(new EnumeratorExecutor(iterator, null));
} else {
this._executors.push(new EnumeratorExecutor(new SingleEnumerator(iterator), null));
}
}
}
}
next(value?: any): IteratorResult<any> {
if (this._executors.length) {
// 先移除[doneFlag=true]協程
let index = this._executors.length;
while (index--) {
let r = this._executors[index];
if (r.doneFlag) {
this._executors.splice(index, 1);
}
}
if (this._executors.length == 0) {
return { done: true, value: undefined };
}
// 執行協程
for (let r of this._executors) {
r.next(value);
}
return { done: false, value: undefined };
}
return { done: true, value: undefined };
}
}

View File

@@ -0,0 +1,10 @@
{
"ver": "1.1.0",
"uuid": "017ebc9a-5152-4f94-bbaf-e3b914e87b41",
"importer": "typescript",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View File

@@ -0,0 +1,18 @@
import { BaseEnumerator } from "./BaseEnumerator";
export class SingleEnumerator extends BaseEnumerator {
private _iterator: Iterator<any>;
constructor(iterator: Iterator<any>) {
super();
this._iterator = iterator;
}
next(value?: any): IteratorResult<any> {
if (!this._iterator) {
return { done: true, value: undefined };
}
return this._iterator.next(value);
}
}

View File

@@ -0,0 +1,10 @@
{
"ver": "1.1.0",
"uuid": "c439d019-2da8-48b8-a65b-bff928d0fda8",
"importer": "typescript",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View File

@@ -0,0 +1,21 @@
import { BaseEnumerator } from "./BaseEnumerator";
export class WaitTimeEnumerator extends BaseEnumerator {
private _seconds: number;
constructor(seconds: number) {
super();
this._seconds = seconds;
}
next(value?: any): IteratorResult<any> {
let delta = value as number;
this._seconds -= delta;
if (this._seconds <= 0) {
return { done: true, value: 0 };
} else {
return { done: false, value: this._seconds };
}
}
}

View File

@@ -0,0 +1,10 @@
{
"ver": "1.1.0",
"uuid": "a3038e6f-1bb4-4aff-a686-b69209df3592",
"importer": "typescript",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View File

@@ -0,0 +1,199 @@
import { CoroutineV2 } from "./CoroutineV2";
import { IEnumeratorV2Started } from "./IEnumeratorV2";
const {ccclass, property} = cc._decorator;
class A {
private numbers: number[] = [1, 2];
private index = 0;
[Symbol.iterator](): IterableIterator<any> {
return this;
}
next(value?: any): IteratorResult<any> {
if (this.index < this.numbers.length) {
let value = this.numbers[this.index++];
cc.log(`A=> ${value}`);
return {
done: false,
value: value
};
}
return { done: true, value: undefined };
}
}
@ccclass
export default class CoroutineExample extends cc.Component {
private _routine: IEnumeratorV2Started;
private _obj: Object = { "a": true };
private _obj2: Object = { "b": true };
private _num: number = 3;
button1Clicked() {
// this._routine = CoroutineV2
// .Parallel(this.Coroutine1(1, 3), this.Coroutine1(4, 6))
// .ThenWaitTime(2)
// .Then(this.Coroutine1(7, 9))
// .ThenWaitTime(2)
// .ThenAction(() => cc.log("action callback 1"))
// .ThenWaitTime(2)
// .ThenAction(this.actionCallback)
// //.Start(this);
// .Start(this);
// this._routine = CoroutineV2.Single(this.FunA()).Start(this);
this._routine = CoroutineV2.Single(this.Test1_1()).Start(this);
// this._routine = CoroutineV2.Single(this.Test2_1()).Start(this);
}
*Test1_1() {
yield null;
yield *this.Test1_2();
// CoroutineV2.Single(this.Test1_3()).Start(this);
yield this.Test1_3();
}
*Test1_2() {
yield null;
}
*Test1_3() {
yield this.Test1_3_1();
yield CoroutineV2.Single(this.Test1_4()).Start(this._obj);
// yield CoroutineV2.Single(this.Test1_4()); //.Start(this);
// yield *this.Test1_4();
cc.log("main wait 3");
yield CoroutineV2.WaitTime(2);
cc.log("done");
}
*Test1_3_1() {
yield this.Test1_3_2();
yield CoroutineV2.WaitTime(1);
cc.log("Test1_3_1.1");
yield CoroutineV2.WaitTime(1);
cc.log("Test1_3_1.2");
}
*Test1_3_2() {
yield this.Test1_3_3();
yield CoroutineV2.WaitTime(1);
cc.log("Test1_3_2.1");
yield CoroutineV2.WaitTime(1);
cc.log("Test1_3_2.2");
yield CoroutineV2.WaitTime(1);
cc.log("Test1_3_2.3");
}
*Test1_3_3() {
yield CoroutineV2.WaitTime(1);
cc.log("Test1_3_3.1");
yield CoroutineV2.WaitTime(1);
cc.log("Test1_3_3.2");
yield CoroutineV2.WaitTime(1);
cc.log("Test1_3_3.3");
}
*Test1_4() {
this._num++;
cc.log(`WaitTime2 ${this._num}`);
yield CoroutineV2.WaitTime(2).Start(this._obj2);
this._num++;
cc.log(`WaitTime2 ${this._num}`);
yield CoroutineV2.WaitTime(2).Start(this._obj2);
this._num++;
cc.log(`WaitTime2 ${this._num}`);
}
*Test2_1() {
cc.log("111");
CoroutineV2.Single(this.Test2_2()).Start(this);
cc.log("333");
}
*Test2_2() {
cc.log("222");
return;
}
button2Clicked() {
// this._routine && this._routine.Stop();
if (this._obj2) {
CoroutineV2.StopCoroutinesBy(this._obj2);
this._obj2 = null;
return;
}
if (this._obj) {
CoroutineV2.StopCoroutinesBy(this._obj);
this._obj = null;
return;
}
CoroutineV2.StopCoroutinesBy(this);
}
button3Clicked() {
// CoroutineV2.StopCoroutinesBy(this);
this._routine && this._routine.Pause();
}
button4Clicked() {
// CoroutineV2.StopCoroutinesBy(this);
this._routine && this._routine.Resume();
}
*Coroutine1(start:number, end: number)
{
for (let i = start; i <= end; i++) {
// yield CoroutineV2.WaitTime(1).Start(); // Start()可以省略, 會由外層啟動
// yield CoroutineV2.WaitTime(1).Start(this); // target也可以省略, 由外層的target控制
yield CoroutineV2.WaitTime(1).Start();
cc.log(`C1 => ${i}`);
// 嵌套
yield CoroutineV2
.WaitTime(1)
.ThenParallel(
// 再嵌套
CoroutineV2.Action(() => cc.log("start parallel")),
this.Coroutine2(10, 2),
this.Coroutine2(20, 2),
new A())
.ThenAction(() => cc.log("end parallel"))
.Start();
// Promise
yield this.loadItemAsync("settings.json");
}
}
*Coroutine2(num: number, repeat: number)
{
for (let i = 0; i < repeat; i++) {
//yield CoroutineV2.WaitTime(2);
yield 0;
cc.log(`C2: ${num}`);
// yield CoroutineV2.WaitTime(1);
}
}
actionCallback() {
cc.log("action callback 2");
}
loadItemAsync(id: string): Promise<{id: string}> {
return new Promise((resolve) => {
cc.log('loading item start:', id);
setTimeout(() => {
resolve({ id: id });
cc.log('loading item done:', id);
}, 3000);
});
}
}

View File

@@ -0,0 +1,10 @@
{
"ver": "1.1.0",
"uuid": "dfd32c11-76f6-4e38-9272-1d7966d1ef3c",
"importer": "typescript",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View File

@@ -0,0 +1,75 @@
import { IEnumeratorV2, IEnumeratorV2Started } from "./IEnumeratorV2";
import { BaseEnumerator } from "./Core/BaseEnumerator";
import { SingleEnumerator } from "./Core/SingleEnumerator";
import { ParallelEnumerator } from "./Core/ParallelEnumerator";
import { WaitTimeEnumerator } from "./Core/WaitTimeEnumerator";
import { ActionEnumerator } from "./Core/ActionEnumerator";
import { CoroutineExecutor } from "./Core/CoroutineExecutor";
export module CoroutineV2 {
/**
* 啟動一般協程
*/
export function StartCoroutine(iterator: Iterator<any>, target?: any): IEnumeratorV2Started {
return Single(iterator).Start(target);
}
/**
* 依據IEnumeratorV2.Start(target)綁定的目標, 來停止協程
* @param target
*/
export function StopCoroutinesBy(target: any) {
CoroutineExecutor.instance.StopCoroutineBy(target);
}
/**
* 單一協程
*/
export function Single(iterator: Iterator<any>): IEnumeratorV2 {
if (iterator instanceof BaseEnumerator) {
return iterator;
} else {
return new SingleEnumerator(iterator);
}
}
/**
* 平行協程
*/
export function Parallel(...iterators: Iterator<any>[]): IEnumeratorV2 {
return new ParallelEnumerator(iterators);
}
/**
* 序列協程
*/
export function Serial(...iterators: Iterator<any>[]): IEnumeratorV2 {
let [iterator, ...others] = iterators;
if (iterator instanceof BaseEnumerator) {
return iterator.ThenSerial(...others);
} else {
return new SingleEnumerator(iterator).ThenSerial(...others);
}
}
/**
* 執行方法協程
* @param action 方法
* @param delaySeconds 延遲秒數
*/
export function Action(action: Function, delaySeconds?: number): IEnumeratorV2 {
if (delaySeconds > 0) {
return new WaitTimeEnumerator(delaySeconds).Then(new ActionEnumerator(action));
} else {
return new ActionEnumerator(action);
}
}
/**
* 等待時間協程
* @param seconds 秒數
*/
export function WaitTime(seconds: number): IEnumeratorV2 {
return new WaitTimeEnumerator(seconds);
}
}

View File

@@ -0,0 +1,10 @@
{
"ver": "1.1.0",
"uuid": "fc38e505-bd37-44c3-9e0a-fd463bb88c51",
"importer": "typescript",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View File

@@ -0,0 +1,16 @@
export interface IEnumeratorV2 extends Iterator<any> {
Start(target?: any): IEnumeratorV2Started;
Then(iterator: Iterator<any>): IEnumeratorV2;
ThenSerial(...iterators: Iterator<any>[]): IEnumeratorV2;
ThenParallel(...iterators: Iterator<any>[]): IEnumeratorV2;
ThenAction(action: Function, delaySeconds?: number): IEnumeratorV2;
ThenWaitTime(seconds: number): IEnumeratorV2;
}
export interface IEnumeratorV2Started {
readonly Current: any;
Pause(): void;
Resume(): void;
Stop(): void;
}

View File

@@ -0,0 +1,10 @@
{
"ver": "1.1.0",
"uuid": "df3ab07d-3d2b-4552-b454-29b95223ea85",
"importer": "typescript",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}