Commit c848d320 authored by nanahira's avatar nanahira

Merge branch 'develop' into ai-play

parents ba65bcef 0d2b5bb9
Pipeline #38152 failed with stages
in 7 minutes and 34 seconds
...@@ -13,7 +13,7 @@ variables: ...@@ -13,7 +13,7 @@ variables:
.docker-x86: .docker-x86:
extends: .docker-op extends: .docker-op
tags: tags:
- docker - docker-noavx2
variables: variables:
ARCH: x86 ARCH: x86
......
...@@ -10,7 +10,7 @@ RUN apt update && \ ...@@ -10,7 +10,7 @@ RUN apt update && \
# windbot # windbot
RUN git clone --depth=1 https://code.mycard.moe/nanahira/windbot /tmp/windbot && \ RUN git clone --depth=1 https://code.mycard.moe/nanahira/windbot /tmp/windbot && \
cd /tmp/windbot && \ cd /tmp/windbot && \
xbuild /property:Configuration=Release /property:TargetFrameworkVersion="v4.5" && \ xbuild /property:Configuration=Release /property:TargetFrameworkVersion="v4.0" && \
mv /tmp/windbot/bin/Release /ygopro-server/windbot && \ mv /tmp/windbot/bin/Release /ygopro-server/windbot && \
cp -rf /ygopro-server/ygopro/cards.cdb /ygopro-server/windbot/ && \ cp -rf /ygopro-server/ygopro/cards.cdb /ygopro-server/windbot/ && \
rm -rf /tmp/windbot rm -rf /tmp/windbot
......
...@@ -2,14 +2,14 @@ ...@@ -2,14 +2,14 @@
FROM debian:bullseye as premake-builder FROM debian:bullseye as premake-builder
RUN apt update && \ RUN apt update && \
env DEBIAN_FRONTEND=noninteractive apt install -y wget build-essential p7zip-full && \ env DEBIAN_FRONTEND=noninteractive apt install -y wget build-essential p7zip-full uuid-dev && \
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* /var/log/* rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* /var/log/*
WORKDIR /usr/src WORKDIR /usr/src
RUN wget -O premake.zip https://github.com/premake/premake-core/releases/download/v5.0.0-beta1/premake-5.0.0-beta1-src.zip && \ RUN wget -O premake.zip https://github.com/premake/premake-core/releases/download/v5.0.0-beta5/premake-5.0.0-beta5-src.zip && \
7z x -y premake.zip && \ 7z x -y premake.zip && \
mv premake-5.0.0-beta1-src premake && \ mv premake-5.0.0-beta5-src premake && \
cd premake/build/gmake2.unix && \ cd premake/build/gmake.unix && \
make -j$(nproc) make -j$(nproc)
FROM node:16-bullseye-slim FROM node:16-bullseye-slim
......
lzma = require 'lzma'
fs = require 'fs'
# Deck = require './Deck.js'
class replayHeader
@replayCompressedFlag = 0x1
@replayTagFlag = 0x2
@replayDecodedFlag = 0x4
constructor: ->
@id = 0
@version = 0
@flag = 0
@seed = 0
@dataSizeRaw = []
@hash = 0
@props = []
getDataSize: ->
@dataSizeRaw[0] + @dataSizeRaw[1] * 0x100 + @dataSizeRaw[2] * 0x10000 + @dataSizeRaw[3] * 0x1000000
getIsTag: ->
@flag & replayHeader.replayTagFlag > 0
getIsCompressed: ->
@flag & replayHeader.replayCompressedFlag > 0
getLzmaHeader: ->
bytes = [].concat(@props[0..4], @dataSizeRaw, [0, 0, 0, 0])
Buffer.from(bytes)
Object.defineProperty replayHeader.prototype, 'dataSize', get: @getDataSize
Object.defineProperty replayHeader.prototype, 'isTag', get: @getIsTag
Object.defineProperty replayHeader.prototype, 'isCompressed', get: @getIsCompressed
class ReplayReader
constructor: (buffer) ->
@pointer = 0
@buffer = buffer
readByte: ->
answer = @buffer.readUInt8(@pointer)
@pointer += 1
answer
readByteArray: (length) ->
answer = []
answer.push @readByte() for i in [1..length]
answer
readInt8: ->
answer = @buffer.readInt8(@pointer)
@pointer += 1
answer
readUInt8: ->
answer = @buffer.readUInt8(@pointer)
@pointer += 1
answer
readInt16: ->
answer = @buffer.readInt16LE @pointer
@pointer += 2
answer
readInt32: ->
answer = @buffer.readInt32LE @pointer
@pointer += 4
answer
readAll: ->
answer = @buffer.slice(@pointer)
# @pointer = 0
answer
readString: (length) ->
if @pointer + length > @buffer.length
return null
full = @buffer.slice(@pointer, @pointer + length).toString('utf-16le')
answer = full.split("\u0000")[0]
@pointer += length
answer
readRaw: (length) ->
if @pointer + length > @buffer.length
return null
answer = @buffer.slice(@pointer, @pointer + length)
@pointer += length
answer
class Replay
constructor: ->
@header = null
@hostName = ""
@clientName = ""
@startLp = 0
@startHand = 0
@drawCount = 0
@opt = 0
@hostDeck = null
@clientDeck = null
@tagHostName = null
@tagClientName = null
@tagHostDeck = null
@tagClientDeck = null
@responses = null
getDecks: ->
if @isTag
[@hostDeck, @clientDeck, @tagHostDeck, @tagClientDeck]
else
[@hostDeck, @clientDeck]
getIsTag: ->
@header == null ? false : @header.isTag
@fromFile: (filePath) ->
Replay.fromBuffer await fs.promises.readFile filePath
@fromBuffer: (buffer) ->
reader = new ReplayReader buffer
header = Replay.readHeader reader
restBuffer = reader.readAll()
lzmaBuffer = Buffer.concat [header.getLzmaHeader(), restBuffer]
if header.isCompressed
decompressed = restBuffer
else
decompressed = Buffer.from lzma.decompress lzmaBuffer
reader = new ReplayReader decompressed
replay = Replay.readReplay header, reader
replay
@readHeader: (reader) ->
header = new replayHeader()
header.id = reader.readInt32()
header.version = reader.readInt32()
header.flag = reader.readInt32()
header.seed = reader.readInt32()
header.dataSizeRaw = reader.readByteArray 4
header.hash = reader.readInt32()
header.props = reader.readByteArray 8
header
@readReplay: (header, reader) ->
replay = new Replay()
replay.header = header
replay.hostName = reader.readString(40)
replay.tagHostName = reader.readString(40) if header.isTag
replay.tagClientName = reader.readString(40) if header.isTag
replay.clientName = reader.readString(40)
replay.startLp = reader.readInt32()
replay.startHand = reader.readInt32()
replay.drawCount = reader.readInt32()
replay.opt = reader.readInt32()
replay.hostDeck = Replay.readDeck reader
replay.tagHostDeck = Replay.readDeck reader if header.isTag
replay.tagClientDeck = Replay.readDeck reader if header.isTag
replay.clientDeck = Replay.readDeck reader
replay.responses = Replay.readResponses reader
replay
@readDeck: (reader) ->
deck = {}
deck.main = Replay.readDeckPack reader
deck.ex = Replay.readDeckPack reader
deck
@readDeckPack: (reader) ->
length = reader.readInt32()
answer = []
answer.push reader.readInt32() for i in [1..length]
answer
@readResponses: (reader) ->
answer = []
while true
try
length = reader.readUInt8()
if length > 64
length = 64
single = reader.readRaw(length)
if !single
break
answer.push(single)
catch
break
answer
Object.defineProperty replayHeader.prototype, 'decks', get: @getDecks
Object.defineProperty replayHeader.prototype, 'isTag', get: @getIsTag
module.exports = Replay
This diff is collapsed.
This diff is collapsed.
...@@ -11,15 +11,13 @@ const typedefs_json_1 = __importDefault(require("./data/typedefs.json")); ...@@ -11,15 +11,13 @@ 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;
} }
async handle(buffer, info, datas, params) { async handle(buffer, info, datas, params) {
if (this.synchronous) { if (this.synchronous) {
return !!(await this.handler(buffer, info, datas, params)); return await this.handler(buffer, info, datas, params);
} }
else { else {
const newBuffer = Buffer.from(buffer); const newBuffer = Buffer.from(buffer);
...@@ -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(),
...@@ -192,7 +183,7 @@ class YGOProMessagesHelper { ...@@ -192,7 +183,7 @@ class YGOProMessagesHelper {
let messageLength = 0; let messageLength = 0;
let bufferProto = 0; let bufferProto = 0;
let datas = []; let datas = [];
const limit = preconnect ? 2 : this.singleHandleLimit; const limit = preconnect ? protoFilter.length * 3 : this.singleHandleLimit;
for (let l = 0; l < limit; ++l) { for (let l = 0; l < limit; ++l) {
if (messageLength === 0) { if (messageLength === 0) {
if (messageBuffer.length >= 2) { if (messageBuffer.length >= 2) {
...@@ -232,7 +223,9 @@ class YGOProMessagesHelper { ...@@ -232,7 +223,9 @@ class YGOProMessagesHelper {
break; break;
} }
let buffer = messageBuffer.slice(3, 2 + messageLength); let buffer = messageBuffer.slice(3, 2 + messageLength);
let bufferMutated = false;
//console.log(l, direction, proto, cancel); //console.log(l, direction, proto, cancel);
let shrinkCount = 0;
for (let priority = 0; priority < 4; ++priority) { for (let priority = 0; priority < 4; ++priority) {
if (cancel) { if (cancel) {
break; break;
...@@ -240,19 +233,37 @@ class YGOProMessagesHelper { ...@@ -240,19 +233,37 @@ class YGOProMessagesHelper {
const handlerCollection = this.handlers[direction][priority]; const handlerCollection = this.handlers[direction][priority];
if (proto && handlerCollection.has(bufferProto)) { if (proto && handlerCollection.has(bufferProto)) {
let struct = this.structs.get(this.proto_structs[direction][proto]); let struct = this.structs.get(this.proto_structs[direction][proto]);
let info = null; for (const handler of handlerCollection.get(bufferProto)) {
if (struct) { let info = null;
struct._setBuff(buffer); if (struct) {
info = underscore_1.default.clone(struct.fields); struct._setBuff(buffer);
} info = underscore_1.default.clone(struct.fields);
for (let handler of handlerCollection.get(bufferProto)) { }
cancel = await handler.handle(buffer, info, datas, params); cancel = await handler.handle(buffer, info, datas, params);
if (cancel) { if (cancel) {
if (cancel === '_cancel') { if (Buffer.isBuffer(cancel)) {
return { buffer = cancel;
datas: [], bufferMutated = true;
feedback cancel = false;
}; }
else if (typeof cancel === "string") {
if (cancel === '_cancel') {
return {
datas: [],
feedback
};
}
else if (cancel.startsWith('_shrink_')) {
const targetShrinkCount = parseInt(cancel.slice(8));
if (targetShrinkCount > buffer.length) {
cancel = true;
}
else {
buffer = buffer.slice(0, buffer.length - targetShrinkCount);
bufferMutated = true;
cancel = false;
}
}
} }
break; break;
} }
...@@ -260,7 +271,14 @@ class YGOProMessagesHelper { ...@@ -260,7 +271,14 @@ class YGOProMessagesHelper {
} }
} }
if (!cancel) { if (!cancel) {
datas.push(messageBuffer.slice(0, 2 + messageLength)); if (bufferMutated) {
const newLength = buffer.length + 1;
messageBuffer.writeUInt16LE(newLength, 0);
datas.push(Buffer.concat([messageBuffer.slice(0, 3), buffer]));
}
else {
datas.push(messageBuffer.slice(0, 2 + messageLength));
}
} }
messageBuffer = messageBuffer.slice(2 + messageLength); messageBuffer = messageBuffer.slice(2 + messageLength);
messageLength = 0; messageLength = 0;
...@@ -290,4 +308,3 @@ class YGOProMessagesHelper { ...@@ -290,4 +308,3 @@ class YGOProMessagesHelper {
} }
} }
exports.YGOProMessagesHelper = YGOProMessagesHelper; exports.YGOProMessagesHelper = YGOProMessagesHelper;
//# sourceMappingURL=YGOProMessages.js.map
\ No newline at end of file
...@@ -8,15 +8,15 @@ import net from "net"; ...@@ -8,15 +8,15 @@ import net from "net";
class Handler { class Handler {
private handler: (buffer: Buffer, info: any, datas: Buffer[], params: any) => Promise<boolean | string>; private handler: (buffer: Buffer, info: any, datas: Buffer[], params: any) => Promise<boolean | string | Buffer>;
synchronous: boolean; synchronous: boolean;
constructor(handler: (buffer: Buffer, info: any, datas: Buffer[], params: any) => Promise<boolean | string>, synchronous: boolean) { constructor(handler: (buffer: Buffer, info: any, datas: Buffer[], params: any) => Promise<boolean | string | Buffer>, synchronous: boolean) {
this.handler = handler; this.handler = handler;
this.synchronous = synchronous || false; this.synchronous = synchronous || false;
} }
async handle(buffer: Buffer, info: any, datas: Buffer[], params: any): Promise<boolean | string> { async handle(buffer: Buffer, info: any, datas: Buffer[], params: any): Promise<boolean | string | Buffer> {
if (this.synchronous) { if (this.synchronous) {
return !!(await this.handler(buffer, info, datas, params)); return await this.handler(buffer, info, datas, params);
} else { } else {
const newBuffer = Buffer.from(buffer); const newBuffer = Buffer.from(buffer);
const newDatas = datas.map(b => Buffer.from(b)); const newDatas = datas.map(b => Buffer.from(b));
...@@ -237,7 +237,7 @@ export class YGOProMessagesHelper { ...@@ -237,7 +237,7 @@ export class YGOProMessagesHelper {
let messageLength = 0; let messageLength = 0;
let bufferProto = 0; let bufferProto = 0;
let datas: Buffer[] = []; let datas: Buffer[] = [];
const limit = preconnect ? 2 : this.singleHandleLimit; const limit = preconnect ? protoFilter.length * 3 : this.singleHandleLimit;
for (let l = 0; l < limit; ++l) { for (let l = 0; l < limit; ++l) {
if (messageLength === 0) { if (messageLength === 0) {
if (messageBuffer.length >= 2) { if (messageBuffer.length >= 2) {
...@@ -264,7 +264,7 @@ export class YGOProMessagesHelper { ...@@ -264,7 +264,7 @@ export class YGOProMessagesHelper {
} else { } else {
if (messageBuffer.length >= 2 + messageLength) { if (messageBuffer.length >= 2 + messageLength) {
const proto = this.constants[direction][bufferProto]; const proto = this.constants[direction][bufferProto];
let cancel: string | boolean = proto && protoFilter && !protoFilter.includes(proto); let cancel: string | boolean | Buffer = proto && protoFilter && !protoFilter.includes(proto);
if (cancel && preconnect) { if (cancel && preconnect) {
feedback = { feedback = {
type: "INVALID_PACKET", type: "INVALID_PACKET",
...@@ -273,7 +273,9 @@ export class YGOProMessagesHelper { ...@@ -273,7 +273,9 @@ export class YGOProMessagesHelper {
break; break;
} }
let buffer = messageBuffer.slice(3, 2 + messageLength); let buffer = messageBuffer.slice(3, 2 + messageLength);
let bufferMutated = false;
//console.log(l, direction, proto, cancel); //console.log(l, direction, proto, cancel);
let shrinkCount = 0;
for (let priority = 0; priority < 4; ++priority) { for (let priority = 0; priority < 4; ++priority) {
if (cancel) { if (cancel) {
break; break;
...@@ -281,18 +283,33 @@ export class YGOProMessagesHelper { ...@@ -281,18 +283,33 @@ export class YGOProMessagesHelper {
const handlerCollection: Map<number, Handler[]> = this.handlers[direction][priority]; const handlerCollection: Map<number, Handler[]> = this.handlers[direction][priority];
if (proto && handlerCollection.has(bufferProto)) { if (proto && handlerCollection.has(bufferProto)) {
let struct = this.structs.get(this.proto_structs[direction][proto]); let struct = this.structs.get(this.proto_structs[direction][proto]);
let info = null; for (const handler of handlerCollection.get(bufferProto)) {
if (struct) { let info = null;
struct._setBuff(buffer); if (struct) {
info = _.clone(struct.fields); struct._setBuff(buffer);
} info = _.clone(struct.fields);
for (let handler of handlerCollection.get(bufferProto)) { }
cancel = await handler.handle(buffer, info, datas, params); cancel = await handler.handle(buffer, info, datas, params);
if (cancel) { if (cancel) {
if (cancel === '_cancel') { if (Buffer.isBuffer(cancel)) {
return { buffer = cancel as any;
datas: [], bufferMutated = true;
feedback cancel = false;
} else if (typeof cancel === "string") {
if (cancel === '_cancel') {
return {
datas: [],
feedback
}
} else if (cancel.startsWith('_shrink_')) {
const targetShrinkCount = parseInt(cancel.slice(8));
if (targetShrinkCount > buffer.length) {
cancel = true;
} else {
buffer = buffer.slice(0, buffer.length - targetShrinkCount);
bufferMutated = true;
cancel = false;
}
} }
} }
break; break;
...@@ -301,7 +318,13 @@ export class YGOProMessagesHelper { ...@@ -301,7 +318,13 @@ export class YGOProMessagesHelper {
} }
} }
if (!cancel) { if (!cancel) {
datas.push(messageBuffer.slice(0, 2 + messageLength)); if (bufferMutated) {
const newLength = buffer.length + 1;
messageBuffer.writeUInt16LE(newLength, 0);
datas.push(Buffer.concat([messageBuffer.slice(0, 3), buffer]));
} else {
datas.push(messageBuffer.slice(0, 2 + messageLength));
}
} }
messageBuffer = messageBuffer.slice(2 + messageLength); messageBuffer = messageBuffer.slice(2 + messageLength);
messageLength = 0; messageLength = 0;
......
"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;
} }
...@@ -57,4 +54,3 @@ class AthleticChecker { ...@@ -57,4 +54,3 @@ class AthleticChecker {
} }
} }
exports.AthleticChecker = AthleticChecker; exports.AthleticChecker = AthleticChecker;
//# sourceMappingURL=athletic-check.js.map
\ No newline at end of file
...@@ -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;
...@@ -67,6 +64,7 @@ class Challonge { ...@@ -67,6 +64,7 @@ class Challonge {
} }
} }
} }
// DELETE /v1/tournaments/${tournament_id}/participants/clear.json?api_key=xxx returns ANY
async clearParticipants() { async clearParticipants() {
try { try {
await axios_1.default.delete(`${this.config.challonge_url}/v1/tournaments/${this.config.tournament_id}/participants/clear.json`, { await axios_1.default.delete(`${this.config.challonge_url}/v1/tournaments/${this.config.tournament_id}/participants/clear.json`, {
...@@ -82,6 +80,7 @@ class Challonge { ...@@ -82,6 +80,7 @@ class Challonge {
return false; return false;
} }
} }
// POST /v1/tournaments/${tournament_id}/participants/bulk_add.json { api_key: string, participants: { name: string }[] } returns ANY
async uploadParticipants(participantNames) { async uploadParticipants(participantNames) {
try { try {
await axios_1.default.post(`${this.config.challonge_url}/v1/tournaments/${this.config.tournament_id}/participants/bulk_add.json`, { await axios_1.default.post(`${this.config.challonge_url}/v1/tournaments/${this.config.tournament_id}/participants/bulk_add.json`, {
...@@ -97,4 +96,3 @@ class Challonge { ...@@ -97,4 +96,3 @@ class Challonge {
} }
} }
exports.Challonge = Challonge; exports.Challonge = Challonge;
//# sourceMappingURL=challonge.js.map
\ No newline at end of file
...@@ -19,8 +19,10 @@ export interface MatchWrapper { ...@@ -19,8 +19,10 @@ export interface MatchWrapper {
export interface Participant { export interface Participant {
id: number; id: number;
name: string; name: string; // 玩家的名称,影响玩家的进服匹配
deckbuf?: string; deckbuf?: string; // 玩家的卡组。如果存在,那么卡组由比赛系统管理。base64
// 构造方法: [uint32 maincount+extracount][uint32 sideccount][uint32 card1][uint32 card2]...
// 示例: NwAAAA8AAAC8beUDdgljAnYJYwJ2CWMCEUKKAxFCigOzoLECB1ekBQdXpAUHV6QFPO4FAzzuBQOSZMQEziwNBM4sDQTOLA0EryPeAK8j3gCvI94AKpVlASqVZQEqlWUBTkEDAE5BAwBOQQMAUI+IAFCPiABQj4gA+twUAaab9AGEoUIBwsdyAcLHcgHCx3IBPRWmBSJImQAiSJkAIkiZADdj4QF8oe8FpFt8A5chZAW1XJ8APXyNAMYzYwOIEXYDtfABBavrrQBq4agDn5BqANCkFwEJWmMAWfK5A3OVmwF8e+QD1xqfAdcanwF99r8Affa/AB43ggEeN4IBhCV+AIQlfgCEJX4APqRxAT6kcQE/OuoDb3bvAG927wC0/F4B
} }
export interface ParticipantWrapper { export interface ParticipantWrapper {
......
"use strict"; "use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k; if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) { }) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k; if (k2 === undefined) k2 = k;
o[k2] = m[k]; o[k2] = m[k];
...@@ -11,13 +15,23 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? ( ...@@ -11,13 +15,23 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
}) : function(o, v) { }) : function(o, v) {
o["default"] = v; o["default"] = v;
}); });
var __importStar = (this && this.__importStar) || function (mod) { var __importStar = (this && this.__importStar) || (function () {
if (mod && mod.__esModule) return mod; var ownKeys = function(o) {
var result = {}; ownKeys = Object.getOwnPropertyNames || function (o) {
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); var ar = [];
__setModuleDefault(result, mod); for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return result; return ar;
}; };
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) { var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod }; return (mod && mod.__esModule) ? mod : { "default": mod };
}; };
...@@ -40,10 +54,6 @@ const jszip_1 = __importDefault(require("jszip")); ...@@ -40,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;
...@@ -780,4 +790,3 @@ class DataManager { ...@@ -780,4 +790,3 @@ class DataManager {
} }
} }
exports.DataManager = DataManager; exports.DataManager = DataManager;
//# sourceMappingURL=DataManager.js.map
\ No newline at end of file
...@@ -3,45 +3,17 @@ var __importDefault = (this && this.__importDefault) || function (mod) { ...@@ -3,45 +3,17 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod }; return (mod && mod.__esModule) ? mod : { "default": mod };
}; };
Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "__esModule", { value: true });
exports.decodeDeck = exports.encodeDeck = void 0; exports.encodeDeck = encodeDeck;
const assert_1 = __importDefault(require("assert")); exports.decodeDeck = decodeDeck;
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;
} }
exports.encodeDeck = encodeDeck;
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 };
} }
exports.decodeDeck = decodeDeck;
//# sourceMappingURL=DeckEncoder.js.map
\ No newline at end of file
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,10 +13,8 @@ exports.Ban = void 0; ...@@ -13,10 +13,8 @@ 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;
__decorate([ __decorate([
(0, typeorm_1.PrimaryGeneratedColumn)({ unsigned: true, type: global.PrimaryKeyType || 'bigint' }), (0, typeorm_1.PrimaryGeneratedColumn)({ unsigned: true, type: global.PrimaryKeyType || 'bigint' }),
__metadata("design:type", Number) __metadata("design:type", Number)
...@@ -31,9 +29,7 @@ __decorate([ ...@@ -31,9 +29,7 @@ __decorate([
(0, typeorm_1.Column)({ type: "varchar", length: 20, nullable: true }), (0, typeorm_1.Column)({ type: "varchar", length: 20, nullable: true }),
__metadata("design:type", String) __metadata("design:type", String)
], Ban.prototype, "name", void 0); ], Ban.prototype, "name", void 0);
Ban = __decorate([ exports.Ban = Ban = __decorate([
(0, typeorm_1.Entity)(), (0, typeorm_1.Entity)(),
(0, typeorm_1.Unique)(["ip", "name"]) (0, typeorm_1.Unique)(["ip", "name"])
], Ban); ], Ban);
exports.Ban = Ban;
//# sourceMappingURL=Ban.js.map
\ No newline at end of file
...@@ -13,10 +13,8 @@ exports.BasePlayer = void 0; ...@@ -13,10 +13,8 @@ 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;
__decorate([ __decorate([
(0, typeorm_1.PrimaryGeneratedColumn)({ unsigned: true, type: global.PrimaryKeyType || 'bigint' }), (0, typeorm_1.PrimaryGeneratedColumn)({ unsigned: true, type: global.PrimaryKeyType || 'bigint' }),
__metadata("design:type", Number) __metadata("design:type", Number)
...@@ -29,5 +27,3 @@ __decorate([ ...@@ -29,5 +27,3 @@ __decorate([
(0, typeorm_1.Column)({ type: "tinyint" }), (0, typeorm_1.Column)({ type: "tinyint" }),
__metadata("design:type", Number) __metadata("design:type", Number)
], BasePlayer.prototype, "pos", void 0); ], BasePlayer.prototype, "pos", void 0);
exports.BasePlayer = BasePlayer;
//# sourceMappingURL=BasePlayer.js.map
\ No newline at end of file
...@@ -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);
...@@ -41,6 +37,7 @@ let CloudReplay = class CloudReplay extends CreateAndUpdateTimeBase_1.CreateAndU ...@@ -41,6 +37,7 @@ let CloudReplay = class CloudReplay extends CreateAndUpdateTimeBase_1.CreateAndU
return `R#${this.id} ${this.getPlayerNamesString()} ${this.getDateString()}`; return `R#${this.id} ${this.getPlayerNamesString()} ${this.getDateString()}`;
} }
}; };
exports.CloudReplay = CloudReplay;
__decorate([ __decorate([
(0, typeorm_1.PrimaryColumn)({ unsigned: true, type: global.PrimaryKeyType || 'bigint' }), (0, typeorm_1.PrimaryColumn)({ unsigned: true, type: global.PrimaryKeyType || 'bigint' }),
__metadata("design:type", Number) __metadata("design:type", Number)
...@@ -58,12 +55,10 @@ __decorate([ ...@@ -58,12 +55,10 @@ __decorate([
(0, typeorm_1.OneToMany)(() => CloudReplayPlayer_1.CloudReplayPlayer, player => player.cloudReplay), (0, typeorm_1.OneToMany)(() => CloudReplayPlayer_1.CloudReplayPlayer, player => player.cloudReplay),
__metadata("design:type", Array) __metadata("design:type", Array)
], CloudReplay.prototype, "players", void 0); ], CloudReplay.prototype, "players", void 0);
CloudReplay = __decorate([ exports.CloudReplay = CloudReplay = __decorate([
(0, typeorm_1.Entity)({ (0, typeorm_1.Entity)({
orderBy: { orderBy: {
date: "DESC" date: "DESC"
} }
}) })
], CloudReplay); ], CloudReplay);
exports.CloudReplay = CloudReplay;
//# sourceMappingURL=CloudReplay.js.map
\ No newline at end of file
...@@ -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;
...@@ -25,6 +23,7 @@ let CloudReplayPlayer = CloudReplayPlayer_1 = class CloudReplayPlayer extends Ba ...@@ -25,6 +23,7 @@ let CloudReplayPlayer = CloudReplayPlayer_1 = class CloudReplayPlayer extends Ba
return p; return p;
} }
}; };
exports.CloudReplayPlayer = CloudReplayPlayer;
__decorate([ __decorate([
(0, typeorm_1.Index)(), (0, typeorm_1.Index)(),
(0, typeorm_1.Column)({ type: "varchar", length: 128 }), (0, typeorm_1.Column)({ type: "varchar", length: 128 }),
...@@ -34,8 +33,6 @@ __decorate([ ...@@ -34,8 +33,6 @@ __decorate([
(0, typeorm_1.ManyToOne)(() => CloudReplay_1.CloudReplay, replay => replay.players), (0, typeorm_1.ManyToOne)(() => CloudReplay_1.CloudReplay, replay => replay.players),
__metadata("design:type", CloudReplay_1.CloudReplay) __metadata("design:type", CloudReplay_1.CloudReplay)
], CloudReplayPlayer.prototype, "cloudReplay", void 0); ], CloudReplayPlayer.prototype, "cloudReplay", void 0);
CloudReplayPlayer = CloudReplayPlayer_1 = __decorate([ exports.CloudReplayPlayer = CloudReplayPlayer = CloudReplayPlayer_1 = __decorate([
(0, typeorm_1.Entity)() (0, typeorm_1.Entity)()
], CloudReplayPlayer); ], CloudReplayPlayer);
exports.CloudReplayPlayer = CloudReplayPlayer;
//# sourceMappingURL=CloudReplayPlayer.js.map
\ No newline at end of file
...@@ -12,9 +12,8 @@ Object.defineProperty(exports, "__esModule", { value: true }); ...@@ -12,9 +12,8 @@ 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;
__decorate([ __decorate([
(0, typeorm_1.CreateDateColumn)(), (0, typeorm_1.CreateDateColumn)(),
__metadata("design:type", Date) __metadata("design:type", Date)
...@@ -23,5 +22,3 @@ __decorate([ ...@@ -23,5 +22,3 @@ __decorate([
(0, typeorm_1.UpdateDateColumn)(), (0, typeorm_1.UpdateDateColumn)(),
__metadata("design:type", Date) __metadata("design:type", Date)
], CreateAndUpdateTimeBase.prototype, "updateTime", void 0); ], CreateAndUpdateTimeBase.prototype, "updateTime", void 0);
exports.CreateAndUpdateTimeBase = CreateAndUpdateTimeBase;
//# sourceMappingURL=CreateAndUpdateTimeBase.js.map
\ No newline at end of file
...@@ -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);
...@@ -55,6 +46,7 @@ let DuelLog = class DuelLog extends CreateAndUpdateTimeBase_1.CreateAndUpdateTim ...@@ -55,6 +46,7 @@ let DuelLog = class DuelLog extends CreateAndUpdateTimeBase_1.CreateAndUpdateTim
return data; return data;
} }
}; };
exports.DuelLog = DuelLog;
__decorate([ __decorate([
(0, typeorm_1.PrimaryGeneratedColumn)({ unsigned: true, type: global.PrimaryKeyType || 'bigint' }), (0, typeorm_1.PrimaryGeneratedColumn)({ unsigned: true, type: global.PrimaryKeyType || 'bigint' }),
__metadata("design:type", Number) __metadata("design:type", Number)
...@@ -94,12 +86,10 @@ __decorate([ ...@@ -94,12 +86,10 @@ __decorate([
(0, typeorm_1.OneToMany)(() => DuelLogPlayer_1.DuelLogPlayer, player => player.duelLog), (0, typeorm_1.OneToMany)(() => DuelLogPlayer_1.DuelLogPlayer, player => player.duelLog),
__metadata("design:type", Array) __metadata("design:type", Array)
], DuelLog.prototype, "players", void 0); ], DuelLog.prototype, "players", void 0);
DuelLog = __decorate([ exports.DuelLog = DuelLog = __decorate([
(0, typeorm_1.Entity)({ (0, typeorm_1.Entity)({
orderBy: { orderBy: {
id: "DESC" id: "DESC"
} }
}) })
], DuelLog); ], DuelLog);
exports.DuelLog = DuelLog;
//# sourceMappingURL=DuelLog.js.map
\ No newline at end of file
...@@ -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;
...@@ -62,6 +52,7 @@ let DuelLogPlayer = DuelLogPlayer_1 = class DuelLogPlayer extends BasePlayer_1.B ...@@ -62,6 +52,7 @@ let DuelLogPlayer = DuelLogPlayer_1 = class DuelLogPlayer extends BasePlayer_1.B
return p; return p;
} }
}; };
exports.DuelLogPlayer = DuelLogPlayer;
__decorate([ __decorate([
(0, typeorm_1.Index)(), (0, typeorm_1.Index)(),
(0, typeorm_1.Column)({ type: "varchar", length: 20 }), (0, typeorm_1.Column)({ type: "varchar", length: 20 }),
...@@ -104,8 +95,6 @@ __decorate([ ...@@ -104,8 +95,6 @@ __decorate([
(0, typeorm_1.ManyToOne)(() => DuelLog_1.DuelLog, duelLog => duelLog.players), (0, typeorm_1.ManyToOne)(() => DuelLog_1.DuelLog, duelLog => duelLog.players),
__metadata("design:type", DuelLog_1.DuelLog) __metadata("design:type", DuelLog_1.DuelLog)
], DuelLogPlayer.prototype, "duelLog", void 0); ], DuelLogPlayer.prototype, "duelLog", void 0);
DuelLogPlayer = DuelLogPlayer_1 = __decorate([ exports.DuelLogPlayer = DuelLogPlayer = DuelLogPlayer_1 = __decorate([
(0, typeorm_1.Entity)() (0, typeorm_1.Entity)()
], DuelLogPlayer); ], DuelLogPlayer);
exports.DuelLogPlayer = DuelLogPlayer;
//# sourceMappingURL=DuelLogPlayer.js.map
\ No newline at end of file
...@@ -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;
} }
...@@ -25,6 +20,7 @@ let RandomDuelBan = class RandomDuelBan extends CreateAndUpdateTimeBase_1.Create ...@@ -25,6 +20,7 @@ let RandomDuelBan = class RandomDuelBan extends CreateAndUpdateTimeBase_1.Create
return this.needTip > 0 ? true : false; return this.needTip > 0 ? true : false;
} }
}; };
exports.RandomDuelBan = RandomDuelBan;
__decorate([ __decorate([
(0, typeorm_1.PrimaryColumn)({ type: "varchar", length: 64 }), (0, typeorm_1.PrimaryColumn)({ type: "varchar", length: 64 }),
__metadata("design:type", String) __metadata("design:type", String)
...@@ -45,8 +41,6 @@ __decorate([ ...@@ -45,8 +41,6 @@ __decorate([
(0, typeorm_1.Column)({ type: "tinyint", unsigned: true }), (0, typeorm_1.Column)({ type: "tinyint", unsigned: true }),
__metadata("design:type", Number) __metadata("design:type", Number)
], RandomDuelBan.prototype, "needTip", void 0); ], RandomDuelBan.prototype, "needTip", void 0);
RandomDuelBan = __decorate([ exports.RandomDuelBan = RandomDuelBan = __decorate([
(0, typeorm_1.Entity)() (0, typeorm_1.Entity)()
], RandomDuelBan); ], RandomDuelBan);
exports.RandomDuelBan = RandomDuelBan;
//# sourceMappingURL=RandomDuelBan.js.map
\ No newline at end of file
...@@ -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];
} }
...@@ -47,6 +42,7 @@ let RandomDuelScore = class RandomDuelScore extends CreateAndUpdateTimeBase_1.Cr ...@@ -47,6 +42,7 @@ let RandomDuelScore = class RandomDuelScore extends CreateAndUpdateTimeBase_1.Cr
} }
} }
}; };
exports.RandomDuelScore = RandomDuelScore;
__decorate([ __decorate([
(0, typeorm_1.PrimaryColumn)({ type: "varchar", length: 20 }), (0, typeorm_1.PrimaryColumn)({ type: "varchar", length: 20 }),
__metadata("design:type", String) __metadata("design:type", String)
...@@ -70,8 +66,6 @@ __decorate([ ...@@ -70,8 +66,6 @@ __decorate([
(0, typeorm_1.Column)("int", { unsigned: true, default: 0 }), (0, typeorm_1.Column)("int", { unsigned: true, default: 0 }),
__metadata("design:type", Number) __metadata("design:type", Number)
], RandomDuelScore.prototype, "winCombo", void 0); ], RandomDuelScore.prototype, "winCombo", void 0);
RandomDuelScore = __decorate([ exports.RandomDuelScore = RandomDuelScore = __decorate([
(0, typeorm_1.Entity)() (0, typeorm_1.Entity)()
], RandomDuelScore); ], RandomDuelScore);
exports.RandomDuelScore = RandomDuelScore;
//# sourceMappingURL=RandomDuelScore.js.map
\ No newline at end of file
...@@ -19,17 +19,11 @@ const VipKey_1 = require("./VipKey"); ...@@ -19,17 +19,11 @@ 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;
__decorate([ __decorate([
(0, typeorm_1.PrimaryColumn)({ type: "varchar", length: 128 }), (0, typeorm_1.PrimaryColumn)({ type: "varchar", length: 128 }),
__metadata("design:type", String) __metadata("design:type", String)
...@@ -59,8 +53,6 @@ __decorate([ ...@@ -59,8 +53,6 @@ __decorate([
(0, typeorm_1.OneToMany)(() => VipKey_1.VipKey, vipKey => vipKey.usedBy), (0, typeorm_1.OneToMany)(() => VipKey_1.VipKey, vipKey => vipKey.usedBy),
__metadata("design:type", Array) __metadata("design:type", Array)
], User.prototype, "usedKeys", void 0); ], User.prototype, "usedKeys", void 0);
User = __decorate([ exports.User = User = __decorate([
(0, typeorm_1.Entity)() (0, typeorm_1.Entity)()
], User); ], User);
exports.User = User;
//# sourceMappingURL=User.js.map
\ No newline at end of file
...@@ -13,11 +13,8 @@ exports.UserDialog = void 0; ...@@ -13,11 +13,8 @@ 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;
__decorate([ __decorate([
(0, typeorm_1.PrimaryGeneratedColumn)({ unsigned: true, type: "bigint" }), (0, typeorm_1.PrimaryGeneratedColumn)({ unsigned: true, type: "bigint" }),
__metadata("design:type", Number) __metadata("design:type", Number)
...@@ -35,8 +32,6 @@ __decorate([ ...@@ -35,8 +32,6 @@ __decorate([
(0, typeorm_1.ManyToOne)(() => User_1.User, user => user.dialogues), (0, typeorm_1.ManyToOne)(() => User_1.User, user => user.dialogues),
__metadata("design:type", User_1.User) __metadata("design:type", User_1.User)
], UserDialog.prototype, "user", void 0); ], UserDialog.prototype, "user", void 0);
UserDialog = __decorate([ exports.UserDialog = UserDialog = __decorate([
(0, typeorm_1.Entity)() (0, typeorm_1.Entity)()
], UserDialog); ], UserDialog);
exports.UserDialog = UserDialog;
//# sourceMappingURL=UserDialog.js.map
\ No newline at end of file
...@@ -14,15 +14,11 @@ const typeorm_1 = require("typeorm"); ...@@ -14,15 +14,11 @@ 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 };
} }
}; };
exports.VipKey = VipKey;
__decorate([ __decorate([
(0, typeorm_1.PrimaryGeneratedColumn)({ unsigned: true, type: "bigint" }), (0, typeorm_1.PrimaryGeneratedColumn)({ unsigned: true, type: "bigint" }),
__metadata("design:type", Number) __metadata("design:type", Number)
...@@ -45,8 +41,6 @@ __decorate([ ...@@ -45,8 +41,6 @@ __decorate([
(0, typeorm_1.ManyToOne)(() => User_1.User, user => user.usedKeys), (0, typeorm_1.ManyToOne)(() => User_1.User, user => user.usedKeys),
__metadata("design:type", User_1.User) __metadata("design:type", User_1.User)
], VipKey.prototype, "usedBy", void 0); ], VipKey.prototype, "usedBy", void 0);
VipKey = __decorate([ exports.VipKey = VipKey = __decorate([
(0, typeorm_1.Entity)() (0, typeorm_1.Entity)()
], VipKey); ], VipKey);
exports.VipKey = VipKey;
//# sourceMappingURL=VipKey.js.map
\ No newline at end of file
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
"20": "SURRENDER", "20": "SURRENDER",
"21": "TIME_CONFIRM", "21": "TIME_CONFIRM",
"22": "CHAT", "22": "CHAT",
"23": "EXTERNAL_ADDRESS",
"32": "HS_TODUELIST", "32": "HS_TODUELIST",
"33": "HS_TOOBSERVER", "33": "HS_TOOBSERVER",
"34": "HS_READY", "34": "HS_READY",
......
...@@ -31,6 +31,15 @@ ...@@ -31,6 +31,15 @@
"replay_delay": true, "replay_delay": true,
"hide_name": false, "hide_name": false,
"display_watchers": false, "display_watchers": false,
"trusted_proxies": [
"127.0.0.1/8",
"::1/128"
],
"ygopro_path": "./ygopro",
"ygopro_exec_path": "./ygopro",
"expansions_path": [
"./expansions"
],
"i18n": { "i18n": {
"auto_pick": false, "auto_pick": false,
"default": "zh-cn", "default": "zh-cn",
...@@ -225,10 +234,6 @@ ...@@ -225,10 +234,6 @@
"neos": { "neos": {
"enabled": false, "enabled": false,
"port": 7977, "port": 7977,
"trusted_proxies": [
"127.0.0.1/8",
"::1/128"
],
"ip_header": "x-forwarded-for" "ip_header": "x-forwarded-for"
}, },
"chatgpt": { "chatgpt": {
......
...@@ -212,6 +212,8 @@ ...@@ -212,6 +212,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": {
...@@ -573,6 +575,8 @@ ...@@ -573,6 +575,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": {
......
...@@ -8,7 +8,8 @@ ...@@ -8,7 +8,8 @@
"HS_KICK":"CTOS_Kick", "HS_KICK":"CTOS_Kick",
"UPDATE_DECK": "deck", "UPDATE_DECK": "deck",
"CHANGE_SIDE":"", "CHANGE_SIDE":"",
"CHAT": "chat" "CHAT": "chat",
"EXTERNAL_ADDRESS": "CTOS_ExternalAddress"
}, },
"STOC":{ "STOC":{
"JOIN_GAME":"STOC_JoinGame", "JOIN_GAME":"STOC_JoinGame",
......
...@@ -42,6 +42,10 @@ ...@@ -42,6 +42,10 @@
{"name": "gameid", "type": "unsigned int"}, {"name": "gameid", "type": "unsigned int"},
{"name": "pass", "type": "unsigned short", "length": 20, "encoding": "UTF-16LE"} {"name": "pass", "type": "unsigned short", "length": 20, "encoding": "UTF-16LE"}
], ],
"CTOS_ExternalAddress": [
{"name": "real_ip", "type": "unsigned int"},
{"name": "hostname", "type": "unsigned short", "length":"256", "encoding": "UTF-16LE"}
],
"CTOS_Kick": [ "CTOS_Kick": [
{"name": "pos", "type": "unsigned char"} {"name": "pos", "type": "unsigned char"}
], ],
......
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BasePolyfiller = void 0;
class BasePolyfiller {
async polyfillGameMsg(msgTitle, buffer) {
return;
}
async polyfillResponse(msgTitle, buffer) {
return;
}
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 newBuf = Buffer.concat([
buf.slice(0, offset),
buf.slice(end)
]);
return newBuf;
}
insert(buf, offset, insertBuf) {
if (offset < 0)
offset = 0;
if (offset > buf.length)
offset = buf.length;
const newBuf = Buffer.concat([
buf.slice(0, offset),
insertBuf,
buf.slice(offset)
]);
return newBuf;
}
}
exports.BasePolyfiller = BasePolyfiller;
export class BasePolyfiller {
async polyfillGameMsg(msgTitle: string, buffer: Buffer): Promise<Buffer | undefined> {
return;
}
async polyfillResponse(msgTitle: string, buffer: Buffer): Promise<Buffer | undefined> {
return;
}
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 newBuf = Buffer.concat([
buf.slice(0, offset),
buf.slice(end)
]);
return newBuf;
}
insert(buf: Buffer, offset: number, insertBuf: Buffer): Buffer {
if (offset < 0) offset = 0;
if (offset > buf.length) offset = buf.length;
const newBuf = Buffer.concat([
buf.slice(0, offset),
insertBuf,
buf.slice(offset)
]);
return newBuf;
}
}
"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, polyfillerCls] of registry_1.polyfillRegistry.entries()) {
if (version <= pVersion) {
polyfillers.push({ version: pVersion, polyfiller: new polyfillerCls() });
}
}
polyfillers.sort((a, b) => a.version - b.version);
return polyfillers.map(p => p.polyfiller);
};
async function polyfillGameMsg(version, msgTitle, buffer) {
const polyfillers = getPolyfillers(version);
let mutated = false;
for (const polyfiller of polyfillers) {
const newBuf = await polyfiller.polyfillGameMsg(msgTitle, buffer);
if (newBuf) {
mutated = true;
buffer = newBuf;
}
}
return mutated ? buffer : undefined;
}
async function polyfillResponse(version, msgTitle, buffer) {
const polyfillers = getPolyfillers(version);
for (const polyfiller of polyfillers) {
await polyfiller.polyfillResponse(msgTitle, buffer);
}
}
import { BasePolyfiller } from "./base-polyfiller";
import { polyfillRegistry } from "./registry";
const getPolyfillers = (version: number) => {
const polyfillers: {version: number, polyfiller: BasePolyfiller}[] = [];
for (const [pVersion, polyfillerCls] of polyfillRegistry.entries()) {
if (version <= pVersion) {
polyfillers.push({ version: pVersion, polyfiller: new polyfillerCls() });
}
}
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);
let mutated = false;
for (const polyfiller of polyfillers) {
const newBuf = await polyfiller.polyfillGameMsg(msgTitle, buffer);
if (newBuf) {
mutated = true;
buffer = newBuf;
}
}
return mutated ? buffer : undefined;
}
export async function polyfillResponse(version: number, msgTitle: string, buffer: Buffer) {
const polyfillers = getPolyfillers(version);
for (const polyfiller of polyfillers) {
await polyfiller.polyfillResponse(msgTitle, buffer);
}
}
"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
return 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;
buffer = this.splice(buffer, itemOffset + 1, 1); // 删除每个 item 的 forced(第 1 字节)
}
// 最后再插入旧版所需的 forced 标志
return 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);
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 => ({
offset,
value: buffer.readUInt32LE(offset),
}));
if (!values.some(v => v.value & 0x80000000)) {
return;
}
const gcds = [targetValue];
for (const { value } of values) {
if (value & 0x80000000) {
gcds.push(value & 0x7FFFFFFF);
}
else {
const op1 = value & 0xffff;
const op2 = (value >>> 16) & 0xffff;
[op1, op2].filter(v => v > 0)
.forEach(v => gcds.push(v));
}
}
const gcdValue = (0, exports.gcd)(gcds);
buffer.writeUInt32LE(targetValue / gcdValue, 3);
for (const trans of values) {
let target = 0;
const { value } = trans;
if (value & 0x80000000) {
target = ((value & 0x7FFFFFFF) / gcdValue) & 0xffff;
}
else {
// shrink op1 and op2
const op1 = value & 0xffff;
const op2 = (value >>> 16) & 0xffff;
target = ((op1 / gcdValue) & 0xffff) | ((((op2 / gcdValue) & 0xffff) << 16) >>> 0);
}
buffer.writeUInt32LE(target, trans.offset);
}
}
return;
}
}
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
return 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;
buffer = this.splice(buffer, itemOffset + 1, 1); // 删除每个 item 的 forced(第 1 字节)
}
// 最后再插入旧版所需的 forced 标志
return 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);
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 => ({
offset,
value: buffer.readUInt32LE(offset),
}));
if (!values.some(v => v.value & 0x80000000)) {
return;
}
const gcds = [targetValue];
for(const { value } of values) {
if (value & 0x80000000) {
gcds.push(value & 0x7FFFFFFF);
} else {
const op1 = value & 0xffff;
const op2 = (value >>> 16) & 0xffff;
[op1, op2].filter(v => v > 0)
.forEach(v => gcds.push(v));
}
}
const gcdValue = gcd(gcds);
buffer.writeUInt32LE(targetValue / gcdValue, 3);
for (const trans of values) {
let target = 0;
const { value } = trans;
if (value & 0x80000000) {
target = ((value & 0x7FFFFFFF) / gcdValue) & 0xffff;
} else {
// shrink op1 and op2
const op1 = value & 0xffff;
const op2 = (value >>> 16) & 0xffff;
target = ((op1 / gcdValue) & 0xffff) | ((((op2 / gcdValue) & 0xffff) << 16) >>> 0);
}
buffer.writeUInt32LE(target, trans.offset);
}
}
return;
}
}
"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, polyfiller);
};
addPolyfiller(0x1361, _0x1361_1.Polyfiller1361);
import { BasePolyfiller } from "./base-polyfiller";
import { Polyfiller1361 } from "./polyfillers/0x1361";
export const polyfillRegistry = new Map<number, typeof BasePolyfiller>();
const addPolyfiller = (version: number, polyfiller: typeof BasePolyfiller) => {
polyfillRegistry.set(version, 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": {
...@@ -48,10 +50,11 @@ ...@@ -48,10 +50,11 @@
"devDependencies": { "devDependencies": {
"@types/bunyan": "^1.8.8", "@types/bunyan": "^1.8.8",
"@types/ip6addr": "^0.2.3", "@types/ip6addr": "^0.2.3",
"@types/node": "^17.0.19", "@types/lzma": "^2.3.0",
"@types/node": "^16.18.126",
"@types/underscore": "^1.11.4", "@types/underscore": "^1.11.4",
"@types/ws": "^8.5.3", "@types/ws": "^8.5.3",
"coffeescript": "^2.6.1", "coffeescript": "^2.7.0",
"typescript": "^4.5.5" "typescript": "^5.8.3"
} }
} }
// Generated by CoffeeScript 2.6.1 // Generated by CoffeeScript 2.7.0
(function() { (function() {
var WebSocketServer, _delete, broadcast, clients, create, init, room_data, server, settings, start, update, url; var WebSocketServer, _delete, broadcast, clients, create, init, room_data, server, settings, start, update, url;
......
{ {
"compilerOptions": { "compilerOptions": {
"module": "commonjs", "module": "commonjs",
"target": "esnext", "target": "ES2020",
"esModuleInterop": true, "esModuleInterop": true,
"resolveJsonModule": true, "resolveJsonModule": true,
"emitDecoratorMetadata": true, "emitDecoratorMetadata": true,
"experimentalDecorators": true, "experimentalDecorators": true
"sourceMap": true
}, },
"compileOnSave": true, "compileOnSave": true,
"allowJs": true, "allowJs": true,
"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"
] ]
} }
// Generated by CoffeeScript 2.6.1 // Generated by CoffeeScript 2.7.0
(function() { (function() {
/* /*
Main script of new dashboard account system. Main script of new dashboard account system.
......
This diff is collapsed.
This diff is collapsed.
// Generated by CoffeeScript 2.6.1 // Generated by CoffeeScript 2.7.0
(function() { (function() {
var Struct, YGOProMessagesHelper, _, loadJSON, translateHandler; var Struct, YGOProMessagesHelper, _, loadJSON, translateHandler;
......
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