UNPKG

yoni-mcscripts-lib

Version:

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

249 lines (216 loc) 8.29 kB
import { Minecraft } from "../../basis.js"; import { EntityUtils } from "../../EntityUtils.js"; import { EntityWraps } from "./EntityWraps.js"; import { EntryType } from "../../scoreboard/EntryType.js"; import { ScoreboardEntry } from "../../scoreboard/ScoreboardEntry.js"; import { Dimension } from "../dimension.js"; import { DimensionLikeValue } from "../../types"; import { Location, Vector2, Vector3 } from "../Location.js"; import { copyPropertiesWithoutOverride } from "../../lib/ObjectUtils.js"; import { Command } from "../../command.js"; const { EntityTypes } = Minecraft; /** * 代表一个实体 */ class Entity { /** * 这个属性映射了一个原版中的实体对象。 * @type {Minecraft.Entity} */ readonly vanillaEntity: Minecraft.Entity; /** * @hideconstructor * @param {Minecraft.Entity} entity */ constructor(entity: Minecraft.Entity){ this.vanillaEntity = entity; Object.defineProperty(this, "vanillaEntity", { configurable: false, enumerable: false, writable: false, value: entity }); } get [Symbol.toStringTag](){ if (this instanceof Entity) return `Entity: { type: ${this.vanillaEntity.typeId} }`; return "Object (Entity)"; } get velocity() { return this.vanillaEntity.getVelocity(); } get rotation(){ return this.vanillaEntity.getRotation(); } get entityType() { return EntityTypes.get(this.typeId); } get dimension(): Dimension { return Dimension.toDimension(this.vanillaEntity.dimension); } get location(): Location { const location = Location.zero; location.setDimension(this.vanillaEntity.dimension); location.setPosition(this.vanillaEntity.location); location.setRotation(this.vanillaEntity.getRotation()); return location; } get scoreboard(): ScoreboardEntry { return ScoreboardEntry.getEntry(EntryType.ENTITY, this.vanillaEntity); } /** * 此方法可以在任何时候调用 * * 返回实体是否可用(即此对象对应的实体是否处于活动状态(即实体处于世界的已加载区域(即已经读取到内存的地图) */ isAliveEntity(){ return EntityUtils.isAliveEntity(this.vanillaEntity); } /** * 返回实体是否为活体。 */ isLivingEntity(){ return EntityUtils.isLivingEntity(this.vanillaEntity); } /** * 获取实体的当前血量。 */ getCurrentHealth(){ return EntityUtils.getCurrentHealth(this.vanillaEntity); } /** * 获取实体的血量组件。 */ getHealthComponent(){ return EntityUtils.getHealthComponent(this.vanillaEntity); } /** * 获取实体的物品栏容器。 */ getInventory(){ return EntityUtils.getInventory(this.vanillaEntity); } /** * 获取实体的最大血量。 */ getMaxHealth(){ return EntityUtils.getMaxHealth(this.vanillaEntity); } /** * 检测实体是否为某一族。 * @abc * @param {string} family */ hasFamily(family: string){ return EntityUtils.hasAnyFamily(this.vanillaEntity, family); } /** * 检测实体是否有指定的多个族中的一个。 * @param {...string} families * @returns {boolean} */ hasAnyFamily(...families: string[]){ return EntityUtils.hasAnyFamily(this.vanillaEntity, ...families); } /** * 请求以此实体的上下文执行命令。 * @param {string} cmd * @returns {Promise<Minecraft.CommandResult>} */ fetchCommand(cmd: string){ return Command.fetchExecute(this.vanillaEntity, cmd); } /** * @param {string} message */ say(message: string){ let command = "say " + message; return Command.fetchExecute(this.vanillaEntity, command); } /** * @param {number} v */ setCurrentHealth(health: number){ return EntityUtils.setCurrentHealth(this.vanillaEntity, health); } /** * @beta * Retrieves or sets an entity that is used as the target of * AI-related behaviors, like attacking. * @returns 目标不存在时返回 `undefined`。 * @throws This property can throw when used. */ get target(): Entity { return (EntityUtils.from(this.vanillaEntity.target) ?? undefined) as unknown as Entity; } addEffect(effectType: string | Minecraft.EffectType, duration: number, amplifier: number, showParticle: boolean): void; addEffect(effectType: string | Minecraft.EffectType, duration: number, options?: Minecraft.EntityEffectOptions): void; addEffect(effectType: string | Minecraft.EffectType, duration: number, amplifier?: Minecraft.EntityEffectOptions | number, showParticles?: boolean): void { let option = amplifier as Minecraft.EntityEffectOptions; if (isFinite(amplifier as number)){ option = { amplifier: amplifier as number, showParticles: showParticles as boolean } } if (option){ this.vanillaEntity.addEffect(effectType, duration, option); } else { this.vanillaEntity.addEffect(effectType, duration); } } teleport(location: Vector3, options?: Minecraft.TeleportOptions): void; teleport(coords: Vector3, dimension: DimensionLikeValue, rotationX: number, rotationY: number, keepVelocity?: boolean): void; teleport(location: Location, keepVelocity?: boolean): void; teleport(...params: any[]){ this.#executeTeleport(this.vanillaEntity.teleport, params); } tryTeleport(location: Vector3, options?: Minecraft.TeleportOptions): boolean; tryTeleport(coords: Vector3, dimension: DimensionLikeValue, rotationX: number, rotationY: number, keepVelocity?: boolean): boolean; tryTeleport(location: Location, keepVelocity?: boolean): boolean; tryTeleport(...params: any[]){ return this.#executeTeleport(this.vanillaEntity.tryTeleport, params) as boolean; } #executeTeleport(teleportFunc: (...args: any[]) => any, params: any[]): any { let coords: Vector3; //@ts-ignore let options: Minecraft.TeleportOptions = {}; if (params[0] instanceof Location){ const location = params[0]; coords = location.getVanillaLocation(); } else { coords = params[0] as Vector3; } if (params.length === 2){ if (params[1] === true || params[1] === false) options.keepVelocity = params[1]; else options = params[1] as Minecraft.TeleportOptions; } else if (params.length === 1 && (params[0] instanceof Location)){ const location = params[0] as Location; options.dimension = location.dimension.vanillaDimension; const { rx: x, ry: y } = location; const rotation: Vector2 = { x, y }; options.rotation = rotation; } else if (params.length > 1){ options.dimension = Dimension.toDimension(params[1] as DimensionLikeValue).vanillaDimension; const rotation: Vector2 = { x: params[2] as number, y: params[3] as number }; options.rotation = rotation; if (params[4] === true || params[4] === false) options.keepVelocity = params[4]; } return teleportFunc.call(this.vanillaEntity, coords, options); } } copyPropertiesWithoutOverride(Entity.prototype, Minecraft.Entity.prototype, "vanillaEntity", ["getRotation", "getVelocity", "addEffect"]); EntityWraps.registerWrap(Entity, Minecraft.Entity); type RemovedKeys = "getRotation" | "getVelocity" type OverridedKeys = "target" | "tryTeleport" | "teleport" | "addEffect" | "dimension" type BaseVanillaEntityClass = Omit< Minecraft.Entity, RemovedKeys | OverridedKeys >; interface Entity extends BaseVanillaEntityClass { } export { Entity, Entity as YoniEntity };