UNPKG

yoni-mcscripts-lib

Version:

为 Minecraft Script API 中的部分接口创建了 wrapper,并提供简单的事件管理器和任务管理器,另附有一些便于代码编写的一些小工具。

172 lines (171 loc) 7.27 kB
import { Minecraft } from "../basis.js"; import { EntryType } from "./EntryType.js"; import { EntityUtils } from "../EntityUtils.js"; import { UnknownEntryError } from "./ScoreboardError.js"; /** * 代表一个可以在记分板上持有分数的分数持有者。 * * 对于运行时的实体与玩家,这个对象是唯一的。 * * 对于虚拟玩家,不能保证对应的对象的唯一性。 */ export class ScoreboardEntry { static #entityMap = new WeakMap; static #playerMap = new WeakMap; static #scbidMap = new WeakMap; /** * 寻找指定对象在记分板上使用的分数持有者对象。 * @param {EntryValueType} one - 可能为分数持有者的值。 * @returns {ScoreboardEntry} 与 `one` 对应的分数持有者对象。 * @throws 若未能根据值得到可能的分数持有者对象,抛出 `UnknownEntryError`。 */ static guessEntry(one) { if (one instanceof ScoreboardEntry) return one; else if (one instanceof Minecraft.ScoreboardIdentity) return ScoreboardEntry.getEntry(one.type, one); else if (EntityUtils.isEntity(one)) if (EntityUtils.entityIsPlayer(one)) return ScoreboardEntry.getEntry(EntryType.PLAYER, EntityUtils.getMinecraftEntity(one)); else return ScoreboardEntry.getEntry(EntryType.ENTITY, EntityUtils.getMinecraftEntity(one)); else if (typeof one === "string") return ScoreboardEntry.getEntry(EntryType.FAKE_PLAYER, one); throw new UnknownEntryError(); } /** * 获取对象可以作为分数持有者对象的值。 * @param {EntryValueType} one - 可能为分数持有者的值。 * @returns {Minecraft.ScoreboardIdentity | string | Minecraft.Entity} 与 `one` 对应的分数持有者对象。 * @throws 若未能根据值得到可能的分数持有者对象,抛出 `UnknownEntryError`。 */ static getIdentity(one) { if (typeof one === "string" || one instanceof Minecraft.ScoreboardIdentity) return one; else if (one instanceof ScoreboardEntry) return one.getIdentity(); else if (EntityUtils.isEntity(one)) return EntityUtils.getMinecraftEntity(one); throw new UnknownEntryError(); } static getEntry(type, identify) { let entry = null; if (type === EntryType.ENTITY) { entry = ScoreboardEntry.#entityMap.get(identify); } else if (type === EntryType.PLAYER) { entry = ScoreboardEntry.#playerMap.get(identify); } if (!entry && (identify instanceof Minecraft.ScoreboardIdentity) && ScoreboardEntry.#scbidMap.has(identify)) { entry = ScoreboardEntry.#scbidMap.get(identify); } if (entry) return entry; entry = new ScoreboardEntry(type, identify); if (identify instanceof Minecraft.ScoreboardIdentity) { ScoreboardEntry.#scbidMap.set(identify, entry); } else if (type === EntryType.FAKE_PLAYER) { // nothing to do } else if (type === EntryType.ENTITY) { ScoreboardEntry.#entityMap.set(identify, entry); } else if (type === EntryType.PLAYER) { ScoreboardEntry.#playerMap.set(identify, entry); } else { throw new TypeError("unknown entry type"); } return entry; } #entity; #name; #vanillaScbid; #id; constructor(type, identify) { if (identify instanceof Minecraft.ScoreboardIdentity) { this.#vanillaScbid = identify; type = identify.type; Object.defineProperty(this, "type", { configurable: false, writable: false, value: type }); } else if (type === EntryType.FAKE_PLAYER && typeof identify === "string") { this.#name = identify; Object.defineProperty(this, "type", { configurable: false, writable: false, value: type }); } else if (type === EntryType.ENTITY) { this.#entity = EntityUtils.getMinecraftEntity(identify); Object.defineProperty(this, "type", { configurable: false, writable: false, value: type }); } else if (type === EntryType.PLAYER) { this.#entity = EntityUtils.getMinecraftEntity(identify); if (!EntityUtils.isPlayer(this.#entity)) { throw new TypeError("not a player"); } Object.defineProperty(this, "type", { configurable: false, writable: false, value: type }); } else { throw new TypeError("not an identify"); } } //@ts-ignore "type"; get id() { if (this.vanillaScoreboardIdentity) return this.vanillaScoreboardIdentity.id; throw new ReferenceError("could not find the id of the entry"); } get displayName() { if (this.type === EntryType.FAKE_PLAYER) return this.#name; else if (this.vanillaScoreboardIdentity !== undefined) return this.vanillaScoreboardIdentity.displayName; else if (this.type === EntryType.ENTITY) return this.#entity.id; else if (this.type === EntryType.PLAYER) return this.#entity.name; else throw new TypeError("unknown displayName"); } getEntity() { if (this.type !== EntryType.FAKE_PLAYER) { if (this.#vanillaScbid && (!this.#entity || !EntityUtils.isAliveEntity(this.#entity))) { this.#entity = this.#vanillaScbid.getEntity(); } if (this.#entity) return EntityUtils.getAliveEntity(this.#entity); } throw new ReferenceError("this ScoreboardIdentity didn't relate to an alive entity"); } getVanillaEntity() { if (this.type !== EntryType.FAKE_PLAYER) { if (this.#vanillaScbid && (!this.#entity || !EntityUtils.isAliveEntity(this.#entity))) { this.#entity = this.#vanillaScbid.getEntity(); } if (this.#entity) return EntityUtils.getAliveVanillaEntity(this.#entity); } throw new ReferenceError("this ScoreboardIdentity didn't relate to an alive entity"); } getIdentity() { if (this.type === EntryType.FAKE_PLAYER) return this.#name; else if (this.vanillaScoreboardIdentity !== undefined) return this.vanillaScoreboardIdentity; else if (this.type === EntryType.ENTITY || this.type === EntryType.PLAYER) return this.getVanillaEntity(); else throw new ReferenceError("failed to get an available identity"); } get vanillaScoreboardIdentity() { if (this.#entity && (this.type === EntryType.ENTITY || this.type === EntryType.PLAYER) && (this.#vanillaScbid ?? undefined) !== (this.#entity?.scoreboardIdentity ?? undefined)) { this.#vanillaScbid = this.#entity?.scoreboardIdentity ?? undefined; if (this.#vanillaScbid) { ScoreboardEntry.#scbidMap.set(this.#vanillaScbid, this); } } return this.#vanillaScbid; } }