[add] Engine
This commit is contained in:
13
assets/Script/Engine/CatanEngine/NetManagerV2/Core.meta
Normal file
13
assets/Script/Engine/CatanEngine/NetManagerV2/Core.meta
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"ver": "1.1.3",
|
||||
"uuid": "5e6c027f-ce4b-47fa-968c-f3bb6059ad81",
|
||||
"importer": "folder",
|
||||
"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,10 @@
|
||||
{
|
||||
"ver": "1.1.0",
|
||||
"uuid": "f97991b5-0da6-4220-ab29-13c8f8f7e405",
|
||||
"importer": "typescript",
|
||||
"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(): Iterator<any>;
|
||||
Send();
|
||||
}
|
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"ver": "1.1.0",
|
||||
"uuid": "339fcf27-bdb9-4b8f-ae18-dd54c9500145",
|
||||
"importer": "typescript",
|
||||
"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,10 @@
|
||||
{
|
||||
"ver": "1.1.0",
|
||||
"uuid": "c4cb0cd4-b98c-4f8e-b1e6-ac3b51281b28",
|
||||
"importer": "typescript",
|
||||
"isPlugin": false,
|
||||
"loadPluginInWeb": true,
|
||||
"loadPluginInNative": true,
|
||||
"loadPluginInEditor": false,
|
||||
"subMetas": {}
|
||||
}
|
13
assets/Script/Engine/CatanEngine/NetManagerV2/Examples.meta
Normal file
13
assets/Script/Engine/CatanEngine/NetManagerV2/Examples.meta
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"ver": "1.1.3",
|
||||
"uuid": "94e55972-723c-4dab-9ebc-870bd5043fca",
|
||||
"importer": "folder",
|
||||
"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} = cc._decorator;
|
||||
|
||||
@ccclass
|
||||
export default class NetTester extends cc.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);
|
||||
}
|
||||
|
||||
cc.log("連線中...");
|
||||
yield NetManager.ConnectAsync(); // 同個connector要再次連線, 可以不用叫CasinoNetManager.Initialize(), 但要先叫CasinoNetManager.Disconnect()
|
||||
cc.log(`連線狀態: ${NetManager.IsConnected}`);
|
||||
}
|
||||
|
||||
onDisconnectClicked() {
|
||||
cc.log("中斷連線中...");
|
||||
NetManager.Disconnect(); // 中斷連線
|
||||
}
|
||||
|
||||
onSendMessageClicked1() {
|
||||
cc.log("發送訊息(不使用協程)");
|
||||
let req = new Slot1_SpinRequestExample(401);
|
||||
req.Send();
|
||||
// CasinoNetManager.Send(req);
|
||||
}
|
||||
|
||||
onSendMessageClicked2() {
|
||||
CoroutineV2.StartCoroutine(this.SendAsync());
|
||||
}
|
||||
|
||||
*SendAsync() {
|
||||
cc.log("發送訊息中(使用協程)...");
|
||||
let req = new Slot1_SpinRequestExample(399);
|
||||
yield req.SendAsync();
|
||||
// yield CasinoNetManager.SendAsync(req);
|
||||
|
||||
let resp = req.Result;
|
||||
cc.log(`發送協程完畢, Server回應: ${resp.Method}(${JSON.stringify(resp.Data)}), 狀態: ${resp.Status}`);
|
||||
// cc.log(`使用介面資料: ${resp.Data.slot}`);
|
||||
}
|
||||
|
||||
private OnNetDisconnected() {
|
||||
cc.log("[事件] 收到連線中斷事件");
|
||||
}
|
||||
|
||||
private OnNetDataReceived(resp: INetResponse<any>) {
|
||||
cc.log(`[事件] 收到server呼叫: ${resp.Method}(${JSON.stringify(resp.Data)}), 狀態: ${resp.Status}`);
|
||||
}
|
||||
|
||||
private OnLoadUIMask(value: boolean) {
|
||||
cc.log(`[事件] LoadUIMask: ${value}`);
|
||||
}
|
||||
}
|
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"ver": "1.1.0",
|
||||
"uuid": "0cb7df7a-d0e7-4ce1-832e-4583cf3385e5",
|
||||
"importer": "typescript",
|
||||
"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,10 @@
|
||||
{
|
||||
"ver": "1.1.0",
|
||||
"uuid": "1af9e6af-3dc3-4d02-8b24-481adc07932a",
|
||||
"importer": "typescript",
|
||||
"isPlugin": false,
|
||||
"loadPluginInWeb": true,
|
||||
"loadPluginInNative": true,
|
||||
"loadPluginInEditor": false,
|
||||
"subMetas": {}
|
||||
}
|
@@ -0,0 +1,4 @@
|
||||
export default class NetConfig {
|
||||
/**是否顯示RPC接送JSON的LOG */
|
||||
public static ShowServerLog: boolean = true;
|
||||
}
|
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"ver": "1.1.0",
|
||||
"uuid": "c7f5f6a9-94fd-4f5f-9f0a-545cd14edca9",
|
||||
"importer": "typescript",
|
||||
"isPlugin": false,
|
||||
"loadPluginInWeb": true,
|
||||
"loadPluginInNative": true,
|
||||
"loadPluginInEditor": false,
|
||||
"subMetas": {}
|
||||
}
|
259
assets/Script/Engine/CatanEngine/NetManagerV2/NetConnector.ts
Normal file
259
assets/Script/Engine/CatanEngine/NetManagerV2/NetConnector.ts
Normal file
@@ -0,0 +1,259 @@
|
||||
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";
|
||||
|
||||
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;
|
||||
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 (CC_DEBUG) {
|
||||
cc.log("[事件]checkHttp=", checkHttp, host, port);
|
||||
}
|
||||
if (checkHttp != "https") {
|
||||
//this._host = `ws://${host}:${port}/?ip=${ip}`;
|
||||
this._host = `ws://${host}:${port}`
|
||||
}
|
||||
else {
|
||||
//this._host = `wss://${host}:${port}/?ip=${ip}`;
|
||||
this._host = `wss://${host}:${port}`;
|
||||
}
|
||||
}
|
||||
|
||||
ConnectAsync() {
|
||||
if (this._ws) {
|
||||
throw new Error("請先執行CasinoNetManager.Disconnect()中斷連線");
|
||||
}
|
||||
if (cc.sys.isNative && cc.sys.os == cc.sys.OS_ANDROID && this._host.indexOf("wss") !== -1) {
|
||||
let cacert = cc.url.raw('resources/cacert.cer');
|
||||
if (cc.loader.md5Pipe) {
|
||||
cacert = cc.loader.md5Pipe.transformURL(cacert)
|
||||
}
|
||||
//@ts-ignore
|
||||
this._ws = new WebSocket(this._host, null, cacert)
|
||||
} else {
|
||||
//@ts-ignore
|
||||
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.onclose = this.OnWebSocketClose.bind(this);
|
||||
|
||||
return new WsConnectEnumerator(this._ws);
|
||||
}
|
||||
|
||||
Send(req: INetRequest<any, any>) {
|
||||
if (!this.IsConnected) return;
|
||||
|
||||
let json = [req.Method];
|
||||
if (req.Data != null && req.Data != undefined && req.Data != NaN) {
|
||||
json[1] = req.Data;
|
||||
}
|
||||
|
||||
if (CC_DEBUG && NetConfig.ShowServerLog) {
|
||||
if (req.Data != null && req.Data != undefined && req.Data != NaN) {
|
||||
cc.log(`[RPC] 傳送server資料: ${req.Method}(${JSON.stringify(req.Data)})`);
|
||||
} else {
|
||||
cc.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);
|
||||
|
||||
this._ws.send(buffer);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
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 (CC_DEBUG) {
|
||||
cc.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 (CC_DEBUG && NetConfig.ShowServerLog) {
|
||||
if (data) {
|
||||
cc.log(`[RPC] 收到server呼叫:(${resp.Status}): ${resp.Method}(${JSON.stringify(resp.Data)})`);
|
||||
} else {
|
||||
cc.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 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;
|
||||
|
||||
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,10 @@
|
||||
{
|
||||
"ver": "1.1.0",
|
||||
"uuid": "221e1688-cc40-450d-9248-464978540a85",
|
||||
"importer": "typescript",
|
||||
"isPlugin": false,
|
||||
"loadPluginInWeb": true,
|
||||
"loadPluginInNative": true,
|
||||
"loadPluginInEditor": false,
|
||||
"subMetas": {}
|
||||
}
|
50
assets/Script/Engine/CatanEngine/NetManagerV2/NetManager.ts
Normal file
50
assets/Script/Engine/CatanEngine/NetManagerV2/NetManager.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
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 ConnectAsync() {
|
||||
this.CheckConnector();
|
||||
return 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 SendAsync(req: INetRequest<any, any>,mask:boolean) {
|
||||
this.CheckConnector();
|
||||
return this._connector.SendAsync(req,mask);
|
||||
}
|
||||
|
||||
private static CheckConnector()
|
||||
{
|
||||
if (!this._connector) throw new Error("請先呼叫CasinoNetManager.Initialize()初始化connector");
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"ver": "1.1.0",
|
||||
"uuid": "7c3e375d-3672-42e7-8a45-dd5ecf9d5fe8",
|
||||
"importer": "typescript",
|
||||
"isPlugin": false,
|
||||
"loadPluginInWeb": true,
|
||||
"loadPluginInNative": true,
|
||||
"loadPluginInEditor": false,
|
||||
"subMetas": {}
|
||||
}
|
21
assets/Script/Engine/CatanEngine/NetManagerV2/NetRequest.ts
Normal file
21
assets/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>;
|
||||
|
||||
SendAsync(mask: boolean = false): Iterator<any> {
|
||||
return NetManager.SendAsync(this, mask);
|
||||
}
|
||||
|
||||
Send() {
|
||||
NetManager.Send(this);
|
||||
}
|
||||
}
|
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"ver": "1.1.0",
|
||||
"uuid": "36534597-4273-48e8-bbeb-8dde4857d26f",
|
||||
"importer": "typescript",
|
||||
"isPlugin": false,
|
||||
"loadPluginInWeb": true,
|
||||
"loadPluginInNative": true,
|
||||
"loadPluginInEditor": false,
|
||||
"subMetas": {}
|
||||
}
|
Reference in New Issue
Block a user