yoni-mcscripts-lib
Version:
为 Minecraft Script API 中的部分接口创建了 wrapper,并提供简单的事件管理器和任务管理器,另附有一些便于代码编写的一些小工具。
176 lines (163 loc) • 8.23 kB
text/typescript
import { Minecraft } from "../basis.js";
import { EntryType, EntryValueType } from "./EntryType.js";
import { EntityUtils } from "../EntityUtils.js";
import { UnknownEntryError } from "./ScoreboardError.js";
import type { YoniEntity, EntityValue } from "../types";
/**
* 代表一个可以在记分板上持有分数的分数持有者。
*
* 对于运行时的实体与玩家,这个对象是唯一的。
*
* 对于虚拟玩家,不能保证对应的对象的唯一性。
*/
export class ScoreboardEntry {
static #entityMap = new WeakMap<Minecraft.Entity, ScoreboardEntry>;
static #playerMap = new WeakMap<Minecraft.Player, ScoreboardEntry>;
static #scbidMap = new WeakMap<Minecraft.ScoreboardIdentity, ScoreboardEntry>;
/**
* 寻找指定对象在记分板上使用的分数持有者对象。
* @param {EntryValueType} one - 可能为分数持有者的值。
* @returns {ScoreboardEntry} 与 `one` 对应的分数持有者对象。
* @throws 若未能根据值得到可能的分数持有者对象,抛出 `UnknownEntryError`。
*/
static guessEntry(one: EntryValueType): ScoreboardEntry {
if (one instanceof ScoreboardEntry)
return one;
else if (one instanceof Minecraft.ScoreboardIdentity)
return ScoreboardEntry.getEntry(one.type as unknown as EntryType, 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: EntryValueType): Minecraft.ScoreboardIdentity | string | Minecraft.Entity {
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: EntryType, identify: Minecraft.ScoreboardIdentity | string | Minecraft.Entity){
let entry: ScoreboardEntry | null | undefined = null;
if (type === EntryType.ENTITY){
entry = ScoreboardEntry.#entityMap.get(identify as Minecraft.Entity);
} else if (type === EntryType.PLAYER){
entry = ScoreboardEntry.#playerMap.get(identify as Minecraft.Player);
}
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 as Minecraft.ScoreboardIdentity, entry);
} else if (type === EntryType.FAKE_PLAYER){
// nothing to do
} else if (type === EntryType.ENTITY){
ScoreboardEntry.#entityMap.set(identify as Minecraft.Entity, entry);
} else if (type === EntryType.PLAYER){
ScoreboardEntry.#playerMap.set(identify as Minecraft.Player, entry);
} else {
throw new TypeError("unknown entry type");
}
return entry;
}
#entity?: Minecraft.Entity;
#name?: string;
#vanillaScbid?: Minecraft.ScoreboardIdentity;
#id?: number;
private constructor(type: EntryType, identify: Minecraft.ScoreboardIdentity | string | Minecraft.Entity){
if (identify instanceof Minecraft.ScoreboardIdentity){
this.#vanillaScbid = identify;
type = identify.type as unknown as EntryType;
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 as EntityValue);
Object.defineProperty(this, "type", { configurable: false, writable: false, value: type });
} else if (type === EntryType.PLAYER){
this.#entity = EntityUtils.getMinecraftEntity(identify as EntityValue);
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
readonly "type": EntryType;
get id(): number {
if (this.vanillaScoreboardIdentity)
return this.vanillaScoreboardIdentity.id;
throw new ReferenceError("could not find the id of the entry");
}
get displayName(): string {
if (this.type === EntryType.FAKE_PLAYER)
return this.#name as string;
else if (this.vanillaScoreboardIdentity !== undefined)
return this.vanillaScoreboardIdentity.displayName;
else if (this.type === EntryType.ENTITY)
return (this.#entity as Minecraft.Entity).id;
else if (this.type === EntryType.PLAYER)
return (this.#entity as Minecraft.Player).name;
else
throw new TypeError("unknown displayName");
}
getEntity(): YoniEntity {
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(): Minecraft.Entity {
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(): Minecraft.ScoreboardIdentity | string | Minecraft.Entity {
if (this.type === EntryType.FAKE_PLAYER)
return this.#name as string;
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(): Minecraft.ScoreboardIdentity | undefined {
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;
}
}