Commit 9372c2cd authored by nanahira's avatar nanahira

Merge branch 'v3-multiserver' into v3

parents dd4db6b7 fe181673
Pipeline #4873 passed with stages
in 9 minutes and 1 second
......@@ -58,6 +58,25 @@
/*margin-bottom: 1em;*/
/*}*/
.small-gutters {
margin-right: -5px;
margin-left: 0px;
}
.small-gutters > .col, .small-gutters > [class*="col-"] {
padding-right: 5px;
padding-left: 0px;
}
.small-gutters > .col-sm-4 {
flex: 0 0 40%;
max-width: 40%;
}
.small-gutters > .col-sm-8 {
flex: 0 0 60%;
max-width: 60%;
}
dl {
margin-bottom: 0;
}
......
<div *ngIf="!matching" id="action">
<button [disabled]="!appsService.allReady(app)" (click)="request_match('athletic')" type="button" class="btn btn-primary btn-sm">
<button [disabled]="!appsService.allReady(app) || currentServer.id !== 'tiramisu'" (click)="request_match('athletic')" type="button" class="btn btn-primary btn-sm">
<i class="fa fa-play" aria-hidden="true"></i> <span i18n>竞技匹配</span></button>
<button i18n [disabled]="!appsService.allReady(app)" (click)="request_match('entertain')" type="button" class="btn btn-secondary btn-sm">娱乐匹配</button>
<button i18n [disabled]="!appsService.allReady(app)" type="button" class="btn btn-secondary btn-sm" data-toggle="modal" data-target="#game-list-modal">自定义游戏</button>
<button i18n [disabled]="!appsService.allReady(app)" type="button" class="btn btn-secondary btn-sm" data-toggle="modal" data-target="#game-create-windbot">单人模式</button>
<button i18n [disabled]="!appsService.allReady(app) || currentServer.id !== 'tiramisu'" (click)="request_match('entertain')" type="button" class="btn btn-secondary btn-sm">娱乐匹配</button>
<button i18n [disabled]="!appsService.allReady(app) || !currentServer.custom" type="button" class="btn btn-secondary btn-sm" data-toggle="modal" data-target="#game-list-modal">自定义游戏</button>
<button i18n [disabled]="!appsService.allReady(app) || !currentServer.windbot" type="button" class="btn btn-secondary btn-sm" data-toggle="modal" data-target="#game-create-windbot">单人模式</button>
<button i18n [disabled]="!appsService.allReady(app)" type="button" class="btn btn-secondary btn-sm" data-toggle="modal" data-target="#game-replay-modal">观战录像</button>
</div>
<!-- 匹配中 -->
......@@ -17,16 +17,24 @@
<span class="input-group-btn"><button i18n class="btn btn-secondary" type="button" [disabled]="!match_cancelable" (click)="cancel_match()">取消</button></span>
</div>
<div class="input-group input-group-sm">
<label i18n class="input-group-addon" id="basic-addon1">卡组</label>
<select class="form-control form-control-sm" id="exampleSelect1" name="deck" [(ngModel)]="current_deck">
<option *ngFor="let deck of decks" [ngValue]="deck">{{deck}}</option>
</select> <span class="input-group-btn">
<button id="edit_deck_button" i18n [disabled]="!appsService.allReady(app)" class="btn btn-secondary btn-sm" (click)="edit_deck(current_deck)">编辑</button>
</span>
<div class="row small-gutters">
<div class="col-sm-4 input-group input-group-sm">
<label i18n class="input-group-addon" id="server-label">环境</label>
<select class="form-control form-control-sm" id="selectServer" name="server" [disabled]="!appsService.allReady(app)" [(ngModel)]="currentServer">
<option *ngFor="let server of selectableServers" [ngValue]="server">{{server.name}}</option>
</select>
</div>
<div class="col-sm-8 input-group input-group-sm">
<label i18n class="input-group-addon" id="basic-addon1">卡组</label>
<select class="form-control form-control-sm" id="exampleSelect1" name="deck" [(ngModel)]="current_deck">
<option *ngFor="let deck of decks" [ngValue]="deck">{{deck}}</option>
</select> <span class="input-group-btn">
<button id="edit_deck_button" i18n [disabled]="!appsService.allReady(app)" class="btn btn-secondary btn-sm" (click)="edit_deck(current_deck)">编辑</button>
</span>
</div>
</div>
<div class="modal fade" id="game-create-windbot" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal fade" id="game-create-windbot" *ngIf="currentServer.windbot" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
......@@ -67,7 +75,7 @@
</thead>
<tbody>
<tr *ngFor="let room of rooms" class="room" (click)="join_room(room)">
<tr *ngFor="let room of rooms_show" class="room" (click)="join_room(room)">
<td class="title">{{room.title}}</td>
<td class="users">
<img *ngFor="let user of room.users" class="avatar rounded" [src]="'https://ygobbs.com/user_avatar/ygobbs.com/' + user.username + '/25/1.png'" data-toggle="tooltip" data-placement="bottom" [title]="user.username" (error)="avatar_fallback($event)">
......
......@@ -47,12 +47,15 @@ interface SystemConf {
}
interface Server {
id?: string;
id: string;
name?: string;
url?: string;
address: string;
port: number;
hidden?: boolean;
custom?: boolean;
replay?: boolean;
windbot?: string[];
}
interface Room {
......@@ -93,7 +96,7 @@ export interface Points {
}
interface YGOProData {
windbot: { [locale: string]: string[] };
servers: Server[]
}
......@@ -129,10 +132,22 @@ export class YGOProComponent implements OnInit, OnDestroy {
youtube: ElementRef;
// points: Points;
windbot: string[]; // ["琪露诺", "谜之剑士LV4", "复制植物", "尼亚"];
get windbot() {
return this.currentServer.windbot;
}
servers: Server[];
selectableServers: Server[];
servers: Server[] = [];
//selectingServerId: string;
currentServer: Server;
/*reloadCurrentServer() {
this.currentServer = this.servers.find(s => s.id === this.selectingServerId);
}*/
// tslint:disable-next-line:member-ordering
rooms_loading = true;
default_options: Options = {
......@@ -153,6 +168,7 @@ export class YGOProComponent implements OnInit, OnDestroy {
room: Room = {title: this.loginService.user.username + '的房间', options: Object.assign({}, this.default_options)};
rooms: Room[] = [];
rooms_show: Room[];
connections: WebSocket[] = [];
replay_connections: WebSocket[] = [];
......@@ -216,45 +232,17 @@ export class YGOProComponent implements OnInit, OnDestroy {
this.refresh_match();
}, 1000);
}
}
// if (this.settingsService.getLocale().startsWith('zh')) {
this.servers.push({
id: 'tiramisu',
url: 'wss://tiramisu.mycard.moe:7923',
address: 'tiramisu.mycard.moe',
port: 7911,
custom: true,
replay: true
}, {
id: 'tiramisu-athletic',
url: 'wss://tiramisu.mycard.moe:8923',
address: 'tiramisu.mycard.moe',
port: 8911,
custom: false,
replay: true
});
/*} else {
this.servers.push({
id: 'mercury-us-1-athletic',
url: 'wss://mercury-us-1.mycard.moe:7923',
address: 'mercury-us-1.mycard.moe',
port: 7911,
custom: true,
replay: true
}, {
id: 'mercury-us-1',
url: 'wss://mercury-us-1.mycard.moe:7923',
address: 'mercury-us-1.mycard.moe',
port: 8911,
custom: false,
replay: true
});
}*/
refresh_rooms() {
this.rooms_show = this.rooms.filter((room) => room.server === this.currentServer);
}
refresh_replay_rooms() {
this.replay_rooms_show = this.replay_rooms.filter((room) => {
if (!room.arena && room.server && room.server !== this.currentServer) {
return false;
}
return ((this.replay_rooms_filter.athletic && room.arena === 'athletic') ||
(this.replay_rooms_filter.entertain && room.arena === 'entertain') ||
(this.replay_rooms_filter.single && room.options.mode === 0 && !room.arena && !room.id!.startsWith('AI#')) ||
......@@ -283,6 +271,10 @@ export class YGOProComponent implements OnInit, OnDestroy {
}
async ngOnInit() {
this.servers = (<YGOProData>this.app.data).servers;
this.selectableServers = this.servers.filter(s => !s.hidden);
this.currentServer = this.selectableServers[0];
//this.reloadCurrentServer();
let locale: string;
if (this.settingsService.getLocale().startsWith('zh')) {
......@@ -290,7 +282,6 @@ export class YGOProComponent implements OnInit, OnDestroy {
} else {
locale = 'en-US';
}
this.windbot = (<YGOProData>this.app.data).windbot[locale];
this.system_conf = path.join(this.app.local!.path, 'system.conf');
await this.refresh();
......@@ -305,10 +296,12 @@ export class YGOProComponent implements OnInit, OnDestroy {
let connection = new WebSocket(url.toString());
connection.onclose = (event: CloseEvent) => {
this.rooms = this.rooms.filter(room => room.server !== server);
this.refresh_rooms();
};
connection.onerror = (event: ErrorEvent) => {
console.log('error', server.id, event);
this.rooms = this.rooms.filter(room => room.server !== server);
this.refresh_rooms();
};
connection.onmessage = (event) => {
let message = JSON.parse(event.data);
......@@ -328,6 +321,7 @@ export class YGOProComponent implements OnInit, OnDestroy {
case 'delete':
this.rooms.splice(this.rooms.findIndex(room => room.server === server && room.id === message.data), 1);
}
this.refresh_rooms();
this.ref.detectChanges();
};
return connection;
......@@ -503,7 +497,7 @@ export class YGOProComponent implements OnInit, OnDestroy {
};
async join(name: string, server: Server) {
let system_conf = await this.load_system_conf();
/*let system_conf = await this.load_system_conf();
await this.fix_fonts(system_conf);
system_conf.lastdeck = this.current_deck;
system_conf.lastip = server.address;
......@@ -511,22 +505,22 @@ export class YGOProComponent implements OnInit, OnDestroy {
system_conf.lastport = server.port.toString();
system_conf.roompass = name;
system_conf.nickname = this.loginService.user.username;
await this.save_system_conf(system_conf);
return this.start_game(['-j']);
await this.save_system_conf(system_conf);*/
return this.start_game(['-h', server.address, '-p', server.port.toString(), '-w', name, '-n', this.loginService.user.username, '-d', this.current_deck, '-j']);
};
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);
system_conf.lastdeck = deck;
await this.save_system_conf(system_conf);
await this.save_system_conf(system_conf);*/
return this.start_game(['-d', deck]);
}
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.save_system_conf(system_conf);
await this.save_system_conf(system_conf);*/
return this.start_game(['-r', path.join('replay', replay + '.yrp')]);
}
......@@ -534,7 +528,7 @@ export class YGOProComponent implements OnInit, OnDestroy {
if (!name) {
name = this.windbot[Math.floor(Math.random() * this.windbot.length)];
}
return this.join('AI#' + name, this.servers[0]);
return this.join('AI#' + name, this.currentServer);
}
async start_game(args: string[]) {
......@@ -666,7 +660,7 @@ export class YGOProComponent implements OnInit, OnDestroy {
body: `房间密码是 ${this.host_password}, 您的对手可在自定义游戏界面输入密码与您对战。`
});
}
this.join(password, this.servers[0]);
this.join(password, this.currentServer);
}
copy(text: string, event: Event) {
......@@ -712,7 +706,7 @@ export class YGOProComponent implements OnInit, OnDestroy {
let name = options_buffer.toString('base64') + password.replace(/\s/, String.fromCharCode(0xFEFF));
this.join(name, this.servers[0]);
this.join(name, this.currentServer);
}
request_match(arena = 'entertain') {
......@@ -729,7 +723,7 @@ export class YGOProComponent implements OnInit, OnDestroy {
}
}).map(response => response.json())
.subscribe((data) => {
this.join(data['password'], {address: data['address'], port: data['port']});
this.join(data['password'], {id: '_match', address: data['address'], port: data['port']});
}, (error) => {
alert(`匹配失败`);
this.matching = matching = undefined;
......
......@@ -79,6 +79,7 @@ System.config({
'tether': 'npm:tether/dist/js/tether.min.js',
'bootstrap': 'npm:bootstrap/dist/js/bootstrap.min.js',
'reconnecting-websocket': 'npm:reconnecting-websocket/dist/index.js',
'popper.js': 'npm:popper.js/dist/umd/popper.min.js',
// 'typeahead.js': '@node/typeahead.js'
'raven-js': 'npm:raven-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