Commit d9c71d11 authored by nanahira's avatar nanahira

fix polyfill shrinking

parent 820e48f8
Pipeline #38042 passed with stages
in 11 minutes and 51 seconds
......@@ -17,7 +17,7 @@ class Handler {
}
async handle(buffer, info, datas, params) {
if (this.synchronous) {
return !!(await this.handler(buffer, info, datas, params));
return await this.handler(buffer, info, datas, params);
}
else {
const newBuffer = Buffer.from(buffer);
......@@ -183,7 +183,7 @@ class YGOProMessagesHelper {
let messageLength = 0;
let bufferProto = 0;
let datas = [];
const limit = preconnect ? 2 : this.singleHandleLimit;
const limit = preconnect ? 9 : this.singleHandleLimit;
for (let l = 0; l < limit; ++l) {
if (messageLength === 0) {
if (messageBuffer.length >= 2) {
......@@ -224,6 +224,7 @@ class YGOProMessagesHelper {
}
let buffer = messageBuffer.slice(3, 2 + messageLength);
//console.log(l, direction, proto, cancel);
let shrinkCount = 0;
for (let priority = 0; priority < 4; ++priority) {
if (cancel) {
break;
......@@ -239,19 +240,31 @@ class YGOProMessagesHelper {
for (let handler of handlerCollection.get(bufferProto)) {
cancel = await handler.handle(buffer, info, datas, params);
if (cancel) {
if (cancel === '_cancel') {
return {
datas: [],
feedback
};
if (typeof cancel === "string") {
if (cancel === '_cancel') {
return {
datas: [],
feedback
};
}
else if (cancel.startsWith('_shrink_')) {
shrinkCount += parseInt(cancel.slice(8));
cancel = false;
}
}
break;
}
}
}
}
if (!cancel) {
datas.push(messageBuffer.slice(0, 2 + messageLength));
if (!cancel && shrinkCount <= messageLength) {
if (shrinkCount > 0) {
// rewrite first 2 bytes of length
const oldLength = messageBuffer.readUInt16LE(0);
const newLength = oldLength - shrinkCount;
messageBuffer.writeUInt16LE(newLength, 0);
}
datas.push(messageBuffer.slice(0, 2 + messageLength - shrinkCount));
}
messageBuffer = messageBuffer.slice(2 + messageLength);
messageLength = 0;
......
......@@ -16,7 +16,7 @@ class Handler {
}
async handle(buffer: Buffer, info: any, datas: Buffer[], params: any): Promise<boolean | string> {
if (this.synchronous) {
return !!(await this.handler(buffer, info, datas, params));
return await this.handler(buffer, info, datas, params);
} else {
const newBuffer = Buffer.from(buffer);
const newDatas = datas.map(b => Buffer.from(b));
......@@ -237,7 +237,7 @@ export class YGOProMessagesHelper {
let messageLength = 0;
let bufferProto = 0;
let datas: Buffer[] = [];
const limit = preconnect ? 2 : this.singleHandleLimit;
const limit = preconnect ? 9 : this.singleHandleLimit;
for (let l = 0; l < limit; ++l) {
if (messageLength === 0) {
if (messageBuffer.length >= 2) {
......@@ -274,6 +274,7 @@ export class YGOProMessagesHelper {
}
let buffer = messageBuffer.slice(3, 2 + messageLength);
//console.log(l, direction, proto, cancel);
let shrinkCount = 0;
for (let priority = 0; priority < 4; ++priority) {
if (cancel) {
break;
......@@ -289,10 +290,15 @@ export class YGOProMessagesHelper {
for (let handler of handlerCollection.get(bufferProto)) {
cancel = await handler.handle(buffer, info, datas, params);
if (cancel) {
if (cancel === '_cancel') {
return {
datas: [],
feedback
if (typeof cancel === "string") {
if (cancel === '_cancel') {
return {
datas: [],
feedback
}
} else if (cancel.startsWith('_shrink_')) {
shrinkCount += parseInt(cancel.slice(8));
cancel = false;
}
}
break;
......@@ -300,8 +306,14 @@ export class YGOProMessagesHelper {
}
}
}
if (!cancel) {
datas.push(messageBuffer.slice(0, 2 + messageLength));
if (!cancel && shrinkCount <= messageLength) {
if (shrinkCount > 0) {
// rewrite first 2 bytes of length
const oldLength = messageBuffer.readUInt16LE(0);
const newLength = oldLength - shrinkCount;
messageBuffer.writeUInt16LE(newLength, 0);
}
datas.push(messageBuffer.slice(0, 2 + messageLength - shrinkCount));
}
messageBuffer = messageBuffer.slice(2 + messageLength);
messageLength = 0;
......
......@@ -2,12 +2,11 @@
Object.defineProperty(exports, "__esModule", { value: true });
exports.BasePolyfiller = void 0;
class BasePolyfiller {
async polyfillGameMsg(msgTitle, buffer) {
return false;
}
async polyfillResponse(msgTitle, buffer) {
return false;
constructor() {
this.shrinkCount = 0;
}
async polyfillGameMsg(msgTitle, buffer) { }
async polyfillResponse(msgTitle, buffer) { }
splice(buf, offset, deleteCount = 1) {
if (offset < 0 || offset >= buf.length)
return Buffer.alloc(0);
......@@ -20,6 +19,7 @@ class BasePolyfiller {
buf.copy(buf, offset, end, buf.length);
}
buf.fill(0, buf.length - deleteCount);
this.shrinkCount += deleteCount;
return deleted;
}
insert(buf, offset, insertBuf) {
......@@ -27,6 +27,7 @@ class BasePolyfiller {
const insertLength = Math.min(insertBuf.length, availableSpace);
buf.copy(buf, offset + insertLength, offset, buf.length - insertLength);
insertBuf.copy(buf, offset, 0, insertLength);
this.shrinkCount -= insertLength;
return buf;
}
}
......
export class BasePolyfiller {
async polyfillGameMsg(msgTitle: string, buffer: Buffer) {
return false;
}
shrinkCount = 0;
async polyfillResponse(msgTitle: string, buffer: Buffer) {
return false;
}
async polyfillGameMsg(msgTitle: string, buffer: Buffer) {}
async polyfillResponse(msgTitle: string, buffer: Buffer) {}
splice(buf: Buffer, offset: number, deleteCount = 1): Buffer {
if (offset < 0 || offset >= buf.length) return Buffer.alloc(0);
......@@ -22,6 +20,8 @@ export class BasePolyfiller {
}
buf.fill(0, buf.length - deleteCount);
this.shrinkCount += deleteCount;
return deleted;
}
......@@ -33,6 +33,8 @@ export class BasePolyfiller {
buf.copy(buf, offset + insertLength, offset, buf.length - insertLength);
insertBuf.copy(buf, offset, 0, insertLength);
this.shrinkCount -= insertLength;
return buf;
}
......
......@@ -5,9 +5,9 @@ exports.polyfillResponse = polyfillResponse;
const registry_1 = require("./registry");
const getPolyfillers = (version) => {
const polyfillers = [];
for (const [pVersion, instance] of registry_1.polyfillRegistry.entries()) {
for (const [pVersion, polyfillerCls] of registry_1.polyfillRegistry.entries()) {
if (version <= pVersion) {
polyfillers.push({ version: pVersion, polyfiller: instance });
polyfillers.push({ version: pVersion, polyfiller: new polyfillerCls() });
}
}
polyfillers.sort((a, b) => a.version - b.version);
......@@ -15,19 +15,21 @@ const getPolyfillers = (version) => {
};
async function polyfillGameMsg(version, msgTitle, buffer) {
const polyfillers = getPolyfillers(version);
let shrinkCount = 0;
for (const polyfiller of polyfillers) {
if (await polyfiller.polyfillGameMsg(msgTitle, buffer)) {
return true;
await polyfiller.polyfillGameMsg(msgTitle, buffer);
if (polyfiller.shrinkCount > 0) {
if (polyfiller.shrinkCount === 0x3f3f3f3f) {
return 0x3f3f3f3f; // special case for cancel message
}
shrinkCount += polyfiller.shrinkCount;
}
}
return false;
return shrinkCount;
}
async function polyfillResponse(version, msgTitle, buffer) {
const polyfillers = getPolyfillers(version);
for (const polyfiller of polyfillers) {
if (await polyfiller.polyfillResponse(msgTitle, buffer)) {
return true;
}
await polyfiller.polyfillResponse(msgTitle, buffer);
}
return false;
}
......@@ -3,9 +3,9 @@ import { polyfillRegistry } from "./registry";
const getPolyfillers = (version: number) => {
const polyfillers: {version: number, polyfiller: BasePolyfiller}[] = [];
for (const [pVersion, instance] of polyfillRegistry.entries()) {
for (const [pVersion, polyfillerCls] of polyfillRegistry.entries()) {
if (version <= pVersion) {
polyfillers.push({version: pVersion, polyfiller: instance});
polyfillers.push({ version: pVersion, polyfiller: new polyfillerCls() });
}
}
polyfillers.sort((a, b) => a.version - b.version);
......@@ -15,20 +15,22 @@ const getPolyfillers = (version: number) => {
export async function polyfillGameMsg(version: number, msgTitle: string, buffer: Buffer) {
const polyfillers = getPolyfillers(version);
let shrinkCount = 0;
for (const polyfiller of polyfillers) {
if (await polyfiller.polyfillGameMsg(msgTitle, buffer)) {
return true;
await polyfiller.polyfillGameMsg(msgTitle, buffer);
if (polyfiller.shrinkCount > 0) {
if (polyfiller.shrinkCount === 0x3f3f3f3f) {
return 0x3f3f3f3f; // special case for cancel message
}
shrinkCount += polyfiller.shrinkCount;
}
}
return false;
return shrinkCount;
}
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;
}
await polyfiller.polyfillResponse(msgTitle, buffer);
}
return false;
}
......@@ -84,7 +84,7 @@ class Polyfiller1361 extends base_polyfiller_1.BasePolyfiller {
value: buffer.readUInt32LE(offset),
}));
if (!values.some(v => v.value & 0x80000000)) {
return false;
return;
}
const gcds = [targetValue];
for (const { value } of values) {
......@@ -115,7 +115,7 @@ class Polyfiller1361 extends base_polyfiller_1.BasePolyfiller {
buffer.writeUInt32LE(target, trans.offset);
}
}
return false;
return;
}
}
exports.Polyfiller1361 = Polyfiller1361;
......@@ -88,7 +88,7 @@ export class Polyfiller1361 extends BasePolyfiller {
value: buffer.readUInt32LE(offset),
}));
if (!values.some(v => v.value & 0x80000000)) {
return false;
return;
}
const gcds = [targetValue];
for(const { value } of values) {
......@@ -117,6 +117,6 @@ export class Polyfiller1361 extends BasePolyfiller {
buffer.writeUInt32LE(target, trans.offset);
}
}
return false;
return;
}
}
......@@ -4,6 +4,6 @@ exports.polyfillRegistry = void 0;
const _0x1361_1 = require("./polyfillers/0x1361");
exports.polyfillRegistry = new Map();
const addPolyfiller = (version, polyfiller) => {
exports.polyfillRegistry.set(version, new 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, BasePolyfiller>();
export const polyfillRegistry = new Map<number, typeof BasePolyfiller>();
const addPolyfiller = (version: number, polyfiller: typeof BasePolyfiller) => {
polyfillRegistry.set(version, new polyfiller());
polyfillRegistry.set(version, polyfiller);
}
addPolyfiller(0x1361, Polyfiller1361);
......@@ -2233,8 +2233,8 @@ netRequestHandler = (client) ->
preconnect = false
if settings.modules.reconnect.enabled and client.pre_reconnecting_to_room
ctos_filter = ["UPDATE_DECK"]
if client.name == null
ctos_filter = ["JOIN_GAME", "PLAYER_INFO"]
else if client.name == null
ctos_filter = ["EXTERNAL_ADDRESS", "JOIN_GAME", "PLAYER_INFO"]
preconnect = true
handle_data = await ygopro.helper.handleBuffer(ctos_buffer, "CTOS", ctos_filter, {
client: client,
......@@ -2823,8 +2823,12 @@ ygopro.stoc_follow 'GAME_MSG', true, (buffer, info, client, server, datas)->
return unless room and !client.reconnecting
msg = buffer.readInt8(0)
msg_name = ygopro.constants.MSG[msg]
if await msg_polyfill.polyfillGameMsg(client.actual_version, msg_name, buffer)
shrink_count = await msg_polyfill.polyfillGameMsg(client.actual_version, msg_name, buffer)
if shrink_count == 0x3f3f3f3f
return true
record_last_game_msg = () ->
client.last_game_msg = Buffer.from(buffer.slice(0, buffer.length - shrink_count))
client.last_game_msg_title = msg_name
#console.log client.pos, "MSG", msg_name
if msg_name == 'RETRY' and room.recovering
room.finish_recover(true)
......@@ -2850,12 +2854,10 @@ ygopro.stoc_follow 'GAME_MSG', true, (buffer, info, client, server, datas)->
ygopro.stoc_send(client, 'GAME_MSG', client.last_game_msg)
return true
else
client.last_game_msg = buffer
client.last_game_msg_title = msg_name
record_last_game_msg()
# log.info(client.name, client.last_game_msg_title)
else if msg_name != 'RETRY'
client.last_game_msg = buffer
client.last_game_msg_title = msg_name
record_last_game_msg()
# log.info(client.name, client.last_game_msg_title)
if (msg >= 10 and msg < 30) or msg == 132 or (msg >= 140 and msg <= 144) #SELECT和ANNOUNCE开头的消息
......@@ -3121,7 +3123,10 @@ ygopro.stoc_follow 'GAME_MSG', true, (buffer, info, client, server, datas)->
room.recover_buffers[client.pos].push(buffer)
return true
await return false
if shrink_count > 0
return "_shrink_#{shrink_count}"
else
return false
#房间管理
ygopro.ctos_follow 'HS_TOOBSERVER', true, (buffer, info, client, server, datas)->
......@@ -3846,8 +3851,7 @@ ygopro.ctos_follow 'RESPONSE', true, (buffer, info, client, server, datas)->
room=ROOM_all[client.rid]
if room and (room.random_type or room.arena)
room.refreshLastActiveTime()
if await msg_polyfill.polyfillResponse(client.actual_version, client.last_game_msg_title, buffer)
return true
await msg_polyfill.polyfillResponse(client.actual_version, client.last_game_msg_title, buffer)
return false
ygopro.stoc_follow 'TIME_LIMIT', true, (buffer, info, client, server, datas)->
......
......@@ -2968,9 +2968,8 @@
preconnect = false;
if (settings.modules.reconnect.enabled && client.pre_reconnecting_to_room) {
ctos_filter = ["UPDATE_DECK"];
}
if (client.name === null) {
ctos_filter = ["JOIN_GAME", "PLAYER_INFO"];
} else if (client.name === null) {
ctos_filter = ["EXTERNAL_ADDRESS", "JOIN_GAME", "PLAYER_INFO"];
preconnect = true;
}
handle_data = (await ygopro.helper.handleBuffer(ctos_buffer, "CTOS", ctos_filter, {
......@@ -3691,16 +3690,21 @@
};
ygopro.stoc_follow('GAME_MSG', true, async function(buffer, info, client, server, datas) {
var act_pos, card, chain, check, count, cpos, deck_found, dialogText, found, hint_type, i, id, j, l, len, len1, len2, len3, limbo_found, loc, m, max_loop, msg, msg_name, n, o, oppo_pos, phase, player, playertype, pos, ppos, r_player, reason, ref, ref1, ref2, ref3, ref4, room, trigger_location, val, victoryWordPlayerList, win_pos;
var act_pos, card, chain, check, count, cpos, deck_found, dialogText, found, hint_type, i, id, j, l, len, len1, len2, len3, limbo_found, loc, m, max_loop, msg, msg_name, n, o, oppo_pos, phase, player, playertype, pos, ppos, r_player, reason, record_last_game_msg, ref, ref1, ref2, ref3, ref4, room, shrink_count, trigger_location, val, victoryWordPlayerList, win_pos;
room = ROOM_all[client.rid];
if (!(room && !client.reconnecting)) {
return;
}
msg = buffer.readInt8(0);
msg_name = ygopro.constants.MSG[msg];
if ((await msg_polyfill.polyfillGameMsg(client.actual_version, msg_name, buffer))) {
shrink_count = (await msg_polyfill.polyfillGameMsg(client.actual_version, msg_name, buffer));
if (shrink_count === 0x3f3f3f3f) {
return true;
}
record_last_game_msg = function() {
client.last_game_msg = Buffer.from(buffer.slice(0, buffer.length - shrink_count));
return client.last_game_msg_title = msg_name;
};
//console.log client.pos, "MSG", msg_name
if (msg_name === 'RETRY' && room.recovering) {
room.finish_recover(true);
......@@ -3732,13 +3736,11 @@
return true;
}
} else {
client.last_game_msg = buffer;
client.last_game_msg_title = msg_name;
record_last_game_msg();
}
// log.info(client.name, client.last_game_msg_title)
} else if (msg_name !== 'RETRY') {
client.last_game_msg = buffer;
client.last_game_msg_title = msg_name;
record_last_game_msg();
}
// log.info(client.name, client.last_game_msg_title)
if ((msg >= 10 && msg < 30) || msg === 132 || (msg >= 140 && msg <= 144)) { //SELECT和ANNOUNCE开头的消息
......@@ -4104,7 +4106,11 @@
}
return true;
}
return false;
if (shrink_count > 0) {
return `_shrink_${shrink_count}`;
} else {
return false;
}
});
//房间管理
......@@ -5157,9 +5163,7 @@
if (room && (room.random_type || room.arena)) {
room.refreshLastActiveTime();
}
if ((await msg_polyfill.polyfillResponse(client.actual_version, client.last_game_msg_title, buffer))) {
return true;
}
await msg_polyfill.polyfillResponse(client.actual_version, client.last_game_msg_title, buffer);
return false;
});
......
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