yoni-mcscripts-lib
Version:
为 Minecraft Script API 中的部分接口创建了 wrapper,并提供简单的事件管理器和任务管理器,另附有一些便于代码编写的一些小工具。
381 lines (380 loc) • 14 kB
JavaScript
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();
}