MatchMaster/tools/test-rainbow-old-block.cjs
WIN-GKKD951VVMJ\Administrator 74cf4413b5 增加一版彩虹机制
2026-09-20 17:14:40 +08:00

115 lines
5.9 KiB
JavaScript

// TYPESCRIPT_PATH may point to the TypeScript bundled with Cocos Creator.
const test = require('node:test');
const assert = require('node:assert/strict');
const fs = require('node:fs');
const path = require('node:path');
const vm = require('node:vm');
const ts = require(process.env.TYPESCRIPT_PATH || 'typescript');
const blockFile = 'assets/Script/Block.ts';
const collideFile = 'assets/Script/lq_collide_system/lq_collide.ts';
function method(file, name, globals = {}) {
const source = ts.createSourceFile(file, fs.readFileSync(path.join(__dirname, '..', file), 'utf8'), ts.ScriptTarget.Latest, true);
const cls = source.statements.find(node => ts.isClassDeclaration(node));
const member = cls.members.find(node => node.name && node.name.getText(source) === name);
assert.ok(member, name);
const code = ts.transpileModule('class Subject {' + member.getText(source) + '}\nSubject;',
{ compilerOptions: { target: ts.ScriptTarget.ES2017 } }).outputText;
return vm.runInNewContext(code, { console, ...globals }).prototype[name];
}
const refresh = method(blockFile, 'refreshOldRainbowVisual');
const sameColorTile = method(blockFile, 'canPassSameColorSimpleBlock');
const BlockType = { 普通块: 0, 叠加块上: 10, 粘合块: 9, 变色块: 20, 单色地块: 22, 问号块: 16 };
function makeBlock(oldRainbow = true, color = 5, type = 2) {
const sprite = {};
const children = {
icon: { active: true, getComponent: () => sprite },
rainbow_old: { active: false },
key: { active: true },
flowerSend: { active: true },
};
return { oldRainbow, color, type, block_Info: { block: 5, type, color, flowerSend: 4 },
node: { getChildByName: name => children[name], children: Object.values(children) },
refreshOldRainbowVisual: refresh, children, sprite };
}
test('old rainbow visuals preserve real color, type and attachments through color refresh and thaw', () => {
const globals = { cc: { Sprite: {} }, BlockType, MapConroler: { _instance: {} },
BlockAssetManager: { instance: { getFrame: name => name } }, blockTexturePath: (color, shape) => `${color}color${shape}` };
const initColor = method(blockFile, 'initColor', globals);
const resetFreeze = method(blockFile, 'resetFreeze', globals);
const b = makeBlock();
initColor.call(b, false);
assert.equal(b.color, 5);
assert.equal(b.type, 2);
assert.equal(b.sprite.spriteFrame, '5color5');
assert.equal(b.children.icon.active, false);
assert.equal(b.children.rainbow_old.active, true);
assert.equal(b.children.key.active, true);
assert.equal(b.children.flowerSend.active, true);
b.type = b.block_Info.type = 4;
b.children.rainbow_old.active = false;
b.children.icon.active = true;
resetFreeze.call(b);
assert.equal(b.type, 0);
assert.equal(b.color, 5);
assert.equal(b.oldRainbow, true);
assert.equal(b.children.rainbow_old.active, true);
assert.equal(b.children.icon.active, false);
const ordinary = makeBlock(false);
refresh.call(ordinary);
assert.equal(ordinary.children.icon.active, true);
});
test('initializing a reused block removes old rainbow capability and overlay', () => {
const b = makeBlock();
let destroyed = false;
b.children.rainbow_old.removeFromParent = () => { delete b.children.rainbow_old; };
b.children.rainbow_old.destroy = () => { destroyed = true; };
b.node.on = () => {};
b.node._touchListener = { setSwallowTouches() {} };
Object.assign(b, { jsonDeepClone: v => JSON.parse(JSON.stringify(v)), initColor() {}, initType() {}, initBlocks() {}, flowerType: 0 });
const init = method(blockFile, 'init', { cc: { Node: { EventType: {} } }, BlockType,
MapConroler: { _instance: { mapInfo: [] } }, setTimeout() {} });
init.call(b, { type: 0, color: 7, block: 5, id: 9 });
assert.equal(destroyed, true);
assert.equal(b.oldRainbow, false);
assert.equal(b.color, 7);
assert.equal(b.type, 0);
assert.equal(b.children.icon.active, true);
});
test('opening conversion blocks input before reading a touch event', () => {
const touchStart = method(blockFile, 'touchStart', { MapConroler: { _instance: { oldRainbowPreparing: true } } });
touchStart.call({}, { getLocation() { throw Error('opening conversion accepted a touch'); } });
});
test('old rainbow passes both kinds of monochrome tile, but not walls, vines or composite restrictions', () => {
const map = { riseFallBlock: [] };
const disable = method(collideFile, 'disableCollider', { MapConroler: { _instance: map } });
let id = 0;
const make = (color, type = 0, oldRainbow = false, info = {}) => {
const block = { color, type, oldRainbow, block_Info: info, canPassSameColorSimpleBlock: sameColorTile };
return { block, node: { name: 'left', parent: { uuid: ++id, getComponent: () => block } } };
};
for (let color = 1; color <= 10; color++) {
const rainbow = make(5, 2, true), tile = make(color, 22);
assert.equal(disable.call(rainbow, tile), true);
assert.equal(disable.call(tile, rainbow), true);
assert.equal(disable.call(rainbow, make(color)), false);
assert.equal(disable.call(make(5, 0, true, { floorMove: true }), tile), false);
const covered = make(5, 0, true); covered.block.flowerType = 2;
assert.equal(disable.call(covered, tile), false);
const ordinary = make(color === 5 ? 6 : 5);
assert.equal(disable.call(ordinary, tile), false);
}
const rainbow = make(5, 0, true);
const fixed = { node: { name: 'rise', parent: { uuid: ++id, getComponent: () => null } } };
map.riseFallBlock = [fixed.node.parent];
assert.equal(disable.call(rainbow, fixed), true);
map.riseFallBlock = [];
assert.equal(disable.call(rainbow, fixed), false, 'unregistered rise includes vines and poles');
fixed.node.name = 'wall';
assert.equal(disable.call(rainbow, fixed), false);
assert.equal(rainbow.block.color, 5);
});