UNPKG

yoni-mcscripts-lib

Version:

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

381 lines (380 loc) 14 kB
import { Minecraft } from "../basis.js"; /** * 允许开发者调用一连串方法来调整出需要的物品对象。 */ export class ItemCreator { /** * 正在修改中的物品对象。所有修改都会直接应用到此物品对象当中。 * @types {Minecraft.ItemStack} */ get itemStack() { if (this.#itemStack) return this.#itemStack; throw Error("物品不存在,可能物品数量为0?"); } set itemStack(itemStack) { this.#itemStack = itemStack; } /** * @types {Minecraft.ItemStack} */ #itemStack; /** * 创建一个新的物品对象,或使用现有的物品对象,随后可以修改它。 * @param {Minecraft.ItemStack|Minecraft.ItemType|string} itemStack * @param {number} [amount] */ constructor(itemStack, amount) { this.#itemStack = itemStack instanceof Minecraft.ItemStack ? itemStack : new Minecraft.ItemStack(itemStack); if (amount != undefined) this.setAmount(amount); } /** * 转换物品的类型,这可能会导致错误。 * @param {Minecraft.ItemType|string} type 新的物品类型。 * @param {boolean} [ignoreError] 指示忽略过程中的所有错误。 * @returns {this} 返回 this */ setType(type, ignoreError = false) { const newItemCreator = new ItemCreator(new Minecraft.ItemStack(type)); const oldItem = this.itemStack; if (oldItem.hasComponent("enchantments")) { const oldEnchants = ItemCreator.getEnchantmentList(oldItem); for (const ench of oldEnchants) { tryExecute(() => { newItemCreator.addEnchant(ench, true); }, ignoreError); } } if (oldItem.hasComponent("durability")) { const oldDamage = oldItem.getComponent("minecraft:durability").damage; newItemCreator.setDurability(oldDamage); } if (oldItem.nameTag != null) tryExecute(() => { newItemCreator.setNameTag(oldItem.nameTag); }, ignoreError); tryExecute(() => { newItemCreator.setAmount(oldItem.amount); }, ignoreError); tryExecute(() => { newItemCreator.setKeepOnDeath(oldItem.keepOnDeath); }, ignoreError); tryExecute(() => { newItemCreator.setLockMode(oldItem.lockMode); }, ignoreError); const lore = oldItem.getLore(); if (lore.length > 0) tryExecute(() => { newItemCreator.setLore(lore); }, ignoreError); this.itemStack = newItemCreator.itemStack; return this; } /** * 增减物品数量。 * @param {number} amount 一个数字,将会在现有数量上加上它。 * @returns {this} 返回 this */ changeAmount(amount) { amount = this.itemStack.amount + amount; this.setAmount(amount); return this; } /** * 修改物品数量,将数量减为0将导致物品消失。 * @param {number} amount 一个数字,代表新的数量。 * @returns {this} 返回 this */ setAmount(amount) { this.itemStack.amount = amount; if (this.itemStack.amount < 1) this.#itemStack = undefined; return this; } /** * 删除物品的 lore 文本。 * @returns {this} 返回 this */ removeLore() { this.itemStack.setLore([]); return this; } setLore(loreList) { if (typeof loreList === "string") loreList = loreList.split("\x00"); this.itemStack.setLore(loreList); return this; } /** * 设置物品存在于物品栏中时,使用的锁定模式。 * @param {Minecraft.ItemLockMode} mode 模式。 * @returns {this} 返回 this */ setLockMode(mode) { this.itemStack.lockMode = mode; return this; } /** * 设置物品存在于玩家的物品栏中时,是否会在玩家死亡时掉落。 * @param {boolean} keepOnDeath 是否启用。 * @returns {this} 返回 this */ setKeepOnDeath(keepOnDeath) { this.itemStack.keepOnDeath = keepOnDeath; return this; } /** * 设置物品的名称。 * @param {string} [nameTag] 物品的名称,为空时清除。 * @returns {this} 返回 this */ setNameTag(nameTag) { this.itemStack.nameTag = nameTag; return this; } /** * 清除物品设置的名称。 * @returns {this} 返回 this */ removeNameTag() { this.itemStack.nameTag = undefined; return this; } /** * 对物品造成耐久消耗,这会受到耐久附魔的影响。如果需要直接修改耐久,请使用{@link ItemCreator#setDurability}。 * @param {number} damage 要造成耐久消耗的次数。 * @param {number} [unbreaking] 可选,额外指定耐久附魔的等级。 * @returns {this} 返回 this */ takeDamage(damage, unbreaking) { ItemCreator.takeDurability(this.itemStack, damage, unbreaking); return this; } /** * 增减物品的耐久消耗度。 * @param {number} damage 一个数字,将会在现有耐久消耗度上加上它。 * @returns {this} 返回 this */ changeDurability(damage) { const component = this.itemStack.getComponent("minecraft:durability"); component.damage = Math.max(0, component.damage + Math.min(component.maxDurability - component.damage, damage)); return this; } /** * 修改物品耐久消耗度。 * @param {number} amount 一个数字,代表新的耐久消耗度。 * @returns {this} 返回 this */ setDurability(damage) { const component = this.itemStack.getComponent("minecraft:durability"); component.damage = damage; return this; } /** * 为物品增添新的附魔。 * @param {Minecraft.Enchantment|Minecraft.EnchantmentType|string} newEnchantment 新添加的附魔类型。 * @param {number} level 新添加的附魔的等级,默认为 1 级。 * @param {boolean} [override] 如果为真,则替换现有附魔(如果附魔存在);否则,为现有附魔条目提升附魔等级。默认为替换附魔。 * @returns {this} 返回 this */ addEnchant(newEnchantment, level, override = true) { let ench; if (level === true || level === false || level === undefined) { override = level ?? true; ench = newEnchantment; } else { ench = { type: newEnchantment, level: level ?? 1 }; } this.addEnchants([ench], override); return this; } /** * 为物品增添一系列新的附魔。 * @param {Enchantment[]} newEnchantments 新添加的附魔。 * @param {boolean} [override] 如果为真,则替换现有附魔(如果附魔存在);否则,为现有附魔条目提升附魔等级。默认为替换附魔。 * @returns {this} 返回 this */ addEnchants(newEnchantments, override = true) { const enchantmentList = ItemCreator.getEnchantmentList(this.itemStack); if (!override) newEnchantments = newEnchantments.map(ench => { let { type, level } = ench; if (enchantmentList.hasEnchantment(type)) level += enchantmentList.getEnchantment(type).level; return { type, level }; }); for (const ench of newEnchantments) { if (enchantmentList.hasEnchantment(ench.type)) enchantmentList.removeEnchantment(ench.type); if (ench.level > 0) enchantmentList.addEnchantment(ItemCreator.getEnchantment(ench.type, ench.level)); } ItemCreator.setEnchantmentList(this.itemStack, enchantmentList); return this; } /** * 从物品上移除附魔。 * @param {Minecraft.Enchantment|Minecraft.EnchantmentType|string} newEnchantment 要移除的附魔类型。 * @param {number} [level] 要移除的附魔的等级,不设置 或 设置为 0 则以已有的附魔等级为此参数的值。 * @param {boolean} [override] 如果为真,则只有在附魔完全相同时才会移除。默认为真。 * @returns {this} 返回 this */ removeEnchant(enchantment, level = 0, completelyMatches = true) { let enchantmentType; if (level === true || level === false || level === 0) { if (enchantment instanceof Minecraft.EnchantmentType || typeof enchantment === "string") { enchantmentType = enchantment; } else { enchantmentType = enchantment.type; completelyMatches = level === 0 ? true : level; level = enchantment.level; } } else { enchantmentType = enchantment; } const enchantmentList = ItemCreator.getEnchantmentList(this.itemStack); if (enchantmentList.hasEnchantment(enchantmentType)) { const oldEnchantment = enchantmentList.getEnchantment(enchantmentType); if (!completelyMatches || (completelyMatches && (level === 0 || oldEnchantment.level === level))) { enchantmentList.removeEnchantment(enchantmentType); if (level !== 0) { let { type, level: level0 } = oldEnchantment; level0 -= level; if (level0 > 0) { enchantmentList.addEnchantment(ItemCreator.getEnchantment(enchantmentType, level0)); } } ItemCreator.setEnchantmentList(this.itemStack, enchantmentList); } } return this; } /** * 从物品上移除所有附魔。 * @returns {this} 返回 this */ removeAllEnchants() { const component = this.itemStack.getComponent("minecraft:enchantments"); component.removeAllEnchantments(); return this; } /** * 复制物品对象。 * @returns {this} 返回 this */ cloneItem() { this.itemStack = this.itemStack.clone(); return this; } /** * 创建此 ItemCreator 以及其内部的物品对象的副本。 * @returns {ItemCreator} 返回新的 ItemCreator。 */ clone() { return new ItemCreator(this.itemStack.clone()); } /** * 复制附魔列表。 * @param {Minecraft.EnchantmentList} list 要复制的附魔列表。 * @returns {Minecraft.EnchantmentList} */ static cloneEnchantmentList(list) { const newList = new Minecraft.EnchantmentList(list.slot); for (const ench of list) newList.addEnchantment(ench); return newList; } /** * 获取附魔类型对象。 * @param {Minecraft.EnchantmentType|string} ench * @returns {Minecraft.EnchantmentType} */ static getEnchantmentType(ench) { return typeof ench === "string" ? Minecraft.EnchantmentTypes.get(ench) : ench; } /** * 获取附魔对象。 * @param {Minecraft.EnchantmentType|string} enchantmentType 附魔类型。 * @param {Minecraft.EnchantmentType|string} level 附魔等级。 * @returns {Minecraft.Enchantment} */ static getEnchantment(enchantmentType, level = 1) { const ench = new Minecraft.Enchantment(enchantmentType); ench.level = level; return ench; } /** * 获取物品的附魔列表。 * @param {Minecraft.ItemStack} itemStack 物品。 * @returns {Minecraft.EnchantmentList} */ static getEnchantmentList(itemStack) { const component = itemStack.getComponent("minecraft:enchantments"); return component.enchantments; } /** * 设置物品的附魔列表。 * @param {Minecraft.ItemStack} itemStack 物品。 * @param {Minecraft.EnchantmentList} list 要使用的附魔列表。 * @returns {Minecraft.ItemStack} */ static setEnchantmentList(itemStack, list) { const component = itemStack.getComponent("minecraft:enchantments"); component.enchantments = list; return itemStack; } /** * 对物品造成耐久消耗,这会受到耐久附魔的影响。 * @param {Minecraft.ItemStack} itemStack 物品。 * @param {number} damage 要造成耐久消耗的次数。 * @param {number} [unbreaking] 可选,额外指定耐久附魔的等级。 * @returns {this} 返回 this */ static takeDurability(itemStack, damage, unbreaking) { const enchantments = ItemCreator.getEnchantmentList(itemStack); if (!unbreaking && enchantments.hasEnchantment("unbreaking")) unbreaking = enchantments.getEnchantment("unbreaking")?.level; const component = itemStack.getComponent("minecraft:durability"); let damageChance; if (!unbreaking || unbreaking === 0) damageChance = 100; else damageChance = component.getDamageChance(unbreaking); let totalDamage = 0; if (damageChance === 100) totalDamage += damage; else while (damage-- > 0) { if (Math.random() * 100 > damageChance) totalDamage += 1; } component.damage += totalDamage; return itemStack; } } function deleteFirst(array, element) { const index = array.indexOf(element); if (index !== -1) array.splice(index, 1); return array; } function tryExecute(func, ignoreError = false) { if (ignoreError) try { func(); } catch { //ignore all errors } else func(); }