Commit 9ccaf124 authored by 神楽坂玲奈's avatar 神楽坂玲奈

约战

parent 30c7c05c
import {Component, Renderer, ChangeDetectorRef, OnInit, ElementRef, ViewChild} from '@angular/core'; import { ChangeDetectorRef, Component, ElementRef, OnInit, Renderer, ViewChild } from '@angular/core';
import {remote, shell} from 'electron';
import {LoginService} from './login.service';
import {SettingsService} from './settings.sevices';
import $ = require('jquery');
import 'bootstrap'; import 'bootstrap';
import { remote, shell } from 'electron';
import * as $ from 'jquery';
import * as Tether from 'tether';
import { LoginService } from './login.service';
import { SettingsService } from './settings.sevices';
window['Tether'] = Tether;
const autoUpdater: Electron.AutoUpdater = remote.getGlobal('autoUpdater'); const autoUpdater: Electron.AutoUpdater = remote.getGlobal('autoUpdater');
...@@ -104,7 +106,7 @@ export class MyCardComponent implements OnInit { ...@@ -104,7 +106,7 @@ export class MyCardComponent implements OnInit {
let element = this.update_elements.get(this.update_status); let element = this.update_elements.get(this.update_status);
if (element) { if (element) {
$(element.nativeElement).tooltip({placement: 'bottom', container: 'body'}); $(element.nativeElement).tooltip({ placement: 'bottom', container: 'body' });
} }
} }
...@@ -119,6 +121,7 @@ export class MyCardComponent implements OnInit { ...@@ -119,6 +121,7 @@ export class MyCardComponent implements OnInit {
remote.app.quit(); remote.app.quit();
} }
} }
// //
// moesound_loaded() { // moesound_loaded() {
// this.moesound.nativeElement.insertCSS(` // this.moesound.nativeElement.insertCSS(`
......
...@@ -205,4 +205,11 @@ form { ...@@ -205,4 +205,11 @@ form {
} }
#watch-filter .form-check-input { #watch-filter .form-check-input {
margin-left: inherit; margin-left: inherit;
} }
\ No newline at end of file
#join-private {
position: absolute;
left: .75rem;
bottom: .75rem;
width: 500px;
}
...@@ -89,15 +89,34 @@ ...@@ -89,15 +89,34 @@
</tr> </tr>
</tbody> </tbody>
</table> </table>
<div id="join-private" class="input-group input-group-sm">
<i class="fa fa-key input-group-addon" aria-hidden="true"></i>
<input [(ngModel)]="join_password" type="text" class="form-control" placeholder="在这输入你朋友的私密房间密码就可以进去了哦!">
<span class="input-group-btn"><button class="btn btn-secondary" type="button" (click)="join_private(join_password)">加入私密房间</button></span>
</div>
</div> </div>
<form (submit)="create_room(room)"> <form (submit)="create_room(room)">
<h3 i18n>创建房间</h3> <h3 i18n>创建房间</h3>
<div class="form-group"> <div class="form-group">
<label i18n for="game-create-title">游戏标题</label> <ng-container *ngIf="!room.private; else private">
<input type="text" maxlength="12" class="form-control form-control-sm" id="game-create-title" name="title" [(ngModel)]="room.title" required> <label i18n for="game-create-title">游戏标题</label>
<small id="emailHelp" class="form-text text-muted">最多 12 个字</small> <input type="text" maxlength="12" class="form-control form-control-sm" id="game-create-title" name="title" [(ngModel)]="room.title" required [readonly]>
<small class="form-text text-muted">最多 12 个字</small>
</ng-container>
<ng-template #private>
<label *ngIf="room.private" for="game-create-title"><i class="fa fa-key" aria-hidden="true"></i>
<span i18n>房间密码</span></label>
<div class="input-group input-group-sm">
<input type="text" maxlength="12" class="form-control" id="game-create-title" name="title" [(ngModel)]="host_password" readonly>
<span id="copy-wrapper" class="input-group-btn" data-toggle="tooltip" title="房间密码已复制到剪贴板">
<button class="btn btn-secondary fa fa-clipboard" type="button" title="复制" (click)="copy(host_password, $event)"></button>
</span>
</div>
<small class="form-text text-muted">把这个分享给你的朋友</small>
</ng-template>
</div> </div>
<div class="form-group"> <div class="form-group">
<label i18n for="game-create-rule">卡片允许</label> <label i18n for="game-create-rule">卡片允许</label>
...@@ -110,7 +129,7 @@ ...@@ -110,7 +129,7 @@
</div> </div>
<div class="form-group"> <div class="form-group">
<label i18n for="game-create-rule">决斗模式</label> <label i18n for="game-create-rule">决斗模式</label>
<select class="form-control form-control-sm" id="game-create-mode" name="mode" [(ngModel)]="room.options.mode"> <select class="form-control form-control-sm" id="game-create-mode" name="mode" (change)="room.options.start_lp = room.options.mode == 2 ? 16000 : 8000" [(ngModel)]="room.options.mode">
<option i18n value="0">单局模式</option> <option i18n value="0">单局模式</option>
<option i18n value="1">比赛模式</option> <option i18n value="1">比赛模式</option>
<option i18n value="2">TAG</option> <option i18n value="2">TAG</option>
...@@ -137,6 +156,10 @@ ...@@ -137,6 +156,10 @@
<input type="number" value="1" min="0" max="16" class="form-control form-control-sm" id="game-create-draw-count" name="draw_count" [(ngModel)]="room.options.draw_count"> <input type="number" value="1" min="0" max="16" class="form-control form-control-sm" id="game-create-draw-count" name="draw_count" [(ngModel)]="room.options.draw_count">
</div> </div>
</div> </div>
<div>
<input id="private" name="private" [(ngModel)]="room.private" type="checkbox">
<label i18n for="private">私密房间</label>
</div>
<div> <div>
<input id="enable_priority" name="enable_priority" [(ngModel)]="room.options.enable_priority" type="checkbox"> <input id="enable_priority" name="enable_priority" [(ngModel)]="room.options.enable_priority" type="checkbox">
<label i18n for="enable_priority">旧规则</label> <label i18n for="enable_priority">旧规则</label>
...@@ -204,7 +227,9 @@ ...@@ -204,7 +227,9 @@
<th class="title"> <th class="title">
<span i18n>游戏模式</span> <span i18n>游戏模式</span>
<div id="watch-filter" class="dropdown"> <div id="watch-filter" class="dropdown">
<button i18n class="btn btn-secondary dropdown-toggle btn-sm" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">筛选</button> <button i18n class="btn btn-secondary dropdown-toggle btn-sm" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
筛选
</button>
<div class="dropdown-menu"> <div class="dropdown-menu">
<h6 i18n class="dropdown-header">匹配</h6> <h6 i18n class="dropdown-header">匹配</h6>
<div class="form-check dropdown-item"> <div class="form-check dropdown-item">
......
...@@ -14,8 +14,8 @@ import { ...@@ -14,8 +14,8 @@ import {
} 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 { remote, shell } from 'electron'; import { clipboard, remote, shell } from 'electron';
import * as fs from 'fs'; 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';
...@@ -178,6 +178,9 @@ export class YGOProComponent implements OnInit, OnDestroy { ...@@ -178,6 +178,9 @@ export class YGOProComponent implements OnInit, OnDestroy {
match_cancelable: boolean; match_cancelable: boolean;
match_interval: Timer | undefined; match_interval: Timer | undefined;
join_password: string;
host_password = (this.loginService.user.external_id ^ 0x54321).toString();
constructor(private http: Http, private appsService: AppsService, private loginService: LoginService, constructor(private http: Http, private appsService: AppsService, private loginService: LoginService,
public settingsService: SettingsService, private ref: ChangeDetectorRef) { public settingsService: SettingsService, private ref: ChangeDetectorRef) {
switch (process.platform) { switch (process.platform) {
...@@ -371,7 +374,7 @@ export class YGOProComponent implements OnInit, OnDestroy { ...@@ -371,7 +374,7 @@ export class YGOProComponent implements OnInit, OnDestroy {
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);
}); });
...@@ -405,34 +408,27 @@ export class YGOProComponent implements OnInit, OnDestroy { ...@@ -405,34 +408,27 @@ export class YGOProComponent implements OnInit, OnDestroy {
} }
}; };
get_decks(): Promise<string[]> { async get_decks(): Promise<string[]> {
return new Promise((resolve, reject) => { try {
fs.readdir(path.join(this.app.local!.path, 'deck'), (error, files) => { let files: string[] = await fs.readdir(path.join(this.app.local!.path, 'deck'));
if (error) { return files.filter(file => path.extname(file) === '.ydk').map(file => path.basename(file, '.ydk'));
resolve([]); } catch (error) {
} else { return [];
resolve(files.filter(file => path.extname(file) === '.ydk').map(file => path.basename(file, '.ydk'))); }
}
});
});
} }
get_replays(): Promise<string[]> { async get_replays(): Promise<string[]> {
return new Promise((resolve, reject) => { try {
fs.readdir(path.join(this.app.local!.path, 'replay'), (error, files) => { let files: string[] = await fs.readdir(path.join(this.app.local!.path, 'replay'));
if (error) { return files.filter(file => path.extname(file) === '.yrp').map(file => path.basename(file, '.yrp'));
resolve([]); } catch (error) {
} else { return [];
resolve(files.filter(file => path.extname(file) === '.yrp').map(file => path.basename(file, '.yrp'))); }
}
});
});
} }
async get_font(files: string[]): Promise<string | undefined> { async get_font(files: string[]): Promise<string | undefined> {
for (let file of files) { for (let file of files) {
let found = await new Promise((resolve) => fs.access(file, fs.constants.R_OK, error => resolve(!error))); if (await fs.pathExists(file)) {
if (found) {
return file; return file;
} }
} }
...@@ -440,7 +436,10 @@ export class YGOProComponent implements OnInit, OnDestroy { ...@@ -440,7 +436,10 @@ export class YGOProComponent implements OnInit, OnDestroy {
async delete_deck(deck: string) { async delete_deck(deck: string) {
if (confirm('确认删除?')) { if (confirm('确认删除?')) {
await new Promise(resolve => fs.unlink(path.join(this.app.local!.path, 'deck', deck + '.ydk'), resolve)); try {
await fs.unlink(path.join(this.app.local!.path, 'deck', deck + '.ydk'));
} catch (error) {
}
return this.refresh(); return this.refresh();
} }
} }
...@@ -461,26 +460,13 @@ export class YGOProComponent implements OnInit, OnDestroy { ...@@ -461,26 +460,13 @@ export class YGOProComponent implements OnInit, OnDestroy {
} }
}; };
load_system_conf(): Promise<SystemConf> { async load_system_conf(): Promise<SystemConf> {
return new Promise((resolve, reject) => { let data = await fs.readFile(this.system_conf, { encoding: 'utf-8' });
fs.readFile(this.system_conf, { encoding: 'utf-8' }, (error, data) => { return ini.parse(data);
if (error) {
return reject(error);
}
resolve(ini.parse(data));
});
});
}; };
save_system_conf(data: SystemConf) { save_system_conf(data: SystemConf) {
return new Promise((resolve, reject) => { return fs.writeFile(this.system_conf, ini.unsafe(ini.stringify(data, <EncodeOptions>{ whitespace: true })));
fs.writeFile(this.system_conf, ini.unsafe(ini.stringify(data, <EncodeOptions>{ whitespace: true })), (error) => {
if (error) {
return reject(error);
}
resolve(data);
});
});
}; };
async join(name: string, server: Server) { async join(name: string, server: Server) {
...@@ -520,7 +506,7 @@ export class YGOProComponent implements OnInit, OnDestroy { ...@@ -520,7 +506,7 @@ export class YGOProComponent implements OnInit, OnDestroy {
async start_game(args: string[]) { async start_game(args: string[]) {
let data: any; let data: any;
let start_time: string ; let start_time: string;
let exp_rank_ex: number; let exp_rank_ex: number;
let arena_rank_ex: number; let arena_rank_ex: number;
let win = remote.getCurrentWindow(); let win = remote.getCurrentWindow();
...@@ -555,18 +541,18 @@ export class YGOProComponent implements OnInit, OnDestroy { ...@@ -555,18 +541,18 @@ export class YGOProComponent implements OnInit, OnDestroy {
.then((d) => { .then((d) => {
start_time = d.data[0].start_time; start_time = d.data[0].start_time;
}); });
}catch (error) { } catch (error) {
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) => {
exp_rank_ex = d2.exp_rank; exp_rank_ex = d2.exp_rank;
arena_rank_ex = d2.arena_rank; arena_rank_ex = d2.arena_rank;
}); });
}catch (error) { } catch (error) {
console.log(error); console.log(error);
} }
}); });
...@@ -607,7 +593,7 @@ export class YGOProComponent implements OnInit, OnDestroy { ...@@ -607,7 +593,7 @@ export class YGOProComponent implements OnInit, OnDestroy {
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);
} }
}; };
...@@ -636,13 +622,24 @@ export class YGOProComponent implements OnInit, OnDestroy { ...@@ -636,13 +622,24 @@ export class YGOProComponent implements OnInit, OnDestroy {
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.title!).replace(/\s/, String.fromCharCode(0xFEFF)); let password = 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) {
new Notification('YGOPro 私密房间已建立', {
body: `房间密码是 ${this.host_password}, 您的对手可在自定义游戏界面输入密码与您对战。`
});
}
this.join(password, this.servers[0]); this.join(password, this.servers[0]);
} }
copy(text: string, event: Event) {
clipboard.writeText(text);
$('#copy-wrapper').tooltip({ trigger: 'manual' }).tooltip('show');
}
join_room(room: Room) { join_room(room: Room) {
let options_buffer = new Buffer(6); let options_buffer = new Buffer(6);
options_buffer.writeUInt8(3 << 4, 1); options_buffer.writeUInt8(3 << 4, 1);
...@@ -658,9 +655,28 @@ export class YGOProComponent implements OnInit, OnDestroy { ...@@ -658,9 +655,28 @@ export class YGOProComponent implements OnInit, OnDestroy {
} }
let password = options_buffer.toString('base64') + room.id; let name = options_buffer.toString('base64') + room.id;
this.join(name, room.server!);
}
join_private(password: string) {
let options_buffer = new Buffer(6);
options_buffer.writeUInt8(5 << 4, 1);
let checksum = 0;
for (let i = 1; i < options_buffer.length; i++) {
checksum -= options_buffer.readUInt8(i);
}
options_buffer.writeUInt8(checksum & 0xFF, 0);
let secret = this.loginService.user.external_id % 65535 + 1;
for (let i = 0; i < options_buffer.length; i += 2) {
options_buffer.writeUInt16LE(options_buffer.readUInt16LE(i) ^ secret, i);
}
let name = options_buffer.toString('base64') + password.replace(/\s/, String.fromCharCode(0xFEFF));
this.join(password, room.server!); this.join(name, this.servers[0]);
} }
request_match(arena = 'entertain') { request_match(arena = 'entertain') {
......
...@@ -73,6 +73,7 @@ System.config({ ...@@ -73,6 +73,7 @@ System.config({
"mkdirp": "@node/mkdirp", "mkdirp": "@node/mkdirp",
"aria2": "@node/aria2", "aria2": "@node/aria2",
"electron-sudo": "@node/electron-sudo", "electron-sudo": "@node/electron-sudo",
'fs-extra': '@node/fs-extra',
'jquery': 'npm:jquery/dist/jquery.min.js', 'jquery': 'npm:jquery/dist/jquery.min.js',
'tether': 'npm:tether/dist/js/tether.min.js', 'tether': 'npm:tether/dist/js/tether.min.js',
......
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