Compare commits
21 Commits
Author | SHA1 | Date | |
---|---|---|---|
5fb9bad702 | |||
3846fa7844 | |||
5dce041429 | |||
1027cc8376 | |||
c2cb85afe4 | |||
2bde4ac72e | |||
fd5f31fd66 | |||
cf6f6f393c | |||
2b53c707c6 | |||
2977ed2341 | |||
05e2ad3d0e | |||
b5d17697c3 | |||
4a2abf55f6 | |||
1606c28b5c | |||
ecad6d01e3 | |||
cfe31371af | |||
b4571e07aa | |||
c0ea0d936b | |||
370f0e99db | |||
e5b166415f | |||
f4b2afb9f5 |
6
.gitignore
vendored
6
.gitignore
vendored
@ -46,6 +46,12 @@ Thumbs.db
|
|||||||
|
|
||||||
.idea/
|
.idea/
|
||||||
|
|
||||||
|
#//////////////////////////
|
||||||
|
# HotUpdate
|
||||||
|
#//////////////////////////
|
||||||
|
|
||||||
|
remote-assets/
|
||||||
|
|
||||||
#//////////////////////////
|
#//////////////////////////
|
||||||
# VS Code files
|
# VS Code files
|
||||||
#//////////////////////////
|
#//////////////////////////
|
||||||
|
BIN
JMKA - 捷徑.lnk
Normal file
BIN
JMKA - 捷徑.lnk
Normal file
Binary file not shown.
13
assets/Prefab.meta
Normal file
13
assets/Prefab.meta
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.1.3",
|
||||||
|
"uuid": "a0181a7b-9c3d-4126-a012-acf5a1e095a2",
|
||||||
|
"importer": "folder",
|
||||||
|
"isBundle": false,
|
||||||
|
"bundleName": "",
|
||||||
|
"priority": 1,
|
||||||
|
"compressionType": {},
|
||||||
|
"optimizeHotUpdate": {},
|
||||||
|
"inlineSpriteFrames": {},
|
||||||
|
"isRemoteBundle": {},
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
3027
assets/Prefab/UpdatePanel.prefab
Normal file
3027
assets/Prefab/UpdatePanel.prefab
Normal file
File diff suppressed because it is too large
Load Diff
9
assets/Prefab/UpdatePanel.prefab.meta
Normal file
9
assets/Prefab/UpdatePanel.prefab.meta
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.3.2",
|
||||||
|
"uuid": "9d9ca13a-071d-47f4-836c-a69d1045dc14",
|
||||||
|
"importer": "prefab",
|
||||||
|
"optimizationPolicy": "AUTO",
|
||||||
|
"asyncLoadAssets": false,
|
||||||
|
"readonly": false,
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
@ -1,125 +1,125 @@
|
|||||||
/**
|
/**
|
||||||
* 回呼函數: fnname (arg: TArg): void
|
* 回呼函數: fnname (arg: TArg): void
|
||||||
*/
|
*/
|
||||||
interface ActionCallback<TArg> {
|
interface ActionCallback<TArg> {
|
||||||
(arg: TArg): void;
|
(arg: TArg): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Struct<TArg> {
|
interface Struct<TArg> {
|
||||||
callback: ActionCallback<TArg>;
|
callback: ActionCallback<TArg>;
|
||||||
target: any;
|
target: any;
|
||||||
once?: boolean;
|
once?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Action<TArg> {
|
export class Action<TArg> {
|
||||||
private _queue: Struct<TArg>[] = [];
|
private _queue: Struct<TArg>[] = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 監聽事件
|
* 監聽事件
|
||||||
* @param callback 回呼函數: fnname (arg: TArg): void
|
* @param callback 回呼函數: fnname (arg: TArg): void
|
||||||
* @param bindTarget 回呼時this綁定的對象
|
* @param bindTarget 回呼時this綁定的對象
|
||||||
*/
|
*/
|
||||||
AddCallback(callback: ActionCallback<TArg>, bindTarget?: any) {
|
AddCallback(callback: ActionCallback<TArg>, bindTarget?: any) {
|
||||||
let q = <Struct<TArg>> {
|
let q = <Struct<TArg>> {
|
||||||
callback: callback,
|
callback: callback,
|
||||||
target: bindTarget
|
target: bindTarget
|
||||||
};
|
};
|
||||||
this._queue.push(q);
|
this._queue.push(q);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 監聽事件 (一次性)
|
* 監聽事件 (一次性)
|
||||||
* @param callback 回呼函數: fnname (arg: TArg): void
|
* @param callback 回呼函數: fnname (arg: TArg): void
|
||||||
* @param bindTarget 回呼時this綁定的對象
|
* @param bindTarget 回呼時this綁定的對象
|
||||||
*/
|
*/
|
||||||
AddCallbackOnce(callback: ActionCallback<TArg>, bindTarget?: any) {
|
AddCallbackOnce(callback: ActionCallback<TArg>, bindTarget?: any) {
|
||||||
let q = <Struct<TArg>> {
|
let q = <Struct<TArg>> {
|
||||||
callback: callback,
|
callback: callback,
|
||||||
target: bindTarget,
|
target: bindTarget,
|
||||||
once: true
|
once: true
|
||||||
};
|
};
|
||||||
this._queue.push(q);
|
this._queue.push(q);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 移除事件
|
* 移除事件
|
||||||
* @param callback
|
* @param callback
|
||||||
*/
|
*/
|
||||||
RemoveByCallback(callback: ActionCallback<TArg>) {
|
RemoveByCallback(callback: ActionCallback<TArg>) {
|
||||||
let index = this._queue.length;
|
let index = this._queue.length;
|
||||||
if (index > 0) {
|
if (index > 0) {
|
||||||
while (index--) {
|
while (index--) {
|
||||||
let q = this._queue[index];
|
let q = this._queue[index];
|
||||||
if (!q.callback || q.callback === callback) {
|
if (!q.callback || q.callback === callback) {
|
||||||
q.callback = undefined;
|
q.callback = undefined;
|
||||||
this._queue.splice(index, 1);
|
this._queue.splice(index, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 移除事件
|
* 移除事件
|
||||||
* @param bindTarget 回呼時this綁定的對象
|
* @param bindTarget 回呼時this綁定的對象
|
||||||
*/
|
*/
|
||||||
RemoveByBindTarget(bindTarget: any) {
|
RemoveByBindTarget(bindTarget: any) {
|
||||||
let index = this._queue.length;
|
let index = this._queue.length;
|
||||||
if (index > 0) {
|
if (index > 0) {
|
||||||
while (index--) {
|
while (index--) {
|
||||||
let q = this._queue[index];
|
let q = this._queue[index];
|
||||||
if (!q.callback || q.target === bindTarget) {
|
if (!q.callback || q.target === bindTarget) {
|
||||||
q.callback = undefined;
|
q.callback = undefined;
|
||||||
this._queue.splice(index, 1);
|
this._queue.splice(index, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 移除全部事件
|
* 移除全部事件
|
||||||
*/
|
*/
|
||||||
RemoveAllCallbacks() {
|
RemoveAllCallbacks() {
|
||||||
this._queue.forEach(q => q.callback = undefined);
|
this._queue.forEach(q => q.callback = undefined);
|
||||||
this._queue.length = 0;
|
this._queue.length = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 發送事件
|
* 發送事件
|
||||||
* @param arg 參數
|
* @param arg 參數
|
||||||
*/
|
*/
|
||||||
DispatchCallback(arg: TArg) {
|
DispatchCallback(arg: TArg) {
|
||||||
let index = this._queue.length;
|
let index = this._queue.length;
|
||||||
if (index > 0) {
|
if (index > 0) {
|
||||||
let cleanRemoved = false;
|
let cleanRemoved = false;
|
||||||
this._queue.slice().forEach(q => {
|
this._queue.slice().forEach(q => {
|
||||||
if (!q.callback) {
|
if (!q.callback) {
|
||||||
cleanRemoved = true;
|
cleanRemoved = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (q.target) {
|
if (q.target) {
|
||||||
q.callback.call(q.target, arg);
|
q.callback.call(q.target, arg);
|
||||||
} else {
|
} else {
|
||||||
q.callback(arg);
|
q.callback(arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (q.once) {
|
if (q.once) {
|
||||||
q.callback = undefined;
|
q.callback = undefined;
|
||||||
cleanRemoved = true;
|
cleanRemoved = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (cleanRemoved) {
|
if (cleanRemoved) {
|
||||||
index = this._queue.length;
|
index = this._queue.length;
|
||||||
if (index > 0) {
|
if (index > 0) {
|
||||||
while (index--) {
|
while (index--) {
|
||||||
let q = this._queue[index];
|
let q = this._queue[index];
|
||||||
if (!q.callback) {
|
if (!q.callback) {
|
||||||
this._queue.splice(index, 1);
|
this._queue.splice(index, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,85 +1,85 @@
|
|||||||
import { Action } from "./Action";
|
import { Action } from "./Action";
|
||||||
import { ActionWithType } from "./ActionWithType";
|
import { ActionWithType } from "./ActionWithType";
|
||||||
import { ActionWithType2 } from "./ActionWithType2";
|
import { ActionWithType2 } from "./ActionWithType2";
|
||||||
|
|
||||||
const {ccclass, property} = cc._decorator;
|
const {ccclass, property} = cc._decorator;
|
||||||
|
|
||||||
enum CustomType {
|
enum CustomType {
|
||||||
Ex1, Ex2
|
Ex1, Ex2
|
||||||
}
|
}
|
||||||
|
|
||||||
class CustomEvent extends ActionWithType<CustomType, number> {}
|
class CustomEvent extends ActionWithType<CustomType, number> {}
|
||||||
class CustomEvent2 extends ActionWithType2<CustomType, number> {}
|
class CustomEvent2 extends ActionWithType2<CustomType, number> {}
|
||||||
|
|
||||||
@ccclass
|
@ccclass
|
||||||
export default class NewClass extends cc.Component {
|
export default class NewClass extends cc.Component {
|
||||||
callback: Action<number> = new Action<number>();
|
callback: Action<number> = new Action<number>();
|
||||||
customCallback: CustomEvent = new CustomEvent();
|
customCallback: CustomEvent = new CustomEvent();
|
||||||
customCallback2: CustomEvent2 = new CustomEvent2();
|
customCallback2: CustomEvent2 = new CustomEvent2();
|
||||||
|
|
||||||
private num: number = 0;
|
private num: number = 0;
|
||||||
|
|
||||||
start () {
|
start () {
|
||||||
this.callback.AddCallback(this.CB, this);
|
this.callback.AddCallback(this.CB, this);
|
||||||
this.callback.AddCallbackOnce(this.OnceCB, this);
|
this.callback.AddCallbackOnce(this.OnceCB, this);
|
||||||
|
|
||||||
this.customCallback.AddCallback(CustomType.Ex1, this.CBType, this);
|
this.customCallback.AddCallback(CustomType.Ex1, this.CBType, this);
|
||||||
this.customCallback.AddCallbackOnce(CustomType.Ex2, this.OnceCBType, this);
|
this.customCallback.AddCallbackOnce(CustomType.Ex2, this.OnceCBType, this);
|
||||||
|
|
||||||
this.customCallback2.AddCallback(CustomType.Ex2, this.CBTypeAllin1, this);
|
this.customCallback2.AddCallback(CustomType.Ex2, this.CBTypeAllin1, this);
|
||||||
this.customCallback2.AddCallbackOnce(CustomType.Ex1, this.CBTypeAllin1, this);
|
this.customCallback2.AddCallbackOnce(CustomType.Ex1, this.CBTypeAllin1, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
DispatchClick() {
|
DispatchClick() {
|
||||||
this.num++;
|
this.num++;
|
||||||
|
|
||||||
this.callback.DispatchCallback(this.num);
|
this.callback.DispatchCallback(this.num);
|
||||||
|
|
||||||
this.customCallback.DispatchCallback(CustomType.Ex1, this.num);
|
this.customCallback.DispatchCallback(CustomType.Ex1, this.num);
|
||||||
this.customCallback.DispatchCallback(CustomType.Ex2, this.num);
|
this.customCallback.DispatchCallback(CustomType.Ex2, this.num);
|
||||||
|
|
||||||
this.customCallback2.DispatchCallback(CustomType.Ex1, this.num);
|
this.customCallback2.DispatchCallback(CustomType.Ex1, this.num);
|
||||||
this.customCallback2.DispatchCallback(CustomType.Ex2, this.num);
|
this.customCallback2.DispatchCallback(CustomType.Ex2, this.num);
|
||||||
}
|
}
|
||||||
|
|
||||||
RemoveEventClick() {
|
RemoveEventClick() {
|
||||||
this.callback.RemoveByCallback(this.CB);
|
this.callback.RemoveByCallback(this.CB);
|
||||||
// this.callback.RemoveByCallback(this.OnceCB);
|
// this.callback.RemoveByCallback(this.OnceCB);
|
||||||
// this.callback.RemoveByBindTarget(this);
|
// this.callback.RemoveByBindTarget(this);
|
||||||
// this.callback.RemoveAll();
|
// this.callback.RemoveAll();
|
||||||
|
|
||||||
// this.callbackWithType.RemoveByCallback(this.CBType);
|
// this.callbackWithType.RemoveByCallback(this.CBType);
|
||||||
// this.callbackWithType.RemoveByCallback(this.OnceCBType);
|
// this.callbackWithType.RemoveByCallback(this.OnceCBType);
|
||||||
this.customCallback.RemoveByType(CustomType.Ex1);
|
this.customCallback.RemoveByType(CustomType.Ex1);
|
||||||
// this.callbackWithType.RemoveByType(CustomType.Ex2);
|
// this.callbackWithType.RemoveByType(CustomType.Ex2);
|
||||||
// this.callbackWithType.RemoveByBindTarget(this);
|
// this.callbackWithType.RemoveByBindTarget(this);
|
||||||
// this.callbackWithType.RemoveAll();
|
// this.callbackWithType.RemoveAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
OnceCB(x: number) {
|
OnceCB(x: number) {
|
||||||
cc.log(`OnceCB [${this.num}]`);
|
cc.log(`OnceCB [${this.num}]`);
|
||||||
}
|
}
|
||||||
|
|
||||||
CB(x: number) {
|
CB(x: number) {
|
||||||
cc.log(`CB [${this.num}]`);
|
cc.log(`CB [${this.num}]`);
|
||||||
}
|
}
|
||||||
|
|
||||||
OnceCBType(x: number) {
|
OnceCBType(x: number) {
|
||||||
cc.log(`OnceCBType [${this.num}]`);
|
cc.log(`OnceCBType [${this.num}]`);
|
||||||
}
|
}
|
||||||
|
|
||||||
CBType(x: number) {
|
CBType(x: number) {
|
||||||
cc.log(`CBType [${this.num}]`);
|
cc.log(`CBType [${this.num}]`);
|
||||||
}
|
}
|
||||||
|
|
||||||
CBTypeAllin1(type: CustomType,x: number) {
|
CBTypeAllin1(type: CustomType,x: number) {
|
||||||
// switch (type) {
|
// switch (type) {
|
||||||
// case CustomType.Ex1:
|
// case CustomType.Ex1:
|
||||||
// break;
|
// break;
|
||||||
// case CustomType.Ex2:
|
// case CustomType.Ex2:
|
||||||
// break;
|
// break;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
cc.log(`CBTypeAllin1 [${CustomType[type]}][${this.num}]`);
|
cc.log(`CBTypeAllin1 [${CustomType[type]}][${this.num}]`);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,166 +1,166 @@
|
|||||||
/**
|
/**
|
||||||
* 回呼函數: fnname (arg: TArg): void
|
* 回呼函數: fnname (arg: TArg): void
|
||||||
*/
|
*/
|
||||||
interface ActionCallback<TArg> {
|
interface ActionCallback<TArg> {
|
||||||
(arg: TArg): void;
|
(arg: TArg): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Struct<TType, TArg> {
|
interface Struct<TType, TArg> {
|
||||||
callback: ActionCallback<TArg>;
|
callback: ActionCallback<TArg>;
|
||||||
target: any;
|
target: any;
|
||||||
type: TType;
|
type: TType;
|
||||||
once?: boolean;
|
once?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ActionWithType<TType, TArg> {
|
export class ActionWithType<TType, TArg> {
|
||||||
private _queue: Struct<TType, TArg>[] = [];
|
private _queue: Struct<TType, TArg>[] = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 監聽事件
|
* 監聽事件
|
||||||
* @param callback 回呼函數: fnname (arg: TArg): void
|
* @param callback 回呼函數: fnname (arg: TArg): void
|
||||||
* @param bindTarget 回呼時this綁定的對象
|
* @param bindTarget 回呼時this綁定的對象
|
||||||
*/
|
*/
|
||||||
AddCallback(type: TType, callback: ActionCallback<TArg>, bindTarget?: any) {
|
AddCallback(type: TType, callback: ActionCallback<TArg>, bindTarget?: any) {
|
||||||
let q = <Struct<TType, TArg>> {
|
let q = <Struct<TType, TArg>> {
|
||||||
callback: callback,
|
callback: callback,
|
||||||
target: bindTarget,
|
target: bindTarget,
|
||||||
type: type
|
type: type
|
||||||
};
|
};
|
||||||
this._queue.push(q);
|
this._queue.push(q);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 監聽事件 (一次性)
|
* 監聽事件 (一次性)
|
||||||
* @param callback 回呼函數: fnname (arg: TArg): void
|
* @param callback 回呼函數: fnname (arg: TArg): void
|
||||||
* @param bindTarget 回呼時this綁定的對象
|
* @param bindTarget 回呼時this綁定的對象
|
||||||
*/
|
*/
|
||||||
AddCallbackOnce(type: TType, callback: ActionCallback<TArg>, bindTarget?: any) {
|
AddCallbackOnce(type: TType, callback: ActionCallback<TArg>, bindTarget?: any) {
|
||||||
let q = <Struct<TType, TArg>> {
|
let q = <Struct<TType, TArg>> {
|
||||||
callback: callback,
|
callback: callback,
|
||||||
target: bindTarget,
|
target: bindTarget,
|
||||||
type: type,
|
type: type,
|
||||||
once: true
|
once: true
|
||||||
};
|
};
|
||||||
this._queue.push(q);
|
this._queue.push(q);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 移除事件
|
* 移除事件
|
||||||
* @param callback
|
* @param callback
|
||||||
*/
|
*/
|
||||||
RemoveByCallback(callback: ActionCallback<TArg>) {
|
RemoveByCallback(callback: ActionCallback<TArg>) {
|
||||||
let index = this._queue.length;
|
let index = this._queue.length;
|
||||||
if (index > 0) {
|
if (index > 0) {
|
||||||
while (index--) {
|
while (index--) {
|
||||||
let q = this._queue[index];
|
let q = this._queue[index];
|
||||||
if (!q.callback || q.callback === callback) {
|
if (!q.callback || q.callback === callback) {
|
||||||
q.callback = undefined;
|
q.callback = undefined;
|
||||||
this._queue.splice(index, 1);
|
this._queue.splice(index, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 移除事件
|
* 移除事件
|
||||||
* @param bindTarget 回呼時this綁定的對象
|
* @param bindTarget 回呼時this綁定的對象
|
||||||
*/
|
*/
|
||||||
RemoveByBindTarget(bindTarget: any) {
|
RemoveByBindTarget(bindTarget: any) {
|
||||||
let index = this._queue.length;
|
let index = this._queue.length;
|
||||||
if (index > 0) {
|
if (index > 0) {
|
||||||
while (index--) {
|
while (index--) {
|
||||||
let q = this._queue[index];
|
let q = this._queue[index];
|
||||||
if (!q.callback || q.target === bindTarget) {
|
if (!q.callback || q.target === bindTarget) {
|
||||||
q.callback = undefined;
|
q.callback = undefined;
|
||||||
this._queue.splice(index, 1);
|
this._queue.splice(index, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 移除事件
|
* 移除事件
|
||||||
* @param type 事件類型
|
* @param type 事件類型
|
||||||
*/
|
*/
|
||||||
RemoveByType(type: TType) {
|
RemoveByType(type: TType) {
|
||||||
let index = this._queue.length;
|
let index = this._queue.length;
|
||||||
if (index > 0) {
|
if (index > 0) {
|
||||||
while (index--) {
|
while (index--) {
|
||||||
let q = this._queue[index];
|
let q = this._queue[index];
|
||||||
if (!q.callback || q.type === type) {
|
if (!q.callback || q.type === type) {
|
||||||
q.callback = undefined;
|
q.callback = undefined;
|
||||||
this._queue.splice(index, 1);
|
this._queue.splice(index, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 移除事件
|
* 移除事件
|
||||||
* @param type 事件類型
|
* @param type 事件類型
|
||||||
* @param callback
|
* @param callback
|
||||||
*/
|
*/
|
||||||
RemoveCallback(type:TType, callback: ActionCallback<TArg>) {
|
RemoveCallback(type:TType, callback: ActionCallback<TArg>) {
|
||||||
let index = this._queue.length;
|
let index = this._queue.length;
|
||||||
if (index > 0) {
|
if (index > 0) {
|
||||||
while (index--) {
|
while (index--) {
|
||||||
let q = this._queue[index];
|
let q = this._queue[index];
|
||||||
if (!q.callback || (q.type === type && q.callback === callback)) {
|
if (!q.callback || (q.type === type && q.callback === callback)) {
|
||||||
q.callback = undefined;
|
q.callback = undefined;
|
||||||
this._queue.splice(index, 1);
|
this._queue.splice(index, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 移除全部事件
|
* 移除全部事件
|
||||||
*/
|
*/
|
||||||
RemoveAllCallbacks() {
|
RemoveAllCallbacks() {
|
||||||
this._queue.forEach(q => q.callback = undefined);
|
this._queue.forEach(q => q.callback = undefined);
|
||||||
this._queue.length = 0;
|
this._queue.length = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 發送事件
|
* 發送事件
|
||||||
* @param type 事件類型
|
* @param type 事件類型
|
||||||
* @param arg 參數
|
* @param arg 參數
|
||||||
*/
|
*/
|
||||||
DispatchCallback(type: TType, arg: TArg) {
|
DispatchCallback(type: TType, arg: TArg) {
|
||||||
let index = this._queue.length;
|
let index = this._queue.length;
|
||||||
if (index > 0) {
|
if (index > 0) {
|
||||||
let cleanRemoved = false;
|
let cleanRemoved = false;
|
||||||
this._queue.slice().forEach(q => {
|
this._queue.slice().forEach(q => {
|
||||||
if (!q.callback)
|
if (!q.callback)
|
||||||
{
|
{
|
||||||
cleanRemoved = true;
|
cleanRemoved = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (q.type !== type) return;
|
if (q.type !== type) return;
|
||||||
|
|
||||||
if (q.target) {
|
if (q.target) {
|
||||||
q.callback.call(q.target, arg);
|
q.callback.call(q.target, arg);
|
||||||
} else {
|
} else {
|
||||||
q.callback(arg);
|
q.callback(arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (q.once) {
|
if (q.once) {
|
||||||
q.callback = undefined;
|
q.callback = undefined;
|
||||||
cleanRemoved = true;
|
cleanRemoved = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (cleanRemoved) {
|
if (cleanRemoved) {
|
||||||
index = this._queue.length;
|
index = this._queue.length;
|
||||||
if (index > 0) {
|
if (index > 0) {
|
||||||
while (index--) {
|
while (index--) {
|
||||||
let q = this._queue[index];
|
let q = this._queue[index];
|
||||||
if (!q.callback) {
|
if (!q.callback) {
|
||||||
this._queue.splice(index, 1);
|
this._queue.splice(index, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,166 +1,166 @@
|
|||||||
/**
|
/**
|
||||||
* 回呼函數: fnname (type: TType, arg: TArg): void
|
* 回呼函數: fnname (type: TType, arg: TArg): void
|
||||||
*/
|
*/
|
||||||
interface ActionCallback<TType, TArg> {
|
interface ActionCallback<TType, TArg> {
|
||||||
(type: TType, arg: TArg): void;
|
(type: TType, arg: TArg): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Struct<TType, TArg> {
|
interface Struct<TType, TArg> {
|
||||||
callback: ActionCallback<TType, TArg>;
|
callback: ActionCallback<TType, TArg>;
|
||||||
target: any;
|
target: any;
|
||||||
type: TType;
|
type: TType;
|
||||||
once?: boolean;
|
once?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ActionWithType2<TType, TArg> {
|
export class ActionWithType2<TType, TArg> {
|
||||||
private _queue: Struct<TType, TArg>[] = [];
|
private _queue: Struct<TType, TArg>[] = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 監聽事件
|
* 監聽事件
|
||||||
* @param callback 回呼函數: fnname (type: TType, arg: TArg): void
|
* @param callback 回呼函數: fnname (type: TType, arg: TArg): void
|
||||||
* @param bindTarget 回呼時this綁定的對象
|
* @param bindTarget 回呼時this綁定的對象
|
||||||
*/
|
*/
|
||||||
AddCallback(type: TType, callback: ActionCallback<TType, TArg>, bindTarget?: any) {
|
AddCallback(type: TType, callback: ActionCallback<TType, TArg>, bindTarget?: any) {
|
||||||
let q = <Struct<TType, TArg>> {
|
let q = <Struct<TType, TArg>> {
|
||||||
callback: callback,
|
callback: callback,
|
||||||
target: bindTarget,
|
target: bindTarget,
|
||||||
type: type
|
type: type
|
||||||
};
|
};
|
||||||
this._queue.push(q);
|
this._queue.push(q);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 監聽事件 (一次性)
|
* 監聽事件 (一次性)
|
||||||
* @param callback 回呼函數: fnname (type: TType, arg: TArg): void
|
* @param callback 回呼函數: fnname (type: TType, arg: TArg): void
|
||||||
* @param bindTarget 回呼時this綁定的對象
|
* @param bindTarget 回呼時this綁定的對象
|
||||||
*/
|
*/
|
||||||
AddCallbackOnce(type: TType, callback: ActionCallback<TType, TArg>, bindTarget?: any) {
|
AddCallbackOnce(type: TType, callback: ActionCallback<TType, TArg>, bindTarget?: any) {
|
||||||
let q = <Struct<TType, TArg>> {
|
let q = <Struct<TType, TArg>> {
|
||||||
callback: callback,
|
callback: callback,
|
||||||
target: bindTarget,
|
target: bindTarget,
|
||||||
type: type,
|
type: type,
|
||||||
once: true
|
once: true
|
||||||
};
|
};
|
||||||
this._queue.push(q);
|
this._queue.push(q);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 移除事件
|
* 移除事件
|
||||||
* @param callback
|
* @param callback
|
||||||
*/
|
*/
|
||||||
RemoveByCallback(callback: ActionCallback<TType, TArg>) {
|
RemoveByCallback(callback: ActionCallback<TType, TArg>) {
|
||||||
let index = this._queue.length;
|
let index = this._queue.length;
|
||||||
if (index > 0) {
|
if (index > 0) {
|
||||||
while (index--) {
|
while (index--) {
|
||||||
let q = this._queue[index];
|
let q = this._queue[index];
|
||||||
if (!q.callback || q.callback === callback) {
|
if (!q.callback || q.callback === callback) {
|
||||||
q.callback = undefined;
|
q.callback = undefined;
|
||||||
this._queue.splice(index, 1);
|
this._queue.splice(index, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 移除事件
|
* 移除事件
|
||||||
* @param bindTarget 回呼時this綁定的對象
|
* @param bindTarget 回呼時this綁定的對象
|
||||||
*/
|
*/
|
||||||
RemoveByBindTarget(bindTarget: any) {
|
RemoveByBindTarget(bindTarget: any) {
|
||||||
let index = this._queue.length;
|
let index = this._queue.length;
|
||||||
if (index > 0) {
|
if (index > 0) {
|
||||||
while (index--) {
|
while (index--) {
|
||||||
let q = this._queue[index];
|
let q = this._queue[index];
|
||||||
if (!q.callback || q.target === bindTarget) {
|
if (!q.callback || q.target === bindTarget) {
|
||||||
q.callback = undefined;
|
q.callback = undefined;
|
||||||
this._queue.splice(index, 1);
|
this._queue.splice(index, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 移除事件
|
* 移除事件
|
||||||
* @param type 事件類型
|
* @param type 事件類型
|
||||||
*/
|
*/
|
||||||
RemoveByType(type: TType) {
|
RemoveByType(type: TType) {
|
||||||
let index = this._queue.length;
|
let index = this._queue.length;
|
||||||
if (index > 0) {
|
if (index > 0) {
|
||||||
while (index--) {
|
while (index--) {
|
||||||
let q = this._queue[index];
|
let q = this._queue[index];
|
||||||
if (!q.callback || q.type === type) {
|
if (!q.callback || q.type === type) {
|
||||||
q.callback = undefined;
|
q.callback = undefined;
|
||||||
this._queue.splice(index, 1);
|
this._queue.splice(index, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 移除事件
|
* 移除事件
|
||||||
* @param type 事件類型
|
* @param type 事件類型
|
||||||
* @param callback
|
* @param callback
|
||||||
*/
|
*/
|
||||||
RemoveCallback(type:TType, callback: ActionCallback<TType, TArg>) {
|
RemoveCallback(type:TType, callback: ActionCallback<TType, TArg>) {
|
||||||
let index = this._queue.length;
|
let index = this._queue.length;
|
||||||
if (index > 0) {
|
if (index > 0) {
|
||||||
while (index--) {
|
while (index--) {
|
||||||
let q = this._queue[index];
|
let q = this._queue[index];
|
||||||
if (!q.callback || (q.type === type && q.callback === callback)) {
|
if (!q.callback || (q.type === type && q.callback === callback)) {
|
||||||
q.callback = undefined;
|
q.callback = undefined;
|
||||||
this._queue.splice(index, 1);
|
this._queue.splice(index, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 移除全部事件
|
* 移除全部事件
|
||||||
*/
|
*/
|
||||||
RemoveAllCallbacks() {
|
RemoveAllCallbacks() {
|
||||||
this._queue.forEach(q => q.callback = undefined);
|
this._queue.forEach(q => q.callback = undefined);
|
||||||
this._queue.length = 0;
|
this._queue.length = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 發送事件
|
* 發送事件
|
||||||
* @param type 事件類型
|
* @param type 事件類型
|
||||||
* @param arg 參數
|
* @param arg 參數
|
||||||
*/
|
*/
|
||||||
DispatchCallback(type: TType, arg: TArg) {
|
DispatchCallback(type: TType, arg: TArg) {
|
||||||
let index = this._queue.length;
|
let index = this._queue.length;
|
||||||
if (index > 0) {
|
if (index > 0) {
|
||||||
let cleanRemoved = false;
|
let cleanRemoved = false;
|
||||||
this._queue.slice().forEach(q => {
|
this._queue.slice().forEach(q => {
|
||||||
if (!q.callback)
|
if (!q.callback)
|
||||||
{
|
{
|
||||||
cleanRemoved = true;
|
cleanRemoved = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (q.type !== type) return;
|
if (q.type !== type) return;
|
||||||
|
|
||||||
if (q.target) {
|
if (q.target) {
|
||||||
q.callback.call(q.target, type, arg);
|
q.callback.call(q.target, type, arg);
|
||||||
} else {
|
} else {
|
||||||
q.callback(type, arg);
|
q.callback(type, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (q.once) {
|
if (q.once) {
|
||||||
q.callback = undefined;
|
q.callback = undefined;
|
||||||
cleanRemoved = true;
|
cleanRemoved = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (cleanRemoved) {
|
if (cleanRemoved) {
|
||||||
index = this._queue.length;
|
index = this._queue.length;
|
||||||
if (index > 0) {
|
if (index > 0) {
|
||||||
while (index--) {
|
while (index--) {
|
||||||
let q = this._queue[index];
|
let q = this._queue[index];
|
||||||
if (!q.callback) {
|
if (!q.callback) {
|
||||||
this._queue.splice(index, 1);
|
this._queue.splice(index, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
|
||||||
|
/** System類型 */
|
||||||
|
export enum System_Eevent {
|
||||||
|
/** SetFCMToken */
|
||||||
|
SetFCMToken,
|
||||||
|
|
||||||
|
/** Test */
|
||||||
|
Test
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"ver": "1.1.0",
|
"ver": "1.1.0",
|
||||||
"uuid": "573d847e-893c-4fa2-8bd2-41918709fcf4",
|
"uuid": "f0d14145-1175-48fa-b591-4b98f59a0e04",
|
||||||
"importer": "typescript",
|
"importer": "typescript",
|
||||||
"isPlugin": false,
|
"isPlugin": false,
|
||||||
"loadPluginInWeb": true,
|
"loadPluginInWeb": true,
|
@ -1,86 +1,86 @@
|
|||||||
export module Encoding.UTF8 {
|
export module Encoding.UTF8 {
|
||||||
|
|
||||||
export function GetBytes(str: string) {
|
export function GetBytes(str: string) {
|
||||||
let len = str.length, resPos = -1;
|
let len = str.length, resPos = -1;
|
||||||
let resArr = new Uint8Array(len * 3);
|
let resArr = new Uint8Array(len * 3);
|
||||||
for (let point = 0, nextcode = 0, i = 0; i !== len;) {
|
for (let point = 0, nextcode = 0, i = 0; i !== len;) {
|
||||||
point = str.charCodeAt(i), i += 1;
|
point = str.charCodeAt(i), i += 1;
|
||||||
if (point >= 0xD800 && point <= 0xDBFF) {
|
if (point >= 0xD800 && point <= 0xDBFF) {
|
||||||
if (i === len) {
|
if (i === len) {
|
||||||
resArr[resPos += 1] = 0xef;
|
resArr[resPos += 1] = 0xef;
|
||||||
resArr[resPos += 1] = 0xbf;
|
resArr[resPos += 1] = 0xbf;
|
||||||
resArr[resPos += 1] = 0xbd;
|
resArr[resPos += 1] = 0xbd;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
nextcode = str.charCodeAt(i);
|
nextcode = str.charCodeAt(i);
|
||||||
if (nextcode >= 0xDC00 && nextcode <= 0xDFFF) {
|
if (nextcode >= 0xDC00 && nextcode <= 0xDFFF) {
|
||||||
point = (point - 0xD800) * 0x400 + nextcode - 0xDC00 + 0x10000;
|
point = (point - 0xD800) * 0x400 + nextcode - 0xDC00 + 0x10000;
|
||||||
i += 1;
|
i += 1;
|
||||||
if (point > 0xffff) {
|
if (point > 0xffff) {
|
||||||
resArr[resPos += 1] = (0x1e << 3) | (point >>> 18);
|
resArr[resPos += 1] = (0x1e << 3) | (point >>> 18);
|
||||||
resArr[resPos += 1] = (0x2 << 6) | ((point >>> 12) & 0x3f);
|
resArr[resPos += 1] = (0x2 << 6) | ((point >>> 12) & 0x3f);
|
||||||
resArr[resPos += 1] = (0x2 << 6) | ((point >>> 6) & 0x3f);
|
resArr[resPos += 1] = (0x2 << 6) | ((point >>> 6) & 0x3f);
|
||||||
resArr[resPos += 1] = (0x2 << 6) | (point & 0x3f);
|
resArr[resPos += 1] = (0x2 << 6) | (point & 0x3f);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
resArr[resPos += 1] = 0xef;
|
resArr[resPos += 1] = 0xef;
|
||||||
resArr[resPos += 1] = 0xbf;
|
resArr[resPos += 1] = 0xbf;
|
||||||
resArr[resPos += 1] = 0xbd;
|
resArr[resPos += 1] = 0xbd;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (point <= 0x007f) {
|
if (point <= 0x007f) {
|
||||||
resArr[resPos += 1] = (0x0 << 7) | point;
|
resArr[resPos += 1] = (0x0 << 7) | point;
|
||||||
} else if (point <= 0x07ff) {
|
} else if (point <= 0x07ff) {
|
||||||
resArr[resPos += 1] = (0x6 << 5) | (point >>> 6);
|
resArr[resPos += 1] = (0x6 << 5) | (point >>> 6);
|
||||||
resArr[resPos += 1] = (0x2 << 6) | (point & 0x3f);
|
resArr[resPos += 1] = (0x2 << 6) | (point & 0x3f);
|
||||||
} else {
|
} else {
|
||||||
resArr[resPos += 1] = (0xe << 4) | (point >>> 12);
|
resArr[resPos += 1] = (0xe << 4) | (point >>> 12);
|
||||||
resArr[resPos += 1] = (0x2 << 6) | ((point >>> 6) & 0x3f);
|
resArr[resPos += 1] = (0x2 << 6) | ((point >>> 6) & 0x3f);
|
||||||
resArr[resPos += 1] = (0x2 << 6) | (point & 0x3f);
|
resArr[resPos += 1] = (0x2 << 6) | (point & 0x3f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return resArr.subarray(0, resPos + 1);
|
return resArr.subarray(0, resPos + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function GetString(array: Uint8Array) {
|
export function GetString(array: Uint8Array) {
|
||||||
let str = "";
|
let str = "";
|
||||||
let i = 0, len = array.length;
|
let i = 0, len = array.length;
|
||||||
while (i < len) {
|
while (i < len) {
|
||||||
let c = array[i++];
|
let c = array[i++];
|
||||||
switch (c >> 4) {
|
switch (c >> 4) {
|
||||||
case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
|
case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
|
||||||
str += String.fromCharCode(c);
|
str += String.fromCharCode(c);
|
||||||
break;
|
break;
|
||||||
case 12: case 13:
|
case 12: case 13:
|
||||||
str += String.fromCharCode(((c & 0x1F) << 6) | (array[i++] & 0x3F));
|
str += String.fromCharCode(((c & 0x1F) << 6) | (array[i++] & 0x3F));
|
||||||
break;
|
break;
|
||||||
case 14:
|
case 14:
|
||||||
str += String.fromCharCode(((c & 0x0F) << 12) | ((array[i++] & 0x3F) << 6) | ((array[i++] & 0x3F) << 0));
|
str += String.fromCharCode(((c & 0x0F) << 12) | ((array[i++] & 0x3F) << 6) | ((array[i++] & 0x3F) << 0));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function b64EncodeUnicode(str) {
|
export function b64EncodeUnicode(str) {
|
||||||
return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) {
|
return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) {
|
||||||
return String.fromCharCode('0x' + p1);
|
return String.fromCharCode('0x' + p1);
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
export function b64DecodeUnicode(str) {
|
export function b64DecodeUnicode(str) {
|
||||||
return decodeURIComponent(atob(str).split('').map(function (c) {
|
return decodeURIComponent(atob(str).split('').map(function (c) {
|
||||||
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
|
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
|
||||||
}).join(''));
|
}).join(''));
|
||||||
}
|
}
|
||||||
export function isBase64(str) {
|
export function isBase64(str) {
|
||||||
if (str === '' || str.trim() === '') { return false; }
|
if (str === '' || str.trim() === '') { return false; }
|
||||||
try {
|
try {
|
||||||
return btoa(atob(str)) == str;
|
return btoa(atob(str)) == str;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
13
assets/Script/Engine/CatanEngine/TableV3.meta
Normal file
13
assets/Script/Engine/CatanEngine/TableV3.meta
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.1.3",
|
||||||
|
"uuid": "c12c11f7-2e17-4727-a114-d4b19dfbe650",
|
||||||
|
"importer": "folder",
|
||||||
|
"isBundle": false,
|
||||||
|
"bundleName": "",
|
||||||
|
"priority": 1,
|
||||||
|
"compressionType": {},
|
||||||
|
"optimizeHotUpdate": {},
|
||||||
|
"inlineSpriteFrames": {},
|
||||||
|
"isRemoteBundle": {},
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
13
assets/Script/Engine/Component.meta
Normal file
13
assets/Script/Engine/Component.meta
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.1.3",
|
||||||
|
"uuid": "63dab366-ead1-4057-a9c2-a2548219328e",
|
||||||
|
"importer": "folder",
|
||||||
|
"isBundle": false,
|
||||||
|
"bundleName": "",
|
||||||
|
"priority": 1,
|
||||||
|
"compressionType": {},
|
||||||
|
"optimizeHotUpdate": {},
|
||||||
|
"inlineSpriteFrames": {},
|
||||||
|
"isRemoteBundle": {},
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
13
assets/Script/Engine/Data.meta
Normal file
13
assets/Script/Engine/Data.meta
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.1.3",
|
||||||
|
"uuid": "edf98a7e-294c-4e7a-8a53-c0b10ea75a45",
|
||||||
|
"importer": "folder",
|
||||||
|
"isBundle": false,
|
||||||
|
"bundleName": "",
|
||||||
|
"priority": 1,
|
||||||
|
"compressionType": {},
|
||||||
|
"optimizeHotUpdate": {},
|
||||||
|
"inlineSpriteFrames": {},
|
||||||
|
"isRemoteBundle": {},
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
export default class LocalStorageData {
|
export default class LocalStorageData {
|
||||||
private static _instance: LocalStorageData = null;
|
private static _instance: LocalStorageData = null;
|
||||||
public static get Instance(): LocalStorageData {
|
public static get Instance(): LocalStorageData {
|
||||||
@ -12,40 +11,10 @@ export default class LocalStorageData {
|
|||||||
// =======================================================================================
|
// =======================================================================================
|
||||||
public get CompileVersion(): string { return cc.sys.localStorage.getItem("CompileVersion"); }
|
public get CompileVersion(): string { return cc.sys.localStorage.getItem("CompileVersion"); }
|
||||||
public set CompileVersion(value: string) { cc.sys.localStorage.setItem("CompileVersion", value.toString()); }
|
public set CompileVersion(value: string) { cc.sys.localStorage.setItem("CompileVersion", value.toString()); }
|
||||||
public get RemoteVerList(): string { return cc.sys.localStorage.getItem("RemoteVerList"); }
|
public get BundleVersion(): string { return cc.sys.localStorage.getItem("BundleVersion"); }
|
||||||
public set RemoteVerList(value: string) { cc.sys.localStorage.setItem("RemoteVerList", value); }
|
public set BundleVersion(value: string) { cc.sys.localStorage.setItem("BundleVersion", value.toString()); }
|
||||||
public get LocalVerList(): string { return cc.sys.localStorage.getItem("LocalVerList"); }
|
|
||||||
public set LocalVerList(value: string) { cc.sys.localStorage.setItem("LocalVerList", value); }
|
|
||||||
public get ComboDeviceID(): string { return cc.sys.localStorage.getItem("ComboDeviceID") || ""; }
|
public get ComboDeviceID(): string { return cc.sys.localStorage.getItem("ComboDeviceID") || ""; }
|
||||||
public set ComboDeviceID(value: string) { cc.sys.localStorage.setItem("ComboDeviceID", value); }
|
public set ComboDeviceID(value: string) { cc.sys.localStorage.setItem("ComboDeviceID", value); }
|
||||||
public get BundleUrl(): string { return cc.sys.localStorage.getItem("BundleUrl"); }
|
public get BundleUrl(): string { return cc.sys.localStorage.getItem("BundleUrl"); }
|
||||||
public set BundleUrl(value: string) { cc.sys.localStorage.setItem("BundleUrl", value); }
|
public set BundleUrl(value: string) { cc.sys.localStorage.setItem("BundleUrl", value); }
|
||||||
public get Language(): string { return cc.sys.localStorage.getItem("language"); }
|
|
||||||
public set Language(value: string) { cc.sys.localStorage.setItem("language", value); }
|
|
||||||
public get MusicType(): string { return cc.sys.localStorage.getItem("MusicType"); }
|
|
||||||
public set MusicType(value: string) { cc.sys.localStorage.setItem("MusicType", value); }
|
|
||||||
public get SoundType(): string { return cc.sys.localStorage.getItem("SoundType"); }
|
|
||||||
public set SoundType(value: string) { cc.sys.localStorage.setItem("SoundType", value); }
|
|
||||||
public get LvUpNotifyType(): boolean { return JSON.parse(cc.sys.localStorage.getItem("LvUpNotifyType")); }
|
|
||||||
public set LvUpNotifyType(value: boolean) { cc.sys.localStorage.setItem("LvUpNotifyType", JSON.stringify(value)); }
|
|
||||||
public get WinNotifyType(): boolean { return JSON.parse(cc.sys.localStorage.getItem("WinNotifyType")); }
|
|
||||||
public set WinNotifyType(value: boolean) { cc.sys.localStorage.setItem("WinNotifyType", JSON.stringify(value)); }
|
|
||||||
public get DownloadList_Preview(): string { return cc.sys.localStorage.getItem("DownloadList_Preview"); }
|
|
||||||
public set DownloadList_Preview(value: string) { cc.sys.localStorage.setItem("DownloadList_Preview", value); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* key: id
|
|
||||||
* value: 是否開過卡
|
|
||||||
*/
|
|
||||||
public get BingoCardInfo(): Map<number, boolean> { return cc.sys.localStorage.getItem("BingoCardInfo") ? new Map(JSON.parse(cc.sys.localStorage.getItem("BingoCardInfo"))) : new Map<number, boolean>(); }
|
|
||||||
public set BingoCardInfo(value: Map<number, boolean>) { cc.sys.localStorage.setItem("BingoCardInfo", JSON.stringify(Array.from(value.entries()))); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* key: id
|
|
||||||
* value: 是否開過卡
|
|
||||||
*/
|
|
||||||
public get FiveCardInfo(): Map<number, boolean> { return cc.sys.localStorage.getItem("FiveCardInfo") ? new Map(JSON.parse(cc.sys.localStorage.getItem("FiveCardInfo"))) : new Map<number, boolean>(); }
|
|
||||||
public set FiveCardInfo(value: Map<number, boolean>) { cc.sys.localStorage.setItem("FiveCardInfo", JSON.stringify(Array.from(value.entries()))); }
|
|
||||||
|
|
||||||
// =======================================================================================
|
|
||||||
}
|
}
|
||||||
|
@ -1,456 +0,0 @@
|
|||||||
import BusinessTypeSetting from "../../_BusinessTypeSetting/BusinessTypeSetting";
|
|
||||||
import LocalStorageData from "../Data/LocalStorageData";
|
|
||||||
import Enum_Loading from "../HUDV2/Enum_Loading";
|
|
||||||
import HUDM from "./HUDM";
|
|
||||||
|
|
||||||
export default class AssetBundleMamager {
|
|
||||||
//#region static 屬性
|
|
||||||
|
|
||||||
private static _instance: AssetBundleMamager = null;
|
|
||||||
public static get Instance(): AssetBundleMamager { return AssetBundleMamager._instance; }
|
|
||||||
|
|
||||||
//#endregion
|
|
||||||
|
|
||||||
//#region public 屬性
|
|
||||||
|
|
||||||
public HUGroup: Map<string, HUDM> = new Map<string, HUDM>();
|
|
||||||
|
|
||||||
/** 本地VerList */
|
|
||||||
public LocalVerList: Enum_Loading.VerListObj = null;
|
|
||||||
|
|
||||||
/** 遠端VerList */
|
|
||||||
public RemoteVerList: Enum_Loading.VerListObj = null;
|
|
||||||
|
|
||||||
public DownloadList_Preview: Object = {};
|
|
||||||
|
|
||||||
/** IsChangeBundleUrl */
|
|
||||||
public IsChangeBundleUrl: boolean = false;
|
|
||||||
|
|
||||||
//#endregion
|
|
||||||
|
|
||||||
//#region Lifecycle
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
AssetBundleMamager._instance = this;
|
|
||||||
CC_PREVIEW && this._initdownloadList_Preview();
|
|
||||||
}
|
|
||||||
|
|
||||||
//#endregion
|
|
||||||
|
|
||||||
//#region Custom Function
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 取得Bundle
|
|
||||||
* @param {string} BundleName Bundle名稱
|
|
||||||
* @param {string} Version 版號
|
|
||||||
* @return {cc.AssetManager.Bundle} Bundle
|
|
||||||
*/
|
|
||||||
public *GetBundle(BundleName: string, Version: string = ""): IterableIterator<cc.AssetManager.Bundle> {
|
|
||||||
let bundle: cc.AssetManager.Bundle = cc.assetManager.getBundle(BundleName);
|
|
||||||
if (bundle) {
|
|
||||||
return bundle;
|
|
||||||
}
|
|
||||||
|
|
||||||
// options是可选参数,引擎会根据保留字段 进行对应的操作,这里添加了version和onFileProgress,可用来记录热更资源版本和下载进度
|
|
||||||
let options: any = null;
|
|
||||||
|
|
||||||
let BundleUrl: string = BundleName;
|
|
||||||
if (cc.sys.isNative && !this.LocalVerList[BundleName].UseLocal) {
|
|
||||||
BundleUrl = `${(jsb.fileUtils ? jsb.fileUtils.getWritablePath() : "/")}Bundle/${BundleName}/remote/${BundleName}`;
|
|
||||||
options = {
|
|
||||||
version: Version
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
cc.assetManager.loadBundle(BundleUrl, options, (err: Error, resp: cc.AssetManager.Bundle) => {
|
|
||||||
if (err) {
|
|
||||||
cc.error(err);
|
|
||||||
bundle = null;
|
|
||||||
}
|
|
||||||
bundle = resp;
|
|
||||||
});
|
|
||||||
while (typeof bundle === "undefined") {
|
|
||||||
yield null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return bundle;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 更新Bundle
|
|
||||||
* @param {HUDM} HUDName HUD
|
|
||||||
*/
|
|
||||||
public *UpdateBundle(HUDName: HUDM | string, onFileProgress?: (finish: number, total: number, item: string) => void): IterableIterator<any> {
|
|
||||||
let HUD: HUDM;
|
|
||||||
if (HUDName instanceof HUDM) {
|
|
||||||
HUD = HUDName;
|
|
||||||
} else {
|
|
||||||
HUD = this.GetHUD(HUDName);
|
|
||||||
}
|
|
||||||
let UpdateingData: Enum_Loading.UpdateingDataObj = yield* HUD.HUD(onFileProgress);
|
|
||||||
if (UpdateingData.IsUpdatecomplete) {
|
|
||||||
this.LocalVerList[HUD.BundleName] = this.RemoteVerList[HUD.BundleName];
|
|
||||||
this.LocalVerList[HUD.BundleName]["UseLocal"] = false;
|
|
||||||
LocalStorageData.Instance.LocalVerList = JSON.stringify(this.LocalVerList);
|
|
||||||
}
|
|
||||||
return UpdateingData;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 更新Bundle
|
|
||||||
* @param {HUDM} HUDName HUD
|
|
||||||
*/
|
|
||||||
public *RetryUpdateBundle(HUDName: HUDM | string, onFileProgress?: (finish: number, total: number, item: string) => void): IterableIterator<any> {
|
|
||||||
let HUD: HUDM;
|
|
||||||
if (HUDName instanceof HUDM) {
|
|
||||||
HUD = HUDName;
|
|
||||||
} else {
|
|
||||||
HUD = this.GetHUD(HUDName);
|
|
||||||
}
|
|
||||||
let UpdateingData: Enum_Loading.UpdateingDataObj = yield* HUD.RetryDownLoadFailedAssets();
|
|
||||||
return UpdateingData;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 從Bundle取得資源
|
|
||||||
* @param {cc.AssetManager.Bundle | string} BundleName Bundle名稱
|
|
||||||
* @param {string} SourceName 資源名稱
|
|
||||||
* @param {string} type 資源型別
|
|
||||||
* @return {any} Source
|
|
||||||
*/
|
|
||||||
public *GetBundleSource(BundleName: cc.AssetManager.Bundle | string, SourceName: string, type?: string | Bundle_Source_Type, onFileProgress?: (finish: number, total: number, item: cc.AssetManager.RequestItem) => void): IterableIterator<any> {
|
|
||||||
let bundle: cc.AssetManager.Bundle;
|
|
||||||
let source: any;
|
|
||||||
if (BundleName instanceof cc.AssetManager.Bundle) {
|
|
||||||
bundle = BundleName;
|
|
||||||
} else {
|
|
||||||
bundle = cc.assetManager.getBundle(BundleName);
|
|
||||||
if (!bundle) {
|
|
||||||
cc.error(`GetBundleSource Error BundleName: ${BundleName}`);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case Bundle_Source_Type.Scene: {
|
|
||||||
bundle.loadScene(SourceName, onFileProgress, function (err: Error, scene: cc.SceneAsset): void {
|
|
||||||
if (err) {
|
|
||||||
cc.error(err);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
// cc.director.runScene(scene);
|
|
||||||
source = scene;
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case Bundle_Source_Type.Json: {
|
|
||||||
bundle.load(SourceName, onFileProgress, function (err: Error, json: cc.JsonAsset): void {
|
|
||||||
if (err) {
|
|
||||||
cc.error(err);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
// source = JSON.parse(json["_nativeAsset"]);
|
|
||||||
source = json;
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case Bundle_Source_Type.Prefab: {
|
|
||||||
bundle.load(SourceName, cc.Prefab, onFileProgress, function (err: Error, prefab: cc.Asset): void {
|
|
||||||
if (err) {
|
|
||||||
cc.error(err);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
// source = JSON.parse(json["_nativeAsset"]);
|
|
||||||
source = prefab;
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
bundle.load(SourceName, function (err: Error, any: any): void {
|
|
||||||
if (err) {
|
|
||||||
cc.error(err);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
source = any;
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (typeof source === "undefined") {
|
|
||||||
yield null;
|
|
||||||
}
|
|
||||||
return source;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 釋放Bundle
|
|
||||||
* @param {string} slotID slotID
|
|
||||||
*/
|
|
||||||
public *BundleRelease(slotID: number): IterableIterator<any> {
|
|
||||||
let gameName: string = `Game_${slotID}`;
|
|
||||||
let sceneName: string = `Slot${slotID}`;
|
|
||||||
let bundle: cc.AssetManager.Bundle = cc.assetManager.getBundle(gameName);
|
|
||||||
if (!bundle) {
|
|
||||||
cc.log(`BundleRelease Error BundleName: ${gameName}`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// let bundles: cc.AssetManager.Cache<cc.AssetManager.Bundle> = cc.assetManager.bundles;
|
|
||||||
// let cacheDir: string = cc.assetManager.cacheManager.cacheDir;
|
|
||||||
// let cachedFiles: Object = cc.assetManager.cacheManager.cachedFiles;
|
|
||||||
|
|
||||||
yield* this.DelBundleCache(bundle);
|
|
||||||
yield* this.DelOthersCache(slotID);
|
|
||||||
bundle.release(sceneName, cc.SceneAsset);
|
|
||||||
cc.assetManager.removeBundle(bundle);
|
|
||||||
cc.sys.garbageCollect();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 從Bundle刪除暫存資源
|
|
||||||
* @param {string} BundleName Bundle名稱
|
|
||||||
*/
|
|
||||||
public *DelBundleCache(BundleName: cc.AssetManager.Bundle | string): IterableIterator<any> {
|
|
||||||
if (!CC_JSB) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let bundle: cc.AssetManager.Bundle;
|
|
||||||
let source: any;
|
|
||||||
if (BundleName instanceof cc.AssetManager.Bundle) {
|
|
||||||
bundle = BundleName;
|
|
||||||
} else {
|
|
||||||
bundle = cc.assetManager.getBundle(BundleName);
|
|
||||||
if (!bundle) {
|
|
||||||
// cc.error(`GetBundleSource Error BundleName: ${BundleName}`);
|
|
||||||
// return;
|
|
||||||
bundle = yield* AssetBundleMamager.Instance.GetBundle(BundleName, this.RemoteVerList[BundleName].Version);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let _map: Object = bundle["_config"].assetInfos._map;
|
|
||||||
for (let map of Object.keys(_map)) {
|
|
||||||
let path: string = _map[map].path;
|
|
||||||
if (!path) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
source = yield* AssetBundleMamager.Instance.GetBundleSource(bundle, path);
|
|
||||||
cc.assetManager.cacheManager.removeCache(source.nativeUrl);
|
|
||||||
bundle.release(path);
|
|
||||||
// return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 從cachedFiles刪除暫存資源
|
|
||||||
* @param {number} slotID slotID
|
|
||||||
*/
|
|
||||||
public *DelOthersCache(slotID: number): IterableIterator<any> {
|
|
||||||
if (!CC_JSB) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let cachedFiles: Object = cc.assetManager.cacheManager.cachedFiles["_map"];
|
|
||||||
let delcache_group: string[] = [`shared/jsons`, `Slot/Slot${slotID}`, "sounds/Slot/Default", `${BusinessTypeSetting.FolderUrlBundle}project.manifest`, "submit.txt"];
|
|
||||||
for (let cached of Object.keys(cachedFiles)) {
|
|
||||||
for (var i: number = 0; i < delcache_group.length; ++i) {
|
|
||||||
let delcache: string = delcache_group[i];
|
|
||||||
if (cached.includes(delcache)) {
|
|
||||||
cc.assetManager.cacheManager.removeCache(cached);
|
|
||||||
// console.log(`removeCache: ${cached}`);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public GetHUD(BundleName: HUDM | string): HUDM {
|
|
||||||
let HUD: HUDM;
|
|
||||||
if (BundleName instanceof HUDM) {
|
|
||||||
HUD = BundleName;
|
|
||||||
} else {
|
|
||||||
if (!this.HUGroup.has(BundleName)) {
|
|
||||||
HUD = new HUDM(BundleName);
|
|
||||||
this.HUGroup.set(BundleName, HUD);
|
|
||||||
} else {
|
|
||||||
HUD = this.HUGroup.get(BundleName);
|
|
||||||
}
|
|
||||||
HUD = this.HUGroup.get(BundleName);
|
|
||||||
}
|
|
||||||
return HUD;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 刪除全部暫存資源 */
|
|
||||||
public ClearAllCache(): void {
|
|
||||||
cc.assetManager.cacheManager.clearCache();
|
|
||||||
cc.game.restart();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public *CheckBundleNeedHUD(BundleName: HUDM | string): IterableIterator<Enum_Loading.NeedUpdateDataObj> {
|
|
||||||
let HUD: HUDM;
|
|
||||||
if (BundleName instanceof HUDM) {
|
|
||||||
HUD = BundleName;
|
|
||||||
} else {
|
|
||||||
HUD = this.GetHUD(BundleName);
|
|
||||||
}
|
|
||||||
if (!this.LocalVerList[HUD.BundleName]) {
|
|
||||||
this.LocalVerList[HUD.BundleName] = new Enum_Loading.BundleDataObj();
|
|
||||||
let apkVersion: string = this.RemoteVerList[HUD.BundleName].ApkVersion;
|
|
||||||
if (apkVersion && apkVersion !== "0") {
|
|
||||||
this.LocalVerList[HUD.BundleName].UseLocal = true;
|
|
||||||
this.LocalVerList[HUD.BundleName].Version = apkVersion;
|
|
||||||
}
|
|
||||||
LocalStorageData.Instance.LocalVerList = JSON.stringify(this.LocalVerList);
|
|
||||||
} else {
|
|
||||||
if (this.RemoteVerList[HUD.BundleName].Version === this.RemoteVerList[HUD.BundleName].ApkVersion) {
|
|
||||||
this.LocalVerList[HUD.BundleName] = this.RemoteVerList[HUD.BundleName];
|
|
||||||
this.LocalVerList[HUD.BundleName].UseLocal = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let UpdateData: Enum_Loading.NeedUpdateDataObj = new Enum_Loading.NeedUpdateDataObj();
|
|
||||||
if (this.LocalVerList[HUD.BundleName].UseLocal) {
|
|
||||||
UpdateData.IsNeedUpdate = AssetBundleMamager.Instance.versionCompareHandle(this.LocalVerList[HUD.BundleName].Version, this.RemoteVerList[HUD.BundleName].Version) < 0 ? true : false;
|
|
||||||
if (UpdateData.IsNeedUpdate) {
|
|
||||||
UpdateData = yield* HUD.CheckUpdate();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
UpdateData = yield* HUD.CheckUpdate();
|
|
||||||
}
|
|
||||||
return UpdateData;
|
|
||||||
}
|
|
||||||
|
|
||||||
// public *CheckBundleNeedHUD(BundleName: string): IterableIterator<boolean> {
|
|
||||||
// if (!this.LocalVerList[BundleName]) {
|
|
||||||
// this.LocalVerList[BundleName] = new Enum_Loading.BundleDataObj();
|
|
||||||
// let apkVersion: string = this.RemoteVerList[BundleName].ApkVersion;
|
|
||||||
// if (apkVersion && apkVersion !== "0") {
|
|
||||||
// this.LocalVerList[BundleName].UseLocal = true;
|
|
||||||
// this.LocalVerList[BundleName].Version = apkVersion;
|
|
||||||
// }
|
|
||||||
// LocalStorageData.Instance.LocalVerList = JSON.stringify(this.LocalVerList);
|
|
||||||
// }
|
|
||||||
// let IsUpdate: boolean = AssetBundleMamager.Instance.versionCompareHandle(this.LocalVerList[BundleName].Version, this.RemoteVerList[BundleName].Version) < 0 ? true : false;
|
|
||||||
// return IsUpdate;
|
|
||||||
// }
|
|
||||||
|
|
||||||
public CheckGameNeedUpdate(GameID: number): boolean {
|
|
||||||
let IsUpdate: boolean = false;
|
|
||||||
let bundleName: string = `Game_${GameID}`;
|
|
||||||
if (!this.RemoteVerList[bundleName]) {
|
|
||||||
this.RemoteVerList[bundleName] = new Enum_Loading.BundleDataObj();
|
|
||||||
this.RemoteVerList[bundleName].HasBundle = false;
|
|
||||||
LocalStorageData.Instance.RemoteVerList = JSON.stringify(this.RemoteVerList);
|
|
||||||
IsUpdate = true;
|
|
||||||
}
|
|
||||||
if (!this.LocalVerList[bundleName]) {
|
|
||||||
this.LocalVerList[bundleName] = new Enum_Loading.BundleDataObj();
|
|
||||||
let apkVersion: string = this.RemoteVerList[bundleName].ApkVersion;
|
|
||||||
if (apkVersion && apkVersion !== "0") {
|
|
||||||
this.LocalVerList[bundleName].UseLocal = true;
|
|
||||||
this.LocalVerList[bundleName].Version = apkVersion;
|
|
||||||
}
|
|
||||||
LocalStorageData.Instance.LocalVerList = JSON.stringify(this.LocalVerList);
|
|
||||||
}
|
|
||||||
if (CC_PREVIEW) {
|
|
||||||
return this._getIsDownload_Preview(GameID);
|
|
||||||
}
|
|
||||||
if (IsUpdate) {
|
|
||||||
return IsUpdate;
|
|
||||||
}
|
|
||||||
IsUpdate = AssetBundleMamager.Instance.versionCompareHandle(this.LocalVerList[bundleName].Version, this.RemoteVerList[bundleName].Version) < 0 ? true : false;
|
|
||||||
return IsUpdate;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 比對版號(熱更能從1.0.0更新到2.0.0,從2.0.0回退到1.0.0)
|
|
||||||
* 官方提供的版本比較函數,只有服務端版本>客戶端版本時,才會進行更新。所以不能從2.0.0回退到1.0.0版本。
|
|
||||||
* @param {string} versionA 本地版號
|
|
||||||
* @param {string} versionB 遠程版號
|
|
||||||
* @return {number} num = -1 須更新
|
|
||||||
* @return {number} num = 0 不須更新
|
|
||||||
*/
|
|
||||||
public versionCompareHandle(versionA: string, versionB: string): number {
|
|
||||||
// console.log("Ver A " + versionA + "VerB " + versionB);
|
|
||||||
var vA: string[] = versionA.split(".");
|
|
||||||
var vB: string[] = versionB.split(".");
|
|
||||||
|
|
||||||
// 長度不相等,則進行更新
|
|
||||||
if (vA.length !== vB.length) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var i: number = 0; i < vA.length; ++i) {
|
|
||||||
var a: number = +vA[i];
|
|
||||||
var b: number = +vB[i] || 0;
|
|
||||||
if (a === b) {
|
|
||||||
// 數字相同,則跳過
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
// 數字不同,則進行更新
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 長度相等且數字相等,則不更新
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//#endregion
|
|
||||||
|
|
||||||
//#region DownloadList_Preview
|
|
||||||
|
|
||||||
private _initdownloadList_Preview(): void {
|
|
||||||
this.DownloadList_Preview = JSON.parse(LocalStorageData.Instance.DownloadList_Preview);
|
|
||||||
this.DownloadList_Preview = this.DownloadList_Preview ? this.DownloadList_Preview : {};
|
|
||||||
}
|
|
||||||
|
|
||||||
private _getIsDownload_Preview(slotID: number): boolean {
|
|
||||||
if (!this.DownloadList_Preview[slotID]) {
|
|
||||||
this.SetIsDownload_Preview(slotID, false);
|
|
||||||
}
|
|
||||||
return !this.DownloadList_Preview[slotID];
|
|
||||||
}
|
|
||||||
|
|
||||||
public SetIsDownload_Preview(slotID: number, isDownload: boolean = true): void {
|
|
||||||
this.DownloadList_Preview[slotID] = isDownload;
|
|
||||||
LocalStorageData.Instance.DownloadList_Preview = JSON.stringify(this.DownloadList_Preview);
|
|
||||||
}
|
|
||||||
|
|
||||||
//#endregion
|
|
||||||
}
|
|
||||||
|
|
||||||
//#region enum
|
|
||||||
|
|
||||||
/** Bundle資源類型 */
|
|
||||||
export enum Bundle_Source_Type {
|
|
||||||
/** Json */
|
|
||||||
Json = "json",
|
|
||||||
|
|
||||||
/** Scene */
|
|
||||||
Scene = "scene",
|
|
||||||
|
|
||||||
/** Prefab */
|
|
||||||
Prefab = "prefab"
|
|
||||||
}
|
|
||||||
|
|
||||||
//#endregion
|
|
||||||
|
|
||||||
//#region 廢棄 Function
|
|
||||||
|
|
||||||
// /**
|
|
||||||
// * 從Bundle刪除暫存資源
|
|
||||||
// * @param {string} BundleName Bundle名稱
|
|
||||||
// */
|
|
||||||
// public *DelBundleCache(BundleName: cc.AssetManager.Bundle | string): IterableIterator<any> {
|
|
||||||
// if (!CC_JSB) {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// let WritablePath: string = `${jsb.fileUtils.getWritablePath()}gamecaches/${BundleName}`;
|
|
||||||
// if (jsb.fileUtils.isDirectoryExist(WritablePath)) {
|
|
||||||
// jsb.fileUtils.removeDirectory(WritablePath);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
//#endregion
|
|
@ -1,425 +0,0 @@
|
|||||||
import BusinessTypeSetting from "../../_BusinessTypeSetting/BusinessTypeSetting";
|
|
||||||
import Enum_Loading from "../HUDV2/Enum_Loading";
|
|
||||||
import AssetBundleMamager from "./AssetBundleMamager";
|
|
||||||
|
|
||||||
const { ccclass, property } = cc._decorator;
|
|
||||||
|
|
||||||
/** HUDManager */
|
|
||||||
@ccclass
|
|
||||||
export default class HUDM extends cc.Component {
|
|
||||||
|
|
||||||
//#region static 屬性
|
|
||||||
|
|
||||||
private static _instance: HUDM = null;
|
|
||||||
public static get Instance(): HUDM { return HUDM._instance; }
|
|
||||||
|
|
||||||
//#endregion
|
|
||||||
|
|
||||||
//#region static 屬性
|
|
||||||
|
|
||||||
public BundleName: string = "";
|
|
||||||
|
|
||||||
//#endregion
|
|
||||||
|
|
||||||
//#region private 屬性
|
|
||||||
|
|
||||||
private _am: jsb.AssetsManager;
|
|
||||||
private _onFileProgress: (finish: number, total: number, item: string) => void;
|
|
||||||
private _updateListener: any;
|
|
||||||
private _checkListener: any;
|
|
||||||
private _versionCompareHandle: any = null;
|
|
||||||
private _needUpdateData: Enum_Loading.NeedUpdateDataObj = null;
|
|
||||||
private _updateingData: Enum_Loading.UpdateingDataObj = null;
|
|
||||||
private _updating: boolean = false;
|
|
||||||
private _canRetry: boolean = false;
|
|
||||||
private _isChangeUrl: boolean = false;
|
|
||||||
private _path: string = "Bundle";
|
|
||||||
private _customManifest: string = "";
|
|
||||||
private _storagePath: string = "";
|
|
||||||
|
|
||||||
//#endregion
|
|
||||||
|
|
||||||
//#region Lifecycle
|
|
||||||
|
|
||||||
constructor(...params: any[]) {
|
|
||||||
super();
|
|
||||||
|
|
||||||
if (!cc.sys.isNative) {
|
|
||||||
return;
|
|
||||||
} else if (params.length === 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
HUDM._instance = this;
|
|
||||||
|
|
||||||
this.BundleName = params[0];
|
|
||||||
// let packageUrl: string = params[1];
|
|
||||||
// let BundleData: Enum_Loading.BundleDataObj = AssetBundleMamager.Instance.RemoteVerList[this.BundleName];
|
|
||||||
// let packageUrl: string = BundleData.BundleUrl;
|
|
||||||
let packageUrl: string = `${BusinessTypeSetting.UsePatch}${BusinessTypeSetting.FolderUrlBundle}${this.BundleName}`;
|
|
||||||
|
|
||||||
this._customManifest = JSON.stringify({
|
|
||||||
"packageUrl": packageUrl,
|
|
||||||
"remoteManifestUrl": `${packageUrl}/project.manifest`,
|
|
||||||
"remoteVersionUrl": `${packageUrl}/version.json`,
|
|
||||||
"version": "0.0.0",
|
|
||||||
});
|
|
||||||
|
|
||||||
this._storagePath = `${(jsb.fileUtils ? jsb.fileUtils.getWritablePath() : "./")}${this._path}/${this.BundleName}`;
|
|
||||||
|
|
||||||
// 本地熱更目錄下已存在project.manifest,則直接修改已存在的project.manifest
|
|
||||||
if (AssetBundleMamager.Instance.IsChangeBundleUrl) {
|
|
||||||
if (jsb.fileUtils.isFileExist(this._storagePath + "/project.manifest")) {
|
|
||||||
this._isChangeUrl = true;
|
|
||||||
this._modifyAppLoadUrlForManifestFile(this._storagePath, packageUrl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this._versionCompareHandle = function (versionA: string, versionB: string): number {
|
|
||||||
// console.log("Ver A " + versionA + "VerB " + versionB);
|
|
||||||
var vA: string[] = versionA.split(".");
|
|
||||||
var vB: string[] = versionB.split(".");
|
|
||||||
|
|
||||||
// 長度不相等,則進行更新
|
|
||||||
if (vA.length !== vB.length) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var i: number = 0; i < vA.length; ++i) {
|
|
||||||
var a: number = +vA[i];
|
|
||||||
var b: number = +vB[i] || 0;
|
|
||||||
if (a === b) {
|
|
||||||
// 數字相同,則跳過
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
// 數字不同,則進行更新
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 長度相等且數字相等,則不更新
|
|
||||||
return 0;
|
|
||||||
};
|
|
||||||
this._initAssetManaget();
|
|
||||||
}
|
|
||||||
private _initAssetManaget(): void {
|
|
||||||
//
|
|
||||||
this._am = new jsb.AssetsManager("", this._storagePath, this._versionCompareHandle);
|
|
||||||
|
|
||||||
// Setup the verification callback, but we don't have md5 check function yet, so only print some message
|
|
||||||
// Return true if the verification passed, otherwise return false
|
|
||||||
this._am.setVerifyCallback(function (path: any, asset: { compressed: any; md5: any; path: any; size: any; }): boolean {
|
|
||||||
// When asset is compressed, we don't need to check its md5, because zip file have been deleted.
|
|
||||||
var compressed: any = asset.compressed;
|
|
||||||
// Retrieve the correct md5 value.
|
|
||||||
var expectedMD5: string = asset.md5;
|
|
||||||
// asset.path is relative path and path is absolute.
|
|
||||||
var relativePath: string = asset.path;
|
|
||||||
// The size of asset file, but this value could be absent.
|
|
||||||
var size: any = asset.size;
|
|
||||||
if (compressed) {
|
|
||||||
// panel.info.string = "Verification passed : " + relativePath;
|
|
||||||
// cc.log("onLoad -> Verification passed : " + relativePath);
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
// panel.info.string = "Verification passed : " + relativePath + ' (' + expectedMD5 + ')';
|
|
||||||
// cc.log("onLoad -> setVerifyCallbackVerification passed : " + relativePath + " (" + expectedMD5 + ")");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (cc.sys.os === cc.sys.OS_ANDROID) {
|
|
||||||
// Some Android device may slow down the download process when concurrent tasks is too much.
|
|
||||||
// The value may not be accurate, please do more test and find what's most suitable for your game.
|
|
||||||
// this._am.setMaxConcurrentTask(10);
|
|
||||||
this._am["setMaxConcurrentTask"](10);
|
|
||||||
// this.panel.info.string = "Max concurrent tasks count have been limited to 2";
|
|
||||||
// cc.log("onLoad -> Max concurrent tasks count have been limited to 10");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private _modifyAppLoadUrlForManifestFile(filePath: string, newBundleUrl: string): void {
|
|
||||||
let allpath: string[] = [filePath, filePath + "_temp"];
|
|
||||||
let manifestname: string[] = ["project.manifest", "project.manifest.temp"];
|
|
||||||
for (var i: number = 0; i < allpath.length; ++i) {
|
|
||||||
let path: string = `${allpath[i]}/${manifestname[i]}`;
|
|
||||||
if (jsb.fileUtils.isFileExist(path)) {
|
|
||||||
// console.log(`[HUD] modifyAppLoadUrlForManifestFile: 有下載的manifest文件,直接修改熱更地址`);
|
|
||||||
// 修改project.manifest
|
|
||||||
let projectManifest: string = jsb.fileUtils.getStringFromFile(path);
|
|
||||||
let projectManifestObj: any = JSON.parse(projectManifest);
|
|
||||||
projectManifestObj.packageUrl = newBundleUrl;
|
|
||||||
projectManifestObj.remoteManifestUrl = newBundleUrl + "/project.manifest";
|
|
||||||
projectManifestObj.remoteVersionUrl = newBundleUrl + "/version.json";
|
|
||||||
let afterString: string = JSON.stringify(projectManifestObj);
|
|
||||||
let isWrittenProject: boolean = jsb.fileUtils.writeStringToFile(afterString, path);
|
|
||||||
// // 更新數據庫中的新請求地址,下次如果檢測到不一致就重新修改 manifest 文件
|
|
||||||
// if (isWrittenProject) {
|
|
||||||
// LocalStorageData.Instance.BundleUrl = BusinessTypeSetting.UsePatch;
|
|
||||||
// }
|
|
||||||
// console.log("[HUD] 修改是否成功,project.manifest:", isWrittenProject);
|
|
||||||
// console.log("[HUD] 修改後文件:", projectManifestObj.packageUrl, projectManifestObj.remoteManifestUrl, projectManifestObj.remoteVersionUrl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//#endregion
|
|
||||||
|
|
||||||
|
|
||||||
public *CheckUpdate(): IterableIterator<any> {
|
|
||||||
this._needUpdateData = null;
|
|
||||||
if (this._updating) {
|
|
||||||
// this.panel.info.string = 'Checking or updating ...';
|
|
||||||
console.error("checkUpdate -> Checking or updating ...");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this._am.getState() === jsb.AssetsManager.State.UNINITED) {
|
|
||||||
let manifest: jsb.Manifest = new jsb.Manifest(this._customManifest, this._storagePath);
|
|
||||||
this._am.loadLocalManifest(manifest, this._storagePath);
|
|
||||||
}
|
|
||||||
if (!this._am.getLocalManifest() || !this._am.getLocalManifest().isLoaded()) {
|
|
||||||
// this.tipsLabel.string = "Failed to load local manifest ...";
|
|
||||||
console.error("checkUpdate -> Failed to load local manifest ...");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this._am.setEventCallback(this.checkCb.bind(this));
|
|
||||||
|
|
||||||
this._am.checkUpdate();
|
|
||||||
this._updating = true;
|
|
||||||
|
|
||||||
while (this._needUpdateData === null) {
|
|
||||||
yield null;
|
|
||||||
}
|
|
||||||
|
|
||||||
let newBundleUrl: string = `${BusinessTypeSetting.UsePatch}${BusinessTypeSetting.FolderUrlBundle}${this.BundleName}`;
|
|
||||||
this._modifyAppLoadUrlForManifestFile(this._storagePath, newBundleUrl);
|
|
||||||
this._initAssetManaget();
|
|
||||||
|
|
||||||
let manifest: jsb.Manifest = new jsb.Manifest(this._customManifest, this._storagePath);
|
|
||||||
this._am.loadLocalManifest(manifest, this._storagePath);
|
|
||||||
if (!this._am.getLocalManifest() || !this._am.getLocalManifest().isLoaded()) {
|
|
||||||
// this.tipsLabel.string = "Failed to load local manifest ...";
|
|
||||||
console.error("checkUpdate -> Failed to load local manifest ...");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更新動態路徑後再跑一次
|
|
||||||
this._am.setEventCallback(this.checkCb.bind(this));
|
|
||||||
|
|
||||||
this._needUpdateData = null;
|
|
||||||
this._am.checkUpdate();
|
|
||||||
this._updating = true;
|
|
||||||
while (this._needUpdateData === null) {
|
|
||||||
yield null;
|
|
||||||
}
|
|
||||||
if (this._isChangeUrl && (!this._needUpdateData.IsNeedUpdate || this._needUpdateData.TotalBytes === "0 B")) {
|
|
||||||
if (jsb.fileUtils.isFileExist(this._storagePath)) {
|
|
||||||
let isremoveDirectory: boolean = jsb.fileUtils.removeDirectory(this._storagePath);
|
|
||||||
let isremoveDirectory_temp: boolean = jsb.fileUtils.removeDirectory(this._storagePath + "_temp");
|
|
||||||
if (isremoveDirectory_temp) {
|
|
||||||
console.log(`removeDirectory: ${this._storagePath}_temp`);
|
|
||||||
}
|
|
||||||
if (isremoveDirectory) {
|
|
||||||
console.log(`removeDirectory: ${this._storagePath}`);
|
|
||||||
this._needUpdateData = null;
|
|
||||||
this._initAssetManaget();
|
|
||||||
this._needUpdateData = yield* this.CheckUpdate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return this._needUpdateData;
|
|
||||||
}
|
|
||||||
|
|
||||||
private checkCb(event: jsb.EventAssetsManager): void {
|
|
||||||
var failed: boolean = false;
|
|
||||||
switch (event.getEventCode()) {
|
|
||||||
case jsb.EventAssetsManager.ERROR_NO_LOCAL_MANIFEST:
|
|
||||||
// this.tipsLabel.string = "No local manifest file found, HUD skipped.";
|
|
||||||
console.error("checkCb -> No local manifest file found, HUD skipped.");
|
|
||||||
failed = true;
|
|
||||||
break;
|
|
||||||
case jsb.EventAssetsManager.ERROR_DOWNLOAD_MANIFEST:
|
|
||||||
case jsb.EventAssetsManager.ERROR_PARSE_MANIFEST:
|
|
||||||
// this.tipsLabel.string = "Fail to download manifest file, HUD skipped.";
|
|
||||||
console.error("checkCb -> Fail to download manifest file, HUD skipped.");
|
|
||||||
failed = true;
|
|
||||||
break;
|
|
||||||
case jsb.EventAssetsManager.ALREADY_UP_TO_DATE:
|
|
||||||
// this.tipsLabel.string = "Already up to date with the latest remote version.";
|
|
||||||
// cc.log("checkCb -> Already up to date with the latest remote version.");
|
|
||||||
this._needUpdateData = new Enum_Loading.NeedUpdateDataObj(false);
|
|
||||||
break;
|
|
||||||
case jsb.EventAssetsManager.NEW_VERSION_FOUND:
|
|
||||||
// this.downloadLabel.node.active = true;
|
|
||||||
// this.downloadLabel.string = "New version found, please try to update." + event.getTotalBytes();
|
|
||||||
// this.panel.checkBtn.active = false;
|
|
||||||
// this.panel.fileProgress.progress = 0;
|
|
||||||
// this.panel.byteProgress.progress = 0;
|
|
||||||
// cc.log("checkCb -> New version found, please try to update." + event.getTotalBytes());
|
|
||||||
this._needUpdateData = new Enum_Loading.NeedUpdateDataObj(true, this._bytesToSize(event.getTotalBytes()));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._am.setEventCallback(null);
|
|
||||||
this._checkListener = null;
|
|
||||||
this._updating = false;
|
|
||||||
|
|
||||||
if (failed) {
|
|
||||||
//
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public *HUD(onFileProgress?: (finish: number, total: number, item: string) => void): IterableIterator<any> {
|
|
||||||
this._updateingData = null;
|
|
||||||
if (this._am && !this._updating) {
|
|
||||||
this._am.setEventCallback(this._updateCb.bind(this));
|
|
||||||
|
|
||||||
if (this._am.getState() === jsb.AssetsManager.State.UNINITED) {
|
|
||||||
let manifest: jsb.Manifest = new jsb.Manifest(this._customManifest, this._storagePath);
|
|
||||||
this._am.loadLocalManifest(manifest, this._storagePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
this._onFileProgress = onFileProgress ? onFileProgress : null;
|
|
||||||
this._am.update();
|
|
||||||
this._updating = true;
|
|
||||||
|
|
||||||
while (this._updateingData === null) {
|
|
||||||
yield null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this._updateingData;
|
|
||||||
} else {
|
|
||||||
return new Enum_Loading.UpdateingDataObj(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private _updateCb(event: jsb.EventAssetsManager): void {
|
|
||||||
var needRestart: boolean = false;
|
|
||||||
var failed: boolean = false;
|
|
||||||
switch (event.getEventCode()) {
|
|
||||||
case jsb.EventAssetsManager.ERROR_NO_LOCAL_MANIFEST:
|
|
||||||
// this.panel.info.string = 'No local manifest file found, HUD skipped.';
|
|
||||||
cc.log("updateCb -> No local manifest file found, HUD skipped.");
|
|
||||||
failed = true;
|
|
||||||
break;
|
|
||||||
case jsb.EventAssetsManager.UPDATE_PROGRESSION:
|
|
||||||
// this.panel.byteProgress.progress = event.getPercent();
|
|
||||||
// this.panel.fileProgress.progress = event.getPercentByFile();
|
|
||||||
// this.panel.fileLabel.string = event.getDownloadedFiles() + ' / ' + event.getTotalFiles();
|
|
||||||
// this.tipsLabel.string = event.getDownloadedBytes() + " / " + event.getTotalBytes();
|
|
||||||
|
|
||||||
// cc.log("updateCb -> " + event.getDownloadedBytes() + " / " + event.getTotalBytes());
|
|
||||||
// var msg: string = event.getMessage();
|
|
||||||
// if (msg) {
|
|
||||||
// // this.panel.info.string = 'Updated file: ' + msg;
|
|
||||||
// cc.log("updateCb -> Updated file: " + msg);
|
|
||||||
// console.log("updateCb -> " + event.getPercent() / 100 + "% : " + msg);
|
|
||||||
// }
|
|
||||||
|
|
||||||
var msg: string = event.getMessage();
|
|
||||||
if (this._onFileProgress) {
|
|
||||||
this._onFileProgress(event.getDownloadedBytes(), event.getTotalBytes(), msg ? msg : "");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case jsb.EventAssetsManager.ERROR_DOWNLOAD_MANIFEST:
|
|
||||||
case jsb.EventAssetsManager.ERROR_PARSE_MANIFEST:
|
|
||||||
// this.panel.info.string = 'Fail to download manifest file, HUD skipped.';
|
|
||||||
console.error("updateCb -> Fail to download manifest file, HUD skipped.");
|
|
||||||
failed = true;
|
|
||||||
break;
|
|
||||||
case jsb.EventAssetsManager.ALREADY_UP_TO_DATE:
|
|
||||||
// this.panel.info.string = 'Already up to date with the latest remote version.';
|
|
||||||
console.error("updateCb -> Already up to date with the latest remote version.");
|
|
||||||
failed = true;
|
|
||||||
break;
|
|
||||||
case jsb.EventAssetsManager.UPDATE_FINISHED:
|
|
||||||
// this.tipsLabel.string = "更新完成. " + event.getMessage();
|
|
||||||
// cc.log("updateCb -> 更新完成. " + event.getMessage());
|
|
||||||
this._updateingData = new Enum_Loading.UpdateingDataObj(true);
|
|
||||||
needRestart = true;
|
|
||||||
break;
|
|
||||||
case jsb.EventAssetsManager.UPDATE_FAILED:
|
|
||||||
// this.panel.info.string = 'Update failed. ' + event.getMessage();
|
|
||||||
console.error("updateCb -> Update failed. " + event.getMessage());
|
|
||||||
// this.panel.retryBtn.active = true;
|
|
||||||
this._canRetry = true;
|
|
||||||
this._updateingData = new Enum_Loading.UpdateingDataObj(false);
|
|
||||||
this._updating = false;
|
|
||||||
break;
|
|
||||||
case jsb.EventAssetsManager.ERROR_UPDATING:
|
|
||||||
// this.panel.info.string = 'Asset update error: ' + event.getAssetId() + ', ' + event.getMessage();
|
|
||||||
console.error("updateCb -> Asset update error: " + event.getAssetId() + ", " + event.getMessage());
|
|
||||||
break;
|
|
||||||
case jsb.EventAssetsManager.ERROR_DECOMPRESS:
|
|
||||||
// this.panel.info.string = event.getMessage();
|
|
||||||
console.error("updateCb -> " + event.getMessage());
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (failed) {
|
|
||||||
this._am.setEventCallback(null);
|
|
||||||
this._updateListener = null;
|
|
||||||
this._updating = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 測試先不restart 之後看情況
|
|
||||||
// if (needRestart) {
|
|
||||||
// this._am.setEventCallback(null);
|
|
||||||
// this._updateListener = null;
|
|
||||||
// // Prepend the manifest's search path
|
|
||||||
// var searchPaths: string[] = jsb.fileUtils.getSearchPaths();
|
|
||||||
|
|
||||||
// // var newPaths = this._am.getLocalManifest().getSearchPaths();
|
|
||||||
// // cc.log("newPath."+JSON.stringify(newPaths));
|
|
||||||
// // Array.prototype.unshift.apply(searchPaths, newPaths);
|
|
||||||
|
|
||||||
// cc.sys.localStorage.setItem("HUDSearchPaths", JSON.stringify(searchPaths));
|
|
||||||
|
|
||||||
// jsb.fileUtils.setSearchPaths(searchPaths);
|
|
||||||
|
|
||||||
// cc.audioEngine.stopAll();
|
|
||||||
// cc.game.restart();
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
public *RetryDownLoadFailedAssets(): IterableIterator<any> {
|
|
||||||
if (!this._updating && this._canRetry) {
|
|
||||||
this._updateingData = null;
|
|
||||||
// this.panel.retryBtn.active = false;
|
|
||||||
this._canRetry = false;
|
|
||||||
|
|
||||||
// this.panel.info.string = 'Retry failed Assets...';
|
|
||||||
// cc.log("retry -> Retry failed Assets...");
|
|
||||||
this._am.downloadFailedAssets();
|
|
||||||
|
|
||||||
while (this._updateingData === null) {
|
|
||||||
yield null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this._updateingData;
|
|
||||||
} else {
|
|
||||||
console.error(`retry -> error updating: ${this._updating}, canRetry: ${this._canRetry}`);
|
|
||||||
this._updateingData = new Enum_Loading.UpdateingDataObj(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private _bytesToSize(bytes: number): string {
|
|
||||||
if (bytes === 0) {
|
|
||||||
return "0 B";
|
|
||||||
}
|
|
||||||
let k: number = 1024;
|
|
||||||
let sizes: string[] = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
|
|
||||||
let i: number = Math.floor(Math.log(bytes) / Math.log(k));
|
|
||||||
return (bytes / Math.pow(k, i)).toPrecision(3) + " " + sizes[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
protected onDestroy(): void {
|
|
||||||
if (this._updateListener) {
|
|
||||||
this._am.setEventCallback(null);
|
|
||||||
this._updateListener = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,522 +0,0 @@
|
|||||||
import BusinessTypeSetting from "../../_BusinessTypeSetting/BusinessTypeSetting";
|
|
||||||
import { CoroutineV2 } from "../CatanEngine/CoroutineV2/CoroutineV2";
|
|
||||||
import LocalStorageData from "../Data/LocalStorageData";
|
|
||||||
import Enum_Loading from "./Enum_Loading";
|
|
||||||
|
|
||||||
export default class AssetBundleMamagerV2 {
|
|
||||||
//#region static 屬性
|
|
||||||
|
|
||||||
private static _instance: AssetBundleMamagerV2 = null;
|
|
||||||
public static get Instance(): AssetBundleMamagerV2 { return AssetBundleMamagerV2._instance; }
|
|
||||||
|
|
||||||
//#endregion
|
|
||||||
|
|
||||||
//#region public 屬性
|
|
||||||
|
|
||||||
/** 本地VerList */
|
|
||||||
public LocalVerList: Enum_Loading.VerListObj = null;
|
|
||||||
|
|
||||||
/** 遠端VerList */
|
|
||||||
public RemoteVerList: JSON = null;
|
|
||||||
|
|
||||||
public DownloadList_Preview: Object = {};
|
|
||||||
|
|
||||||
/** 快取資源 */
|
|
||||||
public CachedFiles: Map<string, cc.Asset> = new Map<string, cc.Asset>();
|
|
||||||
|
|
||||||
//#endregion
|
|
||||||
|
|
||||||
//#region Lifecycle
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
AssetBundleMamagerV2._instance = this;
|
|
||||||
CC_PREVIEW && this._initdownloadList_Preview();
|
|
||||||
}
|
|
||||||
|
|
||||||
//#endregion
|
|
||||||
|
|
||||||
//#region 清除資料
|
|
||||||
|
|
||||||
/** 判斷更改編譯版號.清除BUNDLE記錄 */
|
|
||||||
public CheckCompileVersion(): void {
|
|
||||||
let oldCompileVersion: string = LocalStorageData.Instance.CompileVersion;
|
|
||||||
let newCompileVersion: string = BusinessTypeSetting.COMPILE_VERSION;
|
|
||||||
if (oldCompileVersion && oldCompileVersion !== newCompileVersion) {
|
|
||||||
this.ClearBundleData();
|
|
||||||
console.log("change compile version.");
|
|
||||||
}
|
|
||||||
LocalStorageData.Instance.CompileVersion = BusinessTypeSetting.COMPILE_VERSION;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 判斷更改PATCH環境.清除BUNDLE記錄 */
|
|
||||||
public CheckChangePatchUrl(): void {
|
|
||||||
let oldBundleUrl: string = LocalStorageData.Instance.BundleUrl;
|
|
||||||
let newBundleUrl: string = BusinessTypeSetting.UsePatch;
|
|
||||||
if (oldBundleUrl && oldBundleUrl !== newBundleUrl) {
|
|
||||||
this.ClearBundleData();
|
|
||||||
console.log("change patch url.");
|
|
||||||
}
|
|
||||||
LocalStorageData.Instance.BundleUrl = BusinessTypeSetting.UsePatch;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 清除Bundle資料 */
|
|
||||||
public ClearBundleData(): void {
|
|
||||||
cc.sys.localStorage.removeItem("LocalVerList");
|
|
||||||
cc.sys.localStorage.removeItem("RemoteVerList");
|
|
||||||
cc.assetManager.bundles.clear();
|
|
||||||
if (CC_JSB) {
|
|
||||||
cc.assetManager.cacheManager.clearCache();
|
|
||||||
console.log("clear bundle data.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 清除所有資料重啟 */
|
|
||||||
public ClearAppDataToRestart(): void {
|
|
||||||
cc.sys.localStorage.clear();
|
|
||||||
cc.assetManager.bundles.clear();
|
|
||||||
if (CC_JSB) {
|
|
||||||
cc.assetManager.cacheManager.clearCache();
|
|
||||||
cc.game.restart();
|
|
||||||
} else {
|
|
||||||
window.location.reload();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//#endregion
|
|
||||||
|
|
||||||
//#region Custom Function
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 取得Bundle
|
|
||||||
* @param {string} BundleName Bundle名稱
|
|
||||||
* @param {string} Version 版號
|
|
||||||
* @return {cc.AssetManager.Bundle} Bundle
|
|
||||||
*/
|
|
||||||
public *GetBundle(BundleName: string): IterableIterator<cc.AssetManager.Bundle> {
|
|
||||||
let self: this = this;
|
|
||||||
let bundle: cc.AssetManager.Bundle | boolean = cc.assetManager.getBundle(BundleName);
|
|
||||||
if (bundle) {
|
|
||||||
yield* this.GetDepsBundle(bundle.deps);
|
|
||||||
return bundle;
|
|
||||||
}
|
|
||||||
/** 判斷是不是要下載新版本 */
|
|
||||||
let isNeedUpdate: boolean = this.IsNeedUpdate(BundleName);
|
|
||||||
if (isNeedUpdate) {
|
|
||||||
// 下載新版本前需要先清除暫存
|
|
||||||
console.log(`removeCache: ${BundleName}`);
|
|
||||||
this.DelBundleCache(BundleName);
|
|
||||||
this.LocalVerList[BundleName].UseLocal = false;
|
|
||||||
}
|
|
||||||
/** Bundle路徑 */
|
|
||||||
let BundleUrl: string = BusinessTypeSetting.GetRemoteFileUrl(BundleName);
|
|
||||||
if (CC_DEV) {
|
|
||||||
// CC_DEVBundle路徑為: BundleName
|
|
||||||
// if (BundleName.indexOf("Script") != -1) {
|
|
||||||
BundleUrl = `${BundleName}`;
|
|
||||||
// } else {
|
|
||||||
// BundleUrl = "http://192.168.7.57/bj_casino/test/" + BundleName;
|
|
||||||
// }
|
|
||||||
} else if (this.LocalVerList[BundleName].UseLocal) {
|
|
||||||
// 本地Bundle路徑為: assets/assets/${BundleName}
|
|
||||||
BundleUrl = `assets/${BundleName}`;
|
|
||||||
}
|
|
||||||
if (CC_DEV) {
|
|
||||||
cc.assetManager.loadBundle(BundleUrl, (err: Error, resp: cc.AssetManager.Bundle) => {
|
|
||||||
if (err) {
|
|
||||||
console.error(err);
|
|
||||||
bundle = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
bundle = resp;
|
|
||||||
});
|
|
||||||
while (typeof bundle === "undefined") {
|
|
||||||
yield null;
|
|
||||||
}
|
|
||||||
} else if (BundleName.includes("Script")) {
|
|
||||||
bundle = yield* self.loadScriptBundle(BundleUrl);
|
|
||||||
} else {
|
|
||||||
if (CC_JSB && !this.LocalVerList[BundleName].UseLocal) {
|
|
||||||
let bundlePath: string = `${jsb.fileUtils.getWritablePath()}gamecaches/${BundleName}/`;
|
|
||||||
if (!jsb.fileUtils.isFileExist(bundlePath)) {
|
|
||||||
cc.assetManager.cacheManager["makeBundleFolder"](BundleName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bundle = yield* self.loadUIBundle(BundleUrl);
|
|
||||||
}
|
|
||||||
if (bundle) {
|
|
||||||
yield* this.GetDepsBundle((<cc.AssetManager.Bundle>bundle).deps);
|
|
||||||
if (isNeedUpdate) {
|
|
||||||
// 下載成功後更改本地Bundle版本
|
|
||||||
self.LocalVerList[BundleName].Version = self.RemoteVerList[BundleName];
|
|
||||||
LocalStorageData.Instance.LocalVerList = JSON.stringify(self.LocalVerList);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return bundle;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 從Bundle取得資源
|
|
||||||
* @param {string} BundleUrl Bundle路徑
|
|
||||||
*/
|
|
||||||
public *loadScriptBundle(BundleUrl: string): IterableIterator<any> {
|
|
||||||
let fileName: string = `index.${CC_DEBUG ? "js" : "jsc"}`;
|
|
||||||
let fileUrl: string = `${BundleUrl}/${fileName}`;
|
|
||||||
let run: boolean = true;
|
|
||||||
let isSuceess: boolean = false;
|
|
||||||
cc.assetManager.loadScript(fileUrl, (err: Error) => {
|
|
||||||
if (err) {
|
|
||||||
console.error(`[Error] ${fileUrl}載入失敗 err: ${err}`);
|
|
||||||
run = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
isSuceess = true;
|
|
||||||
run = false;
|
|
||||||
});
|
|
||||||
while (run) {
|
|
||||||
yield null;
|
|
||||||
}
|
|
||||||
return isSuceess;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 從Bundle取得資源
|
|
||||||
* @param {string} BundleUrl Bundle路徑
|
|
||||||
*/
|
|
||||||
public *loadUIBundle(BundleUrl: string): IterableIterator<cc.AssetManager.Bundle> {
|
|
||||||
let fileName: string = "config.json";
|
|
||||||
let fileUrl: string = `${BundleUrl}/${fileName}`;
|
|
||||||
let data: any;
|
|
||||||
let run: boolean = true;
|
|
||||||
cc.assetManager.loadRemote(fileUrl, (err: Error, res: cc.JsonAsset) => {
|
|
||||||
if (err) {
|
|
||||||
console.error(`[Error] ${fileUrl}載入失敗 err: ${err}`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
data = res.json;
|
|
||||||
run = false;
|
|
||||||
});
|
|
||||||
while (run) {
|
|
||||||
yield null;
|
|
||||||
}
|
|
||||||
let bundle: cc.AssetManager.Bundle = new cc.AssetManager.Bundle();
|
|
||||||
data.base = `${BundleUrl}/`;
|
|
||||||
bundle.init(data);
|
|
||||||
return bundle;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 取得Bundle
|
|
||||||
* @param {string} BundleName Bundle名稱
|
|
||||||
* @param {string} Version 版號
|
|
||||||
* @return {cc.AssetManager.Bundle} Bundle
|
|
||||||
*/
|
|
||||||
public *GetDepsBundle(deps: string[]): IterableIterator<any> {
|
|
||||||
if (!deps || deps.length <= 2) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let self: this = this;
|
|
||||||
let GetBundle_F_Arr: IterableIterator<any>[] = [];
|
|
||||||
for (const bundleName of deps) {
|
|
||||||
if (!["main", "internal"].includes(bundleName)) {
|
|
||||||
let GetBundle_F: IterableIterator<any> = function* (): IterableIterator<any> {
|
|
||||||
yield* self.GetBundle(bundleName);
|
|
||||||
}();
|
|
||||||
GetBundle_F_Arr.push(GetBundle_F);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
yield CoroutineV2.Parallel(...GetBundle_F_Arr).Start();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 從Bundle取得資源
|
|
||||||
* @param {number} slotID slotID
|
|
||||||
* @param {Function} onFileProgress onFileProgress
|
|
||||||
*/
|
|
||||||
public *PreloadBundleScene(slotID: number, onFileProgress?: (finish: number, total: number, item: cc.AssetManager.RequestItem) => void): IterableIterator<any> {
|
|
||||||
let BundleName: string = `Game_${slotID}`;
|
|
||||||
let SourceName: string = `Slot${slotID}`;
|
|
||||||
let run: boolean = true;
|
|
||||||
let UpdateingData: Enum_Loading.UpdateingDataObj = new Enum_Loading.UpdateingDataObj(false);
|
|
||||||
let bundle: cc.AssetManager.Bundle = yield* AssetBundleMamagerV2.Instance.GetBundle(BundleName);
|
|
||||||
if (!bundle) {
|
|
||||||
console.error(`GetBundleSource Error BundleName: ${BundleName}`);
|
|
||||||
return UpdateingData;
|
|
||||||
}
|
|
||||||
|
|
||||||
bundle.preloadScene(SourceName, onFileProgress, function (error: Error): void {
|
|
||||||
if (error) {
|
|
||||||
console.error(error);
|
|
||||||
run = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
UpdateingData.IsUpdatecomplete = true;
|
|
||||||
run = false;
|
|
||||||
});
|
|
||||||
|
|
||||||
while (run) {
|
|
||||||
yield null;
|
|
||||||
}
|
|
||||||
return UpdateingData;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 從Bundle取得資源
|
|
||||||
* @param {cc.AssetManager.Bundle | string} BundleName Bundle名稱
|
|
||||||
* @param {string} SourceName 資源名稱
|
|
||||||
* @param {string} type 資源型別
|
|
||||||
* @return {any} Source
|
|
||||||
*/
|
|
||||||
public *GetBundleSource(BundleName: cc.AssetManager.Bundle | string, SourceName: string, type?: string | Bundle_Source_Type, onFileProgress?: (finish: number, total: number, item: cc.AssetManager.RequestItem) => void): IterableIterator<any> {
|
|
||||||
let bundle: cc.AssetManager.Bundle;
|
|
||||||
let source: any;
|
|
||||||
if (BundleName instanceof cc.AssetManager.Bundle) {
|
|
||||||
bundle = BundleName;
|
|
||||||
} else {
|
|
||||||
bundle = yield* AssetBundleMamagerV2.Instance.GetBundle(BundleName);
|
|
||||||
if (!bundle) {
|
|
||||||
cc.error(`GetBundleSource Error BundleName: ${BundleName}`);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case Bundle_Source_Type.Scene: {
|
|
||||||
bundle.loadScene(SourceName, onFileProgress, function (err: Error, scene: cc.SceneAsset): void {
|
|
||||||
if (err) {
|
|
||||||
cc.error(err);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
// cc.director.runScene(scene);
|
|
||||||
source = scene;
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case Bundle_Source_Type.Json: {
|
|
||||||
bundle.load(SourceName, onFileProgress, function (err: Error, json: cc.JsonAsset): void {
|
|
||||||
if (err) {
|
|
||||||
cc.error(err);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
// source = JSON.parse(json["_nativeAsset"]);
|
|
||||||
source = json;
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case Bundle_Source_Type.Prefab: {
|
|
||||||
bundle.load(SourceName, cc.Prefab, onFileProgress, function (err: Error, prefab: cc.Asset): void {
|
|
||||||
if (err) {
|
|
||||||
cc.error(err);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
// source = JSON.parse(json["_nativeAsset"]);
|
|
||||||
source = prefab;
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
bundle.load(SourceName, function (err: Error, any: any): void {
|
|
||||||
if (err) {
|
|
||||||
cc.error(err);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
source = any;
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (typeof source === "undefined") {
|
|
||||||
yield null;
|
|
||||||
}
|
|
||||||
return source;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 從Bundle取得資源(不卡協成)
|
|
||||||
* @param {string} bundleName bundleName
|
|
||||||
* @param {string} sourcePath Bundle資料夾下的路徑
|
|
||||||
*/
|
|
||||||
public static GetBundleSourceV2(bundleName: cc.bundleName | string, sourcePath: string): cc.Prefab {
|
|
||||||
let bundle: cc.AssetManager.Bundle = cc.assetManager.getBundle(bundleName);
|
|
||||||
if (!bundle) {
|
|
||||||
cc.error(`GetBundleSourceV2 getBundle error bundleName: ${bundleName}`);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
let source: cc.Prefab = bundle.get(sourcePath, cc.Prefab);
|
|
||||||
if (!source) {
|
|
||||||
cc.error(`GetBundleSourceV2 bundle.get error bundleName: ${bundleName}, sourcePath: ${sourcePath}`);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return source;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 釋放Bundle
|
|
||||||
* @param {string} slotID slotID
|
|
||||||
*/
|
|
||||||
public *BundleRelease(slotID: number): IterableIterator<any> {
|
|
||||||
let gameName: string = `Game_${slotID}`;
|
|
||||||
let sceneName: string = `Slot${slotID}`;
|
|
||||||
let bundle: cc.AssetManager.Bundle = cc.assetManager.getBundle(gameName);
|
|
||||||
if (!bundle) {
|
|
||||||
cc.log(`BundleRelease Error BundleName: ${gameName}`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.ReleaseSlotCache(slotID);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 從cachedFiles刪除暫存資源
|
|
||||||
* @param {string} BundleName Bundle名稱
|
|
||||||
*/
|
|
||||||
public DelBundleCache(BundleName: string): void {
|
|
||||||
if (CC_BUILD && cc.sys.isNative) {
|
|
||||||
let cachedFiles: Object = cc.assetManager.cacheManager.cachedFiles["_map"];
|
|
||||||
let delcache: string = BusinessTypeSetting.GetRemoteFileUrl(BundleName) + "/";
|
|
||||||
for (let cached of Object.keys(cachedFiles)) {
|
|
||||||
if (cached.includes(delcache)) {
|
|
||||||
cc.assetManager.cacheManager.removeCache(cached);
|
|
||||||
// console.log(`removeCache: ${cached}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 從cachedFiles釋放暫存資源
|
|
||||||
* @param {number} slotID slotID
|
|
||||||
*/
|
|
||||||
public ReleaseSlotCache(slotID: number): void {
|
|
||||||
if (!CC_JSB) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let delcachedKeys: string[] = [];
|
|
||||||
let cachedFiles: Map<string, cc.Asset> = this.CachedFiles;
|
|
||||||
let delcache_group: string[] = [`shared/jsons`, `Slot/Slot${slotID}`, "sounds/Slot/Default", "submit.txt"];
|
|
||||||
cachedFiles.forEach((cached: cc.Asset, key: string, map: Map<string, cc.Asset>) => {
|
|
||||||
for (var i: number = 0; i < delcache_group.length; ++i) {
|
|
||||||
let delcache: string = delcache_group[i];
|
|
||||||
if (key.includes(delcache)) {
|
|
||||||
cc.assetManager.releaseAsset(cached);
|
|
||||||
delcachedKeys.push(key);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
for (var i: number = 0; i < delcachedKeys.length; ++i) {
|
|
||||||
this.CachedFiles.delete(delcachedKeys[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 判斷要不要更新
|
|
||||||
* @param {string} BundleName Bundle名稱
|
|
||||||
*/
|
|
||||||
public IsNeedUpdate(BundleName: string): boolean {
|
|
||||||
let isNeedUpdate: boolean;
|
|
||||||
// 判斷本地有無Bundle資料
|
|
||||||
if (this.LocalVerList[BundleName] && !this.LocalVerList[BundleName].HasBundle) {
|
|
||||||
if (this.RemoteVerList[BundleName]) {
|
|
||||||
// 改成有包過Bundle了,重新走下面流程
|
|
||||||
this.LocalVerList[BundleName] = null;
|
|
||||||
} else {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.LocalVerList[BundleName]) {
|
|
||||||
// 本地無Bundle資料需要新增
|
|
||||||
this.LocalVerList[BundleName] = new Enum_Loading.BundleDataObj();
|
|
||||||
LocalStorageData.Instance.LocalVerList = JSON.stringify(this.LocalVerList);
|
|
||||||
}
|
|
||||||
let version: string = this.RemoteVerList[BundleName];
|
|
||||||
if (!version) {
|
|
||||||
// !version代表還沒包Bundle
|
|
||||||
this.LocalVerList[BundleName].HasBundle = false;
|
|
||||||
LocalStorageData.Instance.LocalVerList = JSON.stringify(this.LocalVerList);
|
|
||||||
return true;
|
|
||||||
} else if (version === "0") {
|
|
||||||
// version === "0" 代表要使用本體Bundle
|
|
||||||
this.LocalVerList[BundleName].UseLocal = true;
|
|
||||||
this.LocalVerList[BundleName].Version = "0";
|
|
||||||
LocalStorageData.Instance.LocalVerList = JSON.stringify(this.LocalVerList);
|
|
||||||
}
|
|
||||||
isNeedUpdate = AssetBundleMamagerV2.Instance.versionCompareHandle(this.LocalVerList[BundleName].Version, this.RemoteVerList[BundleName]) !== 0 ? true : false;
|
|
||||||
return isNeedUpdate;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 比對版號(熱更能從1.0.0更新到2.0.0,從2.0.0回退到1.0.0)
|
|
||||||
* 官方提供的版本比較函數,只有服務端版本>客戶端版本時,才會進行更新。所以不能從2.0.0回退到1.0.0版本。
|
|
||||||
* @param {string} versionA 本地版號
|
|
||||||
* @param {string} versionB 遠程版號
|
|
||||||
* @return {number} num = -1 須更新
|
|
||||||
* @return {number} num = 0 不須更新
|
|
||||||
*/
|
|
||||||
public versionCompareHandle(versionA: string, versionB: string): number {
|
|
||||||
// console.log("Ver A " + versionA + "VerB " + versionB);
|
|
||||||
var vA: string[] = versionA.split(".");
|
|
||||||
var vB: string[] = versionB.split(".");
|
|
||||||
|
|
||||||
// 長度不相等,則進行更新
|
|
||||||
if (vA.length !== vB.length) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var i: number = 0; i < vA.length; ++i) {
|
|
||||||
var a: number = +vA[i];
|
|
||||||
var b: number = +vB[i] || 0;
|
|
||||||
if (a === b) {
|
|
||||||
// 數字相同,則跳過
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
// 數字不同(且版號比目標低),則進行更新
|
|
||||||
return a - b;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 長度相等且數字相等,則不更新
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//#endregion
|
|
||||||
|
|
||||||
//#region DownloadList_Preview
|
|
||||||
|
|
||||||
private _initdownloadList_Preview(): void {
|
|
||||||
this.DownloadList_Preview = JSON.parse(LocalStorageData.Instance.DownloadList_Preview);
|
|
||||||
this.DownloadList_Preview = this.DownloadList_Preview ? this.DownloadList_Preview : {};
|
|
||||||
}
|
|
||||||
|
|
||||||
public GetIsDownload_Preview(slotID: number): boolean {
|
|
||||||
if (!this.DownloadList_Preview[slotID]) {
|
|
||||||
this.SetIsDownload_Preview(slotID, false);
|
|
||||||
}
|
|
||||||
return this.DownloadList_Preview[slotID];
|
|
||||||
}
|
|
||||||
|
|
||||||
public SetIsDownload_Preview(slotID: number, isDownload: boolean = true): void {
|
|
||||||
this.DownloadList_Preview[slotID] = isDownload;
|
|
||||||
LocalStorageData.Instance.DownloadList_Preview = JSON.stringify(this.DownloadList_Preview);
|
|
||||||
}
|
|
||||||
|
|
||||||
//#endregion
|
|
||||||
}
|
|
||||||
|
|
||||||
//#region enum
|
|
||||||
|
|
||||||
/** Bundle資源類型 */
|
|
||||||
export enum Bundle_Source_Type {
|
|
||||||
/** Json */
|
|
||||||
Json = "json",
|
|
||||||
|
|
||||||
/** Scene */
|
|
||||||
Scene = "scene",
|
|
||||||
|
|
||||||
/** Prefab */
|
|
||||||
Prefab = "prefab"
|
|
||||||
}
|
|
||||||
|
|
||||||
//#endregion
|
|
@ -1,72 +0,0 @@
|
|||||||
const { ccclass, property } = cc._decorator;
|
|
||||||
export module Enum_Loading {
|
|
||||||
|
|
||||||
//#region Enum
|
|
||||||
|
|
||||||
//#endregion
|
|
||||||
|
|
||||||
//#region Class
|
|
||||||
|
|
||||||
// /** BaseBundle資料 */
|
|
||||||
// @ccclass("BaseBundleObj")
|
|
||||||
// export class BaseBundleObj {
|
|
||||||
// @property({ displayName: "Bundle名稱", tooltip: "Bundle名稱" })
|
|
||||||
// public BundleName: string = "";
|
|
||||||
|
|
||||||
// @property({ displayName: "優先度", tooltip: "優先度", type: cc.Integer })
|
|
||||||
// public Priority: number = 1;
|
|
||||||
// }
|
|
||||||
|
|
||||||
class BundleDictionary<T> {
|
|
||||||
[x: string]: T;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** VerList資料 */
|
|
||||||
@ccclass("VerListObj")
|
|
||||||
export class VerListObj extends BundleDictionary<BundleDataObj> {
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Bundle資料 */
|
|
||||||
@ccclass("BundleDataObj")
|
|
||||||
export class BundleDataObj {
|
|
||||||
public Version: string = "0";
|
|
||||||
|
|
||||||
public ApkVersion: string = "0";
|
|
||||||
|
|
||||||
public UseLocal: boolean = false;
|
|
||||||
|
|
||||||
/** 有沒有包到Bundle */
|
|
||||||
public HasBundle: boolean = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Bundle資料 */
|
|
||||||
@ccclass("NeedUpdateDataObj")
|
|
||||||
export class NeedUpdateDataObj {
|
|
||||||
|
|
||||||
/** 是否需要更新 */
|
|
||||||
public IsNeedUpdate: boolean;
|
|
||||||
|
|
||||||
/** 更新大小 */
|
|
||||||
public TotalBytes: string;
|
|
||||||
|
|
||||||
constructor(...params: any[]) {
|
|
||||||
this.IsNeedUpdate = params[0];
|
|
||||||
this.TotalBytes = params[1] ? params[1] : null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Bundle資料 */
|
|
||||||
@ccclass("UpdateingDataObj")
|
|
||||||
export class UpdateingDataObj {
|
|
||||||
|
|
||||||
/** 是否更新完成 */
|
|
||||||
public IsUpdatecomplete: boolean;
|
|
||||||
|
|
||||||
constructor(...params: any[]) {
|
|
||||||
this.IsUpdatecomplete = params[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//#endregion
|
|
||||||
}
|
|
||||||
export default Enum_Loading;
|
|
@ -1,43 +0,0 @@
|
|||||||
|
|
||||||
const { ccclass, property } = cc._decorator;
|
|
||||||
|
|
||||||
export module GameData_HUD {
|
|
||||||
|
|
||||||
//#region Enum
|
|
||||||
|
|
||||||
/** BundleName */
|
|
||||||
export enum BundleName {
|
|
||||||
/** CommonSound */
|
|
||||||
CommonSound = "CommonSound",
|
|
||||||
CommonLanguageTexture = "CommonLanguageTexture",
|
|
||||||
Common = "Common",
|
|
||||||
ResourceItem = "ResourceItem",
|
|
||||||
MainControl = "MainControl",
|
|
||||||
Login = "Login",
|
|
||||||
Lobby = "Lobby",
|
|
||||||
BindAccount = "BindAccount",
|
|
||||||
Shop = "Shop",
|
|
||||||
Vip = "Vip",
|
|
||||||
Ad = "Ad",
|
|
||||||
SettingPanel = "SettingPanel",
|
|
||||||
PlayerInfo = "PlayerInfo",
|
|
||||||
Rank = "Rank",
|
|
||||||
Chat = "Chat",
|
|
||||||
Gift = "Gift",
|
|
||||||
Activity = "Activity",
|
|
||||||
Mail = "Mail",
|
|
||||||
GettingPanel = "GettingPanel",
|
|
||||||
Backpack = "Backpack",
|
|
||||||
Game_GetCoin = "Game_GetCoin",
|
|
||||||
Game_BigWinJackpot = "Game_BigWinJackpot",
|
|
||||||
Game_BottomUI_BJ = "Game_BottomUI_BJ",
|
|
||||||
Game_BottomUI_SD = "Game_BottomUI_SD",
|
|
||||||
SlotCommom = "SlotCommom",
|
|
||||||
TableCommon = "TableCommon",
|
|
||||||
FishCommon = "FishCommon",
|
|
||||||
ActivityMission = "ActivityMission"
|
|
||||||
}
|
|
||||||
|
|
||||||
//#endregion
|
|
||||||
}
|
|
||||||
export default GameData_HUD;
|
|
13
assets/Script/Engine/Timer.meta
Normal file
13
assets/Script/Engine/Timer.meta
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.1.3",
|
||||||
|
"uuid": "fd4b4720-4e75-4bfe-a27c-1520c3f18eb0",
|
||||||
|
"importer": "folder",
|
||||||
|
"isBundle": false,
|
||||||
|
"bundleName": "",
|
||||||
|
"priority": 1,
|
||||||
|
"compressionType": {},
|
||||||
|
"optimizeHotUpdate": {},
|
||||||
|
"inlineSpriteFrames": {},
|
||||||
|
"isRemoteBundle": {},
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
13
assets/Script/Engine/Utils.meta
Normal file
13
assets/Script/Engine/Utils.meta
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.1.3",
|
||||||
|
"uuid": "eba93305-455d-4d2d-a914-db71bc7f0022",
|
||||||
|
"importer": "folder",
|
||||||
|
"isBundle": false,
|
||||||
|
"bundleName": "",
|
||||||
|
"priority": 1,
|
||||||
|
"compressionType": {},
|
||||||
|
"optimizeHotUpdate": {},
|
||||||
|
"inlineSpriteFrames": {},
|
||||||
|
"isRemoteBundle": {},
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
13
assets/Script/HUD.meta
Normal file
13
assets/Script/HUD.meta
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.1.3",
|
||||||
|
"uuid": "b4db1c37-7356-4f88-ba5c-9ea4e86a85b7",
|
||||||
|
"importer": "folder",
|
||||||
|
"isBundle": false,
|
||||||
|
"bundleName": "",
|
||||||
|
"priority": 1,
|
||||||
|
"compressionType": {},
|
||||||
|
"optimizeHotUpdate": {},
|
||||||
|
"inlineSpriteFrames": {},
|
||||||
|
"isRemoteBundle": {},
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
456
assets/Script/HUD/AssetBundleMamager.ts
Normal file
456
assets/Script/HUD/AssetBundleMamager.ts
Normal file
@ -0,0 +1,456 @@
|
|||||||
|
// import BusinessTypeSetting from "../../_BusinessTypeSetting/BusinessTypeSetting";
|
||||||
|
// import LocalStorageData from "../Data/LocalStorageData";
|
||||||
|
// import Enum_Loading from "../HUDV2/Enum_Loading";
|
||||||
|
// import HUDM from "./HUDM";
|
||||||
|
|
||||||
|
// export default class AssetBundleMamager {
|
||||||
|
// //#region static 屬性
|
||||||
|
|
||||||
|
// private static _instance: AssetBundleMamager = null;
|
||||||
|
// public static get Instance(): AssetBundleMamager { return AssetBundleMamager._instance; }
|
||||||
|
|
||||||
|
// //#endregion
|
||||||
|
|
||||||
|
// //#region public 屬性
|
||||||
|
|
||||||
|
// public HUGroup: Map<string, HUDM> = new Map<string, HUDM>();
|
||||||
|
|
||||||
|
// /** 本地VerList */
|
||||||
|
// public LocalVerList: Enum_Loading.VerListObj = null;
|
||||||
|
|
||||||
|
// /** 遠端VerList */
|
||||||
|
// public RemoteVerList: Enum_Loading.VerListObj = null;
|
||||||
|
|
||||||
|
// public DownloadList_Preview: Object = {};
|
||||||
|
|
||||||
|
// /** IsChangeBundleUrl */
|
||||||
|
// public IsChangeBundleUrl: boolean = false;
|
||||||
|
|
||||||
|
// //#endregion
|
||||||
|
|
||||||
|
// //#region Lifecycle
|
||||||
|
|
||||||
|
// constructor() {
|
||||||
|
// AssetBundleMamager._instance = this;
|
||||||
|
// CC_PREVIEW && this._initdownloadList_Preview();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// //#endregion
|
||||||
|
|
||||||
|
// //#region Custom Function
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * 取得Bundle
|
||||||
|
// * @param {string} BundleName Bundle名稱
|
||||||
|
// * @param {string} Version 版號
|
||||||
|
// * @return {cc.AssetManager.Bundle} Bundle
|
||||||
|
// */
|
||||||
|
// public *GetBundle(BundleName: string, Version: string = ""): IterableIterator<cc.AssetManager.Bundle> {
|
||||||
|
// let bundle: cc.AssetManager.Bundle = cc.assetManager.getBundle(BundleName);
|
||||||
|
// if (bundle) {
|
||||||
|
// return bundle;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // options是可选参数,引擎会根据保留字段 进行对应的操作,这里添加了version和onFileProgress,可用来记录热更资源版本和下载进度
|
||||||
|
// let options: any = null;
|
||||||
|
|
||||||
|
// let BundleUrl: string = BundleName;
|
||||||
|
// if (cc.sys.isNative && !this.LocalVerList[BundleName].UseLocal) {
|
||||||
|
// BundleUrl = `${(jsb.fileUtils ? jsb.fileUtils.getWritablePath() : "/")}Bundle/${BundleName}/remote/${BundleName}`;
|
||||||
|
// options = {
|
||||||
|
// version: Version
|
||||||
|
// };
|
||||||
|
// }
|
||||||
|
|
||||||
|
// cc.assetManager.loadBundle(BundleUrl, options, (err: Error, resp: cc.AssetManager.Bundle) => {
|
||||||
|
// if (err) {
|
||||||
|
// cc.error(err);
|
||||||
|
// bundle = null;
|
||||||
|
// }
|
||||||
|
// bundle = resp;
|
||||||
|
// });
|
||||||
|
// while (typeof bundle === "undefined") {
|
||||||
|
// yield null;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return bundle;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * 更新Bundle
|
||||||
|
// * @param {HUDM} HUDName HUD
|
||||||
|
// */
|
||||||
|
// public *UpdateBundle(HUDName: HUDM | string, onFileProgress?: (finish: number, total: number, item: string) => void): IterableIterator<any> {
|
||||||
|
// let HUD: HUDM;
|
||||||
|
// if (HUDName instanceof HUDM) {
|
||||||
|
// HUD = HUDName;
|
||||||
|
// } else {
|
||||||
|
// HUD = this.GetHUD(HUDName);
|
||||||
|
// }
|
||||||
|
// let UpdateingData: Enum_Loading.UpdateingDataObj = yield* HUD.HUD(onFileProgress);
|
||||||
|
// if (UpdateingData.IsUpdatecomplete) {
|
||||||
|
// this.LocalVerList[HUD.BundleName] = this.RemoteVerList[HUD.BundleName];
|
||||||
|
// this.LocalVerList[HUD.BundleName]["UseLocal"] = false;
|
||||||
|
// LocalStorageData.Instance.LocalVerList = JSON.stringify(this.LocalVerList);
|
||||||
|
// }
|
||||||
|
// return UpdateingData;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * 更新Bundle
|
||||||
|
// * @param {HUDM} HUDName HUD
|
||||||
|
// */
|
||||||
|
// public *RetryUpdateBundle(HUDName: HUDM | string, onFileProgress?: (finish: number, total: number, item: string) => void): IterableIterator<any> {
|
||||||
|
// let HUD: HUDM;
|
||||||
|
// if (HUDName instanceof HUDM) {
|
||||||
|
// HUD = HUDName;
|
||||||
|
// } else {
|
||||||
|
// HUD = this.GetHUD(HUDName);
|
||||||
|
// }
|
||||||
|
// let UpdateingData: Enum_Loading.UpdateingDataObj = yield* HUD.RetryDownLoadFailedAssets();
|
||||||
|
// return UpdateingData;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * 從Bundle取得資源
|
||||||
|
// * @param {cc.AssetManager.Bundle | string} BundleName Bundle名稱
|
||||||
|
// * @param {string} SourceName 資源名稱
|
||||||
|
// * @param {string} type 資源型別
|
||||||
|
// * @return {any} Source
|
||||||
|
// */
|
||||||
|
// public *GetBundleSource(BundleName: cc.AssetManager.Bundle | string, SourceName: string, type?: string | Bundle_Source_Type, onFileProgress?: (finish: number, total: number, item: cc.AssetManager.RequestItem) => void): IterableIterator<any> {
|
||||||
|
// let bundle: cc.AssetManager.Bundle;
|
||||||
|
// let source: any;
|
||||||
|
// if (BundleName instanceof cc.AssetManager.Bundle) {
|
||||||
|
// bundle = BundleName;
|
||||||
|
// } else {
|
||||||
|
// bundle = cc.assetManager.getBundle(BundleName);
|
||||||
|
// if (!bundle) {
|
||||||
|
// cc.error(`GetBundleSource Error BundleName: ${BundleName}`);
|
||||||
|
// return null;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// switch (type) {
|
||||||
|
// case Bundle_Source_Type.Scene: {
|
||||||
|
// bundle.loadScene(SourceName, onFileProgress, function (err: Error, scene: cc.SceneAsset): void {
|
||||||
|
// if (err) {
|
||||||
|
// cc.error(err);
|
||||||
|
// return null;
|
||||||
|
// }
|
||||||
|
// // cc.director.runScene(scene);
|
||||||
|
// source = scene;
|
||||||
|
// });
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// case Bundle_Source_Type.Json: {
|
||||||
|
// bundle.load(SourceName, onFileProgress, function (err: Error, json: cc.JsonAsset): void {
|
||||||
|
// if (err) {
|
||||||
|
// cc.error(err);
|
||||||
|
// return null;
|
||||||
|
// }
|
||||||
|
// // source = JSON.parse(json["_nativeAsset"]);
|
||||||
|
// source = json;
|
||||||
|
// });
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// case Bundle_Source_Type.Prefab: {
|
||||||
|
// bundle.load(SourceName, cc.Prefab, onFileProgress, function (err: Error, prefab: cc.Asset): void {
|
||||||
|
// if (err) {
|
||||||
|
// cc.error(err);
|
||||||
|
// return null;
|
||||||
|
// }
|
||||||
|
// // source = JSON.parse(json["_nativeAsset"]);
|
||||||
|
// source = prefab;
|
||||||
|
// });
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// default:
|
||||||
|
// bundle.load(SourceName, function (err: Error, any: any): void {
|
||||||
|
// if (err) {
|
||||||
|
// cc.error(err);
|
||||||
|
// return null;
|
||||||
|
// }
|
||||||
|
// source = any;
|
||||||
|
// });
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// while (typeof source === "undefined") {
|
||||||
|
// yield null;
|
||||||
|
// }
|
||||||
|
// return source;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * 釋放Bundle
|
||||||
|
// * @param {string} slotID slotID
|
||||||
|
// */
|
||||||
|
// public *BundleRelease(slotID: number): IterableIterator<any> {
|
||||||
|
// let gameName: string = `Game_${slotID}`;
|
||||||
|
// let sceneName: string = `Slot${slotID}`;
|
||||||
|
// let bundle: cc.AssetManager.Bundle = cc.assetManager.getBundle(gameName);
|
||||||
|
// if (!bundle) {
|
||||||
|
// cc.log(`BundleRelease Error BundleName: ${gameName}`);
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // let bundles: cc.AssetManager.Cache<cc.AssetManager.Bundle> = cc.assetManager.bundles;
|
||||||
|
// // let cacheDir: string = cc.assetManager.cacheManager.cacheDir;
|
||||||
|
// // let cachedFiles: Object = cc.assetManager.cacheManager.cachedFiles;
|
||||||
|
|
||||||
|
// yield* this.DelBundleCache(bundle);
|
||||||
|
// yield* this.DelOthersCache(slotID);
|
||||||
|
// bundle.release(sceneName, cc.SceneAsset);
|
||||||
|
// cc.assetManager.removeBundle(bundle);
|
||||||
|
// cc.sys.garbageCollect();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * 從Bundle刪除暫存資源
|
||||||
|
// * @param {string} BundleName Bundle名稱
|
||||||
|
// */
|
||||||
|
// public *DelBundleCache(BundleName: cc.AssetManager.Bundle | string): IterableIterator<any> {
|
||||||
|
// if (!CC_JSB) {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// let bundle: cc.AssetManager.Bundle;
|
||||||
|
// let source: any;
|
||||||
|
// if (BundleName instanceof cc.AssetManager.Bundle) {
|
||||||
|
// bundle = BundleName;
|
||||||
|
// } else {
|
||||||
|
// bundle = cc.assetManager.getBundle(BundleName);
|
||||||
|
// if (!bundle) {
|
||||||
|
// // cc.error(`GetBundleSource Error BundleName: ${BundleName}`);
|
||||||
|
// // return;
|
||||||
|
// bundle = yield* AssetBundleMamager.Instance.GetBundle(BundleName, this.RemoteVerList[BundleName].Version);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// let _map: Object = bundle["_config"].assetInfos._map;
|
||||||
|
// for (let map of Object.keys(_map)) {
|
||||||
|
// let path: string = _map[map].path;
|
||||||
|
// if (!path) {
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// source = yield* AssetBundleMamager.Instance.GetBundleSource(bundle, path);
|
||||||
|
// cc.assetManager.cacheManager.removeCache(source.nativeUrl);
|
||||||
|
// bundle.release(path);
|
||||||
|
// // return;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * 從cachedFiles刪除暫存資源
|
||||||
|
// * @param {number} slotID slotID
|
||||||
|
// */
|
||||||
|
// public *DelOthersCache(slotID: number): IterableIterator<any> {
|
||||||
|
// if (!CC_JSB) {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// let cachedFiles: Object = cc.assetManager.cacheManager.cachedFiles["_map"];
|
||||||
|
// let delcache_group: string[] = [`shared/jsons`, `Slot/Slot${slotID}`, "sounds/Slot/Default", `${BusinessTypeSetting.FolderUrlBundle}project.manifest`, "submit.txt"];
|
||||||
|
// for (let cached of Object.keys(cachedFiles)) {
|
||||||
|
// for (var i: number = 0; i < delcache_group.length; ++i) {
|
||||||
|
// let delcache: string = delcache_group[i];
|
||||||
|
// if (cached.includes(delcache)) {
|
||||||
|
// cc.assetManager.cacheManager.removeCache(cached);
|
||||||
|
// // console.log(`removeCache: ${cached}`);
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public GetHUD(BundleName: HUDM | string): HUDM {
|
||||||
|
// let HUD: HUDM;
|
||||||
|
// if (BundleName instanceof HUDM) {
|
||||||
|
// HUD = BundleName;
|
||||||
|
// } else {
|
||||||
|
// if (!this.HUGroup.has(BundleName)) {
|
||||||
|
// HUD = new HUDM(BundleName);
|
||||||
|
// this.HUGroup.set(BundleName, HUD);
|
||||||
|
// } else {
|
||||||
|
// HUD = this.HUGroup.get(BundleName);
|
||||||
|
// }
|
||||||
|
// HUD = this.HUGroup.get(BundleName);
|
||||||
|
// }
|
||||||
|
// return HUD;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /** 刪除全部暫存資源 */
|
||||||
|
// public ClearAllCache(): void {
|
||||||
|
// cc.assetManager.cacheManager.clearCache();
|
||||||
|
// cc.game.restart();
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
// public *CheckBundleNeedHUD(BundleName: HUDM | string): IterableIterator<Enum_Loading.NeedUpdateDataObj> {
|
||||||
|
// let HUD: HUDM;
|
||||||
|
// if (BundleName instanceof HUDM) {
|
||||||
|
// HUD = BundleName;
|
||||||
|
// } else {
|
||||||
|
// HUD = this.GetHUD(BundleName);
|
||||||
|
// }
|
||||||
|
// if (!this.LocalVerList[HUD.BundleName]) {
|
||||||
|
// this.LocalVerList[HUD.BundleName] = new Enum_Loading.BundleDataObj();
|
||||||
|
// let apkVersion: string = this.RemoteVerList[HUD.BundleName].ApkVersion;
|
||||||
|
// if (apkVersion && apkVersion !== "0") {
|
||||||
|
// this.LocalVerList[HUD.BundleName].UseLocal = true;
|
||||||
|
// this.LocalVerList[HUD.BundleName].Version = apkVersion;
|
||||||
|
// }
|
||||||
|
// LocalStorageData.Instance.LocalVerList = JSON.stringify(this.LocalVerList);
|
||||||
|
// } else {
|
||||||
|
// if (this.RemoteVerList[HUD.BundleName].Version === this.RemoteVerList[HUD.BundleName].ApkVersion) {
|
||||||
|
// this.LocalVerList[HUD.BundleName] = this.RemoteVerList[HUD.BundleName];
|
||||||
|
// this.LocalVerList[HUD.BundleName].UseLocal = true;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// let UpdateData: Enum_Loading.NeedUpdateDataObj = new Enum_Loading.NeedUpdateDataObj();
|
||||||
|
// if (this.LocalVerList[HUD.BundleName].UseLocal) {
|
||||||
|
// UpdateData.IsNeedUpdate = AssetBundleMamager.Instance.versionCompareHandle(this.LocalVerList[HUD.BundleName].Version, this.RemoteVerList[HUD.BundleName].Version) < 0 ? true : false;
|
||||||
|
// if (UpdateData.IsNeedUpdate) {
|
||||||
|
// UpdateData = yield* HUD.CheckUpdate();
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// UpdateData = yield* HUD.CheckUpdate();
|
||||||
|
// }
|
||||||
|
// return UpdateData;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // public *CheckBundleNeedHUD(BundleName: string): IterableIterator<boolean> {
|
||||||
|
// // if (!this.LocalVerList[BundleName]) {
|
||||||
|
// // this.LocalVerList[BundleName] = new Enum_Loading.BundleDataObj();
|
||||||
|
// // let apkVersion: string = this.RemoteVerList[BundleName].ApkVersion;
|
||||||
|
// // if (apkVersion && apkVersion !== "0") {
|
||||||
|
// // this.LocalVerList[BundleName].UseLocal = true;
|
||||||
|
// // this.LocalVerList[BundleName].Version = apkVersion;
|
||||||
|
// // }
|
||||||
|
// // LocalStorageData.Instance.LocalVerList = JSON.stringify(this.LocalVerList);
|
||||||
|
// // }
|
||||||
|
// // let IsUpdate: boolean = AssetBundleMamager.Instance.versionCompareHandle(this.LocalVerList[BundleName].Version, this.RemoteVerList[BundleName].Version) < 0 ? true : false;
|
||||||
|
// // return IsUpdate;
|
||||||
|
// // }
|
||||||
|
|
||||||
|
// public CheckGameNeedUpdate(GameID: number): boolean {
|
||||||
|
// let IsUpdate: boolean = false;
|
||||||
|
// let bundleName: string = `Game_${GameID}`;
|
||||||
|
// if (!this.RemoteVerList[bundleName]) {
|
||||||
|
// this.RemoteVerList[bundleName] = new Enum_Loading.BundleDataObj();
|
||||||
|
// this.RemoteVerList[bundleName].HasBundle = false;
|
||||||
|
// LocalStorageData.Instance.RemoteVerList = JSON.stringify(this.RemoteVerList);
|
||||||
|
// IsUpdate = true;
|
||||||
|
// }
|
||||||
|
// if (!this.LocalVerList[bundleName]) {
|
||||||
|
// this.LocalVerList[bundleName] = new Enum_Loading.BundleDataObj();
|
||||||
|
// let apkVersion: string = this.RemoteVerList[bundleName].ApkVersion;
|
||||||
|
// if (apkVersion && apkVersion !== "0") {
|
||||||
|
// this.LocalVerList[bundleName].UseLocal = true;
|
||||||
|
// this.LocalVerList[bundleName].Version = apkVersion;
|
||||||
|
// }
|
||||||
|
// LocalStorageData.Instance.LocalVerList = JSON.stringify(this.LocalVerList);
|
||||||
|
// }
|
||||||
|
// if (CC_PREVIEW) {
|
||||||
|
// return this._getIsDownload_Preview(GameID);
|
||||||
|
// }
|
||||||
|
// if (IsUpdate) {
|
||||||
|
// return IsUpdate;
|
||||||
|
// }
|
||||||
|
// IsUpdate = AssetBundleMamager.Instance.versionCompareHandle(this.LocalVerList[bundleName].Version, this.RemoteVerList[bundleName].Version) < 0 ? true : false;
|
||||||
|
// return IsUpdate;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * 比對版號(熱更能從1.0.0更新到2.0.0,從2.0.0回退到1.0.0)
|
||||||
|
// * 官方提供的版本比較函數,只有服務端版本>客戶端版本時,才會進行更新。所以不能從2.0.0回退到1.0.0版本。
|
||||||
|
// * @param {string} versionA 本地版號
|
||||||
|
// * @param {string} versionB 遠程版號
|
||||||
|
// * @return {number} num = -1 須更新
|
||||||
|
// * @return {number} num = 0 不須更新
|
||||||
|
// */
|
||||||
|
// public versionCompareHandle(versionA: string, versionB: string): number {
|
||||||
|
// // console.log("Ver A " + versionA + "VerB " + versionB);
|
||||||
|
// var vA: string[] = versionA.split(".");
|
||||||
|
// var vB: string[] = versionB.split(".");
|
||||||
|
|
||||||
|
// // 長度不相等,則進行更新
|
||||||
|
// if (vA.length !== vB.length) {
|
||||||
|
// return -1;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// for (var i: number = 0; i < vA.length; ++i) {
|
||||||
|
// var a: number = +vA[i];
|
||||||
|
// var b: number = +vB[i] || 0;
|
||||||
|
// if (a === b) {
|
||||||
|
// // 數字相同,則跳過
|
||||||
|
// continue;
|
||||||
|
// } else {
|
||||||
|
// // 數字不同,則進行更新
|
||||||
|
// return -1;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // 長度相等且數字相等,則不更新
|
||||||
|
// return 0;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// //#endregion
|
||||||
|
|
||||||
|
// //#region DownloadList_Preview
|
||||||
|
|
||||||
|
// private _initdownloadList_Preview(): void {
|
||||||
|
// this.DownloadList_Preview = JSON.parse(LocalStorageData.Instance.DownloadList_Preview);
|
||||||
|
// this.DownloadList_Preview = this.DownloadList_Preview ? this.DownloadList_Preview : {};
|
||||||
|
// }
|
||||||
|
|
||||||
|
// private _getIsDownload_Preview(slotID: number): boolean {
|
||||||
|
// if (!this.DownloadList_Preview[slotID]) {
|
||||||
|
// this.SetIsDownload_Preview(slotID, false);
|
||||||
|
// }
|
||||||
|
// return !this.DownloadList_Preview[slotID];
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public SetIsDownload_Preview(slotID: number, isDownload: boolean = true): void {
|
||||||
|
// this.DownloadList_Preview[slotID] = isDownload;
|
||||||
|
// LocalStorageData.Instance.DownloadList_Preview = JSON.stringify(this.DownloadList_Preview);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// //#endregion
|
||||||
|
// }
|
||||||
|
|
||||||
|
// //#region enum
|
||||||
|
|
||||||
|
// /** Bundle資源類型 */
|
||||||
|
// export enum Bundle_Source_Type {
|
||||||
|
// /** Json */
|
||||||
|
// Json = "json",
|
||||||
|
|
||||||
|
// /** Scene */
|
||||||
|
// Scene = "scene",
|
||||||
|
|
||||||
|
// /** Prefab */
|
||||||
|
// Prefab = "prefab"
|
||||||
|
// }
|
||||||
|
|
||||||
|
// //#endregion
|
||||||
|
|
||||||
|
// //#region 廢棄 Function
|
||||||
|
|
||||||
|
// // /**
|
||||||
|
// // * 從Bundle刪除暫存資源
|
||||||
|
// // * @param {string} BundleName Bundle名稱
|
||||||
|
// // */
|
||||||
|
// // public *DelBundleCache(BundleName: cc.AssetManager.Bundle | string): IterableIterator<any> {
|
||||||
|
// // if (!CC_JSB) {
|
||||||
|
// // return;
|
||||||
|
// // }
|
||||||
|
// // let WritablePath: string = `${jsb.fileUtils.getWritablePath()}gamecaches/${BundleName}`;
|
||||||
|
// // if (jsb.fileUtils.isDirectoryExist(WritablePath)) {
|
||||||
|
// // jsb.fileUtils.removeDirectory(WritablePath);
|
||||||
|
// // }
|
||||||
|
// // }
|
||||||
|
|
||||||
|
// //#endregion
|
72
assets/Script/HUD/Enum_HUDM.ts
Normal file
72
assets/Script/HUD/Enum_HUDM.ts
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
const { ccclass, property } = cc._decorator;
|
||||||
|
export module Enum_HUDM {
|
||||||
|
|
||||||
|
//#region Enum
|
||||||
|
|
||||||
|
//#endregion
|
||||||
|
|
||||||
|
//#region Class
|
||||||
|
|
||||||
|
// /** BaseBundle資料 */
|
||||||
|
// @ccclass("BaseBundleObj")
|
||||||
|
// export class BaseBundleObj {
|
||||||
|
// @property({ displayName: "Bundle名稱", tooltip: "Bundle名稱" })
|
||||||
|
// public BundleName: string = "";
|
||||||
|
|
||||||
|
// @property({ displayName: "優先度", tooltip: "優先度", type: cc.Integer })
|
||||||
|
// public Priority: number = 1;
|
||||||
|
// }
|
||||||
|
|
||||||
|
class BundleDictionary<T> {
|
||||||
|
[x: string]: T;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** VerList資料 */
|
||||||
|
@ccclass("VerListObj")
|
||||||
|
export class VerListObj extends BundleDictionary<BundleDataObj> {
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Bundle資料 */
|
||||||
|
@ccclass("BundleDataObj")
|
||||||
|
export class BundleDataObj {
|
||||||
|
public Version: string = "0";
|
||||||
|
|
||||||
|
public ApkVersion: string = "0";
|
||||||
|
|
||||||
|
public UseLocal: boolean = false;
|
||||||
|
|
||||||
|
/** 有沒有包到Bundle */
|
||||||
|
public HasBundle: boolean = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Bundle資料 */
|
||||||
|
@ccclass("NeedUpdateDataObj")
|
||||||
|
export class NeedUpdateDataObj {
|
||||||
|
|
||||||
|
/** 是否需要更新 */
|
||||||
|
public IsNeedUpdate: boolean;
|
||||||
|
|
||||||
|
/** 更新大小 */
|
||||||
|
public TotalBytes: string;
|
||||||
|
|
||||||
|
constructor(...params: any[]) {
|
||||||
|
this.IsNeedUpdate = params[0];
|
||||||
|
this.TotalBytes = params[1] ? params[1] : null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Bundle資料 */
|
||||||
|
@ccclass("UpdateingDataObj")
|
||||||
|
export class UpdateingDataObj {
|
||||||
|
|
||||||
|
/** 是否更新完成 */
|
||||||
|
public IsUpdatecomplete: boolean;
|
||||||
|
|
||||||
|
constructor(...params: any[]) {
|
||||||
|
this.IsUpdatecomplete = params[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//#endregion
|
||||||
|
}
|
||||||
|
export default Enum_HUDM;
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"ver": "1.1.0",
|
"ver": "1.1.0",
|
||||||
"uuid": "e85368d6-e018-430e-bf1d-6ecd2973c6a8",
|
"uuid": "7217469f-9c06-46fd-be21-69020675c24d",
|
||||||
"importer": "typescript",
|
"importer": "typescript",
|
||||||
"isPlugin": false,
|
"isPlugin": false,
|
||||||
"loadPluginInWeb": true,
|
"loadPluginInWeb": true,
|
448
assets/Script/HUD/HUDM.ts
Normal file
448
assets/Script/HUD/HUDM.ts
Normal file
@ -0,0 +1,448 @@
|
|||||||
|
import { CoroutineV2 } from "../Engine/CatanEngine/CoroutineV2/CoroutineV2";
|
||||||
|
import LocalStorageData from "../Engine/Data/LocalStorageData";
|
||||||
|
import UpdatePanel from "../UpdatePanel";
|
||||||
|
import BusinessTypeSetting from "../_BusinessTypeSetting/BusinessTypeSetting";
|
||||||
|
import Enum_HUDM from "./Enum_HUDM";
|
||||||
|
|
||||||
|
const { ccclass, property } = cc._decorator;
|
||||||
|
|
||||||
|
/** HUDManager */
|
||||||
|
@ccclass
|
||||||
|
export default class HUDM extends cc.Component {
|
||||||
|
|
||||||
|
//#region static 屬性
|
||||||
|
|
||||||
|
private static _instance: HUDM = null;
|
||||||
|
public static get Instance(): HUDM { return HUDM._instance; }
|
||||||
|
|
||||||
|
//#endregion
|
||||||
|
|
||||||
|
//#region private 屬性
|
||||||
|
|
||||||
|
private _updatePanel: UpdatePanel;
|
||||||
|
private _am: jsb.AssetsManager;
|
||||||
|
private _onFileProgress: (finish: number, total: number, item: string) => void;
|
||||||
|
private _updateListener: any;
|
||||||
|
private _checkListener: any;
|
||||||
|
private _versionCompareHandle: any = null;
|
||||||
|
private _needUpdateData: Enum_HUDM.NeedUpdateDataObj = null;
|
||||||
|
private _updateingData: Enum_HUDM.UpdateingDataObj = null;
|
||||||
|
private _updating: boolean = false;
|
||||||
|
private _canRetry: boolean = false;
|
||||||
|
private _isChangeUrl: boolean = false;
|
||||||
|
private _isNewBundle: boolean = false;
|
||||||
|
private _path: string = "Bundle";
|
||||||
|
private _customManifest: string = "";
|
||||||
|
private _storagePath: string = "";
|
||||||
|
|
||||||
|
//#endregion
|
||||||
|
|
||||||
|
//#region Lifecycle
|
||||||
|
|
||||||
|
constructor(...params: any[]) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
if (!cc.sys.isNative) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
HUDM._instance = this;
|
||||||
|
this._updatePanel = params[0];
|
||||||
|
this._isNewBundle = params[1];
|
||||||
|
// let packageUrl: string = `https://jianmiau.tk/Resources/App/JMKA/update/remote-assets/${BusinessTypeSetting.COMPILE_VERSION}`;
|
||||||
|
let packageUrl: string = BusinessTypeSetting.UsePatch;
|
||||||
|
|
||||||
|
this.CheckCompileVersion();
|
||||||
|
this.CheckChangePatchUrl();
|
||||||
|
|
||||||
|
this._customManifest = JSON.stringify({
|
||||||
|
"packageUrl": packageUrl,
|
||||||
|
"remoteManifestUrl": `${packageUrl}/project.manifest`,
|
||||||
|
"remoteVersionUrl": `${packageUrl}/version.json`,
|
||||||
|
"version": "0.0.0",
|
||||||
|
});
|
||||||
|
|
||||||
|
this._storagePath = `${(jsb.fileUtils ? jsb.fileUtils.getWritablePath() : "./")}${this._path}`;
|
||||||
|
|
||||||
|
// 本地熱更目錄下已存在project.manifest,則直接修改已存在的project.manifest
|
||||||
|
if (this._isChangeUrl) {
|
||||||
|
if (jsb.fileUtils.isFileExist(this._storagePath + "/project.manifest")) {
|
||||||
|
this._isChangeUrl = true;
|
||||||
|
this._modifyAppLoadUrlForManifestFile(this._storagePath, packageUrl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this._versionCompareHandle = function (versionA: string, versionB: string): number {
|
||||||
|
// console.log("Ver A " + versionA + "VerB " + versionB);
|
||||||
|
let vA: string[] = versionA.split(".");
|
||||||
|
let vB: string[] = versionB.split(".");
|
||||||
|
|
||||||
|
// 長度不相等,則進行更新
|
||||||
|
if (vA.length !== vB.length) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i: number = 0; i < vA.length; ++i) {
|
||||||
|
let a: number = +vA[i];
|
||||||
|
let b: number = +vB[i] || 0;
|
||||||
|
if (a === b) {
|
||||||
|
// 數字相同,則跳過
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
// 數字不同,則進行更新
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 長度相等且數字相等,則不更新
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
this._initAssetManaget();
|
||||||
|
}
|
||||||
|
private _initAssetManaget(): void {
|
||||||
|
let self: this = this;
|
||||||
|
//
|
||||||
|
this._am = new jsb.AssetsManager("", this._storagePath, this._versionCompareHandle);
|
||||||
|
|
||||||
|
// Setup the verification callback, but we don't have md5 check function yet, so only print some message
|
||||||
|
// Return true if the verification passed, otherwise return false
|
||||||
|
this._am.setVerifyCallback(function (path: any, asset: { compressed: any; md5: any; path: any; size: any; }): boolean {
|
||||||
|
// When asset is compressed, we don't need to check its md5, because zip file have been deleted.
|
||||||
|
let compressed: any = asset.compressed;
|
||||||
|
// Retrieve the correct md5 value.
|
||||||
|
let expectedMD5: string = asset.md5;
|
||||||
|
// asset.path is relative path and path is absolute.
|
||||||
|
let relativePath: string = asset.path;
|
||||||
|
// The size of asset file, but this value could be absent.
|
||||||
|
let size: any = asset.size;
|
||||||
|
if (compressed) {
|
||||||
|
self._updatePanel.info.string = "Verification passed : " + relativePath;
|
||||||
|
// console.log("onLoad -> Verification passed : " + relativePath);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
self._updatePanel.info.string = "Verification passed : " + relativePath + " (" + expectedMD5 + ")";
|
||||||
|
// console.log("onLoad -> setVerifyCallbackVerification passed : " + relativePath + " (" + expectedMD5 + ")");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (cc.sys.os === cc.sys.OS_ANDROID) {
|
||||||
|
// Some Android device may slow down the download process when concurrent tasks is too much.
|
||||||
|
// The value may not be accurate, please do more test and find what's most suitable for your game.
|
||||||
|
// this._am.setMaxConcurrentTask(10);
|
||||||
|
this._am["setMaxConcurrentTask"](10);
|
||||||
|
// this._updatePanel.info.string = "Max concurrent tasks count have been limited to 2";
|
||||||
|
// console.log("onLoad -> Max concurrent tasks count have been limited to 10");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private _modifyAppLoadUrlForManifestFile(filePath: string, newBundleUrl: string): void {
|
||||||
|
let allpath: string[] = [filePath, filePath + "_temp"];
|
||||||
|
let manifestname: string[] = ["project.manifest", "project.manifest.temp"];
|
||||||
|
for (var i: number = 0; i < allpath.length; ++i) {
|
||||||
|
let path: string = `${allpath[i]}/${manifestname[i]}`;
|
||||||
|
if (jsb.fileUtils.isFileExist(path)) {
|
||||||
|
// console.log(`[HUD] modifyAppLoadUrlForManifestFile: 有下載的manifest文件,直接修改熱更地址`);
|
||||||
|
// 修改project.manifest
|
||||||
|
let projectManifest: string = jsb.fileUtils.getStringFromFile(path);
|
||||||
|
let projectManifestObj: any = JSON.parse(projectManifest);
|
||||||
|
projectManifestObj.packageUrl = newBundleUrl;
|
||||||
|
projectManifestObj.remoteManifestUrl = newBundleUrl + "/project.manifest";
|
||||||
|
projectManifestObj.remoteVersionUrl = newBundleUrl + "/version.json";
|
||||||
|
let afterString: string = JSON.stringify(projectManifestObj);
|
||||||
|
jsb.fileUtils.writeStringToFile(afterString, path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//#endregion
|
||||||
|
|
||||||
|
public *CheckUpdate(): IterableIterator<any> {
|
||||||
|
this._needUpdateData = null;
|
||||||
|
if (this._updating) {
|
||||||
|
this._updatePanel.info.string = "Checking or updating ...";
|
||||||
|
console.error("checkUpdate -> Checking or updating ...");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._am.getState() === jsb.AssetsManager.State.UNINITED) {
|
||||||
|
let manifest: jsb.Manifest = new jsb.Manifest(this._customManifest, this._storagePath);
|
||||||
|
this._am.loadLocalManifest(manifest, this._storagePath);
|
||||||
|
}
|
||||||
|
if (!this._am.getLocalManifest() || !this._am.getLocalManifest().isLoaded()) {
|
||||||
|
// this.tipsLabel.string = "Failed to load local manifest ...";
|
||||||
|
console.error("checkUpdate -> Failed to load local manifest ...");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._am.setEventCallback(this.checkCb.bind(this));
|
||||||
|
|
||||||
|
this._am.checkUpdate();
|
||||||
|
this._updating = true;
|
||||||
|
|
||||||
|
while (this._needUpdateData === null) {
|
||||||
|
yield null;
|
||||||
|
}
|
||||||
|
|
||||||
|
let newBundleUrl: string = BusinessTypeSetting.UsePatch;
|
||||||
|
this._modifyAppLoadUrlForManifestFile(this._storagePath, newBundleUrl);
|
||||||
|
this._initAssetManaget();
|
||||||
|
|
||||||
|
let manifest: jsb.Manifest = new jsb.Manifest(this._customManifest, this._storagePath);
|
||||||
|
this._am.loadLocalManifest(manifest, this._storagePath);
|
||||||
|
if (!this._am.getLocalManifest() || !this._am.getLocalManifest().isLoaded()) {
|
||||||
|
// this.tipsLabel.string = "Failed to load local manifest ...";
|
||||||
|
console.error("checkUpdate -> Failed to load local manifest ...");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新動態路徑後再跑一次
|
||||||
|
this._am.setEventCallback(this.checkCb.bind(this));
|
||||||
|
|
||||||
|
this._needUpdateData = null;
|
||||||
|
this._am.checkUpdate();
|
||||||
|
this._updating = true;
|
||||||
|
while (this._needUpdateData === null) {
|
||||||
|
yield null;
|
||||||
|
}
|
||||||
|
if ((this._isChangeUrl || this._isNewBundle) && ((!this._needUpdateData.IsNeedUpdate && this._needUpdateData.TotalBytes !== "failed") || this._needUpdateData.TotalBytes === "0 B")) {
|
||||||
|
if (jsb.fileUtils.isFileExist(this._storagePath)) {
|
||||||
|
let isremoveDirectory: boolean = jsb.fileUtils.removeDirectory(this._storagePath);
|
||||||
|
let isremoveDirectory_temp: boolean = jsb.fileUtils.removeDirectory(this._storagePath + "_temp");
|
||||||
|
if (isremoveDirectory_temp) {
|
||||||
|
console.log(`removeDirectory: ${this._storagePath}_temp`);
|
||||||
|
}
|
||||||
|
if (isremoveDirectory) {
|
||||||
|
console.log(`removeDirectory: ${this._storagePath}`);
|
||||||
|
this._needUpdateData = null;
|
||||||
|
this._initAssetManaget();
|
||||||
|
this._needUpdateData = yield* this.CheckUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this._needUpdateData;
|
||||||
|
}
|
||||||
|
|
||||||
|
private checkCb(event: jsb.EventAssetsManager): void {
|
||||||
|
let failed: boolean = false;
|
||||||
|
switch (event.getEventCode()) {
|
||||||
|
case jsb.EventAssetsManager.ERROR_NO_LOCAL_MANIFEST:
|
||||||
|
console.error("checkCb -> No local manifest file found, HUD skipped.");
|
||||||
|
failed = true;
|
||||||
|
break;
|
||||||
|
case jsb.EventAssetsManager.ERROR_DOWNLOAD_MANIFEST:
|
||||||
|
case jsb.EventAssetsManager.ERROR_PARSE_MANIFEST:
|
||||||
|
console.error("checkCb -> Fail to download manifest file, HUD skipped.");
|
||||||
|
failed = true;
|
||||||
|
break;
|
||||||
|
case jsb.EventAssetsManager.ALREADY_UP_TO_DATE:
|
||||||
|
console.log("checkCb -> Already up to date with the latest remote version.");
|
||||||
|
this._needUpdateData = new Enum_HUDM.NeedUpdateDataObj(false);
|
||||||
|
break;
|
||||||
|
case jsb.EventAssetsManager.NEW_VERSION_FOUND:
|
||||||
|
this._updatePanel.checkBtn.active = false;
|
||||||
|
this._updatePanel.fileProgress.progress = 0;
|
||||||
|
this._updatePanel.byteProgress.progress = 0;
|
||||||
|
this._updatePanel.info.string = "發現新版本,請嘗試更新。 " + this._bytesToSize(event.getTotalBytes());
|
||||||
|
console.log("checkCb -> New version found, please try to update." + event.getTotalBytes());
|
||||||
|
this._needUpdateData = new Enum_HUDM.NeedUpdateDataObj(true, this._bytesToSize(event.getTotalBytes()));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._am.setEventCallback(null);
|
||||||
|
this._checkListener = null;
|
||||||
|
this._updating = false;
|
||||||
|
|
||||||
|
if (failed) {
|
||||||
|
this._needUpdateData = new Enum_HUDM.NeedUpdateDataObj(false, "failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public *HUD(onFileProgress?: (finish: number, total: number, item: string) => void): IterableIterator<any> {
|
||||||
|
this._updatePanel.updateBtn.active = false;
|
||||||
|
this._updateingData = null;
|
||||||
|
if (this._am && !this._updating) {
|
||||||
|
this._am.setEventCallback(this._updateCb.bind(this));
|
||||||
|
|
||||||
|
if (this._am.getState() === jsb.AssetsManager.State.UNINITED) {
|
||||||
|
let manifest: jsb.Manifest = new jsb.Manifest(this._customManifest, this._storagePath);
|
||||||
|
this._am.loadLocalManifest(manifest, this._storagePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
this._onFileProgress = onFileProgress ? onFileProgress : null;
|
||||||
|
this._am.update();
|
||||||
|
this._updating = true;
|
||||||
|
|
||||||
|
while (this._updateingData === null) {
|
||||||
|
yield null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this._updateingData;
|
||||||
|
} else {
|
||||||
|
return new Enum_HUDM.UpdateingDataObj(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private _updateCb(event: jsb.EventAssetsManager): void {
|
||||||
|
let self: this = this;
|
||||||
|
let needRestart: boolean = false;
|
||||||
|
let failed: boolean = false;
|
||||||
|
switch (event.getEventCode()) {
|
||||||
|
case jsb.EventAssetsManager.ERROR_NO_LOCAL_MANIFEST:
|
||||||
|
this._updatePanel.info.string = "No local manifest file found, HUD skipped.";
|
||||||
|
console.log("updateCb -> No local manifest file found, HUD skipped.");
|
||||||
|
failed = true;
|
||||||
|
break;
|
||||||
|
case jsb.EventAssetsManager.UPDATE_PROGRESSION:
|
||||||
|
this._updatePanel.byteProgress.progress = event.getPercent();
|
||||||
|
this._updatePanel.fileProgress.progress = event.getPercentByFile();
|
||||||
|
this._updatePanel.fileLabel.string = event.getDownloadedFiles() + " / " + event.getTotalFiles();
|
||||||
|
// this.tipsLabel.string = event.getDownloadedBytes() + " / " + event.getTotalBytes();
|
||||||
|
|
||||||
|
// console.log("updateCb -> " + event.getDownloadedBytes() + " / " + event.getTotalBytes());
|
||||||
|
// let msg: string = event.getMessage();
|
||||||
|
// if (msg) {
|
||||||
|
// this._updatePanel.info.string = 'Updated file: ' + msg;
|
||||||
|
// console.log("updateCb -> Updated file: " + msg);
|
||||||
|
// console.log("updateCb -> " + event.getPercent() / 100 + "% : " + msg);
|
||||||
|
// }
|
||||||
|
|
||||||
|
let msg: string = event.getMessage();
|
||||||
|
if (this._onFileProgress) {
|
||||||
|
this._onFileProgress(event.getDownloadedBytes(), event.getTotalBytes(), msg ? msg : "");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case jsb.EventAssetsManager.ERROR_DOWNLOAD_MANIFEST:
|
||||||
|
case jsb.EventAssetsManager.ERROR_PARSE_MANIFEST:
|
||||||
|
this._updatePanel.info.string = "Fail to download manifest file, HUD skipped.";
|
||||||
|
console.error("updateCb -> Fail to download manifest file, HUD skipped.");
|
||||||
|
failed = true;
|
||||||
|
break;
|
||||||
|
case jsb.EventAssetsManager.ALREADY_UP_TO_DATE:
|
||||||
|
this._updatePanel.info.string = "Already up to date with the latest remote version.";
|
||||||
|
console.error("updateCb -> Already up to date with the latest remote version.");
|
||||||
|
failed = true;
|
||||||
|
break;
|
||||||
|
case jsb.EventAssetsManager.UPDATE_FINISHED:
|
||||||
|
// this.tipsLabel.string = "更新完成. " + event.getMessage();
|
||||||
|
console.log("updateCb -> 更新完成. " + event.getMessage());
|
||||||
|
this._updateingData = new Enum_HUDM.UpdateingDataObj(true);
|
||||||
|
needRestart = true;
|
||||||
|
break;
|
||||||
|
case jsb.EventAssetsManager.UPDATE_FAILED:
|
||||||
|
this._updatePanel.info.string = "Update failed. " + event.getMessage();
|
||||||
|
console.error("updateCb -> Update failed. " + event.getMessage());
|
||||||
|
this._updatePanel.retryBtn.active = true;
|
||||||
|
this._canRetry = true;
|
||||||
|
this._updateingData = new Enum_HUDM.UpdateingDataObj(false);
|
||||||
|
this._updating = false;
|
||||||
|
break;
|
||||||
|
case jsb.EventAssetsManager.ERROR_UPDATING:
|
||||||
|
this._updatePanel.info.string = "Asset update error: " + event.getAssetId() + ", " + event.getMessage();
|
||||||
|
console.error("updateCb -> Asset update error: " + event.getAssetId() + ", " + event.getMessage());
|
||||||
|
break;
|
||||||
|
case jsb.EventAssetsManager.ERROR_DECOMPRESS:
|
||||||
|
this._updatePanel.info.string = event.getMessage();
|
||||||
|
console.error("updateCb -> " + event.getMessage());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (failed) {
|
||||||
|
this._am.setEventCallback(null);
|
||||||
|
this._updateListener = null;
|
||||||
|
this._updating = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (needRestart) {
|
||||||
|
let AsyncFunction: () => IterableIterator<any> = function* (): IterableIterator<any> {
|
||||||
|
self._updatePanel.info.string = "更新完成 即將重啟";
|
||||||
|
// 卡個一幀不然都看不到100%的畫面
|
||||||
|
yield CoroutineV2.WaitTime(5 / cc.game.getFrameRate()).Start();
|
||||||
|
|
||||||
|
self._am.setEventCallback(null);
|
||||||
|
self._updateListener = null;
|
||||||
|
// Prepend the manifest's search path
|
||||||
|
let searchPaths: string[] = jsb.fileUtils.getSearchPaths();
|
||||||
|
let newPaths: [string] = self._am.getLocalManifest().getSearchPaths();
|
||||||
|
console.log(JSON.stringify(newPaths));
|
||||||
|
Array.prototype.unshift.apply(searchPaths, newPaths);
|
||||||
|
// This value will be retrieved and appended to the default search path during game startup,
|
||||||
|
// please refer to samples/js-tests/main.js for detailed usage.
|
||||||
|
// !!! Re-add the search paths in main.js is very important, otherwise, new scripts won't take effect.
|
||||||
|
cc.sys.localStorage.setItem("HotUpdateSearchPaths", JSON.stringify(searchPaths));
|
||||||
|
jsb.fileUtils.setSearchPaths(searchPaths);
|
||||||
|
|
||||||
|
cc.audioEngine.stopAll();
|
||||||
|
cc.game.restart();
|
||||||
|
};
|
||||||
|
CoroutineV2.Single(AsyncFunction()).Start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public *RetryDownLoadFailedAssets(): IterableIterator<any> {
|
||||||
|
if (!this._updating && this._canRetry) {
|
||||||
|
this._updateingData = null;
|
||||||
|
this._updatePanel.retryBtn.active = false;
|
||||||
|
this._canRetry = false;
|
||||||
|
|
||||||
|
this._updatePanel.info.string = "Retry failed Assets...";
|
||||||
|
console.log("retry -> Retry failed Assets...");
|
||||||
|
this._am.downloadFailedAssets();
|
||||||
|
|
||||||
|
while (this._updateingData === null) {
|
||||||
|
yield null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this._updateingData;
|
||||||
|
} else {
|
||||||
|
console.error(`retry -> error updating: ${this._updating}, canRetry: ${this._canRetry}`);
|
||||||
|
this._updateingData = new Enum_HUDM.UpdateingDataObj(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private _bytesToSize(bytes: number): string {
|
||||||
|
if (bytes === 0) {
|
||||||
|
return "0 B";
|
||||||
|
}
|
||||||
|
let k: number = 1024;
|
||||||
|
let sizes: string[] = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
|
||||||
|
let i: number = Math.floor(Math.log(bytes) / Math.log(k));
|
||||||
|
return (bytes / Math.pow(k, i)).toPrecision(3) + " " + sizes[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected onDestroy(): void {
|
||||||
|
if (this._updateListener) {
|
||||||
|
this._am.setEventCallback(null);
|
||||||
|
this._updateListener = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//#region 清除資料
|
||||||
|
|
||||||
|
/** 判斷更改編譯版號.清除BUNDLE記錄 */
|
||||||
|
public CheckCompileVersion(): void {
|
||||||
|
let oldCompileVersion: string = LocalStorageData.Instance.CompileVersion;
|
||||||
|
let newCompileVersion: string = BusinessTypeSetting.COMPILE_VERSION;
|
||||||
|
if (oldCompileVersion && oldCompileVersion !== newCompileVersion) {
|
||||||
|
// this.ClearBundleData();
|
||||||
|
console.warn(`change compile version. ${oldCompileVersion} -> ${newCompileVersion}`);
|
||||||
|
}
|
||||||
|
LocalStorageData.Instance.CompileVersion = BusinessTypeSetting.COMPILE_VERSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 判斷更改PATCH環境.清除BUNDLE記錄 */
|
||||||
|
public CheckChangePatchUrl(): void {
|
||||||
|
let oldBundleUrl: string = LocalStorageData.Instance.BundleUrl;
|
||||||
|
let newBundleUrl: string = BusinessTypeSetting.UsePatch;
|
||||||
|
if (oldBundleUrl && oldBundleUrl !== newBundleUrl) {
|
||||||
|
// this.ClearBundleData();
|
||||||
|
console.warn(`change patch url. ${oldBundleUrl} -> ${newBundleUrl}`);
|
||||||
|
this._isChangeUrl = true;
|
||||||
|
}
|
||||||
|
LocalStorageData.Instance.BundleUrl = BusinessTypeSetting.UsePatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
//#endregion
|
||||||
|
}
|
@ -1,4 +1,17 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
node version_generator.js -v 1.0.0 -u https://jianmiau.tk/Resources/App/JMKA/update/remote-assets/ -s build/jsb-default/remote-assets -d remote-assets
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { CoroutineV2 } from "./Engine/CatanEngine/CoroutineV2/CoroutineV2";
|
||||||
|
import { System_Eevent } from "./Engine/CatanEngine/CSharp/System/System_Eevent";
|
||||||
|
import LocalStorageData from "./Engine/Data/LocalStorageData";
|
||||||
|
import { Enum_HUDM } from "./HUD/Enum_HUDM";
|
||||||
|
import HUDM from "./HUD/HUDM";
|
||||||
import NativeClass from "./NativeClass";
|
import NativeClass from "./NativeClass";
|
||||||
|
import UpdatePanel from "./UpdatePanel";
|
||||||
|
import BusinessTypeSetting from "./_BusinessTypeSetting/BusinessTypeSetting";
|
||||||
|
|
||||||
const { ccclass, property } = cc._decorator;
|
const { ccclass, property } = cc._decorator;
|
||||||
|
|
||||||
@ -12,25 +25,56 @@ export default class Manager extends cc.Component {
|
|||||||
@property({ type: cc.Node })
|
@property({ type: cc.Node })
|
||||||
public BG: cc.Node = null;
|
public BG: cc.Node = null;
|
||||||
|
|
||||||
//#endregion
|
@property({ type: cc.Node })
|
||||||
|
public UpdatePanel: cc.Node = null;
|
||||||
|
|
||||||
//#region private
|
@property({ type: cc.Label })
|
||||||
|
public Version: cc.Label = null;
|
||||||
// private _text_to_Speech: Text_to_Speech;
|
|
||||||
|
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
//#region Lifecycle
|
//#region Lifecycle
|
||||||
|
|
||||||
protected onLoad(): void {
|
protected onLoad(): void {
|
||||||
if (CC_DEBUG) {
|
CoroutineV2.Single(this._init()).Start();
|
||||||
console.log("Debug");
|
}
|
||||||
}
|
|
||||||
|
|
||||||
new NativeClass();
|
private *_init(): IterableIterator<any> {
|
||||||
|
new LocalStorageData();
|
||||||
|
let isNewBundle: boolean = yield* this.CheckBundleVersion();
|
||||||
|
console.log(`BUNDLE VERSION: ${LocalStorageData.Instance.BundleVersion}`);
|
||||||
|
console.log(`COMPILE VERSION: ${BusinessTypeSetting.COMPILE_VERSION}`);
|
||||||
|
this.Version.string = `Ver ${BusinessTypeSetting.COMPILE_VERSION}`;
|
||||||
|
BusinessTypeSetting.UsePatch = `https://jianmiau.tk/Resources/App/JMKA/update/remote-assets/${BusinessTypeSetting.MajorVersion}.${BusinessTypeSetting.MinorVersion}`;
|
||||||
|
cc.debug.setDisplayStats(false);
|
||||||
|
|
||||||
|
new NativeClass(this.webview);
|
||||||
|
if (cc.sys.isNative && isNewBundle) {
|
||||||
|
new HUDM(this.UpdatePanel.getComponentInChildren(UpdatePanel), isNewBundle);
|
||||||
|
let needUpdateData: Enum_HUDM.NeedUpdateDataObj = yield* HUDM.Instance.CheckUpdate();
|
||||||
|
if (needUpdateData.IsNeedUpdate) {
|
||||||
|
this.UpdatePanel.active = true;
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
this.UpdatePanel.active = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let self: this = this;
|
let self: this = this;
|
||||||
// this._text_to_Speech = new Text_to_Speech();
|
// this._text_to_Speech = new Text_to_Speech();
|
||||||
|
let href: string = window.location.href;
|
||||||
|
|
||||||
|
// let url: string = `http://220.134.195.1/public/bonus_casino/html5/jianmiau/Test/?host=${href}&v=${Date.now()}`;
|
||||||
|
// let url: string = `https://karolchang.github.io/jm-expense-vue-ts/?host=${href}&ignore=${Date.now()}`;
|
||||||
|
// let url: string = `http://karol.jianmiau.cf/jm-expense-vue-ts/?v=${Date.now()}`;
|
||||||
|
let url: string = `https://jm-expense-2022.firebaseapp.com/login?host=${href}&v=${Date.now()}`;
|
||||||
|
this.webview.url = url;
|
||||||
|
this.webview.node.active = true;
|
||||||
|
|
||||||
|
cc.view.setResizeCallback(this._resize.bind(this));
|
||||||
|
this._resize();
|
||||||
|
|
||||||
|
// Set EventListener
|
||||||
window.addEventListener("message", function (e: MessageEvent<any>): void {
|
window.addEventListener("message", function (e: MessageEvent<any>): void {
|
||||||
let data: any = e.data;
|
let data: any = e.data;
|
||||||
let method: string = data.method;
|
let method: string = data.method;
|
||||||
@ -47,28 +91,19 @@ export default class Manager extends cc.Component {
|
|||||||
}
|
}
|
||||||
let scheme: string = "jmka";
|
let scheme: string = "jmka";
|
||||||
this.webview.setJavascriptInterfaceScheme(scheme);
|
this.webview.setJavascriptInterfaceScheme(scheme);
|
||||||
this.webview.setOnJSCallback((sender, url) => {
|
this.webview.setOnJSCallback((sender: any, url: any) => {
|
||||||
let data: JSON = JSON.parse(decodeURI(url.split(`${scheme}://`)[1]));
|
let content: string = decodeURI(url.split(`${scheme}://?data=`)[1]);
|
||||||
let method: any = data["method"];
|
try {
|
||||||
let value: any = data["value"];
|
let data: JSON = JSON.parse(content);
|
||||||
if (method) {
|
let method: any = data["method"];
|
||||||
self.Birdge(method, ...value);
|
let value: any = data["value"];
|
||||||
|
if (method) {
|
||||||
|
self.Birdge(method, ...value);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
let href: string = window.location.href;
|
|
||||||
|
|
||||||
// let url: string = `http://220.134.195.1/public/bonus_casino/html5/jianmiau/Test/?host=${href}&v=${Date.now()}`;
|
|
||||||
// let url: string = `https://karolchang.github.io/jm-expense-vue-ts/?host=${href}&ignore=${Date.now()}`;
|
|
||||||
// let url: string = `http://karol.jianmiau.cf/jm-expense-vue-ts/?v=${Date.now()}`;
|
|
||||||
let url: string = `https://jm-expense-2022.firebaseapp.com/login?host=${href}&v=${Date.now()}`;
|
|
||||||
this.webview.url = url;
|
|
||||||
this.webview.node.active = true;
|
|
||||||
|
|
||||||
cc.view.setResizeCallback(this._resize.bind(this));
|
|
||||||
this._resize();
|
|
||||||
|
|
||||||
const FCMToken: string = NativeClass.Instance.GetFCMToken();
|
|
||||||
console.log(`FCMToken ${FCMToken}`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 跨版本溝通
|
/** 跨版本溝通
|
||||||
@ -102,6 +137,21 @@ export default class Manager extends cc.Component {
|
|||||||
NativeClass.Instance.TTS_Play(msg);
|
NativeClass.Instance.TTS_Play(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public onLoadOK(): void {
|
||||||
|
CoroutineV2.Single(this.GetFCMToken()).Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public *GetFCMToken(): IterableIterator<any> {
|
||||||
|
const FCMToken: string = NativeClass.Instance.GetFCMToken();
|
||||||
|
if (cc.sys.os === cc.sys.OS_IOS && !FCMToken) {
|
||||||
|
yield CoroutineV2.WaitTime(1);
|
||||||
|
yield this.GetFCMToken();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log(`FCMToken ${FCMToken}`);
|
||||||
|
NativeClass.Instance.CocosBridge(System_Eevent.SetFCMToken, `"${FCMToken}"`);
|
||||||
|
}
|
||||||
|
|
||||||
public Alert(msg: string): void {
|
public Alert(msg: string): void {
|
||||||
alert(msg);
|
alert(msg);
|
||||||
}
|
}
|
||||||
@ -133,5 +183,65 @@ export default class Manager extends cc.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 判斷更改Bundle版號.清除BUNDLE記錄 */
|
||||||
|
public *CheckBundleVersion(): IterableIterator<any> {
|
||||||
|
let isNewBundle: boolean = false;
|
||||||
|
let remote_version: string = "0";
|
||||||
|
let versionLoadEnd: boolean = false;
|
||||||
|
let fileName: string = "BundleVersion";
|
||||||
|
let fileFormat: string = ".txt";
|
||||||
|
let fileVersion: string = `?v=${Date.now()}`;
|
||||||
|
let fileUrl: string = `https://jianmiau.tk/Resources/App/JMKA/update/remote-assets/${fileName}${fileFormat}${fileVersion}`;
|
||||||
|
cc.assetManager.loadRemote(fileUrl, (err: Error, res: cc.TextAsset) => {
|
||||||
|
if (!err) {
|
||||||
|
remote_version = res.text;
|
||||||
|
versionLoadEnd = true;
|
||||||
|
console.log(`${fileName}.txt loaded`);
|
||||||
|
} else {
|
||||||
|
console.error(`[Error] ${fileName}載入失敗`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
while (!versionLoadEnd) {
|
||||||
|
yield null;
|
||||||
|
}
|
||||||
|
let oldBundleVersion: string = LocalStorageData.Instance.BundleVersion || "0.0.0";
|
||||||
|
let newBundleVersion: string = remote_version;
|
||||||
|
if (oldBundleVersion) {
|
||||||
|
let IsUpdate: boolean = this.VersionCompareHandle(oldBundleVersion, newBundleVersion) < 0 ? true : false;
|
||||||
|
if (IsUpdate) {
|
||||||
|
console.warn(`change bundle version. ${oldBundleVersion} -> ${newBundleVersion}`);
|
||||||
|
isNewBundle = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LocalStorageData.Instance.BundleVersion = newBundleVersion;
|
||||||
|
return isNewBundle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public VersionCompareHandle(versionA: string, versionB: string): number {
|
||||||
|
// console.log("Ver A " + versionA + "VerB " + versionB);
|
||||||
|
let vA: string[] = versionA.split(".");
|
||||||
|
let vB: string[] = versionB.split(".");
|
||||||
|
|
||||||
|
// 長度不相等,則進行更新
|
||||||
|
if (vA.length !== vB.length) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i: number = 0; i < vA.length; ++i) {
|
||||||
|
let a: number = +vA[i];
|
||||||
|
let b: number = +vB[i] || 0;
|
||||||
|
if (a === b) {
|
||||||
|
// 數字相同,則跳過
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
// 數字不同,則進行更新
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 長度相等且數字相等,則不更新
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
//#endregion
|
//#endregion
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
// import Text_to_Speech from "./Text_to_Speech";
|
// import Text_to_Speech from "./Text_to_Speech";
|
||||||
|
|
||||||
|
import { System_Eevent } from "./Engine/CatanEngine/CSharp/System/System_Eevent";
|
||||||
|
|
||||||
const { ccclass } = cc._decorator;
|
const { ccclass } = cc._decorator;
|
||||||
|
|
||||||
@ccclass
|
@ccclass
|
||||||
@ -13,6 +15,8 @@ export default class NativeClass extends cc.Component {
|
|||||||
|
|
||||||
//#region public 屬性
|
//#region public 屬性
|
||||||
|
|
||||||
|
public WebView: cc.WebView = null;
|
||||||
|
|
||||||
public URLscheme: Object = {};
|
public URLscheme: Object = {};
|
||||||
|
|
||||||
public URLschemeFlags: number = 0;
|
public URLschemeFlags: number = 0;
|
||||||
@ -27,9 +31,10 @@ export default class NativeClass extends cc.Component {
|
|||||||
|
|
||||||
//#region Lifecycle
|
//#region Lifecycle
|
||||||
|
|
||||||
constructor() {
|
constructor(...param: any[]) {
|
||||||
super();
|
super();
|
||||||
NativeClass._instance = this;
|
NativeClass._instance = this;
|
||||||
|
this.WebView = param[0];
|
||||||
this.init();
|
this.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,6 +137,20 @@ export default class NativeClass extends cc.Component {
|
|||||||
|
|
||||||
//#region Custom Function
|
//#region Custom Function
|
||||||
|
|
||||||
|
/** CocosBridge */
|
||||||
|
public CocosBridge(type: System_Eevent, ...param: any[]): void {
|
||||||
|
let value: string = "";
|
||||||
|
for (let i: number = 0; i < param.length; i++) {
|
||||||
|
let element: any = param[i];
|
||||||
|
if (element === "") {
|
||||||
|
element = "\"\"";
|
||||||
|
}
|
||||||
|
value += `,${element}`;
|
||||||
|
}
|
||||||
|
let command: string = `window.CocosBridge(${type}${value})`;
|
||||||
|
this.WebView.evaluateJS(command);
|
||||||
|
}
|
||||||
|
|
||||||
/** GetFCMToken */
|
/** GetFCMToken */
|
||||||
public GetFCMToken(): string {
|
public GetFCMToken(): string {
|
||||||
let resp: any = "";
|
let resp: any = "";
|
||||||
|
73
assets/Script/UpdatePanel.ts
Normal file
73
assets/Script/UpdatePanel.ts
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
import { CoroutineV2 } from "./Engine/CatanEngine/CoroutineV2/CoroutineV2";
|
||||||
|
import { Enum_HUDM } from "./HUD/Enum_HUDM";
|
||||||
|
import HUDM from "./HUD/HUDM";
|
||||||
|
|
||||||
|
const { ccclass, property } = cc._decorator;
|
||||||
|
|
||||||
|
@ccclass
|
||||||
|
export default class UpdatePanel extends cc.Component {
|
||||||
|
//#region 外調參數
|
||||||
|
|
||||||
|
@property({ type: cc.Label })
|
||||||
|
public info: cc.Label = null;
|
||||||
|
|
||||||
|
@property({ type: cc.ProgressBar })
|
||||||
|
public fileProgress: cc.ProgressBar = null;
|
||||||
|
|
||||||
|
@property({ type: cc.Label })
|
||||||
|
public fileLabel: cc.Label = null;
|
||||||
|
|
||||||
|
@property({ type: cc.ProgressBar })
|
||||||
|
public byteProgress: cc.ProgressBar = null;
|
||||||
|
|
||||||
|
@property({ type: cc.Label })
|
||||||
|
public byteLabel: cc.Label = null;
|
||||||
|
|
||||||
|
@property({ type: cc.Node })
|
||||||
|
public close: cc.Node = null;
|
||||||
|
|
||||||
|
@property({ type: cc.Node })
|
||||||
|
public checkBtn: cc.Node = null;
|
||||||
|
|
||||||
|
@property({ type: cc.Node })
|
||||||
|
public retryBtn: cc.Node = null;
|
||||||
|
|
||||||
|
@property({ type: cc.Node })
|
||||||
|
public updateBtn: cc.Node = null;
|
||||||
|
|
||||||
|
//#endregion
|
||||||
|
|
||||||
|
//#region Lifecycle
|
||||||
|
|
||||||
|
protected onLoad(): void {
|
||||||
|
let self: this = this;
|
||||||
|
this.close.on(cc.Node.EventType.TOUCH_END, () => {
|
||||||
|
self.node.active = false;
|
||||||
|
}, this);
|
||||||
|
|
||||||
|
this.node.getChildByName("update_btn").on("click", () => { CoroutineV2.Single(this.OnClickUpdate()).Start(); }, this);
|
||||||
|
this.node.getChildByName("check_btn").on("click", () => { CoroutineV2.Single(this.OnClickCheck()).Start(); }, this);
|
||||||
|
this.node.getChildByName("retry_btn").on("click", () => { CoroutineV2.Single(this.OnClickRetry()).Start(); }, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
//#endregion
|
||||||
|
|
||||||
|
//#region OnClick
|
||||||
|
|
||||||
|
public *OnClickUpdate(): IterableIterator<any> {
|
||||||
|
let updateingData: Enum_HUDM.UpdateingDataObj = yield* HUDM.Instance.HUD();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
public *OnClickCheck(): IterableIterator<any> {
|
||||||
|
let needUpdateData: Enum_HUDM.NeedUpdateDataObj = yield* HUDM.Instance.CheckUpdate();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
public *OnClickRetry(): IterableIterator<any> {
|
||||||
|
let updateingData: Enum_HUDM.UpdateingDataObj = yield* HUDM.Instance.RetryDownLoadFailedAssets();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//#endregion
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"ver": "1.1.0",
|
"ver": "1.1.0",
|
||||||
"uuid": "383b4628-2b2a-4de4-8aca-913015e91cae",
|
"uuid": "86711b47-13f6-4a4e-8a9d-0e24e7fca6e7",
|
||||||
"importer": "typescript",
|
"importer": "typescript",
|
||||||
"isPlugin": false,
|
"isPlugin": false,
|
||||||
"loadPluginInWeb": true,
|
"loadPluginInWeb": true,
|
13
assets/Script/_BusinessTypeSetting.meta
Normal file
13
assets/Script/_BusinessTypeSetting.meta
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.1.3",
|
||||||
|
"uuid": "78c83bfa-4d05-4a0a-ade0-864ea68a5837",
|
||||||
|
"importer": "folder",
|
||||||
|
"isBundle": false,
|
||||||
|
"bundleName": "",
|
||||||
|
"priority": 1,
|
||||||
|
"compressionType": {},
|
||||||
|
"optimizeHotUpdate": {},
|
||||||
|
"inlineSpriteFrames": {},
|
||||||
|
"isRemoteBundle": {},
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
11
assets/Script/_BusinessTypeSetting/BusinessTypeSetting.ts
Normal file
11
assets/Script/_BusinessTypeSetting/BusinessTypeSetting.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
export default class BusinessTypeSetting {
|
||||||
|
public static readonly MajorVersion: number = 3;
|
||||||
|
public static readonly MinorVersion: number = 0;
|
||||||
|
// public static readonly BuildVersion: number = 0;
|
||||||
|
public static readonly Revision: number = 0;
|
||||||
|
/** 編譯版本 */
|
||||||
|
public static readonly COMPILE_VERSION: string = `${BusinessTypeSetting.MajorVersion}.${BusinessTypeSetting.MinorVersion}.${BusinessTypeSetting.Revision}`;
|
||||||
|
|
||||||
|
/** 資源伺服器網址 */
|
||||||
|
public static UsePatch: string = null;
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.1.0",
|
||||||
|
"uuid": "b913b231-4f44-467c-a60f-065ce8e1fa42",
|
||||||
|
"importer": "typescript",
|
||||||
|
"isPlugin": false,
|
||||||
|
"loadPluginInWeb": true,
|
||||||
|
"loadPluginInNative": true,
|
||||||
|
"loadPluginInEditor": false,
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
13
assets/Texture/UI.meta
Normal file
13
assets/Texture/UI.meta
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.1.3",
|
||||||
|
"uuid": "e47b98da-e2c8-4c74-9530-0f718d04b512",
|
||||||
|
"importer": "folder",
|
||||||
|
"isBundle": false,
|
||||||
|
"bundleName": "",
|
||||||
|
"priority": 1,
|
||||||
|
"compressionType": {},
|
||||||
|
"optimizeHotUpdate": {},
|
||||||
|
"inlineSpriteFrames": {},
|
||||||
|
"isRemoteBundle": {},
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
13
assets/Texture/UI/chat.meta
Normal file
13
assets/Texture/UI/chat.meta
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.1.3",
|
||||||
|
"uuid": "72d8bf4e-9f48-4cdc-9121-eb140ee30407",
|
||||||
|
"importer": "folder",
|
||||||
|
"isBundle": false,
|
||||||
|
"bundleName": "",
|
||||||
|
"priority": 1,
|
||||||
|
"compressionType": {},
|
||||||
|
"optimizeHotUpdate": {},
|
||||||
|
"inlineSpriteFrames": {},
|
||||||
|
"isRemoteBundle": {},
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
BIN
assets/Texture/UI/chat/button_orange.png
Normal file
BIN
assets/Texture/UI/chat/button_orange.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
38
assets/Texture/UI/chat/button_orange.png.meta
Normal file
38
assets/Texture/UI/chat/button_orange.png.meta
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
"ver": "2.3.7",
|
||||||
|
"uuid": "3459ab36-782c-4c4e-8aef-7280aff8b272",
|
||||||
|
"importer": "texture",
|
||||||
|
"type": "sprite",
|
||||||
|
"wrapMode": "clamp",
|
||||||
|
"filterMode": "bilinear",
|
||||||
|
"premultiplyAlpha": false,
|
||||||
|
"genMipmaps": false,
|
||||||
|
"packable": true,
|
||||||
|
"width": 240,
|
||||||
|
"height": 95,
|
||||||
|
"platformSettings": {},
|
||||||
|
"subMetas": {
|
||||||
|
"button_orange": {
|
||||||
|
"ver": "1.0.6",
|
||||||
|
"uuid": "c01466ea-7283-4fce-b615-4ee78c774af0",
|
||||||
|
"importer": "sprite-frame",
|
||||||
|
"rawTextureUuid": "3459ab36-782c-4c4e-8aef-7280aff8b272",
|
||||||
|
"trimType": "auto",
|
||||||
|
"trimThreshold": 1,
|
||||||
|
"rotated": false,
|
||||||
|
"offsetX": 0,
|
||||||
|
"offsetY": 0,
|
||||||
|
"trimX": 0,
|
||||||
|
"trimY": 0,
|
||||||
|
"width": 240,
|
||||||
|
"height": 95,
|
||||||
|
"rawWidth": 240,
|
||||||
|
"rawHeight": 95,
|
||||||
|
"borderTop": 0,
|
||||||
|
"borderBottom": 0,
|
||||||
|
"borderLeft": 0,
|
||||||
|
"borderRight": 0,
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
BIN
assets/Texture/UI/chat/gb_inputbox.png
Normal file
BIN
assets/Texture/UI/chat/gb_inputbox.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.5 KiB |
38
assets/Texture/UI/chat/gb_inputbox.png.meta
Normal file
38
assets/Texture/UI/chat/gb_inputbox.png.meta
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
"ver": "2.3.7",
|
||||||
|
"uuid": "c39ea496-96eb-4dc5-945a-e7c919b77c21",
|
||||||
|
"importer": "texture",
|
||||||
|
"type": "sprite",
|
||||||
|
"wrapMode": "clamp",
|
||||||
|
"filterMode": "bilinear",
|
||||||
|
"premultiplyAlpha": false,
|
||||||
|
"genMipmaps": false,
|
||||||
|
"packable": true,
|
||||||
|
"width": 54,
|
||||||
|
"height": 81,
|
||||||
|
"platformSettings": {},
|
||||||
|
"subMetas": {
|
||||||
|
"gb_inputbox": {
|
||||||
|
"ver": "1.0.6",
|
||||||
|
"uuid": "7d1d4e60-aba2-48e8-85f8-8e328f34e7cc",
|
||||||
|
"importer": "sprite-frame",
|
||||||
|
"rawTextureUuid": "c39ea496-96eb-4dc5-945a-e7c919b77c21",
|
||||||
|
"trimType": "auto",
|
||||||
|
"trimThreshold": 1,
|
||||||
|
"rotated": false,
|
||||||
|
"offsetX": 0,
|
||||||
|
"offsetY": 0,
|
||||||
|
"trimX": 0,
|
||||||
|
"trimY": 0,
|
||||||
|
"width": 54,
|
||||||
|
"height": 81,
|
||||||
|
"rawWidth": 54,
|
||||||
|
"rawHeight": 81,
|
||||||
|
"borderTop": 11,
|
||||||
|
"borderBottom": 11,
|
||||||
|
"borderLeft": 12,
|
||||||
|
"borderRight": 12,
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
13
assets/Texture/UI/new.meta
Normal file
13
assets/Texture/UI/new.meta
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.1.3",
|
||||||
|
"uuid": "d695c8b9-c7e7-4290-84e5-c10e9988e966",
|
||||||
|
"importer": "folder",
|
||||||
|
"isBundle": false,
|
||||||
|
"bundleName": "",
|
||||||
|
"priority": 1,
|
||||||
|
"compressionType": {},
|
||||||
|
"optimizeHotUpdate": {},
|
||||||
|
"inlineSpriteFrames": {},
|
||||||
|
"isRemoteBundle": {},
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
BIN
assets/Texture/UI/new/bg_rankinglist.png
Normal file
BIN
assets/Texture/UI/new/bg_rankinglist.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.7 KiB |
38
assets/Texture/UI/new/bg_rankinglist.png.meta
Normal file
38
assets/Texture/UI/new/bg_rankinglist.png.meta
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
"ver": "2.3.7",
|
||||||
|
"uuid": "700faa17-11a6-46cd-aeb5-d6900bc264f8",
|
||||||
|
"importer": "texture",
|
||||||
|
"type": "sprite",
|
||||||
|
"wrapMode": "clamp",
|
||||||
|
"filterMode": "bilinear",
|
||||||
|
"premultiplyAlpha": false,
|
||||||
|
"genMipmaps": false,
|
||||||
|
"packable": true,
|
||||||
|
"width": 504,
|
||||||
|
"height": 144,
|
||||||
|
"platformSettings": {},
|
||||||
|
"subMetas": {
|
||||||
|
"bg_rankinglist": {
|
||||||
|
"ver": "1.0.6",
|
||||||
|
"uuid": "ca7dd73d-526a-4c85-9702-eb51e93b9d99",
|
||||||
|
"importer": "sprite-frame",
|
||||||
|
"rawTextureUuid": "700faa17-11a6-46cd-aeb5-d6900bc264f8",
|
||||||
|
"trimType": "auto",
|
||||||
|
"trimThreshold": 1,
|
||||||
|
"rotated": false,
|
||||||
|
"offsetX": 0,
|
||||||
|
"offsetY": 0,
|
||||||
|
"trimX": 0,
|
||||||
|
"trimY": 0,
|
||||||
|
"width": 504,
|
||||||
|
"height": 144,
|
||||||
|
"rawWidth": 504,
|
||||||
|
"rawHeight": 144,
|
||||||
|
"borderTop": 69,
|
||||||
|
"borderBottom": 36,
|
||||||
|
"borderLeft": 36,
|
||||||
|
"borderRight": 36,
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
BIN
assets/Texture/UI/new/icon_back.png
Normal file
BIN
assets/Texture/UI/new/icon_back.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.2 KiB |
38
assets/Texture/UI/new/icon_back.png.meta
Normal file
38
assets/Texture/UI/new/icon_back.png.meta
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
"ver": "2.3.7",
|
||||||
|
"uuid": "2ddfe005-2129-41d8-aeec-2b1f51f02962",
|
||||||
|
"importer": "texture",
|
||||||
|
"type": "sprite",
|
||||||
|
"wrapMode": "clamp",
|
||||||
|
"filterMode": "bilinear",
|
||||||
|
"premultiplyAlpha": false,
|
||||||
|
"genMipmaps": false,
|
||||||
|
"packable": true,
|
||||||
|
"width": 33,
|
||||||
|
"height": 48,
|
||||||
|
"platformSettings": {},
|
||||||
|
"subMetas": {
|
||||||
|
"icon_back": {
|
||||||
|
"ver": "1.0.6",
|
||||||
|
"uuid": "6035fac6-5208-4e0b-bea7-62ff9fb1338b",
|
||||||
|
"importer": "sprite-frame",
|
||||||
|
"rawTextureUuid": "2ddfe005-2129-41d8-aeec-2b1f51f02962",
|
||||||
|
"trimType": "auto",
|
||||||
|
"trimThreshold": 1,
|
||||||
|
"rotated": false,
|
||||||
|
"offsetX": 0,
|
||||||
|
"offsetY": 0,
|
||||||
|
"trimX": 0,
|
||||||
|
"trimY": 0,
|
||||||
|
"width": 33,
|
||||||
|
"height": 48,
|
||||||
|
"rawWidth": 33,
|
||||||
|
"rawHeight": 48,
|
||||||
|
"borderTop": 0,
|
||||||
|
"borderBottom": 0,
|
||||||
|
"borderLeft": 0,
|
||||||
|
"borderRight": 0,
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
13
assets/Texture/UI/table.meta
Normal file
13
assets/Texture/UI/table.meta
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.1.3",
|
||||||
|
"uuid": "7e51bdf1-1b2e-4de4-9e05-b9c9715f6229",
|
||||||
|
"importer": "folder",
|
||||||
|
"isBundle": false,
|
||||||
|
"bundleName": "",
|
||||||
|
"priority": 1,
|
||||||
|
"compressionType": {},
|
||||||
|
"optimizeHotUpdate": {},
|
||||||
|
"inlineSpriteFrames": {},
|
||||||
|
"isRemoteBundle": {},
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
BIN
assets/Texture/UI/table/bg_jinbishu.png
Normal file
BIN
assets/Texture/UI/table/bg_jinbishu.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.8 KiB |
38
assets/Texture/UI/table/bg_jinbishu.png.meta
Normal file
38
assets/Texture/UI/table/bg_jinbishu.png.meta
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
"ver": "2.3.7",
|
||||||
|
"uuid": "caaaf9ff-5036-4232-a8a7-88b80b2e4c88",
|
||||||
|
"importer": "texture",
|
||||||
|
"type": "sprite",
|
||||||
|
"wrapMode": "clamp",
|
||||||
|
"filterMode": "bilinear",
|
||||||
|
"premultiplyAlpha": false,
|
||||||
|
"genMipmaps": false,
|
||||||
|
"packable": true,
|
||||||
|
"width": 40,
|
||||||
|
"height": 30,
|
||||||
|
"platformSettings": {},
|
||||||
|
"subMetas": {
|
||||||
|
"bg_jinbishu": {
|
||||||
|
"ver": "1.0.6",
|
||||||
|
"uuid": "022a80ab-4cde-42ca-9e04-8a23745cf138",
|
||||||
|
"importer": "sprite-frame",
|
||||||
|
"rawTextureUuid": "caaaf9ff-5036-4232-a8a7-88b80b2e4c88",
|
||||||
|
"trimType": "auto",
|
||||||
|
"trimThreshold": 1,
|
||||||
|
"rotated": false,
|
||||||
|
"offsetX": 0,
|
||||||
|
"offsetY": 0,
|
||||||
|
"trimX": 0,
|
||||||
|
"trimY": 0,
|
||||||
|
"width": 40,
|
||||||
|
"height": 30,
|
||||||
|
"rawWidth": 40,
|
||||||
|
"rawHeight": 30,
|
||||||
|
"borderTop": 0,
|
||||||
|
"borderBottom": 0,
|
||||||
|
"borderLeft": 11,
|
||||||
|
"borderRight": 12,
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
<?xml version='1.0' encoding='UTF-8'?>
|
<?xml version='1.0' encoding='UTF-8'?>
|
||||||
<resources>
|
<resources>
|
||||||
<string name="app_name" translatable="false">爆機娛樂城</string>
|
<string name="app_name" translatable="false">卡羅記帳</string>
|
||||||
</resources>
|
</resources>
|
@ -3,21 +3,21 @@
|
|||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
<key>CLIENT_ID</key>
|
<key>CLIENT_ID</key>
|
||||||
<string>407474781989-oj00t4rdam3scpnaoohm2dii1c7tti5c.apps.googleusercontent.com</string>
|
<string>349734230365-elglntiic9hpnr2b1sti3hba0flgqglj.apps.googleusercontent.com</string>
|
||||||
<key>REVERSED_CLIENT_ID</key>
|
<key>REVERSED_CLIENT_ID</key>
|
||||||
<string>com.googleusercontent.apps.407474781989-oj00t4rdam3scpnaoohm2dii1c7tti5c</string>
|
<string>com.googleusercontent.apps.349734230365-elglntiic9hpnr2b1sti3hba0flgqglj</string>
|
||||||
<key>API_KEY</key>
|
<key>API_KEY</key>
|
||||||
<string>AIzaSyBwhNhVYqErLAwU5SMmkDiN6NOVrhpykOQ</string>
|
<string>AIzaSyCpWUse7RWwAaM81Va0kPbzr3jXUIVD28Q</string>
|
||||||
<key>GCM_SENDER_ID</key>
|
<key>GCM_SENDER_ID</key>
|
||||||
<string>407474781989</string>
|
<string>349734230365</string>
|
||||||
<key>PLIST_VERSION</key>
|
<key>PLIST_VERSION</key>
|
||||||
<string>1</string>
|
<string>1</string>
|
||||||
<key>BUNDLE_ID</key>
|
<key>BUNDLE_ID</key>
|
||||||
<string>org.jianmiau.jmka</string>
|
<string>org.jianmiau.jmka</string>
|
||||||
<key>PROJECT_ID</key>
|
<key>PROJECT_ID</key>
|
||||||
<string>jmka-baa31</string>
|
<string>jm-expense-2022</string>
|
||||||
<key>STORAGE_BUCKET</key>
|
<key>STORAGE_BUCKET</key>
|
||||||
<string>jmka-baa31.appspot.com</string>
|
<string>jm-expense-2022.appspot.com</string>
|
||||||
<key>IS_ADS_ENABLED</key>
|
<key>IS_ADS_ENABLED</key>
|
||||||
<false></false>
|
<false></false>
|
||||||
<key>IS_ANALYTICS_ENABLED</key>
|
<key>IS_ANALYTICS_ENABLED</key>
|
||||||
@ -29,6 +29,6 @@
|
|||||||
<key>IS_SIGNIN_ENABLED</key>
|
<key>IS_SIGNIN_ENABLED</key>
|
||||||
<true></true>
|
<true></true>
|
||||||
<key>GOOGLE_APP_ID</key>
|
<key>GOOGLE_APP_ID</key>
|
||||||
<string>1:407474781989:ios:0bcba35c2e54c67a25a4cc</string>
|
<string>1:349734230365:ios:c6eafd0a0e1f02f089f0b4</string>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
@ -823,7 +823,7 @@
|
|||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
LIBRARY_SEARCH_PATHS = "$(SRCROOT)/../../cocos2d-x/external/ios/libs";
|
LIBRARY_SEARCH_PATHS = "$(SRCROOT)/../../cocos2d-x/external/ios/libs";
|
||||||
MARKETING_VERSION = 2.1;
|
MARKETING_VERSION = 3.0;
|
||||||
OTHER_LDFLAGS = (
|
OTHER_LDFLAGS = (
|
||||||
"-ObjC",
|
"-ObjC",
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
@ -873,7 +873,7 @@
|
|||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
LIBRARY_SEARCH_PATHS = "$(SRCROOT)/../../cocos2d-x/external/ios/libs";
|
LIBRARY_SEARCH_PATHS = "$(SRCROOT)/../../cocos2d-x/external/ios/libs";
|
||||||
MARKETING_VERSION = 2.1;
|
MARKETING_VERSION = 3.0;
|
||||||
OTHER_LDFLAGS = (
|
OTHER_LDFLAGS = (
|
||||||
"-ObjC",
|
"-ObjC",
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
|
Binary file not shown.
@ -7,7 +7,7 @@
|
|||||||
<key>JMKA-desktop.xcscheme_^#shared#^_</key>
|
<key>JMKA-desktop.xcscheme_^#shared#^_</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>orderHint</key>
|
<key>orderHint</key>
|
||||||
<integer>3</integer>
|
<integer>1</integer>
|
||||||
</dict>
|
</dict>
|
||||||
<key>JMKA-mobile.xcscheme_^#shared#^_</key>
|
<key>JMKA-mobile.xcscheme_^#shared#^_</key>
|
||||||
<dict>
|
<dict>
|
||||||
|
@ -0,0 +1,72 @@
|
|||||||
|
//
|
||||||
|
// Firebase_S.swift
|
||||||
|
// JMKA-mobile
|
||||||
|
//
|
||||||
|
// Created by JianMiau on 2022/8/26.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
import Foundation
|
||||||
|
//import UserNotifications
|
||||||
|
//import Firebase
|
||||||
|
|
||||||
|
//class Firebase_S: NSObject, UNUserNotificationCenterDelegate, MessagingDelegate {
|
||||||
|
// @objc public func onLoad(_ application: UIApplication) {
|
||||||
|
// FirebaseApp.configure()
|
||||||
|
// Messaging.messaging().delegate = self
|
||||||
|
// if #available(iOS 10.0, *) {
|
||||||
|
// // For iOS 10 display notification (sent via APNS)
|
||||||
|
// UNUserNotificationCenter.current().delegate = self
|
||||||
|
//
|
||||||
|
// let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
|
||||||
|
// UNUserNotificationCenter.current().requestAuthorization(
|
||||||
|
// options: authOptions,
|
||||||
|
// completionHandler: { _, _ in }
|
||||||
|
// )
|
||||||
|
// } else {
|
||||||
|
// let settings: UIUserNotificationSettings =
|
||||||
|
// UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
|
||||||
|
// application.registerUserNotificationSettings(settings)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// application.registerForRemoteNotifications()
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @objc public func getFMTCoken() {
|
||||||
|
// Messaging.messaging().token { token, error in
|
||||||
|
// if let error = error {
|
||||||
|
// print("Error fetching FCM registration token: \(error)")
|
||||||
|
// } else if let token = token {
|
||||||
|
// print("FCM registration token: \(token)")
|
||||||
|
// // self.fcmRegTokenMessage.text = "Remote FCM registration token: \(token)"
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
|
//extension Firebase_S: MessagingDelegate {
|
||||||
|
//
|
||||||
|
// func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
|
||||||
|
// print("fcm Token", fcmToken ?? "")
|
||||||
|
// // 將 fcm token 傳送給後台
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
|
//extension Firebase_S: UNUserNotificationCenterDelegate {
|
||||||
|
// // 使用者點選推播時觸發
|
||||||
|
// func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
|
||||||
|
// print(#function)
|
||||||
|
// let content = response.notification.request.content
|
||||||
|
// print(content.userInfo)
|
||||||
|
// completionHandler()
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // 讓 App 在前景也能顯示推播
|
||||||
|
// func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
|
||||||
|
// if #available(iOS 14.0, *) {
|
||||||
|
// completionHandler([.banner])
|
||||||
|
// } else {
|
||||||
|
// // Fallback on earlier versions
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
149
build-templates/jsb-default/main.js
Normal file
149
build-templates/jsb-default/main.js
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
window.boot = function () {
|
||||||
|
var settings = window._CCSettings;
|
||||||
|
window._CCSettings = undefined;
|
||||||
|
var onProgress = null;
|
||||||
|
|
||||||
|
var RESOURCES = cc.AssetManager.BuiltinBundleName.RESOURCES;
|
||||||
|
var INTERNAL = cc.AssetManager.BuiltinBundleName.INTERNAL;
|
||||||
|
var MAIN = cc.AssetManager.BuiltinBundleName.MAIN;
|
||||||
|
function setLoadingDisplay() {
|
||||||
|
// Loading splash scene
|
||||||
|
var splash = document.getElementById('splash');
|
||||||
|
var progressBar = splash.querySelector('.progress-bar span');
|
||||||
|
onProgress = function (finish, total) {
|
||||||
|
var percent = 100 * finish / total;
|
||||||
|
if (progressBar) {
|
||||||
|
progressBar.style.width = percent.toFixed(2) + '%';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
splash.style.display = 'block';
|
||||||
|
progressBar.style.width = '0%';
|
||||||
|
|
||||||
|
cc.director.once(cc.Director.EVENT_AFTER_SCENE_LAUNCH, function () {
|
||||||
|
splash.style.display = 'none';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var onStart = function () {
|
||||||
|
|
||||||
|
cc.view.enableRetina(true);
|
||||||
|
cc.view.resizeWithBrowserSize(true);
|
||||||
|
|
||||||
|
if (cc.sys.isBrowser) {
|
||||||
|
setLoadingDisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cc.sys.isMobile) {
|
||||||
|
if (settings.orientation === 'landscape') {
|
||||||
|
cc.view.setOrientation(cc.macro.ORIENTATION_LANDSCAPE);
|
||||||
|
}
|
||||||
|
else if (settings.orientation === 'portrait') {
|
||||||
|
cc.view.setOrientation(cc.macro.ORIENTATION_PORTRAIT);
|
||||||
|
}
|
||||||
|
cc.view.enableAutoFullScreen([
|
||||||
|
cc.sys.BROWSER_TYPE_BAIDU,
|
||||||
|
cc.sys.BROWSER_TYPE_BAIDU_APP,
|
||||||
|
cc.sys.BROWSER_TYPE_WECHAT,
|
||||||
|
cc.sys.BROWSER_TYPE_MOBILE_QQ,
|
||||||
|
cc.sys.BROWSER_TYPE_MIUI,
|
||||||
|
cc.sys.BROWSER_TYPE_HUAWEI,
|
||||||
|
cc.sys.BROWSER_TYPE_UC,
|
||||||
|
].indexOf(cc.sys.browserType) < 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Limit downloading max concurrent task to 2,
|
||||||
|
// more tasks simultaneously may cause performance draw back on some android system / browsers.
|
||||||
|
// You can adjust the number based on your own test result, you have to set it before any loading process to take effect.
|
||||||
|
if (cc.sys.isBrowser && cc.sys.os === cc.sys.OS_ANDROID) {
|
||||||
|
cc.assetManager.downloader.maxConcurrency = 2;
|
||||||
|
cc.assetManager.downloader.maxRequestsPerFrame = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
var launchScene = settings.launchScene;
|
||||||
|
var bundle = cc.assetManager.bundles.find(function (b) {
|
||||||
|
return b.getSceneInfo(launchScene);
|
||||||
|
});
|
||||||
|
|
||||||
|
bundle.loadScene(launchScene, null, onProgress,
|
||||||
|
function (err, scene) {
|
||||||
|
if (!err) {
|
||||||
|
cc.director.runSceneImmediate(scene);
|
||||||
|
if (cc.sys.isBrowser) {
|
||||||
|
// show canvas
|
||||||
|
var canvas = document.getElementById('GameCanvas');
|
||||||
|
canvas.style.visibility = '';
|
||||||
|
var div = document.getElementById('GameDiv');
|
||||||
|
if (div) {
|
||||||
|
div.style.backgroundImage = '';
|
||||||
|
}
|
||||||
|
console.log('Success to load scene: ' + launchScene);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
var option = {
|
||||||
|
id: 'GameCanvas',
|
||||||
|
debugMode: settings.debug ? cc.debug.DebugMode.INFO : cc.debug.DebugMode.ERROR,
|
||||||
|
showFPS: settings.debug,
|
||||||
|
frameRate: 60,
|
||||||
|
groupList: settings.groupList,
|
||||||
|
collisionMatrix: settings.collisionMatrix,
|
||||||
|
};
|
||||||
|
|
||||||
|
cc.assetManager.init({
|
||||||
|
bundleVers: settings.bundleVers,
|
||||||
|
remoteBundles: settings.remoteBundles,
|
||||||
|
server: settings.server
|
||||||
|
});
|
||||||
|
|
||||||
|
var bundleRoot = [INTERNAL];
|
||||||
|
settings.hasResourcesBundle && bundleRoot.push(RESOURCES);
|
||||||
|
|
||||||
|
var count = 0;
|
||||||
|
function cb(err) {
|
||||||
|
if (err) return console.error(err.message, err.stack);
|
||||||
|
count++;
|
||||||
|
if (count === bundleRoot.length + 1) {
|
||||||
|
cc.assetManager.loadBundle(MAIN, function (err) {
|
||||||
|
if (!err) cc.game.run(option, onStart);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cc.assetManager.loadScript(settings.jsList.map(function (x) { return 'src/' + x; }), cb);
|
||||||
|
|
||||||
|
for (var i = 0; i < bundleRoot.length; i++) {
|
||||||
|
cc.assetManager.loadBundle(bundleRoot[i], cb);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (window.jsb) {
|
||||||
|
var hotUpdateSearchPaths = localStorage.getItem('HotUpdateSearchPaths');
|
||||||
|
if (hotUpdateSearchPaths) {
|
||||||
|
jsb.fileUtils.setSearchPaths(JSON.parse(hotUpdateSearchPaths));
|
||||||
|
}
|
||||||
|
|
||||||
|
var isRuntime = (typeof loadRuntime === 'function');
|
||||||
|
if (isRuntime) {
|
||||||
|
require('src/settings.js');
|
||||||
|
require('src/cocos2d-runtime.js');
|
||||||
|
if (CC_PHYSICS_BUILTIN || CC_PHYSICS_CANNON) {
|
||||||
|
require('src/physics.js');
|
||||||
|
}
|
||||||
|
require('jsb-adapter/engine/index.js');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
require('src/settings.js');
|
||||||
|
require('src/cocos2d-jsb.js');
|
||||||
|
if (CC_PHYSICS_BUILTIN || CC_PHYSICS_CANNON) {
|
||||||
|
require('src/physics.js');
|
||||||
|
}
|
||||||
|
require('jsb-adapter/jsb-engine.js');
|
||||||
|
}
|
||||||
|
|
||||||
|
cc.macro.CLEANUP_IMAGE_CACHE = true;
|
||||||
|
window.boot();
|
||||||
|
}
|
28301
creator.d.ts
vendored
28301
creator.d.ts
vendored
File diff suppressed because it is too large
Load Diff
31
hotupdate.bat
Normal file
31
hotupdate.bat
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
@echo off
|
||||||
|
|
||||||
|
set MainVer=3.0
|
||||||
|
set BundleVer=3.0.1
|
||||||
|
set START1=%~dp0\build\jsb-default\remote-assets
|
||||||
|
set START2=%~dp0\remote-assets
|
||||||
|
set END=W:\web\MyWeb\Resources\App\JMKA\update\remote-assets\%MainVer%
|
||||||
|
|
||||||
|
node version_generator.js -v %BundleVer% -u https://jianmiau.tk/Resources/App/JMKA/update/remote-assets/%MainVer%/ -s build/jsb-default/remote-assets -d remote-assets
|
||||||
|
|
||||||
|
@REM rmdir /s /q %END%
|
||||||
|
@REM del /f "%END%"
|
||||||
|
@REM mkdir %END%
|
||||||
|
mkdir %END%
|
||||||
|
chcp 950 >NUL
|
||||||
|
GOTO ALL
|
||||||
|
|
||||||
|
:ALL
|
||||||
|
echo ¦P¨BbuildÀÉ®×
|
||||||
|
robocopy %START1% %END% /E /Z /FFT /COPY:D /NJH /NJS /NDL
|
||||||
|
GOTO ALL2
|
||||||
|
|
||||||
|
:ALL2
|
||||||
|
echo ¦P¨BmanifestÀÉ®×
|
||||||
|
robocopy %START2% %END% /E /Z /FFT /COPY:D /NJH /NJS /NDL
|
||||||
|
GOTO END
|
||||||
|
|
||||||
|
:END
|
||||||
|
echo Done!
|
||||||
|
PAUSE
|
||||||
|
|
35
packages/hot-update-tools/CommonIssue.md
Normal file
35
packages/hot-update-tools/CommonIssue.md
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
# 常见问题
|
||||||
|
## 说明
|
||||||
|
这里是作者热更新过程中遇到的一些问题,仅供参考
|
||||||
|
|
||||||
|
### 局域网测试时,为啥我的热更新请求地址是bogon(127.0.0.1)
|
||||||
|
![图片](../../doc/热更新/desc/issue1.png)
|
||||||
|
- 导致原因
|
||||||
|
- 开发环境所在的局域网路由器可能设置了ip虚拟化导致这个问题
|
||||||
|
- 此时你可以ping一下同局域网的电脑,如果和下图一样,主机ip为bogon,那么很有可能是ip虚拟化导致看不到主机名字
|
||||||
|
![图片](../../doc/热更新/desc/issue2.png)
|
||||||
|
- 解决办法:
|
||||||
|
- 可以发布到公网测试下,如果在公网环境仍然存在这个问题,那么很有可能就是代码的问题!
|
||||||
|
- 如果仍然想在局域网环境测试,Windows的话,务必确认已经关闭本机防火墙,再次尝试
|
||||||
|
### 热更新黑屏,报错如图
|
||||||
|
![图片](../../doc/热更新/desc/issue3.png)
|
||||||
|
尝试着使用gradle:2.3.0 也许能够解决问题
|
||||||
|
文件地址: proj.android-studio/build.gradle
|
||||||
|
```
|
||||||
|
classpath 'com.android.tools.build:gradle:2.3.0'
|
||||||
|
```
|
||||||
|
|
||||||
|
### 插件全局安装目录在哪里?
|
||||||
|
- 在win上
|
||||||
|
```
|
||||||
|
C:\Users\用户名\.CocosCreator\packages
|
||||||
|
```
|
||||||
|
比如
|
||||||
|
```
|
||||||
|
C:\Users\Administrator\.CocosCreator\packages
|
||||||
|
```
|
||||||
|
- mac上
|
||||||
|
```
|
||||||
|
~/.CocosCreator
|
||||||
|
```
|
||||||
|
|
81
packages/hot-update-tools/README.md
Normal file
81
packages/hot-update-tools/README.md
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
# hot-update-tools
|
||||||
|
## 工具说明
|
||||||
|
本工具仅仅是对官方的热更新方案的一个可视化解决方案,可以帮助你快速生成project.manifest和version.manifest文件,并且提供了本地测试的一些常用操作
|
||||||
|
使用前请移步官方热更新教程 https://github.com/cocos-creator/tutorial-hot-update
|
||||||
|
|
||||||
|
|
||||||
|
## 使用说明
|
||||||
|
使用该工具前,必须执行 **项目=>构建** ,插件自身带有构建提示,仅仅作为构建参考!
|
||||||
|
![插件工作原理](../../doc/热更新/desc/热更新工作原理.png)
|
||||||
|
|
||||||
|
|
||||||
|
### 界面一共包含4部分,下边是具体的说明
|
||||||
|
#### 第1部分:生成Manifest操作
|
||||||
|
在这部分你可以看到有2个需要你填写的参数:
|
||||||
|
- 版本号:
|
||||||
|
```
|
||||||
|
游戏热更新版本号,这个版本号建议是x.x的格式,例如1.2, 2.01等
|
||||||
|
```
|
||||||
|
|
||||||
|
- 资源服务器url:
|
||||||
|
```
|
||||||
|
游戏热更新资源的服务器url,即客户端发起热更新http请求的url
|
||||||
|
例如你的服务器地址为100.200.300.400,那么这里你需要填写 http://100.200.300.400
|
||||||
|
如果你有目录层级,比如我放在了gameUpdate目录下,那么这里你就需要填写 http://100.200.300.400/gameUpdate
|
||||||
|
也就是说你最终填写的这个url+"project.manifest",能够在浏览器中正确访问,那么这个url就是有效的,不懂得请仔细查阅官方热更新文档
|
||||||
|
```
|
||||||
|
同是你看到有2个参数是不可编辑的
|
||||||
|
- build项目资源文件目录
|
||||||
|
```
|
||||||
|
如果你执行过 项目=>构建 的话,那么在插件启动时,该目录就会默认指向build/jsb-default,如果该目录下的src,res就是热更新要的文件,如果插件启动后,该参数为空,日志会提示需要你构建一下项目
|
||||||
|
```
|
||||||
|
- manifest存储目录
|
||||||
|
```
|
||||||
|
该参数会在插件启动时默认初始化,指向的目录就是最终热更新生成的manifest文件存放处,该参数对于开发者是透明,避免参数过多,造成混淆
|
||||||
|
```
|
||||||
|
#### 第2部分:检测当前游戏的状态
|
||||||
|
开发这个功能原因:
|
||||||
|
- **经常看到其他人在填写版本号的时候,填写的很随意,不知道当前游戏版本号是多少,很容易填写的版本号比当前运行游戏的版本号要低,然后反馈给我说游戏热更新不能用**
|
||||||
|
|
||||||
|
在这个界面里更方便的查看当前项目里面的版本信息
|
||||||
|
- 项目中使用的manifest
|
||||||
|
- package url
|
||||||
|
- 游戏版本号
|
||||||
|
|
||||||
|
需要注意的是
|
||||||
|
**如果项目中的manifest文件发生变动,该插件不会主动刷新,需要手动点击刷新按钮**
|
||||||
|
|
||||||
|
#### 第3部分:方便进行本地测试
|
||||||
|
当第1部分的参数配置ok,点击**生成**按钮,顺利生成manifest文件后,你可能需要进行一下本机的一个简单测试,那么这个功能就是为此开发的
|
||||||
|
- 使用前请先指定本地的server物理路径
|
||||||
|
- 部署
|
||||||
|
```
|
||||||
|
该操作会将生成的manifest文件,src,res,三部分文件一同拷贝到指定的server路径里
|
||||||
|
```
|
||||||
|
- 清理模拟器
|
||||||
|
```
|
||||||
|
该操作会删除creator自带模拟器的热更新缓存
|
||||||
|
windows下为:creator\resources\cocos2d-x\simulator\win32\remote-asset
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 第4部分: 日志
|
||||||
|
这里显示了一些插件的操作提示,如果使用过程中出现问题,请耐心阅读提示,也许能够得到帮助
|
||||||
|
#### 最后
|
||||||
|
工具仅仅是原理的一个友好帮助,在使用的过程中,还是希望使用者能够对官方的热更新文档进行仔细的阅读,这样才能更加透彻的理解和使用该工具.
|
||||||
|
|
||||||
|
|
||||||
|
## 如何导出热更新资源
|
||||||
|
有2种方式:
|
||||||
|
- 1.插件的部署操作里面,你可以指定一个目录,该操作会将热更新的所有资源放到那个目录里面,你可以手动压缩这里的文件.
|
||||||
|
- 2.插件在执行**生成**操作的时候,会在 **项目目录/packVersion/** 下生成一个包含版本号的zip包,比如:ver_1.1.zip, 这个压缩文件就是你需要的热更新资源包
|
||||||
|
|
||||||
|
## 关于
|
||||||
|
- 该工具是自己游戏开发生涯中的一个小积累
|
||||||
|
- 如果你喜欢,请告诉你的小伙伴,
|
||||||
|
- 如果不喜欢,请告诉我哪里不好(企鹅 774177933),或者直接在Issues里面提问,帮助我完善它
|
||||||
|
|
||||||
|
## 其他文档
|
||||||
|
[更新记录](UPDATE.md)
|
||||||
|
[常见问题](CommonIssue.md)
|
||||||
|
## QQ打赏:
|
||||||
|
![enter image description here](http://7xq9nm.com1.z0.glb.clouddn.com/qqPay.png)
|
27
packages/hot-update-tools/UPDATE.md
Normal file
27
packages/hot-update-tools/UPDATE.md
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
## 简介
|
||||||
|
- 本工具仅仅是对官方的热更新方案的一个可视化解决方案,可以帮助你快速生成project.manifest和version.manifest文件,并且提供了本地测试的一些常用操作
|
||||||
|
- 使用前请移步官方热更新教程 https://github.com/cocos-creator/tutorial-hot-update
|
||||||
|
|
||||||
|
## 使用说明
|
||||||
|
- 详细的说明使用文档请前往
|
||||||
|
https://github.com/tidys/CocosCreatorPlugins/tree/master/packages/hot-update-tools
|
||||||
|
|
||||||
|
## 帮助
|
||||||
|
- 使用过程中如果遇到任何问题,欢迎加入QQ群224756137
|
||||||
|
## 更新内容
|
||||||
|
- [2017/06/12]
|
||||||
|
- 修复MD5计算不一致,导致更新失败
|
||||||
|
- 感谢反馈:http://forum.cocos.com/t/bug/47530
|
||||||
|
|
||||||
|
- [2017/12/10]
|
||||||
|
- 修复报错: too many open files
|
||||||
|
- 感谢反馈: http://forum.cocos.com/t/1-6-2-too-many-open-files/54221
|
||||||
|
|
||||||
|
- [2018/01/04]
|
||||||
|
- 在<生成Manifest配置>中增加了**资源服务器url配置历史**,方便多版本配置
|
||||||
|
- **资源服务器url** 中追加显示version,如果url存在问题,则不显示版本号
|
||||||
|
|
||||||
|
- [2018/01/06]
|
||||||
|
- 增加功能:如果再次使用工具未构建项目,点击生成的时候,提示构建项目!
|
||||||
|
- [2018/01/08]
|
||||||
|
- [增加] 生成manifest的同时,在 **项目目录/packVersion** 下生成该版本的热更资源包
|
128
packages/hot-update-tools/core/CfgUtil.js
Normal file
128
packages/hot-update-tools/core/CfgUtil.js
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
let fs = require('fire-fs');
|
||||||
|
let path = require('fire-path');
|
||||||
|
let electron = require('electron');
|
||||||
|
let FileUtil = Editor.require("packages://hot-update-tools/core/FileUtil");
|
||||||
|
|
||||||
|
|
||||||
|
let self = module.exports = {
|
||||||
|
cfgData: {
|
||||||
|
version: "",
|
||||||
|
serverRootDir: "",
|
||||||
|
resourceRootDir: "",
|
||||||
|
genManifestDir: "",
|
||||||
|
genProjectManifestFile: "",
|
||||||
|
localServerPath: "",
|
||||||
|
|
||||||
|
hotAddressArray: [],
|
||||||
|
buildTime: null,// 构建时间,全部保存int值
|
||||||
|
genTime: null,// manifest生成时间
|
||||||
|
genVersion: null,// manifest版本
|
||||||
|
},
|
||||||
|
updateBuildTimeByMain(time) {
|
||||||
|
// 在main.js中调用electron中没有remote属性
|
||||||
|
// Editor.log(electron.app.getPath('userData'));
|
||||||
|
let cfgPath = this._getAppCfgPath();
|
||||||
|
if (fs.existsSync(cfgPath)) {
|
||||||
|
let data = fs.readFileSync(cfgPath, 'utf-8');
|
||||||
|
let json = JSON.parse(data);
|
||||||
|
json.buildTime = time;
|
||||||
|
json.genTime = time;
|
||||||
|
fs.writeFileSync(cfgPath, JSON.stringify(json));
|
||||||
|
} else {
|
||||||
|
Editor.log("热更新配置文件不存在: " + cfgPath);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
updateBuildTime(time) {
|
||||||
|
this.cfgData.buildTime = time;
|
||||||
|
this.cfgData.genTime = time;
|
||||||
|
this._save();
|
||||||
|
},
|
||||||
|
updateGenTime(time, version) {
|
||||||
|
this.cfgData.genTime = time;
|
||||||
|
this.cfgData.genVersion = version;
|
||||||
|
this._save();
|
||||||
|
},
|
||||||
|
// 获取构建时间生成时间
|
||||||
|
getBuildTimeGenTime() {
|
||||||
|
let ret = { buildTime: null, genTime: null };
|
||||||
|
let cfgPath = this._getAppCfgPath();
|
||||||
|
if (fs.existsSync(cfgPath)) {
|
||||||
|
let data = fs.readFileSync(cfgPath, 'utf-8');
|
||||||
|
let json = JSON.parse(data);
|
||||||
|
ret.buildTime = json.buildTime;
|
||||||
|
ret.genTime = json.genTime;
|
||||||
|
this.cfgData.buildTime = json.buildTime;
|
||||||
|
this.cfgData.genTime = json.genTime;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
},
|
||||||
|
saveConfig(data) {
|
||||||
|
this.cfgData.version = data.version;
|
||||||
|
this.cfgData.genProjectManifestFile = data.genProjectManifestFile;
|
||||||
|
this.cfgData.serverRootDir = data.serverRootDir;
|
||||||
|
this.cfgData.resourceRootDir = data.resourceRootDir;
|
||||||
|
this.cfgData.localServerPath = data.localServerPath;
|
||||||
|
this.cfgData.hotAddressArray = data.hotAddressArray;
|
||||||
|
this._save();
|
||||||
|
},
|
||||||
|
_save() {
|
||||||
|
let configFilePath = self._getAppCfgPath();
|
||||||
|
let ret = fs.writeFileSync(configFilePath, JSON.stringify(this.cfgData));
|
||||||
|
console.log("保存配置成功!");
|
||||||
|
},
|
||||||
|
cleanConfig() {
|
||||||
|
fs.unlink(this._getAppCfgPath());
|
||||||
|
},
|
||||||
|
|
||||||
|
// manifest文件包地址
|
||||||
|
getMainFestDir() {
|
||||||
|
let userDataPath = electron.remote.app.getPath('userData');
|
||||||
|
return path.join(userDataPath, "hot-update-tools-manifestOutPut");
|
||||||
|
//输出文件不能存在在插件目录下,否则会造成插件刷新
|
||||||
|
// return Editor.url('packages://hot-update-tools/outPut');
|
||||||
|
},
|
||||||
|
// 获取打包目录地址,一般放在项目目录下
|
||||||
|
getPackZipDir() {
|
||||||
|
let userDataPath = electron.remote.app.getPath('userData');
|
||||||
|
return path.join(this._getAppRootPath(), "packVersion");
|
||||||
|
},
|
||||||
|
_getAppRootPath() {
|
||||||
|
let lib = Editor.libraryPath;
|
||||||
|
return lib.substring(0, lib.length - 7);
|
||||||
|
},
|
||||||
|
_getAppCfgPath() {
|
||||||
|
let userDataPath = null;
|
||||||
|
if (electron.remote) {
|
||||||
|
userDataPath = electron.remote.app.getPath('userData');
|
||||||
|
} else {
|
||||||
|
userDataPath = electron.app.getPath('userData');
|
||||||
|
}
|
||||||
|
|
||||||
|
let tar = Editor.libraryPath;
|
||||||
|
tar = tar.replace(/\\/g, '-');
|
||||||
|
tar = tar.replace(/:/g, '-');
|
||||||
|
tar = tar.replace(/\//g, '-');
|
||||||
|
return path.join(userDataPath, "hot-update-tools-cfg-" + tar + ".json");
|
||||||
|
// return Editor.url('packages://hot-update-tools/save/cfg.json');
|
||||||
|
},
|
||||||
|
initCfg(cb) {
|
||||||
|
let configFilePath = this._getAppCfgPath();
|
||||||
|
let b = FileUtil.isFileExit(configFilePath);
|
||||||
|
if (b) {
|
||||||
|
console.log("cfg path: " + configFilePath);
|
||||||
|
fs.readFile(configFilePath, 'utf-8', function (err, data) {
|
||||||
|
if (!err) {
|
||||||
|
let saveData = JSON.parse(data.toString());
|
||||||
|
self.cfgData = saveData;
|
||||||
|
if (cb) {
|
||||||
|
cb(saveData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.bind(self));
|
||||||
|
} else {
|
||||||
|
if (cb) {
|
||||||
|
cb(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
136
packages/hot-update-tools/core/FileUtil.js
Normal file
136
packages/hot-update-tools/core/FileUtil.js
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
let fs = require("fire-fs");
|
||||||
|
let path = require("fire-path");
|
||||||
|
|
||||||
|
let self = module.exports = {
|
||||||
|
getDirAllFiles(dirPath, result) {
|
||||||
|
let files = fs.readdirSync(dirPath);
|
||||||
|
files.forEach((val, index) => {
|
||||||
|
let fPath = path.join(dirPath, val);
|
||||||
|
let stats = fs.statSync(fPath);
|
||||||
|
if (stats.isDirectory()) {
|
||||||
|
this.getDirAllFiles(fPath, result);
|
||||||
|
} else if (stats.isFile()) {
|
||||||
|
result.push(fPath);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
getFileString(fileList, options) {
|
||||||
|
let curIndex = 0;
|
||||||
|
let totalIndex = fileList.length;
|
||||||
|
let str = {};
|
||||||
|
for (let key in fileList) {
|
||||||
|
let filePath = fileList[key];
|
||||||
|
let b = this._isFileExit(filePath);
|
||||||
|
if (b) {
|
||||||
|
fs.readFile(filePath, 'utf-8', function (err, data) {
|
||||||
|
if (!err) {
|
||||||
|
self._collectString(data, str);
|
||||||
|
} else {
|
||||||
|
console.log("error: " + filePath);
|
||||||
|
}
|
||||||
|
self._onCollectStep(filePath, ++curIndex, totalIndex, str, options);
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
self._onCollectStep(filePath, ++curIndex, totalIndex, str, options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_onCollectStep(filePath, cur, total, str, data) {
|
||||||
|
if (data && data.stepCb) {
|
||||||
|
data.stepCb(filePath, cur, total);
|
||||||
|
}
|
||||||
|
if (cur >= total) {
|
||||||
|
self._onCollectOver(str, data);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_onCollectOver(collectObjArr, data) {
|
||||||
|
let strArr = [];
|
||||||
|
let str = "";
|
||||||
|
for (let k in collectObjArr) {
|
||||||
|
str += k;
|
||||||
|
strArr.push(k);
|
||||||
|
}
|
||||||
|
// console.log("一共有" + strArr.length + "个字符, " + strArr);
|
||||||
|
console.log("一共有" + strArr.length + "个字符");
|
||||||
|
if (data && data.compCb) {
|
||||||
|
data.compCb(str);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mkDir(path) {
|
||||||
|
try {
|
||||||
|
fs.mkdirSync(path);
|
||||||
|
} catch (e) {
|
||||||
|
if (e.code !== 'EEXIST') throw e;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
isFileExit(file) {
|
||||||
|
try {
|
||||||
|
fs.accessSync(file, fs.F_OK);
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
_collectString(data, collectObject) {
|
||||||
|
for (let i in data) {
|
||||||
|
let char = data.charAt(i);
|
||||||
|
if (collectObject[char]) {
|
||||||
|
collectObject[char]++;
|
||||||
|
} else {
|
||||||
|
collectObject[char] = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
emptyDir(rootFile) {
|
||||||
|
//删除所有的文件(将所有文件夹置空)
|
||||||
|
let emptyDir = function (fileUrl) {
|
||||||
|
let files = fs.readdirSync(fileUrl);//读取该文件夹
|
||||||
|
for (let k in files) {
|
||||||
|
let filePath = path.join(fileUrl, files[k]);
|
||||||
|
let stats = fs.statSync(filePath);
|
||||||
|
if (stats.isDirectory()) {
|
||||||
|
emptyDir(filePath);
|
||||||
|
} else {
|
||||||
|
fs.unlinkSync(filePath);
|
||||||
|
console.log("删除文件:" + filePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
//删除所有的空文件夹
|
||||||
|
let rmEmptyDir = function (fileUrl) {
|
||||||
|
let files = fs.readdirSync(fileUrl);
|
||||||
|
if (files.length > 0) {
|
||||||
|
for (let k in files) {
|
||||||
|
let rmDir = path.join(fileUrl, files[k]);
|
||||||
|
rmEmptyDir(rmDir);
|
||||||
|
}
|
||||||
|
if (fileUrl !== rootFile) {// 不删除根目录
|
||||||
|
fs.rmdirSync(fileUrl);
|
||||||
|
console.log('删除空文件夹' + fileUrl);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (fileUrl !== rootFile) {// 不删除根目录
|
||||||
|
fs.rmdirSync(fileUrl);
|
||||||
|
console.log('删除空文件夹' + fileUrl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
emptyDir(rootFile);
|
||||||
|
rmEmptyDir(rootFile);
|
||||||
|
},
|
||||||
|
/*
|
||||||
|
is_fileType($('#uploadfile').val(), 'doc,pdf,txt,wps,odf,md,png,gif,jpg')
|
||||||
|
* */
|
||||||
|
is_fileType(filename, types) {
|
||||||
|
types = types.split(',');
|
||||||
|
let pattern = '\.(';
|
||||||
|
for (let i = 0; i < types.length; i++) {
|
||||||
|
if (0 !== i) {
|
||||||
|
pattern += '|';
|
||||||
|
}
|
||||||
|
pattern += types[i].trim();
|
||||||
|
}
|
||||||
|
pattern += ')$';
|
||||||
|
return new RegExp(pattern, 'i').test(filename);
|
||||||
|
}
|
||||||
|
}
|
141
packages/hot-update-tools/core/HttpService.js
Normal file
141
packages/hot-update-tools/core/HttpService.js
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
"use strict";
|
||||||
|
/**
|
||||||
|
* 处理内部逻辑发出HTTP请求
|
||||||
|
*/
|
||||||
|
|
||||||
|
var http = require("http");
|
||||||
|
var https = require('https');
|
||||||
|
var qs = require('querystring');
|
||||||
|
|
||||||
|
var HttpService = function(){
|
||||||
|
//todo
|
||||||
|
};
|
||||||
|
|
||||||
|
var pro = HttpService.prototype;
|
||||||
|
|
||||||
|
//发送HTTP GET请求
|
||||||
|
pro.sendHttpGetReq = function(hostName,port,path,param,cb){
|
||||||
|
console.log("sendHttpGetReq");
|
||||||
|
|
||||||
|
var content = qs.stringify(param);
|
||||||
|
console.log("content:",content);
|
||||||
|
|
||||||
|
var options = {
|
||||||
|
hostname: hostName,
|
||||||
|
port: port,
|
||||||
|
path: path+"?"+content,
|
||||||
|
method: 'GET'
|
||||||
|
};
|
||||||
|
|
||||||
|
console.log(options);
|
||||||
|
|
||||||
|
//todo 请求超时timer
|
||||||
|
var req = http.request(options, function (res) {
|
||||||
|
console.log('STATUS: ' + res.statusCode);
|
||||||
|
res.setEncoding('utf8');
|
||||||
|
res.on('data', function (chunk) {
|
||||||
|
cb(null,JSON.parse(chunk));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
req.on('error', function (e) {
|
||||||
|
console.log('problem with request: ' + e.message);
|
||||||
|
cb(new Error("err"),null)
|
||||||
|
});
|
||||||
|
|
||||||
|
req.end();
|
||||||
|
};
|
||||||
|
//发送HTTPS GET请求
|
||||||
|
pro.sendHttpsGetReq = function(hostName,port,path,param,cb){
|
||||||
|
|
||||||
|
console.log("sendHttpGetReq");
|
||||||
|
|
||||||
|
var content = qs.stringify(param);
|
||||||
|
|
||||||
|
https.get(hostName + ":" + port + path + "?"+content, function(res){
|
||||||
|
console.log('statusCode: ', res.statusCode);
|
||||||
|
res.on('data', function(d){
|
||||||
|
cb(null,JSON.parse(d.toString()))
|
||||||
|
});
|
||||||
|
|
||||||
|
}).on('error',function(e) {
|
||||||
|
console.error(e);
|
||||||
|
cb(e)
|
||||||
|
});
|
||||||
|
};
|
||||||
|
//发送HTTP POST请求
|
||||||
|
pro.sendHttpPostReq = function(hostName,port,path,param,cb){
|
||||||
|
|
||||||
|
console.log("sendHttpPostReq");
|
||||||
|
|
||||||
|
var content = qs.stringify(param);
|
||||||
|
console.log("content:",content);
|
||||||
|
|
||||||
|
var options = {
|
||||||
|
hostname: hostName,
|
||||||
|
port: port,
|
||||||
|
path: path,
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
"Content-Type": 'application/x-www-form-urlencoded',
|
||||||
|
"Content-Length": content.length
|
||||||
|
}
|
||||||
|
};
|
||||||
|
//todo 请求超时timer
|
||||||
|
var req = http.request(options, function (res) {
|
||||||
|
console.log('STATUS: ' + res.statusCode);
|
||||||
|
if (res.statusCode == 200) {
|
||||||
|
res.setEncoding('utf8');
|
||||||
|
var data = "";
|
||||||
|
res.on('data', function (chunk) {
|
||||||
|
data += chunk;
|
||||||
|
});
|
||||||
|
res.on('end', function () {
|
||||||
|
console.log(data);
|
||||||
|
cb(null,JSON.parse(data));
|
||||||
|
});
|
||||||
|
}else{
|
||||||
|
res.send(500, "error");
|
||||||
|
cb(new Error("err"),null)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
req.on('error', function (e) {
|
||||||
|
cb(new Error("err"),null)
|
||||||
|
});
|
||||||
|
|
||||||
|
req.write(content);
|
||||||
|
|
||||||
|
req.end();
|
||||||
|
|
||||||
|
};
|
||||||
|
//发送HTTPS POST请求
|
||||||
|
pro.sendHttpsPostReq = function(hostName,port,path,param,cb){
|
||||||
|
|
||||||
|
console.log("sendHttpsPostReq");
|
||||||
|
var content = qs.stringify(param);
|
||||||
|
|
||||||
|
path = path + "?" + content;
|
||||||
|
console.log("path=>",path);
|
||||||
|
|
||||||
|
var options = {
|
||||||
|
hostname: hostName,
|
||||||
|
port: port || 443,
|
||||||
|
path: path || '/',
|
||||||
|
method: 'POST'
|
||||||
|
};
|
||||||
|
|
||||||
|
https.request(options,function(res){
|
||||||
|
console.log('statusCode: ', res.statusCode);
|
||||||
|
res.on('data', function(d){
|
||||||
|
cb(null,JSON.parse(d.toString()))
|
||||||
|
});
|
||||||
|
|
||||||
|
}).on('error',function(e) {
|
||||||
|
console.error(e);
|
||||||
|
cb(e)
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = new HttpService();
|
3
packages/hot-update-tools/i18n/en.js
Normal file
3
packages/hot-update-tools/i18n/en.js
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
module.exports={
|
||||||
|
title:'hotUpdateTools',
|
||||||
|
};
|
3
packages/hot-update-tools/i18n/zh.js
Normal file
3
packages/hot-update-tools/i18n/zh.js
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
module.exports={
|
||||||
|
title:'热更新工具',
|
||||||
|
}
|
57
packages/hot-update-tools/mail/Mail.js
Normal file
57
packages/hot-update-tools/mail/Mail.js
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
'use strict';
|
||||||
|
let NodeMailer = Editor.require('packages://hot-update-tools/node_modules/nodemailer');
|
||||||
|
let Fs = require('fire-fs');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
_service: "qq",
|
||||||
|
_user: "xu_yanfeng@qq.com",
|
||||||
|
_pass: "fizyosflryzlbege",
|
||||||
|
|
||||||
|
setMailServiceInfo(user, pass) {
|
||||||
|
this._user = user;
|
||||||
|
this._pass = pass;
|
||||||
|
},
|
||||||
|
isArray(object) {
|
||||||
|
return object && typeof object === 'object' && Array == object.constructor;
|
||||||
|
},
|
||||||
|
sendMail(version, content, people, sendCb) {
|
||||||
|
let transporter = NodeMailer.createTransport({
|
||||||
|
service: this._service,
|
||||||
|
auth: {
|
||||||
|
user: this._user,
|
||||||
|
pass: this._pass, //授权码,通过QQ获取
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let sendPeople = ['xu_yanfeng@126.com'];
|
||||||
|
if (this.isArray(people)) {
|
||||||
|
for (let k in people) {
|
||||||
|
sendPeople.push(people[k]);
|
||||||
|
}
|
||||||
|
} else if (typeof people === "string") {
|
||||||
|
sendPeople.push(people);
|
||||||
|
}
|
||||||
|
let data = Fs.readFileSync(Editor.url('packages://hot-update-tools/mail/MailTemp.html', 'utf8')).toString();
|
||||||
|
if (data.indexOf('%version%') !== -1) {
|
||||||
|
data = data.replace("%version%", version);
|
||||||
|
}
|
||||||
|
if (data.indexOf('%content%') !== -1) {
|
||||||
|
data = data.replace("%content%", content);
|
||||||
|
}
|
||||||
|
let mailOptions = {
|
||||||
|
from: this._user, // 发送者
|
||||||
|
to: sendPeople.toString(), // 接受者,可以同时发送多个,以逗号隔开
|
||||||
|
subject: '测试版本 发布通知-v' + version, // 标题
|
||||||
|
text: 'Hello world', // 文本
|
||||||
|
html: data,
|
||||||
|
};
|
||||||
|
transporter.sendMail(mailOptions, function (err, info) {
|
||||||
|
if (sendCb) {
|
||||||
|
sendCb();
|
||||||
|
}
|
||||||
|
if (err) {
|
||||||
|
console.log(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
6
packages/hot-update-tools/mail/MailTemp.html
Normal file
6
packages/hot-update-tools/mail/MailTemp.html
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<h2>版本:%version%</h2>
|
||||||
|
<h2>更新内容</h2>
|
||||||
|
<h3>%content%</h3>
|
||||||
|
<h3>
|
||||||
|
<a href="https://fir.im/mdgame?release_id=5a4c41d1959d69315a0002a6">基础热更包下载</a>
|
||||||
|
</h3>
|
66
packages/hot-update-tools/main.js
Normal file
66
packages/hot-update-tools/main.js
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
module.exports = {
|
||||||
|
load() {
|
||||||
|
// 当 package 被正确加载的时候执行
|
||||||
|
},
|
||||||
|
|
||||||
|
unload() {
|
||||||
|
// 当 package 被正确卸载的时候执行
|
||||||
|
},
|
||||||
|
|
||||||
|
messages: {
|
||||||
|
'showPanel'() {
|
||||||
|
Editor.Panel.open('hot-update-tools');
|
||||||
|
},
|
||||||
|
'test'(event, args) {
|
||||||
|
console.log("1111111");
|
||||||
|
Editor.log(args);
|
||||||
|
Editor.Ipc.sendToPanel('hot-update-tools', 'hot-update-tools:onBuildFinished');
|
||||||
|
},
|
||||||
|
// 当插件构建完成的时候触发
|
||||||
|
'editor:build-finished': function (event, target) {
|
||||||
|
let Fs = require("fire-fs");
|
||||||
|
let Path = require("fire-path");
|
||||||
|
|
||||||
|
Editor.log("[HotUpdateTools] build platform:" + target.platform);
|
||||||
|
if (target.platform === "web-mobile" || target.platform === "web-desktop") {
|
||||||
|
Editor.log("[HotUpdateTools] don't need update main.js");
|
||||||
|
} else {
|
||||||
|
let root = Path.normalize(target.dest);
|
||||||
|
let url = Path.join(root, "main.js");
|
||||||
|
Fs.readFile(url, "utf8", function (err, data) {
|
||||||
|
if (err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
let newStr =
|
||||||
|
"(function () { \n" +
|
||||||
|
"\n" +
|
||||||
|
" if (cc && cc.sys.isNative) { \n" +
|
||||||
|
" var hotUpdateSearchPaths = cc.sys.localStorage.getItem('HotUpdateSearchPaths'); \n" +
|
||||||
|
" if (hotUpdateSearchPaths) { \n" +
|
||||||
|
" jsb.fileUtils.setSearchPaths(JSON.parse(hotUpdateSearchPaths)); \n" +
|
||||||
|
" console.log('[main.js] 热更新SearchPath: ' + JSON.parse(hotUpdateSearchPaths));\n" +
|
||||||
|
" }else {\n" +
|
||||||
|
" console.log('[main.js] 未获取到热更新资源路径!');\n" +
|
||||||
|
" }\n" +
|
||||||
|
" }else {\n" +
|
||||||
|
" console.log('[main.js] 不是native平台!');\n" +
|
||||||
|
" }\n";
|
||||||
|
|
||||||
|
let newData = data.replace("(function () {", newStr);
|
||||||
|
Fs.writeFile(url, newData, function (error) {
|
||||||
|
if (err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
Editor.log("[HotUpdateTools] SearchPath updated in built main.js for hot update");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let time = new Date().getTime();
|
||||||
|
// 通知panel更新时间
|
||||||
|
Editor.Ipc.sendToPanel('hot-update-tools', 'hot-update-tools:onBuildFinished', time);
|
||||||
|
// 写入本地
|
||||||
|
let CfgUtil = Editor.require('packages://hot-update-tools/core/CfgUtil.js');
|
||||||
|
CfgUtil.updateBuildTimeByMain(time);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
822
packages/hot-update-tools/package-lock.json
generated
Normal file
822
packages/hot-update-tools/package-lock.json
generated
Normal file
@ -0,0 +1,822 @@
|
|||||||
|
{
|
||||||
|
"name": "hot-update-tools",
|
||||||
|
"version": "0.0.3",
|
||||||
|
"lockfileVersion": 1,
|
||||||
|
"requires": true,
|
||||||
|
"dependencies": {
|
||||||
|
"address": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/address/-/address-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-z55ocwKBRLryBs394Sm3ushTtBeg6VAeuku7utSoSnsJKvKcnXFIyC6vh27n3rXyxSgkJBBCAvyOn7gSUcTYjg=="
|
||||||
|
},
|
||||||
|
"agent-base": {
|
||||||
|
"version": "4.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.0.tgz",
|
||||||
|
"integrity": "sha512-c+R/U5X+2zz2+UCrCFv6odQzJdoqI+YecuhnAJLa1zYaMc13zPfwMwZrr91Pd1DYNo/yPRbiM4WVf9whgwFsIg==",
|
||||||
|
"requires": {
|
||||||
|
"es6-promisify": "5.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"agentkeepalive": {
|
||||||
|
"version": "2.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-2.2.0.tgz",
|
||||||
|
"integrity": "sha1-xdG9SxKQCPEWPyNvhuX66iAm4u8="
|
||||||
|
},
|
||||||
|
"ali-oss": {
|
||||||
|
"version": "4.11.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/ali-oss/-/ali-oss-4.11.4.tgz",
|
||||||
|
"integrity": "sha1-S3GfOfbNkVtI/RN4RAEkFAK63Uc=",
|
||||||
|
"requires": {
|
||||||
|
"address": "1.0.3",
|
||||||
|
"agentkeepalive": "2.2.0",
|
||||||
|
"bowser": "1.9.1",
|
||||||
|
"co": "4.6.0",
|
||||||
|
"co-defer": "1.0.0",
|
||||||
|
"co-gather": "0.0.1",
|
||||||
|
"copy-to": "2.0.1",
|
||||||
|
"dateformat": "2.2.0",
|
||||||
|
"debug": "2.6.9",
|
||||||
|
"destroy": "1.0.4",
|
||||||
|
"end-or-error": "1.0.1",
|
||||||
|
"get-ready": "1.0.0",
|
||||||
|
"humanize-ms": "1.2.1",
|
||||||
|
"is-type-of": "1.2.0",
|
||||||
|
"merge-descriptors": "1.0.1",
|
||||||
|
"mime": "1.6.0",
|
||||||
|
"platform": "1.3.4",
|
||||||
|
"sdk-base": "2.0.1",
|
||||||
|
"urllib": "2.25.3",
|
||||||
|
"utility": "1.13.1",
|
||||||
|
"xml2js": "0.4.19"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"any-promise": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
|
||||||
|
"integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8="
|
||||||
|
},
|
||||||
|
"ast-types": {
|
||||||
|
"version": "0.10.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.10.1.tgz",
|
||||||
|
"integrity": "sha512-UY7+9DPzlJ9VM8eY0b2TUZcZvF+1pO0hzMtAyjBYKhOmnvRlqYNYnWdtsMj0V16CGaMlpL0G1jnLbLo4AyotuQ=="
|
||||||
|
},
|
||||||
|
"bowser": {
|
||||||
|
"version": "1.9.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/bowser/-/bowser-1.9.1.tgz",
|
||||||
|
"integrity": "sha512-UXti1JB6oK8hO983AImunnV6j/fqAEeDlPXh99zhsP5g32oLbxJJ6qcOaUesR+tqqhnUVQHlRJyD0dfiV0Hxaw=="
|
||||||
|
},
|
||||||
|
"bytes": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
|
||||||
|
"integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg="
|
||||||
|
},
|
||||||
|
"co": {
|
||||||
|
"version": "4.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
|
||||||
|
"integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ="
|
||||||
|
},
|
||||||
|
"co-defer": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/co-defer/-/co-defer-1.0.0.tgz",
|
||||||
|
"integrity": "sha1-Pkp4eo7tawoh7ih8CU9+jeDTyBg="
|
||||||
|
},
|
||||||
|
"co-gather": {
|
||||||
|
"version": "0.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/co-gather/-/co-gather-0.0.1.tgz",
|
||||||
|
"integrity": "sha1-76NfvvAsn2R9inQLP123MYYlNbw=",
|
||||||
|
"requires": {
|
||||||
|
"co-thread": "0.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"co-thread": {
|
||||||
|
"version": "0.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/co-thread/-/co-thread-0.0.1.tgz",
|
||||||
|
"integrity": "sha1-V3E/DvS4flWV1PI3Ef/ks7beXnQ="
|
||||||
|
},
|
||||||
|
"content-type": {
|
||||||
|
"version": "1.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
|
||||||
|
"integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
|
||||||
|
},
|
||||||
|
"copy-to": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/copy-to/-/copy-to-2.0.1.tgz",
|
||||||
|
"integrity": "sha1-JoD7uAaKSNCGVrYJgJK9r8kG9KU="
|
||||||
|
},
|
||||||
|
"core-js": {
|
||||||
|
"version": "2.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.3.0.tgz",
|
||||||
|
"integrity": "sha1-+rg/uwstjchfpjbEudNMdUIMbWU="
|
||||||
|
},
|
||||||
|
"core-util-is": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
|
||||||
|
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
|
||||||
|
},
|
||||||
|
"data-uri-to-buffer": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-vKQ9DTQPN1FLYiiEEOQ6IBGFqvjCa5rSK3cWMy/Nespm5d/x3dGFT9UBZnkLxCwua/IXBi2TYnwTEpsOvhC4UQ=="
|
||||||
|
},
|
||||||
|
"dateformat": {
|
||||||
|
"version": "2.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz",
|
||||||
|
"integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI="
|
||||||
|
},
|
||||||
|
"debug": {
|
||||||
|
"version": "2.6.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||||
|
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
||||||
|
"requires": {
|
||||||
|
"ms": "2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"deep-is": {
|
||||||
|
"version": "0.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
|
||||||
|
"integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ="
|
||||||
|
},
|
||||||
|
"default-user-agent": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/default-user-agent/-/default-user-agent-1.0.0.tgz",
|
||||||
|
"integrity": "sha1-FsRu/cq6PtxF8k8r1IaLAbfCrcY=",
|
||||||
|
"requires": {
|
||||||
|
"os-name": "1.0.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"degenerator": {
|
||||||
|
"version": "1.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/degenerator/-/degenerator-1.0.4.tgz",
|
||||||
|
"integrity": "sha1-/PSQo37OJmRk2cxDGrmMWBnO0JU=",
|
||||||
|
"requires": {
|
||||||
|
"ast-types": "0.10.1",
|
||||||
|
"escodegen": "1.9.0",
|
||||||
|
"esprima": "3.1.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"depd": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz",
|
||||||
|
"integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k="
|
||||||
|
},
|
||||||
|
"destroy": {
|
||||||
|
"version": "1.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
|
||||||
|
"integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
|
||||||
|
},
|
||||||
|
"digest-header": {
|
||||||
|
"version": "0.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/digest-header/-/digest-header-0.0.1.tgz",
|
||||||
|
"integrity": "sha1-Ecz23uxXZqw3l0TZAcEsuklRS+Y=",
|
||||||
|
"requires": {
|
||||||
|
"utility": "0.1.11"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"utility": {
|
||||||
|
"version": "0.1.11",
|
||||||
|
"resolved": "https://registry.npmjs.org/utility/-/utility-0.1.11.tgz",
|
||||||
|
"integrity": "sha1-/eYM+bTkdRlHoM9dEEzik2ciZxU=",
|
||||||
|
"requires": {
|
||||||
|
"address": "1.0.3"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ee-first": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
|
||||||
|
"integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
|
||||||
|
},
|
||||||
|
"end-or-error": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/end-or-error/-/end-or-error-1.0.1.tgz",
|
||||||
|
"integrity": "sha1-3HpiEP5403L+4kqLSJnb0VVBTcs="
|
||||||
|
},
|
||||||
|
"es6-promise": {
|
||||||
|
"version": "3.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.0.2.tgz",
|
||||||
|
"integrity": "sha1-AQ1YWEI6XxGJeWZfRkhqlcbuK7Y="
|
||||||
|
},
|
||||||
|
"es6-promisify": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz",
|
||||||
|
"integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=",
|
||||||
|
"requires": {
|
||||||
|
"es6-promise": "4.2.2"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"es6-promise": {
|
||||||
|
"version": "4.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.2.tgz",
|
||||||
|
"integrity": "sha512-LSas5vsuA6Q4nEdf9wokY5/AJYXry98i0IzXsv49rYsgDGDNDPbqAYR1Pe23iFxygfbGZNR/5VrHXBCh2BhvUQ=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"escape-html": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
|
||||||
|
"integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
|
||||||
|
},
|
||||||
|
"escodegen": {
|
||||||
|
"version": "1.9.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.9.0.tgz",
|
||||||
|
"integrity": "sha512-v0MYvNQ32bzwoG2OSFzWAkuahDQHK92JBN0pTAALJ4RIxEZe766QJPDR8Hqy7XNUy5K3fnVL76OqYAdc4TZEIw==",
|
||||||
|
"requires": {
|
||||||
|
"esprima": "3.1.3",
|
||||||
|
"estraverse": "4.2.0",
|
||||||
|
"esutils": "2.0.2",
|
||||||
|
"optionator": "0.8.2",
|
||||||
|
"source-map": "0.5.7"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"esprima": {
|
||||||
|
"version": "3.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz",
|
||||||
|
"integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM="
|
||||||
|
},
|
||||||
|
"estraverse": {
|
||||||
|
"version": "4.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz",
|
||||||
|
"integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM="
|
||||||
|
},
|
||||||
|
"esutils": {
|
||||||
|
"version": "2.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
|
||||||
|
"integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs="
|
||||||
|
},
|
||||||
|
"extend": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz",
|
||||||
|
"integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ="
|
||||||
|
},
|
||||||
|
"fast-levenshtein": {
|
||||||
|
"version": "2.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
|
||||||
|
"integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc="
|
||||||
|
},
|
||||||
|
"file-uri-to-path": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw=="
|
||||||
|
},
|
||||||
|
"ftp": {
|
||||||
|
"version": "0.3.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/ftp/-/ftp-0.3.10.tgz",
|
||||||
|
"integrity": "sha1-kZfYYa2BQvPmPVqDv+TFn3MwiF0=",
|
||||||
|
"requires": {
|
||||||
|
"readable-stream": "1.1.14",
|
||||||
|
"xregexp": "2.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"isarray": {
|
||||||
|
"version": "0.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
|
||||||
|
"integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
|
||||||
|
},
|
||||||
|
"readable-stream": {
|
||||||
|
"version": "1.1.14",
|
||||||
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
|
||||||
|
"integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
|
||||||
|
"requires": {
|
||||||
|
"core-util-is": "1.0.2",
|
||||||
|
"inherits": "2.0.3",
|
||||||
|
"isarray": "0.0.1",
|
||||||
|
"string_decoder": "0.10.31"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"get-ready": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/get-ready/-/get-ready-1.0.0.tgz",
|
||||||
|
"integrity": "sha1-+RgX8emt7P6hOlYq38jeiDqzR4I="
|
||||||
|
},
|
||||||
|
"get-uri": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/get-uri/-/get-uri-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-7aelVrYqCLuVjq2kEKRTH8fXPTC0xKTkM+G7UlFkEwCXY3sFbSxvY375JoFowOAYbkaU47SrBvOefUlLZZ+6QA==",
|
||||||
|
"requires": {
|
||||||
|
"data-uri-to-buffer": "1.2.0",
|
||||||
|
"debug": "2.6.9",
|
||||||
|
"extend": "3.0.1",
|
||||||
|
"file-uri-to-path": "1.0.0",
|
||||||
|
"ftp": "0.3.10",
|
||||||
|
"readable-stream": "2.0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"http-errors": {
|
||||||
|
"version": "1.6.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz",
|
||||||
|
"integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=",
|
||||||
|
"requires": {
|
||||||
|
"depd": "1.1.1",
|
||||||
|
"inherits": "2.0.3",
|
||||||
|
"setprototypeof": "1.0.3",
|
||||||
|
"statuses": "1.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"http-proxy-agent": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-1.0.0.tgz",
|
||||||
|
"integrity": "sha1-zBzjjkU7+YSg93AtLdWcc9CBKEo=",
|
||||||
|
"requires": {
|
||||||
|
"agent-base": "2.1.1",
|
||||||
|
"debug": "2.6.9",
|
||||||
|
"extend": "3.0.1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"agent-base": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-2.1.1.tgz",
|
||||||
|
"integrity": "sha1-1t4Q1a9hMtW9aSQn1G/FOFOQlMc=",
|
||||||
|
"requires": {
|
||||||
|
"extend": "3.0.1",
|
||||||
|
"semver": "5.0.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"semver": {
|
||||||
|
"version": "5.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/semver/-/semver-5.0.3.tgz",
|
||||||
|
"integrity": "sha1-d0Zt5YnNXTyV8TiqeLxWmjy10no="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"https-proxy-agent": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz",
|
||||||
|
"integrity": "sha1-NffabEjOTdv6JkiRrFk+5f+GceY=",
|
||||||
|
"requires": {
|
||||||
|
"agent-base": "2.1.1",
|
||||||
|
"debug": "2.6.9",
|
||||||
|
"extend": "3.0.1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"agent-base": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-2.1.1.tgz",
|
||||||
|
"integrity": "sha1-1t4Q1a9hMtW9aSQn1G/FOFOQlMc=",
|
||||||
|
"requires": {
|
||||||
|
"extend": "3.0.1",
|
||||||
|
"semver": "5.0.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"semver": {
|
||||||
|
"version": "5.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/semver/-/semver-5.0.3.tgz",
|
||||||
|
"integrity": "sha1-d0Zt5YnNXTyV8TiqeLxWmjy10no="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"humanize-ms": {
|
||||||
|
"version": "1.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz",
|
||||||
|
"integrity": "sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=",
|
||||||
|
"requires": {
|
||||||
|
"ms": "2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"iconv-lite": {
|
||||||
|
"version": "0.4.19",
|
||||||
|
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz",
|
||||||
|
"integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ=="
|
||||||
|
},
|
||||||
|
"immediate": {
|
||||||
|
"version": "3.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
|
||||||
|
"integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps="
|
||||||
|
},
|
||||||
|
"inherits": {
|
||||||
|
"version": "2.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
|
||||||
|
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
|
||||||
|
},
|
||||||
|
"ip": {
|
||||||
|
"version": "1.1.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz",
|
||||||
|
"integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo="
|
||||||
|
},
|
||||||
|
"is-class": {
|
||||||
|
"version": "0.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-class/-/is-class-0.0.4.tgz",
|
||||||
|
"integrity": "sha1-4FdFFwW7NOOePjNZjJOpg3KWtzY="
|
||||||
|
},
|
||||||
|
"is-type-of": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-type-of/-/is-type-of-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-10ezBXuEDp3Fp/jPCaVd4hSrAEj2lPyr1LT7+cWi9HCLd15wbh9X8dJfTDB+ZgkZSCGTG2TF6f61ugI5mSlhDA==",
|
||||||
|
"requires": {
|
||||||
|
"core-util-is": "1.0.2",
|
||||||
|
"is-class": "0.0.4",
|
||||||
|
"isstream": "0.1.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"isarray": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
||||||
|
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
|
||||||
|
},
|
||||||
|
"isstream": {
|
||||||
|
"version": "0.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
|
||||||
|
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
|
||||||
|
},
|
||||||
|
"jquery": {
|
||||||
|
"version": "3.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.2.1.tgz",
|
||||||
|
"integrity": "sha1-XE2d5lKvbNCncBVKYxu6ErAVx4c="
|
||||||
|
},
|
||||||
|
"jszip": {
|
||||||
|
"version": "3.1.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/jszip/-/jszip-3.1.5.tgz",
|
||||||
|
"integrity": "sha512-5W8NUaFRFRqTOL7ZDDrx5qWHJyBXy6velVudIzQUSoqAAYqzSh2Z7/m0Rf1QbmQJccegD0r+YZxBjzqoBiEeJQ==",
|
||||||
|
"requires": {
|
||||||
|
"core-js": "2.3.0",
|
||||||
|
"es6-promise": "3.0.2",
|
||||||
|
"lie": "3.1.1",
|
||||||
|
"pako": "1.0.6",
|
||||||
|
"readable-stream": "2.0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"levn": {
|
||||||
|
"version": "0.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
|
||||||
|
"integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=",
|
||||||
|
"requires": {
|
||||||
|
"prelude-ls": "1.1.2",
|
||||||
|
"type-check": "0.3.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"lie": {
|
||||||
|
"version": "3.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz",
|
||||||
|
"integrity": "sha1-mkNrLMd0bKWd56QfpGmz77dr2H4=",
|
||||||
|
"requires": {
|
||||||
|
"immediate": "3.0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"lru-cache": {
|
||||||
|
"version": "2.7.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz",
|
||||||
|
"integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI="
|
||||||
|
},
|
||||||
|
"merge-descriptors": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
|
||||||
|
"integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
|
||||||
|
},
|
||||||
|
"mime": {
|
||||||
|
"version": "1.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
|
||||||
|
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
|
||||||
|
},
|
||||||
|
"minimist": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
|
||||||
|
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
|
||||||
|
},
|
||||||
|
"mkdirp": {
|
||||||
|
"version": "0.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
|
||||||
|
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
|
||||||
|
"requires": {
|
||||||
|
"minimist": "0.0.8"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"minimist": {
|
||||||
|
"version": "0.0.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
|
||||||
|
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ms": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||||
|
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
|
||||||
|
},
|
||||||
|
"mz": {
|
||||||
|
"version": "2.7.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
|
||||||
|
"integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
|
||||||
|
"requires": {
|
||||||
|
"any-promise": "1.3.0",
|
||||||
|
"object-assign": "4.1.1",
|
||||||
|
"thenify-all": "1.6.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"netmask": {
|
||||||
|
"version": "1.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/netmask/-/netmask-1.0.6.tgz",
|
||||||
|
"integrity": "sha1-ICl+idhvb2QA8lDZ9Pa0wZRfzTU="
|
||||||
|
},
|
||||||
|
"nodemailer": {
|
||||||
|
"version": "4.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-4.4.1.tgz",
|
||||||
|
"integrity": "sha512-1bnszJJXatcHJhLpxQ1XMkLDjCjPKvGKMtRQ73FOsoNln3UQjddEQmz6fAwM3aj0GtQ3dQX9qtMHPelz63GU7A=="
|
||||||
|
},
|
||||||
|
"object-assign": {
|
||||||
|
"version": "4.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||||
|
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
|
||||||
|
},
|
||||||
|
"optionator": {
|
||||||
|
"version": "0.8.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz",
|
||||||
|
"integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=",
|
||||||
|
"requires": {
|
||||||
|
"deep-is": "0.1.3",
|
||||||
|
"fast-levenshtein": "2.0.6",
|
||||||
|
"levn": "0.3.0",
|
||||||
|
"prelude-ls": "1.1.2",
|
||||||
|
"type-check": "0.3.2",
|
||||||
|
"wordwrap": "1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"os-name": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/os-name/-/os-name-1.0.3.tgz",
|
||||||
|
"integrity": "sha1-GzefZINa98Wn9JizV8uVIVwVnt8=",
|
||||||
|
"requires": {
|
||||||
|
"osx-release": "1.1.0",
|
||||||
|
"win-release": "1.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"osx-release": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/osx-release/-/osx-release-1.1.0.tgz",
|
||||||
|
"integrity": "sha1-8heRGigTaUmvG/kwiyQeJzfTzWw=",
|
||||||
|
"requires": {
|
||||||
|
"minimist": "1.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pac-proxy-agent": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-t57UiJpi5mFLTvjheC1SNSwIhml3+ElNOj69iRrydtQXZJr8VIFYSDtyPi/3ZysA62kD2dmww6pDlzk0VaONZg==",
|
||||||
|
"requires": {
|
||||||
|
"agent-base": "2.1.1",
|
||||||
|
"debug": "2.6.9",
|
||||||
|
"get-uri": "2.0.1",
|
||||||
|
"http-proxy-agent": "1.0.0",
|
||||||
|
"https-proxy-agent": "1.0.0",
|
||||||
|
"pac-resolver": "3.0.0",
|
||||||
|
"raw-body": "2.3.2",
|
||||||
|
"socks-proxy-agent": "3.0.1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"agent-base": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-2.1.1.tgz",
|
||||||
|
"integrity": "sha1-1t4Q1a9hMtW9aSQn1G/FOFOQlMc=",
|
||||||
|
"requires": {
|
||||||
|
"extend": "3.0.1",
|
||||||
|
"semver": "5.0.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"semver": {
|
||||||
|
"version": "5.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/semver/-/semver-5.0.3.tgz",
|
||||||
|
"integrity": "sha1-d0Zt5YnNXTyV8TiqeLxWmjy10no="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pac-resolver": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-tcc38bsjuE3XZ5+4vP96OfhOugrX+JcnpUbhfuc4LuXBLQhoTthOstZeoQJBDnQUDYzYmdImKsbz0xSl1/9qeA==",
|
||||||
|
"requires": {
|
||||||
|
"co": "4.6.0",
|
||||||
|
"degenerator": "1.0.4",
|
||||||
|
"ip": "1.1.5",
|
||||||
|
"netmask": "1.0.6",
|
||||||
|
"thunkify": "2.1.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pako": {
|
||||||
|
"version": "1.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz",
|
||||||
|
"integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg=="
|
||||||
|
},
|
||||||
|
"platform": {
|
||||||
|
"version": "1.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/platform/-/platform-1.3.4.tgz",
|
||||||
|
"integrity": "sha1-bw+xftqqSPIUQrOpdcBjEw8cPr0="
|
||||||
|
},
|
||||||
|
"prelude-ls": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
|
||||||
|
"integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ="
|
||||||
|
},
|
||||||
|
"process-nextick-args": {
|
||||||
|
"version": "1.0.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
|
||||||
|
"integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M="
|
||||||
|
},
|
||||||
|
"proxy-agent": {
|
||||||
|
"version": "2.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-2.2.0.tgz",
|
||||||
|
"integrity": "sha512-cmWjNB7/5pVrYAFAt+6ppLyUAWd4LhWw47hkUISXHAieM5jT2PWjhh1dbpHUEX3lJhWjAqdNGrW8RnUFfLCU9w==",
|
||||||
|
"requires": {
|
||||||
|
"agent-base": "4.2.0",
|
||||||
|
"debug": "2.6.9",
|
||||||
|
"http-proxy-agent": "1.0.0",
|
||||||
|
"https-proxy-agent": "1.0.0",
|
||||||
|
"lru-cache": "2.7.3",
|
||||||
|
"pac-proxy-agent": "2.0.0",
|
||||||
|
"socks-proxy-agent": "3.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"qs": {
|
||||||
|
"version": "6.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz",
|
||||||
|
"integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A=="
|
||||||
|
},
|
||||||
|
"raw-body": {
|
||||||
|
"version": "2.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz",
|
||||||
|
"integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=",
|
||||||
|
"requires": {
|
||||||
|
"bytes": "3.0.0",
|
||||||
|
"http-errors": "1.6.2",
|
||||||
|
"iconv-lite": "0.4.19",
|
||||||
|
"unpipe": "1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"readable-stream": {
|
||||||
|
"version": "2.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz",
|
||||||
|
"integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=",
|
||||||
|
"requires": {
|
||||||
|
"core-util-is": "1.0.2",
|
||||||
|
"inherits": "2.0.3",
|
||||||
|
"isarray": "1.0.0",
|
||||||
|
"process-nextick-args": "1.0.7",
|
||||||
|
"string_decoder": "0.10.31",
|
||||||
|
"util-deprecate": "1.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sax": {
|
||||||
|
"version": "1.2.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
|
||||||
|
"integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
|
||||||
|
},
|
||||||
|
"sdk-base": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/sdk-base/-/sdk-base-2.0.1.tgz",
|
||||||
|
"integrity": "sha1-ukAonovfJy7RHdnql+r5jgNtJMY=",
|
||||||
|
"requires": {
|
||||||
|
"get-ready": "1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"semver": {
|
||||||
|
"version": "5.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz",
|
||||||
|
"integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA=="
|
||||||
|
},
|
||||||
|
"setprototypeof": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz",
|
||||||
|
"integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ="
|
||||||
|
},
|
||||||
|
"smart-buffer": {
|
||||||
|
"version": "1.1.15",
|
||||||
|
"resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-1.1.15.tgz",
|
||||||
|
"integrity": "sha1-fxFLW2X6s+KjWqd1uxLw0cZJvxY="
|
||||||
|
},
|
||||||
|
"socks": {
|
||||||
|
"version": "1.1.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/socks/-/socks-1.1.10.tgz",
|
||||||
|
"integrity": "sha1-W4t/x8jzQcU+0FbpKbe/Tei6e1o=",
|
||||||
|
"requires": {
|
||||||
|
"ip": "1.1.5",
|
||||||
|
"smart-buffer": "1.1.15"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"socks-proxy-agent": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-ZwEDymm204mTzvdqyUqOdovVr2YRd2NYskrYrF2LXyZ9qDiMAoFESGK8CRphiO7rtbo2Y757k2Nia3x2hGtalA==",
|
||||||
|
"requires": {
|
||||||
|
"agent-base": "4.2.0",
|
||||||
|
"socks": "1.1.10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"source-map": {
|
||||||
|
"version": "0.5.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
|
||||||
|
"integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"statuses": {
|
||||||
|
"version": "1.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz",
|
||||||
|
"integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew=="
|
||||||
|
},
|
||||||
|
"string_decoder": {
|
||||||
|
"version": "0.10.31",
|
||||||
|
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
|
||||||
|
"integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
|
||||||
|
},
|
||||||
|
"thenify": {
|
||||||
|
"version": "3.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.0.tgz",
|
||||||
|
"integrity": "sha1-5p44obq+lpsBCCB5eLn2K4hgSDk=",
|
||||||
|
"requires": {
|
||||||
|
"any-promise": "1.3.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"thenify-all": {
|
||||||
|
"version": "1.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
|
||||||
|
"integrity": "sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY=",
|
||||||
|
"requires": {
|
||||||
|
"thenify": "3.3.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"thunkify": {
|
||||||
|
"version": "2.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/thunkify/-/thunkify-2.1.2.tgz",
|
||||||
|
"integrity": "sha1-+qDp0jDFGsyVyhOjYawFyn4EVT0="
|
||||||
|
},
|
||||||
|
"type-check": {
|
||||||
|
"version": "0.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
|
||||||
|
"integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=",
|
||||||
|
"requires": {
|
||||||
|
"prelude-ls": "1.1.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"unpipe": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
|
||||||
|
"integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
|
||||||
|
},
|
||||||
|
"urllib": {
|
||||||
|
"version": "2.25.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/urllib/-/urllib-2.25.3.tgz",
|
||||||
|
"integrity": "sha512-CqPp/0GWdX09HwdnjypiW9U7mPzV8dfDyxhMnHyamT7vd6Ht+pmb2VgYh0hNw5luDjxEH81ElWxCWebQ0VNzWw==",
|
||||||
|
"requires": {
|
||||||
|
"any-promise": "1.3.0",
|
||||||
|
"content-type": "1.0.4",
|
||||||
|
"debug": "2.6.9",
|
||||||
|
"default-user-agent": "1.0.0",
|
||||||
|
"digest-header": "0.0.1",
|
||||||
|
"ee-first": "1.1.1",
|
||||||
|
"humanize-ms": "1.2.1",
|
||||||
|
"iconv-lite": "0.4.19",
|
||||||
|
"proxy-agent": "2.2.0",
|
||||||
|
"qs": "6.5.1",
|
||||||
|
"statuses": "1.4.0",
|
||||||
|
"utility": "1.13.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"util-deprecate": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||||
|
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
|
||||||
|
},
|
||||||
|
"utility": {
|
||||||
|
"version": "1.13.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/utility/-/utility-1.13.1.tgz",
|
||||||
|
"integrity": "sha512-OQYqjyhHSCeSm+IziPHNbLc+WR3jUNa3goeyLoiITV1saN/BesDDsUIvh1LTRXa3XO2UpobByW//mm5p62/9tQ==",
|
||||||
|
"requires": {
|
||||||
|
"copy-to": "2.0.1",
|
||||||
|
"escape-html": "1.0.3",
|
||||||
|
"mkdirp": "0.5.1",
|
||||||
|
"mz": "2.7.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"win-release": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/win-release/-/win-release-1.1.1.tgz",
|
||||||
|
"integrity": "sha1-X6VeAr58qTTt/BJmVjLoSbcuUgk=",
|
||||||
|
"requires": {
|
||||||
|
"semver": "5.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"wordwrap": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
|
||||||
|
"integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus="
|
||||||
|
},
|
||||||
|
"xml2js": {
|
||||||
|
"version": "0.4.19",
|
||||||
|
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz",
|
||||||
|
"integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==",
|
||||||
|
"requires": {
|
||||||
|
"sax": "1.2.4",
|
||||||
|
"xmlbuilder": "9.0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"xmlbuilder": {
|
||||||
|
"version": "9.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.4.tgz",
|
||||||
|
"integrity": "sha1-UZy0ymhtAFqEINNJbz8MruzKWA8="
|
||||||
|
},
|
||||||
|
"xregexp": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/xregexp/-/xregexp-2.0.0.tgz",
|
||||||
|
"integrity": "sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
28
packages/hot-update-tools/package.json
Normal file
28
packages/hot-update-tools/package.json
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
{
|
||||||
|
"name": "hot-update-tools",
|
||||||
|
"version": "0.0.3",
|
||||||
|
"description": "hotUpdateTools",
|
||||||
|
"author": "xu_yanfeng",
|
||||||
|
"main": "main.js",
|
||||||
|
"main-menu": {
|
||||||
|
"i18n:MAIN_MENU.project.title/i18n:hot-update-tools.title": {
|
||||||
|
"icon": "icon.png",
|
||||||
|
"accelerator": "CmdOrCtrl+u",
|
||||||
|
"message": "hot-update-tools:showPanel"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"panel": {
|
||||||
|
"main": "panel/index.js",
|
||||||
|
"type": "dockable",
|
||||||
|
"title": "hotUpdateTools",
|
||||||
|
"width": 900,
|
||||||
|
"height": 900
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"ali-oss": "^4.11.4",
|
||||||
|
"co": "^4.6.0",
|
||||||
|
"jquery": "^3.2.1",
|
||||||
|
"jszip": "^3.1.5",
|
||||||
|
"nodemailer": "^4.4.1"
|
||||||
|
}
|
||||||
|
}
|
14
packages/hot-update-tools/panel/index.css
Normal file
14
packages/hot-update-tools/panel/index.css
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
:host {
|
||||||
|
margin: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
color: #11ff00;
|
||||||
|
}
|
||||||
|
|
||||||
|
ui-section {
|
||||||
|
overflow-y: auto;
|
||||||
|
margin: 0px 0px;
|
||||||
|
padding: 0 0px;
|
||||||
|
flex: 1
|
||||||
|
}
|
222
packages/hot-update-tools/panel/index.html
Normal file
222
packages/hot-update-tools/panel/index.html
Normal file
@ -0,0 +1,222 @@
|
|||||||
|
<div class="layout vertical" style="height: 100%" xmlns:v-bind="http://www.w3.org/1999/xhtml">
|
||||||
|
<!--<div class="layout horizontal start-justified center">-->
|
||||||
|
<!--<ui-select class="flex-3" v-on:change="onIpSelectChange" id="ipSelection">-->
|
||||||
|
|
||||||
|
<!--<template v-for="ip in hotAddressArray">-->
|
||||||
|
<!--<option v-bind:value="ip">{{ip}}</option>-->
|
||||||
|
<!--</template>-->
|
||||||
|
<!--</ui-select>-->
|
||||||
|
<!--<ui-button v-disabled="false" v-on:confirm="onTestSelect">add select</ui-button>-->
|
||||||
|
<!--<ui-button v-disabled="false" v-on:confirm="onLogIp">ip</ui-button>-->
|
||||||
|
<!--</div>-->
|
||||||
|
<div class="layout vertical start-justified">
|
||||||
|
<h2>生成Manifest配置</h2>
|
||||||
|
<!-- <ui-prop name="版本号">
|
||||||
|
<div class="flex-1 layout horizontal center">
|
||||||
|
<ui-input class="flex-1" v-on:blur="onInputVersionOver" v-value="version"></ui-input>
|
||||||
|
<1!--<ui-button v-on:confirm="onTest">测试</ui-button>--1>
|
||||||
|
</div>
|
||||||
|
</ui-prop> -->
|
||||||
|
|
||||||
|
<ui-prop name="资源服务器url" tooltip="游戏热更新服务器的url">
|
||||||
|
<div class="flex-1 layout horizontal center">
|
||||||
|
<ui-input class="flex-2" v-on:blur="onInPutUrlOver" v-value="serverRootDir"></ui-input>
|
||||||
|
<!--<ui-button v-on:confirm="onTestUrl">Test URL</ui-button>-->
|
||||||
|
<!--<ui-button v-on:confirm="onOpenUrl">浏览器访问</ui-button>-->
|
||||||
|
<ui-input style="width: 100px;" readonly v-value="remoteServerVersion" v-if="isShowRemoteServerVersion">
|
||||||
|
</ui-input>
|
||||||
|
<ui-button v-on:confirm="userLocalIP">使用本机IP</ui-button>
|
||||||
|
</div>
|
||||||
|
</ui-prop>
|
||||||
|
<!------------------------------配置历史-------------------------------->
|
||||||
|
<ui-prop name="资源服务器url配置历史">
|
||||||
|
<div class="flex-1 layout horizontal center">
|
||||||
|
<ui-select class="flex-2" style="width: auto" id="hotAddressSelect"
|
||||||
|
v-on:change="onChangeSelectHotAddress">
|
||||||
|
<option v-for="(index, address) in hotAddressArray" v-bind:value="address">
|
||||||
|
{{'['+index+'] ' +address}}
|
||||||
|
</option>
|
||||||
|
</ui-select>
|
||||||
|
<ui-button class="green" v-on:confirm="onBtnClickUseSelectedHotAddress" v-show="isShowUseAddrBtn">使用
|
||||||
|
</ui-button>
|
||||||
|
<ui-button class="red" v-on:confirm="onBtnClickDelSelectedHotAddress" v-show="isShowDelAddrBtn">删除
|
||||||
|
</ui-button>
|
||||||
|
</div>
|
||||||
|
</ui-prop>
|
||||||
|
|
||||||
|
<ui-prop name="項目熱更配置文件(project.mainfest)">
|
||||||
|
<div class="flex-1 layout horizontal center">
|
||||||
|
<ui-input class="flex-2" readonly disabled v-value="genProjectManifestFile"></ui-input>
|
||||||
|
<ui-button v-on:confirm="onSelectGenProjectManifestFile">选择</ui-button>
|
||||||
|
<ui-button v-on:confirm="onOpenProjectManifestFile">
|
||||||
|
<i class="icon-doc-text"></i>
|
||||||
|
<!--打开-->
|
||||||
|
</ui-button>
|
||||||
|
</div>
|
||||||
|
</ui-prop>
|
||||||
|
|
||||||
|
<ui-prop name="build项目资源文件目录">
|
||||||
|
<div class="flex-1 layout horizontal center">
|
||||||
|
<ui-input class="flex-2" readonly disabled v-value="resourceRootDir"></ui-input>
|
||||||
|
<ui-button v-on:confirm="onSelectResourceRootDir">选择</ui-button>
|
||||||
|
<ui-button v-on:confirm="onOpenResourceDir">
|
||||||
|
<i class="icon-doc-text"></i>
|
||||||
|
<!--打开-->
|
||||||
|
</ui-button>
|
||||||
|
</div>
|
||||||
|
</ui-prop>
|
||||||
|
|
||||||
|
<ui-prop name="manifest存储目录">
|
||||||
|
<div class="flex-1 layout horizontal center">
|
||||||
|
<ui-input class="flex-2" readonly disabled v-value="genManifestDir"></ui-input>
|
||||||
|
<!--<ui-button v-on:confirm="onSelectGenManifestDir">选择</ui-button>-->
|
||||||
|
<ui-button v-on:confirm="onOpenManifestDir">
|
||||||
|
<i class="icon-doc-text"></i>
|
||||||
|
<!--打开-->
|
||||||
|
</ui-button>
|
||||||
|
</div>
|
||||||
|
</ui-prop>
|
||||||
|
|
||||||
|
<div class="self-end">
|
||||||
|
<!--<ui-button class="self-start" v-on:confirm="onCleanAPPCfg">-->
|
||||||
|
<!--清除APP配置-->
|
||||||
|
<!--</ui-button>-->
|
||||||
|
<!--<ui-button class="self-end green" v-on:confirm="onBtnClickPackVersion"> 压缩打包</ui-button>-->
|
||||||
|
<ui-button class="self-end red" v-on:confirm="onClickClear"> 清除Log</ui-button>
|
||||||
|
<ui-button class="self-end blue" v-on:confirm="onClickPrintProjectManifest"> 查看版號</ui-button>
|
||||||
|
<ui-button class="self-end green" v-on:confirm="onClickGenCfg"> 生成</ui-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- <div class="layout vertical">
|
||||||
|
<h2> 当前游戏配置</h2>
|
||||||
|
<ui-prop name="项目热更配置文件(project.mainfest)">
|
||||||
|
<div class="flex-1 layout horizontal center">
|
||||||
|
<ui-input class="flex-1" disabled v-value="localGameProjectManifest"></ui-input>
|
||||||
|
<ui-button v-on:confirm="onOpenLocalGameManifestDir">
|
||||||
|
<i class="icon-doc-text"></i>
|
||||||
|
<1!--打开文件夹--1>
|
||||||
|
</ui-button>
|
||||||
|
</div>
|
||||||
|
</ui-prop>
|
||||||
|
<ui-prop name="项目热更配置文件(version.mainfest)">
|
||||||
|
<div class="flex-1 layout horizontal center">
|
||||||
|
<ui-input class="flex-1" disabled v-value="localGameVersionManifest"></ui-input>
|
||||||
|
<ui-button v-on:confirm="onOpenLocalGameManifestDir">
|
||||||
|
<i class="icon-doc-text"></i>
|
||||||
|
<1!--打开文件夹--1>
|
||||||
|
</ui-button>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</ui-prop>
|
||||||
|
<ui-prop name="package url:">
|
||||||
|
<div class="flex-1 layout horizontal center">
|
||||||
|
<h4 class="flex-2">{{localGamePackageUrl}}</h4>
|
||||||
|
</div>
|
||||||
|
</ui-prop>
|
||||||
|
<ui-prop name="游戏版本号:">
|
||||||
|
<div class="flex-1 layout horizontal center">
|
||||||
|
<h4 class="flex-2">{{localGameVersion}}</h4>
|
||||||
|
<ui-button title="将生成的2个manifest文件导入到项目中" class="end-justified blue"
|
||||||
|
v-on:confirm="importManifestToGame">
|
||||||
|
导入manifest
|
||||||
|
</ui-button>
|
||||||
|
<ui-button class="end-justified" v-on:confirm="initLocalGameVersion">
|
||||||
|
<i class="icon-arrows-cw"></i>
|
||||||
|
<1!--刷新--1>
|
||||||
|
</ui-button>
|
||||||
|
</div>
|
||||||
|
</ui-prop>
|
||||||
|
</div> -->
|
||||||
|
<!--------------------------------测试环境----------------------------------------------->
|
||||||
|
<div class="layout vertical">
|
||||||
|
<div class="layout horizontal center">
|
||||||
|
<h2>测试环境 - </h2>
|
||||||
|
<div style="display: none">
|
||||||
|
<ui-select class="" v-on:change="onTestEnvChange" v-value="testEnvSelect" id="testEnvSelect">
|
||||||
|
<option value='0'>本地</option>
|
||||||
|
<option value='1'>阿里云</option>
|
||||||
|
<option value='2'>发送邮件</option>
|
||||||
|
</ui-select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-------------------------------本地测试环境-------------------------------------->
|
||||||
|
<div class="layout vertical" v-if="testEnvLocal">
|
||||||
|
<ui-prop name="package url">
|
||||||
|
<div class="flex-1 layout horizontal center">
|
||||||
|
<h4 class="flex-2">{{serverPackageUrl}}</h4>
|
||||||
|
</div>
|
||||||
|
</ui-prop>
|
||||||
|
<ui-prop name="服务器版本">
|
||||||
|
<div class="flex-1 layout horizontal center">
|
||||||
|
<h4 class="flex-2">{{serverVersion}}</h4>
|
||||||
|
<ui-button class="end-justified" v-on:confirm="refreshLocalServerVersion">
|
||||||
|
<i class="icon-arrows-cw"></i>
|
||||||
|
<!--刷新-->
|
||||||
|
</ui-button>
|
||||||
|
</div>
|
||||||
|
</ui-prop>
|
||||||
|
|
||||||
|
<ui-prop name="本机server物理路径">
|
||||||
|
<div class="flex-1 layout horizontal center">
|
||||||
|
<ui-input class="flex-2" disabled v-value="localServerPath"></ui-input>
|
||||||
|
<ui-button v-on:confirm="onSelectLocalServerPath">选择</ui-button>
|
||||||
|
<ui-button v-on:confirm="onOpenLocalServer">
|
||||||
|
<i class="icon-doc-text"></i>
|
||||||
|
<!--打开目录-->
|
||||||
|
</ui-button>
|
||||||
|
</div>
|
||||||
|
</ui-prop>
|
||||||
|
<ui-prop name="操作">
|
||||||
|
<div class="flex-1 layout horizontal center">
|
||||||
|
<h3 class="flex-2"></h3>
|
||||||
|
<ui-button class="end-justified red" v-on:confirm="onCleanSimRemoteRes">
|
||||||
|
<i class="icon-trash-empty" title="删除win32模拟器热更新资源"></i>
|
||||||
|
清理模拟器缓存
|
||||||
|
</ui-button>
|
||||||
|
<ui-button class="end-justified green" v-on:confirm="onCopyFileToLocalServer">部署</ui-button>
|
||||||
|
</div>
|
||||||
|
</ui-prop>
|
||||||
|
<ui-progress style="width: 100%;" v-value="copyProgress">40</ui-progress>
|
||||||
|
</div>
|
||||||
|
<!---------------------------------阿里云测试环境-------------------------------------------------->
|
||||||
|
<div class="layout vertical" v-if="testEnvALi">
|
||||||
|
<h2>阿里云</h2>
|
||||||
|
<ui-prop name="">
|
||||||
|
|
||||||
|
</ui-prop>
|
||||||
|
<div class="self-end">
|
||||||
|
<ui-button class="self-end green" v-on:confirm="onBtnClickAliTest"> 测试阿里云</ui-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="layout vertical" v-if="testEnvEmail">
|
||||||
|
<ui-prop name="添加邮件接收者">
|
||||||
|
<ui-input class="flex-2" v-on:blur="onInputMailPeopleOver" v-value="addMailPeople"></ui-input>
|
||||||
|
<ui-button v-if="isPeopleExist()">添加</ui-button>
|
||||||
|
</ui-prop>
|
||||||
|
<ui-prop name="邮件接收者" auto-height>
|
||||||
|
<div class="layout vertical">
|
||||||
|
<ui-checkbox v-for="(index, people) in emailPeopleArray" v-bind:value="people">
|
||||||
|
{{'['+index+']'+people}}
|
||||||
|
</ui-checkbox>
|
||||||
|
</div>
|
||||||
|
</ui-prop>
|
||||||
|
|
||||||
|
<ui-prop name="发布的游戏版本">
|
||||||
|
<ui-input class="flex-1" disabled v-value="serverRootDir"></ui-input>
|
||||||
|
<ui-input style="width: 100px;" disabled
|
||||||
|
v-if="remoteServerVersion!== null && remoteServerVersion !== '' " v-value="remoteServerVersion">1.0
|
||||||
|
</ui-input>
|
||||||
|
</ui-prop>
|
||||||
|
<ui-prop name="更新内容" auto-height>
|
||||||
|
<ui-text-area class="flex-1" resize-v placeholder="更新内容" v-value="emailContent">
|
||||||
|
</ui-text-area>
|
||||||
|
</ui-prop>
|
||||||
|
<div class="self-end">
|
||||||
|
<ui-button class="self-end green" v-on:confirm="onBtnClickSendMail"> 发送邮件</ui-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<h2>日志:</h2>
|
||||||
|
<textarea class="flex-1 " id="logTextArea" v-value="logView"
|
||||||
|
style="width: 100%; height: 100%; background: #252525; color: #fd942b; border-color: #fd942b;"></textarea>
|
||||||
|
</div>
|
1236
packages/hot-update-tools/panel/index.js
Normal file
1236
packages/hot-update-tools/panel/index.js
Normal file
File diff suppressed because it is too large
Load Diff
0
packages/hot-update-tools/panel/test.js
Normal file
0
packages/hot-update-tools/panel/test.js
Normal file
0
packages/hot-update-tools/test/TestEnvAli.html
Normal file
0
packages/hot-update-tools/test/TestEnvAli.html
Normal file
14
packages/hot-update-tools/test/TestEnvAli.js
Normal file
14
packages/hot-update-tools/test/TestEnvAli.js
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
'use strict';
|
||||||
|
var Fs = require('fire-fs');
|
||||||
|
var Path = require('fire-path');
|
||||||
|
let url = Editor.url(window.packageRoot + "panel/TestEnvAli.html", 'utf8');
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
init() {
|
||||||
|
Vue.component('TestEnvAli', {
|
||||||
|
props: ['data'],
|
||||||
|
template: Fs.readFileSync(url),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
44
packages/hot-update/main.js
Normal file
44
packages/hot-update/main.js
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var Fs = require("fire-fs");
|
||||||
|
var Path = require("fire-path");
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
load: function () {
|
||||||
|
// 当 package 被正确加载的时候执行
|
||||||
|
},
|
||||||
|
|
||||||
|
unload: function () {
|
||||||
|
// 当 package 被正确卸载的时候执行
|
||||||
|
},
|
||||||
|
|
||||||
|
messages: {
|
||||||
|
'editor:build-finished': function (event, target) {
|
||||||
|
var root = Path.normalize(target.dest);
|
||||||
|
var url = Path.join(root, "main.js");
|
||||||
|
Fs.readFile(url, "utf8", function (err, data) {
|
||||||
|
if (err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
|
||||||
|
var newStr =
|
||||||
|
"(function () { \n"+
|
||||||
|
"\n"+
|
||||||
|
" if (cc.sys.isNative) { \n" +
|
||||||
|
" var hotUpdateSearchPaths = cc.sys.localStorage.getItem('HotUpdateSearchPaths'); \n" +
|
||||||
|
" if (hotUpdateSearchPaths) { \n" +
|
||||||
|
" jsb.fileUtils.setSearchPaths(JSON.parse(hotUpdateSearchPaths)); \n" +
|
||||||
|
" }\n" +
|
||||||
|
" }";
|
||||||
|
|
||||||
|
var newData = data.replace("(function () {", newStr);
|
||||||
|
Fs.writeFile(url, newData, function (error) {
|
||||||
|
if (err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
Editor.log("SearchPath updated in built main.js for hot update");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
7
packages/hot-update/package.json
Normal file
7
packages/hot-update/package.json
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"name": "hot-update",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"description": "用于热更新插件",
|
||||||
|
"author": "Cocos Creator",
|
||||||
|
"main": "main.js"
|
||||||
|
}
|
1
remote-assets/project.manifest
Normal file
1
remote-assets/project.manifest
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"packageUrl":"https://jianmiau.tk/Resources/App/JMKA/update/remote-assets/3.0/","remoteManifestUrl":"https://jianmiau.tk/Resources/App/JMKA/update/remote-assets/3.0/project.manifest","remoteVersionUrl":"https://jianmiau.tk/Resources/App/JMKA/update/remote-assets/3.0/version.manifest","version":"3.1","assets":{"src/assets/Plugins/responsivevoice.js":{"size":104943,"md5":"9f71d303fc7feda51261c2bf856ad4f1"},"src/assets/Script/Engine/Component/Animation/SkeletonExt.js":{"size":1161,"md5":"7e27cb40c535213460334d5f536e16b9"},"src/cocos2d-jsb.js":{"size":2995026,"md5":"8f7fa2615af9cf7f2121cf3077b97c0a"},"src/settings.js":{"size":500,"md5":"d989547c4773fe77c3dac0293e87e174"},"assets/main/config.json":{"size":1720,"md5":"4f2027d695a724c279c1f4faaea59ae9"},"assets/main/import/02/0254af710.json":{"size":281,"md5":"e859c04502eab6f53d55174bbd4f1d3d"},"assets/main/import/06/06cf73164.json":{"size":36298,"md5":"208e5254dfe5589ad716071ab641bfb5"},"assets/main/index.js":{"size":438903,"md5":"326c1799c4ce005357ea688eb7abea00"},"assets/main/native/2d/2ddfe005-2129-41d8-aeec-2b1f51f02962.png":{"size":2290,"md5":"740ebade1729539882383360b2066d36"},"assets/main/native/34/3459ab36-782c-4c4e-8aef-7280aff8b272.png":{"size":18969,"md5":"96e39d211db65235f425ba3957b723b0"},"assets/main/native/70/700faa17-11a6-46cd-aeb5-d6900bc264f8.png":{"size":3765,"md5":"60ab4dfb6d3e8a147753b5665dcba27a"},"assets/main/native/71/71561142-4c83-4933-afca-cb7a17f67053.png":{"size":1050,"md5":"72c8f8527cdbe8246b8223a54f409ca3"},"assets/main/native/b4/b43ff3c2-02bb-4874-81f7-f2dea6970f18.png":{"size":1114,"md5":"49624805cb214b8d78d34a0c03dfbd00"},"assets/main/native/c3/c39ea496-96eb-4dc5-945a-e7c919b77c21.png":{"size":2548,"md5":"c3b93af99c4a65d85ad414e8e46dbfd5"},"assets/main/native/ca/caaaf9ff-5036-4232-a8a7-88b80b2e4c88.png":{"size":1829,"md5":"e3e1ef9049e7c82cbb696bc4e8cfa64b"},"assets/main/native/e5/e56254ca-0ee4-42ea-b69e-d2e57804a4f1.jpg":{"size":5809,"md5":"8fbe8a70e5b43c90bed44cf38e0e2a50"}},"searchPaths":[]}
|
1
remote-assets/version.manifest
Normal file
1
remote-assets/version.manifest
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"packageUrl":"https://jianmiau.tk/Resources/App/JMKA/update/remote-assets/3.0/","remoteManifestUrl":"https://jianmiau.tk/Resources/App/JMKA/update/remote-assets/3.0/project.manifest","remoteVersionUrl":"https://jianmiau.tk/Resources/App/JMKA/update/remote-assets/3.0/version.manifest","version":"3.1"}
|
@ -15,7 +15,7 @@
|
|||||||
"mainCompressionType": "default",
|
"mainCompressionType": "default",
|
||||||
"mainIsRemote": false,
|
"mainIsRemote": false,
|
||||||
"optimizeHotUpdate": false,
|
"optimizeHotUpdate": false,
|
||||||
"md5Cache": true,
|
"md5Cache": false,
|
||||||
"nativeMd5Cache": false,
|
"nativeMd5Cache": false,
|
||||||
"encryptJs": true,
|
"encryptJs": true,
|
||||||
"xxteaKey": "e32c167b-561b-4d",
|
"xxteaKey": "e32c167b-561b-4d",
|
||||||
@ -23,7 +23,7 @@
|
|||||||
"fb-instant-games": {},
|
"fb-instant-games": {},
|
||||||
"android": {
|
"android": {
|
||||||
"REMOTE_SERVER_ROOT": "",
|
"REMOTE_SERVER_ROOT": "",
|
||||||
"packageName": "org.cocos2d.demo"
|
"packageName": "org.jianmiau.jmka"
|
||||||
},
|
},
|
||||||
"ios": {
|
"ios": {
|
||||||
"REMOTE_SERVER_ROOT": "",
|
"REMOTE_SERVER_ROOT": "",
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
"height": 640,
|
"height": 640,
|
||||||
"width": 960
|
"width": 960
|
||||||
},
|
},
|
||||||
"last-module-event-record-time": 1661333345776,
|
"last-module-event-record-time": 1662216568639,
|
||||||
"assets-sort-type": "name",
|
"assets-sort-type": "name",
|
||||||
"facebook": {
|
"facebook": {
|
||||||
"appID": "",
|
"appID": "",
|
||||||
|
@ -1,19 +1,31 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"module": "commonjs",
|
"module": "commonjs",
|
||||||
"lib": [ "es2015", "es2017", "dom" ],
|
"lib": [
|
||||||
"target": "es5",
|
"es2015",
|
||||||
"experimentalDecorators": true,
|
"es2017",
|
||||||
"skipLibCheck": true,
|
"dom"
|
||||||
"outDir": "temp/vscode-dist",
|
],
|
||||||
"forceConsistentCasingInFileNames": true
|
"target": "es5",
|
||||||
},
|
"allowJs": true,
|
||||||
"exclude": [
|
"experimentalDecorators": true,
|
||||||
"node_modules",
|
"skipLibCheck": true,
|
||||||
"library",
|
"outDir": "temp/vscode-dist",
|
||||||
"local",
|
"forceConsistentCasingInFileNames": true,
|
||||||
"temp",
|
"downlevelIteration": true,
|
||||||
"build",
|
"sourceMap": true
|
||||||
"settings"
|
},
|
||||||
]
|
"exclude": [
|
||||||
|
"node_modules",
|
||||||
|
"library",
|
||||||
|
"local",
|
||||||
|
"temp",
|
||||||
|
"build",
|
||||||
|
"settings",
|
||||||
|
".git",
|
||||||
|
".vscode",
|
||||||
|
"build-templates",
|
||||||
|
"preview-templates",
|
||||||
|
"packages"
|
||||||
|
]
|
||||||
}
|
}
|
218
tslint.json
218
tslint.json
@ -1,115 +1,107 @@
|
|||||||
{
|
{
|
||||||
"rules": {
|
"defaultSeverity": "warning",
|
||||||
"ban": [
|
"rules": {
|
||||||
true,
|
"ban": [
|
||||||
[
|
true,
|
||||||
"_",
|
[
|
||||||
"extend"
|
"_",
|
||||||
],
|
"extend"
|
||||||
[
|
],
|
||||||
"_",
|
[
|
||||||
"isNull"
|
"_",
|
||||||
],
|
"isNull"
|
||||||
[
|
],
|
||||||
"_",
|
[
|
||||||
"isDefined"
|
"_",
|
||||||
]
|
"isDefined"
|
||||||
],
|
]
|
||||||
"class-name": false,
|
],
|
||||||
"comment-format": [
|
"class-name": false,
|
||||||
true,
|
"comment-format": [
|
||||||
"check-space"
|
true,
|
||||||
],
|
"check-space"
|
||||||
"curly": true,
|
],
|
||||||
"eofline": false,
|
"curly": true,
|
||||||
"forin": false,
|
"eofline": false,
|
||||||
"indent": [
|
"forin": false,
|
||||||
true,
|
"indent": [
|
||||||
4
|
true,
|
||||||
],
|
4
|
||||||
"interface-name": [
|
],
|
||||||
true,
|
"interface-name": [
|
||||||
"never-prefix"
|
true,
|
||||||
],
|
"never-prefix"
|
||||||
"jsdoc-format": true,
|
],
|
||||||
"label-position": true,
|
"jsdoc-format": true,
|
||||||
"label-undefined": true,
|
"label-position": true,
|
||||||
"max-line-length": [
|
"max-line-length": [
|
||||||
false,
|
false,
|
||||||
140
|
140
|
||||||
],
|
],
|
||||||
"no-arg": true,
|
"no-arg": true,
|
||||||
"no-bitwise": false,
|
"no-bitwise": false,
|
||||||
"no-console": [
|
"no-console": [
|
||||||
true,
|
true,
|
||||||
"debug",
|
"debug",
|
||||||
"info",
|
"info",
|
||||||
"time",
|
"time",
|
||||||
"timeEnd",
|
"timeEnd",
|
||||||
"trace"
|
"trace"
|
||||||
],
|
],
|
||||||
"no-construct": true,
|
"no-construct": true,
|
||||||
"no-debugger": true,
|
"no-debugger": true,
|
||||||
"no-duplicate-key": true,
|
"no-duplicate-variable": true,
|
||||||
"no-duplicate-variable": true,
|
"no-empty": true,
|
||||||
"no-empty": true,
|
// "no-eval": true,
|
||||||
// "no-eval": true,
|
"no-string-literal": false,
|
||||||
"no-string-literal": false,
|
"no-trailing-whitespace": true,
|
||||||
"no-trailing-comma": true,
|
"no-unused-expression": false,
|
||||||
"no-trailing-whitespace": true,
|
"no-unused-variable": true,
|
||||||
"no-unused-expression": false,
|
"no-use-before-declare": false,
|
||||||
"no-unused-variable": true,
|
"one-line": [
|
||||||
"no-unreachable": true,
|
true,
|
||||||
"no-use-before-declare": false,
|
"check-open-brace",
|
||||||
"one-line": [
|
"check-catch",
|
||||||
true,
|
"check-else",
|
||||||
"check-open-brace",
|
"check-whitespace"
|
||||||
"check-catch",
|
],
|
||||||
"check-else",
|
"quotemark": [
|
||||||
"check-whitespace"
|
true,
|
||||||
],
|
"double"
|
||||||
"quotemark": [
|
],
|
||||||
true,
|
"radix": true,
|
||||||
"double"
|
"semicolon": [
|
||||||
],
|
true,
|
||||||
"radix": true,
|
"always"
|
||||||
"semicolon": [
|
],
|
||||||
true,
|
"triple-equals": [
|
||||||
"always"
|
true,
|
||||||
],
|
"allow-null-check"
|
||||||
"triple-equals": [
|
],
|
||||||
true,
|
"typedef": [
|
||||||
"allow-null-check"
|
true,
|
||||||
],
|
"call-signature",
|
||||||
"typedef": [
|
"parameter",
|
||||||
true,
|
"property-declaration",
|
||||||
"call-signature",
|
"variable-declaration"
|
||||||
"parameter",
|
],
|
||||||
"property-declaration",
|
"typedef-whitespace": [
|
||||||
"variable-declaration"
|
true,
|
||||||
],
|
{
|
||||||
"typedef-whitespace": [
|
"call-signature": "nospace"
|
||||||
true,
|
},
|
||||||
{
|
{
|
||||||
"call-signature": "nospace"
|
"index-signature": "space"
|
||||||
},
|
}
|
||||||
{
|
],
|
||||||
"index-signature": "space"
|
"variable-name": false,
|
||||||
}
|
"whitespace": [
|
||||||
],
|
false,
|
||||||
"use-strict": [
|
"check-branch",
|
||||||
true,
|
"check-decl",
|
||||||
"check-module",
|
"check-operator",
|
||||||
"check-function"
|
"check-separator",
|
||||||
],
|
"check-type"
|
||||||
"variable-name": false,
|
]
|
||||||
"whitespace": [
|
}
|
||||||
false,
|
|
||||||
"check-branch",
|
|
||||||
"check-decl",
|
|
||||||
"check-operator",
|
|
||||||
"check-separator",
|
|
||||||
"check-type"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
}
|
115
version_generator.js
Normal file
115
version_generator.js
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
var fs = require('fs');
|
||||||
|
var path = require('path');
|
||||||
|
var crypto = require('crypto');
|
||||||
|
|
||||||
|
var manifest = {
|
||||||
|
packageUrl: 'http://localhost/tutorial-hot-update/remote-assets/',
|
||||||
|
remoteManifestUrl: 'http://localhost/tutorial-hot-update/remote-assets/project.manifest',
|
||||||
|
remoteVersionUrl: 'http://localhost/tutorial-hot-update/remote-assets/version.manifest',
|
||||||
|
version: '1.0.0',
|
||||||
|
assets: {},
|
||||||
|
searchPaths: []
|
||||||
|
};
|
||||||
|
|
||||||
|
var dest = './remote-assets/';
|
||||||
|
var src = './jsb/';
|
||||||
|
|
||||||
|
// Parse arguments
|
||||||
|
var i = 2;
|
||||||
|
while (i < process.argv.length) {
|
||||||
|
var arg = process.argv[i];
|
||||||
|
|
||||||
|
switch (arg) {
|
||||||
|
case '--url':
|
||||||
|
case '-u':
|
||||||
|
var url = process.argv[i + 1];
|
||||||
|
manifest.packageUrl = url;
|
||||||
|
manifest.remoteManifestUrl = url + 'project.manifest';
|
||||||
|
manifest.remoteVersionUrl = url + 'version.manifest';
|
||||||
|
i += 2;
|
||||||
|
break;
|
||||||
|
case '--version':
|
||||||
|
case '-v':
|
||||||
|
manifest.version = process.argv[i + 1];
|
||||||
|
i += 2;
|
||||||
|
break;
|
||||||
|
case '--src':
|
||||||
|
case '-s':
|
||||||
|
src = process.argv[i + 1];
|
||||||
|
i += 2;
|
||||||
|
break;
|
||||||
|
case '--dest':
|
||||||
|
case '-d':
|
||||||
|
dest = process.argv[i + 1];
|
||||||
|
i += 2;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
i++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function readDir(dir, obj) {
|
||||||
|
var stat = fs.statSync(dir);
|
||||||
|
if (!stat.isDirectory()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var subpaths = fs.readdirSync(dir), subpath, size, md5, compressed, relative;
|
||||||
|
for (var i = 0; i < subpaths.length; ++i) {
|
||||||
|
if (subpaths[i][0] === '.') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
subpath = path.join(dir, subpaths[i]);
|
||||||
|
stat = fs.statSync(subpath);
|
||||||
|
if (stat.isDirectory()) {
|
||||||
|
readDir(subpath, obj);
|
||||||
|
}
|
||||||
|
else if (stat.isFile()) {
|
||||||
|
// Size in Bytes
|
||||||
|
size = stat['size'];
|
||||||
|
md5 = crypto.createHash('md5').update(fs.readFileSync(subpath, 'binary')).digest('hex');
|
||||||
|
compressed = path.extname(subpath).toLowerCase() === '.zip';
|
||||||
|
|
||||||
|
relative = path.relative(src, subpath);
|
||||||
|
relative = relative.replace(/\\/g, '/');
|
||||||
|
relative = encodeURI(relative);
|
||||||
|
obj[relative] = {
|
||||||
|
'size': size,
|
||||||
|
'md5': md5
|
||||||
|
};
|
||||||
|
if (compressed) {
|
||||||
|
obj[relative].compressed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var mkdirSync = function (path) {
|
||||||
|
try {
|
||||||
|
fs.mkdirSync(path);
|
||||||
|
} catch (e) {
|
||||||
|
if (e.code != 'EEXIST') throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterate res and src folder
|
||||||
|
readDir(path.join(src, 'src'), manifest.assets);
|
||||||
|
readDir(path.join(src, 'assets'), manifest.assets);
|
||||||
|
|
||||||
|
var destManifest = path.join(dest, 'project.manifest');
|
||||||
|
var destVersion = path.join(dest, 'version.manifest');
|
||||||
|
|
||||||
|
mkdirSync(dest);
|
||||||
|
|
||||||
|
fs.writeFile(destManifest, JSON.stringify(manifest), (err) => {
|
||||||
|
if (err) throw err;
|
||||||
|
console.log('Manifest successfully generated');
|
||||||
|
});
|
||||||
|
|
||||||
|
delete manifest.assets;
|
||||||
|
delete manifest.searchPaths;
|
||||||
|
fs.writeFile(destVersion, JSON.stringify(manifest), (err) => {
|
||||||
|
if (err) throw err;
|
||||||
|
console.log('Version successfully generated');
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user