import { on } from 'events' import minecraft_data from 'minecraft-data' import UUID from 'uuid-1345' import { aiter } from 'iterator-helper' import { VERSION } from '../settings.js' import { Context } from '../events.js' import Entities from '../../data/entities.json' assert { type: 'json' } import { to_metadata } from '../entity_metadata.js' const { entitiesByName } = minecraft_data(VERSION) export const color_by_category = { mob: 'white', archiMob: 'gold', boss: 'red', npc: 'green', garde: 'blue', } function despawn_signal({ events, entity_id }) { const controller = new AbortController() aiter(on(events, Context.MOB_DESPAWNED)) .filter(([id]) => id === entity_id) .take(0) // TODO: should be 1, seems to be a iterator-helper bug .toArray() .then(() => controller.abort()) return controller.signal } export function spawn_mob(client, { mob, position, events }) { const { entity_id, type, level } = mob const { category, minecraft_entity, displayName } = Entities[type] client.write('spawn_entity_living', { entityId: entity_id, entityUUID: UUID.v4(), type: entitiesByName[minecraft_entity].id, x: position.x, y: position.y, z: position.z, yaw: 0, pitch: 0, headPitch: 0, velocityX: 0, velocityY: 0, velocityZ: 0, }) client.write('entity_metadata', { entityId: entity_id, metadata: to_metadata('entity', { custom_name: JSON.stringify({ text: displayName, color: color_by_category[category], extra: level && [{ text: ` [Lvl ${level}]`, color: 'dark_red' }], }), is_custom_name_visible: true, }), }) events.emit(Context.MOB_SPAWNED, { mob, signal: despawn_signal({ events, entity_id: mob.entity_id }), }) } export function despawn_mobs(client, { ids, events }) { client.write('entity_destroy', { entityIds: ids }) for (const entity_id of ids) events.emit(Context.MOB_DESPAWNED, entity_id) } export default { /** @type {import('../context.js').Observer} */ observe({ client, events }) { events.on(Context.CHUNK_LOADED_WITH_MOBS, ({ mobs }) => { for (const { mob, position } of mobs) spawn_mob(client, { mob, position, events }) }) events.on(Context.CHUNK_UNLOADED_WITH_MOBS, ({ mobs }) => { despawn_mobs(client, { ids: mobs.map(({ mob }) => mob.entity_id), events, }) }) }, }