Commit 8d548790 authored by JoyJ's avatar JoyJ

add room for future

parent ad92f856
Pipeline #1823 canceled with stages
...@@ -10,22 +10,22 @@ import { ...@@ -10,22 +10,22 @@ import {
OnDestroy, OnDestroy,
OnInit, OnInit,
Output, Output,
ViewChild ViewChild,
} from '@angular/core'; } from "@angular/core";
import { Headers, Http } from '@angular/http'; import { Headers, Http } from "@angular/http";
import * as child_process from 'child_process'; import * as child_process from "child_process";
import { clipboard, remote, shell } from 'electron'; import { clipboard, remote, shell } from "electron";
import * as fs from 'fs-extra'; import * as fs from "fs-extra";
import * as ini from 'ini'; import * as ini from "ini";
import { EncodeOptions } from 'ini'; import { EncodeOptions } from "ini";
import * as $ from 'jquery'; import * as $ from "jquery";
import * as path from 'path'; import * as path from "path";
import 'rxjs/Rx'; import "rxjs/Rx";
import { ISubscription } from 'rxjs/Subscription'; import { ISubscription } from "rxjs/Subscription";
import { App } from '../app'; import { App } from "../app";
import { AppsService } from '../apps.service'; import { AppsService } from "../apps.service";
import { LoginService } from '../login.service'; import { LoginService } from "../login.service";
import { SettingsService } from '../settings.service'; import { SettingsService } from "../settings.service";
import Timer = NodeJS.Timer; import Timer = NodeJS.Timer;
// import WillNavigateEvent = Electron.WillNavigateEvent; // import WillNavigateEvent = Electron.WillNavigateEvent;
...@@ -69,10 +69,10 @@ interface Room { ...@@ -69,10 +69,10 @@ interface Room {
id?: string; id?: string;
title?: string; title?: string;
server?: Server; server?: Server;
'private'?: boolean; private?: boolean;
options: Options; options: Options;
arena?: string; arena?: string;
users?: { username: string, position: number }[]; users?: { username: string; position: number }[];
} }
interface Options { interface Options {
...@@ -103,15 +103,14 @@ interface YGOProData { ...@@ -103,15 +103,14 @@ interface YGOProData {
windbot: { [locale: string]: string[] }; windbot: { [locale: string]: string[] };
} }
let matching: ISubscription | undefined; let matching: ISubscription | undefined;
let matching_arena: string | undefined; let matching_arena: string | undefined;
let match_started_at: Date; let match_started_at: Date;
@Component({ @Component({
selector: 'mycard-ygopro', selector: "mycard-ygopro",
templateUrl: './ygopro.component.html', templateUrl: "./ygopro.component.html",
styleUrls: ['./ygopro.component.css'] styleUrls: ["./ygopro.component.css"],
}) })
export class YGOProComponent implements OnInit, OnDestroy { export class YGOProComponent implements OnInit, OnDestroy {
@Input() @Input()
...@@ -128,10 +127,10 @@ export class YGOProComponent implements OnInit, OnDestroy { ...@@ -128,10 +127,10 @@ export class YGOProComponent implements OnInit, OnDestroy {
numfont: string[]; numfont: string[];
textfont: string[]; textfont: string[];
@ViewChild('bilibili') @ViewChild("bilibili")
bilibili: ElementRef; bilibili: ElementRef;
@ViewChild('youtube') @ViewChild("youtube")
youtube: ElementRef; youtube: ElementRef;
// points: Points; // points: Points;
...@@ -143,7 +142,7 @@ export class YGOProComponent implements OnInit, OnDestroy { ...@@ -143,7 +142,7 @@ export class YGOProComponent implements OnInit, OnDestroy {
default_options: Options = { default_options: Options = {
mode: 1, mode: 1,
rule: this.settingsService.getLocale().startsWith('zh') ? 0 : 1, rule: this.settingsService.getLocale().startsWith("zh") ? 0 : 1,
start_lp: 8000, start_lp: 8000,
start_hand: 5, start_hand: 5,
draw_count: 1, draw_count: 1,
...@@ -151,10 +150,13 @@ export class YGOProComponent implements OnInit, OnDestroy { ...@@ -151,10 +150,13 @@ export class YGOProComponent implements OnInit, OnDestroy {
no_check_deck: false, no_check_deck: false,
no_shuffle_deck: false, no_shuffle_deck: false,
lflist: 0, lflist: 0,
time_limit: 180 time_limit: 180,
}; };
room: Room = { title: this.loginService.user.username + '的房间', options: Object.assign({}, this.default_options) }; room: Room = {
title: this.loginService.user.username + "的房间",
options: Object.assign({}, this.default_options),
};
rooms: Room[] = []; rooms: Room[] = [];
...@@ -168,7 +170,7 @@ export class YGOProComponent implements OnInit, OnDestroy { ...@@ -168,7 +170,7 @@ export class YGOProComponent implements OnInit, OnDestroy {
single: true, single: true,
match: true, match: true,
tag: true, tag: true,
windbot: false windbot: false,
}; };
matching: ISubscription | undefined; matching: ISubscription | undefined;
...@@ -180,19 +182,26 @@ export class YGOProComponent implements OnInit, OnDestroy { ...@@ -180,19 +182,26 @@ export class YGOProComponent implements OnInit, OnDestroy {
join_password: string; join_password: string;
host_password = (this.loginService.user.external_id ^ 0x54321).toString(); host_password = (this.loginService.user.external_id ^ 0x54321).toString();
constructor(private http: Http, public appsService: AppsService, private loginService: LoginService, constructor(
public settingsService: SettingsService, private ref: ChangeDetectorRef) { private http: Http,
public appsService: AppsService,
private loginService: LoginService,
public settingsService: SettingsService,
private ref: ChangeDetectorRef
) {
switch (process.platform) { switch (process.platform) {
case 'darwin': case "darwin":
this.numfont = ['/System/Library/Fonts/SFNSTextCondensed-Bold.otf']; this.numfont = ["/System/Library/Fonts/SFNSTextCondensed-Bold.otf"];
this.textfont = ['/System/Library/Fonts/PingFang.ttc']; this.textfont = ["/System/Library/Fonts/PingFang.ttc"];
break; break;
case 'win32': case "win32":
this.numfont = [path.join(process.env['SystemRoot']!, 'Fonts', 'arialbd.ttf')]; this.numfont = [
path.join(process.env["SystemRoot"]!, "Fonts", "arialbd.ttf"),
];
this.textfont = [ this.textfont = [
path.join(process.env['SystemRoot']!, 'Fonts', 'msyh.ttc'), path.join(process.env["SystemRoot"]!, "Fonts", "msyh.ttc"),
path.join(process.env['SystemRoot']!, 'Fonts', 'msyh.ttf'), path.join(process.env["SystemRoot"]!, "Fonts", "msyh.ttf"),
path.join(process.env['SystemRoot']!, 'Fonts', 'simsun.ttc') path.join(process.env["SystemRoot"]!, "Fonts", "simsun.ttc"),
]; ];
break; break;
} }
...@@ -206,124 +215,160 @@ export class YGOProComponent implements OnInit, OnDestroy { ...@@ -206,124 +215,160 @@ export class YGOProComponent implements OnInit, OnDestroy {
}, 1000); }, 1000);
} }
if (this.settingsService.getLocale().startsWith('zh')) { if (this.settingsService.getLocale().startsWith("zh")) {
this.servers.push({ this.servers.push(
id: 'tiramisu', {
url: 'wss://tiramisu.mycard.moe:7923', id: "tiramisu",
address: '112.124.105.11', url: "wss://tiramisu.mycard.moe:7923",
port: 7911, address: "112.124.105.11",
custom: true, port: 7911,
replay: true custom: true,
}, { replay: true,
id: 'tiramisu-athletic', },
url: 'wss://tiramisu.mycard.moe:8923', {
address: '112.124.105.11', id: "tiramisu-athletic",
port: 8911, url: "wss://tiramisu.mycard.moe:8923",
custom: false, address: "112.124.105.11",
replay: true port: 8911,
}); custom: false,
replay: true,
}
);
} else { } else {
this.servers.push({ this.servers.push(
id: 'mercury-us-1-athletic', {
url: 'wss://mercury-us-1.mycard.moe:7923', id: "mercury-us-1-athletic",
address: '104.237.154.173', url: "wss://mercury-us-1.mycard.moe:7923",
port: 7911, address: "104.237.154.173",
custom: true, port: 7911,
replay: true custom: true,
}, { replay: true,
id: 'mercury-us-1', },
url: 'wss://mercury-us-1.mycard.moe:7923', {
address: '104.237.154.173', id: "mercury-us-1",
port: 8911, url: "wss://mercury-us-1.mycard.moe:7923",
custom: false, address: "104.237.154.173",
replay: true port: 8911,
}); custom: false,
replay: true,
}
);
} }
} }
refresh_replay_rooms() { refresh_replay_rooms() {
this.replay_rooms_show = this.replay_rooms.filter((room) => { this.replay_rooms_show = this.replay_rooms
return ((this.replay_rooms_filter.athletic && room.arena === 'athletic') || .filter((room) => {
(this.replay_rooms_filter.entertain && room.arena === 'entertain') || return (
(this.replay_rooms_filter.single && room.options.mode === 0 && !room.arena && !room.id!.startsWith('AI#')) || (this.replay_rooms_filter.athletic && room.arena === "athletic") ||
(this.replay_rooms_filter.match && room.options.mode === 1 && !room.arena && !room.id!.startsWith('AI#')) || (this.replay_rooms_filter.entertain && room.arena === "entertain") ||
(this.replay_rooms_filter.tag && room.options.mode === 2 && !room.arena && !room.id!.startsWith('AI#')) || (this.replay_rooms_filter.single &&
(this.replay_rooms_filter.windbot && room.id!.startsWith('AI#'))); room.options.mode === 0 &&
}).sort((a, b) => { !room.arena &&
// if (a.arena === 'athletic' && b.arena === 'athletic') { !room.id!.startsWith("AI#")) ||
// return a.dp - b.dp; (this.replay_rooms_filter.match &&
// } else if (a.arena === 'entertain' && b.arena === 'entertain') { room.options.mode === 1 &&
// return a.exp - b.exp; !room.arena &&
// } !room.id!.startsWith("AI#")) ||
let [a_priority, b_priority] = [a, b].map((room) => { (this.replay_rooms_filter.tag &&
if (room.arena === 'athletic') { room.options.mode === 2 &&
return 0; !room.arena &&
} else if (room.arena === 'entertain') { !room.id!.startsWith("AI#")) ||
return 1; (this.replay_rooms_filter.windbot && room.id!.startsWith("AI#"))
} else if (room.id!.startsWith('AI#')) { );
return 5; })
} else { .sort((a, b) => {
return room.options.mode + 2; // if (a.arena === 'athletic' && b.arena === 'athletic') {
} // return a.dp - b.dp;
// } else if (a.arena === 'entertain' && b.arena === 'entertain') {
// return a.exp - b.exp;
// }
let [a_priority, b_priority] = [a, b].map((room) => {
if (room.arena === "athletic") {
return 0;
} else if (room.arena === "entertain") {
return 1;
} else if (room.id!.startsWith("AI#")) {
return 5;
} else {
return room.options.mode + 2;
}
});
return a_priority - b_priority;
}); });
return a_priority - b_priority;
});
} }
async ngOnInit() { async ngOnInit() {
let locale: string; let locale: string;
if (this.settingsService.getLocale().startsWith('zh')) { if (this.settingsService.getLocale().startsWith("zh")) {
locale = 'zh-CN'; locale = "zh-CN";
} else { } else {
locale = 'en-US'; locale = "en-US";
} }
this.windbot = (<YGOProData>this.app.data).windbot[locale]; this.windbot = (<YGOProData>this.app.data).windbot[locale];
this.system_conf = path.join(this.app.local!.path, 'system.conf'); this.system_conf = path.join(this.app.local!.path, "system.conf");
await this.refresh(); await this.refresh();
let modal = $('#game-list-modal'); let modal = $("#game-list-modal");
modal.on('show.bs.modal', () => { modal.on("show.bs.modal", () => {
this.rooms_loading = true; this.rooms_loading = true;
this.connections = this.servers.filter(server => server.custom).map((server) => { this.connections = this.servers
let url = new URL(server.url!); .filter((server) => server.custom)
url['searchParams'].set('filter', 'waiting'); .map((server) => {
let connection = new WebSocket(url.toString()); let url = new URL(server.url!);
connection.onclose = (event: CloseEvent) => { url["searchParams"].set("filter", "waiting");
this.rooms = this.rooms.filter(room => room.server !== server); let connection = new WebSocket(url.toString());
}; connection.onclose = (event: CloseEvent) => {
connection.onerror = (event: ErrorEvent) => { this.rooms = this.rooms.filter((room) => room.server !== server);
console.log('error', server.id, event); };
this.rooms = this.rooms.filter(room => room.server !== server); connection.onerror = (event: ErrorEvent) => {
}; console.log("error", server.id, event);
connection.onmessage = (event) => { this.rooms = this.rooms.filter((room) => room.server !== server);
let message = JSON.parse(event.data); };
switch (message.event) { connection.onmessage = (event) => {
case 'init': let message = JSON.parse(event.data);
this.rooms_loading = false; switch (message.event) {
this.rooms = this.rooms.filter(room => room.server !== server).concat( case "init":
message.data.map((room: Room) => Object.assign({ server: server }, room)) this.rooms_loading = false;
); this.rooms = this.rooms
break; .filter((room) => room.server !== server)
case 'create': .concat(
this.rooms.push(Object.assign({ server: server }, message.data)); message.data.map((room: Room) =>
break; Object.assign({ server: server }, room)
case 'update': )
Object.assign(this.rooms.find(room => room.server === server && room.id === message.data.id), message.data); );
break; break;
case 'delete': case "create":
this.rooms.splice(this.rooms.findIndex(room => room.server === server && room.id === message.data), 1); this.rooms.push(
} Object.assign({ server: server }, message.data)
this.ref.detectChanges(); );
}; break;
return connection; case "update":
}); Object.assign(
this.rooms.find(
(room) =>
room.server === server && room.id === message.data.id
),
message.data
);
break;
case "delete":
this.rooms.splice(
this.rooms.findIndex(
(room) => room.server === server && room.id === message.data
),
1
);
}
this.ref.detectChanges();
};
return connection;
});
}); });
modal.on('hide.bs.modal', () => { modal.on("hide.bs.modal", () => {
for (let connection of this.connections) { for (let connection of this.connections) {
connection.close(); connection.close();
} }
...@@ -331,61 +376,78 @@ export class YGOProComponent implements OnInit, OnDestroy { ...@@ -331,61 +376,78 @@ export class YGOProComponent implements OnInit, OnDestroy {
}); });
// TODO: 跟上面的逻辑合并 // TODO: 跟上面的逻辑合并
let replay_modal = $('#game-replay-modal'); let replay_modal = $("#game-replay-modal");
replay_modal.on('show.bs.modal', () => { replay_modal.on("show.bs.modal", () => {
this.replay_connections = this.servers.filter(server => server.replay).map((server) => { this.replay_connections = this.servers
let url = new URL(server.url!); .filter((server) => server.replay)
url['searchParams'].set('filter', 'started'); .map((server) => {
let connection = new WebSocket(url.toString()); let url = new URL(server.url!);
connection.onclose = () => { url["searchParams"].set("filter", "started");
this.replay_rooms = this.replay_rooms.filter(room => room.server !== server); let connection = new WebSocket(url.toString());
this.refresh_replay_rooms(); connection.onclose = () => {
}; this.replay_rooms = this.replay_rooms.filter(
connection.onmessage = (event) => { (room) => room.server !== server
let message = JSON.parse(event.data); );
switch (message.event) { this.refresh_replay_rooms();
case 'init': };
this.replay_rooms = this.replay_rooms.filter(room => room.server !== server).concat( connection.onmessage = (event) => {
message.data.map((room: Room) => Object.assign({ let message = JSON.parse(event.data);
server: server, switch (message.event) {
'private': /^\d+$/.test(room.title!) case "init":
}, room)) this.replay_rooms = this.replay_rooms
); .filter((room) => room.server !== server)
break; .concat(
case 'create': message.data.map((room: Room) =>
this.replay_rooms.push(Object.assign({ Object.assign(
server: server, {
'private': /^\d+$/.test(message.data.title!) server: server,
}, message.data)); private: /^\d+$/.test(room.title!),
break; },
case 'delete': room
this.replay_rooms.splice( )
this.replay_rooms.findIndex(room => room.server === server && room.id === message.data), )
1 );
); break;
} case "create":
this.refresh_replay_rooms(); this.replay_rooms.push(
this.ref.detectChanges(); Object.assign(
}; {
return connection; server: server,
}); private: /^\d+$/.test(message.data.title!),
},
message.data
)
);
break;
case "delete":
this.replay_rooms.splice(
this.replay_rooms.findIndex(
(room) => room.server === server && room.id === message.data
),
1
);
}
this.refresh_replay_rooms();
this.ref.detectChanges();
};
return connection;
});
}); });
replay_modal.on('hide.bs.modal', () => { replay_modal.on("hide.bs.modal", () => {
for (let connection of this.replay_connections) { for (let connection of this.replay_connections) {
connection.close(); connection.close();
} }
this.replay_connections = []; this.replay_connections = [];
}); });
remote.ipcMain.on('YGOPro', (e: any, type: string) => { remote.ipcMain.on("YGOPro", (e: any, type: string) => {
console.log('rrrrr'); console.log("rrrrr");
this.request_match(type); this.request_match(type);
}); });
} }
async refresh() { async refresh() {
this.decks = await this.get_decks(); this.decks = await this.get_decks();
let system_conf = await this.load_system_conf(); let system_conf = await this.load_system_conf();
...@@ -400,23 +462,28 @@ export class YGOProComponent implements OnInit, OnDestroy { ...@@ -400,23 +462,28 @@ export class YGOProComponent implements OnInit, OnDestroy {
// https://mycard.moe/ygopro/api/user?username=ozxdno // https://mycard.moe/ygopro/api/user?username=ozxdno
try { try {
let points = await this.http.get('https://mycard.moe/ygopro/api/user', { let points = await this.http
search: { .get("https://mycard.moe/ygopro/api/user", {
username: this.loginService.user.username search: {
} username: this.loginService.user.username,
}) },
})
.map((response) => response.json()) .map((response) => response.json())
.toPromise(); .toPromise();
this.points.emit(points); this.points.emit(points);
} catch (error) { } catch (error) {
console.log(error); console.log(error);
} }
}; }
async get_decks(): Promise<string[]> { async get_decks(): Promise<string[]> {
try { try {
let files: string[] = await fs.readdir(path.join(this.app.local!.path, 'deck')); let files: string[] = await fs.readdir(
return files.filter(file => path.extname(file) === '.ydk').map(file => path.basename(file, '.ydk')); path.join(this.app.local!.path, "deck")
);
return files
.filter((file) => path.extname(file) === ".ydk")
.map((file) => path.basename(file, ".ydk"));
} catch (error) { } catch (error) {
return []; return [];
} }
...@@ -424,8 +491,12 @@ export class YGOProComponent implements OnInit, OnDestroy { ...@@ -424,8 +491,12 @@ export class YGOProComponent implements OnInit, OnDestroy {
async get_replays(): Promise<string[]> { async get_replays(): Promise<string[]> {
try { try {
let files: string[] = await fs.readdir(path.join(this.app.local!.path, 'replay')); let files: string[] = await fs.readdir(
return files.filter(file => path.extname(file) === '.yrp').map(file => path.basename(file, '.yrp')); path.join(this.app.local!.path, "replay")
);
return files
.filter((file) => path.extname(file) === ".yrp")
.map((file) => path.basename(file, ".yrp"));
} catch (error) { } catch (error) {
return []; return [];
} }
...@@ -440,39 +511,44 @@ export class YGOProComponent implements OnInit, OnDestroy { ...@@ -440,39 +511,44 @@ export class YGOProComponent implements OnInit, OnDestroy {
} }
async delete_deck(deck: string) { async delete_deck(deck: string) {
if (confirm('确认删除?')) { if (confirm("确认删除?")) {
try { try {
await fs.unlink(path.join(this.app.local!.path, 'deck', deck + '.ydk')); await fs.unlink(path.join(this.app.local!.path, "deck", deck + ".ydk"));
} catch (error) { } catch (error) {}
}
return this.refresh(); return this.refresh();
} }
} }
async fix_fonts(data: SystemConf) { async fix_fonts(data: SystemConf) {
if (!await this.get_font([data.numfont])) { if (!(await this.get_font([data.numfont]))) {
let font = await this.get_font(this.numfont); let font = await this.get_font(this.numfont);
if (font) { if (font) {
data['numfont'] = font; data["numfont"] = font;
} }
} }
if (data.textfont === 'c:/windows/fonts/simsun.ttc 14' || !await this.get_font([data.textfont.split(' ', 2)[0]])) { if (
data.textfont === "c:/windows/fonts/simsun.ttc 14" ||
!(await this.get_font([data.textfont.split(" ", 2)[0]]))
) {
let font = await this.get_font(this.textfont); let font = await this.get_font(this.textfont);
if (font) { if (font) {
data['textfont'] = `${font} 14`; data["textfont"] = `${font} 14`;
} }
} }
}; }
async load_system_conf(): Promise<SystemConf> { async load_system_conf(): Promise<SystemConf> {
let data = await fs.readFile(this.system_conf, { encoding: 'utf-8' }); let data = await fs.readFile(this.system_conf, { encoding: "utf-8" });
return ini.parse(data); return ini.parse(data);
}; }
save_system_conf(data: SystemConf) { save_system_conf(data: SystemConf) {
return fs.writeFile(this.system_conf, ini.unsafe(ini.stringify(data, <EncodeOptions>{ whitespace: true }))); return fs.writeFile(
}; this.system_conf,
ini.unsafe(ini.stringify(data, <EncodeOptions>{ whitespace: true }))
);
}
async join(name: string, server: Server) { async join(name: string, server: Server) {
let system_conf = await this.load_system_conf(); let system_conf = await this.load_system_conf();
...@@ -484,33 +560,42 @@ export class YGOProComponent implements OnInit, OnDestroy { ...@@ -484,33 +560,42 @@ export class YGOProComponent implements OnInit, OnDestroy {
system_conf.roompass = name; system_conf.roompass = name;
system_conf.nickname = this.loginService.user.username; system_conf.nickname = this.loginService.user.username;
await this.save_system_conf(system_conf); await this.save_system_conf(system_conf);
return this.start_game(['-j']); return this.start_game(["-j"]);
}; }
async edit_deck(deck: string) { async edit_deck(deck: string) {
let system_conf = await this.load_system_conf(); let system_conf = await this.load_system_conf();
await this.fix_fonts(system_conf); await this.fix_fonts(system_conf);
system_conf.lastdeck = deck; system_conf.lastdeck = deck;
await this.save_system_conf(system_conf); await this.save_system_conf(system_conf);
return this.start_game(['-d', deck]); return this.start_game(["-d", deck]);
} }
async watch_replay(replay: string) { async watch_replay(replay: string) {
let system_conf = await this.load_system_conf(); let system_conf = await this.load_system_conf();
await this.fix_fonts(system_conf); await this.fix_fonts(system_conf);
await this.save_system_conf(system_conf); await this.save_system_conf(system_conf);
return this.start_game(['-r', path.join('replay', replay + '.yrp')]); return this.start_game(["-r", path.join("replay", replay + ".yrp")]);
} }
join_windbot(name?: string) { join_windbot(name?: string) {
if (!name) { if (!name) {
name = this.windbot[Math.floor(Math.random() * this.windbot.length)]; name = this.windbot[Math.floor(Math.random() * this.windbot.length)];
} }
return this.join('AI#' + name, this.servers[0]); return this.join("AI#" + name, this.servers[0]);
} }
duel_chronicle(room: string) { duel_chronicle(room: string) {
this.start_game(['-n',this.loginService.user.username,'-h','duelstart.com','-p','2333']); this.start_game([
"-n",
this.loginService.user.username,
"-h",
"duelstart.com",
"-p",
"2333",
"-w",
room,
]);
} }
async start_game(args: string[]) { async start_game(args: string[]) {
...@@ -522,29 +607,34 @@ export class YGOProComponent implements OnInit, OnDestroy { ...@@ -522,29 +607,34 @@ export class YGOProComponent implements OnInit, OnDestroy {
win.minimize(); win.minimize();
await new Promise((resolve, reject) => { await new Promise((resolve, reject) => {
let child = child_process.spawn(path.join(this.app.local!.path, this.app.actions.get('main')!.execute), args, { let child = child_process.spawn(
cwd: this.app.local!.path, path.join(this.app.local!.path, this.app.actions.get("main")!.execute),
stdio: 'inherit' args,
}); {
child.on('error', (error) => { cwd: this.app.local!.path,
stdio: "inherit",
}
);
child.on("error", (error) => {
reject(error); reject(error);
win.restore(); win.restore();
}); });
child.on('exit', async (code, signal) => { child.on("exit", async (code, signal) => {
// error 触发之后还可能会触发exit,但是Promise只承认首次状态转移,因此这里无需重复判断是否已经error过。 // error 触发之后还可能会触发exit,但是Promise只承认首次状态转移,因此这里无需重复判断是否已经error过。
await this.refresh(); await this.refresh();
resolve(); resolve();
win.restore(); win.restore();
}); });
try { try {
this.http.get('https://mycard.moe/ygopro/api/history', { this.http
search: { .get("https://mycard.moe/ygopro/api/history", {
page: 1, search: {
username: this.loginService.user.username, page: 1,
type: 0, username: this.loginService.user.username,
page_num: 1 type: 0,
} page_num: 1,
}) },
})
.map((response) => response.json()) .map((response) => response.json())
.toPromise() .toPromise()
.then((d) => { .then((d) => {
...@@ -554,7 +644,10 @@ export class YGOProComponent implements OnInit, OnDestroy { ...@@ -554,7 +644,10 @@ export class YGOProComponent implements OnInit, OnDestroy {
console.log(error); console.log(error);
} }
try { try {
this.http.get('https://api.mycard.moe/ygopro/arena/user', { search: { username: this.loginService.user.username } }) this.http
.get("https://api.mycard.moe/ygopro/arena/user", {
search: { username: this.loginService.user.username },
})
.map((response) => response.json()) .map((response) => response.json())
.toPromise() .toPromise()
.then((d2) => { .then((d2) => {
...@@ -566,15 +659,16 @@ export class YGOProComponent implements OnInit, OnDestroy { ...@@ -566,15 +659,16 @@ export class YGOProComponent implements OnInit, OnDestroy {
} }
}); });
try { try {
await this.http.get('https://mycard.moe/ygopro/api/history', { await this.http
search: { .get("https://mycard.moe/ygopro/api/history", {
page: 1, search: {
username: this.loginService.user.username, page: 1,
// username: "星光pokeboy", username: this.loginService.user.username,
type: 0, // username: "星光pokeboy",
page_num: 1 type: 0,
} page_num: 1,
}) },
})
.map((response) => response.json()) .map((response) => response.json())
.toPromise() .toPromise()
.then((d) => { .then((d) => {
...@@ -582,11 +676,12 @@ export class YGOProComponent implements OnInit, OnDestroy { ...@@ -582,11 +676,12 @@ export class YGOProComponent implements OnInit, OnDestroy {
data.myname = this.loginService.user.username; data.myname = this.loginService.user.username;
}); });
await this.http.get('https://api.mycard.moe/ygopro/arena/user', { await this.http
search: { .get("https://api.mycard.moe/ygopro/arena/user", {
username: this.loginService.user.username, search: {
} username: this.loginService.user.username,
}) },
})
.map((response) => response.json()) .map((response) => response.json())
.toPromise() .toPromise()
.then((data2) => { .then((data2) => {
...@@ -599,46 +694,58 @@ export class YGOProComponent implements OnInit, OnDestroy { ...@@ -599,46 +694,58 @@ export class YGOProComponent implements OnInit, OnDestroy {
data.exp_rank_ex = exp_rank_ex; data.exp_rank_ex = exp_rank_ex;
data.arena_rank_ex = arena_rank_ex; data.arena_rank_ex = arena_rank_ex;
if (start_time !== data.start_time) { if (start_time !== data.start_time) {
this.appsService.showResult('end_YGOPro_single.html', data, 202, 222); this.appsService.showResult(
"end_YGOPro_single.html",
data,
202,
222
);
} }
}); });
} catch (error) { } catch (error) {
console.log(error); console.log(error);
} }
}; }
create_room(room: Room) { create_room(room: Room) {
let options_buffer = new Buffer(6); let options_buffer = new Buffer(6);
// 建主密码 https://docs.google.com/document/d/1rvrCGIONua2KeRaYNjKBLqyG9uybs9ZI-AmzZKNftOI/edit // 建主密码 https://docs.google.com/document/d/1rvrCGIONua2KeRaYNjKBLqyG9uybs9ZI-AmzZKNftOI/edit
options_buffer.writeUInt8((room.private ? 2 : 1) << 4, 1); options_buffer.writeUInt8((room.private ? 2 : 1) << 4, 1);
options_buffer.writeUInt8( options_buffer.writeUInt8(
room.options.rule << 5 | (room.options.rule << 5) |
room.options.mode << 3 | (room.options.mode << 3) |
(room.options.enable_priority ? 1 << 2 : 0) | (room.options.enable_priority ? 1 << 2 : 0) |
(room.options.no_check_deck ? 1 << 1 : 0) | (room.options.no_check_deck ? 1 << 1 : 0) |
(room.options.no_shuffle_deck ? 1 : 0) (room.options.no_shuffle_deck ? 1 : 0),
, 2); 2
);
options_buffer.writeUInt16LE(room.options.start_lp, 3); options_buffer.writeUInt16LE(room.options.start_lp, 3);
options_buffer.writeUInt8(room.options.start_hand << 4 | room.options.draw_count, 5); options_buffer.writeUInt8(
(room.options.start_hand << 4) | room.options.draw_count,
5
);
let checksum = 0; let checksum = 0;
for (let i = 1; i < options_buffer.length; i++) { for (let i = 1; i < options_buffer.length; i++) {
checksum -= options_buffer.readUInt8(i); checksum -= options_buffer.readUInt8(i);
} }
options_buffer.writeUInt8(checksum & 0xFF, 0); options_buffer.writeUInt8(checksum & 0xff, 0);
let secret = this.loginService.user.external_id % 65535 + 1; let secret = (this.loginService.user.external_id % 65535) + 1;
for (let i = 0; i < options_buffer.length; i += 2) { for (let i = 0; i < options_buffer.length; i += 2) {
options_buffer.writeUInt16LE(options_buffer.readUInt16LE(i) ^ secret, i); options_buffer.writeUInt16LE(options_buffer.readUInt16LE(i) ^ secret, i);
} }
let password = options_buffer.toString('base64') + (room.private ? this.host_password : let password =
room.title!.replace(/\s/, String.fromCharCode(0xFEFF))); options_buffer.toString("base64") +
(room.private
? this.host_password
: room.title!.replace(/\s/, String.fromCharCode(0xfeff)));
// let room_id = crypto.createHash('md5').update(password + this.loginService.user.username).digest('base64') // let room_id = crypto.createHash('md5').update(password + this.loginService.user.username).digest('base64')
// .slice(0, 10).replace('+', '-').replace('/', '_'); // .slice(0, 10).replace('+', '-').replace('/', '_');
if (room.private) { if (room.private) {
new Notification('YGOPro 私密房间已建立', { new Notification("YGOPro 私密房间已建立", {
body: `房间密码是 ${this.host_password}, 您的对手可在自定义游戏界面输入密码与您对战。` body: `房间密码是 ${this.host_password}, 您的对手可在自定义游戏界面输入密码与您对战。`,
}); });
} }
this.join(password, this.servers[0]); this.join(password, this.servers[0]);
...@@ -646,7 +753,7 @@ export class YGOProComponent implements OnInit, OnDestroy { ...@@ -646,7 +753,7 @@ export class YGOProComponent implements OnInit, OnDestroy {
copy(text: string, event: Event) { copy(text: string, event: Event) {
clipboard.writeText(text); clipboard.writeText(text);
$('#copy-wrapper').tooltip({ trigger: 'manual' }).tooltip('show'); $("#copy-wrapper").tooltip({ trigger: "manual" }).tooltip("show");
} }
join_room(room: Room) { join_room(room: Room) {
...@@ -656,15 +763,14 @@ export class YGOProComponent implements OnInit, OnDestroy { ...@@ -656,15 +763,14 @@ export class YGOProComponent implements OnInit, OnDestroy {
for (let i = 1; i < options_buffer.length; i++) { for (let i = 1; i < options_buffer.length; i++) {
checksum -= options_buffer.readUInt8(i); checksum -= options_buffer.readUInt8(i);
} }
options_buffer.writeUInt8(checksum & 0xFF, 0); options_buffer.writeUInt8(checksum & 0xff, 0);
let secret = this.loginService.user.external_id % 65535 + 1; let secret = (this.loginService.user.external_id % 65535) + 1;
for (let i = 0; i < options_buffer.length; i += 2) { for (let i = 0; i < options_buffer.length; i += 2) {
options_buffer.writeUInt16LE(options_buffer.readUInt16LE(i) ^ secret, i); options_buffer.writeUInt16LE(options_buffer.readUInt16LE(i) ^ secret, i);
} }
let name = options_buffer.toString("base64") + room.id;
let name = options_buffer.toString('base64') + room.id;
this.join(name, room.server!); this.join(name, room.server!);
} }
...@@ -676,49 +782,67 @@ export class YGOProComponent implements OnInit, OnDestroy { ...@@ -676,49 +782,67 @@ export class YGOProComponent implements OnInit, OnDestroy {
for (let i = 1; i < options_buffer.length; i++) { for (let i = 1; i < options_buffer.length; i++) {
checksum -= options_buffer.readUInt8(i); checksum -= options_buffer.readUInt8(i);
} }
options_buffer.writeUInt8(checksum & 0xFF, 0); options_buffer.writeUInt8(checksum & 0xff, 0);
let secret = this.loginService.user.external_id % 65535 + 1; let secret = (this.loginService.user.external_id % 65535) + 1;
for (let i = 0; i < options_buffer.length; i += 2) { for (let i = 0; i < options_buffer.length; i += 2) {
options_buffer.writeUInt16LE(options_buffer.readUInt16LE(i) ^ secret, i); options_buffer.writeUInt16LE(options_buffer.readUInt16LE(i) ^ secret, i);
} }
let name = options_buffer.toString('base64') + password.replace(/\s/, String.fromCharCode(0xFEFF)); let name =
options_buffer.toString("base64") +
password.replace(/\s/, String.fromCharCode(0xfeff));
this.join(name, this.servers[0]); this.join(name, this.servers[0]);
} }
request_match(arena = 'entertain') { request_match(arena = "entertain") {
let headers = new Headers(); let headers = new Headers();
headers.append('Authorization', headers.append(
'Basic ' + Buffer.from(this.loginService.user.username + ':' + this.loginService.user.external_id).toString('base64')); "Authorization",
"Basic " +
Buffer.from(
this.loginService.user.username +
":" +
this.loginService.user.external_id
).toString("base64")
);
match_started_at = new Date(); match_started_at = new Date();
this.matching_arena = matching_arena = arena; this.matching_arena = matching_arena = arena;
this.matching = matching = this.http.post('https://api.mycard.moe/ygopro/match', null, { this.matching = matching = this.http
headers: headers, .post("https://api.mycard.moe/ygopro/match", null, {
search: { headers: headers,
arena, search: {
locale: this.settingsService.getLocale() arena,
} locale: this.settingsService.getLocale(),
}).map(response => response.json()) },
.subscribe((data) => { })
this.join(data['password'], { address: data['address'], port: data['port'] }); .map((response) => response.json())
}, (error) => { .subscribe(
alert(`匹配失败`); (data) => {
this.matching = matching = undefined; this.join(data["password"], {
this.matching_arena = matching_arena = undefined; address: data["address"],
if (this.match_interval) { port: data["port"],
clearInterval(this.match_interval); });
this.match_interval = undefined; },
} (error) => {
}, () => { alert(`匹配失败`);
this.matching = matching = undefined; this.matching = matching = undefined;
this.matching_arena = matching_arena = undefined; this.matching_arena = matching_arena = undefined;
if (this.match_interval) { if (this.match_interval) {
clearInterval(this.match_interval); clearInterval(this.match_interval);
this.match_interval = undefined; this.match_interval = undefined;
}
},
() => {
this.matching = matching = undefined;
this.matching_arena = matching_arena = undefined;
if (this.match_interval) {
clearInterval(this.match_interval);
this.match_interval = undefined;
}
} }
}); );
this.refresh_match(); this.refresh_match();
this.match_interval = setInterval(() => { this.match_interval = setInterval(() => {
...@@ -742,18 +866,20 @@ export class YGOProComponent implements OnInit, OnDestroy { ...@@ -742,18 +866,20 @@ export class YGOProComponent implements OnInit, OnDestroy {
this.match_interval = undefined; this.match_interval = undefined;
} }
remote.ipcMain.removeAllListeners('YGOPro'); remote.ipcMain.removeAllListeners("YGOPro");
} }
refresh_match() { refresh_match() {
let match_time = Math.floor((new Date().getTime() - match_started_at.getTime()) / 1000); let match_time = Math.floor(
(new Date().getTime() - match_started_at.getTime()) / 1000
);
let minute = Math.floor(match_time / 60).toString(); let minute = Math.floor(match_time / 60).toString();
if (minute.length === 1) { if (minute.length === 1) {
minute = '0' + minute; minute = "0" + minute;
} }
let second = (match_time % 60).toString(); let second = (match_time % 60).toString();
if (second.length === 1) { if (second.length === 1) {
second = '0' + second; second = "0" + second;
} }
this.match_time = `${minute}:${second}`; this.match_time = `${minute}:${second}`;
this.match_cancelable = match_time <= 5 || match_time >= 180; this.match_cancelable = match_time <= 5 || match_time >= 180;
...@@ -780,7 +906,8 @@ export class YGOProComponent implements OnInit, OnDestroy { ...@@ -780,7 +906,8 @@ export class YGOProComponent implements OnInit, OnDestroy {
bilibili_navigate(event: any) { bilibili_navigate(event: any) {
// event.preventDefault(); // event.preventDefault();
// https://github.com/electron/electron/issues/1378 // https://github.com/electron/electron/issues/1378
this.bilibili.nativeElement.src = 'http://m.bilibili.com/search.html?keyword=YGOPro'; this.bilibili.nativeElement.src =
"http://m.bilibili.com/search.html?keyword=YGOPro";
shell.openExternal(event.url); shell.openExternal(event.url);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment