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