LTDV10/packet/kubejs/server_scripts/mbd2/mechanical_craft_encoder.js
2026-04-14 18:20:56 +08:00

206 lines
8.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const $BigItemStack = Java.loadClass("com.simibubi.create.content.logistics.BigItemStack")
const $PackageOrderWithCrafts = Java.loadClass("com.simibubi.create.content.logistics.stockTicker.PackageOrderWithCrafts")
const $MechanicalCraftingRecipe = Java.loadClass("com.simibubi.create.content.kinetics.crafter.MechanicalCraftingRecipe")
const $ItemStackHandler = Java.loadClass("net.minecraftforge.items.ItemStackHandler")
const $PackageItem = Java.loadClass("com.simibubi.create.content.logistics.box.PackageItem")
MBDMachineEvents.onLoad("createdelight:mechanical_craft_encoder", e => {
let event = e.event
const { machine } = event
const { customData } = machine
/**@type {ItemStackTransfer} */
let input = machine.getTraitByName("item_input_slot").storage
input.setOnContentsChanged(() => {
customData.putInt("handle_countdown", 30)
})
})
/**
*
* @param {Internal.MBDMachine} machine
* @param {Internal.Level} level
*/
function handleChanged(machine, level) {
/**@type {ItemStackTransfer} */
let input = machine.getTraitByName("item_input_slot").storage
/**@type {ItemStackTransfer} */
let filter = machine.getTraitByName("item_filter_slot").storage
/**@type {ItemStackTransfer} */
let output = machine.getTraitByName("item_output_slot").storage
let outputFull = true
for (let index = 0; index < output.slots; index++) {
let element = output.getStackInSlot(index);
if (element.empty)
outputFull = false
}
if (outputFull)
return
let minWidth = machine.customData.getInt("width") || 5
/**@type {Internal.MechanicalCraftingRecipe[]} */
let recipelist = level.recipeManager.getAllRecipesFor("create:mechanical_crafting")
.filter(recipe => {
if (filter.getStackInSlot(0).empty)
return true
else
return recipe.getResultItem(level.registryAccess()).is(filter.getStackInSlot(0))
})
.filter(recipe => {
let snapshot = input.createSnapshot() // 保存当前状态
// 遍历配方中的每个食材
let allIngredientsConsumed = true; // 假设所有食材都能消耗完
for (let i = 0; i < recipe.ingredients.size(); i++) {
let ingr = recipe.ingredients.get(i); // 获取当前配方中的食材
// 如果食材是空的,跳过
if (ingr.empty) continue;
// 遍历input中的每个槽位检查是否有匹配的物品
let ingredientConsumed = false;
for (let j = 0; j < input.slots; j++) {
let inputStack = input.getStackInSlot(j)
if (!inputStack.empty && ingr.test(inputStack.id)) {
// 获取食材的数量
let countToExtract = ingr.getFirst().getCount();
let res = input.extractItem(j, countToExtract, false, false);
// 如果成功提取物品,减少该食材数量
if (res.count > 0) {
ingredientConsumed = true;
}
break; // 一旦消耗了匹配的食材,跳出内层循环
}
}
// 如果某个食材无法消耗完则返回false
if (!ingredientConsumed) {
allIngredientsConsumed = false;
break;
}
}
// 恢复input状态
input.restoreFromSnapshot(snapshot);
return allIngredientsConsumed; // 如果所有食材都已成功消耗返回true
})
recipelist
.filter(recipe => {
return recipe.width <= minWidth
})
.sort((a, b) => {
return Math.abs(a.width - minWidth) - Math.abs(b.width - minWidth) //越接近所设置宽度值的越在前面
})
if (recipelist.length !== 0) {
// 获取recipe的宽度和高度
let width = recipelist[0].width;
let height = recipelist[0].height;
// 模拟空食材
let emptyIngredient = Item.empty; // Empty ItemStack
let craftingIngredients = Utils.newList();
// 获取设定的最小宽度(确保它至少等于配方的宽度)
let gridWidth = Math.max(minWidth, width); // 如果设定的宽度小于配方的宽度,取配方的宽度
let resultItemHandler = new $ItemStackHandler()
resultItemHandler.setSize(81)
// 按照设定的宽度填充craftingIngredients
for (let i = 0; i < height; i++) {
for (let j = 0; j < gridWidth; j++) {
if (j < width) {
// 处于配方区域,添加食材
let ingredient = recipelist[0].ingredients.get(i * width + j); // 计算配方食材的索引
let craftingIngredient = emptyIngredient;
if (!ingredient.isEmpty()) {
// 在input中寻找对应的物品
for (let k = 0; k < input.slots; k++) {
let inputStack = input.getStackInSlot(k);
if (!inputStack.empty && ingredient.test(inputStack)) {
craftingIngredient = inputStack.copyWithCount(1); // 复制食材
resultItemHandler.insertItem(craftingIngredient, false)
inputStack.shrink(1); // 从input中消耗该物品
break;
}
}
}
craftingIngredients.push(new $BigItemStack(craftingIngredient));
} else {
// 超过配方区域,填充空食材
craftingIngredients.push(new $BigItemStack(emptyIngredient));
}
}
}
// 保证craftingIngredients长度为9
while (craftingIngredients.length < 9) {
craftingIngredients.push(new $BigItemStack(emptyIngredient));
}
let order = $PackageOrderWithCrafts.singleRecipe(craftingIngredients);
// 移除input内的对应配方所应该消耗的内容
// recipelist[0].ingredients.forEach((ingredient) => {
// for (let i = 0; i < input.slots; i++) {
// let inputStack = input.getStackInSlot(i);
// if (!inputStack.empty && !ingredient.empty && ingredient.test(inputStack)) {
// let countToExtract = ingredient.first.count;
// let res = input.extractItem(i, countToExtract, false, false);
// console.log(res)
// list.push(res);
// break;
// }
// }
// });
let pack = $PackageItem["containing(net.minecraftforge.items.ItemStackHandler)"](resultItemHandler);
pack.nbt.put("Fragment", { OrderContext: order.write() });
ItemTransferHelper.insertItemStacked(output, pack, false);
}
}
MBDMachineEvents.onTick("createdelight:mechanical_craft_encoder", e => {
let event = e.event
const { machine } = event
const { level, customData } = machine
// if (customData.getInt("handle_countdown") == 1) {
// handleChanged(machine, level)
// }
// if (customData.getInt("handle_countdown") > 0) {
// customData.putInt("handle_countdown", customData.getInt("handle_countdown") - 1)
// }
if (level.time % 30 == 0 && level.hasNeighborSignal(machine.pos))
handleChanged(machine, level)
})
MBDMachineEvents.onNeighborChanged("createdelight:mechanical_craft_encoder", e => {
let event = e.event
const { machine } = event
const { level, customData } = machine
if (level.hasNeighborSignal(machine.pos))
handleChanged(machine, level)
})
MBDMachineEvents.onUI("createdelight:mechanical_craft_encoder", e => {
let event = e.event
const { machine, root } = event
/**@type {TextFieldWidget} */
let text = root.getFirstWidgetById("width")
text.currentString = (machine.customData.getInt("width") || 5).toFixed()
text.setNumbersOnlyInt(1, 9)
text.setTextResponder(str => {
machine.customData.putInt("width", parseInt(str))
})
})