import { world, Player, ItemStack, GameMode, Entity } from "@minecraft/server"; import { axeConvertBlockIds, hoeConvertBlockIds, shovelConvertBlockIds, } from "lazuli-game-data"; import { getEquipmentItem, consumeDurability, setEquipmentItem, } from "lazuli-utils"; /** * Dispose the item when entity use it. * @param durability The durability to reduce. * @param item The item to be used. * @param entity The entity that used the item. * @param event */ function disposeItem( durability: number, item: ItemStack, entity: Entity, event?: (holder: Entity, item: ItemStack) => void ): void { const newItem = consumeDurability(item, durability, entity); setEquipmentItem(entity, newItem); if (!newItem && event) { event(entity, item); } } /** * Define a tool tag. * @category Need Registry */ export class ToolTag { constructor( /** * The tool tag. */ public tag: string, /** * Additional options of the tool. */ public options?: ToolOptions ) {} /** * Automatically consume durability for the tools. */ listeningDurability() { world.afterEvents.playerBreakBlock.subscribe((event) => { const [PLAYER, ITEM] = [event.player, getEquipmentItem(event.player)]; if (ITEM?.hasTag(this.tag)) { if ( PLAYER.getGameMode() === GameMode.survival || PLAYER.getGameMode() === GameMode.adventure ) { disposeItem(1, ITEM, PLAYER, this.options?.destroyedAfterEvents); } } }); world.afterEvents.entityHitEntity.subscribe((event) => { const [ENTITY, ITEM] = [ event.damagingEntity, getEquipmentItem(event.damagingEntity), ]; if (ITEM?.hasTag(this.tag)) { if (ENTITY instanceof Player) { if ( ENTITY.getGameMode() === GameMode.survival || ENTITY.getGameMode() === GameMode.adventure ) { disposeItem(2, ITEM, ENTITY, this.options?.destroyedAfterEvents); } } else { disposeItem(2, ITEM, ENTITY, this.options?.destroyedAfterEvents); } } }); } /** * Consume durability when the tool use on dirts. */ listeningShovelDurability() { world.afterEvents.itemUseOn.subscribe((event) => { const [ITEM, BLOCK, PLAYER] = [ event.itemStack, event.block, event.source, ]; if ( ITEM.hasTag(this.tag) && shovelConvertBlockIds.includes(BLOCK.typeId) ) { /** * 锹压地的事件 */ const newItem = consumeDurability(ITEM, 1, PLAYER); setEquipmentItem(PLAYER, newItem); PLAYER.playSound("step.grass"); if (!newItem && this.options?.destroyedAfterEvents) { this.options?.destroyedAfterEvents(PLAYER, ITEM); } } }); } listeningHoeDurability() { world.afterEvents.itemUseOn.subscribe((event) => { const [ITEM, BLOCK, PLAYER] = [ event.itemStack, event.block, event.source, ]; if (ITEM.hasTag(this.tag) && hoeConvertBlockIds.includes(BLOCK.typeId)) { /** * 锹压地的事件 */ const newItem = consumeDurability(ITEM, 1, PLAYER); setEquipmentItem(PLAYER, newItem); PLAYER.playSound("step.gravel"); if (!newItem && this.options?.destroyedAfterEvents) { this.options?.destroyedAfterEvents(PLAYER, ITEM); } } }); } /** * Consume durability when the tool use on logs. */ listeningAxeDurability() { world.afterEvents.itemUseOn.subscribe((event) => { const [ITEM, BLOCK, PLAYER] = [ event.itemStack, event.block, event.source, ]; if (ITEM.hasTag(this.tag) && axeConvertBlockIds.includes(BLOCK.typeId)) { /** * 斧剥皮的事件 */ const newItem = consumeDurability(ITEM, 1, PLAYER); setEquipmentItem(PLAYER, newItem); PLAYER.playSound("use.wood"); if (!newItem && this.options?.destroyedAfterEvents) { this.options?.destroyedAfterEvents(PLAYER, ITEM); } } }); } } /** * Define a tool. * @category Need Registry */ export class ToolItem { constructor( /** * Item of the weapon. */ public item: ItemStack, /** * Additional options of the tool. */ public options?: ToolOptions ) { this.listeningDurability(); if (this.options?.type === ToolType.shovel) { this.listeningShovelDurability(); } if (this.options?.type === ToolType.axe) { this.listeningAxeDurability(); } } /** * Automatically consume durability for the tools. */ listeningDurability() { world.afterEvents.playerBreakBlock.subscribe((event) => { const [PLAYER, ITEM] = [event.player, getEquipmentItem(event.player)]; if (ITEM?.typeId === this.item.typeId) { if ( PLAYER.getGameMode() === GameMode.survival || PLAYER.getGameMode() === GameMode.adventure ) { disposeItem(2, ITEM, PLAYER, this.options?.destroyedAfterEvents); } } }); world.afterEvents.entityHitEntity.subscribe((event) => { const [ENTITY, ITEM] = [ event.damagingEntity, getEquipmentItem(event.damagingEntity), ]; if (ITEM?.typeId === this.item.typeId) { if (ENTITY instanceof Player) { if ( ENTITY.getGameMode() === GameMode.survival || ENTITY.getGameMode() === GameMode.adventure ) { disposeItem(2, ITEM, ENTITY, this.options?.destroyedAfterEvents); } } else { disposeItem(2, ITEM, ENTITY, this.options?.destroyedAfterEvents); } } }); } listeningHoeDurability() { world.afterEvents.itemUseOn.subscribe((event) => { const [ITEM, BLOCK, PLAYER] = [ event.itemStack, event.block, event.source, ]; if ( ITEM.typeId === this.item.typeId && hoeConvertBlockIds.includes(BLOCK.typeId) ) { /** * 锹压地的事件 */ const newItem = consumeDurability(ITEM, 1, PLAYER); setEquipmentItem(PLAYER, newItem); PLAYER.playSound("step.gravel"); if (!newItem && this.options?.destroyedAfterEvents) { this.options?.destroyedAfterEvents(PLAYER, ITEM); } } }); } /** * Consume durability when the tool use on dirts. */ listeningShovelDurability() { world.afterEvents.itemUseOn.subscribe((event) => { const [ITEM, BLOCK, PLAYER] = [ event.itemStack, event.block, event.source, ]; if ( ITEM.typeId === this.item.typeId && shovelConvertBlockIds.includes(BLOCK.typeId) ) { /** * 锹压地的事件 */ const newItem = consumeDurability(ITEM, 1, PLAYER); setEquipmentItem(PLAYER, newItem); PLAYER.playSound("step.grass"); if (!newItem && this.options?.destroyedAfterEvents) { this.options?.destroyedAfterEvents(PLAYER, ITEM); } } }); } /** * Consume durability when the tool use on logs. */ listeningAxeDurability() { world.afterEvents.itemUseOn.subscribe((event) => { const [ITEM, BLOCK, PLAYER] = [ event.itemStack, event.block, event.source, ]; if ( ITEM.typeId === this.item.typeId && axeConvertBlockIds.includes(BLOCK.typeId) ) { /** * 斧剥皮的事件 */ const newItem = consumeDurability(ITEM, 1, PLAYER); setEquipmentItem(PLAYER, newItem); PLAYER.playSound("use.wood"); if (!newItem && this.options?.destroyedAfterEvents) { this.options?.destroyedAfterEvents(PLAYER, ITEM); } } }); } } /** * Type of the tool. */ export enum ToolType { /** * Define the tool is an axe. */ axe, /** * Define the tool is a shovel. */ shovel, /** * Define the tool is a hoe. */ hoe, /** * Define the tool is a pickaxe. */ pickaxe, /** * Define a custom tool. */ custom, } export interface ToolOptions { /** * Type of the tool. */ type?: ToolType; /** * Trigger events when the tool has been destroyed. */ destroyedAfterEvents?: (holder: Entity, item: ItemStack) => void; }