206 lines
8.2 KiB
JavaScript
206 lines
8.2 KiB
JavaScript
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))
|
||
})
|
||
|
||
}) |