Commit ac57d1d8 authored by wudizhanche1000's avatar wudizhanche1000

Merge branch 'v3' of https://github.com/mycard/mycard into v3

parents d22b570c b10efc6e
...@@ -18,4 +18,8 @@ a { ...@@ -18,4 +18,8 @@ a {
.active > a { .active > a {
color: #fff; color: #fff;
}
span {
margin-left: 8px;
} }
\ No newline at end of file
<span>已安装</span> <span *ngIf="grouped_apps.installed">已安装</span>
<ul class="nav nav-sidebar"> <ul *ngIf="grouped_apps.installed" class="nav nav-sidebar">
<li *ngFor="let app of grouped_apps.installed" [class.active]="app.id==routingService.app"> <li *ngFor="let app of grouped_apps.installed" [class.active]="app.id==routingService.app">
<a (click)="selectApp(app.id)" href="#">{{app.name[app.locales[0]]}}</a> <a (click)="selectApp(app.id)" href="#">{{app.name[app.locales[0]]}}</a>
</li> </li>
</ul> </ul>
<span>未安装</span> <span *ngIf="grouped_apps.yugioh">游戏王</span>
<ul class="nav nav-sidebar"> <ul *ngIf="grouped_apps.yugioh" class="nav nav-sidebar">
<li *ngFor="let app of grouped_apps.not_installed" [class.active]="app.id==routingService.app"> <li *ngFor="let app of grouped_apps.yugioh" [class.active]="app.id==routingService.app">
<a (click)="selectApp(app.id)" href="#">{{app.name[app.locales[0]]}}</a> <a (click)="selectApp(app.id)" href="#">{{app.name[app.locales[0]]}}</a>
</li> </li>
</ul> </ul>
<!--<ul class="nav nav-sidebar"> <span *ngIf="grouped_apps.touhou">东方 Project</span>
<li><a href="">Nav item</a></li> <ul *ngIf="grouped_apps.touhou" class="nav nav-sidebar">
<li><a href="">Nav item again</a></li> <li *ngFor="let app of grouped_apps.touhou" [class.active]="app.id==routingService.app">
<li><a href="">One more nav</a></li> <a (click)="selectApp(app.id)" href="#">{{app.name[app.locales[0]]}}</a>
<li><a href="">Another nav item</a></li> </li>
<li><a href="">More navigation</a></li>
</ul> </ul>
<ul class="nav nav-sidebar"> <span *ngIf="grouped_apps.touhou_pc98">东方旧作</span>
<li><a href="">Nav item again</a></li> <ul *ngIf="grouped_apps.touhou_pc98" class="nav nav-sidebar">
<li><a href="">One more nav</a></li> <li *ngFor="let app of grouped_apps.touhou_pc98" [class.active]="app.id==routingService.app">
<li><a href="">Another nav item</a></li> <a (click)="selectApp(app.id)" href="#">{{app.name[app.locales[0]]}}</a>
</ul>--> </li>
</ul>
\ No newline at end of file
<!--<div class="list-group">
</div>-->
\ No newline at end of file
...@@ -42,16 +42,18 @@ export class AppsComponent { ...@@ -42,16 +42,18 @@ export class AppsComponent {
} }
get grouped_apps() { get grouped_apps() {
let result = {'installed': [], 'not_installed': []}; let result = {'installed': []};
for (let app of this.apps) { for (let app of this.apps) {
if (app.local) { if (app.local) {
result.installed.push(app) result.installed.push(app)
} else { } else {
result.not_installed.push(app) if (!result[app.tags[0]]) {
result[app.tags[0]] = []
}
result[app.tags[0]].push(app)
} }
} }
//console.log(result)
return result return result
} }
}
} \ No newline at end of file
#game-list-modal tbody {
display: block;
overflow-y: auto;
height: 21.5rem;
}
#game-list-modal thead {
position: relative;
display: block;
}
#game-list-modal tr {
width: 100%;
display: table;
}
#game-list-modal .table {
margin-bottom: 0;
}
#game-list-modal .avatar {
width: 25px;
height: 25px;
border-radius: 50%;
}
#game-list-modal .players {
padding-top: .5rem;
padding-bottom: .5rem;
}
#game-list-modal .close {
position: absolute;
top: 15px;
right: 15px;
}
#game-list-modal .modal-header {
padding-left: 0;
padding-right: 0;
}
#game-list-modal .modal-header th {
line-height: 36px;
padding-top: 0;
padding-bottom: 0;
border: none;
}
#game-list-modal .modal-body {
padding: 0;
height: 21.4rem;
}
#game-list-modal .modal-body tr:first-child td{
border-top: none;
}
#game-list-modal .modal-body tr:last-child td{
border-bottom: none;
}
/*fixme: auto width*/
#game-list-modal .title {
width: 25%;
}
#game-list-modal .users {
width: 20%;
}
#game-list-modal .mode {
width: 20%;
}
#game-list-modal .extra {
width: 35%;
}
.float-left {
float: left;
}
\ No newline at end of file
...@@ -53,19 +53,20 @@ ...@@ -53,19 +53,20 @@
</button> </button>
<h4 class="modal-title" id="myModalLabel">创建房间</h4> <h4 class="modal-title" id="myModalLabel">创建房间</h4>
</div> </div>
<form id="game-create"> <form id="game-create" (submit)="create_room(room)">
<div class="modal-body"> <div class="modal-body">
<div class="form-group row"> <div class="form-group row">
<label for="game-create-title" class="col-sm-2 form-control-label">游戏标题</label> <label for="game-create-title" class="col-sm-2 form-control-label">游戏标题</label>
<div class="col-sm-10"> <div class="col-sm-10">
<input type="text" class="form-control" id="game-create-title" name="title"> <input type="text" class="form-control" id="game-create-title" name="title"
[(ngModel)]="room.title">
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label for="game-create-rule" class="col-sm-2 form-control-label">卡片允许</label> <label for="game-create-rule" class="col-sm-2 form-control-label">卡片允许</label>
<div class="col-sm-10"> <div class="col-sm-10">
<select class="form-control" id="game-create-rule" name="rule"> <select class="form-control" id="game-create-rule" name="rule" [(ngModel)]="room.rule">
<option value="0" selected>OCG</option> <option value="0">OCG</option>
<option value="1">TCG</option> <option value="1">TCG</option>
<option value="2">OCG & TCG</option> <option value="2">OCG & TCG</option>
<option value="3">专有卡禁止</option> <option value="3">专有卡禁止</option>
...@@ -75,22 +76,22 @@ ...@@ -75,22 +76,22 @@
<div class="form-group row"> <div class="form-group row">
<label for="game-create-mode" class="col-sm-2 form-control-label">决斗模式</label> <label for="game-create-mode" class="col-sm-2 form-control-label">决斗模式</label>
<div class="col-sm-10"> <div class="col-sm-10">
<select class="form-control" id="game-create-mode" name="mode"> <select class="form-control" id="game-create-mode" name="mode" [(ngModel)]="room.mode">
<option value="0">单局模式</option> <option value="0">单局模式</option>
<option value="1" selected>比赛模式</option> <option value="1">比赛模式</option>
<option value="2">TAG</option> <option value="2">TAG</option>
</select> </select>
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-2 form-control-label">额外选项</label> <label class="col-sm-2 form-control-label">额外选项</label>
<div class="col-sm-4"> <div class="col-sm-5">
<div class="row"> <div class="row">
<label for="game-create-start-lp" class="col-sm-6 form-control-label">初始 LP</label> <label for="game-create-start-lp" class="col-sm-6 form-control-label">初始 LP</label>
<div class="col-sm-6"> <div class="col-sm-6">
<input name="start_lp" type="number" value="8000" min="1" max="65536" <input name="start_lp" type="number" value="8000" min="1" max="65536"
class="form-control form-control-sm game-create-extra" class="form-control form-control-sm game-create-extra"
id="game-create-start-lp"> id="game-create-start-lp" [(ngModel)]="room.start_lp">
</div> </div>
</div> </div>
<div class="row"> <div class="row">
...@@ -98,7 +99,7 @@ ...@@ -98,7 +99,7 @@
<div class="col-sm-6"> <div class="col-sm-6">
<input name="start_hand" type="number" value="5" min="0" max="16" <input name="start_hand" type="number" value="5" min="0" max="16"
class="form-control form-control-sm game-create-extra" class="form-control form-control-sm game-create-extra"
id="game-create-start-hand"> id="game-create-start-hand" [(ngModel)]="room.start_hand">
</div> </div>
</div> </div>
<div class="row"> <div class="row">
...@@ -106,29 +107,29 @@ ...@@ -106,29 +107,29 @@
<div class="col-sm-6"> <div class="col-sm-6">
<input name="draw_count" type="number" value="1" min="0" max="16" <input name="draw_count" type="number" value="1" min="0" max="16"
class="form-control form-control-sm game-create-extra" class="form-control form-control-sm game-create-extra"
id="game-create-draw-count"> id="game-create-draw-count" [(ngModel)]="room.draw_count">
</div> </div>
</div> </div>
</div> </div>
<div class="col-sm-6"> <div class="col-sm-5">
<div class="checkbox"> <div class="checkbox">
<label> <label>
<input name="enable_priority" type="checkbox">允许启动效果优先权 <input name="enable_priority" type="checkbox" [(ngModel)]="room.enable_priority">允许启动效果优先权
</label> </label>
</div> </div>
<div class="checkbox"> <div class="checkbox">
<label> <label>
<input name="no_check_deck" type="checkbox">不检查卡组 <input name="no_check_deck" type="checkbox" [(ngModel)]="room.no_check_deck">不检查卡组
</label> </label>
</div> </div>
<div class="checkbox"> <div class="checkbox">
<label> <label>
<input name="no_shuffle_deck" type="checkbox">开局不洗卡组 <input name="no_shuffle_deck" type="checkbox" [(ngModel)]="room.no_shuffle_deck">开局不洗卡组
</label> </label>
</div> </div>
</div> </div>
</div> </div>
<div class="form-group row"> <!--<div class="form-group row">
<label class="col-sm-2">私密房间</label> <label class="col-sm-2">私密房间</label>
<div class="col-sm-10"> <div class="col-sm-10">
<div class="checkbox"> <div class="checkbox">
...@@ -137,7 +138,7 @@ ...@@ -137,7 +138,7 @@
</label> </label>
</div> </div>
</div> </div>
</div> </div>-->
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button type="button" class="btn btn-secondary float-left" data-dismiss="modal" data-toggle="modal" <button type="button" class="btn btn-secondary float-left" data-dismiss="modal" data-toggle="modal"
...@@ -164,7 +165,25 @@ ...@@ -164,7 +165,25 @@
<th class="extra">额外选项</th> <th class="extra">额外选项</th>
</tr> </tr>
</thead> </thead>
<tbody class="modal-body"></tbody> <tbody class="modal-body">
<tr *ngFor="let room of rooms" class="room" (click)="join_room(room)">
<td class="title">{{room.title}}</td>
<td class="users">
<img *ngFor="let user of room.users" class="avatar"
[src]="'https://ygobbs.com/user_avatar/ygobbs.com/' + user.username + '/25/1.png'">
</td>
<td class="mode">{{{'0': '单局模式', '1': '比赛模式', '2': 'TAG'}[room.mode]}}</td>
<td class="extra">
<span *ngIf="room.rule != default_options.rule">{{{'0': 'OCG', '1': 'TCG', '2': 'O/T', '3': '专有卡禁止'}[room.rule]}}</span>
<span *ngIf="room.start_lp != default_options.start_lp">{{room.start_lp}} LP</span>
<span *ngIf="room.start_hand != default_options.start_hand">{{room.start_hand}} 初始</span>
<span *ngIf="room.draw_count != default_options.draw_count">{{room.draw_count}} 抽卡</span>
<span *ngIf="room.enable_priority != default_options.enable_priority">优先权</span>
<span *ngIf="room.no_check_deck != default_options.no_check_deck">不检查</span>
<span *ngIf="room.no_shuffle_deck != default_options.no_shuffle_deck">不洗卡</span>
</td>
</tbody>
</table> </table>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"> <button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span> <span aria-hidden="true">&times;</span>
......
/** /**
* Created by zh99998 on 16/9/2. * Created by zh99998 on 16/9/2.
*/ */
import {Component} from '@angular/core'; import {Component, OnInit, ChangeDetectorRef} from '@angular/core';
import {AppsService} from "./apps.service"; import {AppsService} from "./apps.service";
import {RoutingService} from "./routing.service"; import {RoutingService} from "./routing.service";
declare var process; declare var process;
declare var System; declare var System;
declare var $;
const fs = System._nodeRequire('fs'); const fs = System._nodeRequire('fs');
const path = System._nodeRequire('path'); const path = System._nodeRequire('path');
const crypto = System._nodeRequire('crypto');
const child_process = System._nodeRequire('child_process'); const child_process = System._nodeRequire('child_process');
//const Promise = System._nodeRequire('bluebird'); //const Promise = System._nodeRequire('bluebird');
const ini = System._nodeRequire('ini'); const ini = System._nodeRequire('ini');
...@@ -19,7 +23,7 @@ const electron = System._nodeRequire('electron'); ...@@ -19,7 +23,7 @@ const electron = System._nodeRequire('electron');
templateUrl: 'app/ygopro.component.html', templateUrl: 'app/ygopro.component.html',
styleUrls: ['app/ygopro.component.css'], styleUrls: ['app/ygopro.component.css'],
}) })
export class YGOProComponent { export class YGOProComponent implements OnInit {
app = this.appsService.searchApp('ygopro'); app = this.appsService.searchApp('ygopro');
decks = []; decks = [];
current_deck; current_deck;
...@@ -30,10 +34,69 @@ export class YGOProComponent { ...@@ -30,10 +34,69 @@ export class YGOProComponent {
windbot = ["琪露诺", "谜之剑士LV4", "复制植物", "尼亚"]; windbot = ["琪露诺", "谜之剑士LV4", "复制植物", "尼亚"];
servers = [{address:"112.124.105.11", port: 7911}]; servers = [{id: 'tiramisu', url: 'wss://tiramisu.mycard.moe:7923', address: "112.124.105.11", port: 7911}];
user = {external_id: 1, username: 'zh99998'}; // for test
default_options = {
mode: 1,
rule: 0,
start_lp: 8000,
start_hand: 5,
draw_count: 1,
enable_priority: false,
no_check_deck: false,
no_shuffle_deck: false
};
room = Object.assign({title: this.user.username + '的房间'}, this.default_options);
constructor(private appsService: AppsService, private routingService: RoutingService) { rooms = [];
this.refresh()
connections = [];
constructor(private appsService: AppsService, private routingService: RoutingService, private ref: ChangeDetectorRef) {
this.refresh();
}
ngOnInit() {
let modal = $('#game-list-modal');
modal.on('show.bs.modal', (event) => {
this.connections = this.servers.map((server)=> {
let connection = new WebSocket(server.url);
connection.onclose = () => {
this.rooms = this.rooms.filter(room=>room.server != server)
};
connection.onmessage = (event) => {
let message = JSON.parse(event.data);
//console.log(message)
switch (message.event) {
case 'init':
this.rooms = this.rooms.filter(room => room.server != server).concat(message.data.map(data => Object.assign({server: server}, this.default_options, data)));
break;
case 'create':
this.rooms.push(Object.assign({server: server}, this.default_options, message.data));
break;
case 'update':
Object.assign(this.rooms.find(room=>room.server == server && room.id == message.data.id), this.default_options, 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', (event) => {
for (let connection of this.connections) {
connection.close();
}
this.connections = []
});
} }
refresh = () => { refresh = () => {
...@@ -124,16 +187,18 @@ export class YGOProComponent { ...@@ -124,16 +187,18 @@ export class YGOProComponent {
data['lastip'] = server.address; data['lastip'] = server.address;
data['lastport'] = server.port; data['lastport'] = server.port;
data['roompass'] = name; data['roompass'] = name;
data['nickname'] = this.user.username;
console.log(data)
return data return data
}) })
.then(this.save_system_conf) .then(this.save_system_conf)
.then(()=>['-j']) .then(()=>['-j'])
.then(this.start_game) .then(this.start_game)
.catch(reason=>console.log(reason)) .catch(reason=>alert(reason))
}; };
join_windbot(name) { join_windbot(name) {
this.join('AI#'+name, this.servers[0]) this.join('AI#' + name, this.servers[0])
} }
start_game = (args) => { start_game = (args) => {
...@@ -152,4 +217,48 @@ export class YGOProComponent { ...@@ -152,4 +217,48 @@ export class YGOProComponent {
}) })
}) })
}; };
create_room(options) {
let options_buffer = new Buffer(6);
// 建主密码 https://docs.google.com/document/d/1rvrCGIONua2KeRaYNjKBLqyG9uybs9ZI-AmzZKNftOI/edit
options_buffer.writeUInt8((options.private ? 2 : 1) << 4, 1);
options_buffer.writeUInt8(parseInt(options.rule) << 5 | parseInt(options.mode) << 3 | (options.enable_priority ? 1 << 2 : 0) | (options.no_check_deck ? 1 << 1 : 0) | (options.no_shuffle_deck ? 1 : 0), 2);
options_buffer.writeUInt16LE(parseInt(options.start_lp), 3);
options_buffer.writeUInt8(parseInt(options.start_hand) << 4 | parseInt(options.draw_count), 5);
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.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 password = options_buffer.toString('base64') + options.title.replace(/\s/, String.fromCharCode(0xFEFF));
let room_id = crypto.createHash('md5').update(password + this.user.username).digest('base64').slice(0, 10).replace('+', '-').replace('/', '_')
this.join(password, this.servers[0]);
}
join_room(room) {
let options_buffer = new Buffer(6);
options_buffer.writeUInt8(3 << 4, 1);
let checksum = 0;
for (var i = 1; i < options_buffer.length; i++) {
checksum -= options_buffer.readUInt8(i)
}
options_buffer.writeUInt8(checksum & 0xFF, 0);
let secret = this.user.external_id % 65535 + 1;
for (i = 0; i < options_buffer.length; i += 2) {
options_buffer.writeUInt16LE(options_buffer.readUInt16LE(i) ^ secret, i)
}
let password = options_buffer.toString('base64') + room.id;
this.join(password, room.server);
}
} }
...@@ -48,7 +48,7 @@ ...@@ -48,7 +48,7 @@
"zh-CN" "zh-CN"
], ],
"name": { "name": {
"zh-CN": "\u4e1c\u65b9\u7ea2\u9b54\u4e61 \u8bed\u8a00\u5305(\u7e41\u4f53\u4e2d\u6587)" "zh-CN": "东方红魔乡 语言包(繁体中文)"
} }
}, },
{ {
...@@ -57,7 +57,7 @@ ...@@ -57,7 +57,7 @@
"zh-CN": "fxt desc" "zh-CN": "fxt desc"
}, },
"tags": [ "tags": [
"game" "touhou"
], ],
"homepage": "http://www.myacg.cc", "homepage": "http://www.myacg.cc",
"author": "ZUN", "author": "ZUN",
...@@ -118,7 +118,7 @@ ...@@ -118,7 +118,7 @@
"zh-CN" "zh-CN"
], ],
"name": { "name": {
"zh-CN": "\u4e1c\u65b9\u7ea2\u9b54\u4e61" "zh-CN": "东方红魔乡"
} }
}, },
{ {
...@@ -156,8 +156,7 @@ ...@@ -156,8 +156,7 @@
"darwin": "1.06" "darwin": "1.06"
}, },
"references": { "references": {
"win32": [ "win32": [],
],
"darwin": [] "darwin": []
}, },
"download": { "download": {
...@@ -170,7 +169,7 @@ ...@@ -170,7 +169,7 @@
"zh-CN" "zh-CN"
], ],
"name": { "name": {
"zh-CN": "\u4e1c\u65b9\u8403\u68a6\u60f3 \u8bed\u8a00\u5305(\u7e41\u4f53\u4e2d\u6587)" "zh-CN": "东方萃梦想 语言包(繁体中文)"
} }
}, },
{ {
...@@ -179,7 +178,7 @@ ...@@ -179,7 +178,7 @@
"zh-CN": "fxt desc" "zh-CN": "fxt desc"
}, },
"tags": [ "tags": [
"game" "touhou"
], ],
"homepage": "http://www.myacg.cc", "homepage": "http://www.myacg.cc",
"author": "ZUN", "author": "ZUN",
...@@ -221,7 +220,7 @@ ...@@ -221,7 +220,7 @@
"zh-CN" "zh-CN"
], ],
"name": { "name": {
"zh-CN": "\u4e1c\u65b9\u8403\u68a6\u60f3" "zh-CN": "东方萃梦想"
} }
}, },
{ {
...@@ -272,7 +271,7 @@ ...@@ -272,7 +271,7 @@
"zh-CN" "zh-CN"
], ],
"name": { "name": {
"zh-CN": "\u4e1c\u65b9\u5996\u5996\u68a6 \u8bed\u8a00\u5305(\u7e41\u4f53\u4e2d\u6587)" "zh-CN": "东方妖妖梦 语言包(繁体中文)"
} }
}, },
{ {
...@@ -281,7 +280,7 @@ ...@@ -281,7 +280,7 @@
"zh-CN": "fxt desc" "zh-CN": "fxt desc"
}, },
"tags": [ "tags": [
"game" "touhou"
], ],
"homepage": "http://www.myacg.cc", "homepage": "http://www.myacg.cc",
"author": "ZUN", "author": "ZUN",
...@@ -323,7 +322,7 @@ ...@@ -323,7 +322,7 @@
"zh-CN" "zh-CN"
], ],
"name": { "name": {
"zh-CN": "\u4e1c\u65b9\u5996\u5996\u68a6" "zh-CN": "东方妖妖梦"
} }
}, },
{ {
...@@ -374,7 +373,7 @@ ...@@ -374,7 +373,7 @@
"zh-CN" "zh-CN"
], ],
"name": { "name": {
"zh-CN": "\u4e1c\u65b9\u6c38\u591c\u6284 \u8bed\u8a00\u5305(\u7b80\u4f53\u4e2d\u6587)" "zh-CN": "东方永夜抄 语言包(简体中文)"
} }
}, },
{ {
...@@ -383,7 +382,7 @@ ...@@ -383,7 +382,7 @@
"zh-CN": "fxt desc" "zh-CN": "fxt desc"
}, },
"tags": [ "tags": [
"game" "touhou"
], ],
"homepage": "http://www.myacg.cc", "homepage": "http://www.myacg.cc",
"author": "ZUN", "author": "ZUN",
...@@ -425,7 +424,7 @@ ...@@ -425,7 +424,7 @@
"zh-CN" "zh-CN"
], ],
"name": { "name": {
"zh-CN": "\u4e1c\u65b9\u6c38\u591c\u6284" "zh-CN": "东方永夜抄"
} }
}, },
{ {
...@@ -476,7 +475,7 @@ ...@@ -476,7 +475,7 @@
"zh-CN" "zh-CN"
], ],
"name": { "name": {
"zh-CN": "\u4e1c\u65b9\u6587\u82b1\u5e16 (\u7e41\u4f53\u4e2d\u6587)" "zh-CN": "东方文花帖 (繁体中文)"
} }
}, },
{ {
...@@ -485,7 +484,7 @@ ...@@ -485,7 +484,7 @@
"zh-CN": "fxt desc" "zh-CN": "fxt desc"
}, },
"tags": [ "tags": [
"game" "touhou"
], ],
"homepage": "http://www.myacg.cc", "homepage": "http://www.myacg.cc",
"author": "ZUN", "author": "ZUN",
...@@ -527,7 +526,7 @@ ...@@ -527,7 +526,7 @@
"zh-CN" "zh-CN"
], ],
"name": { "name": {
"zh-CN": "\u4e1c\u65b9\u6587\u82b1\u5e16" "zh-CN": "东方文花帖"
} }
}, },
{ {
...@@ -578,7 +577,7 @@ ...@@ -578,7 +577,7 @@
"zh-CN" "zh-CN"
], ],
"name": { "name": {
"zh-CN": "\u4e1c\u65b9\u82b1\u6620\u51a2 (\u7e41\u4f53\u4e2d\u6587)" "zh-CN": "东方花映冢 (繁体中文)"
} }
}, },
{ {
...@@ -587,7 +586,7 @@ ...@@ -587,7 +586,7 @@
"zh-CN": "fxt desc" "zh-CN": "fxt desc"
}, },
"tags": [ "tags": [
"game" "touhou"
], ],
"homepage": "http://www.myacg.cc", "homepage": "http://www.myacg.cc",
"author": "ZUN", "author": "ZUN",
...@@ -629,7 +628,7 @@ ...@@ -629,7 +628,7 @@
"zh-CN" "zh-CN"
], ],
"name": { "name": {
"zh-CN": "\u4e1c\u65b9\u82b1\u6620\u51a2" "zh-CN": "东方花映冢"
} }
}, },
{ {
...@@ -680,7 +679,7 @@ ...@@ -680,7 +679,7 @@
"zh-CN" "zh-CN"
], ],
"name": { "name": {
"zh-CN": "\u4e1c\u65b9\u7eef\u60f3\u5929 \u8bed\u8a00\u5305 (\u7b80\u4f53\u4e2d\u6587)" "zh-CN": "东方绯想天 语言包 (简体中文)"
} }
}, },
{ {
...@@ -689,7 +688,7 @@ ...@@ -689,7 +688,7 @@
"zh-CN": "fxt desc" "zh-CN": "fxt desc"
}, },
"tags": [ "tags": [
"game" "touhou"
], ],
"homepage": "http://www.myacg.cc", "homepage": "http://www.myacg.cc",
"author": "ZUN", "author": "ZUN",
...@@ -731,7 +730,7 @@ ...@@ -731,7 +730,7 @@
"zh-CN" "zh-CN"
], ],
"name": { "name": {
"zh-CN": "\u4e1c\u65b9\u7eef\u60f3\u5929" "zh-CN": "东方绯想天"
} }
}, },
{ {
...@@ -782,7 +781,7 @@ ...@@ -782,7 +781,7 @@
"zh-CN" "zh-CN"
], ],
"name": { "name": {
"zh-CN": "\u4e1c\u65b9\u98ce\u795e\u5f55 \u8bed\u8a00\u5305 (\u7b80\u4f53\u4e2d\u6587, \u7e41\u4f53\u4e2d\u6587)" "zh-CN": "东方风神录 语言包 (简体中文, 繁体中文)"
} }
}, },
{ {
...@@ -791,7 +790,7 @@ ...@@ -791,7 +790,7 @@
"zh-CN": "fxt desc" "zh-CN": "fxt desc"
}, },
"tags": [ "tags": [
"game" "touhou"
], ],
"homepage": "http://www.myacg.cc", "homepage": "http://www.myacg.cc",
"author": "ZUN", "author": "ZUN",
...@@ -833,7 +832,7 @@ ...@@ -833,7 +832,7 @@
"zh-CN" "zh-CN"
], ],
"name": { "name": {
"zh-CN": "\u4e1c\u65b9\u98ce\u795e\u5f55" "zh-CN": "东方风神录"
} }
}, },
{ {
...@@ -884,7 +883,7 @@ ...@@ -884,7 +883,7 @@
"zh-CN" "zh-CN"
], ],
"name": { "name": {
"zh-CN": "\u4e1c\u65b9\u5730\u7075\u6bbf \u8bed\u8a00\u5305 (\u7e41\u4f53\u4e2d\u6587)" "zh-CN": "东方地灵殿 语言包 (繁体中文)"
} }
}, },
{ {
...@@ -893,7 +892,7 @@ ...@@ -893,7 +892,7 @@
"zh-CN": "fxt desc" "zh-CN": "fxt desc"
}, },
"tags": [ "tags": [
"game" "touhou"
], ],
"homepage": "http://www.myacg.cc", "homepage": "http://www.myacg.cc",
"author": "ZUN", "author": "ZUN",
...@@ -935,7 +934,7 @@ ...@@ -935,7 +934,7 @@
"zh-CN" "zh-CN"
], ],
"name": { "name": {
"zh-CN": "\u4e1c\u65b9\u5730\u7075\u6bbf" "zh-CN": "东方地灵殿"
} }
}, },
{ {
...@@ -986,7 +985,7 @@ ...@@ -986,7 +985,7 @@
"zh-CN" "zh-CN"
], ],
"name": { "name": {
"zh-CN": "\u4e1c\u65b9\u975e\u60f3\u5929\u5219 \u8bed\u8a00\u5305 (\u7b80\u4f53\u4e2d\u6587)" "zh-CN": "东方非想天则 语言包 (简体中文)"
} }
}, },
{ {
...@@ -995,7 +994,7 @@ ...@@ -995,7 +994,7 @@
"zh-CN": "fxt desc" "zh-CN": "fxt desc"
}, },
"tags": [ "tags": [
"game" "touhou"
], ],
"homepage": "http://www.myacg.cc", "homepage": "http://www.myacg.cc",
"author": "ZUN", "author": "ZUN",
...@@ -1037,7 +1036,7 @@ ...@@ -1037,7 +1036,7 @@
"zh-CN" "zh-CN"
], ],
"name": { "name": {
"zh-CN": "\u4e1c\u65b9\u975e\u60f3\u5929\u5219" "zh-CN": "东方非想天则"
} }
}, },
{ {
...@@ -1088,7 +1087,7 @@ ...@@ -1088,7 +1087,7 @@
"zh-CN" "zh-CN"
], ],
"name": { "name": {
"zh-CN": "\u4e1c\u65b9\u661f\u83b2\u8239 \u8bed\u8a00\u5305 (\u7e41\u4f53\u4e2d\u6587)" "zh-CN": "东方星莲船 语言包 (繁体中文)"
} }
}, },
{ {
...@@ -1097,7 +1096,7 @@ ...@@ -1097,7 +1096,7 @@
"zh-CN": "fxt desc" "zh-CN": "fxt desc"
}, },
"tags": [ "tags": [
"game" "touhou"
], ],
"homepage": "http://www.myacg.cc", "homepage": "http://www.myacg.cc",
"author": "ZUN", "author": "ZUN",
...@@ -1139,7 +1138,7 @@ ...@@ -1139,7 +1138,7 @@
"zh-CN" "zh-CN"
], ],
"name": { "name": {
"zh-CN": "\u4e1c\u65b9\u661f\u83b2\u8239" "zh-CN": "东方星莲船"
} }
}, },
{ {
...@@ -1190,7 +1189,7 @@ ...@@ -1190,7 +1189,7 @@
"zh-CN" "zh-CN"
], ],
"name": { "name": {
"zh-CN": "\u4e1c\u65b9\u7075\u5f02\u4f20 \u8bed\u8a00\u5305 (\u7e41\u4f53\u4e2d\u6587)" "zh-CN": "东方灵异传 语言包 (繁体中文)"
} }
}, },
{ {
...@@ -1199,7 +1198,7 @@ ...@@ -1199,7 +1198,7 @@
"zh-CN": "fxt desc" "zh-CN": "fxt desc"
}, },
"tags": [ "tags": [
"game" "touhou_pc98"
], ],
"homepage": "http://www.myacg.cc", "homepage": "http://www.myacg.cc",
"author": "ZUN", "author": "ZUN",
...@@ -1241,7 +1240,7 @@ ...@@ -1241,7 +1240,7 @@
"zh-CN" "zh-CN"
], ],
"name": { "name": {
"zh-CN": "\u4e1c\u65b9\u7075\u5f02\u4f20" "zh-CN": "东方灵异传"
} }
}, },
{ {
...@@ -1292,7 +1291,7 @@ ...@@ -1292,7 +1291,7 @@
"zh-CN" "zh-CN"
], ],
"name": { "name": {
"zh-CN": "\u4e1c\u65b9\u68a6\u65f6\u7a7a \u8bed\u8a00\u5305 (\u7e41\u4f53\u4e2d\u6587)" "zh-CN": "东方梦时空 语言包 (繁体中文)"
} }
}, },
{ {
...@@ -1301,7 +1300,7 @@ ...@@ -1301,7 +1300,7 @@
"zh-CN": "fxt desc" "zh-CN": "fxt desc"
}, },
"tags": [ "tags": [
"game" "touhou_pc98"
], ],
"homepage": "http://www.myacg.cc", "homepage": "http://www.myacg.cc",
"author": "ZUN", "author": "ZUN",
...@@ -1343,7 +1342,7 @@ ...@@ -1343,7 +1342,7 @@
"zh-CN" "zh-CN"
], ],
"name": { "name": {
"zh-CN": "\u4e1c\u65b9\u68a6\u65f6\u7a7a" "zh-CN": "东方梦时空"
} }
}, },
{ {
...@@ -1394,7 +1393,7 @@ ...@@ -1394,7 +1393,7 @@
"zh-CN" "zh-CN"
], ],
"name": { "name": {
"zh-CN": "\u4e1c\u65b9\u5c01\u9b54\u5f55 \u8bed\u8a00\u5305 (\u7e41\u4f53\u4e2d\u6587)" "zh-CN": "东方封魔录 语言包 (繁体中文)"
} }
}, },
{ {
...@@ -1403,7 +1402,7 @@ ...@@ -1403,7 +1402,7 @@
"zh-CN": "fxt desc" "zh-CN": "fxt desc"
}, },
"tags": [ "tags": [
"game" "touhou_pc98"
], ],
"homepage": "http://www.myacg.cc", "homepage": "http://www.myacg.cc",
"author": "ZUN", "author": "ZUN",
...@@ -1445,7 +1444,7 @@ ...@@ -1445,7 +1444,7 @@
"zh-CN" "zh-CN"
], ],
"name": { "name": {
"zh-CN": "\u4e1c\u65b9\u5c01\u9b54\u5f55" "zh-CN": "东方封魔录"
} }
}, },
{ {
...@@ -1496,7 +1495,7 @@ ...@@ -1496,7 +1495,7 @@
"zh-CN" "zh-CN"
], ],
"name": { "name": {
"zh-CN": "\u4e1c\u65b9\u5e7b\u60f3\u4e61 \u8bed\u8a00\u5305 (\u7e41\u4f53\u4e2d\u6587)" "zh-CN": "东方幻想乡 语言包 (繁体中文)"
} }
}, },
{ {
...@@ -1505,7 +1504,7 @@ ...@@ -1505,7 +1504,7 @@
"zh-CN": "fxt desc" "zh-CN": "fxt desc"
}, },
"tags": [ "tags": [
"game" "touhou_pc98"
], ],
"homepage": "http://www.myacg.cc", "homepage": "http://www.myacg.cc",
"author": "ZUN", "author": "ZUN",
...@@ -1547,7 +1546,7 @@ ...@@ -1547,7 +1546,7 @@
"zh-CN" "zh-CN"
], ],
"name": { "name": {
"zh-CN": "\u4e1c\u65b9\u5e7b\u60f3\u4e61" "zh-CN": "东方幻想乡"
} }
}, },
{ {
...@@ -1598,7 +1597,7 @@ ...@@ -1598,7 +1597,7 @@
"zh-CN" "zh-CN"
], ],
"name": { "name": {
"zh-CN": "\u4e1c\u65b9\u602a\u7eee\u8c08 \u8bed\u8a00\u5305 (\u7e41\u4f53\u4e2d\u6587)" "zh-CN": "东方怪绮谈 语言包 (繁体中文)"
} }
}, },
{ {
...@@ -1607,7 +1606,7 @@ ...@@ -1607,7 +1606,7 @@
"zh-CN": "fxt desc" "zh-CN": "fxt desc"
}, },
"tags": [ "tags": [
"game" "touhou_pc98"
], ],
"homepage": "http://www.myacg.cc", "homepage": "http://www.myacg.cc",
"author": "ZUN", "author": "ZUN",
...@@ -1649,7 +1648,7 @@ ...@@ -1649,7 +1648,7 @@
"zh-CN" "zh-CN"
], ],
"name": { "name": {
"zh-CN": "\u4e1c\u65b9\u602a\u7eee\u8c08" "zh-CN": "东方怪绮谈"
} }
}, },
{ {
...@@ -1662,8 +1661,7 @@ ...@@ -1662,8 +1661,7 @@
}, },
"category": "game", "category": "game",
"tags": [ "tags": [
"game", "yugioh"
"card"
], ],
"locales": [ "locales": [
"zh-CN" "zh-CN"
......
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