Commit 2a54a2d8 authored by nanahira's avatar nanahira

Merge branch 'develop' of ../srvpro into develop

parents e3c45cbe 2a80918f
Pipeline #38026 passed with stages
in 11 minutes and 10 seconds
...@@ -43,23 +43,20 @@ exports.REPLAY_ID_YRP2 = 0x32707279; ...@@ -43,23 +43,20 @@ exports.REPLAY_ID_YRP2 = 0x32707279;
* Metadata stored at the beginning of every replay file. * Metadata stored at the beginning of every replay file.
*/ */
class ReplayHeader { class ReplayHeader {
static REPLAY_COMPRESSED_FLAG = 0x1; constructor() {
static REPLAY_TAG_FLAG = 0x2; this.id = 0;
static REPLAY_DECODED_FLAG = 0x4; this.version = 0;
static REPLAY_SINGLE_MODE = 0x8; this.flag = 0;
static REPLAY_UNIFORM = 0x10; this.seed = 0;
id = 0; this.dataSizeRaw = [];
version = 0; this.hash = 0;
flag = 0; this.props = [];
seed = 0; this.seedSequence = [];
dataSizeRaw = []; this.headerVersion = 0;
hash = 0; this.value1 = 0;
props = []; this.value2 = 0;
seedSequence = []; this.value3 = 0;
headerVersion = 0; }
value1 = 0;
value2 = 0;
value3 = 0;
/** Decompressed size as little‑endian 32‑bit */ /** Decompressed size as little‑endian 32‑bit */
get dataSize() { get dataSize() {
return Buffer.from(this.dataSizeRaw).readUInt32LE(0); return Buffer.from(this.dataSizeRaw).readUInt32LE(0);
...@@ -84,12 +81,16 @@ class ReplayHeader { ...@@ -84,12 +81,16 @@ class ReplayHeader {
} }
} }
exports.ReplayHeader = ReplayHeader; exports.ReplayHeader = ReplayHeader;
ReplayHeader.REPLAY_COMPRESSED_FLAG = 0x1;
ReplayHeader.REPLAY_TAG_FLAG = 0x2;
ReplayHeader.REPLAY_DECODED_FLAG = 0x4;
ReplayHeader.REPLAY_SINGLE_MODE = 0x8;
ReplayHeader.REPLAY_UNIFORM = 0x10;
/** Utility for reading little‑endian primitives from a Buffer */ /** Utility for reading little‑endian primitives from a Buffer */
class ReplayReader { class ReplayReader {
buffer;
pointer = 0;
constructor(buffer) { constructor(buffer) {
this.buffer = buffer; this.buffer = buffer;
this.pointer = 0;
} }
advance(size, read) { advance(size, read) {
const value = read(); const value = read();
...@@ -145,10 +146,9 @@ class ReplayReader { ...@@ -145,10 +146,9 @@ class ReplayReader {
} }
/** Utility for writing little‑endian primitives into a Buffer */ /** Utility for writing little‑endian primitives into a Buffer */
class ReplayWriter { class ReplayWriter {
buffer;
pointer = 0;
constructor(buffer) { constructor(buffer) {
this.buffer = buffer; this.buffer = buffer;
this.pointer = 0;
} }
advance(action, size) { advance(action, size) {
action(); action();
...@@ -195,20 +195,22 @@ class ReplayWriter { ...@@ -195,20 +195,22 @@ class ReplayWriter {
} }
} }
class Replay { class Replay {
header = null; constructor() {
hostName = ''; this.header = null;
clientName = ''; this.hostName = '';
startLp = 0; this.clientName = '';
startHand = 0; this.startLp = 0;
drawCount = 0; this.startHand = 0;
opt = 0; this.drawCount = 0;
hostDeck = null; this.opt = 0;
clientDeck = null; this.hostDeck = null;
tagHostName = null; this.clientDeck = null;
tagClientName = null; this.tagHostName = null;
tagHostDeck = null; this.tagClientName = null;
tagClientDeck = null; this.tagHostDeck = null;
responses = []; this.tagClientDeck = null;
this.responses = [];
}
/** All deck objects in play order */ /** All deck objects in play order */
get decks() { get decks() {
return this.isTag return this.isTag
......
...@@ -11,8 +11,6 @@ const typedefs_json_1 = __importDefault(require("./data/typedefs.json")); ...@@ -11,8 +11,6 @@ const typedefs_json_1 = __importDefault(require("./data/typedefs.json"));
const proto_structs_json_1 = __importDefault(require("./data/proto_structs.json")); const proto_structs_json_1 = __importDefault(require("./data/proto_structs.json"));
const constants_json_1 = __importDefault(require("./data/constants.json")); const constants_json_1 = __importDefault(require("./data/constants.json"));
class Handler { class Handler {
handler;
synchronous;
constructor(handler, synchronous) { constructor(handler, synchronous) {
this.handler = handler; this.handler = handler;
this.synchronous = synchronous || false; this.synchronous = synchronous || false;
...@@ -30,13 +28,6 @@ class Handler { ...@@ -30,13 +28,6 @@ class Handler {
} }
} }
class YGOProMessagesHelper { class YGOProMessagesHelper {
handlers;
structs;
structs_declaration;
typedefs;
proto_structs;
constants;
singleHandleLimit;
constructor(singleHandleLimit) { constructor(singleHandleLimit) {
this.handlers = { this.handlers = {
STOC: [new Map(), STOC: [new Map(),
......
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ClientVersionBlocker = void 0;
const aragami_1 = require("aragami");
let ClientVersionBlocker = class ClientVersionBlocker {
};
exports.ClientVersionBlocker = ClientVersionBlocker;
__decorate([
(0, aragami_1.CacheKey)(),
__metadata("design:type", String)
], ClientVersionBlocker.prototype, "clientKey", void 0);
exports.ClientVersionBlocker = ClientVersionBlocker = __decorate([
(0, aragami_1.CacheTTL)(60000)
], ClientVersionBlocker);
import { CacheKey, CacheTTL } from "aragami";
@CacheTTL(60000)
export class ClientVersionBlocker {
@CacheKey()
clientKey: string;
}
...@@ -8,9 +8,6 @@ const axios_1 = __importDefault(require("axios")); ...@@ -8,9 +8,6 @@ const axios_1 = __importDefault(require("axios"));
const querystring_1 = __importDefault(require("querystring")); const querystring_1 = __importDefault(require("querystring"));
const moment_1 = __importDefault(require("moment")); const moment_1 = __importDefault(require("moment"));
class AthleticChecker { class AthleticChecker {
config;
athleticDeckCache;
lastAthleticDeckFetchTime;
constructor(config) { constructor(config) {
this.config = config; this.config = config;
} }
......
...@@ -9,14 +9,11 @@ const bunyan_1 = require("bunyan"); ...@@ -9,14 +9,11 @@ const bunyan_1 = require("bunyan");
const moment_1 = __importDefault(require("moment")); const moment_1 = __importDefault(require("moment"));
const p_queue_1 = __importDefault(require("p-queue")); const p_queue_1 = __importDefault(require("p-queue"));
class Challonge { class Challonge {
config;
constructor(config) { constructor(config) {
this.config = config; this.config = config;
this.queue = new p_queue_1.default({ concurrency: 1 });
this.log = (0, bunyan_1.createLogger)({ name: 'challonge' });
} }
queue = new p_queue_1.default({ concurrency: 1 });
log = (0, bunyan_1.createLogger)({ name: 'challonge' });
previous;
previousTime;
async getTournamentProcess(noCache = false) { async getTournamentProcess(noCache = false) {
if (!noCache && this.previous && this.previousTime.isAfter((0, moment_1.default)().subtract(this.config.cache_ttl, 'ms'))) { if (!noCache && this.previous && this.previousTime.isAfter((0, moment_1.default)().subtract(this.config.cache_ttl, 'ms'))) {
return this.previous; return this.previous;
......
...@@ -54,10 +54,6 @@ const jszip_1 = __importDefault(require("jszip")); ...@@ -54,10 +54,6 @@ const jszip_1 = __importDefault(require("jszip"));
const fs = __importStar(require("fs")); const fs = __importStar(require("fs"));
require("reflect-metadata"); require("reflect-metadata");
class DataManager { class DataManager {
config;
log;
ready;
db;
constructor(config, log) { constructor(config, log) {
this.config = config; this.config = config;
this.log = log; this.log = log;
......
...@@ -5,41 +5,15 @@ var __importDefault = (this && this.__importDefault) || function (mod) { ...@@ -5,41 +5,15 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "__esModule", { value: true });
exports.encodeDeck = encodeDeck; exports.encodeDeck = encodeDeck;
exports.decodeDeck = decodeDeck; exports.decodeDeck = decodeDeck;
const assert_1 = __importDefault(require("assert")); const ygopro_deck_encode_1 = __importDefault(require("ygopro-deck-encode"));
// deprecated. Use YGOProDeck instead
function encodeDeck(deck) { function encodeDeck(deck) {
deck.main ??= []; const pdeck = new ygopro_deck_encode_1.default();
deck.side ??= []; pdeck.main = deck.main;
let pointer = 0; pdeck.extra = [];
const bufferSize = (2 + deck.main.length + deck.side.length) * 4; pdeck.side = deck.side;
const buffer = Buffer.allocUnsafe(bufferSize); return Buffer.from(pdeck.toUpdateDeckPayload());
buffer.writeInt32LE(deck.main.length, pointer);
pointer += 4;
buffer.writeInt32LE(deck.side.length, pointer);
pointer += 4;
for (let cardCode of deck.main.concat(deck.side)) {
buffer.writeInt32LE(cardCode, pointer);
pointer += 4;
}
(0, assert_1.default)(pointer === bufferSize, `Invalid buffer size. Expected: ${bufferSize}. Got: ${pointer}`);
return buffer;
} }
function decodeDeck(buffer) { function decodeDeck(buffer) {
let pointer = 0; return ygopro_deck_encode_1.default.fromUpdateDeckPayload(buffer);
const mainLength = buffer.readInt32LE(pointer);
pointer += 4;
const sideLength = buffer.readInt32LE(pointer);
pointer += 4;
const correctBufferLength = (2 + mainLength + sideLength) * 4;
(0, assert_1.default)(buffer.length >= (2 + mainLength + sideLength) * 4, `Invalid buffer size. Expected: ${correctBufferLength}. Got: ${buffer.length}`);
const main = [];
const side = [];
for (let i = 0; i < mainLength; ++i) {
main.push(buffer.readInt32LE(pointer));
pointer += 4;
}
for (let i = 0; i < sideLength; ++i) {
side.push(buffer.readInt32LE(pointer));
pointer += 4;
}
return { main, side };
} }
import assert from "assert"; import YGOProDeck from "ygopro-deck-encode";
export interface Deck { export interface Deck {
main: number[]; main: number[];
side: number[]; side: number[];
} }
// deprecated. Use YGOProDeck instead
export function encodeDeck(deck: Deck) { export function encodeDeck(deck: Deck) {
deck.main ??= []; const pdeck = new YGOProDeck();
deck.side ??= []; pdeck.main = deck.main;
let pointer = 0; pdeck.extra = [];
const bufferSize = (2 + deck.main.length + deck.side.length) * 4; pdeck.side = deck.side;
const buffer = Buffer.allocUnsafe(bufferSize); return Buffer.from(pdeck.toUpdateDeckPayload());
buffer.writeInt32LE(deck.main.length, pointer);
pointer += 4;
buffer.writeInt32LE(deck.side.length, pointer);
pointer += 4;
for(let cardCode of deck.main.concat(deck.side)) {
buffer.writeInt32LE(cardCode, pointer);
pointer += 4;
}
assert(pointer === bufferSize, `Invalid buffer size. Expected: ${bufferSize}. Got: ${pointer}`);
return buffer;
} }
export function decodeDeck(buffer: Buffer): Deck { export function decodeDeck(buffer: Buffer): Deck {
let pointer = 0; return YGOProDeck.fromUpdateDeckPayload(buffer);
const mainLength = buffer.readInt32LE(pointer);
pointer += 4;
const sideLength = buffer.readInt32LE(pointer);
pointer += 4;
const correctBufferLength = (2 + mainLength + sideLength) * 4;
assert(buffer.length >= (2 + mainLength + sideLength) * 4, `Invalid buffer size. Expected: ${correctBufferLength}. Got: ${buffer.length}`);
const main: number[] = [];
const side: number[] = [];
for(let i = 0; i < mainLength; ++i) {
main.push(buffer.readInt32LE(pointer));
pointer += 4;
}
for(let i = 0; i < sideLength; ++i) {
side.push(buffer.readInt32LE(pointer));
pointer += 4;
}
return {main, side};
} }
...@@ -13,9 +13,6 @@ exports.Ban = void 0; ...@@ -13,9 +13,6 @@ exports.Ban = void 0;
const typeorm_1 = require("typeorm"); const typeorm_1 = require("typeorm");
const CreateAndUpdateTimeBase_1 = require("./CreateAndUpdateTimeBase"); const CreateAndUpdateTimeBase_1 = require("./CreateAndUpdateTimeBase");
let Ban = class Ban extends CreateAndUpdateTimeBase_1.CreateAndUpdateTimeBase { let Ban = class Ban extends CreateAndUpdateTimeBase_1.CreateAndUpdateTimeBase {
id;
ip;
name;
}; };
exports.Ban = Ban; exports.Ban = Ban;
__decorate([ __decorate([
......
...@@ -13,9 +13,6 @@ exports.BasePlayer = void 0; ...@@ -13,9 +13,6 @@ exports.BasePlayer = void 0;
const typeorm_1 = require("typeorm"); const typeorm_1 = require("typeorm");
const CreateAndUpdateTimeBase_1 = require("./CreateAndUpdateTimeBase"); const CreateAndUpdateTimeBase_1 = require("./CreateAndUpdateTimeBase");
class BasePlayer extends CreateAndUpdateTimeBase_1.CreateAndUpdateTimeBase { class BasePlayer extends CreateAndUpdateTimeBase_1.CreateAndUpdateTimeBase {
id;
name;
pos;
} }
exports.BasePlayer = BasePlayer; exports.BasePlayer = BasePlayer;
__decorate([ __decorate([
......
...@@ -19,19 +19,15 @@ const underscore_1 = __importDefault(require("underscore")); ...@@ -19,19 +19,15 @@ const underscore_1 = __importDefault(require("underscore"));
const moment_1 = __importDefault(require("moment")); const moment_1 = __importDefault(require("moment"));
const CreateAndUpdateTimeBase_1 = require("./CreateAndUpdateTimeBase"); const CreateAndUpdateTimeBase_1 = require("./CreateAndUpdateTimeBase");
let CloudReplay = class CloudReplay extends CreateAndUpdateTimeBase_1.CreateAndUpdateTimeBase { let CloudReplay = class CloudReplay extends CreateAndUpdateTimeBase_1.CreateAndUpdateTimeBase {
id;
data;
fromBuffer(buffer) { fromBuffer(buffer) {
this.data = buffer.toString("base64"); this.data = buffer.toString("base64");
} }
toBuffer() { toBuffer() {
return Buffer.from(this.data, "base64"); return Buffer.from(this.data, "base64");
} }
date;
getDateString() { getDateString() {
return (0, moment_1.default)(this.date).format('YYYY-MM-DD HH:mm:ss'); return (0, moment_1.default)(this.date).format('YYYY-MM-DD HH:mm:ss');
} }
players;
getPlayerNamesString() { getPlayerNamesString() {
const playerInfos = underscore_1.default.clone(this.players); const playerInfos = underscore_1.default.clone(this.players);
playerInfos.sort((p1, p2) => p1.pos - p2.pos); playerInfos.sort((p1, p2) => p1.pos - p2.pos);
......
...@@ -15,8 +15,6 @@ const typeorm_1 = require("typeorm"); ...@@ -15,8 +15,6 @@ const typeorm_1 = require("typeorm");
const CloudReplay_1 = require("./CloudReplay"); const CloudReplay_1 = require("./CloudReplay");
const BasePlayer_1 = require("./BasePlayer"); const BasePlayer_1 = require("./BasePlayer");
let CloudReplayPlayer = CloudReplayPlayer_1 = class CloudReplayPlayer extends BasePlayer_1.BasePlayer { let CloudReplayPlayer = CloudReplayPlayer_1 = class CloudReplayPlayer extends BasePlayer_1.BasePlayer {
key;
cloudReplay;
static fromPlayerInfo(info) { static fromPlayerInfo(info) {
const p = new CloudReplayPlayer_1(); const p = new CloudReplayPlayer_1();
p.key = info.key; p.key = info.key;
......
...@@ -12,8 +12,6 @@ Object.defineProperty(exports, "__esModule", { value: true }); ...@@ -12,8 +12,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
exports.CreateAndUpdateTimeBase = void 0; exports.CreateAndUpdateTimeBase = void 0;
const typeorm_1 = require("typeorm"); const typeorm_1 = require("typeorm");
class CreateAndUpdateTimeBase { class CreateAndUpdateTimeBase {
createTime;
updateTime;
} }
exports.CreateAndUpdateTimeBase = CreateAndUpdateTimeBase; exports.CreateAndUpdateTimeBase = CreateAndUpdateTimeBase;
__decorate([ __decorate([
......
...@@ -19,15 +19,6 @@ const moment_1 = __importDefault(require("moment")); ...@@ -19,15 +19,6 @@ const moment_1 = __importDefault(require("moment"));
const underscore_1 = __importDefault(require("underscore")); const underscore_1 = __importDefault(require("underscore"));
const CreateAndUpdateTimeBase_1 = require("./CreateAndUpdateTimeBase"); const CreateAndUpdateTimeBase_1 = require("./CreateAndUpdateTimeBase");
let DuelLog = class DuelLog extends CreateAndUpdateTimeBase_1.CreateAndUpdateTimeBase { let DuelLog = class DuelLog extends CreateAndUpdateTimeBase_1.CreateAndUpdateTimeBase {
id;
time;
name;
roomId;
cloudReplayId; // not very needed to become a relation
replayFileName;
roomMode;
duelCount;
players;
getViewString() { getViewString() {
const viewPlayers = underscore_1.default.clone(this.players); const viewPlayers = underscore_1.default.clone(this.players);
viewPlayers.sort((p1, p2) => p1.pos - p2.pos); viewPlayers.sort((p1, p2) => p1.pos - p2.pos);
......
...@@ -16,15 +16,6 @@ const BasePlayer_1 = require("./BasePlayer"); ...@@ -16,15 +16,6 @@ const BasePlayer_1 = require("./BasePlayer");
const DuelLog_1 = require("./DuelLog"); const DuelLog_1 = require("./DuelLog");
const DeckEncoder_1 = require("../DeckEncoder"); const DeckEncoder_1 = require("../DeckEncoder");
let DuelLogPlayer = DuelLogPlayer_1 = class DuelLogPlayer extends BasePlayer_1.BasePlayer { let DuelLogPlayer = DuelLogPlayer_1 = class DuelLogPlayer extends BasePlayer_1.BasePlayer {
realName;
ip;
isFirst;
score;
lp;
cardCount;
startDeckBuffer;
currentDeckBuffer;
winner;
setStartDeck(deck) { setStartDeck(deck) {
if (!deck) { if (!deck) {
this.startDeckBuffer = null; this.startDeckBuffer = null;
...@@ -45,7 +36,6 @@ let DuelLogPlayer = DuelLogPlayer_1 = class DuelLogPlayer extends BasePlayer_1.B ...@@ -45,7 +36,6 @@ let DuelLogPlayer = DuelLogPlayer_1 = class DuelLogPlayer extends BasePlayer_1.B
getCurrentDeck() { getCurrentDeck() {
return (0, DeckEncoder_1.decodeDeck)(Buffer.from(this.currentDeckBuffer, "base64")); return (0, DeckEncoder_1.decodeDeck)(Buffer.from(this.currentDeckBuffer, "base64"));
} }
duelLog;
static fromDuelLogPlayerInfo(info) { static fromDuelLogPlayerInfo(info) {
const p = new DuelLogPlayer_1(); const p = new DuelLogPlayer_1();
p.name = info.name; p.name = info.name;
......
...@@ -13,11 +13,6 @@ exports.RandomDuelBan = void 0; ...@@ -13,11 +13,6 @@ exports.RandomDuelBan = void 0;
const typeorm_1 = require("typeorm"); const typeorm_1 = require("typeorm");
const CreateAndUpdateTimeBase_1 = require("./CreateAndUpdateTimeBase"); const CreateAndUpdateTimeBase_1 = require("./CreateAndUpdateTimeBase");
let RandomDuelBan = class RandomDuelBan extends CreateAndUpdateTimeBase_1.CreateAndUpdateTimeBase { let RandomDuelBan = class RandomDuelBan extends CreateAndUpdateTimeBase_1.CreateAndUpdateTimeBase {
ip;
time;
count;
reasons;
needTip;
setNeedTip(need) { setNeedTip(need) {
this.needTip = need ? 1 : 0; this.needTip = need ? 1 : 0;
} }
......
...@@ -13,11 +13,6 @@ exports.RandomDuelScore = void 0; ...@@ -13,11 +13,6 @@ exports.RandomDuelScore = void 0;
const typeorm_1 = require("typeorm"); const typeorm_1 = require("typeorm");
const CreateAndUpdateTimeBase_1 = require("./CreateAndUpdateTimeBase"); const CreateAndUpdateTimeBase_1 = require("./CreateAndUpdateTimeBase");
let RandomDuelScore = class RandomDuelScore extends CreateAndUpdateTimeBase_1.CreateAndUpdateTimeBase { let RandomDuelScore = class RandomDuelScore extends CreateAndUpdateTimeBase_1.CreateAndUpdateTimeBase {
name;
winCount;
loseCount;
fleeCount;
winCombo;
getDisplayName() { getDisplayName() {
return this.name.split("$")[0]; return this.name.split("$")[0];
} }
......
...@@ -19,16 +19,9 @@ const VipKey_1 = require("./VipKey"); ...@@ -19,16 +19,9 @@ const VipKey_1 = require("./VipKey");
const moment_1 = __importDefault(require("moment")); const moment_1 = __importDefault(require("moment"));
const CreateAndUpdateTimeBase_1 = require("./CreateAndUpdateTimeBase"); const CreateAndUpdateTimeBase_1 = require("./CreateAndUpdateTimeBase");
let User = class User extends CreateAndUpdateTimeBase_1.CreateAndUpdateTimeBase { let User = class User extends CreateAndUpdateTimeBase_1.CreateAndUpdateTimeBase {
key;
chatColor;
vipExpireDate;
isVip() { isVip() {
return this.vipExpireDate && (0, moment_1.default)().isBefore(this.vipExpireDate); return this.vipExpireDate && (0, moment_1.default)().isBefore(this.vipExpireDate);
} }
victory;
words;
dialogues;
usedKeys;
}; };
exports.User = User; exports.User = User;
__decorate([ __decorate([
......
...@@ -13,10 +13,6 @@ exports.UserDialog = void 0; ...@@ -13,10 +13,6 @@ exports.UserDialog = void 0;
const typeorm_1 = require("typeorm"); const typeorm_1 = require("typeorm");
const User_1 = require("./User"); const User_1 = require("./User");
let UserDialog = class UserDialog { let UserDialog = class UserDialog {
id;
cardCode;
text;
user;
}; };
exports.UserDialog = UserDialog; exports.UserDialog = UserDialog;
__decorate([ __decorate([
......
...@@ -14,11 +14,6 @@ const typeorm_1 = require("typeorm"); ...@@ -14,11 +14,6 @@ const typeorm_1 = require("typeorm");
const User_1 = require("./User"); const User_1 = require("./User");
const CreateAndUpdateTimeBase_1 = require("./CreateAndUpdateTimeBase"); const CreateAndUpdateTimeBase_1 = require("./CreateAndUpdateTimeBase");
let VipKey = class VipKey extends CreateAndUpdateTimeBase_1.CreateAndUpdateTimeBase { let VipKey = class VipKey extends CreateAndUpdateTimeBase_1.CreateAndUpdateTimeBase {
id;
key;
type;
isUsed;
usedBy;
toJSON() { toJSON() {
return { key: this.key, type: this.type }; return { key: this.key, type: this.type };
} }
......
...@@ -210,6 +210,8 @@ ...@@ -210,6 +210,8 @@
"banned_athletic_deck_part1": "Entertainment Mode does not allow top ", "banned_athletic_deck_part1": "Entertainment Mode does not allow top ",
"banned_athletic_deck_part2": " popular meta decks. Please change your deck.", "banned_athletic_deck_part2": " popular meta decks. Please change your deck.",
"chat_disabled": "Chat is disabled in this room.", "chat_disabled": "Chat is disabled in this room.",
"version_to_polyfill": "Your client version is not fully supported. Please rejoin to enable temporary compatibility mode. For the best experience, we recommend updating your game to the latest version.",
"version_polyfilled": "Temporary compatibility mode has been enabled for your version. We recommend updating your game to avoid potential compatibility issues in the future.",
"using_athletic_deck": " is using a competitive deck." "using_athletic_deck": " is using a competitive deck."
}, },
"es-es": { "es-es": {
...@@ -569,6 +571,8 @@ ...@@ -569,6 +571,8 @@
"banned_athletic_deck_part1": "娱乐匹配中禁止使用使用数前", "banned_athletic_deck_part1": "娱乐匹配中禁止使用使用数前",
"banned_athletic_deck_part2": "的竞技卡组。请更换卡组。", "banned_athletic_deck_part2": "的竞技卡组。请更换卡组。",
"chat_disabled": "本房间禁止聊天。", "chat_disabled": "本房间禁止聊天。",
"version_to_polyfill": "当前客户端版本暂未完全支持。请重新加入以启用临时兼容模式。为获得更佳体验,建议尽快更新游戏版本。",
"version_polyfilled": "已为当前版本启用临时兼容模式。建议尽快更新游戏,以避免后续兼容性问题。",
"using_athletic_deck": " 正在使用竞技卡组。" "using_athletic_deck": " 正在使用竞技卡组。"
}, },
"ko-kr": { "ko-kr": {
......
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BasePolyfiller = void 0;
class BasePolyfiller {
async polyfillGameMsg(msgTitle, buffer) {
return false;
}
async polyfillResponse(msgTitle, buffer) {
return false;
}
splice(buf, offset, deleteCount = 1) {
if (offset < 0 || offset >= buf.length)
return Buffer.alloc(0);
deleteCount = Math.min(deleteCount, buf.length - offset);
const end = offset + deleteCount;
const deleted = Buffer.allocUnsafe(deleteCount);
buf.copy(deleted, 0, offset, end);
const moveLength = buf.length - end;
if (moveLength > 0) {
buf.copy(buf, offset, end, buf.length);
}
buf.fill(0, buf.length - deleteCount);
return deleted;
}
insert(buf, offset, insertBuf) {
const availableSpace = buf.length - offset;
const insertLength = Math.min(insertBuf.length, availableSpace);
buf.copy(buf, offset + insertLength, offset, buf.length - insertLength);
insertBuf.copy(buf, offset, 0, insertLength);
return buf;
}
}
exports.BasePolyfiller = BasePolyfiller;
export class BasePolyfiller {
async polyfillGameMsg(msgTitle: string, buffer: Buffer) {
return false;
}
async polyfillResponse(msgTitle: string, buffer: Buffer) {
return false;
}
splice(buf: Buffer, offset: number, deleteCount = 1): Buffer {
if (offset < 0 || offset >= buf.length) return Buffer.alloc(0);
deleteCount = Math.min(deleteCount, buf.length - offset);
const end = offset + deleteCount;
const deleted = Buffer.allocUnsafe(deleteCount);
buf.copy(deleted, 0, offset, end);
const moveLength = buf.length - end;
if (moveLength > 0) {
buf.copy(buf, offset, end, buf.length);
}
buf.fill(0, buf.length - deleteCount);
return deleted;
}
insert(buf: Buffer, offset: number, insertBuf: Buffer) {
const availableSpace = buf.length - offset;
const insertLength = Math.min(insertBuf.length, availableSpace);
buf.copy(buf, offset + insertLength, offset, buf.length - insertLength);
insertBuf.copy(buf, offset, 0, insertLength);
return buf;
}
}
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.polyfillGameMsg = polyfillGameMsg;
exports.polyfillResponse = polyfillResponse;
const registry_1 = require("./registry");
const getPolyfillers = (version) => {
const polyfillers = [];
for (const [pVersion, instance] of registry_1.polyfillRegistry.entries()) {
if (version <= pVersion) {
polyfillers.push({ version: pVersion, polyfiller: instance });
}
}
polyfillers.sort((a, b) => a.version - b.version);
return polyfillers.map(p => p.polyfiller);
};
async function polyfillGameMsg(version, msgTitle, buffer) {
const polyfillers = getPolyfillers(version);
for (const polyfiller of polyfillers) {
if (await polyfiller.polyfillGameMsg(msgTitle, buffer)) {
return true;
}
}
return false;
}
async function polyfillResponse(version, msgTitle, buffer) {
const polyfillers = getPolyfillers(version);
for (const polyfiller of polyfillers) {
if (await polyfiller.polyfillResponse(msgTitle, buffer)) {
return true;
}
}
return false;
}
import { BasePolyfiller } from "./base-polyfiller";
import { polyfillRegistry } from "./registry";
const getPolyfillers = (version: number) => {
const polyfillers: {version: number, polyfiller: BasePolyfiller}[] = [];
for (const [pVersion, instance] of polyfillRegistry.entries()) {
if (version <= pVersion) {
polyfillers.push({version: pVersion, polyfiller: instance});
}
}
polyfillers.sort((a, b) => a.version - b.version);
return polyfillers.map(p => p.polyfiller);
}
export async function polyfillGameMsg(version: number, msgTitle: string, buffer: Buffer) {
const polyfillers = getPolyfillers(version);
for (const polyfiller of polyfillers) {
if (await polyfiller.polyfillGameMsg(msgTitle, buffer)) {
return true;
}
}
return false;
}
export async function polyfillResponse(version: number, msgTitle: string, buffer: Buffer) {
const polyfillers = getPolyfillers(version);
for (const polyfiller of polyfillers) {
if (await polyfiller.polyfillResponse(msgTitle, buffer)) {
return true;
}
}
return false;
}
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Polyfiller1361 = exports.gcd = void 0;
const base_polyfiller_1 = require("../base-polyfiller");
const gcd = (nums) => {
const gcdTwo = (a, b) => {
if (b === 0)
return a;
return gcdTwo(b, a % b);
};
return nums.reduce((acc, num) => gcdTwo(acc, num));
};
exports.gcd = gcd;
class Polyfiller1361 extends base_polyfiller_1.BasePolyfiller {
async polyfillGameMsg(msgTitle, buffer) {
if (msgTitle === 'CONFIRM_CARDS') {
// buf[0]: MSG_CONFIRM_CARDS
// buf[1]: playerid
// buf[2]: ADDED skip_panel
this.splice(buffer, 2, 1);
}
else if (msgTitle === 'SELECT_CHAIN') {
// buf[0]: MSG_SELECT_CHAIN
// buf[1]: playerid
// buf[2]: size
// buf[3]: spe_count
// buf[REMOVED]: forced
// buf[4-7]: hint_timing player
// buf[8-11]: hint_timing 1-player
// then it's 14 bytes for each item
// item[0]: not related
// item[1]: ADDED forced
// item[2-13] not related
const size = buffer[2];
const itemStartOffset = 12; // after the header (up to hint timings)
// 判断是否存在任何 item 的 forced = 1(在原始 buffer 中判断)
let anyForced = false;
for (let i = 0; i < size; i++) {
const itemOffset = itemStartOffset + i * 14;
const forced = buffer[itemOffset + 1];
if (forced === 1) {
anyForced = true;
break;
}
}
// 从后往前 splice 每个 item 的 forced 字段
for (let i = size - 1; i >= 0; i--) {
const itemOffset = itemStartOffset + i * 14;
this.splice(buffer, itemOffset + 1, 1); // 删除每个 item 的 forced(第 1 字节)
}
// 最后再插入旧版所需的 forced 标志
this.insert(buffer, 4, Buffer.from([anyForced ? 1 : 0]));
}
else if (msgTitle === 'SELECT_SUM') {
// buf[0]: MSG_SELECT_SUM
// buf[1]: 0 => equal, 1 => greater
// buf[2]: playerid
// buf[3-6]: target_value
// buf[7]: min
// buf[8]: max
// buf[9]: forced_count
// then each item 11 bytes
// item[0-3] code
// item[4] controler
// item[5] location
// item[6] sequence
// item[7-10] value
// item[10 + forced_count * 11] card_count
// same as above items
const targetValue = buffer.readUInt32LE(3);
if (!(targetValue | 0x80000000)) {
return false;
}
const forcedCount = buffer[9];
const cardCount = buffer[10 + forcedCount * 11];
const valueOffsets = [];
for (let i = 0; i < forcedCount; i++) {
const itemOffset = 10 + i * 11;
valueOffsets.push(itemOffset + 7);
}
for (let i = 0; i < cardCount; i++) {
const itemOffset = 11 + forcedCount * 11 + i * 11;
valueOffsets.push(itemOffset + 7);
}
const values = valueOffsets.map(offset => buffer.readUInt32LE(offset));
const gcdValue = (0, exports.gcd)([...values, targetValue & 0x7FFFFFFF]);
buffer.writeUInt32LE(Math.floor(targetValue / gcdValue) & 0xffff, 3);
for (const offset of valueOffsets) {
const value = buffer.readUInt32LE(offset);
buffer.writeUInt32LE(Math.floor(value / gcdValue), offset);
}
}
return false;
}
}
exports.Polyfiller1361 = Polyfiller1361;
import { BasePolyfiller } from "../base-polyfiller";
export const gcd = (nums: number[]) => {
const gcdTwo = (a: number, b: number) => {
if (b === 0) return a;
return gcdTwo(b, a % b);
};
return nums.reduce((acc, num) => gcdTwo(acc, num));
}
export class Polyfiller1361 extends BasePolyfiller {
async polyfillGameMsg(msgTitle: string, buffer: Buffer) {
if (msgTitle === 'CONFIRM_CARDS') {
// buf[0]: MSG_CONFIRM_CARDS
// buf[1]: playerid
// buf[2]: ADDED skip_panel
this.splice(buffer, 2, 1);
} else if (msgTitle === 'SELECT_CHAIN') {
// buf[0]: MSG_SELECT_CHAIN
// buf[1]: playerid
// buf[2]: size
// buf[3]: spe_count
// buf[REMOVED]: forced
// buf[4-7]: hint_timing player
// buf[8-11]: hint_timing 1-player
// then it's 14 bytes for each item
// item[0]: not related
// item[1]: ADDED forced
// item[2-13] not related
const size = buffer[2];
const itemStartOffset = 12; // after the header (up to hint timings)
// 判断是否存在任何 item 的 forced = 1(在原始 buffer 中判断)
let anyForced = false;
for (let i = 0; i < size; i++) {
const itemOffset = itemStartOffset + i * 14;
const forced = buffer[itemOffset + 1];
if (forced === 1) {
anyForced = true;
break;
}
}
// 从后往前 splice 每个 item 的 forced 字段
for (let i = size - 1; i >= 0; i--) {
const itemOffset = itemStartOffset + i * 14;
this.splice(buffer, itemOffset + 1, 1); // 删除每个 item 的 forced(第 1 字节)
}
// 最后再插入旧版所需的 forced 标志
this.insert(buffer, 4, Buffer.from([anyForced ? 1 : 0]));
} else if (msgTitle === 'SELECT_SUM') {
// buf[0]: MSG_SELECT_SUM
// buf[1]: 0 => equal, 1 => greater
// buf[2]: playerid
// buf[3-6]: target_value
// buf[7]: min
// buf[8]: max
// buf[9]: forced_count
// then each item 11 bytes
// item[0-3] code
// item[4] controler
// item[5] location
// item[6] sequence
// item[7-10] value
// item[10 + forced_count * 11] card_count
// same as above items
const targetValue = buffer.readUInt32LE(3);
if (!(targetValue | 0x80000000)) {
return false;
}
const forcedCount = buffer[9];
const cardCount = buffer[10 + forcedCount * 11];
const valueOffsets: number[] = [];
for(let i = 0; i < forcedCount; i++) {
const itemOffset = 10 + i * 11;
valueOffsets.push(itemOffset + 7);
}
for(let i = 0; i < cardCount; i++) {
const itemOffset = 11 + forcedCount * 11 + i * 11;
valueOffsets.push(itemOffset + 7);
}
const values = valueOffsets.map(offset => buffer.readUInt32LE(offset));
const gcdValue = gcd([...values, targetValue & 0x7FFFFFFF]);
buffer.writeUInt32LE(Math.floor(targetValue / gcdValue) & 0xffff, 3);
for(const offset of valueOffsets) {
const value = buffer.readUInt32LE(offset);
buffer.writeUInt32LE(Math.floor(value / gcdValue), offset);
}
}
return false;
}
}
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.polyfillRegistry = void 0;
const _0x1361_1 = require("./polyfillers/0x1361");
exports.polyfillRegistry = new Map();
const addPolyfiller = (version, polyfiller) => {
exports.polyfillRegistry.set(version, new polyfiller());
};
addPolyfiller(0x1361, _0x1361_1.Polyfiller1361);
import { BasePolyfiller } from "./base-polyfiller";
import { Polyfiller1361 } from "./polyfillers/0x1361";
export const polyfillRegistry = new Map<number, BasePolyfiller>();
const addPolyfiller = (version: number, polyfiller: typeof BasePolyfiller) => {
polyfillRegistry.set(version, new polyfiller());
}
addPolyfiller(0x1361, Polyfiller1361);
This diff is collapsed.
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
], ],
"author": "zh99998 <zh99998@gmail.com>, mercury233 <me@mercury233.me>, Nanahira <78877@qq.com>", "author": "zh99998 <zh99998@gmail.com>, mercury233 <me@mercury233.me>, Nanahira <78877@qq.com>",
"dependencies": { "dependencies": {
"aragami": "^1.2.5",
"async": "^3.2.0", "async": "^3.2.0",
"axios": "^0.19.2", "axios": "^0.19.2",
"bunyan": "^1.8.14", "bunyan": "^1.8.14",
...@@ -34,7 +35,8 @@ ...@@ -34,7 +35,8 @@
"typeorm": "^0.2.29", "typeorm": "^0.2.29",
"underscore": "^1.11.0", "underscore": "^1.11.0",
"underscore.string": "^3.3.6", "underscore.string": "^3.3.6",
"ws": "^8.9.0" "ws": "^8.9.0",
"ygopro-deck-encode": "^1.0.9"
}, },
"license": "AGPL-3.0", "license": "AGPL-3.0",
"scripts": { "scripts": {
......
{ {
"compilerOptions": { "compilerOptions": {
"module": "commonjs", "module": "commonjs",
"target": "esnext", "target": "ES2020",
"esModuleInterop": true, "esModuleInterop": true,
"resolveJsonModule": true, "resolveJsonModule": true,
"emitDecoratorMetadata": true, "emitDecoratorMetadata": true,
...@@ -12,6 +12,8 @@ ...@@ -12,6 +12,8 @@
"include": [ "include": [
"*.ts", "*.ts",
"data-manager/*.ts", "data-manager/*.ts",
"data-manager/entities/*.ts" "data-manager/entities/*.ts",
"msg-polyfill/*.ts",
"msg-polyfill/polyfillers/*.ts"
] ]
} }
This diff is collapsed.
This diff is collapsed.
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