UNPKG

yoni-mcscripts-lib

Version:

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

291 lines (290 loc) 11.3 kB
import { VanillaScoreboard, Minecraft } from "../basis.js"; import { Objective } from "./Objective.js"; import { ScoreboardEntry } from "./ScoreboardEntry.js"; /** * 可用的显示位。 */ export var DisplaySlot; (function (DisplaySlot) { /** * 在暂停菜单中显示。 */ DisplaySlot["list"] = "List"; /** * 在屏幕右侧显示。 */ DisplaySlot["sidebar"] = "Sidebar"; /** * 在玩家名字下方显示。 */ DisplaySlot["belowname"] = "BelowName"; })(DisplaySlot || (DisplaySlot = {})); /** * 记分项中每条项目的排序方式。 */ export var ObjectiveSortOrder; (function (ObjectiveSortOrder) { /** * 以正序排列项目(A-Z)。 */ ObjectiveSortOrder["ascending"] = "ascending"; /** * 以倒序排列项目(Z-A)。 */ ObjectiveSortOrder["descending"] = "descending"; })(ObjectiveSortOrder || (ObjectiveSortOrder = {})); /** * 代表了记录着记分对象在记分项上的分数的记分板。 */ export class Scoreboard { /** * 存储原始记分项对象。 * @type {Map<string, Objective>} */ static #objectives = new Map(); /** * 在记分板上添加新的记分项。 * @param {string} name - 新的记分项的名称(标识符)。 * @param {string} criteria - 记分项的准则,永远都应该是 `"dummy"`。 * @param {string} [displayName] - 为新添加的记分项指定显示名称, * 若不指定则将 `name` 作为显示名称。 * @returns {Objective} 添加的记分项的对象。 * @throws 若准则不为 `"dummy"`,抛出错误。 * @throws 若 `name` 指定的记分项已经存在,抛出错误。 */ static addObjective(name, criteria = "dummy", displayName = name) { if (!name || typeof name !== "string") throw new TypeError("Objective name not valid!"); else if (Scoreboard.tryGetObjective(name) !== false) throw new Error("Objective " + name + " existed!"); else if (criteria !== "dummy") throw new Error("Unsupported criteria: " + criteria); else if (typeof name !== "string" || name.length === 0) throw new TypeError("Objective display name not valid!"); let vanillaObjective = VanillaScoreboard.addObjective(name, displayName); let newObjective = new Objective(Scoreboard, name, criteria, displayName, { vanillaObjective }); Scoreboard.#objectives.set(name, newObjective); return newObjective; } /** * 移除记分板上的记分项。 * @param {string|Objective|Minecraft.ScoreboardObjective} nameOrObjective - 要移除的记分项,可以直接指定记分项的名称。 * @returns {boolean} 是否成功移除了记分项。 */ static removeObjective(objective) { let objectiveId; if (objective instanceof Objective || objective instanceof Minecraft.ScoreboardObjective) { objectiveId = objective.id; } else { objectiveId = objective; } if (typeof objectiveId === "string") { if (Scoreboard.#objectives.has(objectiveId)) { Scoreboard.#objectives.delete(objectiveId); } try { return VanillaScoreboard.removeObjective(objectiveId); } catch { return false; } } else { return false; //throw new TypeError("could not determine what objective to remove"); } } /** * 尝试获取名称为 `name` 的记分项对象。 * @param {string} name - 记分项的 ID。 * @returns {Objective} 名称为 `name` 的记分项,或者 `false`。 */ static tryGetObjective(name) { let objective = Scoreboard.#objectives.get(name); if (objective?.vanillaObjective.isValid()) { return objective; } else if (Scoreboard.#objectives.has(name)) { Scoreboard.#objectives.delete(name); } let vanillaObjective = null; try { vanillaObjective = VanillaScoreboard.getObjective(name); } catch { return false; } if (vanillaObjective == null) { return false; } objective = new Objective(Scoreboard, vanillaObjective.id, "dummy", vanillaObjective.displayName, { vanillaObjective }); Scoreboard.#objectives.set(name, objective); return objective; } /** * 获取记分项。 * @param {string | Minecraft.ScoreboardObjective} objectiveId - 代表一个记分项的值,可以为它的 ID 或原版记分项对象。 * @param {boolean} autoCreateDummy - 如果为 `true` ,在未找到对应记分项时,创建新的记分项并返回。 * @returns {Objective} `objectiveId` 所对应的的记分项。 * @throws 若 `objectiveId` 为记分项ID,且未设置 `autoCreateDummy` 为 `true`,抛出 ReferenceError `记分项不存在`。 * @throws 若 `objectiveId` 为原版记分项对象,且无法读取记分项信息,抛出 ReferenceError `尝试获取/读取无法使用的记分项对象`。 */ static getObjective(objectiveId, autoCreateDummy) { let objective = null; let name = null; if (objectiveId instanceof Minecraft.ScoreboardObjective) { let vanillaObjective = objectiveId; if (vanillaObjective.isValid()) { name = vanillaObjective.id; } else if (autoCreateDummy) { try { name = vanillaObjective.id; } catch { throw new ReferenceError("attempt to create a removed objective"); } } else { throw new ReferenceError("attempt to get a removed objective"); } } else { name = objectiveId; } if (name) { objective = Scoreboard.tryGetObjective(name) || null; if (!objective && autoCreateDummy) { VanillaScoreboard.addObjective(name, name); objective = Scoreboard.tryGetObjective(name); } } if (!objective) throw new ReferenceError("objective " + name + " didn't exist"); return objective; } /** * 获取记分板上的所有记分项。 * @returns {Objective[]} 包含了所有记分项对象的数组。 */ static getObjectives() { const objectives = []; for (const vanillaObjective of VanillaScoreboard.getObjectives()) { objectives.push(Scoreboard.tryGetObjective(vanillaObjective.id)); } return objectives; } /** * 获得显示位上正在显示的内容的信息。 * @param {DisplaySlot|Minecraft.DisplaySlotId} slot - 显示位。 * @returns {DisplayOptions} - 显示位上显示的内容。 */ static getDisplayAtSlot(slot) { const vanillaResult = VanillaScoreboard.getObjectiveAtDisplaySlot(slot); if (!vanillaResult) return undefined; const objective = Scoreboard.getObjective(vanillaResult.objective.id); const result = { objective }; if (vanillaResult?.sortOrder != null) { result.sortOrder = vanillaResult.sortOrder; } return result; } static #getIdOfObjective(any) { if (any instanceof Objective || any instanceof Minecraft.ScoreboardObjective) { return any.id; } else if (any && typeof any === "string") { return any; } else { throw new TypeError("unknown objective"); } } /** * 设置显示位上显示的记分项,并允许额外的设置。 * @param {DisplaySlot|Minecraft.DisplaySlotId} slot - 显示位。 * @param {DisplayOptionsDefinition} settings - 显示位的设置。 * @returns {Objective} 显示位先前显示的记分项的对象,若先前未显示任何记分项,返回 `undefined` 。 */ static setDisplayAtSlot(slot, settings) { const objective = Scoreboard.getObjective(Scoreboard.#getIdOfObjective(settings?.objective)); let settingArg = { objective: objective.vanillaObjective }; if (settings.sortOrder != null) { if (settings.sortOrder === ObjectiveSortOrder.ascending) { settingArg.sortOrder = Minecraft.ObjectiveSortOrder.Ascending; } else if (settings.sortOrder === ObjectiveSortOrder.descending) { settingArg.sortOrder = Minecraft.ObjectiveSortOrder.Descending; } else { throw new Error("unknown ObjectiveSortOrder"); } } let lastDisplayingObjective = VanillaScoreboard.setObjectiveAtDisplaySlot(slot, settingArg); if (lastDisplayingObjective == undefined) return undefined; return Scoreboard.getObjective(lastDisplayingObjective.id); } /** * 清空显示位上正显示的记分项。 * @param {DisplaySlot|Minecraft.DisplaySlotId} slot - 显示位。 * @returns {Objective} 显示位先前显示的记分项,若无,返回 `null` 。 */ static clearDisplaySlot(slot) { let rt = VanillaScoreboard.clearObjectiveAtDisplaySlot(slot); if (rt?.id != null) { return Scoreboard.getObjective(rt.id); } else { return null; } } /** * 获取记分板上记录的所有分数持有者。 * @returns {ScoreboardEntry[]} */ static getEntries() { const entries = []; for (const identify of VanillaScoreboard.getParticipants()) { const entry = ScoreboardEntry.getEntry(identify.type, identify); entries.push(entry); } return entries; } /** * 移除记分板的所有记分项。 */ static removeAllObjectives() { for (const objective of VanillaScoreboard.getObjectives()) { Scoreboard.removeObjective(objective); } } /** * 重置记分板上所有分数持有者的所有分数记录。 */ static resetAllScores() { for (const objective of VanillaScoreboard.getObjectives()) { for (const scbid of objective.getParticipants()) { objective.removeParticipant(scbid); } } } /** * 重置记分板上指定分数持有者的所有分数记录。 * @param {EntryValueType} one - 可能对应分数持有者的值。 * @throws 当分数持有者为虚拟玩家,并且世界上存在与其名字相同的玩家时,抛出 `NameConflictError`。 * @throws 未能在世界上找到分数持有者的实体对象时,抛出错误。 */ static resetScore(one) { let identify = ScoreboardEntry.getIdentity(one); for (const objective of VanillaScoreboard.getObjectives()) { if (objective.hasParticipant(identify)) { objective.removeParticipant(identify); } } } }