yoni-mcscripts-lib
Version:
为 Minecraft Script API 中的部分接口创建了 wrapper,并提供简单的事件管理器和任务管理器,另附有一些便于代码编写的一些小工具。
291 lines (290 loc) • 11.3 kB
JavaScript
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);
}
}
}
}