Merge pull request #741 from nofficalfs/PR-pref-ArrayContents
Add new ArrayContent format.
This commit is contained in:
commit
8796a30851
53
game/game.js
53
game/game.js
|
@ -11,36 +11,41 @@ new Promise(resolve => {
|
|||
}
|
||||
}).then(() => {
|
||||
const userAgent = navigator.userAgent.toLowerCase();
|
||||
|
||||
const exit = () => {
|
||||
const ios = userAgent.includes('iphone') || userAgent.includes('ipad') || userAgent.includes('macintosh');
|
||||
//electron
|
||||
if (typeof window.process == 'object' && typeof window.require == 'function') {
|
||||
const versions = window.process.versions;
|
||||
// @ts-ignore
|
||||
const electronVersion = parseFloat(versions.electron);
|
||||
let remote;
|
||||
if (electronVersion >= 14) {
|
||||
// @ts-ignore
|
||||
remote = require('@electron/remote');
|
||||
} else {
|
||||
// @ts-ignore
|
||||
remote = require('electron').remote;
|
||||
}
|
||||
const thisWindow = remote.getCurrentWindow();
|
||||
thisWindow.destroy();
|
||||
window.process.exit();
|
||||
}
|
||||
//android-cordova环境
|
||||
//ios-cordova环境或ios浏览器环境
|
||||
//非ios的网页版
|
||||
else if (!ios) {
|
||||
window.close();
|
||||
}
|
||||
};
|
||||
|
||||
if (!localStorage.getItem('gplv3_noname_alerted')) {
|
||||
if (confirm('①无名杀是一款基于GPLv3协议的开源软件!\n你可以在遵守GPLv3协议的基础上任意使用,修改并转发《无名杀》,以及所有基于《无名杀》开发的拓展。\n点击“确定”即代表您认可并接受GPLv3协议↓️\nhttps://www.gnu.org/licenses/gpl-3.0.html\n②无名杀官方发布地址仅有GitHub仓库!\n其他所有的所谓“无名杀”社群(包括但不限于绝大多数“官方”QQ群、QQ频道等)均为玩家自发组织,与无名杀官方无关!')) {
|
||||
// @ts-ignore
|
||||
localStorage.setItem('gplv3_noname_alerted', true);
|
||||
}
|
||||
else {
|
||||
const ios = userAgent.includes('iphone') || userAgent.includes('ipad') || userAgent.includes('macintosh');
|
||||
//electron
|
||||
if (typeof window.process == 'object' && typeof window.require == 'function') {
|
||||
const versions = window.process.versions;
|
||||
// @ts-ignore
|
||||
const electronVersion = parseFloat(versions.electron);
|
||||
let remote;
|
||||
if (electronVersion >= 14) {
|
||||
// @ts-ignore
|
||||
remote = require('@electron/remote');
|
||||
} else {
|
||||
// @ts-ignore
|
||||
remote = require('electron').remote;
|
||||
}
|
||||
const thisWindow = remote.getCurrentWindow();
|
||||
thisWindow.destroy();
|
||||
window.process.exit();
|
||||
}
|
||||
//android-cordova环境
|
||||
//ios-cordova环境或ios浏览器环境
|
||||
//非ios的网页版
|
||||
else if (!ios) {
|
||||
window.close();
|
||||
}
|
||||
exit();
|
||||
}
|
||||
}
|
||||
window['b' + 'ann' + 'e' + 'dE' + 'x' + 'ten' + 's' + 'i' + 'o' + 'ns'] = ['\u4fa0\u4e49', '\u5168\u6559\u7a0b'];
|
||||
|
|
|
@ -16,7 +16,7 @@ import { Library as lib } from '../library/index.js';
|
|||
import { status as _status } from '../status/index.js';
|
||||
import { UI as ui } from '../ui/index.js';
|
||||
import { GNC as gnc } from '../gnc/index.js';
|
||||
import { userAgent, Uninstantable, GeneratorFunction, AsyncFunction } from "../util/index.js";
|
||||
import { userAgent, Uninstantable, GeneratorFunction, AsyncFunction, delay } from "../util/index.js";
|
||||
|
||||
export class Game extends Uninstantable {
|
||||
static online = false;
|
||||
|
@ -5833,8 +5833,53 @@ export class Game extends Uninstantable {
|
|||
static runContent(belongAsyncEvent) {
|
||||
return new Promise(resolve => {
|
||||
let event = (belongAsyncEvent && belongAsyncEvent.parent == _status.event) ? belongAsyncEvent : _status.event;
|
||||
let { step, source, player, target, targets, card, cards, skill, forced, num, _trigger: trigger, _result: result } = event;
|
||||
if (event.content instanceof GeneratorFunction) {
|
||||
let { step, source, player, target, targets, card, cards, skill, forced, num, _trigger: trigger, _result: result, _storeEvent } = event;
|
||||
// 数组形式
|
||||
if ("contents" in event && Array.isArray(event.contents)) {
|
||||
/*
|
||||
event.contents[step](event, trigger, player, _storeEvent).then((evt) => {
|
||||
if (evt) event._storeEvent = evt;
|
||||
if (game.executingAsyncEventMap.has(event.toEvent())) {
|
||||
game.executingAsyncEventMap.set(_status.event.toEvent(), game.executingAsyncEventMap.get(_status.event.toEvent()).then(() => {
|
||||
if (event.step >= event.contents.length - 1) event.finish();
|
||||
resolve();
|
||||
}));
|
||||
} else {
|
||||
if (event.step >= event.contents.length - 1) event.finish();
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
*/
|
||||
// 解决不了问题...就把问题统一
|
||||
const run = async (event) => {
|
||||
if (typeof event.step !== "number") event.step = 0;
|
||||
while (event.step < event.contents.length && !event.finished) {
|
||||
const evt = await event.contents[event.step](event, event._trigger, event.player, event._tmpStoreEvent);
|
||||
if (evt) event._tmpStoreEvent = evt;
|
||||
|
||||
if (game.executingAsyncEventMap.has(event.toEvent())) {
|
||||
await game.executingAsyncEventMap.get(_status.event.toEvent());
|
||||
await game.executingAsyncEventMap.get(event.toEvent());
|
||||
}
|
||||
|
||||
++event.step;
|
||||
}
|
||||
--event.step;
|
||||
};
|
||||
|
||||
run(event).then(() => {
|
||||
if (game.executingAsyncEventMap.has(event.toEvent())) {
|
||||
game.executingAsyncEventMap.set(_status.event.toEvent(), game.executingAsyncEventMap.get(_status.event.toEvent()).then(() => {
|
||||
event.finish();
|
||||
resolve();
|
||||
}));
|
||||
} else {
|
||||
event.finish();
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
}
|
||||
else if (event.content instanceof GeneratorFunction) {
|
||||
if (!event.debugging) {
|
||||
if (event.generatorContent) event.generatorContent.return();
|
||||
event.generatorContent = event.content(event, step, source, player, target, targets,
|
||||
|
@ -5964,9 +6009,7 @@ export class Game extends Uninstantable {
|
|||
time = time * lib.config.duration + time2;
|
||||
if (lib.config.speed == 'vvfast') time /= 3;
|
||||
//_status.timeout=setTimeout(game.resume,time);
|
||||
return new Promise(resolve => {
|
||||
setTimeout(resolve, time);
|
||||
});
|
||||
return delay(time);
|
||||
}
|
||||
/**
|
||||
* 在async content中对game.delayx的代替使用方法
|
||||
|
@ -6544,13 +6587,13 @@ export class Game extends Uninstantable {
|
|||
* @param { import('../library/index.js').Player } [player2]
|
||||
*/
|
||||
static swapPlayer(player, player2) {
|
||||
let players = game.players.concat(game.dead)
|
||||
if (player2) {
|
||||
if (player == game.me) game.swapPlayer(player2);
|
||||
else if (player2 == game.me) game.swapPlayer(player);
|
||||
}
|
||||
else {
|
||||
if (player == game.me) return;
|
||||
let players = game.players.concat(game.dead);
|
||||
for (let i = 0; i < players.length; i++) {
|
||||
players[i].style.transition = 'all 0s';
|
||||
}
|
||||
|
@ -6603,11 +6646,11 @@ export class Game extends Uninstantable {
|
|||
if (lib.config.mode == 'identity') {
|
||||
game.me.setIdentity(game.me.identity);
|
||||
}
|
||||
setTimeout(() => {
|
||||
setTimeout((players) => {
|
||||
for (let i = 0; i < players.length; i++) {
|
||||
players[i].style.transition = '';
|
||||
}
|
||||
}, 100);
|
||||
}, 100, players);
|
||||
}
|
||||
/**
|
||||
* @param { import('../library/index.js').Player } player
|
||||
|
|
|
@ -5,7 +5,7 @@ import { Game as game } from '../game/index.js';
|
|||
import { status as _status } from '../status/index.js';
|
||||
import { UI as ui } from '../ui/index.js';
|
||||
|
||||
export function cordovaReady() {
|
||||
export async function cordovaReady() {
|
||||
lib.path = (await import('../library/path.js')).default;
|
||||
if (lib.device == 'android') {
|
||||
document.addEventListener("pause", function () {
|
||||
|
|
|
@ -83,11 +83,12 @@ export async function boot() {
|
|||
}
|
||||
|
||||
// 在dom加载完后执行相应的操作
|
||||
if (document.readyState !== 'complete') {
|
||||
window.onload = onWindowReady;
|
||||
} else {
|
||||
onWindowReady.call(window);
|
||||
}
|
||||
const waitDomLoad = new Promise((resolve) => {
|
||||
if (document.readyState !== 'complete') {
|
||||
window.onload = resolve;
|
||||
} else resolve(void 0)
|
||||
}).then(onWindowReady.bind(window));
|
||||
|
||||
|
||||
// 闭源客户端检测并提醒
|
||||
if (lib.assetURL.includes('com.widget.noname.qingyao') || lib.assetURL.includes('online.nonamekill.android')) {
|
||||
|
@ -555,11 +556,8 @@ export async function boot() {
|
|||
delete _status.importing;
|
||||
}
|
||||
|
||||
if (_status.windowLoaded) {
|
||||
delete _status.windowLoaded;
|
||||
lib.init.onload();
|
||||
}
|
||||
else _status.packLoaded = true;
|
||||
await waitDomLoad;
|
||||
lib.init.onload();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -744,16 +742,21 @@ async function loadCss() {
|
|||
});
|
||||
}
|
||||
|
||||
function onWindowReady() {
|
||||
async function onWindowReady() {
|
||||
if (Reflect.has(lib, 'device')) {
|
||||
var script = document.createElement('script');
|
||||
script.src = 'cordova.js';
|
||||
document.body.appendChild(script);
|
||||
// @ts-ignore
|
||||
const { promise, resolve } = Promise.withResolvers();
|
||||
document.addEventListener('deviceready', async () => {
|
||||
const { cordovaReady } = await import('./cordova.js');
|
||||
cordovaReady();
|
||||
await cordovaReady();
|
||||
resolve()
|
||||
});
|
||||
await promise;
|
||||
}
|
||||
/*
|
||||
if (_status.packLoaded) {
|
||||
delete _status.packLoaded;
|
||||
lib.init.onload();
|
||||
|
@ -761,6 +764,7 @@ function onWindowReady() {
|
|||
else {
|
||||
_status.windowLoaded = true;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
function setBackground() {
|
||||
|
|
|
@ -9,8 +9,16 @@ export function nodeReady() {
|
|||
lib.node = {
|
||||
fs: require('fs'),
|
||||
path: require("path"),
|
||||
debug: function () {
|
||||
require('electron').remote.getCurrentWindow().toggleDevTools();
|
||||
debug() {
|
||||
let remote;
|
||||
if (electronVersion >= 14) {
|
||||
// @ts-ignore
|
||||
remote = require('@electron/remote');
|
||||
} else {
|
||||
// @ts-ignore
|
||||
remote = require('electron').remote;
|
||||
}
|
||||
remote.getCurrentWindow().toggleDevTools();
|
||||
}
|
||||
};
|
||||
lib.path = lib.node.path;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,289 @@
|
|||
import { AI as ai } from '../../ai/index.js';
|
||||
import { Get as get } from '../../get/index.js';
|
||||
import { Game as game } from '../../game/index.js';
|
||||
import { Library as lib } from "../index.js";
|
||||
import { status as _status } from '../../status/index.js';
|
||||
import { UI as ui } from '../../ui/index.js';
|
||||
import { GNC as gnc } from '../../gnc/index.js';
|
||||
|
||||
export default {
|
||||
phase: [
|
||||
async (event, _trigger, player) => {
|
||||
// 初始化阶段列表
|
||||
if (!event.phaseList) {
|
||||
event.phaseList = ['phaseZhunbei', 'phaseJudge', 'phaseDraw', 'phaseUse', 'phaseDiscard', 'phaseJieshu'];
|
||||
}
|
||||
|
||||
if (typeof event.num != 'number') {
|
||||
event.num = 0;
|
||||
}
|
||||
|
||||
// 规则集中的“回合开始后①”,更新游戏轮数,触发“一轮游戏开始时”
|
||||
let isRound = false;
|
||||
if (!event.skill) {
|
||||
isRound = _status.roundSkipped;
|
||||
if (_status.isRoundFilter) {
|
||||
isRound = _status.isRoundFilter(event, player);
|
||||
}
|
||||
else if (_status.seatNumSettled) {
|
||||
var seatNum = player.getSeatNum();
|
||||
if (seatNum != 0) {
|
||||
// @ts-ignore
|
||||
if (get.itemtype(_status.lastPhasedPlayer) != 'player' || seatNum < _status.lastPhasedPlayer.getSeatNum()) isRound = true;
|
||||
_status.lastPhasedPlayer = player;
|
||||
}
|
||||
}
|
||||
else if (player == _status.roundStart) isRound = true;
|
||||
if (isRound) {
|
||||
delete _status.roundSkipped;
|
||||
game.roundNumber++;
|
||||
event._roundStart = true;
|
||||
game.updateRoundNumber();
|
||||
for (var i = 0; i < game.players.length; i++) {
|
||||
// @ts-ignore
|
||||
if (game.players[i].isOut() && game.players[i].outCount > 0) {
|
||||
// @ts-ignore
|
||||
game.players[i].outCount--;
|
||||
if (game.players[i].outCount == 0 && !game.players[i].outSkills) {
|
||||
game.players[i].in();
|
||||
}
|
||||
}
|
||||
}
|
||||
event.trigger('roundStart');
|
||||
}
|
||||
}
|
||||
|
||||
_status.globalHistory.push({
|
||||
cardMove: [],
|
||||
custom: [],
|
||||
useCard: [],
|
||||
changeHp: [],
|
||||
everything: [],
|
||||
});
|
||||
|
||||
const players = game.players.slice(0).concat(game.dead);
|
||||
for (const current of players) {
|
||||
// @ts-ignore
|
||||
current.actionHistory.push({ useCard: [], respond: [], skipped: [], lose: [], gain: [], sourceDamage: [], damage: [], custom: [], useSkill: [] });
|
||||
// @ts-ignore
|
||||
current.stat.push({ card: {}, skill: {} });
|
||||
if (isRound) {
|
||||
current.getHistory().isRound = true;
|
||||
current.getStat().isRound = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (isRound) {
|
||||
// @ts-ignore
|
||||
game.getGlobalHistory().isRound = true;
|
||||
}
|
||||
},
|
||||
async (event) => {
|
||||
//规则集中的“回合开始后②(1v1武将登场专用)”
|
||||
event.trigger('phaseBeforeStart');
|
||||
},
|
||||
async (event) => {
|
||||
//规则集中的“回合开始后③(处理“游戏开始时”的时机)”
|
||||
event.trigger('phaseBefore');
|
||||
},
|
||||
async (event) => {
|
||||
//规则集中的“回合开始后④(卑弥呼〖纵傀〗的时机)”
|
||||
event.trigger('phaseBeforeEnd');
|
||||
},
|
||||
async (event, _trigger, player) => {
|
||||
//规则集中的“回合开始后⑤”,进行翻面检测
|
||||
if (player.isTurnedOver() && !event._noTurnOver) {
|
||||
event.cancel();
|
||||
player.turnOver();
|
||||
player.phaseSkipped = true;
|
||||
}
|
||||
else {
|
||||
player.phaseSkipped = false;
|
||||
player.getHistory().isMe = true;
|
||||
player.getStat().isMe = true;
|
||||
}
|
||||
},
|
||||
async (event, _trigger, player) => {
|
||||
// 规则集中的“回合开始后⑥”,更新“当前回合角色”
|
||||
// @ts-ignore
|
||||
while (ui.dialogs.length) {
|
||||
// @ts-ignore
|
||||
ui.dialogs[0].close();
|
||||
}
|
||||
|
||||
++game.phaseNumber;
|
||||
++player.phaseNumber;
|
||||
|
||||
// @ts-ignore
|
||||
game.broadcastAll((player, num, popup) => {
|
||||
if (lib.config.glow_phase) {
|
||||
player.classList.add('glow_phase');
|
||||
}
|
||||
player.phaseNumber = num;
|
||||
_status.currentPhase = player;
|
||||
if (popup && lib.config.show_phase_prompt) player.popup('回合开始', null, false);
|
||||
}, player, player.phaseNumber, !player.noPhaseDelay);
|
||||
|
||||
_status.currentPhase = player;
|
||||
_status.discarded = [];
|
||||
|
||||
game.syncState();
|
||||
// @ts-ignore
|
||||
game.addVideo('phaseChange', player);
|
||||
|
||||
if (game.phaseNumber == 1) {
|
||||
delete player._start_cards;
|
||||
if (lib.configOL.observe) {
|
||||
lib.configOL.observeReady = true;
|
||||
game.send('server', 'config', lib.configOL);
|
||||
}
|
||||
}
|
||||
|
||||
game.log();
|
||||
game.log(player, '的回合开始');
|
||||
player._noVibrate = true;
|
||||
|
||||
if (get.config('identity_mode') != 'zhong' && get.config('identity_mode') != 'purple' && !_status.connectMode) {
|
||||
let num;
|
||||
switch (get.config('auto_identity')) {
|
||||
case 'one': num = 1; break;
|
||||
case 'two': num = 2; break;
|
||||
case 'three': num = 3; break;
|
||||
case 'always': num = -1; break;
|
||||
default: num = 0; break;
|
||||
}
|
||||
// @ts-ignore
|
||||
if (num && !_status.identityShown && game.phaseNumber > game.players.length * num && game.showIdentity) {
|
||||
if (!_status.video) player.popup('显示身份');
|
||||
_status.identityShown = true;
|
||||
// @ts-ignore
|
||||
game.showIdentity(false);
|
||||
}
|
||||
}
|
||||
player.ai.tempIgnore = [];
|
||||
// @ts-ignore
|
||||
if (ui.land && ui.land.player == player) {
|
||||
// @ts-ignore
|
||||
game.addVideo('destroyLand');
|
||||
// @ts-ignore
|
||||
ui.land.destroy();
|
||||
}
|
||||
},
|
||||
async (event) => {
|
||||
//规则集中的“回合开始后⑦”,国战武将明置武将牌
|
||||
event.trigger('phaseBeginStart');
|
||||
},
|
||||
async (event) => {
|
||||
//规则集中的“回合开始后⑨”,进行当先,化身等操作
|
||||
//没有⑧ 因为⑧用不到
|
||||
event.trigger('phaseBegin');
|
||||
},
|
||||
async (event, _trigger, player) => {
|
||||
if (event.num < event.phaseList.length) {
|
||||
//规则集中没有的新时机 可以用来插入额外阶段啥的
|
||||
if (player.isIn()) event.trigger('phaseChange');
|
||||
}
|
||||
else event.goto(11);
|
||||
},
|
||||
async (event, _trigger, player) => {
|
||||
if (player.isIn() && event.num < event.phaseList.length) {
|
||||
const phase = event.phaseList[event.num].split('|');
|
||||
event.currentPhase = phase[0];
|
||||
if (event.currentPhase == 'phaseDraw' || event.currentPhase == 'phaseDiscard') {
|
||||
if (!player.noPhaseDelay) {
|
||||
// @ts-ignore
|
||||
if (player == game.me) {
|
||||
await game.asyncDelay();
|
||||
// game.delay();
|
||||
}
|
||||
else {
|
||||
await game.asyncDelayx();
|
||||
// game.delayx();
|
||||
}
|
||||
}
|
||||
}
|
||||
const next = player[event.currentPhase]();
|
||||
next.phaseIndex = event.num;
|
||||
if (phase.length > 1) {
|
||||
next._extraPhaseReason = phase[1];
|
||||
}
|
||||
return await next;
|
||||
}
|
||||
},
|
||||
async (event, _trigger, player) => {
|
||||
if (event.currentPhase === 'phaseUse') {
|
||||
// @ts-ignore
|
||||
game.broadcastAll(() => {
|
||||
// @ts-ignore
|
||||
if (ui.tempnowuxie) {
|
||||
// @ts-ignore
|
||||
ui.tempnowuxie.close();
|
||||
// @ts-ignore
|
||||
delete ui.tempnowuxie;
|
||||
}
|
||||
});
|
||||
delete player._noSkill;
|
||||
}
|
||||
++event.num;
|
||||
},
|
||||
async (event) => {
|
||||
if (event.num < event.phaseList.length) {
|
||||
event.goto(8);
|
||||
}
|
||||
else if (!event._phaseEndTriggered) {
|
||||
event._phaseEndTriggered = true;
|
||||
event.trigger('phaseEnd');
|
||||
event.redo();
|
||||
}
|
||||
},
|
||||
async (event) => {
|
||||
event.trigger('phaseAfter');
|
||||
},
|
||||
async ({ player }) => {
|
||||
//删除当前回合角色 此时处于“不属于任何角色的回合”的阶段
|
||||
// @ts-ignore
|
||||
game.broadcastAll((player) => {
|
||||
player.classList.remove('glow_phase');
|
||||
delete _status.currentPhase;
|
||||
}, player);
|
||||
}
|
||||
],
|
||||
phaseDraw: [
|
||||
async (event, _trigger, player) => {
|
||||
game.log(player, '进入了摸牌阶段');
|
||||
event.trigger("phaseDrawBegin1");
|
||||
},
|
||||
async (event) => {
|
||||
event.trigger("phaseDrawBegin2");
|
||||
},
|
||||
async (event, _trigger, player) => {
|
||||
// @ts-ignore
|
||||
if (game.modPhaseDraw) {
|
||||
// @ts-ignore
|
||||
return game.modPhaseDraw(player, event.num);
|
||||
}
|
||||
else {
|
||||
if (event.num > 0) {
|
||||
let num = event.num;
|
||||
if (event.attachDraw) {
|
||||
for (let i = 0; i < event.attachDraw.length; i++) {
|
||||
// @ts-ignore
|
||||
ui.cardPile.insertBefore(event.attachDraw[i], ui.cardPile.firstChild);
|
||||
}
|
||||
num += event.attachDraw.length;
|
||||
}
|
||||
const next = player.draw(num);
|
||||
if (event.attachDraw) {
|
||||
next.minnum = event.attachDraw.length;
|
||||
}
|
||||
return next;
|
||||
}
|
||||
}
|
||||
},
|
||||
async (event, _trigger, _player, { result }) => {
|
||||
if (Array.isArray(result)) {
|
||||
event.cards = result;
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
File diff suppressed because it is too large
Load Diff
17981
noname/library/index.js
17981
noname/library/index.js
File diff suppressed because it is too large
Load Diff
|
@ -11,3 +11,12 @@ export class Uninstantable {
|
|||
throw new TypeError(`${new.target.name} is not a constructor`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {number} ms
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
export function delay(ms) {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue