[add] First
This commit is contained in:
commit
4804fc1005
23
.gitignore
vendored
Normal file
23
.gitignore
vendored
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
|
||||||
|
node_modules
|
||||||
|
dist-ssr
|
||||||
|
*.local
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/extensions.json
|
||||||
|
.idea
|
||||||
|
.DS_Store
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
*.sw?
|
3
.vscode/extensions.json
vendored
Normal file
3
.vscode/extensions.json
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"recommendations": ["johnsoncodehk.volar"]
|
||||||
|
}
|
19
README.md
Normal file
19
README.md
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# Vue 3 + Typescript + Vite
|
||||||
|
|
||||||
|
1. npm install
|
||||||
|
2. npm run dev
|
||||||
|
|
||||||
|
This template should help get you started developing with Vue 3 and Typescript in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more.
|
||||||
|
|
||||||
|
## Recommended IDE Setup
|
||||||
|
|
||||||
|
- [VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=johnsoncodehk.volar)
|
||||||
|
|
||||||
|
## Type Support For `.vue` Imports in TS
|
||||||
|
|
||||||
|
Since TypeScript cannot handle type information for `.vue` imports, they are shimmed to be a generic Vue component type by default. In most cases this is fine if you don't really care about component prop types outside of templates. However, if you wish to get actual prop types in `.vue` imports (for example to get props validation when using manual `h(...)` calls), you can enable Volar's Take Over mode by following these steps:
|
||||||
|
|
||||||
|
1. Run `Extensions: Show Built-in Extensions` from VSCode's command palette, look for `TypeScript and JavaScript Language Features`, then right click and select `Disable (Workspace)`. By default, Take Over mode will enable itself if the default TypeScript extension is disabled.
|
||||||
|
2. Reload the VSCode window by running `Developer: Reload Window` from the command palette.
|
||||||
|
|
||||||
|
You can learn more about Take Over mode [here](https://github.com/johnsoncodehk/volar/discussions/471).
|
BIN
favicon.ico
Normal file
BIN
favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 264 KiB |
18
index.html
Normal file
18
index.html
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<link rel="icon" href="/favicon.ico" />
|
||||||
|
<link href="./src/assets/ZenMaruGothic-Regular.ttf" rel="stylesheet">
|
||||||
|
<!-- <link href="https://fonts.googleapis.com/css2?family=Zen+Maru+Gothic&display=swap" rel="stylesheet"> -->
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>BJ_ServerState</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="app"></div>
|
||||||
|
<script type="module" src="/src/main.ts"></script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
3162
package-lock.json
generated
Normal file
3162
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
26
package.json
Normal file
26
package.json
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"name": "bj-casino-rank",
|
||||||
|
"private": true,
|
||||||
|
"version": "0.0.0",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "vite --host",
|
||||||
|
"build": "vite build",
|
||||||
|
"preview": "vite preview"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@ant-design/icons-vue": "^6.1.0",
|
||||||
|
"@popperjs/core": "^2.11.5",
|
||||||
|
"axios": "^0.26.1",
|
||||||
|
"bootstrap": "^5.1.3",
|
||||||
|
"element-plus": "^2.1.9",
|
||||||
|
"moment": "^2.29.2",
|
||||||
|
"vue": "^3.2.25",
|
||||||
|
"vue-loading-overlay": "^5.0.3"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@vitejs/plugin-vue": "^2.3.0",
|
||||||
|
"typescript": "^4.5.4",
|
||||||
|
"vite": "^2.9.0",
|
||||||
|
"vue-tsc": "^0.29.8"
|
||||||
|
}
|
||||||
|
}
|
BIN
public/assets/ZenMaruGothic-Regular.2d389171.ttf
Normal file
BIN
public/assets/ZenMaruGothic-Regular.2d389171.ttf
Normal file
Binary file not shown.
BIN
public/assets/favicon.69a65d1f.ico
Normal file
BIN
public/assets/favicon.69a65d1f.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 264 KiB |
46
public/assets/index.59c18d08.js
Normal file
46
public/assets/index.59c18d08.js
Normal file
File diff suppressed because one or more lines are too long
6
public/assets/index.b312efde.css
Normal file
6
public/assets/index.b312efde.css
Normal file
File diff suppressed because one or more lines are too long
20
public/index.html
Normal file
20
public/index.html
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<link rel="icon" href="./assets/favicon.69a65d1f.ico" />
|
||||||
|
<link href="./src/assets/ZenMaruGothic-Regular.ttf" rel="stylesheet">
|
||||||
|
<!-- <link href="https://fonts.googleapis.com/css2?family=Zen+Maru+Gothic&display=swap" rel="stylesheet"> -->
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>BJ_ServerState</title>
|
||||||
|
<script type="module" crossorigin src="./assets/index.59c18d08.js"></script>
|
||||||
|
<link rel="stylesheet" href="./assets/index.b312efde.css">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="app"></div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
56
src/App.vue
Normal file
56
src/App.vue
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import 'vue-loading-overlay/dist/vue-loading.css';
|
||||||
|
import BJ_ServerState from './components/BJ_ServerState.vue';
|
||||||
|
import { BJ_Casino_Data } from './script/BJ_Casino_Data';
|
||||||
|
|
||||||
|
const self = {}
|
||||||
|
let Title = ref("BJ_ServerState");
|
||||||
|
const BJ_Casino = new BJ_Casino_Data(self)
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<h1>
|
||||||
|
{{ Title }}
|
||||||
|
</h1>
|
||||||
|
<div class="d-flex justify-content-center">
|
||||||
|
<table class="table table-striped table-info table-hover">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th align="left">名稱</th>
|
||||||
|
<th align="left">Host</th>
|
||||||
|
<th align="left">Port</th>
|
||||||
|
<th align="left">狀態</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody v-for="(item, index) in BJ_Casino.Config.ServerList" :key="index">
|
||||||
|
<BJ_ServerState :BJ_Casino="BJ_Casino" :ID=index />
|
||||||
|
</tbody>
|
||||||
|
<!-- <BJ_ServerState :BJ_Casino="BJ_Casino" :ID=0 /> -->
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
@import url('../src/assets/fonts.css');
|
||||||
|
@import url('../src/assets/style.css');
|
||||||
|
|
||||||
|
.el-tabs__nav {
|
||||||
|
float: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-tabs__item {
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#app {
|
||||||
|
font-family: Avenir, Helvetica, Arial, sans-serif;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
text-align: center;
|
||||||
|
color: #2c3e50;
|
||||||
|
margin-top: 0px;
|
||||||
|
font-family: 'Zen Maru Gothic', sans-serif;
|
||||||
|
}
|
||||||
|
</style>
|
49
src/assets/config.json
Normal file
49
src/assets/config.json
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
{
|
||||||
|
"ServerList": [
|
||||||
|
{
|
||||||
|
"name": "內版",
|
||||||
|
"host": "http://220.134.195.1",
|
||||||
|
"port": "19005"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "肉乾 9006",
|
||||||
|
"host": "http://192.168.5.230",
|
||||||
|
"port": "9006"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "肉乾 9007",
|
||||||
|
"host": "http://192.168.5.230",
|
||||||
|
"port": "9007"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "40 9487",
|
||||||
|
"host": "http://192.168.5.12",
|
||||||
|
"port": "9487"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "送審",
|
||||||
|
"host": "https://submit.online-bj.com",
|
||||||
|
"port": "9005"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "外版",
|
||||||
|
"host": "https://game.online-bj.com",
|
||||||
|
"port": "9005"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "testing1",
|
||||||
|
"host": "http://bj-testing1.casino.catan.com.tw",
|
||||||
|
"port": "9005"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "testing2",
|
||||||
|
"host": "http://bj-testing2.casino.catan.com.tw",
|
||||||
|
"port": "9005"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "testing3",
|
||||||
|
"host": "http://bj-testing3.casino.catan.com.tw",
|
||||||
|
"port": "9005"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
7
src/assets/fonts.css
Normal file
7
src/assets/fonts.css
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
@font-face {
|
||||||
|
/* 重命名字体名 */
|
||||||
|
font-family: 'Zen Maru Gothic';
|
||||||
|
src: url('./fonts/ZenMaruGothic-Regular.ttf');
|
||||||
|
font-weight: normal;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
BIN
src/assets/fonts/ZenMaruGothic-Regular.ttf
Normal file
BIN
src/assets/fonts/ZenMaruGothic-Regular.ttf
Normal file
Binary file not shown.
BIN
src/assets/logo.png
Normal file
BIN
src/assets/logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.7 KiB |
8
src/assets/style.css
Normal file
8
src/assets/style.css
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
.table {
|
||||||
|
width: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-tabs__nav-scroll {
|
||||||
|
/* width: 50%; */
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
4
src/assets/style_mobile_a.css
Normal file
4
src/assets/style_mobile_a.css
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
.xyhot {
|
||||||
|
width: auto;
|
||||||
|
overflow-y: hidden;
|
||||||
|
}
|
4
src/assets/style_mobile_iPad.css
Normal file
4
src/assets/style_mobile_iPad.css
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
.xyhot {
|
||||||
|
width: auto;
|
||||||
|
overflow-y: hidden;
|
||||||
|
}
|
4
src/assets/style_mobile_no.css
Normal file
4
src/assets/style_mobile_no.css
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
.xyhot {
|
||||||
|
width: 100%;
|
||||||
|
overflow-y: hidden;
|
||||||
|
}
|
4
src/assets/style_mobile_other.css
Normal file
4
src/assets/style_mobile_other.css
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
/* .xyhot {
|
||||||
|
width: auto;
|
||||||
|
overflow-y: hidden;
|
||||||
|
} */
|
39
src/components/BJ_ServerState.vue
Normal file
39
src/components/BJ_ServerState.vue
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from "vue";
|
||||||
|
import { BJ_Casino_Data } from "../script/BJ_Casino_Data";
|
||||||
|
import { BJ_ServerState } from "../script/BJ_ServerState";
|
||||||
|
|
||||||
|
const props = defineProps<{ BJ_Casino: BJ_Casino_Data, ID: number }>()
|
||||||
|
|
||||||
|
let Name = ref("");
|
||||||
|
let Host = ref("");
|
||||||
|
let Port = ref("");
|
||||||
|
let IsConnect = ref("false");
|
||||||
|
const self = {
|
||||||
|
ID: props.ID,
|
||||||
|
BJ_Casino: props.BJ_Casino,
|
||||||
|
Name: Name,
|
||||||
|
Host: Host,
|
||||||
|
Port: Port,
|
||||||
|
IsConnect: IsConnect,
|
||||||
|
}
|
||||||
|
const Script = new BJ_ServerState(self);
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<font size="5"><b>{{ Name }}</b></font>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<font size="5"><b>{{ Host }}</b></font>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<font size="5"><b>{{ Port }}</b></font>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<font size="5"><b>{{ IsConnect }}</b></font>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</template>
|
8
src/env.d.ts
vendored
Normal file
8
src/env.d.ts
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
/// <reference types="vite/client" />
|
||||||
|
|
||||||
|
declare module '*.vue' {
|
||||||
|
import type { DefineComponent } from 'vue'
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types
|
||||||
|
const component: DefineComponent<{}, {}, any>
|
||||||
|
export default component
|
||||||
|
}
|
11
src/main.ts
Normal file
11
src/main.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import '@popperjs/core';
|
||||||
|
import 'bootstrap';
|
||||||
|
import 'bootstrap/dist/css/bootstrap.min.css';
|
||||||
|
import ElementPlus from 'element-plus';
|
||||||
|
import 'element-plus/dist/index.css';
|
||||||
|
import locale from 'element-plus/lib/locale/lang/zh-tw';
|
||||||
|
import { createApp } from 'vue';
|
||||||
|
import App from './App.vue';
|
||||||
|
|
||||||
|
|
||||||
|
createApp(App).use(ElementPlus, { locale }).mount('#app')
|
29
src/script/BJ_Casino_Data.ts
Normal file
29
src/script/BJ_Casino_Data.ts
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import config from '../../src/assets/config.json';
|
||||||
|
import "./Engine/CatanEngine/CSharp/String";
|
||||||
|
|
||||||
|
export class BJ_Casino_Data {
|
||||||
|
|
||||||
|
//#region public
|
||||||
|
|
||||||
|
public Client: any;
|
||||||
|
|
||||||
|
public Config: any;
|
||||||
|
|
||||||
|
//#endregion
|
||||||
|
|
||||||
|
//#region Lifecycle
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
constructor(client: any) {
|
||||||
|
this.Client = client;
|
||||||
|
this.onLoad();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async onLoad(): Promise<void> {
|
||||||
|
this.Config = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
//#endregion
|
||||||
|
}
|
124
src/script/BJ_ServerState.ts
Normal file
124
src/script/BJ_ServerState.ts
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
import { BJ_Casino_Data } from "./BJ_Casino_Data";
|
||||||
|
import { NetConnector } from "./Engine/CatanEngine/NetManagerV2/NetConnector";
|
||||||
|
import { Tools } from "./Tools";
|
||||||
|
|
||||||
|
export class BJ_ServerState {
|
||||||
|
//#region Lifecycle
|
||||||
|
|
||||||
|
public BJ_Casino: BJ_Casino_Data;
|
||||||
|
|
||||||
|
public ID: number;
|
||||||
|
|
||||||
|
//#endregion
|
||||||
|
|
||||||
|
//#region private
|
||||||
|
|
||||||
|
private _conn: NetConnector = null;
|
||||||
|
|
||||||
|
private _client: any;
|
||||||
|
|
||||||
|
//#endregion
|
||||||
|
|
||||||
|
//#region Lifecycle
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
constructor(client: any) {
|
||||||
|
this._client = client;
|
||||||
|
this.BJ_Casino = client.BJ_Casino;
|
||||||
|
this.ID = client.ID;
|
||||||
|
this.onLoad();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async onLoad(): Promise<void> {
|
||||||
|
await this.ConnectServer();
|
||||||
|
}
|
||||||
|
|
||||||
|
//#endregion
|
||||||
|
|
||||||
|
//#region 網路相關
|
||||||
|
|
||||||
|
/** 連線 */
|
||||||
|
public async ConnectServer(): Promise<void> {
|
||||||
|
let serverList = this.BJ_Casino.Config.ServerList;
|
||||||
|
let server = serverList[this.ID];
|
||||||
|
if (!server) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const Name: string = server.name;
|
||||||
|
const Host: string = server.host;
|
||||||
|
const Port: string = server.port;
|
||||||
|
this._client.Name.value = Name;
|
||||||
|
this._client.Host.value = Host;
|
||||||
|
this._client.Port.value = Port;
|
||||||
|
await this.ConnectAsync(Host, +Port);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 連線(目前沒有重連機制) */
|
||||||
|
public async ConnectAsync(host: string, port: number): Promise<void> {
|
||||||
|
let self = this;
|
||||||
|
var url: string = "https://api.ipify.org/?format=json";
|
||||||
|
var xhr: XMLHttpRequest = new XMLHttpRequest();
|
||||||
|
let ip: string = "";
|
||||||
|
xhr.onreadystatechange = function (): void {
|
||||||
|
if (xhr.readyState === 4 && (xhr.status >= 200 && xhr.status < 400)) {
|
||||||
|
ip = JSON.parse(xhr.responseText)["ip"];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
xhr.open("GET", url, true);
|
||||||
|
xhr.send();
|
||||||
|
console.log("[事件]準備連線...");
|
||||||
|
while (ip === "") {
|
||||||
|
await Tools.Sleep(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
let checkHttp: string = "";
|
||||||
|
let ws: string = "";
|
||||||
|
let index: number = host.indexOf("https://");
|
||||||
|
if (index != -1) {
|
||||||
|
checkHttp = "https";
|
||||||
|
host = host.replace("https://", "");
|
||||||
|
} else {
|
||||||
|
checkHttp = window.location.href.substring(0, 5);
|
||||||
|
host = host.replace("http://", "");
|
||||||
|
}
|
||||||
|
if (true) {
|
||||||
|
console.log("[事件]checkHttp=", checkHttp, host, port);
|
||||||
|
}
|
||||||
|
if (checkHttp != "https") {
|
||||||
|
ws = `ws://${host}:${port}/?ip=${ip}`;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ws = `wss://${host}:${port}/?ip=${ip}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
let socket = new WebSocket(ws);
|
||||||
|
|
||||||
|
socket.onopen = function (e) {
|
||||||
|
console.log(`[事件] [${self._client.Name.value}] 連線狀態: true`);
|
||||||
|
self._client.IsConnect.value = "true";
|
||||||
|
};
|
||||||
|
|
||||||
|
socket.onmessage = function (event) {
|
||||||
|
// alert(`[message] Data received from server: ${event.data}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
socket.onclose = function (event) {
|
||||||
|
// if (event.wasClean) {
|
||||||
|
// // alert(`[close] Connection closed cleanly, code=${event.code} reason=${event.reason}`);
|
||||||
|
// } else {
|
||||||
|
// // 例如服务器进程被杀死或网络中断
|
||||||
|
// // 在这种情况下,event.code 通常为 1006
|
||||||
|
// // alert('[close] Connection died');
|
||||||
|
// }
|
||||||
|
};
|
||||||
|
|
||||||
|
socket.onerror = function (error) {
|
||||||
|
// alert(`[error] ${error["message"]}`);
|
||||||
|
self._client.IsConnect.value = "無回應";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
//#endregion
|
||||||
|
}
|
237
src/script/Base/BusinessTypeSetting.ts
Normal file
237
src/script/Base/BusinessTypeSetting.ts
Normal file
@ -0,0 +1,237 @@
|
|||||||
|
export module BusinessEnum {
|
||||||
|
export enum BusinessType {
|
||||||
|
Type1 = "H5",
|
||||||
|
Type2 = "App"
|
||||||
|
}
|
||||||
|
export enum ServerType {
|
||||||
|
/** WEB格式 */
|
||||||
|
Web = 1,
|
||||||
|
/** 外版 */
|
||||||
|
Out = 2,
|
||||||
|
/** 送審環境 */
|
||||||
|
Submit = 3,
|
||||||
|
/** 內版商業DEMO測試(B2B) */
|
||||||
|
Internal_release = 4,
|
||||||
|
/** 內版開發(內網&4G) */
|
||||||
|
Internal_Dev = 5,
|
||||||
|
/** 外部商業DEMO(B2B) */
|
||||||
|
Out_B2B = 6
|
||||||
|
}
|
||||||
|
export enum LogoType {
|
||||||
|
/** 完美(目前只有WEB) */
|
||||||
|
WM = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
產品商業類別設定檔
|
||||||
|
@explain 讀不同表就代表不同商業類別.要多開GIT並設定新測試環境
|
||||||
|
@explain 遊戲一定都一樣不能改動介面
|
||||||
|
*/
|
||||||
|
export default class BusinessTypeSetting {
|
||||||
|
/** 產品商業類別字串(組合判斷用) */
|
||||||
|
public static readonly TYPE_BUSINESS: string = "App";
|
||||||
|
/** 編譯版本 */
|
||||||
|
public static readonly COMPILE_VERSION: string = "1.3.1";
|
||||||
|
/** 編譯程式碼版號 */
|
||||||
|
public static readonly SCRIPT_BUNLE_LIST: string[] = [
|
||||||
|
"FormTableScript", "CommonScript", "ElementUIScript", "LoginScript", "LobbyScript", "SlotScript"
|
||||||
|
];
|
||||||
|
public static readonly ART_UI_BUNLE_LIST: string[] = [
|
||||||
|
"Common", "CommonSound", "Login", "Lobby", "GameCommon",
|
||||||
|
"Game_BottomUI_SD", "Game_BigWinJackpot", "GameMessage", "CommonLanguageTexture", "MainControl",
|
||||||
|
"BindAccount", "SettingPanel", "Shop", "Vip", "Ad",
|
||||||
|
"Mail", "Chat", "PlayerInfo", "Rank", "Gift",
|
||||||
|
"ResourceItem", "Backpack", "GettingPanel", "Activity", "Game_BottomUI_BJ"
|
||||||
|
];
|
||||||
|
public static readonly DEV_ART_UI_BUNLE_LIST: string[] = [
|
||||||
|
|
||||||
|
]
|
||||||
|
public static readonly ART_GAME_BUNLE_LIST: string[] = [
|
||||||
|
"Game_1201", "Game_1202", "Game_1302"
|
||||||
|
]
|
||||||
|
public static readonly ART_REMOTE_GAME_BUNLE_LIST: string[] = [
|
||||||
|
"Game_1", "Game_2", "Game_5", "Game_8", "Game_9",
|
||||||
|
"Game_10", "Game_12", "Game_15", "Game_16", "Game_18",
|
||||||
|
"Game_23", "Game_24", "Game_25", "Game_26", "Game_27",
|
||||||
|
"Game_28", "Game_29", "Game_30", "Game_32", "Game_33",
|
||||||
|
"Game_34", "Game_35", "Game_37", "Game_36", "Game_40",
|
||||||
|
"Game_44", "Game_48", "Game_50", "Game_51", "Game_58",
|
||||||
|
"Game_1101", "Game_1401", "Game_1501", "Game_2001", "Game_2003",
|
||||||
|
"Game_3002", "Game_3003", "Game_3012",
|
||||||
|
]
|
||||||
|
/** 送審旗標(讀取外版自動判斷是否送審) */
|
||||||
|
public static IsSubmit: boolean = false;
|
||||||
|
/** 跑送審2的手動旗標(若是送審且設為true跑2號環境) */
|
||||||
|
public static IsSubmitTestFlight: boolean = false;
|
||||||
|
/** B2B手動旗標(true寫死B2B環境) */
|
||||||
|
public static IsB2B: boolean = false;
|
||||||
|
|
||||||
|
/** 商業LOGO圖代碼(讀同一張表但UI有改的設定) */
|
||||||
|
public static Logo: number = null!;
|
||||||
|
/** 連線IP(網頁版會接網址參數所以要多開變數直接指定) */
|
||||||
|
public static UseHost: string = null!;
|
||||||
|
/** 連接阜(網頁版會接網址參數所以要多開變數直接指定) */
|
||||||
|
public static UsePort: number = null!;
|
||||||
|
/** 資源伺服器網址 */
|
||||||
|
public static UsePatch: string = null!;
|
||||||
|
/** 帳號 */
|
||||||
|
public static Account: string = null!;
|
||||||
|
/** 密碼 */
|
||||||
|
public static Password: string = null!;
|
||||||
|
|
||||||
|
// =======================================================================================
|
||||||
|
/** 執行環境ProductEnum.ServerType */
|
||||||
|
public static UseServerTpye: BusinessEnum.ServerType = BusinessEnum.ServerType.Web;
|
||||||
|
/** 網頁是否在伺服器上 */
|
||||||
|
public static readonly CheckOnServer: boolean =
|
||||||
|
window.location.href.indexOf("localhost") == -1
|
||||||
|
&& window.location.href.indexOf("/build/") == -1;
|
||||||
|
/** 網頁測試讀取對應資源的位置 */
|
||||||
|
public static readonly FolderUrlImg: string = "shared/img/";
|
||||||
|
public static readonly FolderUrlBg: string = "shared/bg/";
|
||||||
|
public static readonly FolderUrlJson: string = "shared/jsons/";
|
||||||
|
public static readonly FolderUrlTxt: string = "shared/txt/";
|
||||||
|
public static readonly FolderUrlLoading: string = "shared/loading/";
|
||||||
|
public static readonly FolderUrlMp3: string = "shared/";
|
||||||
|
public static readonly FolderUrlBundle: string = `Bundle_${true ? "Debug" : "Release"}/`;
|
||||||
|
public static readonly FolderOS: string = "Android/";
|
||||||
|
/**遠端Bundle路徑為: URL + BundleName.非遊戲資源到各自平台資料夾找BUNDLE */
|
||||||
|
public static GetRemoteFileUrl(bundleName: string): string {
|
||||||
|
let gameNumber: string = bundleName.split("Game_")[1];
|
||||||
|
var regExp: RegExp = /^[0-9]+$/;
|
||||||
|
let isGame: boolean = regExp.test(gameNumber);
|
||||||
|
let bundleUrl: string = `${BusinessTypeSetting.UsePatch}${BusinessTypeSetting.FolderUrlBundle}`;
|
||||||
|
if (isGame) {
|
||||||
|
bundleUrl = `${bundleUrl}${bundleName}`;
|
||||||
|
} else {
|
||||||
|
bundleUrl = `${bundleUrl}${BusinessTypeSetting.FolderOS}${bundleName}`;
|
||||||
|
}
|
||||||
|
return bundleUrl;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 取得PACH資原路徑
|
||||||
|
* @param type 執行環境()
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
public static GetPatchUrl(type: BusinessEnum.ServerType): string {
|
||||||
|
if (this.UseServerTpye == BusinessEnum.ServerType.Web) {
|
||||||
|
// TYP2網頁版資源路路徑判斷
|
||||||
|
if (this.CheckOnServer) {
|
||||||
|
return "../shared/";
|
||||||
|
} else {
|
||||||
|
return "http://patch-dev.online-bj.com//shared/";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch (type) {
|
||||||
|
case BusinessEnum.ServerType.Out:
|
||||||
|
return "https://patch.online-bj.com/game/";
|
||||||
|
case BusinessEnum.ServerType.Submit:
|
||||||
|
if (!this.IsSubmitTestFlight) {
|
||||||
|
return "https://patch-submit.online-bj.com/game/";
|
||||||
|
} else {
|
||||||
|
return "https://patch-submit2.online-bj.com/game/";
|
||||||
|
}
|
||||||
|
|
||||||
|
case BusinessEnum.ServerType.Out_B2B:
|
||||||
|
return "https://patch-demo.online-bj.com/game/";
|
||||||
|
case BusinessEnum.ServerType.Internal_release:
|
||||||
|
return "http://patch-release.online-bj.com/";
|
||||||
|
|
||||||
|
case BusinessEnum.ServerType.Internal_Dev:
|
||||||
|
return "http://patch-dev.online-bj.com/";
|
||||||
|
|
||||||
|
default:
|
||||||
|
console.warn("GetPatchUrl Uncheck ServerType.");
|
||||||
|
return "http://patch-dev.online-bj.com/";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 取得連線伺服器IP
|
||||||
|
* @param type 執行環境
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
public static GetHostUrl(type: BusinessEnum.ServerType): string {
|
||||||
|
if (this.UseServerTpye == BusinessEnum.ServerType.Web) {
|
||||||
|
return "app.casino.catan.com.tw";
|
||||||
|
}
|
||||||
|
switch (type) {
|
||||||
|
case BusinessEnum.ServerType.Out:
|
||||||
|
return "https://game.online-bj.com";
|
||||||
|
case BusinessEnum.ServerType.Submit:
|
||||||
|
if (!this.IsSubmitTestFlight) {
|
||||||
|
return "https://submit.online-bj.com";
|
||||||
|
} else {
|
||||||
|
return "https://submit2.online-bj.com";
|
||||||
|
}
|
||||||
|
|
||||||
|
case BusinessEnum.ServerType.Out_B2B:
|
||||||
|
return "https://demo.online-bj.com";
|
||||||
|
case BusinessEnum.ServerType.Internal_release:
|
||||||
|
return "https://demo.online-bj.com";
|
||||||
|
|
||||||
|
case BusinessEnum.ServerType.Internal_Dev:
|
||||||
|
return "http://220.134.195.1";
|
||||||
|
|
||||||
|
default:
|
||||||
|
console.warn("GetHostUrl Uncheck ServerType.");
|
||||||
|
// 只有內網可憐IP
|
||||||
|
return "app.casino.catan.com.tw";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 取得伺服器連接端口
|
||||||
|
* @param type 執行環境
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
public static GetPortNum(type: BusinessEnum.ServerType): number {
|
||||||
|
if (this.UseServerTpye == BusinessEnum.ServerType.Web) {
|
||||||
|
// 網頁版測試專用.正式接網頁參數
|
||||||
|
return 9005;
|
||||||
|
}
|
||||||
|
switch (type) {
|
||||||
|
case BusinessEnum.ServerType.Out:
|
||||||
|
return 9005;
|
||||||
|
case BusinessEnum.ServerType.Submit:
|
||||||
|
if (!this.IsSubmitTestFlight) {
|
||||||
|
return 9005;
|
||||||
|
} else {
|
||||||
|
return 9005;
|
||||||
|
}
|
||||||
|
|
||||||
|
case BusinessEnum.ServerType.Out_B2B:
|
||||||
|
return 9005;
|
||||||
|
case BusinessEnum.ServerType.Internal_release:
|
||||||
|
return 9005;
|
||||||
|
|
||||||
|
case BusinessEnum.ServerType.Internal_Dev:
|
||||||
|
return 19005;
|
||||||
|
|
||||||
|
default:
|
||||||
|
console.warn("GePortNum Uncheck ServerType.");
|
||||||
|
return 9005;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static GetDownloadUrl(type: BusinessEnum.ServerType): string {
|
||||||
|
switch (type) {
|
||||||
|
case BusinessEnum.ServerType.Internal_Dev:
|
||||||
|
return "http://static-dev.online-bj.com/";
|
||||||
|
default:
|
||||||
|
let url: string = this.GetHostUrl(type);
|
||||||
|
url = url.replace("http://", "");
|
||||||
|
url = url.replace("https://", "");
|
||||||
|
return "https://static-" + url;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GetUploadUrl(type: BusinessEnum.ServerType): string {
|
||||||
|
let port: string = ":9080";
|
||||||
|
switch (type) {
|
||||||
|
case BusinessEnum.ServerType.Internal_Dev:
|
||||||
|
return "http://static-dev.online-bj.com" + port;
|
||||||
|
default:
|
||||||
|
return this.GetHostUrl(type) + port;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// =======================================================================================
|
||||||
|
}
|
8
src/script/Base/CSMessage.ts
Normal file
8
src/script/Base/CSMessage.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
/** 訊息框相關 */
|
||||||
|
export default class CSMessage {
|
||||||
|
/** 網路錯誤訊息 */
|
||||||
|
public static NetError(method: string, state: number, str: string = ""): void {
|
||||||
|
let error: string = String.Format("[{0}] state:{1} {2}", method, state, str);
|
||||||
|
console.warn("網路錯誤訊息: ", error);
|
||||||
|
}
|
||||||
|
}
|
22
src/script/Base/Config.ts
Normal file
22
src/script/Base/Config.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
/**放跟ProductSetting沒關係的變數 */
|
||||||
|
export default class Config {
|
||||||
|
/**是否是連線模式 */
|
||||||
|
public static IsOnlineMode: boolean = false;
|
||||||
|
/**內版帳號登入(目前只支援TYPE1.請從GM工具創好帳號在去DEMO場景加按鈕) */
|
||||||
|
public static IsDemoLogin: boolean = false;
|
||||||
|
/**遊戲模式(0一般 1特色.WEB才有分) */
|
||||||
|
public static GameMode: number = 0;
|
||||||
|
/**顯示金錢變動LOG */
|
||||||
|
public static ShowMoneyLog: boolean = true;
|
||||||
|
/**顯示測試畫面 */
|
||||||
|
public static ShowTest: boolean = false;
|
||||||
|
public static GetRunDevice(): number {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
public static IsANDROID(): boolean {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
public static IsIOS(): boolean {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
237
src/script/Base/Request/AccountRequest.ts
Normal file
237
src/script/Base/Request/AccountRequest.ts
Normal file
@ -0,0 +1,237 @@
|
|||||||
|
import { NetRequest } from "../../Engine/CatanEngine/NetManagerV2/NetRequest";
|
||||||
|
import BusinessTypeSetting from "../BusinessTypeSetting";
|
||||||
|
import Config from "../Config";
|
||||||
|
|
||||||
|
// =======================================================================================
|
||||||
|
/** 通用回傳SERVER創的帳號 */
|
||||||
|
interface CommonAccountResponse {
|
||||||
|
a: string;
|
||||||
|
pw: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// =======================================================================================
|
||||||
|
interface CreateResquest {
|
||||||
|
p: number;
|
||||||
|
}
|
||||||
|
/** 直接玩(訪客給SERVER創帳號) */
|
||||||
|
export class AccountCreateRequest extends NetRequest<CreateResquest, CommonAccountResponse> {
|
||||||
|
get Method(): string {
|
||||||
|
return "account.create";
|
||||||
|
}
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.Data = {
|
||||||
|
p: Config.GetRunDevice(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// =======================================================================================
|
||||||
|
interface LoginResquest {
|
||||||
|
p: number;
|
||||||
|
device_info: string[];
|
||||||
|
fcm_token: string;
|
||||||
|
a: string;
|
||||||
|
pw: string;
|
||||||
|
ver: string;
|
||||||
|
}
|
||||||
|
interface LoginResponse {
|
||||||
|
pr: string;
|
||||||
|
cu: string;
|
||||||
|
}
|
||||||
|
/** 通用登入 */
|
||||||
|
export class AccountLoginRequest extends NetRequest<LoginResquest, LoginResponse> {
|
||||||
|
get Method(): string {
|
||||||
|
return "account.login";
|
||||||
|
}
|
||||||
|
constructor(account: string, password: string) {
|
||||||
|
super();
|
||||||
|
this.Data = {
|
||||||
|
p: Config.GetRunDevice(),
|
||||||
|
device_info: ["Windows", "Windows"],
|
||||||
|
fcm_token: "",
|
||||||
|
a: account,
|
||||||
|
pw: password,
|
||||||
|
ver: BusinessTypeSetting.COMPILE_VERSION
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// =======================================================================================
|
||||||
|
interface CustomResquest {
|
||||||
|
a: string;
|
||||||
|
pw: string;
|
||||||
|
}
|
||||||
|
/** 自定帳號榜定 */
|
||||||
|
export class CustomBindRequest extends NetRequest<CustomResquest, null> {
|
||||||
|
get Method(): string {
|
||||||
|
return "register.account_bind";
|
||||||
|
}
|
||||||
|
constructor(account: string, password: string) {
|
||||||
|
super();
|
||||||
|
this.Data = {
|
||||||
|
a: account,
|
||||||
|
pw: password,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/** 自定帳號登入(回傳SERVER帳號) */
|
||||||
|
export class CustomLoginRequest extends NetRequest<CustomResquest, CommonAccountResponse> {
|
||||||
|
get Method(): string {
|
||||||
|
return "register.account_login";
|
||||||
|
}
|
||||||
|
constructor(account: string, password: string) {
|
||||||
|
super();
|
||||||
|
this.Data = {
|
||||||
|
a: account,
|
||||||
|
pw: password,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// =======================================================================================
|
||||||
|
interface FBResquest {
|
||||||
|
t: string;
|
||||||
|
}
|
||||||
|
/** FB綁定 */
|
||||||
|
export class FBBindRequest extends NetRequest<FBResquest, null> {
|
||||||
|
get Method(): string {
|
||||||
|
return "register.fb_bind";
|
||||||
|
}
|
||||||
|
constructor(token: string) {
|
||||||
|
super();
|
||||||
|
this.Data = {
|
||||||
|
t: token,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/** FB登入(回傳SERVER帳號) */
|
||||||
|
export class FBLoginRequest extends NetRequest<FBResquest, CommonAccountResponse> {
|
||||||
|
get Method(): string {
|
||||||
|
return "register.fb_login";
|
||||||
|
}
|
||||||
|
constructor(token: string) {
|
||||||
|
super();
|
||||||
|
this.Data = {
|
||||||
|
t: token,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// =======================================================================================
|
||||||
|
interface GoogleResquest {
|
||||||
|
c: string;
|
||||||
|
}
|
||||||
|
/** GOOGLE綁定 */
|
||||||
|
export class GoogleBindRequest extends NetRequest<GoogleResquest, null> {
|
||||||
|
get Method(): string {
|
||||||
|
return "register.google_bind";
|
||||||
|
}
|
||||||
|
constructor(token: string) {
|
||||||
|
super();
|
||||||
|
this.Data = {
|
||||||
|
c: token,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/** GOOGLE登入(回傳SERVER帳號) */
|
||||||
|
export class GoogleLoginRequest extends NetRequest<GoogleResquest, CommonAccountResponse> {
|
||||||
|
get Method(): string {
|
||||||
|
return "register.google_login";
|
||||||
|
}
|
||||||
|
constructor(token: string) {
|
||||||
|
super();
|
||||||
|
this.Data = {
|
||||||
|
c: token,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// =======================================================================================
|
||||||
|
interface AppleResquest {
|
||||||
|
c: string;
|
||||||
|
}
|
||||||
|
/** APPEL綁定 */
|
||||||
|
export class AppleBindRequest extends NetRequest<AppleResquest, null> {
|
||||||
|
get Method(): string {
|
||||||
|
return "register.apple_bind";
|
||||||
|
}
|
||||||
|
constructor(token: string) {
|
||||||
|
super();
|
||||||
|
this.Data = {
|
||||||
|
c: token,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/** APPLE登入(回傳SERVER帳號) */
|
||||||
|
export class AppleLoginRequest extends NetRequest<AppleResquest, CommonAccountResponse> {
|
||||||
|
get Method(): string {
|
||||||
|
return "register.apple_login";
|
||||||
|
}
|
||||||
|
constructor(token: string) {
|
||||||
|
super();
|
||||||
|
this.Data = {
|
||||||
|
c: token,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// =======================================================================================
|
||||||
|
/** 電話驗證 */
|
||||||
|
export interface PhoneCodeRequest {
|
||||||
|
p: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class PhoneGet extends NetRequest<PhoneCodeRequest, string> {
|
||||||
|
get Method(): string {
|
||||||
|
return "register.phone_code";
|
||||||
|
}
|
||||||
|
constructor(p: string) {
|
||||||
|
super();
|
||||||
|
this.Data = {
|
||||||
|
p: p
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PhoneBindRequest {
|
||||||
|
c: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class PhoneBind extends NetRequest<PhoneBindRequest, string> {
|
||||||
|
get Method(): string {
|
||||||
|
return "register.phone_bind";
|
||||||
|
}
|
||||||
|
constructor(c: string) {
|
||||||
|
super();
|
||||||
|
this.Data = {
|
||||||
|
c: c
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// =======================================================================================
|
||||||
|
/** 旗標更新 */
|
||||||
|
export class FlagOpenAdd extends NetRequest<number, string> {
|
||||||
|
get Method(): string {
|
||||||
|
return "flag.open_add";
|
||||||
|
}
|
||||||
|
constructor(type: number) {
|
||||||
|
super();
|
||||||
|
this.Data = type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========================================================================================
|
||||||
|
export interface ForgotInfo {
|
||||||
|
a: string;
|
||||||
|
p: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 忘記密碼 */
|
||||||
|
export class ForgotPassword extends NetRequest<ForgotInfo, null> {
|
||||||
|
get Method(): string {
|
||||||
|
return "register.account_forget";
|
||||||
|
}
|
||||||
|
constructor(account: string, phone: string) {
|
||||||
|
super();
|
||||||
|
this.Data = {
|
||||||
|
a: account,
|
||||||
|
p: phone,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
72
src/script/Base/Request/RankRequest.ts
Normal file
72
src/script/Base/Request/RankRequest.ts
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
import { NetRequest } from "../../Engine/CatanEngine/NetManagerV2/NetRequest";
|
||||||
|
|
||||||
|
export interface RankInfo {
|
||||||
|
t: number;
|
||||||
|
p?: number;
|
||||||
|
id?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class AppRankInfo extends NetRequest<RankInfo, JSON> {
|
||||||
|
get Method(): string {
|
||||||
|
return "rank.info";
|
||||||
|
}
|
||||||
|
constructor(Type: number, Parameter?: number) {
|
||||||
|
super();
|
||||||
|
this.Data = {
|
||||||
|
t: Type,
|
||||||
|
p: Parameter,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class AppRankHistory extends NetRequest<RankInfo, JSON> {
|
||||||
|
get Method(): string {
|
||||||
|
return "rank.history";
|
||||||
|
}
|
||||||
|
constructor(Type: number, Parameter: number, DayId: number) {
|
||||||
|
super();
|
||||||
|
this.Data = {
|
||||||
|
id: DayId,
|
||||||
|
t: Type,
|
||||||
|
p: Parameter
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RankReplayInfo {
|
||||||
|
id: number;
|
||||||
|
t: number;
|
||||||
|
r: number;
|
||||||
|
p: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export class AppRankLog extends NetRequest<RankReplayInfo, JSON> {
|
||||||
|
get Method(): string {
|
||||||
|
return "rank.log";
|
||||||
|
}
|
||||||
|
constructor(DayId: number, Type: number, rank: number, Parameter: number) {
|
||||||
|
super();
|
||||||
|
this.Data = {
|
||||||
|
id: DayId,
|
||||||
|
t: Type,
|
||||||
|
r: rank,
|
||||||
|
p: Parameter
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class TestAppRankLog extends NetRequest<RankReplayInfo, JSON> {
|
||||||
|
get Method(): string {
|
||||||
|
return "rank.log_test";
|
||||||
|
}
|
||||||
|
constructor(DayId: number, Type: number, rank: number, Parameter: number) {
|
||||||
|
super();
|
||||||
|
this.Data = {
|
||||||
|
id: DayId,
|
||||||
|
t: Type,
|
||||||
|
r: rank,
|
||||||
|
p: Parameter
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
12
src/script/Engine/CatanEngine.meta
Normal file
12
src/script/Engine/CatanEngine.meta
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.1.2",
|
||||||
|
"uuid": "a69fe64f-177f-4e4b-83f0-1f418203d85f",
|
||||||
|
"isBundle": false,
|
||||||
|
"bundleName": "",
|
||||||
|
"priority": 1,
|
||||||
|
"compressionType": {},
|
||||||
|
"optimizeHotUpdate": {},
|
||||||
|
"inlineSpriteFrames": {},
|
||||||
|
"isRemoteBundle": {},
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
12
src/script/Engine/CatanEngine/CSharp.meta
Normal file
12
src/script/Engine/CatanEngine/CSharp.meta
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.1.2",
|
||||||
|
"uuid": "f9edb32f-c4ab-4e5d-8270-71fa609e1db7",
|
||||||
|
"isBundle": false,
|
||||||
|
"bundleName": "",
|
||||||
|
"priority": 1,
|
||||||
|
"compressionType": {},
|
||||||
|
"optimizeHotUpdate": {},
|
||||||
|
"inlineSpriteFrames": {},
|
||||||
|
"isRemoteBundle": {},
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
20
src/script/Engine/CatanEngine/CSharp/String.ts
Normal file
20
src/script/Engine/CatanEngine/CSharp/String.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
declare global {
|
||||||
|
interface StringConstructor {
|
||||||
|
IsNullOrEmpty: (value: string) => boolean;
|
||||||
|
Format: (format: string, ...args: any[]) => string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String.IsNullOrEmpty = function (value: string): boolean {
|
||||||
|
return value === undefined || value === null || value.trim() === '';
|
||||||
|
};
|
||||||
|
|
||||||
|
String.Format = function (format: string, ...args: any[]): string {
|
||||||
|
return format.replace(/{(\d+)}/g, (match, index) => {
|
||||||
|
let value = args[index];
|
||||||
|
if (value === null || value === undefined) return '';
|
||||||
|
return '' + value;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export { };
|
9
src/script/Engine/CatanEngine/CSharp/String.ts.meta
Normal file
9
src/script/Engine/CatanEngine/CSharp/String.ts.meta
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.0.8",
|
||||||
|
"uuid": "0c3d1ca6-bdaf-4a00-b209-6ef460802cdc",
|
||||||
|
"isPlugin": false,
|
||||||
|
"loadPluginInWeb": true,
|
||||||
|
"loadPluginInNative": true,
|
||||||
|
"loadPluginInEditor": false,
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
12
src/script/Engine/CatanEngine/CSharp/System.meta
Normal file
12
src/script/Engine/CatanEngine/CSharp/System.meta
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.1.2",
|
||||||
|
"uuid": "01b35dee-e6e0-4a6e-a73c-3b49c37f1c5f",
|
||||||
|
"isBundle": false,
|
||||||
|
"bundleName": "",
|
||||||
|
"priority": 1,
|
||||||
|
"compressionType": {},
|
||||||
|
"optimizeHotUpdate": {},
|
||||||
|
"inlineSpriteFrames": {},
|
||||||
|
"isRemoteBundle": {},
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
125
src/script/Engine/CatanEngine/CSharp/System/Action.ts
Normal file
125
src/script/Engine/CatanEngine/CSharp/System/Action.ts
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
/**
|
||||||
|
* 回呼函數: fnname (arg: TArg): void
|
||||||
|
*/
|
||||||
|
interface ActionCallback<TArg> {
|
||||||
|
(arg: TArg): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Struct<TArg> {
|
||||||
|
callback: ActionCallback<TArg>;
|
||||||
|
target: any;
|
||||||
|
once?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Action<TArg> {
|
||||||
|
private _queue: Struct<TArg>[] = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 監聽事件
|
||||||
|
* @param callback 回呼函數: fnname (arg: TArg): void
|
||||||
|
* @param bindTarget 回呼時this綁定的對象
|
||||||
|
*/
|
||||||
|
AddCallback(callback: ActionCallback<TArg>, bindTarget?: any) {
|
||||||
|
let q = <Struct<TArg>> {
|
||||||
|
callback: callback,
|
||||||
|
target: bindTarget
|
||||||
|
};
|
||||||
|
this._queue.push(q);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 監聽事件 (一次性)
|
||||||
|
* @param callback 回呼函數: fnname (arg: TArg): void
|
||||||
|
* @param bindTarget 回呼時this綁定的對象
|
||||||
|
*/
|
||||||
|
AddCallbackOnce(callback: ActionCallback<TArg>, bindTarget?: any) {
|
||||||
|
let q = <Struct<TArg>> {
|
||||||
|
callback: callback,
|
||||||
|
target: bindTarget,
|
||||||
|
once: true
|
||||||
|
};
|
||||||
|
this._queue.push(q);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 移除事件
|
||||||
|
* @param callback
|
||||||
|
*/
|
||||||
|
RemoveByCallback(callback: ActionCallback<TArg>) {
|
||||||
|
let index = this._queue.length;
|
||||||
|
if (index > 0) {
|
||||||
|
while (index--) {
|
||||||
|
let q = this._queue[index];
|
||||||
|
if (!q.callback || q.callback === callback) {
|
||||||
|
q.callback = undefined;
|
||||||
|
this._queue.splice(index, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 移除事件
|
||||||
|
* @param bindTarget 回呼時this綁定的對象
|
||||||
|
*/
|
||||||
|
RemoveByBindTarget(bindTarget: any) {
|
||||||
|
let index = this._queue.length;
|
||||||
|
if (index > 0) {
|
||||||
|
while (index--) {
|
||||||
|
let q = this._queue[index];
|
||||||
|
if (!q.callback || q.target === bindTarget) {
|
||||||
|
q.callback = undefined;
|
||||||
|
this._queue.splice(index, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 移除全部事件
|
||||||
|
*/
|
||||||
|
RemoveAllCallbacks() {
|
||||||
|
this._queue.forEach(q => q.callback = undefined);
|
||||||
|
this._queue.length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 發送事件
|
||||||
|
* @param arg 參數
|
||||||
|
*/
|
||||||
|
DispatchCallback(arg: TArg) {
|
||||||
|
let index = this._queue.length;
|
||||||
|
if (index > 0) {
|
||||||
|
let cleanRemoved = false;
|
||||||
|
this._queue.slice().forEach(q => {
|
||||||
|
if (!q.callback) {
|
||||||
|
cleanRemoved = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (q.target) {
|
||||||
|
q.callback.call(q.target, arg);
|
||||||
|
} else {
|
||||||
|
q.callback(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (q.once) {
|
||||||
|
q.callback = undefined;
|
||||||
|
cleanRemoved = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (cleanRemoved) {
|
||||||
|
index = this._queue.length;
|
||||||
|
if (index > 0) {
|
||||||
|
while (index--) {
|
||||||
|
let q = this._queue[index];
|
||||||
|
if (!q.callback) {
|
||||||
|
this._queue.splice(index, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.0.8",
|
||||||
|
"uuid": "ea9bf762-40a7-4bab-b949-8d5b3d4289e2",
|
||||||
|
"isPlugin": false,
|
||||||
|
"loadPluginInWeb": true,
|
||||||
|
"loadPluginInNative": true,
|
||||||
|
"loadPluginInEditor": false,
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
85
src/script/Engine/CatanEngine/CSharp/System/ActionExample.ts
Normal file
85
src/script/Engine/CatanEngine/CSharp/System/ActionExample.ts
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
import { Action } from "./Action";
|
||||||
|
import { ActionWithType } from "./ActionWithType";
|
||||||
|
import { ActionWithType2 } from "./ActionWithType2";
|
||||||
|
|
||||||
|
const { ccclass, property } = console._decorator;
|
||||||
|
|
||||||
|
enum CustomType {
|
||||||
|
Ex1, Ex2
|
||||||
|
}
|
||||||
|
|
||||||
|
class CustomEvent extends ActionWithType<CustomType, number> { }
|
||||||
|
class CustomEvent2 extends ActionWithType2<CustomType, number> { }
|
||||||
|
|
||||||
|
@ccclass
|
||||||
|
export default class NewClass extends console.Component {
|
||||||
|
callback: Action<number> = new Action<number>();
|
||||||
|
customCallback: CustomEvent = new CustomEvent();
|
||||||
|
customCallback2: CustomEvent2 = new CustomEvent2();
|
||||||
|
|
||||||
|
private num: number = 0;
|
||||||
|
|
||||||
|
start() {
|
||||||
|
this.callback.AddCallback(this.CB, this);
|
||||||
|
this.callback.AddCallbackOnce(this.OnceCB, this);
|
||||||
|
|
||||||
|
this.customCallback.AddCallback(CustomType.Ex1, this.CBType, this);
|
||||||
|
this.customCallback.AddCallbackOnce(CustomType.Ex2, this.OnceCBType, this);
|
||||||
|
|
||||||
|
this.customCallback2.AddCallback(CustomType.Ex2, this.CBTypeAllin1, this);
|
||||||
|
this.customCallback2.AddCallbackOnce(CustomType.Ex1, this.CBTypeAllin1, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
DispatchClick() {
|
||||||
|
this.num++;
|
||||||
|
|
||||||
|
this.callback.DispatchCallback(this.num);
|
||||||
|
|
||||||
|
this.customCallback.DispatchCallback(CustomType.Ex1, this.num);
|
||||||
|
this.customCallback.DispatchCallback(CustomType.Ex2, this.num);
|
||||||
|
|
||||||
|
this.customCallback2.DispatchCallback(CustomType.Ex1, this.num);
|
||||||
|
this.customCallback2.DispatchCallback(CustomType.Ex2, this.num);
|
||||||
|
}
|
||||||
|
|
||||||
|
RemoveEventClick() {
|
||||||
|
this.callback.RemoveByCallback(this.CB);
|
||||||
|
// this.callback.RemoveByCallback(this.OnceCB);
|
||||||
|
// this.callback.RemoveByBindTarget(this);
|
||||||
|
// this.callback.RemoveAll();
|
||||||
|
|
||||||
|
// this.callbackWithType.RemoveByCallback(this.CBType);
|
||||||
|
// this.callbackWithType.RemoveByCallback(this.OnceCBType);
|
||||||
|
this.customCallback.RemoveByType(CustomType.Ex1);
|
||||||
|
// this.callbackWithType.RemoveByType(CustomType.Ex2);
|
||||||
|
// this.callbackWithType.RemoveByBindTarget(this);
|
||||||
|
// this.callbackWithType.RemoveAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
OnceCB(x: number) {
|
||||||
|
console.log(`OnceCB [${this.num}]`);
|
||||||
|
}
|
||||||
|
|
||||||
|
CB(x: number) {
|
||||||
|
console.log(`CB [${this.num}]`);
|
||||||
|
}
|
||||||
|
|
||||||
|
OnceCBType(x: number) {
|
||||||
|
console.log(`OnceCBType [${this.num}]`);
|
||||||
|
}
|
||||||
|
|
||||||
|
CBType(x: number) {
|
||||||
|
console.log(`CBType [${this.num}]`);
|
||||||
|
}
|
||||||
|
|
||||||
|
CBTypeAllin1(type: CustomType, x: number) {
|
||||||
|
// switch (type) {
|
||||||
|
// case CustomType.Ex1:
|
||||||
|
// break;
|
||||||
|
// case CustomType.Ex2:
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
|
||||||
|
console.log(`CBTypeAllin1 [${CustomType[type]}][${this.num}]`);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.0.8",
|
||||||
|
"uuid": "cc645b73-6192-414d-a5bc-4220c24e322d",
|
||||||
|
"isPlugin": false,
|
||||||
|
"loadPluginInWeb": true,
|
||||||
|
"loadPluginInNative": true,
|
||||||
|
"loadPluginInEditor": false,
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
166
src/script/Engine/CatanEngine/CSharp/System/ActionWithType.ts
Normal file
166
src/script/Engine/CatanEngine/CSharp/System/ActionWithType.ts
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
/**
|
||||||
|
* 回呼函數: fnname (arg: TArg): void
|
||||||
|
*/
|
||||||
|
interface ActionCallback<TArg> {
|
||||||
|
(arg: TArg): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Struct<TType, TArg> {
|
||||||
|
callback: ActionCallback<TArg>;
|
||||||
|
target: any;
|
||||||
|
type: TType;
|
||||||
|
once?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ActionWithType<TType, TArg> {
|
||||||
|
private _queue: Struct<TType, TArg>[] = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 監聽事件
|
||||||
|
* @param callback 回呼函數: fnname (arg: TArg): void
|
||||||
|
* @param bindTarget 回呼時this綁定的對象
|
||||||
|
*/
|
||||||
|
AddCallback(type: TType, callback: ActionCallback<TArg>, bindTarget?: any) {
|
||||||
|
let q = <Struct<TType, TArg>> {
|
||||||
|
callback: callback,
|
||||||
|
target: bindTarget,
|
||||||
|
type: type
|
||||||
|
};
|
||||||
|
this._queue.push(q);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 監聽事件 (一次性)
|
||||||
|
* @param callback 回呼函數: fnname (arg: TArg): void
|
||||||
|
* @param bindTarget 回呼時this綁定的對象
|
||||||
|
*/
|
||||||
|
AddCallbackOnce(type: TType, callback: ActionCallback<TArg>, bindTarget?: any) {
|
||||||
|
let q = <Struct<TType, TArg>> {
|
||||||
|
callback: callback,
|
||||||
|
target: bindTarget,
|
||||||
|
type: type,
|
||||||
|
once: true
|
||||||
|
};
|
||||||
|
this._queue.push(q);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 移除事件
|
||||||
|
* @param callback
|
||||||
|
*/
|
||||||
|
RemoveByCallback(callback: ActionCallback<TArg>) {
|
||||||
|
let index = this._queue.length;
|
||||||
|
if (index > 0) {
|
||||||
|
while (index--) {
|
||||||
|
let q = this._queue[index];
|
||||||
|
if (!q.callback || q.callback === callback) {
|
||||||
|
q.callback = undefined;
|
||||||
|
this._queue.splice(index, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 移除事件
|
||||||
|
* @param bindTarget 回呼時this綁定的對象
|
||||||
|
*/
|
||||||
|
RemoveByBindTarget(bindTarget: any) {
|
||||||
|
let index = this._queue.length;
|
||||||
|
if (index > 0) {
|
||||||
|
while (index--) {
|
||||||
|
let q = this._queue[index];
|
||||||
|
if (!q.callback || q.target === bindTarget) {
|
||||||
|
q.callback = undefined;
|
||||||
|
this._queue.splice(index, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 移除事件
|
||||||
|
* @param type 事件類型
|
||||||
|
*/
|
||||||
|
RemoveByType(type: TType) {
|
||||||
|
let index = this._queue.length;
|
||||||
|
if (index > 0) {
|
||||||
|
while (index--) {
|
||||||
|
let q = this._queue[index];
|
||||||
|
if (!q.callback || q.type === type) {
|
||||||
|
q.callback = undefined;
|
||||||
|
this._queue.splice(index, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 移除事件
|
||||||
|
* @param type 事件類型
|
||||||
|
* @param callback
|
||||||
|
*/
|
||||||
|
RemoveCallback(type:TType, callback: ActionCallback<TArg>) {
|
||||||
|
let index = this._queue.length;
|
||||||
|
if (index > 0) {
|
||||||
|
while (index--) {
|
||||||
|
let q = this._queue[index];
|
||||||
|
if (!q.callback || (q.type === type && q.callback === callback)) {
|
||||||
|
q.callback = undefined;
|
||||||
|
this._queue.splice(index, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 移除全部事件
|
||||||
|
*/
|
||||||
|
RemoveAllCallbacks() {
|
||||||
|
this._queue.forEach(q => q.callback = undefined);
|
||||||
|
this._queue.length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 發送事件
|
||||||
|
* @param type 事件類型
|
||||||
|
* @param arg 參數
|
||||||
|
*/
|
||||||
|
DispatchCallback(type: TType, arg: TArg) {
|
||||||
|
let index = this._queue.length;
|
||||||
|
if (index > 0) {
|
||||||
|
let cleanRemoved = false;
|
||||||
|
this._queue.slice().forEach(q => {
|
||||||
|
if (!q.callback)
|
||||||
|
{
|
||||||
|
cleanRemoved = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (q.type !== type) return;
|
||||||
|
|
||||||
|
if (q.target) {
|
||||||
|
q.callback.call(q.target, arg);
|
||||||
|
} else {
|
||||||
|
q.callback(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (q.once) {
|
||||||
|
q.callback = undefined;
|
||||||
|
cleanRemoved = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (cleanRemoved) {
|
||||||
|
index = this._queue.length;
|
||||||
|
if (index > 0) {
|
||||||
|
while (index--) {
|
||||||
|
let q = this._queue[index];
|
||||||
|
if (!q.callback) {
|
||||||
|
this._queue.splice(index, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.0.8",
|
||||||
|
"uuid": "61d770ec-24e2-425b-b66b-2b03e192e45b",
|
||||||
|
"isPlugin": false,
|
||||||
|
"loadPluginInWeb": true,
|
||||||
|
"loadPluginInNative": true,
|
||||||
|
"loadPluginInEditor": false,
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
166
src/script/Engine/CatanEngine/CSharp/System/ActionWithType2.ts
Normal file
166
src/script/Engine/CatanEngine/CSharp/System/ActionWithType2.ts
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
/**
|
||||||
|
* 回呼函數: fnname (type: TType, arg: TArg): void
|
||||||
|
*/
|
||||||
|
interface ActionCallback<TType, TArg> {
|
||||||
|
(type: TType, arg: TArg): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Struct<TType, TArg> {
|
||||||
|
callback: ActionCallback<TType, TArg>;
|
||||||
|
target: any;
|
||||||
|
type: TType;
|
||||||
|
once?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ActionWithType2<TType, TArg> {
|
||||||
|
private _queue: Struct<TType, TArg>[] = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 監聽事件
|
||||||
|
* @param callback 回呼函數: fnname (type: TType, arg: TArg): void
|
||||||
|
* @param bindTarget 回呼時this綁定的對象
|
||||||
|
*/
|
||||||
|
AddCallback(type: TType, callback: ActionCallback<TType, TArg>, bindTarget?: any) {
|
||||||
|
let q = <Struct<TType, TArg>> {
|
||||||
|
callback: callback,
|
||||||
|
target: bindTarget,
|
||||||
|
type: type
|
||||||
|
};
|
||||||
|
this._queue.push(q);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 監聽事件 (一次性)
|
||||||
|
* @param callback 回呼函數: fnname (type: TType, arg: TArg): void
|
||||||
|
* @param bindTarget 回呼時this綁定的對象
|
||||||
|
*/
|
||||||
|
AddCallbackOnce(type: TType, callback: ActionCallback<TType, TArg>, bindTarget?: any) {
|
||||||
|
let q = <Struct<TType, TArg>> {
|
||||||
|
callback: callback,
|
||||||
|
target: bindTarget,
|
||||||
|
type: type,
|
||||||
|
once: true
|
||||||
|
};
|
||||||
|
this._queue.push(q);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 移除事件
|
||||||
|
* @param callback
|
||||||
|
*/
|
||||||
|
RemoveByCallback(callback: ActionCallback<TType, TArg>) {
|
||||||
|
let index = this._queue.length;
|
||||||
|
if (index > 0) {
|
||||||
|
while (index--) {
|
||||||
|
let q = this._queue[index];
|
||||||
|
if (!q.callback || q.callback === callback) {
|
||||||
|
q.callback = undefined;
|
||||||
|
this._queue.splice(index, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 移除事件
|
||||||
|
* @param bindTarget 回呼時this綁定的對象
|
||||||
|
*/
|
||||||
|
RemoveByBindTarget(bindTarget: any) {
|
||||||
|
let index = this._queue.length;
|
||||||
|
if (index > 0) {
|
||||||
|
while (index--) {
|
||||||
|
let q = this._queue[index];
|
||||||
|
if (!q.callback || q.target === bindTarget) {
|
||||||
|
q.callback = undefined;
|
||||||
|
this._queue.splice(index, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 移除事件
|
||||||
|
* @param type 事件類型
|
||||||
|
*/
|
||||||
|
RemoveByType(type: TType) {
|
||||||
|
let index = this._queue.length;
|
||||||
|
if (index > 0) {
|
||||||
|
while (index--) {
|
||||||
|
let q = this._queue[index];
|
||||||
|
if (!q.callback || q.type === type) {
|
||||||
|
q.callback = undefined;
|
||||||
|
this._queue.splice(index, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 移除事件
|
||||||
|
* @param type 事件類型
|
||||||
|
* @param callback
|
||||||
|
*/
|
||||||
|
RemoveCallback(type:TType, callback: ActionCallback<TType, TArg>) {
|
||||||
|
let index = this._queue.length;
|
||||||
|
if (index > 0) {
|
||||||
|
while (index--) {
|
||||||
|
let q = this._queue[index];
|
||||||
|
if (!q.callback || (q.type === type && q.callback === callback)) {
|
||||||
|
q.callback = undefined;
|
||||||
|
this._queue.splice(index, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 移除全部事件
|
||||||
|
*/
|
||||||
|
RemoveAllCallbacks() {
|
||||||
|
this._queue.forEach(q => q.callback = undefined);
|
||||||
|
this._queue.length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 發送事件
|
||||||
|
* @param type 事件類型
|
||||||
|
* @param arg 參數
|
||||||
|
*/
|
||||||
|
DispatchCallback(type: TType, arg: TArg) {
|
||||||
|
let index = this._queue.length;
|
||||||
|
if (index > 0) {
|
||||||
|
let cleanRemoved = false;
|
||||||
|
this._queue.slice().forEach(q => {
|
||||||
|
if (!q.callback)
|
||||||
|
{
|
||||||
|
cleanRemoved = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (q.type !== type) return;
|
||||||
|
|
||||||
|
if (q.target) {
|
||||||
|
q.callback.call(q.target, type, arg);
|
||||||
|
} else {
|
||||||
|
q.callback(type, arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (q.once) {
|
||||||
|
q.callback = undefined;
|
||||||
|
cleanRemoved = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (cleanRemoved) {
|
||||||
|
index = this._queue.length;
|
||||||
|
if (index > 0) {
|
||||||
|
while (index--) {
|
||||||
|
let q = this._queue[index];
|
||||||
|
if (!q.callback) {
|
||||||
|
this._queue.splice(index, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.0.8",
|
||||||
|
"uuid": "ed703ebd-efd4-4ec9-9b84-de748ef8f9e8",
|
||||||
|
"isPlugin": false,
|
||||||
|
"loadPluginInWeb": true,
|
||||||
|
"loadPluginInNative": true,
|
||||||
|
"loadPluginInEditor": false,
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
12
src/script/Engine/CatanEngine/CSharp/System/Text.meta
Normal file
12
src/script/Engine/CatanEngine/CSharp/System/Text.meta
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.1.2",
|
||||||
|
"uuid": "09d69d12-a6d1-4bb1-bcfe-faa811632467",
|
||||||
|
"isBundle": false,
|
||||||
|
"bundleName": "",
|
||||||
|
"priority": 1,
|
||||||
|
"compressionType": {},
|
||||||
|
"optimizeHotUpdate": {},
|
||||||
|
"inlineSpriteFrames": {},
|
||||||
|
"isRemoteBundle": {},
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
68
src/script/Engine/CatanEngine/CSharp/System/Text/Encoding.ts
Normal file
68
src/script/Engine/CatanEngine/CSharp/System/Text/Encoding.ts
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
export module Encoding.UTF8 {
|
||||||
|
|
||||||
|
export function GetBytes(str: string) {
|
||||||
|
let len = str.length, resPos = -1;
|
||||||
|
let resArr = new Uint8Array(len * 3);
|
||||||
|
for (let point = 0, nextcode = 0, i = 0; i !== len; ) {
|
||||||
|
point = str.charCodeAt(i), i += 1;
|
||||||
|
if (point >= 0xD800 && point <= 0xDBFF) {
|
||||||
|
if (i === len) {
|
||||||
|
resArr[resPos += 1] = 0xef;
|
||||||
|
resArr[resPos += 1] = 0xbf;
|
||||||
|
resArr[resPos += 1] = 0xbd;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
nextcode = str.charCodeAt(i);
|
||||||
|
if (nextcode >= 0xDC00 && nextcode <= 0xDFFF) {
|
||||||
|
point = (point - 0xD800) * 0x400 + nextcode - 0xDC00 + 0x10000;
|
||||||
|
i += 1;
|
||||||
|
if (point > 0xffff) {
|
||||||
|
resArr[resPos += 1] = (0x1e << 3) | (point >>> 18);
|
||||||
|
resArr[resPos += 1] = (0x2 << 6) | ((point >>> 12) & 0x3f);
|
||||||
|
resArr[resPos += 1] = (0x2 << 6) | ((point >>> 6) & 0x3f);
|
||||||
|
resArr[resPos += 1] = (0x2 << 6) | (point & 0x3f);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
resArr[resPos += 1] = 0xef;
|
||||||
|
resArr[resPos += 1] = 0xbf;
|
||||||
|
resArr[resPos += 1] = 0xbd;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (point <= 0x007f) {
|
||||||
|
resArr[resPos += 1] = (0x0 << 7) | point;
|
||||||
|
} else if (point <= 0x07ff) {
|
||||||
|
resArr[resPos += 1] = (0x6 << 5) | (point >>> 6);
|
||||||
|
resArr[resPos += 1] = (0x2 << 6) | (point & 0x3f);
|
||||||
|
} else {
|
||||||
|
resArr[resPos += 1] = (0xe << 4) | (point >>> 12);
|
||||||
|
resArr[resPos += 1] = (0x2 << 6) | ((point >>> 6) & 0x3f);
|
||||||
|
resArr[resPos += 1] = (0x2 << 6) | (point & 0x3f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return resArr.subarray(0, resPos + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function GetString(array: Uint8Array) {
|
||||||
|
let str = "";
|
||||||
|
let i = 0, len = array.length;
|
||||||
|
while(i < len) {
|
||||||
|
let c = array[i++];
|
||||||
|
switch (c >> 4)
|
||||||
|
{
|
||||||
|
case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
|
||||||
|
str += String.fromCharCode(c);
|
||||||
|
break;
|
||||||
|
case 12: case 13:
|
||||||
|
str += String.fromCharCode(((c & 0x1F) << 6) | (array[i++] & 0x3F));
|
||||||
|
break;
|
||||||
|
case 14:
|
||||||
|
str += String.fromCharCode(((c & 0x0F) << 12) | ((array[i++] & 0x3F) << 6) | ((array[i++] & 0x3F) << 0));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.0.8",
|
||||||
|
"uuid": "43bf5724-e939-4189-b981-c32ef694e5a5",
|
||||||
|
"isPlugin": false,
|
||||||
|
"loadPluginInWeb": true,
|
||||||
|
"loadPluginInNative": true,
|
||||||
|
"loadPluginInEditor": false,
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
12
src/script/Engine/CatanEngine/CoroutineV2.meta
Normal file
12
src/script/Engine/CatanEngine/CoroutineV2.meta
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.1.2",
|
||||||
|
"uuid": "9f510f2b-83d8-4097-8683-32d6134323fb",
|
||||||
|
"isBundle": false,
|
||||||
|
"bundleName": "",
|
||||||
|
"priority": 1,
|
||||||
|
"compressionType": {},
|
||||||
|
"optimizeHotUpdate": {},
|
||||||
|
"inlineSpriteFrames": {},
|
||||||
|
"isRemoteBundle": {},
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.0.8",
|
||||||
|
"uuid": "9a414131-91a8-4d02-9921-9d1ee01764c3",
|
||||||
|
"isPlugin": false,
|
||||||
|
"loadPluginInWeb": true,
|
||||||
|
"loadPluginInNative": true,
|
||||||
|
"loadPluginInEditor": false,
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
12
src/script/Engine/CatanEngine/CoroutineV2/Core.meta
Normal file
12
src/script/Engine/CatanEngine/CoroutineV2/Core.meta
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.1.2",
|
||||||
|
"uuid": "fbfe97a8-24ca-4f67-b049-323652c7194b",
|
||||||
|
"isBundle": false,
|
||||||
|
"bundleName": "",
|
||||||
|
"priority": 1,
|
||||||
|
"compressionType": {},
|
||||||
|
"optimizeHotUpdate": {},
|
||||||
|
"inlineSpriteFrames": {},
|
||||||
|
"isRemoteBundle": {},
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
@ -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 };
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.0.8",
|
||||||
|
"uuid": "3cf9e5c3-520f-48a9-8821-9be76d519765",
|
||||||
|
"isPlugin": false,
|
||||||
|
"loadPluginInWeb": true,
|
||||||
|
"loadPluginInNative": true,
|
||||||
|
"loadPluginInEditor": false,
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.0.8",
|
||||||
|
"uuid": "4084537c-c7e8-4d47-b283-39be77ef9685",
|
||||||
|
"isPlugin": false,
|
||||||
|
"loadPluginInWeb": true,
|
||||||
|
"loadPluginInNative": true,
|
||||||
|
"loadPluginInEditor": false,
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
@ -0,0 +1,94 @@
|
|||||||
|
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: console.Scheduler;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this._scheduler = console.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 (true) {
|
||||||
|
console.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;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.0.8",
|
||||||
|
"uuid": "f25b1e42-90d8-4fc0-9925-6e7e92296d57",
|
||||||
|
"isPlugin": false,
|
||||||
|
"loadPluginInWeb": true,
|
||||||
|
"loadPluginInNative": true,
|
||||||
|
"loadPluginInEditor": false,
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
@ -0,0 +1,168 @@
|
|||||||
|
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) {
|
||||||
|
console.error(e.stack);
|
||||||
|
} else {
|
||||||
|
console.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) {
|
||||||
|
console.error(e.stack);
|
||||||
|
} else {
|
||||||
|
console.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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.0.8",
|
||||||
|
"uuid": "91cb70ed-e6f9-4ce0-b7c5-1720087b3bd7",
|
||||||
|
"isPlugin": false,
|
||||||
|
"loadPluginInWeb": true,
|
||||||
|
"loadPluginInNative": true,
|
||||||
|
"loadPluginInEditor": false,
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
@ -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 };
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.0.8",
|
||||||
|
"uuid": "017ebc9a-5152-4f94-bbaf-e3b914e87b41",
|
||||||
|
"isPlugin": false,
|
||||||
|
"loadPluginInWeb": true,
|
||||||
|
"loadPluginInNative": true,
|
||||||
|
"loadPluginInEditor": false,
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.0.8",
|
||||||
|
"uuid": "c439d019-2da8-48b8-a65b-bff928d0fda8",
|
||||||
|
"isPlugin": false,
|
||||||
|
"loadPluginInWeb": true,
|
||||||
|
"loadPluginInNative": true,
|
||||||
|
"loadPluginInEditor": false,
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
@ -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 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.0.8",
|
||||||
|
"uuid": "a3038e6f-1bb4-4aff-a686-b69209df3592",
|
||||||
|
"isPlugin": false,
|
||||||
|
"loadPluginInWeb": true,
|
||||||
|
"loadPluginInNative": true,
|
||||||
|
"loadPluginInEditor": false,
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
197
src/script/Engine/CatanEngine/CoroutineV2/CoroutineExample.ts
Normal file
197
src/script/Engine/CatanEngine/CoroutineV2/CoroutineExample.ts
Normal file
@ -0,0 +1,197 @@
|
|||||||
|
import { CoroutineV2 } from "./CoroutineV2";
|
||||||
|
import { IEnumeratorV2Started } from "./IEnumeratorV2";
|
||||||
|
|
||||||
|
const { ccclass, property } = console._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++];
|
||||||
|
console.log(`A=> ${value}`);
|
||||||
|
return {
|
||||||
|
done: false,
|
||||||
|
value: value
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return { done: true, value: undefined };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ccclass
|
||||||
|
export default class CoroutineExample extends console.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(() => console.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();
|
||||||
|
console.log("main wait 3");
|
||||||
|
yield CoroutineV2.WaitTime(2);
|
||||||
|
console.log("done");
|
||||||
|
}
|
||||||
|
|
||||||
|
*Test1_3_1() {
|
||||||
|
yield this.Test1_3_2();
|
||||||
|
yield CoroutineV2.WaitTime(1);
|
||||||
|
console.log("Test1_3_1.1");
|
||||||
|
yield CoroutineV2.WaitTime(1);
|
||||||
|
console.log("Test1_3_1.2");
|
||||||
|
}
|
||||||
|
|
||||||
|
*Test1_3_2() {
|
||||||
|
yield this.Test1_3_3();
|
||||||
|
yield CoroutineV2.WaitTime(1);
|
||||||
|
console.log("Test1_3_2.1");
|
||||||
|
yield CoroutineV2.WaitTime(1);
|
||||||
|
console.log("Test1_3_2.2");
|
||||||
|
yield CoroutineV2.WaitTime(1);
|
||||||
|
console.log("Test1_3_2.3");
|
||||||
|
}
|
||||||
|
|
||||||
|
*Test1_3_3() {
|
||||||
|
yield CoroutineV2.WaitTime(1);
|
||||||
|
console.log("Test1_3_3.1");
|
||||||
|
yield CoroutineV2.WaitTime(1);
|
||||||
|
console.log("Test1_3_3.2");
|
||||||
|
yield CoroutineV2.WaitTime(1);
|
||||||
|
console.log("Test1_3_3.3");
|
||||||
|
}
|
||||||
|
|
||||||
|
*Test1_4() {
|
||||||
|
this._num++;
|
||||||
|
console.log(`WaitTime2 ${this._num}`);
|
||||||
|
yield CoroutineV2.WaitTime(2).Start(this._obj2);
|
||||||
|
this._num++;
|
||||||
|
console.log(`WaitTime2 ${this._num}`);
|
||||||
|
yield CoroutineV2.WaitTime(2).Start(this._obj2);
|
||||||
|
this._num++;
|
||||||
|
console.log(`WaitTime2 ${this._num}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
*Test2_1() {
|
||||||
|
console.log("111");
|
||||||
|
CoroutineV2.Single(this.Test2_2()).Start(this);
|
||||||
|
console.log("333");
|
||||||
|
}
|
||||||
|
|
||||||
|
*Test2_2() {
|
||||||
|
console.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();
|
||||||
|
console.log(`C1 => ${i}`);
|
||||||
|
|
||||||
|
// 嵌套
|
||||||
|
yield CoroutineV2
|
||||||
|
.WaitTime(1)
|
||||||
|
.ThenParallel(
|
||||||
|
// 再嵌套
|
||||||
|
CoroutineV2.Action(() => console.log("start parallel")),
|
||||||
|
this.Coroutine2(10, 2),
|
||||||
|
this.Coroutine2(20, 2),
|
||||||
|
new A())
|
||||||
|
.ThenAction(() => console.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;
|
||||||
|
console.log(`C2: ${num}`);
|
||||||
|
// yield CoroutineV2.WaitTime(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
actionCallback() {
|
||||||
|
console.log("action callback 2");
|
||||||
|
}
|
||||||
|
|
||||||
|
loadItemAsync(id: string): Promise<{ id: string }> {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
console.log('loading item start:', id);
|
||||||
|
setTimeout(() => {
|
||||||
|
resolve({ id: id });
|
||||||
|
console.log('loading item done:', id);
|
||||||
|
}, 3000);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.0.8",
|
||||||
|
"uuid": "dfd32c11-76f6-4e38-9272-1d7966d1ef3c",
|
||||||
|
"isPlugin": false,
|
||||||
|
"loadPluginInWeb": true,
|
||||||
|
"loadPluginInNative": true,
|
||||||
|
"loadPluginInEditor": false,
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
75
src/script/Engine/CatanEngine/CoroutineV2/CoroutineV2.ts
Normal file
75
src/script/Engine/CatanEngine/CoroutineV2/CoroutineV2.ts
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.0.8",
|
||||||
|
"uuid": "fc38e505-bd37-44c3-9e0a-fd463bb88c51",
|
||||||
|
"isPlugin": false,
|
||||||
|
"loadPluginInWeb": true,
|
||||||
|
"loadPluginInNative": true,
|
||||||
|
"loadPluginInEditor": false,
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
16
src/script/Engine/CatanEngine/CoroutineV2/IEnumeratorV2.ts
Normal file
16
src/script/Engine/CatanEngine/CoroutineV2/IEnumeratorV2.ts
Normal 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;
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.0.8",
|
||||||
|
"uuid": "df3ab07d-3d2b-4552-b454-29b95223ea85",
|
||||||
|
"isPlugin": false,
|
||||||
|
"loadPluginInWeb": true,
|
||||||
|
"loadPluginInNative": true,
|
||||||
|
"loadPluginInEditor": false,
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
12
src/script/Engine/CatanEngine/NetManagerV2.meta
Normal file
12
src/script/Engine/CatanEngine/NetManagerV2.meta
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.1.2",
|
||||||
|
"uuid": "6f870efd-e869-4415-9cf2-138ab667cd5d",
|
||||||
|
"isBundle": false,
|
||||||
|
"bundleName": "",
|
||||||
|
"priority": 1,
|
||||||
|
"compressionType": {},
|
||||||
|
"optimizeHotUpdate": {},
|
||||||
|
"inlineSpriteFrames": {},
|
||||||
|
"isRemoteBundle": {},
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
12
src/script/Engine/CatanEngine/NetManagerV2/Core.meta
Normal file
12
src/script/Engine/CatanEngine/NetManagerV2/Core.meta
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.1.2",
|
||||||
|
"uuid": "5e6c027f-ce4b-47fa-968c-f3bb6059ad81",
|
||||||
|
"isBundle": false,
|
||||||
|
"bundleName": "",
|
||||||
|
"priority": 1,
|
||||||
|
"compressionType": {},
|
||||||
|
"optimizeHotUpdate": {},
|
||||||
|
"inlineSpriteFrames": {},
|
||||||
|
"isRemoteBundle": {},
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
import { Action } from "../../CSharp/System/Action";
|
||||||
|
import { INetRequest } from "./INetRequest";
|
||||||
|
import { INetResponse } from "./INetResponse";
|
||||||
|
|
||||||
|
export interface INetConnector {
|
||||||
|
readonly OnDataReceived: Action<INetResponse<any>>;
|
||||||
|
readonly OnDisconnected: Action<void>;
|
||||||
|
readonly IsConnected: boolean;
|
||||||
|
|
||||||
|
SendAsync<TRequest, TResponse>(req: INetRequest<TRequest, TResponse>): Iterator<any>;
|
||||||
|
Send<TRequest, TResponse>(req: INetRequest<TRequest, TResponse>);
|
||||||
|
Logout();
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.0.8",
|
||||||
|
"uuid": "f97991b5-0da6-4220-ab29-13c8f8f7e405",
|
||||||
|
"isPlugin": false,
|
||||||
|
"loadPluginInWeb": true,
|
||||||
|
"loadPluginInNative": true,
|
||||||
|
"loadPluginInEditor": false,
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
import { INetResponse } from "./INetResponse";
|
||||||
|
|
||||||
|
export interface INetRequest<TRequest, TResponse> {
|
||||||
|
readonly Method: string;
|
||||||
|
readonly MethodBack: string;
|
||||||
|
|
||||||
|
Data: TRequest;
|
||||||
|
Result: INetResponse<TResponse>;
|
||||||
|
|
||||||
|
SendAsync(): Promise<Iterator<any>>;
|
||||||
|
Send();
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.0.8",
|
||||||
|
"uuid": "339fcf27-bdb9-4b8f-ae18-dd54c9500145",
|
||||||
|
"isPlugin": false,
|
||||||
|
"loadPluginInWeb": true,
|
||||||
|
"loadPluginInNative": true,
|
||||||
|
"loadPluginInEditor": false,
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
export interface INetResponse<TResponse> {
|
||||||
|
readonly Method: string;
|
||||||
|
readonly Status: number;
|
||||||
|
readonly Data: TResponse;
|
||||||
|
readonly IsValid: boolean;
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.0.8",
|
||||||
|
"uuid": "c4cb0cd4-b98c-4f8e-b1e6-ac3b51281b28",
|
||||||
|
"isPlugin": false,
|
||||||
|
"loadPluginInWeb": true,
|
||||||
|
"loadPluginInNative": true,
|
||||||
|
"loadPluginInEditor": false,
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
12
src/script/Engine/CatanEngine/NetManagerV2/Examples.meta
Normal file
12
src/script/Engine/CatanEngine/NetManagerV2/Examples.meta
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.1.2",
|
||||||
|
"uuid": "94e55972-723c-4dab-9ebc-870bd5043fca",
|
||||||
|
"isBundle": false,
|
||||||
|
"bundleName": "",
|
||||||
|
"priority": 1,
|
||||||
|
"compressionType": {},
|
||||||
|
"optimizeHotUpdate": {},
|
||||||
|
"inlineSpriteFrames": {},
|
||||||
|
"isRemoteBundle": {},
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
@ -0,0 +1,69 @@
|
|||||||
|
import { CoroutineV2 } from "../../CoroutineV2/CoroutineV2";
|
||||||
|
import { INetResponse } from "../Core/INetResponse";
|
||||||
|
import { NetConnector } from "../NetConnector";
|
||||||
|
import { NetManager } from "../NetManager";
|
||||||
|
import { Slot1_SpinRequestExample } from "./Slot1_SpinRequestExample";
|
||||||
|
|
||||||
|
const { ccclass, property } = console._decorator;
|
||||||
|
|
||||||
|
@ccclass
|
||||||
|
export default class NetTester extends console.Component {
|
||||||
|
|
||||||
|
onConnectClicked() {
|
||||||
|
CoroutineV2.StartCoroutine(this.ConnectAsync());
|
||||||
|
}
|
||||||
|
|
||||||
|
*ConnectAsync() {
|
||||||
|
if (!NetManager.HasInit) {
|
||||||
|
let conn = new NetConnector("192.168.7.165", 9005);
|
||||||
|
conn.OnDataReceived.AddCallback(this.OnNetDataReceived, this);
|
||||||
|
conn.OnDisconnected.AddCallback(this.OnNetDisconnected, this);
|
||||||
|
conn.OnLoadUIMask.AddCallback(this.OnLoadUIMask, this);
|
||||||
|
|
||||||
|
NetManager.Initialize(conn);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("連線中...");
|
||||||
|
yield NetManager.ConnectAsync(); // 同個connector要再次連線, 可以不用叫CasinoNetManager.Initialize(), 但要先叫CasinoNetManager.Disconnect()
|
||||||
|
console.log(`連線狀態: ${NetManager.IsConnected}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
onDisconnectClicked() {
|
||||||
|
console.log("中斷連線中...");
|
||||||
|
NetManager.Disconnect(); // 中斷連線
|
||||||
|
}
|
||||||
|
|
||||||
|
onSendMessageClicked1() {
|
||||||
|
console.log("發送訊息(不使用協程)");
|
||||||
|
let req = new Slot1_SpinRequestExample(401);
|
||||||
|
req.Send();
|
||||||
|
// CasinoNetManager.Send(req);
|
||||||
|
}
|
||||||
|
|
||||||
|
onSendMessageClicked2() {
|
||||||
|
CoroutineV2.StartCoroutine(this.SendAsync());
|
||||||
|
}
|
||||||
|
|
||||||
|
*SendAsync() {
|
||||||
|
console.log("發送訊息中(使用協程)...");
|
||||||
|
let req = new Slot1_SpinRequestExample(399);
|
||||||
|
yield req.SendAsync();
|
||||||
|
// yield CasinoNetManager.SendAsync(req);
|
||||||
|
|
||||||
|
let resp = req.Result;
|
||||||
|
console.log(`發送協程完畢, Server回應: ${resp.Method}(${JSON.stringify(resp.Data)}), 狀態: ${resp.Status}`);
|
||||||
|
// console.log(`使用介面資料: ${resp.Data.slot}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
private OnNetDisconnected() {
|
||||||
|
console.log("[事件] 收到連線中斷事件");
|
||||||
|
}
|
||||||
|
|
||||||
|
private OnNetDataReceived(resp: INetResponse<any>) {
|
||||||
|
console.log(`[事件] 收到server呼叫: ${resp.Method}(${JSON.stringify(resp.Data)}), 狀態: ${resp.Status}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
private OnLoadUIMask(value: boolean) {
|
||||||
|
console.log(`[事件] LoadUIMask: ${value}`);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.0.8",
|
||||||
|
"uuid": "0cb7df7a-d0e7-4ce1-832e-4583cf3385e5",
|
||||||
|
"isPlugin": false,
|
||||||
|
"loadPluginInWeb": true,
|
||||||
|
"loadPluginInNative": true,
|
||||||
|
"loadPluginInEditor": false,
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
import { NetRequest } from "../NetRequest";
|
||||||
|
|
||||||
|
// 送給server的結構
|
||||||
|
interface Request {
|
||||||
|
pay: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
// server回應的結構
|
||||||
|
interface Response {
|
||||||
|
pay: [[number, number]];
|
||||||
|
/**拉霸結果 */
|
||||||
|
slot: number[];
|
||||||
|
get: any[];
|
||||||
|
}
|
||||||
|
|
||||||
|
// class Account_CreateRequest extends CasinoRequest<number, any> { // 也可以是基本類或any, 但不建議用any, 使用介面ts才會有提示
|
||||||
|
export class Slot1_SpinRequestExample extends NetRequest<Request, Response> {
|
||||||
|
get Method(): string {
|
||||||
|
return "slot1.spin";
|
||||||
|
}
|
||||||
|
|
||||||
|
// MethodBack預設回傳Method, 不一樣才需要覆寫
|
||||||
|
// get MethodBack(): string {
|
||||||
|
// return "slot1.freespin";
|
||||||
|
// }
|
||||||
|
|
||||||
|
constructor(totalBet: number) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
// 原本的SingleValue拿掉, 統一使用Data來存送出結構
|
||||||
|
|
||||||
|
// this.Data = 2;
|
||||||
|
this.Data = {
|
||||||
|
pay: totalBet,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.0.8",
|
||||||
|
"uuid": "1af9e6af-3dc3-4d02-8b24-481adc07932a",
|
||||||
|
"isPlugin": false,
|
||||||
|
"loadPluginInWeb": true,
|
||||||
|
"loadPluginInNative": true,
|
||||||
|
"loadPluginInEditor": false,
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
4
src/script/Engine/CatanEngine/NetManagerV2/NetConfig.ts
Normal file
4
src/script/Engine/CatanEngine/NetManagerV2/NetConfig.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export default class NetConfig {
|
||||||
|
/**是否顯示RPC接送JSON的LOG */
|
||||||
|
public static ShowServerLog: boolean = true;
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.0.8",
|
||||||
|
"uuid": "c7f5f6a9-94fd-4f5f-9f0a-545cd14edca9",
|
||||||
|
"isPlugin": false,
|
||||||
|
"loadPluginInWeb": true,
|
||||||
|
"loadPluginInNative": true,
|
||||||
|
"loadPluginInEditor": false,
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
263
src/script/Engine/CatanEngine/NetManagerV2/NetConnector.ts
Normal file
263
src/script/Engine/CatanEngine/NetManagerV2/NetConnector.ts
Normal file
@ -0,0 +1,263 @@
|
|||||||
|
import { Tools } from "../../../Tools";
|
||||||
|
import { BaseEnumerator } from "../CoroutineV2/Core/BaseEnumerator";
|
||||||
|
import { Action } from "../CSharp/System/Action";
|
||||||
|
import { Encoding } from "../CSharp/System/Text/Encoding";
|
||||||
|
import { INetRequest } from "./Core/INetRequest";
|
||||||
|
import { INetResponse } from "./Core/INetResponse";
|
||||||
|
import NetConfig from "./NetConfig";
|
||||||
|
import { NetManager } from "./NetManager";
|
||||||
|
|
||||||
|
export class NetConnector {
|
||||||
|
readonly OnDataReceived: Action<INetResponse<any>> = new Action<INetResponse<any>>();
|
||||||
|
readonly OnDisconnected: Action<void> = new Action<void>();
|
||||||
|
readonly OnLoadUIMask: Action<boolean> = new Action<boolean>();
|
||||||
|
|
||||||
|
get IsConnected() {
|
||||||
|
return this._ws && this._ws.readyState === WebSocket.OPEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _host: string;
|
||||||
|
private _ws: WebSocket = null!;
|
||||||
|
private _waitings: WsRequestEnumerator[] = [];
|
||||||
|
|
||||||
|
constructor(host: string, port: number, ip: string) {
|
||||||
|
let checkHttp: string = "";
|
||||||
|
let index: number = host.indexOf("https://");
|
||||||
|
if (index != -1) {
|
||||||
|
checkHttp = "https";
|
||||||
|
host = host.replace("https://", "");
|
||||||
|
} else {
|
||||||
|
checkHttp = window.location.href.substring(0, 5);
|
||||||
|
host = host.replace("http://", "");
|
||||||
|
}
|
||||||
|
if (true) {
|
||||||
|
console.log("[事件]checkHttp=", checkHttp, host, port);
|
||||||
|
}
|
||||||
|
if (checkHttp != "https") {
|
||||||
|
this._host = `ws://${host}:${port}/?ip=${ip}`;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this._host = `wss://${host}:${port}/?ip=${ip}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async ConnectAsync() {
|
||||||
|
if (this._ws) {
|
||||||
|
throw new Error("請先執行CasinoNetManager.Disconnect()中斷連線");
|
||||||
|
}
|
||||||
|
this._ws = new WebSocket(this._host);
|
||||||
|
|
||||||
|
this._ws.binaryType = 'arraybuffer';
|
||||||
|
this._ws.onopen = this.OnWebSocketOpen.bind(this);
|
||||||
|
this._ws.onmessage = this.OnWebSocketMessage.bind(this);
|
||||||
|
this._ws.onerror = this.OnWebSocketError.bind(this);
|
||||||
|
this._ws.onclose = this.OnWebSocketClose.bind(this);
|
||||||
|
|
||||||
|
while (!NetManager.IsConnected) {
|
||||||
|
await Tools.Sleep(1);
|
||||||
|
}
|
||||||
|
return new WsConnectEnumerator(this._ws);
|
||||||
|
}
|
||||||
|
|
||||||
|
async Send(req: INetRequest<any, any>) {
|
||||||
|
if (!this.IsConnected) return;
|
||||||
|
|
||||||
|
let json = [req.Method];
|
||||||
|
if (req.Data != null && req.Data != undefined && req.Data) {
|
||||||
|
json[1] = req.Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (true && NetConfig.ShowServerLog) {
|
||||||
|
if (req.Data != null && req.Data != undefined && req.Data) {
|
||||||
|
console.log(`[RPC] 傳送server資料: ${req.Method}(${JSON.stringify(req.Data)})`);
|
||||||
|
} else {
|
||||||
|
console.log(`[RPC] 傳送server資料: ${req.Method}()`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let str = JSON.stringify(json);
|
||||||
|
if (str.length > 65535) {
|
||||||
|
throw new Error('要傳的資料太大囉');
|
||||||
|
}
|
||||||
|
|
||||||
|
let strary = Encoding.UTF8.GetBytes(str);
|
||||||
|
let buffer = new Uint8Array(4 + strary.byteLength);
|
||||||
|
let u16ary = new Uint16Array(buffer.buffer, 0, 3);
|
||||||
|
u16ary[0] = strary.byteLength;
|
||||||
|
buffer[3] = 0x01;
|
||||||
|
buffer.set(strary, 4);
|
||||||
|
|
||||||
|
await this._ws.send(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
async SendAsync(req: INetRequest<any, any>, mask: boolean) {
|
||||||
|
let iterator = new WsRequestEnumerator(req);
|
||||||
|
if (!this.IsConnected) {
|
||||||
|
iterator.SetResponse(ErrorResponse);
|
||||||
|
} else {
|
||||||
|
this._waitings.push(iterator);
|
||||||
|
if (mask) {
|
||||||
|
this.OnLoadUIMask.DispatchCallback(true);
|
||||||
|
}
|
||||||
|
this.Send(req);
|
||||||
|
while (!iterator.Done) {
|
||||||
|
await Tools.Sleep(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return iterator;
|
||||||
|
};
|
||||||
|
|
||||||
|
Disconnect() {
|
||||||
|
this.WebSocketEnded();
|
||||||
|
}
|
||||||
|
|
||||||
|
private WebSocketEnded() {
|
||||||
|
if (!this._ws) return;
|
||||||
|
|
||||||
|
this._ws.close();
|
||||||
|
this._ws.onopen = null;
|
||||||
|
this._ws.onmessage = null;
|
||||||
|
this._ws.onclose = () => { };
|
||||||
|
this._ws = null!;
|
||||||
|
|
||||||
|
this.CleanWaitings();
|
||||||
|
this.OnDisconnected.DispatchCallback();
|
||||||
|
}
|
||||||
|
|
||||||
|
private CleanWaitings() {
|
||||||
|
for (let w of this._waitings) {
|
||||||
|
w.SetResponse(ErrorResponse);
|
||||||
|
this.OnLoadUIMask.DispatchCallback(false);
|
||||||
|
}
|
||||||
|
this._waitings.length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private OnWebSocketOpen(e: Event) {
|
||||||
|
if (true) {
|
||||||
|
console.log(`[RPC] ${this._host} Connected.`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private OnWebSocketMessage(e: MessageEvent) {
|
||||||
|
if (e.data instanceof ArrayBuffer) {
|
||||||
|
this.ParseRpcMessage(e.data);
|
||||||
|
} else if (e.data instanceof Blob) {
|
||||||
|
let reader = new FileReader();
|
||||||
|
reader.onload = (e) => { this.ParseRpcMessage(<ArrayBuffer>reader.result); reader.onload = null; }
|
||||||
|
reader.readAsArrayBuffer(e.data);
|
||||||
|
} else {
|
||||||
|
throw new Error(`未知的OnWebSocketMessage(e.data)類型: ${e.data}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ParseRpcMessage(buffer: ArrayBuffer) {
|
||||||
|
let startIndex = 0, byteLength = buffer.byteLength;
|
||||||
|
while (startIndex + 4 < byteLength) {
|
||||||
|
let strlen = new DataView(buffer, startIndex, 3).getUint16(0, true);
|
||||||
|
let str = Encoding.UTF8.GetString(new Uint8Array(buffer, startIndex + 4, strlen));
|
||||||
|
startIndex += strlen + 4;
|
||||||
|
|
||||||
|
try {
|
||||||
|
let json = JSON.parse(str);
|
||||||
|
let method = <string>json[0];
|
||||||
|
let status = <number>json[1][0];
|
||||||
|
let data = json[1][1];
|
||||||
|
|
||||||
|
let resp = <INetResponse<any>>{
|
||||||
|
Method: method,
|
||||||
|
Status: status,
|
||||||
|
Data: data,
|
||||||
|
IsValid: method && status === 0
|
||||||
|
};
|
||||||
|
|
||||||
|
if (true && NetConfig.ShowServerLog) {
|
||||||
|
if (data) {
|
||||||
|
console.log(`[RPC] 收到server呼叫:(${resp.Status}): ${resp.Method}(${JSON.stringify(resp.Data)})`);
|
||||||
|
} else {
|
||||||
|
console.log(`[RPC] 收到server呼叫:(${resp.Status}): ${resp.Method}()`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let dispatch = true;
|
||||||
|
for (let i = 0, len = this._waitings.length; i < len; i++) {
|
||||||
|
let w = this._waitings[i];
|
||||||
|
if (w.MethodBack === resp.Method) {
|
||||||
|
dispatch = false;
|
||||||
|
this._waitings.splice(i, 1);
|
||||||
|
w.SetResponse(resp);
|
||||||
|
this.OnLoadUIMask.DispatchCallback(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dispatch) {
|
||||||
|
this.OnDataReceived.DispatchCallback(resp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
throw new Error(`[RPC] 無法解析Server回應: ${str}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private OnWebSocketError(ev: Event) {
|
||||||
|
throw new Error(`[RPC] 無法解析Server回應: ${ev}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
private OnWebSocketClose(e: CloseEvent) {
|
||||||
|
this.WebSocketEnded();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const ErrorResponse: INetResponse<any> = {
|
||||||
|
Status: -1,
|
||||||
|
Method: "",
|
||||||
|
Data: {},
|
||||||
|
IsValid: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
class WsConnectEnumerator extends BaseEnumerator {
|
||||||
|
private _ws: WebSocket;
|
||||||
|
|
||||||
|
constructor(ws: WebSocket) {
|
||||||
|
super();
|
||||||
|
this._ws = ws;
|
||||||
|
}
|
||||||
|
|
||||||
|
next(value?: any): IteratorResult<any> {
|
||||||
|
return {
|
||||||
|
done: this._ws.readyState === WebSocket.OPEN || this._ws.readyState === WebSocket.CLOSED,
|
||||||
|
value: undefined
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class WsRequestEnumerator extends BaseEnumerator {
|
||||||
|
readonly MethodBack: string;
|
||||||
|
|
||||||
|
private _req: INetRequest<any, any>;
|
||||||
|
private _done: boolean = false;
|
||||||
|
|
||||||
|
public get Done(): boolean { return this._done; }
|
||||||
|
|
||||||
|
constructor(req: INetRequest<any, any>) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this._req = req;
|
||||||
|
this.MethodBack = req.MethodBack;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetResponse(resp: INetResponse<any>) {
|
||||||
|
this._req.Result = resp;
|
||||||
|
this._done = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
next(value?: any): IteratorResult<any> {
|
||||||
|
return {
|
||||||
|
done: this._done,
|
||||||
|
value: undefined
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.0.8",
|
||||||
|
"uuid": "221e1688-cc40-450d-9248-464978540a85",
|
||||||
|
"isPlugin": false,
|
||||||
|
"loadPluginInWeb": true,
|
||||||
|
"loadPluginInNative": true,
|
||||||
|
"loadPluginInEditor": false,
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
49
src/script/Engine/CatanEngine/NetManagerV2/NetManager.ts
Normal file
49
src/script/Engine/CatanEngine/NetManagerV2/NetManager.ts
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
import { INetRequest } from "./Core/INetRequest";
|
||||||
|
import { NetConnector } from "./NetConnector";
|
||||||
|
|
||||||
|
export class NetManager {
|
||||||
|
static get IsConnected() { return this._connector && this._connector.IsConnected; }
|
||||||
|
static get HasInit() { return this._connector != null; }
|
||||||
|
|
||||||
|
private static _connector: NetConnector;
|
||||||
|
|
||||||
|
static Initialize(connector: NetConnector) {
|
||||||
|
this._connector = connector;
|
||||||
|
}
|
||||||
|
|
||||||
|
static async ConnectAsync() {
|
||||||
|
this.CheckConnector();
|
||||||
|
return await this._connector.ConnectAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 斷線
|
||||||
|
*/
|
||||||
|
static Disconnect() {
|
||||||
|
this.CheckConnector();
|
||||||
|
this._connector.Disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 傳送資料給Server, 不等待回應
|
||||||
|
* @param req
|
||||||
|
*/
|
||||||
|
static Send(req: INetRequest<any, any>) {
|
||||||
|
this.CheckConnector();
|
||||||
|
this._connector.Send(req);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 傳送資料給Server, 並等待回應
|
||||||
|
* @param req
|
||||||
|
*/
|
||||||
|
static async SendAsync(req: INetRequest<any, any>, mask: boolean) {
|
||||||
|
this.CheckConnector();
|
||||||
|
return await this._connector.SendAsync(req, mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static CheckConnector() {
|
||||||
|
if (!this._connector) throw new Error("請先呼叫CasinoNetManager.Initialize()初始化connector");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.0.8",
|
||||||
|
"uuid": "7c3e375d-3672-42e7-8a45-dd5ecf9d5fe8",
|
||||||
|
"isPlugin": false,
|
||||||
|
"loadPluginInWeb": true,
|
||||||
|
"loadPluginInNative": true,
|
||||||
|
"loadPluginInEditor": false,
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
21
src/script/Engine/CatanEngine/NetManagerV2/NetRequest.ts
Normal file
21
src/script/Engine/CatanEngine/NetManagerV2/NetRequest.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import { INetRequest } from "./Core/INetRequest";
|
||||||
|
import { NetManager } from "./NetManager";
|
||||||
|
|
||||||
|
export abstract class NetRequest<TResquest, TResponse> implements INetRequest<TResquest, TResponse> {
|
||||||
|
abstract get Method(): string;
|
||||||
|
|
||||||
|
get MethodBack(): string {
|
||||||
|
return this.Method;
|
||||||
|
}
|
||||||
|
|
||||||
|
Data: TResquest;
|
||||||
|
Result: import("./Core/INetResponse").INetResponse<TResponse>;
|
||||||
|
|
||||||
|
async SendAsync(mask: boolean = false): Promise<Iterator<any>> {
|
||||||
|
return await NetManager.SendAsync(this, mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
Send() {
|
||||||
|
NetManager.Send(this);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.0.8",
|
||||||
|
"uuid": "36534597-4273-48e8-bbeb-8dde4857d26f",
|
||||||
|
"isPlugin": false,
|
||||||
|
"loadPluginInWeb": true,
|
||||||
|
"loadPluginInNative": true,
|
||||||
|
"loadPluginInEditor": false,
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
81
src/script/Engine/CatanEngine/NoSleep.ts
Normal file
81
src/script/Engine/CatanEngine/NoSleep.ts
Normal file
File diff suppressed because one or more lines are too long
9
src/script/Engine/CatanEngine/NoSleep.ts.meta
Normal file
9
src/script/Engine/CatanEngine/NoSleep.ts.meta
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.0.8",
|
||||||
|
"uuid": "90f2152c-2c37-4c7c-b3a3-04c8aee53c34",
|
||||||
|
"isPlugin": false,
|
||||||
|
"loadPluginInWeb": true,
|
||||||
|
"loadPluginInNative": true,
|
||||||
|
"loadPluginInEditor": false,
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
12
src/script/Engine/CatanEngine/TableV3.meta
Normal file
12
src/script/Engine/CatanEngine/TableV3.meta
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.1.2",
|
||||||
|
"uuid": "8e05805d-5ab8-4526-8463-f4c837e23534",
|
||||||
|
"isBundle": false,
|
||||||
|
"bundleName": "",
|
||||||
|
"priority": 1,
|
||||||
|
"compressionType": {},
|
||||||
|
"optimizeHotUpdate": {},
|
||||||
|
"inlineSpriteFrames": {},
|
||||||
|
"isRemoteBundle": {},
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
0
src/script/Engine/CatanEngine/公司自架接功能.txt
Normal file
0
src/script/Engine/CatanEngine/公司自架接功能.txt
Normal file
5
src/script/Engine/CatanEngine/公司自架接功能.txt.meta
Normal file
5
src/script/Engine/CatanEngine/公司自架接功能.txt.meta
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"ver": "2.0.0",
|
||||||
|
"uuid": "6ab253ff-8c5d-419f-9f8b-5cf0ef661a28",
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
12
src/script/Engine/Component.meta
Normal file
12
src/script/Engine/Component.meta
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.1.2",
|
||||||
|
"uuid": "c87ad2c2-0bf9-4822-84db-00b939f614ee",
|
||||||
|
"isBundle": false,
|
||||||
|
"bundleName": "",
|
||||||
|
"priority": 1,
|
||||||
|
"compressionType": {},
|
||||||
|
"optimizeHotUpdate": {},
|
||||||
|
"inlineSpriteFrames": {},
|
||||||
|
"isRemoteBundle": {},
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
12
src/script/Engine/Data.meta
Normal file
12
src/script/Engine/Data.meta
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.1.2",
|
||||||
|
"uuid": "89d65072-29d8-4f58-a9d7-5750406209e6",
|
||||||
|
"isBundle": false,
|
||||||
|
"bundleName": "",
|
||||||
|
"priority": 1,
|
||||||
|
"compressionType": {},
|
||||||
|
"optimizeHotUpdate": {},
|
||||||
|
"inlineSpriteFrames": {},
|
||||||
|
"isRemoteBundle": {},
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user