@occultus/entity-api
Version:
Star Tenon entity api and utils
165 lines (161 loc) • 4.9 kB
text/typescript
import { Entity, ItemStack, Vector3, world } from "@minecraft/server";
import { BlockEntityData } from "../interface/BlockEntityData.js";
import { ItemStackData } from "./ItemStackData.js";
/**
* 方块实体
*/
export class BlockEntity {
constructor() {}
/**
* 从一个方块实体获取实体数据
* @param entity 要获取数据的方块实体
* @returns
*/
static getData(entity: Entity) {
const block = entity.dimension.getBlock(entity.location);
if (!block) return;
const data: BlockEntityData = {
dimension: entity.dimension,
entity: entity,
location: entity.location,
block: block,
scoreboardObjective: world.scoreboard.getObjective(
`${entity.typeId}:${entity.id}`
),
};
return data;
}
/**
* 存储物品到方块实体数据中
*
* @param items 要存储的物品,可以是单个物品或物品数组
* @param data 用于存储物品的方块实体数据
*/
static storeItem(items: ItemStack[] | ItemStack, data: BlockEntityData) {
if (Array.isArray(items)) {
this.storeWithContainer(data, items);
return;
}
if (data.entity.hasComponent("inventory")) {
this.storeWithContainer(data, items);
return;
}
this.storeWithDynamicProperty(data, items);
}
/**
* 摧毁方块实体数据,这会将其中存储的物品掉落在世界中
* @param data
*/
static destory(data: BlockEntityData) {
const item = this.getStoredItem(data);
if (!item) {
this.remove(data);
return;
}
if (Array.isArray(item)) {
item.forEach((i) => {
data.dimension.spawnItem(i, data.entity.location);
});
} else {
data.dimension.spawnItem(item, data.entity.location);
}
this.remove(data);
}
/**
* 直接移除方块实体数据
* @param data
*/
static remove(data: BlockEntityData) {
if (data.scoreboardObjective)
world.scoreboard.removeObjective(data.scoreboardObjective);
data.entity?.remove();
}
/**
* 清除方块实体所存储的物品
* @param data
*/
static clearStoredItem(data: BlockEntityData) {
if (data.entity.hasComponent("inventory")) {
const container = data.entity.getComponent("inventory")?.container;
if (!container) return;
container.clearAll();
return;
} else {
data.entity.setDynamicProperty("starock:storedItem");
}
}
/**
* 获取方块实体存储的物品
* @param data
* @returns 方块实体存储的物品
*/
static getStoredItem(
data: BlockEntityData
): ItemStack | ItemStack[] | undefined {
if (data.entity.hasComponent("inventory")) {
const container = data.entity.getComponent("inventory")?.container;
if (!container) return;
const items: ItemStack[] = [];
for (let i = 0; i < container.size; i++) {
const item = container.getItem(i);
if (item) {
items.push(item);
}
}
return items;
}
const rawData = data.entity.getDynamicProperty("starock:storedItem");
if (typeof rawData !== "string") return;
const itemData = JSON.parse(rawData);
const item = new ItemStack(itemData.typeId, itemData.amount);
if (!item.hasComponent("durability")) return item;
if (!itemData.damage) return item;
item.getComponent("durability")!.damage = itemData.damage;
return item;
}
static storeWithContainer(
data: BlockEntityData,
item: ItemStack | ItemStack[]
) {
const container = data.entity.getComponent("inventory")?.container;
if (!container) return;
if (Array.isArray(item)) {
item.forEach((item) => {
container.addItem(item);
});
} else {
container.addItem(item);
}
}
static storeWithDynamicProperty(data: BlockEntityData, item: ItemStack) {
const itemData: ItemStackData = {
typeId: item.typeId,
amount: item.amount,
damage: item.getComponent("durability")?.damage,
};
data.entity.setDynamicProperty(
"starock:storedItem",
JSON.stringify(itemData)
);
console.log(JSON.stringify(itemData));
}
/**
* 将方块实体同步到其应该在的位置
* @param data
*/
synchronize(data: BlockEntityData) {
const { location, entity } = data;
const correctLocation = entity.getDynamicProperty(
"starock:blockEntityLocation"
) as Vector3;
if (equals(location, correctLocation)) return;
entity.teleport(correctLocation);
}
}
function equals(location: Vector3, correctLocation: Vector3): boolean {
return (
location.x === correctLocation.x &&
location.y === correctLocation.y &&
location.z === correctLocation.z
);
}