From 47695dd923964111af06ba0faf30dcc903f42a4c Mon Sep 17 00:00:00 2001 From: dalizi2333 Date: Wed, 13 May 2026 13:56:23 +0800 Subject: [PATCH 01/10] gitignore --- .gitignore | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bd9adc8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,14 @@ +# IDE files +.vscode/ +.trae/ + +# IDE configuration files +**/jsconfig.json +config/probe-settings.json + +# OS files +Thumbs.db +.DS_Store + +# Change log +change log/ \ No newline at end of file From 005ea3b4e45d6dc25e429aa0bdf80f0beb1950ef Mon Sep 17 00:00:00 2001 From: dalizi2333 Date: Fri, 15 May 2026 21:50:23 +0800 Subject: [PATCH 02/10] =?UTF-8?q?=E5=BC=80=E5=8F=91=E4=B8=AD=EF=BC=8C?= =?UTF-8?q?=E5=88=9D=E6=AD=A5=E5=AE=9E=E7=8E=B0=E4=BB=8E=E5=A4=A7=E6=A1=B6?= =?UTF-8?q?=E5=AF=86=E5=B0=81=E9=85=8D=E6=96=B9=E6=89=B9=E9=87=8F=E8=BD=AC?= =?UTF-8?q?=E6=8D=A2=E5=8F=91=E9=85=B5=E9=85=8D=E6=96=B9=EF=BC=8C=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E9=9D=9E=E8=85=90=E8=B4=A5=E9=A3=9F=E6=9D=90=E9=99=90?= =?UTF-8?q?=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../biodiesel_fix/fermenting_from_barrel.js | 205 ++++++++++++++++++ .../test_fermenting_recipes.js.pass | 96 ++++++++ server_scripts/test_large_leather.js.pass | 26 +++ server_scripts/test_not_rotten.js.pass | 56 +++++ server_scripts/test_tfc_modifiers.js.faild | 32 +++ 5 files changed, 415 insertions(+) create mode 100644 server_scripts/biodiesel_fix/fermenting_from_barrel.js create mode 100644 server_scripts/test_fermenting_recipes.js.pass create mode 100644 server_scripts/test_large_leather.js.pass create mode 100644 server_scripts/test_not_rotten.js.pass create mode 100644 server_scripts/test_tfc_modifiers.js.faild diff --git a/server_scripts/biodiesel_fix/fermenting_from_barrel.js b/server_scripts/biodiesel_fix/fermenting_from_barrel.js new file mode 100644 index 0000000..00f4790 --- /dev/null +++ b/server_scripts/biodiesel_fix/fermenting_from_barrel.js @@ -0,0 +1,205 @@ +// ============================================================================ +// 批量从TFC密封大桶配方创建Create发酵配方 +// ============================================================================ + +ServerEvents.recipes(event => { + console.info('[生物柴油修复] 开始批量转换TFC密封大桶配方为Create发酵配方...'); + + let convertedCount = 0; + let skippedCount = 0; + + event.forEachRecipe({ type: 'tfc:barrel_sealed' }, recipe => { + const json = recipe.json; + + let inputItem = null; + if (json.has('input_item')) { + inputItem = JSON.parse(json.get('input_item').toString()); + } + + let inputFluid = null; + if (json.has('input_fluid')) { + inputFluid = JSON.parse(json.get('input_fluid').toString()); + } + + let outputItem = null; + if (json.has('output_item')) { + outputItem = JSON.parse(json.get('output_item').toString()); + } + + let outputFluid = null; + if (json.has('output_fluid')) { + outputFluid = JSON.parse(json.get('output_fluid').toString()); + } + + // 检查输入物品堆叠数量 + if (inputItem) { + let itemId = inputItem.item || inputItem.tag; + if (itemId) { + let count = inputItem.count || 1; + try { + let maxStack; + if (inputItem.tag) { + let tagItems = Ingredient.of(`#${inputItem.tag}`).items; + if (tagItems && tagItems.length > 0) { + let minStack = tagItems[0].maxStack; + for (let i = 1; i < tagItems.length; i++) { + if (tagItems[i].maxStack < minStack) { + minStack = tagItems[i].maxStack; + } + } + maxStack = minStack; + } + } else { + maxStack = Item.of(itemId, 1).items[0].maxStack; + } + if (maxStack && count > maxStack) { + skippedCount++; + return; + } + } catch (e) { + if (count > 64) { + skippedCount++; + return; + } + } + } + } + + // 检查输出物品堆叠数量 + if (outputItem) { + let outputId = outputItem.id || outputItem.item; + if (outputId) { + let count = outputItem.count || 1; + try { + let maxStack = Item.of(outputId, 1).items[0].maxStack; + if (maxStack && count > maxStack) { + skippedCount++; + return; + } + } catch (e) { + if (count > 64) { + skippedCount++; + return; + } + } + } + } + + // 检查流体量 + if (inputFluid && inputFluid.amount > 1000) { + skippedCount++; + return; + } + if (outputFluid && outputFluid.amount > 1000) { + skippedCount++; + return; + } + + // 跳过modifiers + if (outputItem && outputItem.modifiers) { + skippedCount++; + return; + } + + let sealTime = json.has('seal_time') ? json.get('seal_time').getAsInt() : 0; + let ingredients = []; + let results = []; + + // 添加输入物品 + if (inputItem) { + if (inputItem.type === 'tfc:and' && inputItem.children) { + let count = inputItem.count || 1; + for (let i = 0; i < count; i++) { + ingredients.push({ + type: 'tfc:and', + children: inputItem.children + }); + } + } else { + let itemId = inputItem.item || inputItem.tag; + if (itemId && typeof itemId === 'string' && itemId.includes('food/')) { + let count = inputItem.count || 1; + for (let i = 0; i < count; i++) { + ingredients.push({ + type: 'tfc:and', + children: [ + inputItem.item ? { item: inputItem.item } : { tag: inputItem.tag }, + { type: 'tfc:not_rotten' } + ] + }); + } + } else { + let count = inputItem.count || 1; + if (inputItem.item) { + for (let i = 0; i < count; i++) { + ingredients.push({ item: inputItem.item }); + } + } else if (inputItem.tag) { + for (let i = 0; i < count; i++) { + ingredients.push({ tag: inputItem.tag }); + } + } + } + } + } + + // 添加输入流体 + if (inputFluid) { + if (inputFluid.fluid && inputFluid.amount > 0) { + ingredients.push({ + type: 'fluid_stack', + fluid: inputFluid.fluid, + amount: inputFluid.amount + }); + } else if (inputFluid.tag && inputFluid.amount > 0) { + ingredients.push({ + type: 'fluid_tag', + fluid_tag: inputFluid.tag, + amount: inputFluid.amount + }); + } + } + + // 添加输出物品 + if (outputItem) { + let itemId = outputItem.id || outputItem.item; + if (itemId) { + let singleResult = { id: itemId }; + if (outputItem.count && outputItem.count > 1) { + singleResult.count = outputItem.count; + } + if (outputItem.chance) { + singleResult.chance = outputItem.chance; + } + results.push(singleResult); + } + } + + // 添加输出流体 + if (outputFluid) { + let fluidId = outputFluid.id || outputFluid.fluid; + if (fluidId && outputFluid.amount > 0) { + results.push({ + id: fluidId, + amount: outputFluid.amount + }); + } + } + + let processingTime = Math.max(100, Math.round(sealTime / 5)); + + if (results.length > 0 && ingredients.length > 0) { + event.custom({ + type: 'createdieselgenerators:basin_fermenting', + ingredients: ingredients, + processing_time: processingTime, + results: results + }).id(`kubejs:tfc_barrel_sealed/${recipe.getId().replace(':', '_')}`); + convertedCount++; + } else { + skippedCount++; + } + }); + + console.info(`[生物柴油修复] 完成!共转换 ${convertedCount} 个配方,跳过 ${skippedCount} 个`); +}); diff --git a/server_scripts/test_fermenting_recipes.js.pass b/server_scripts/test_fermenting_recipes.js.pass new file mode 100644 index 0000000..4cf9375 --- /dev/null +++ b/server_scripts/test_fermenting_recipes.js.pass @@ -0,0 +1,96 @@ +// ============================================================================ +// 手动创建TFC密封大桶配方对应的CDG发酵配方(完全按照参考格式) +// ============================================================================ + +ServerEvents.recipes(event => { + console.info('[生物柴油修复] 开始手动创建测试配方(完全按照参考格式)...'); + + // 1. black_wool - 黑色羊毛染色 + event.custom({ + type: 'createdieselgenerators:basin_fermenting', + ingredients: [ + { item: 'minecraft:white_wool' }, + { + type: 'fluid_stack', + fluid: 'tfc:black_dye', + amount: 25 + } + ], + processing_time: Math.max(100, Math.round(1200 / 5)), + results: [ + { id: 'minecraft:black_wool' } + ] + }).id('kubejs:test/black_wool'); + + // 2. corn_whiskey - 玉米威士忌 + event.custom({ + type: 'createdieselgenerators:basin_fermenting', + ingredients: [ + { + type: 'tfc:and', + children: [ + { item: 'tfc:food/maize_flour' }, + { type: 'tfc:not_rotten' } + ] + }, + { + type: 'fluid_stack', + fluid: 'minecraft:water', + amount: 500 + } + ], + processing_time: Math.max(100, Math.round(72000 / 5)), + results: [ + { + id: 'tfc:corn_whiskey', + amount: 500 + } + ] + }).id('kubejs:test/corn_whiskey'); + + // 3. sugar - 糖 + event.custom({ + type: 'createdieselgenerators:basin_fermenting', + ingredients: [ + { + type: 'tfc:and', + children: [ + { item: 'tfc:food/sugarcane' }, + { type: 'tfc:not_rotten' } + ] + }, + { + type: 'fluid_stack', + fluid: 'minecraft:water', + amount: 600 + } + ], + processing_time: Math.max(100, Math.round(7200 / 5)), + results: [ + { id: 'minecraft:sugar' } + ] + }).id('kubejs:test/sugar'); + + // 4. firmalife_cream - Firmalife奶油制作(使用流体标签格式) + event.custom({ + type: 'createdieselgenerators:basin_fermenting', + ingredients: [ + { item: 'firmalife:cheesecloth' }, + { + type: 'fluid_tag', // ✅ 使用fluid_tag类型 + fluid_tag: 'firmalife:milks', + amount: 1000 + } + ], + processing_time: Math.max(100, Math.round(1000 / 5)), + results: [ + { id: 'firmalife:cheesecloth' }, + { + id: 'firmalife:cream', + amount: 1000 + } + ] + }).id('kubejs:test/firmalife_cream'); + + console.info('[生物柴油修复] 手动测试配方(完全按照参考格式)创建完成!'); +}); diff --git a/server_scripts/test_large_leather.js.pass b/server_scripts/test_large_leather.js.pass new file mode 100644 index 0000000..bb313f2 --- /dev/null +++ b/server_scripts/test_large_leather.js.pass @@ -0,0 +1,26 @@ +// ============================================================================ +// 测试large_leather和medium_leather配方转换 +// ============================================================================ + +ServerEvents.recipes(event => { + console.info('[测试] 开始测试皮革配方...'); + + // 测试: medium用直接count字段 + event.custom({ + type: 'createdieselgenerators:basin_fermenting', + ingredients: [ + { item: 'tfc:medium_prepared_hide' }, + { + type: 'fluid_stack', + fluid: 'tfc:tannin', + amount: 500 + } + ], + processing_time: Math.max(100, Math.round(7200 / 5)), + results: [ + { id: 'minecraft:leather', count: 2 } + ] + }).id('kubejs:test/medium_leather_count'); + + console.info('[测试] 皮革配方测试创建完成!'); +}); diff --git a/server_scripts/test_not_rotten.js.pass b/server_scripts/test_not_rotten.js.pass new file mode 100644 index 0000000..a2f676b --- /dev/null +++ b/server_scripts/test_not_rotten.js.pass @@ -0,0 +1,56 @@ +// ============================================================================ +// 测试脚本:非腐败条件限制器在Create配方中的使用 +// 使用Ingredient.of(物品类型, 数量)的方式实现多物品限制 +// ============================================================================ + +ServerEvents.recipes(event => { + console.info('[生物柴油修复测试] 开始测试非腐败条件限制器...'); + + // 测试1:橄榄塑形配方(10个新鲜橄榄 → 800mb橄榄油) + event.recipes.create.compacting( + [Fluid.of('tfc:olive_oil', 800)], + [ + Ingredient.of({ + type: 'tfc:and', + children: [ + { item: 'tfc:food/olive' }, + { type: 'tfc:not_rotten' } + ] + }, 10) + ], + 100 + ).id('kubejs:test_olive_to_oil_not_rotten'); + + // 测试2:小麦面粉混合配方(16个新鲜小麦面粉 + 水 → 啤酒) + event.recipes.create.mixing( + [Fluid.of('tfc:beer', 1000)], + [ + Ingredient.of({ + type: 'tfc:and', + children: [ + { item: 'tfc:food/wheat_flour' }, + { type: 'tfc:not_rotten' } + ] + }, 16), + Fluid.of('minecraft:water', 1000) + ], + 100 + ).id('kubejs:test_wheat_flour_to_beer_not_rotten'); + + // 测试3:小麦研磨配方(1个新鲜小麦种子 → 面粉) + event.recipes.create.milling( + ['tfc:food/wheat_flour'], + [ + Ingredient.of({ + type: 'tfc:and', + children: [ + { item: 'tfc:food/wheat_grain' }, + { type: 'tfc:not_rotten' } + ] + }) + ], + 50 + ).id('kubejs:test_wheat_grain_to_flour_not_rotten'); + + console.info('[生物柴油修复测试] 所有配方创建完成!'); +}); diff --git a/server_scripts/test_tfc_modifiers.js.faild b/server_scripts/test_tfc_modifiers.js.faild new file mode 100644 index 0000000..f43f517 --- /dev/null +++ b/server_scripts/test_tfc_modifiers.js.faild @@ -0,0 +1,32 @@ +// ============================================================================ +// 测试TFC修饰符格式是否被CDG支持 +// ============================================================================ + +ServerEvents.recipes(event => { + console.info('[生物柴油修复] 开始测试TFC修饰符格式...'); + + // 测试black_dyeable - 带TFC修饰符的输出 + event.custom({ + type: 'createdieselgenerators:basin_fermenting', + ingredients: [ + { tag: 'minecraft:dyeable' }, + { + type: 'fluid_stack', + fluid: 'tfc:black_dye', + amount: 25 + } + ], + processing_time: Math.max(100, Math.round(1200 / 5)), + results: [ + { + item: 'minecraft:leather', // 试试直接用item字段 + modifiers: [ + { type: 'tfc:copy_input' }, + { type: 'tfc:dye_leather', color: 'black' } + ] + } + ] + }).id('kubejs:test/black_dyeable_with_modifiers'); + + console.info('[生物柴油修复] TFC修饰符格式测试完成!'); +}); From 6bc4d0a48cd6a718f87e5b1c766794efb0f9f998 Mon Sep 17 00:00:00 2001 From: dalizi2333 Date: Sat, 16 May 2026 14:15:52 +0800 Subject: [PATCH 03/10] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E9=99=A4=E4=BA=86modif?= =?UTF-8?q?iers=20=E7=9A=84=E9=85=8D=E6=96=B9=E5=A4=96=E5=85=A8=E9=83=A8?= =?UTF-8?q?=E9=85=8D=E6=96=B9=E5=B0=BD=E5=8F=AF=E8=83=BD=E5=80=8D=E5=A2=9E?= =?UTF-8?q?=E5=8F=91=E9=85=B5=E9=85=8D=E6=96=B9=EF=BC=8C=E5=80=8D=E5=A2=9E?= =?UTF-8?q?=E5=80=8D=E7=8E=87=E5=B0=8F=E4=BA=8E1=E6=97=B6=E4=BC=9A?= =?UTF-8?q?=E8=B7=B3=E8=BF=87=E5=8F=91=E9=85=B5=E9=85=8D=E6=96=B9=E7=94=9F?= =?UTF-8?q?=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../biodiesel_fix/fermenting_from_barrel.js | 163 +++++++++++------- .../test_basin_fermenting_schema.js.faild | 67 +++++++ server_scripts/test_maxstack_debug.js.pass | 138 +++++++++++++++ 3 files changed, 301 insertions(+), 67 deletions(-) create mode 100644 server_scripts/test_basin_fermenting_schema.js.faild create mode 100644 server_scripts/test_maxstack_debug.js.pass diff --git a/server_scripts/biodiesel_fix/fermenting_from_barrel.js b/server_scripts/biodiesel_fix/fermenting_from_barrel.js index 00f4790..4ba1123 100644 --- a/server_scripts/biodiesel_fix/fermenting_from_barrel.js +++ b/server_scripts/biodiesel_fix/fermenting_from_barrel.js @@ -1,16 +1,43 @@ // ============================================================================ // 批量从TFC密封大桶配方创建Create发酵配方 // ============================================================================ +// +// 功能说明: +// - 遍历所有 TFC 密封大桶配方 (tfc:barrel_sealed) +// - 将其转换为 Create Diesel Generators 的 Basin Fermenting 配方 +// - 自动计算配方倍增倍数,实现高吞吐单次发酵 +// +// 核心技术难点与解决方案: +// ---------------------------------------------------------------------------- +// 问题:TFC 的 tfc:not_rotten 条件只能在 TFC 配方系统中解析 +// 当在 Create 配方中使用 { type: 'tfc:and', children: [...] } 结构时, +// 无法通过设置 count 属性实现数量倍增(会导致 JSON 解析错误) +// +// 解决方案:用数组重复代替 count 属性倍增 +// - 对于普通物品:重复 { item: 'xxx' } N 次 +// - 对于带条件的物品:重复 { type: 'tfc:and', children: [...] } N 次 +// - 流体和输出仍使用 amount/count 属性倍增(它们不受此限制) +// ---------------------------------------------------------------------------- +// +// 倍增倍数计算规则: +// 1. 输入物品:maxStack / count +// 2. 输出物品:maxStack / count +// 3. 输入流体:1000 / amount(Basin 流体槽容量) +// 4. 输出流体:1000 / amount +// 取以上最小值作为 maxMultiplier,向下取整后使用 +// ============================================================================ ServerEvents.recipes(event => { console.info('[生物柴油修复] 开始批量转换TFC密封大桶配方为Create发酵配方...'); - let convertedCount = 0; - let skippedCount = 0; + let convertedCount = 0; // 成功转换的配方数 + let skippedCount = 0; // 跳过的配方数 + // 遍历所有 TFC 密封大桶配方 event.forEachRecipe({ type: 'tfc:barrel_sealed' }, recipe => { const json = recipe.json; + // 1. 提取配方的输入输出数据 let inputItem = null; if (json.has('input_item')) { inputItem = JSON.parse(json.get('input_item').toString()); @@ -31,7 +58,11 @@ ServerEvents.recipes(event => { outputFluid = JSON.parse(json.get('output_fluid').toString()); } - // 检查输入物品堆叠数量 + // 2. 计算最大倍增倍数 maxMultiplier + const FLUID_SLOT_LIMIT = 1000; // Basin 流体槽最大容量 + let maxMultiplier = Infinity; // 初始值设为无穷大 + + // 2.1 根据输入物品堆叠限制计算 if (inputItem) { let itemId = inputItem.item || inputItem.tag; if (itemId) { @@ -39,134 +70,128 @@ ServerEvents.recipes(event => { try { let maxStack; if (inputItem.tag) { + // 处理标签类型,取标签中堆叠最小的物品 let tagItems = Ingredient.of(`#${inputItem.tag}`).items; if (tagItems && tagItems.length > 0) { - let minStack = tagItems[0].maxStack; + let minStack = tagItems[0].getMaxStackSize(); for (let i = 1; i < tagItems.length; i++) { - if (tagItems[i].maxStack < minStack) { - minStack = tagItems[i].maxStack; + if (tagItems[i].getMaxStackSize() < minStack) { + minStack = tagItems[i].getMaxStackSize(); } } maxStack = minStack; } } else { - maxStack = Item.of(itemId, 1).items[0].maxStack; + // 处理单个物品 + maxStack = Item.of(itemId, 1).getMaxStackSize(); } - if (maxStack && count > maxStack) { - skippedCount++; - return; + if (maxStack) { + maxMultiplier = Math.min(maxMultiplier, maxStack / count); } } catch (e) { - if (count > 64) { - skippedCount++; - return; - } + // 获取失败时使用默认值 64 + maxMultiplier = Math.min(maxMultiplier, 64 / count); } } } - - // 检查输出物品堆叠数量 + + // 2.2 根据输出物品堆叠限制计算 if (outputItem) { let outputId = outputItem.id || outputItem.item; if (outputId) { let count = outputItem.count || 1; try { - let maxStack = Item.of(outputId, 1).items[0].maxStack; - if (maxStack && count > maxStack) { - skippedCount++; - return; + let maxStack = Item.of(outputId, 1).getMaxStackSize(); + if (maxStack) { + maxMultiplier = Math.min(maxMultiplier, maxStack / count); } } catch (e) { - if (count > 64) { - skippedCount++; - return; - } + maxMultiplier = Math.min(maxMultiplier, 64 / count); } } } - - // 检查流体量 - if (inputFluid && inputFluid.amount > 1000) { - skippedCount++; - return; + + // 2.3 根据输入流体限制计算 + if (inputFluid && inputFluid.amount > 0) { + maxMultiplier = Math.min(maxMultiplier, FLUID_SLOT_LIMIT / inputFluid.amount); + } + + // 2.4 根据输出流体限制计算 + if (outputFluid && outputFluid.amount > 0) { + maxMultiplier = Math.min(maxMultiplier, FLUID_SLOT_LIMIT / outputFluid.amount); } - if (outputFluid && outputFluid.amount > 1000) { + + // 3. 确定最终倍增倍数(向下取整) + let flooredMultiplier = Math.floor(maxMultiplier); + + // 4. 过滤条件检查 + // 4.1 倍数小于1则跳过(无法倍增) + if (flooredMultiplier < 1) { skippedCount++; return; } - // 跳过modifiers + // 4.2 跳过带有 modifiers 的配方(复杂逻辑暂不处理) if (outputItem && outputItem.modifiers) { skippedCount++; return; } + // 5. 构建新配方的 ingredients 和 results let sealTime = json.has('seal_time') ? json.get('seal_time').getAsInt() : 0; let ingredients = []; let results = []; - // 添加输入物品 + // 5.1 添加输入物品(核心:用数组重复实现倍增) if (inputItem) { if (inputItem.type === 'tfc:and' && inputItem.children) { - let count = inputItem.count || 1; - for (let i = 0; i < count; i++) { + // 情况A:原始配方已有 tfc:and 结构(如带 not_rotten 条件的食物) + // 直接重复整个 tfc:and 对象 N 次(保留原始条件) + for (let i = 0; i < flooredMultiplier; i++) { ingredients.push({ type: 'tfc:and', children: inputItem.children }); } } else { - let itemId = inputItem.item || inputItem.tag; - if (itemId && typeof itemId === 'string' && itemId.includes('food/')) { - let count = inputItem.count || 1; - for (let i = 0; i < count; i++) { - ingredients.push({ - type: 'tfc:and', - children: [ - inputItem.item ? { item: inputItem.item } : { tag: inputItem.tag }, - { type: 'tfc:not_rotten' } - ] - }); - } - } else { - let count = inputItem.count || 1; + // 情况B:普通物品(包括食物类但没有显式 not_rotten 条件的) + // 直接重复 N 次,不添加额外条件(尊重原始配方意图) + for (let i = 0; i < flooredMultiplier; i++) { if (inputItem.item) { - for (let i = 0; i < count; i++) { - ingredients.push({ item: inputItem.item }); - } + ingredients.push({ item: inputItem.item }); } else if (inputItem.tag) { - for (let i = 0; i < count; i++) { - ingredients.push({ tag: inputItem.tag }); - } + ingredients.push({ tag: inputItem.tag }); } } } } - // 添加输入流体 + // 5.2 添加输入流体(用 amount 属性倍增) if (inputFluid) { - if (inputFluid.fluid && inputFluid.amount > 0) { + let amount = inputFluid.amount * flooredMultiplier; + if (inputFluid.fluid && amount > 0) { ingredients.push({ type: 'fluid_stack', fluid: inputFluid.fluid, - amount: inputFluid.amount + amount: amount }); - } else if (inputFluid.tag && inputFluid.amount > 0) { + } else if (inputFluid.tag && amount > 0) { ingredients.push({ type: 'fluid_tag', fluid_tag: inputFluid.tag, - amount: inputFluid.amount + amount: amount }); } } - // 添加输出物品 + // 5.3 添加输出物品(用 count 属性倍增) if (outputItem) { let itemId = outputItem.id || outputItem.item; if (itemId) { let singleResult = { id: itemId }; - if (outputItem.count && outputItem.count > 1) { - singleResult.count = outputItem.count; + let outputCount = (outputItem.count || 1) * flooredMultiplier; + if (outputCount > 1) { + singleResult.count = outputCount; } if (outputItem.chance) { singleResult.chance = outputItem.chance; @@ -174,32 +199,36 @@ ServerEvents.recipes(event => { results.push(singleResult); } } - - // 添加输出流体 + + // 5.4 添加输出流体(用 amount 属性倍增) if (outputFluid) { let fluidId = outputFluid.id || outputFluid.fluid; if (fluidId && outputFluid.amount > 0) { results.push({ id: fluidId, - amount: outputFluid.amount + amount: outputFluid.amount * flooredMultiplier }); } } + // 6. 计算处理时间(转换 TFC 时间单位到 Create 时间单位) let processingTime = Math.max(100, Math.round(sealTime / 5)); - + let multStr = flooredMultiplier.toString(); + + // 7. 创建并注册新配方 if (results.length > 0 && ingredients.length > 0) { event.custom({ type: 'createdieselgenerators:basin_fermenting', ingredients: ingredients, processing_time: processingTime, results: results - }).id(`kubejs:tfc_barrel_sealed/${recipe.getId().replace(':', '_')}`); + }).id(`kubejs:tfc_barrel_sealed/${multStr}_${recipe.getId().replace(':', '_')}`); convertedCount++; } else { skippedCount++; } }); + // 输出统计信息 console.info(`[生物柴油修复] 完成!共转换 ${convertedCount} 个配方,跳过 ${skippedCount} 个`); }); diff --git a/server_scripts/test_basin_fermenting_schema.js.faild b/server_scripts/test_basin_fermenting_schema.js.faild new file mode 100644 index 0000000..65eebab --- /dev/null +++ b/server_scripts/test_basin_fermenting_schema.js.faild @@ -0,0 +1,67 @@ +// ============================================================================ +// 测试脚本:使用 basin_fermenting 配方 schema +// ============================================================================ + +ServerEvents.recipes(event => { + console.info('[DEBUG] 开始测试 basin_fermenting 配方 schema...'); + + // 测试物品 + let testItemId = 'tfc:food/barley_flour'; + + // 获取堆叠限制 + let actualMaxStack = 64; + try { + actualMaxStack = Item.of(testItemId, 1).getMaxStackSize(); + console.info(`[DEBUG] 获取到 ${testItemId} 的堆叠限制 = ${actualMaxStack}`); + } catch (e) { + console.info(`[DEBUG] 获取堆叠限制失败: ${e.message},使用默认值 64`); + } + + let FLUID_SLOT_LIMIT = 1000; + let maxMultiplier = Infinity; + + // 输入物品: barley_flour, count = 1 + let itemCount = 1; + let itemMultiplier = actualMaxStack / itemCount; + maxMultiplier = Math.min(maxMultiplier, itemMultiplier); + console.info('[DEBUG] 输入物品: ' + testItemId + ', count=' + itemCount + ', maxStack=' + actualMaxStack + ', multiplier=' + itemMultiplier.toFixed(2)); + + // 输入流体: water, amount = 500 + let inputFluidAmount = 500; + let inputFluidMultiplier = FLUID_SLOT_LIMIT / inputFluidAmount; + maxMultiplier = Math.min(maxMultiplier, inputFluidMultiplier); + console.info('[DEBUG] 输入流体: minecraft:water, amount=' + inputFluidAmount + ', multiplier=' + inputFluidMultiplier.toFixed(2)); + + // 输出流体: beer, amount = 500 + let outputFluidAmount = 500; + let outputFluidMultiplier = FLUID_SLOT_LIMIT / outputFluidAmount; + maxMultiplier = Math.min(maxMultiplier, outputFluidMultiplier); + console.info('[DEBUG] 输出流体: tfc:beer, amount=' + outputFluidAmount + ', multiplier=' + outputFluidMultiplier.toFixed(2)); + + let flooredMultiplier = Math.floor(maxMultiplier); + console.info('[DEBUG] 向下取整 flooredMultiplier = ' + flooredMultiplier); + + // 创建测试配方 - 使用新的配方 schema + if (flooredMultiplier >= 1) { + console.info('[DEBUG] 创建测试配方...'); + + let inputItemCount = 1 * flooredMultiplier; + let finalInputFluidAmount = 500 * flooredMultiplier; + let finalOutputFluidAmount = 500 * flooredMultiplier; + + event.recipes.createdieselgenerators.basinFermenting([ + Ingredient.of({ + type: 'tfc:and', + children: [ + { item: testItemId }, + { type: 'tfc:not_rotten' } + ] + }, inputItemCount), + Fluid.of('minecraft:water', finalInputFluidAmount) + ], [ + Fluid.of('tfc:beer', finalOutputFluidAmount) + ]).id('kubejs:test_fermenting/beer/' + flooredMultiplier + '_from_barley_flour'); + + console.info('[DEBUG] 成功创建配方: kubejs:test_fermenting/beer/' + flooredMultiplier + '_from_barley_flour'); + } +}); diff --git a/server_scripts/test_maxstack_debug.js.pass b/server_scripts/test_maxstack_debug.js.pass new file mode 100644 index 0000000..823eda1 --- /dev/null +++ b/server_scripts/test_maxstack_debug.js.pass @@ -0,0 +1,138 @@ +// ============================================================================ +// 调试脚本:测试获取 tfc:food/barley_flour 的最大堆叠数量 +// ============================================================================ +// 以下注释内容将辅助正式脚本修改过程,不允许删除 +// 重要发现: +// 1. maxMultiplier 初始值问题: +// - 错误:let maxMultiplier = 1.0; +// - 正确:let maxMultiplier = Infinity; +// - 原因:使用 Math.min() 取最小值时,初始值必须大于所有可能的乘数 +// - 示例:若乘数为 64, 2, 2,初始值为 1 会导致结果始终为 1 +// +// 2. 获取堆叠限制的方法: +// - Item.of().getMaxStackSize() 实际上能返回正确的值(包括 TFC 的 Weight 组件影响) +// - 测试结果:barley_flour 返回 32,符合预期 +// +// 3. 新发现 (2026-05-16): +// - event.recipes.createdieselgenerators.basinFermenting() 路线失败 +// - 直接使用 event.custom() 配合 { type: 'tfc:and', children: [...] } 结构成功 +// - 关键:用数组重复代替数量倍增 +// 例如 flooredMultiplier = 2 时,把 { type: 'tfc:and', children: [...] } 重复2次 +// ============================================================================ + +ServerEvents.recipes(event => { + console.info('[DEBUG] ============================================'); + console.info('[DEBUG] 测试配方1: TFC酿酒 (barley_flour + water -> beer)'); + console.info('[DEBUG] ============================================'); + + let testItemId1 = 'tfc:food/barley_flour'; + let inputFluidId1 = 'minecraft:water'; + let outputFluidId1 = 'tfc:beer'; + let inputFluidAmount1 = 500; + let outputFluidAmount1 = 500; + let inputItemCount1 = 1; + + let actualMaxStack1 = Item.of(testItemId1, 1).getMaxStackSize(); + console.info(`[DEBUG] ${testItemId1} 堆叠限制 = ${actualMaxStack1}`); + + let FLUID_SLOT_LIMIT = 1000; + let maxMultiplier1 = Infinity; + let itemMultiplier1 = actualMaxStack1 / inputItemCount1; + let fluidMultiplier1 = FLUID_SLOT_LIMIT / inputFluidAmount1; + let outputFluidMultiplier1 = FLUID_SLOT_LIMIT / outputFluidAmount1; + maxMultiplier1 = Math.min(maxMultiplier1, itemMultiplier1, fluidMultiplier1, outputFluidMultiplier1); + + let flooredMultiplier1 = Math.floor(maxMultiplier1); + console.info(`[DEBUG] maxMultiplier=${maxMultiplier1.toFixed(2)}, flooredMultiplier=${flooredMultiplier1}`); + + if (flooredMultiplier1 >= 1) { + let ingredients1 = []; + let results1 = []; + + // 用数组重复实现物品倍增 + for (let i = 0; i < flooredMultiplier1; i++) { + ingredients1.push({ + type: 'tfc:and', + children: [ + { item: testItemId1 }, + { type: 'tfc:not_rotten' } + ] + }); + } + + // 流体倍增用 amount + ingredients1.push({ + type: 'fluid_stack', + fluid: inputFluidId1, + amount: inputFluidAmount1 * flooredMultiplier1 + }); + + // 输出流体 + results1.push({ + id: outputFluidId1, + amount: outputFluidAmount1 * flooredMultiplier1 + }); + + console.info(`[DEBUG] 创建配方1: ${flooredMultiplier1}x ${testItemId1} + ${inputFluidAmount1 * flooredMultiplier1}mB water -> ${outputFluidAmount1 * flooredMultiplier1}mB beer`); + + event.custom({ + type: 'createdieselgenerators:basin_fermenting', + ingredients: ingredients1, + processing_time: 400, + results: results1 + }).id(`kubejs:test_fermenting/barley_flour_x${flooredMultiplier1}`); + } + + console.info('[DEBUG] ============================================'); + console.info('[DEBUG] 测试配方2: black_wool (white_wool + black_dye -> black_wool)'); + console.info('[DEBUG] ============================================'); + + let testItemId2 = 'minecraft:white_wool'; + let inputFluidId2 = 'tfc:black_dye'; + let outputItemId2 = 'minecraft:black_wool'; + let inputFluidAmount2 = 25; + let inputItemCount2 = 1; + + let actualMaxStack2 = Item.of(testItemId2, 1).getMaxStackSize(); + console.info(`[DEBUG] ${testItemId2} 堆叠限制 = ${actualMaxStack2}`); + + let maxMultiplier2 = Infinity; + let itemMultiplier2 = actualMaxStack2 / inputItemCount2; + let fluidMultiplier2 = FLUID_SLOT_LIMIT / inputFluidAmount2; + maxMultiplier2 = Math.min(maxMultiplier2, itemMultiplier2, fluidMultiplier2); + + let flooredMultiplier2 = Math.floor(maxMultiplier2); + console.info(`[DEBUG] maxMultiplier=${maxMultiplier2.toFixed(2)}, flooredMultiplier=${flooredMultiplier2}`); + + if (flooredMultiplier2 >= 1) { + let ingredients2 = []; + let results2 = []; + + // 用数组重复实现物品倍增 + for (let i = 0; i < flooredMultiplier2; i++) { + ingredients2.push({ item: testItemId2 }); + } + + // 流体倍增用 amount + ingredients2.push({ + type: 'fluid_stack', + fluid: inputFluidId2, + amount: inputFluidAmount2 * flooredMultiplier2 + }); + + // 输出物品 + results2.push({ + id: outputItemId2, + count: flooredMultiplier2 + }); + + console.info(`[DEBUG] 创建配方2: ${flooredMultiplier2}x ${testItemId2} + ${inputFluidAmount2 * flooredMultiplier2}mB ${inputFluidId2} -> ${flooredMultiplier2}x ${outputItemId2}`); + + event.custom({ + type: 'createdieselgenerators:basin_fermenting', + ingredients: ingredients2, + processing_time: 100, + results: results2 + }).id(`kubejs:test_fermenting/wool_x${flooredMultiplier2}`); + } +}); From 0ec1f0cd4f02df8a8964c73a32f28a36e71260d3 Mon Sep 17 00:00:00 2001 From: dalizi2333 Date: Sun, 17 May 2026 23:17:59 +0800 Subject: [PATCH 04/10] =?UTF-8?q?=E5=87=86=E5=A4=87=E8=BF=81=E7=A7=BB?= =?UTF-8?q?=E5=88=B0=E4=BA=91=E6=9C=8D=E5=8A=A1=E5=99=A8=E4=B8=8A=E5=BC=80?= =?UTF-8?q?=E5=8F=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../biodiesel_fix/fermenting_from_barrel.js | 234 --------- .../fermenting_from_barrel.js.disable | 424 +++++++++++++++++ .../biodiesel_fix/fermenting_test.js | 443 ++++++++++++++++++ 3 files changed, 867 insertions(+), 234 deletions(-) delete mode 100644 server_scripts/biodiesel_fix/fermenting_from_barrel.js create mode 100644 server_scripts/biodiesel_fix/fermenting_from_barrel.js.disable create mode 100644 server_scripts/biodiesel_fix/fermenting_test.js diff --git a/server_scripts/biodiesel_fix/fermenting_from_barrel.js b/server_scripts/biodiesel_fix/fermenting_from_barrel.js deleted file mode 100644 index 4ba1123..0000000 --- a/server_scripts/biodiesel_fix/fermenting_from_barrel.js +++ /dev/null @@ -1,234 +0,0 @@ -// ============================================================================ -// 批量从TFC密封大桶配方创建Create发酵配方 -// ============================================================================ -// -// 功能说明: -// - 遍历所有 TFC 密封大桶配方 (tfc:barrel_sealed) -// - 将其转换为 Create Diesel Generators 的 Basin Fermenting 配方 -// - 自动计算配方倍增倍数,实现高吞吐单次发酵 -// -// 核心技术难点与解决方案: -// ---------------------------------------------------------------------------- -// 问题:TFC 的 tfc:not_rotten 条件只能在 TFC 配方系统中解析 -// 当在 Create 配方中使用 { type: 'tfc:and', children: [...] } 结构时, -// 无法通过设置 count 属性实现数量倍增(会导致 JSON 解析错误) -// -// 解决方案:用数组重复代替 count 属性倍增 -// - 对于普通物品:重复 { item: 'xxx' } N 次 -// - 对于带条件的物品:重复 { type: 'tfc:and', children: [...] } N 次 -// - 流体和输出仍使用 amount/count 属性倍增(它们不受此限制) -// ---------------------------------------------------------------------------- -// -// 倍增倍数计算规则: -// 1. 输入物品:maxStack / count -// 2. 输出物品:maxStack / count -// 3. 输入流体:1000 / amount(Basin 流体槽容量) -// 4. 输出流体:1000 / amount -// 取以上最小值作为 maxMultiplier,向下取整后使用 -// ============================================================================ - -ServerEvents.recipes(event => { - console.info('[生物柴油修复] 开始批量转换TFC密封大桶配方为Create发酵配方...'); - - let convertedCount = 0; // 成功转换的配方数 - let skippedCount = 0; // 跳过的配方数 - - // 遍历所有 TFC 密封大桶配方 - event.forEachRecipe({ type: 'tfc:barrel_sealed' }, recipe => { - const json = recipe.json; - - // 1. 提取配方的输入输出数据 - let inputItem = null; - if (json.has('input_item')) { - inputItem = JSON.parse(json.get('input_item').toString()); - } - - let inputFluid = null; - if (json.has('input_fluid')) { - inputFluid = JSON.parse(json.get('input_fluid').toString()); - } - - let outputItem = null; - if (json.has('output_item')) { - outputItem = JSON.parse(json.get('output_item').toString()); - } - - let outputFluid = null; - if (json.has('output_fluid')) { - outputFluid = JSON.parse(json.get('output_fluid').toString()); - } - - // 2. 计算最大倍增倍数 maxMultiplier - const FLUID_SLOT_LIMIT = 1000; // Basin 流体槽最大容量 - let maxMultiplier = Infinity; // 初始值设为无穷大 - - // 2.1 根据输入物品堆叠限制计算 - if (inputItem) { - let itemId = inputItem.item || inputItem.tag; - if (itemId) { - let count = inputItem.count || 1; - try { - let maxStack; - if (inputItem.tag) { - // 处理标签类型,取标签中堆叠最小的物品 - let tagItems = Ingredient.of(`#${inputItem.tag}`).items; - if (tagItems && tagItems.length > 0) { - let minStack = tagItems[0].getMaxStackSize(); - for (let i = 1; i < tagItems.length; i++) { - if (tagItems[i].getMaxStackSize() < minStack) { - minStack = tagItems[i].getMaxStackSize(); - } - } - maxStack = minStack; - } - } else { - // 处理单个物品 - maxStack = Item.of(itemId, 1).getMaxStackSize(); - } - if (maxStack) { - maxMultiplier = Math.min(maxMultiplier, maxStack / count); - } - } catch (e) { - // 获取失败时使用默认值 64 - maxMultiplier = Math.min(maxMultiplier, 64 / count); - } - } - } - - // 2.2 根据输出物品堆叠限制计算 - if (outputItem) { - let outputId = outputItem.id || outputItem.item; - if (outputId) { - let count = outputItem.count || 1; - try { - let maxStack = Item.of(outputId, 1).getMaxStackSize(); - if (maxStack) { - maxMultiplier = Math.min(maxMultiplier, maxStack / count); - } - } catch (e) { - maxMultiplier = Math.min(maxMultiplier, 64 / count); - } - } - } - - // 2.3 根据输入流体限制计算 - if (inputFluid && inputFluid.amount > 0) { - maxMultiplier = Math.min(maxMultiplier, FLUID_SLOT_LIMIT / inputFluid.amount); - } - - // 2.4 根据输出流体限制计算 - if (outputFluid && outputFluid.amount > 0) { - maxMultiplier = Math.min(maxMultiplier, FLUID_SLOT_LIMIT / outputFluid.amount); - } - - // 3. 确定最终倍增倍数(向下取整) - let flooredMultiplier = Math.floor(maxMultiplier); - - // 4. 过滤条件检查 - // 4.1 倍数小于1则跳过(无法倍增) - if (flooredMultiplier < 1) { - skippedCount++; - return; - } - - // 4.2 跳过带有 modifiers 的配方(复杂逻辑暂不处理) - if (outputItem && outputItem.modifiers) { - skippedCount++; - return; - } - - // 5. 构建新配方的 ingredients 和 results - let sealTime = json.has('seal_time') ? json.get('seal_time').getAsInt() : 0; - let ingredients = []; - let results = []; - - // 5.1 添加输入物品(核心:用数组重复实现倍增) - if (inputItem) { - if (inputItem.type === 'tfc:and' && inputItem.children) { - // 情况A:原始配方已有 tfc:and 结构(如带 not_rotten 条件的食物) - // 直接重复整个 tfc:and 对象 N 次(保留原始条件) - for (let i = 0; i < flooredMultiplier; i++) { - ingredients.push({ - type: 'tfc:and', - children: inputItem.children - }); - } - } else { - // 情况B:普通物品(包括食物类但没有显式 not_rotten 条件的) - // 直接重复 N 次,不添加额外条件(尊重原始配方意图) - for (let i = 0; i < flooredMultiplier; i++) { - if (inputItem.item) { - ingredients.push({ item: inputItem.item }); - } else if (inputItem.tag) { - ingredients.push({ tag: inputItem.tag }); - } - } - } - } - - // 5.2 添加输入流体(用 amount 属性倍增) - if (inputFluid) { - let amount = inputFluid.amount * flooredMultiplier; - if (inputFluid.fluid && amount > 0) { - ingredients.push({ - type: 'fluid_stack', - fluid: inputFluid.fluid, - amount: amount - }); - } else if (inputFluid.tag && amount > 0) { - ingredients.push({ - type: 'fluid_tag', - fluid_tag: inputFluid.tag, - amount: amount - }); - } - } - - // 5.3 添加输出物品(用 count 属性倍增) - if (outputItem) { - let itemId = outputItem.id || outputItem.item; - if (itemId) { - let singleResult = { id: itemId }; - let outputCount = (outputItem.count || 1) * flooredMultiplier; - if (outputCount > 1) { - singleResult.count = outputCount; - } - if (outputItem.chance) { - singleResult.chance = outputItem.chance; - } - results.push(singleResult); - } - } - - // 5.4 添加输出流体(用 amount 属性倍增) - if (outputFluid) { - let fluidId = outputFluid.id || outputFluid.fluid; - if (fluidId && outputFluid.amount > 0) { - results.push({ - id: fluidId, - amount: outputFluid.amount * flooredMultiplier - }); - } - } - - // 6. 计算处理时间(转换 TFC 时间单位到 Create 时间单位) - let processingTime = Math.max(100, Math.round(sealTime / 5)); - let multStr = flooredMultiplier.toString(); - - // 7. 创建并注册新配方 - if (results.length > 0 && ingredients.length > 0) { - event.custom({ - type: 'createdieselgenerators:basin_fermenting', - ingredients: ingredients, - processing_time: processingTime, - results: results - }).id(`kubejs:tfc_barrel_sealed/${multStr}_${recipe.getId().replace(':', '_')}`); - convertedCount++; - } else { - skippedCount++; - } - }); - - // 输出统计信息 - console.info(`[生物柴油修复] 完成!共转换 ${convertedCount} 个配方,跳过 ${skippedCount} 个`); -}); diff --git a/server_scripts/biodiesel_fix/fermenting_from_barrel.js.disable b/server_scripts/biodiesel_fix/fermenting_from_barrel.js.disable new file mode 100644 index 0000000..d344627 --- /dev/null +++ b/server_scripts/biodiesel_fix/fermenting_from_barrel.js.disable @@ -0,0 +1,424 @@ +// ============================================================================ +// 批量从TFC密封大桶配方创建Create发酵配方(策略模式重构版) +// ============================================================================ +// +// 策略模式实现: +// 1. 分析配方属性,添加策略标记(strategy type) +// 2. 注册不同策略的处理函数 +// 3. 执行时根据标记自动选择并执行对应策略 +// ============================================================================ + +// ============================================================================ +// 策略注册表 +// ============================================================================ +var recipeStrategies = {}; + +// 注册策略 +function registerStrategy(name, condition, handler) { + recipeStrategies[name] = { + condition: condition, + handler: handler + }; +} + +// ============================================================================ +// 数据结构定义 +// ============================================================================ + +// 配方转换器数据 +function createConverterData(event) { + return { + event: event, + stats: { + basin: 0, + bulk: 0, + skipped: 0 + }, + FLUID_SLOT_LIMIT: 1000 + }; +} + +// 配方数据对象(添加策略标记) +function createRecipeData(json, data, recipe) { + var result = { + inputItem: null, + inputFluid: null, + outputItem: null, + outputFluid: null, + sealTime: 0, + maxMultiplier: Infinity, + flooredMultiplier: 0, + recipeId: recipe ? recipe.getId() : null, // 添加配方ID + bulkMultiplier: 0 // bulk 倍率标记 + }; + + // 提取数据 + result.inputItem = parseJsonField(json, 'input_item'); + result.inputFluid = parseJsonField(json, 'input_fluid'); + result.outputItem = parseJsonField(json, 'output_item'); + result.outputFluid = parseJsonField(json, 'output_fluid'); + // 支持 seal_time 和 duration 两种字段名 + if (json.has('seal_time')) { + result.sealTime = json.get('seal_time').getAsInt(); + } else if (json.has('duration')) { + result.sealTime = json.get('duration').getAsInt(); + } else { + result.sealTime = 0; + } + + return result; +} + +// ============================================================================ +// 工具函数 +// ============================================================================ + +// 解析 JSON 字段 +function parseJsonField(json, fieldName) { + if (json.has(fieldName)) { + try { + return JSON.parse(json.get(fieldName).toString()); + } catch (e) { + return null; + } + } + return null; +} + +// 获取物品最大堆叠数 +function getMaxStackSize(itemData) { + var itemId = itemData.item || itemData.tag; + if (!itemId) return null; + + try { + if (itemData.tag) { + var tagItems = Ingredient.of('#' + itemData.tag).items; + if (tagItems && tagItems.length > 0) { + var minStack = tagItems[0].getMaxStackSize(); + for (var i = 1; i < tagItems.length; i++) { + if (tagItems[i].getMaxStackSize() < minStack) { + minStack = tagItems[i].getMaxStackSize(); + } + } + return minStack; + } + } else { + return Item.of(itemId, 1).getMaxStackSize(); + } + } catch (e) { + return 64; + } + return null; +} + +// 计算最大倍增倍数 +function calculateMaxMultiplier(recipeData, data) { + var maxMultiplier = Infinity; + + if (recipeData.inputItem) { + var itemId = recipeData.inputItem.item || recipeData.inputItem.tag; + if (itemId) { + var count = recipeData.inputItem.count || 1; + var maxStack = getMaxStackSize(recipeData.inputItem); + if (maxStack) { + maxMultiplier = Math.min(maxMultiplier, maxStack / count); + } + } + } + + if (recipeData.outputItem) { + var outputId = recipeData.outputItem.id || recipeData.outputItem.item; + if (outputId) { + var count = recipeData.outputItem.count || 1; + try { + var maxStack = Item.of(outputId, 1).getMaxStackSize(); + if (maxStack) { + maxMultiplier = Math.min(maxMultiplier, maxStack / count); + } + } catch (e) { + maxMultiplier = Math.min(maxMultiplier, 64 / count); + } + } + } + + if (recipeData.inputFluid && recipeData.inputFluid.amount > 0) { + maxMultiplier = Math.min(maxMultiplier, data.FLUID_SLOT_LIMIT / recipeData.inputFluid.amount); + } + + if (recipeData.outputFluid && recipeData.outputFluid.amount > 0) { + maxMultiplier = Math.min(maxMultiplier, data.FLUID_SLOT_LIMIT / recipeData.outputFluid.amount); + } + + return maxMultiplier; +} + +// 构建 ingredients +function buildIngredients(inputItem, inputFluid, multiplier) { + var ingredients = []; + + if (inputItem) { + if (inputItem.type === 'tfc:and' && inputItem.children) { + for (var i = 0; i < multiplier; i++) { + ingredients.push({ + type: 'tfc:and', + children: inputItem.children + }); + } + } else { + for (var i = 0; i < multiplier; i++) { + if (inputItem.item) { + ingredients.push({ item: inputItem.item }); + } else if (inputItem.tag) { + ingredients.push({ tag: inputItem.tag }); + } + } + } + } + + if (inputFluid) { + var amount = inputFluid.amount * multiplier; + if (inputFluid.fluid && amount > 0) { + ingredients.push({ + type: 'fluid_stack', + fluid: inputFluid.fluid, + amount: amount + }); + } else if (inputFluid.tag && amount > 0) { + ingredients.push({ + type: 'fluid_tag', + fluid_tag: inputFluid.tag, + amount: amount + }); + } + } + + return ingredients; +} + +// 构建 results +function buildResults(outputItem, outputFluid, multiplier) { + var results = []; + + if (outputItem) { + var itemId = outputItem.id || outputItem.item; + if (itemId) { + var singleResult = { id: itemId }; + var outputCount = (outputItem.count || 1) * multiplier; + if (outputCount > 1) { + singleResult.count = outputCount; + } + if (outputItem.chance) { + singleResult.chance = outputItem.chance; + } + results.push(singleResult); + } + } + + if (outputFluid) { + var fluidId = outputFluid.id || outputFluid.fluid; + if (fluidId && outputFluid.amount > 0) { + results.push({ + id: fluidId, + amount: outputFluid.amount * multiplier + }); + } + } + + return results; +} + +// ============================================================================ +// 策略:配方分析(添加标记) +// ============================================================================ + +// 策略1:检查原配方输入物品数,计算 bulk 倍率 +registerStrategy('bulk_multiplier_check', function(recipeData) { + // 计算原配方输入物品数 + var originalItemCount = 0; + if (recipeData.inputItem) { + originalItemCount = 1; + } + + // 计算 bulk 倍率:floor(9 / 原物品数) + var bulkMultiplier = Math.floor(9 / originalItemCount); + + // 将倍率存储到 recipeData 中(作为标记) + recipeData.bulkMultiplier = bulkMultiplier; + + // 如果倍率 > 0,则 bulk_fermenting 可用 + return bulkMultiplier > 0; +}, function(data, recipe, recipeData) { + // 这个策略只是添加标记,不做实际处理 + return false; // 继续后续策略 +}); + +// 策略2:检查特殊配方(如 mortar,输出过多需要限制倍率) +registerStrategy('bulk_special_recipe', function(recipeData) { + // 直接判断配方ID + if (recipeData.recipeId === 'tfc:barrel/mortar') { + recipeData.bulkMultiplier = 6; // 特殊倍率 + return true; + } + return false; +}, function(data, recipe, recipeData) { + // 标记已添加,不做实际处理 + return false; +}); + +// 策略2.1:检查陈酿酒配方(输出流体以 tfcagedalcohol:aged 开头) +registerStrategy('bulk_aged_alcohol', function(recipeData) { + // 检查输出流体ID是否以 tfcagedalcohol:aged 开头 + var fluidId = null; + if (recipeData.outputFluid) { + fluidId = recipeData.outputFluid.id || recipeData.outputFluid.fluid; + } + if (fluidId && fluidId.indexOf('tfcagedalcohol:aged') === 0) { + recipeData.bulkMultiplier = 3.6; // 陈酿酒倍率 + return true; + } + return false; +}, function(data, recipe, recipeData) { + // 标记已添加,不做实际处理 + return false; +}); + +// 策略3:检查是否需要跳过(带modifiers的配方) +registerStrategy('skip_modifiers', function(recipeData) { + return recipeData.outputItem && recipeData.outputItem.modifiers; +}, function(data, recipe, recipeData) { + data.stats.skipped++; + return true; // 已处理,不再执行后续策略 +}); + +// 策略4:Basin Fermenting(倍数 >= 1) +registerStrategy('basin_fermenting', function(recipeData) { + return recipeData.flooredMultiplier >= 1; +}, function(data, recipe, recipeData) { + var multiplier = recipeData.flooredMultiplier; + var ingredients = buildIngredients(recipeData.inputItem, recipeData.inputFluid, multiplier); + var results = buildResults(recipeData.outputItem, recipeData.outputFluid, multiplier); + + if (results.length === 0 || ingredients.length === 0) { + return false; + } + + var processingTime = Math.max(100, Math.round(recipeData.sealTime / 5)); + var multStr = multiplier.toString(); + + data.event.custom({ + type: 'createdieselgenerators:basin_fermenting', + ingredients: ingredients, + processing_time: processingTime, + results: results + }).id('kubejs:tfc_barrel_sealed/basin/' + multStr + '_' + recipe.getId().replace(':', '_')); + + data.stats.basin++; + return true; +}); + +// 策略5:Bulk Fermenting(使用 bulkMultiplier 标记) +registerStrategy('bulk_fermenting', function(recipeData) { + // 检查是否有 bulkMultiplier 标记且大于0 + return recipeData.bulkMultiplier && recipeData.bulkMultiplier > 0; +}, function(data, recipe, recipeData) { + // 使用标记的倍率(可能是特殊的6,也可能是计算的倍率) + var multiplier = recipeData.bulkMultiplier; + + var ingredients = buildIngredients(recipeData.inputItem, recipeData.inputFluid, multiplier); + var results = buildResults(recipeData.outputItem, recipeData.outputFluid, multiplier); + + if (results.length === 0 || ingredients.length === 0) { + return false; + } + + var processingTime = Math.max(100, Math.round(recipeData.sealTime / 4)); + var multStr = multiplier.toString(); + + data.event.custom({ + type: 'createdieselgenerators:bulk_fermenting', + ingredients: ingredients, + processing_time: processingTime, + results: results + }).id('kubejs:tfc_barrel_sealed/bulk/' + multStr + '_' + recipe.getId().replace(':', '_')); + + data.stats.bulk++; + return true; +}); + +// ============================================================================ +// 主流程 +// ============================================================================ + +// 分析配方并添加策略标记 +function analyzeRecipe(recipeData, data) { + // 计算倍数 + recipeData.maxMultiplier = calculateMaxMultiplier(recipeData, data); + recipeData.flooredMultiplier = Math.floor(recipeData.maxMultiplier); + + // 根据条件收集适用的策略 + recipeData.strategies = []; + for (var strategyName in recipeStrategies) { + if (recipeStrategies.hasOwnProperty(strategyName)) { + var strategy = recipeStrategies[strategyName]; + if (strategy.condition(recipeData)) { + recipeData.strategies.push(strategyName); + } + } + } +} + +// 执行配方的所有策略 +function executeStrategies(data, recipe, recipeData) { + for (var i = 0; i < recipeData.strategies.length; i++) { + var strategyName = recipeData.strategies[i]; + var strategy = recipeStrategies[strategyName]; + if (strategy) { + var result = strategy.handler(data, recipe, recipeData); + if (result === true) { + // 策略已处理,可以选择继续或中断 + // 这里可以根据需要决定是否继续 + } + } + } +} + +// 转换单个配方 +function convertSingleRecipe(data, recipe) { + var json = recipe.json; + + // 创建配方数据对象 + var recipeData = createRecipeData(json, data, recipe); + + // 过滤:跳过带modifiers的配方(快速检查) + if (recipeData.outputItem && recipeData.outputItem.modifiers) { + data.stats.skipped++; + return; + } + + // 分析配方,添加策略标记 + analyzeRecipe(recipeData, data); + + // 执行所有适用的策略 + executeStrategies(data, recipe, recipeData); +} + +// 批量转换 +function convertAllRecipes(data) { + console.info('[生物柴油修复] 开始批量转换TFC密封大桶配方...'); + + data.event.forEachRecipe({ type: 'tfc:barrel_sealed' }, function(recipe) { + convertSingleRecipe(data, recipe); + }); + + console.info('[生物柴油修复] 完成!Basin: ' + data.stats.basin + + ', Bulk: ' + data.stats.bulk + + ', 跳过: ' + data.stats.skipped); +} + +// ============================================================================ +// 执行 +// ============================================================================ +ServerEvents.recipes(function(event) { + var data = createConverterData(event); + convertAllRecipes(data); +}); diff --git a/server_scripts/biodiesel_fix/fermenting_test.js b/server_scripts/biodiesel_fix/fermenting_test.js new file mode 100644 index 0000000..9fbc95f --- /dev/null +++ b/server_scripts/biodiesel_fix/fermenting_test.js @@ -0,0 +1,443 @@ +// ============================================================================ +// 测试脚本:真正创建配方,测试完整方案 +// ============================================================================ + +ServerEvents.recipes(function(event) { + console.info('[测试] 开始测试4个示例配方(真正创建配方)...'); + + var stats = { basin: 0, bulk: 0, skipped: 0 }; + var FLUID_SLOT_LIMIT = 1000; + + // ============================================================================ + // 工具函数 + // ============================================================================ + + // 计算 basin 倍率:受限的物品堆叠数和流体<1000的同步物体与流体倍率 + function calculateBasinMultiplier(inputItem, inputFluid, outputItem, outputFluid) { + var maxMult = Infinity; + + // 输入物品堆叠限制 + if (inputItem) { + var itemCount = inputItem.count || 1; + var itemId = inputItem.item || inputItem.tag; + if (itemId) { + try { + var maxStack = 64; // 默认值 + if (inputItem.tag) { + var items = Ingredient.of('#' + inputItem.tag).items; + if (items && items.length > 0) { + maxStack = items[0].getMaxStackSize(); + } + } else { + maxStack = Item.of(itemId, 1).getMaxStackSize(); + } + maxMult = Math.min(maxMult, maxStack / itemCount); + } catch (e) { + maxMult = Math.min(maxMult, 64 / itemCount); + } + } + } + + // 输出物品堆叠限制 + if (outputItem) { + var itemCount = outputItem.count || 1; + var itemId = outputItem.id || outputItem.item; + if (itemId) { + try { + var maxStack = Item.of(itemId, 1).getMaxStackSize(); + maxMult = Math.min(maxMult, maxStack / itemCount); + } catch (e) { + maxMult = Math.min(maxMult, 64 / itemCount); + } + } + } + + // 输入流体限制(必须 < 1000) + if (inputFluid && inputFluid.amount > 0) { + maxMult = Math.min(maxMult, 1000 / inputFluid.amount); + } + + // 输出流体限制(必须 < 1000) + if (outputFluid && outputFluid.amount > 0) { + maxMult = Math.min(maxMult, 1000 / outputFluid.amount); + } + + return Math.floor(maxMult); + } + + function buildBasinIngredients(inputItem, inputFluid, multiplier) { + var ingredients = []; + + if (inputItem && multiplier > 0) { + for (var i = 0; i < multiplier; i++) { + if (inputItem.item) { + ingredients.push({ item: inputItem.item }); + } else if (inputItem.tag) { + ingredients.push({ tag: inputItem.tag }); + } + } + } + + if (inputFluid && multiplier > 0) { + var fluidAmount = inputFluid.amount * multiplier; + if (fluidAmount > 0) { + if (inputFluid.fluid) { + ingredients.push({ + type: 'fluid_stack', + fluid: inputFluid.fluid, + amount: fluidAmount + }); + } else if (inputFluid.tag) { + ingredients.push({ + type: 'fluid_tag', + fluid_tag: inputFluid.tag, + amount: fluidAmount + }); + } + } + } + + return ingredients; + } + + function buildBasinResults(outputItem, outputFluid, multiplier) { + var results = []; + + if (outputItem && multiplier > 0) { + var itemId = outputItem.id || outputItem.item; + if (itemId) { + var singleResult = { id: itemId }; + var outputCount = (outputItem.count || 1) * multiplier; + if (outputCount > 1) { + singleResult.count = outputCount; + } + results.push(singleResult); + } + } + + if (outputFluid && outputFluid.amount > 0 && multiplier > 0) { + var fluidId = outputFluid.id || outputFluid.fluid; + if (fluidId) { + var fluidAmount = outputFluid.amount * multiplier; + if (fluidAmount > 0) { + results.push({ + id: fluidId, + amount: fluidAmount + }); + } + } + } + + return results; + } + + function buildBulkIngredients(inputItem, inputFluid, bulkParams) { + var ingredients = []; + + if (inputItem) { + var itemMult = bulkParams.itemMultiplier; + for (var i = 0; i < itemMult; i++) { + if (inputItem.item) { + ingredients.push({ item: inputItem.item }); + } else if (inputItem.tag) { + ingredients.push({ tag: inputItem.tag }); + } + } + } + + if (inputFluid) { + var fluidAmount = inputFluid.amount * bulkParams.fluidMultiplier + bulkParams.fluidAddition; + if (fluidAmount > 0) { + if (inputFluid.fluid) { + ingredients.push({ + type: 'fluid_stack', + fluid: inputFluid.fluid, + amount: fluidAmount + }); + } else if (inputFluid.tag) { + ingredients.push({ + type: 'fluid_tag', + fluid_tag: inputFluid.tag, + amount: fluidAmount + }); + } + } + } + + return ingredients; + } + + function buildBulkResults(outputItem, outputFluid, bulkParams) { + var results = []; + + if (outputItem) { + var itemId = outputItem.id || outputItem.item; + if (itemId) { + var singleResult = { id: itemId }; + var outputCount = (outputItem.count || 1) * bulkParams.itemMultiplier; + if (outputCount > 1) { + singleResult.count = outputCount; + } + results.push(singleResult); + } + } + + if (outputFluid && outputFluid.amount >= 0) { + var fluidId = outputFluid.id || outputFluid.fluid; + if (fluidId) { + var fluidAmount = outputFluid.amount * bulkParams.fluidMultiplier + bulkParams.fluidAddition; + if (fluidAmount > 0) { + results.push({ + id: fluidId, + amount: fluidAmount + }); + } + } + } + + return results; + } + + // ============================================================================ + // 测试用例1:FirmaLife 奶酪 + // ============================================================================ + console.info('--- 测试1:FirmaLife 奶酪 ---'); + + var test1 = { + recipeId: 'firmalife:barrel/cheese', + duration: 1000, + input_item: { count: 1, item: 'firmalife:cheesecloth' }, + input_fluid: { amount: 1000, tag: 'firmalife:milks' }, + output_item: { count: 1, id: 'firmalife:cheesecloth' }, + output_fluid: { amount: 1000, id: 'firmalife:cream' } + }; + + // Basin倍率计算:min(64/1, 64/1, 1000/1000, 1000/1000) = 1 + var basinMult1 = calculateBasinMultiplier(test1.input_item, test1.input_fluid, test1.output_item, test1.output_fluid); + console.info('[测试1] Basin倍率: ' + basinMult1); + + var bulkParams1 = { + itemMultiplier: 9, + fluidMultiplier: 9, + fluidAddition: 0 + }; + + // Basin Fermenting(同步倍率) + var ingredients1_basin = buildBasinIngredients(test1.input_item, test1.input_fluid, basinMult1); + var results1_basin = buildBasinResults(test1.output_item, test1.output_fluid, basinMult1); + + event.custom({ + type: 'createdieselgenerators:basin_fermenting', + ingredients: ingredients1_basin, + processing_time: Math.max(100, Math.round(test1.duration / 5)), + results: results1_basin + }).id('kubejs:test/basin/firmalife_barrel_cheese'); + + stats.basin++; + console.info('[测试] 创建 Basin: ' + test1.recipeId); + console.info(' BasinMultiplier: ' + basinMult1); + console.info(' Ingredients: ' + JSON.stringify(ingredients1_basin)); + console.info(' Results: ' + JSON.stringify(results1_basin)); + + // Bulk Fermenting + var ingredients1_bulk = buildBulkIngredients(test1.input_item, test1.input_fluid, bulkParams1); + var results1_bulk = buildBulkResults(test1.output_item, test1.output_fluid, bulkParams1); + + event.custom({ + type: 'createdieselgenerators:bulk_fermenting', + ingredients: ingredients1_bulk, + processing_time: Math.max(100, Math.round(test1.duration / 4)), + results: results1_bulk + }).id('kubejs:test/bulk/firmalife_barrel_cheese'); + + stats.bulk++; + console.info('[测试] 创建 Bulk: ' + test1.recipeId); + console.info(' BulkParams: ' + JSON.stringify(bulkParams1)); + console.info(' Ingredients: ' + JSON.stringify(ingredients1_bulk)); + console.info(' Results: ' + JSON.stringify(results1_bulk)); + + // ============================================================================ + // 测试用例2:陈酿玉米威士忌 + // ============================================================================ + console.info('--- 测试2:陈酿玉米威士忌 ---'); + + var test2 = { + recipeId: 'tfc:barrel/aged_corn_whiskey', + duration: 691200, + input_fluid: { fluid: 'tfc:corn_whiskey', amount: 10000 }, + output_fluid: { id: 'tfcagedalcohol:aged_corn_whiskey', amount: 10000 } + }; + + // Basin倍率计算:min(1000/10000, 1000/10000) = 0.1 → floor = 0 + var basinMult2 = calculateBasinMultiplier(null, test2.input_fluid, null, test2.output_fluid); + console.info('[测试2] Basin倍率: ' + basinMult2); + + var bulkParams2 = { + itemMultiplier: 1, + fluidMultiplier: 3.6, + fluidAddition: 0 + }; + + // Basin Fermenting(倍率为0,不创建) + if (basinMult2 > 0) { + var ingredients2_basin = buildBasinIngredients(null, test2.input_fluid, basinMult2); + var results2_basin = buildBasinResults(null, test2.output_fluid, basinMult2); + + event.custom({ + type: 'createdieselgenerators:basin_fermenting', + ingredients: ingredients2_basin, + processing_time: Math.max(100, Math.round(test2.duration / 5)), + results: results2_basin + }).id('kubejs:test/basin/tfc_barrel_aged_corn_whiskey'); + + stats.basin++; + console.info('[测试] 创建 Basin: ' + test2.recipeId); + console.info(' BasinMultiplier: ' + basinMult2); + } else { + console.info('[测试] Basin倍率=0,跳过创建 Basin'); + } + + // Bulk Fermenting + var ingredients2_bulk = buildBulkIngredients(null, test2.input_fluid, bulkParams2); + var results2_bulk = buildBulkResults(null, test2.output_fluid, bulkParams2); + + event.custom({ + type: 'createdieselgenerators:bulk_fermenting', + ingredients: ingredients2_bulk, + processing_time: Math.max(100, Math.round(test2.duration / 4)), + results: results2_bulk + }).id('kubejs:test/bulk/tfc_barrel_aged_corn_whiskey'); + + stats.bulk++; + console.info('[测试] 创建 Bulk: ' + test2.recipeId); + console.info(' BulkParams: ' + JSON.stringify(bulkParams2)); + console.info(' Ingredients: ' + JSON.stringify(ingredients2_bulk)); + console.info(' Results: ' + JSON.stringify(results2_bulk)); + + // ============================================================================ + // 测试用例3:black_wool(无流体输出,需返还染料) + // ============================================================================ + console.info('--- 测试3:black_wool ---'); + + var test3 = { + recipeId: 'tfc:barrel/black_wool', + duration: 1200, + input_item: { count: 1, item: 'minecraft:white_wool' }, + input_fluid: { fluid: 'tfc:black_dye', amount: 25 }, + output_item: { count: 1, id: 'minecraft:black_wool' } + }; + + // Basin倍率计算:min(64/1, 1000/25) = 40 + var basinMult3 = calculateBasinMultiplier(test3.input_item, test3.input_fluid, test3.output_item, null); + console.info('[测试3] Basin倍率: ' + basinMult3); + + // 计算返还量:25 * 9 = 225, 1000 - 225 = 775 + var bulkParams3 = { + itemMultiplier: 9, + fluidMultiplier: 9, + fluidAddition: 775 + }; + + // 创建虚拟输出流体(用于buildBulkResults处理返还) + var virtualOutputFluid3 = { id: 'tfc:black_dye', amount: 0 }; + + // Basin Fermenting(无返还逻辑,因为 basin 倍率是受限计算出来的) + var ingredients3_basin = buildBasinIngredients(test3.input_item, test3.input_fluid, basinMult3); + var results3_basin = buildBasinResults(test3.output_item, null, basinMult3); + + if (results3_basin.length > 0 && ingredients3_basin.length > 0) { + event.custom({ + type: 'createdieselgenerators:basin_fermenting', + ingredients: ingredients3_basin, + processing_time: Math.max(100, Math.round(test3.duration / 5)), + results: results3_basin + }).id('kubejs:test/basin/tfc_barrel_black_wool'); + + stats.basin++; + console.info('[测试] 创建 Basin: ' + test3.recipeId); + console.info(' BasinMultiplier: ' + basinMult3); + console.info(' Ingredients: ' + JSON.stringify(ingredients3_basin)); + console.info(' Results: ' + JSON.stringify(results3_basin)); + } + + // Bulk Fermenting(有返还逻辑) + var ingredients3_bulk = buildBulkIngredients(test3.input_item, test3.input_fluid, bulkParams3); + var results3_bulk = buildBulkResults(test3.output_item, virtualOutputFluid3, bulkParams3); + + event.custom({ + type: 'createdieselgenerators:bulk_fermenting', + ingredients: ingredients3_bulk, + processing_time: Math.max(100, Math.round(test3.duration / 4)), + results: results3_bulk + }).id('kubejs:test/bulk/tfc_barrel_black_wool'); + + stats.bulk++; + console.info('[测试] 创建 Bulk: ' + test3.recipeId); + console.info(' BulkParams: ' + JSON.stringify(bulkParams3)); + console.info(' Ingredients: ' + JSON.stringify(ingredients3_bulk)); + console.info(' Results: ' + JSON.stringify(results3_bulk)); + + // ============================================================================ + // 测试用例4:mortar(特殊配方) + // ============================================================================ + console.info('--- 测试4:mortar ---'); + + var test4 = { + recipeId: 'tfc:barrel/mortar', + duration: 7200, + input_item: { count: 1, tag: 'c:sands' }, + input_fluid: { fluid: 'tfc:limewater', amount: 100 }, + output_item: { count: 16, id: 'tfc:mortar' } + }; + + // Basin倍率计算:min(64/1, 64/16, 1000/100) = 4 + var basinMult4 = calculateBasinMultiplier(test4.input_item, test4.input_fluid, test4.output_item, null); + console.info('[测试4] Basin倍率: ' + basinMult4); + + var bulkParams4 = { + itemMultiplier: 6, + fluidMultiplier: 6, + fluidAddition: 0 + }; + + // Basin Fermenting(倍率4,是受限计算得出的) + var ingredients4_basin = buildBasinIngredients(test4.input_item, test4.input_fluid, basinMult4); + var results4_basin = buildBasinResults(test4.output_item, null, basinMult4); + + if (results4_basin.length > 0 && ingredients4_basin.length > 0) { + event.custom({ + type: 'createdieselgenerators:basin_fermenting', + ingredients: ingredients4_basin, + processing_time: Math.max(100, Math.round(test4.duration / 5)), + results: results4_basin + }).id('kubejs:test/basin/tfc_barrel_mortar'); + + stats.basin++; + console.info('[测试] 创建 Basin: ' + test4.recipeId); + console.info(' BasinMultiplier: ' + basinMult4); + console.info(' Ingredients: ' + JSON.stringify(ingredients4_basin)); + console.info(' Results: ' + JSON.stringify(results4_basin)); + } + + // Bulk Fermenting(特殊倍率6) + var ingredients4_bulk = buildBulkIngredients(test4.input_item, test4.input_fluid, bulkParams4); + var results4_bulk = buildBulkResults(test4.output_item, null, bulkParams4); + + event.custom({ + type: 'createdieselgenerators:bulk_fermenting', + ingredients: ingredients4_bulk, + processing_time: Math.max(100, Math.round(test4.duration / 4)), + results: results4_bulk + }).id('kubejs:test/bulk/tfc_barrel_mortar'); + + stats.bulk++; + console.info('[测试] 创建 Bulk: ' + test4.recipeId); + console.info(' BulkParams: ' + JSON.stringify(bulkParams4)); + console.info(' Ingredients: ' + JSON.stringify(ingredients4_bulk)); + console.info(' Results: ' + JSON.stringify(results4_bulk)); + + // ============================================================================ + // 完成 + // ============================================================================ + console.info('[测试] 完成!Basin: ' + stats.basin + ', Bulk: ' + stats.bulk); +}); From 3d9eead0d9a052fcef7fd54df825c299378805d3 Mon Sep 17 00:00:00 2001 From: dalizi2333 Date: Mon, 18 May 2026 04:15:35 +0800 Subject: [PATCH 05/10] =?UTF-8?q?=E5=90=8C=E6=AD=A5=E5=AE=A2=E6=88=B7?= =?UTF-8?q?=E7=AB=AF20260518=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server_scripts/cbc_melting.js | 14 ++++----- server_scripts/event_recipes.js | 32 ++++++++++++++++---- server_scripts/tfc_compact.js | 52 +++++++++++++++++++++++++++++++++ 3 files changed, 86 insertions(+), 12 deletions(-) create mode 100644 server_scripts/tfc_compact.js diff --git a/server_scripts/cbc_melting.js b/server_scripts/cbc_melting.js index 0125eda..8c42fe8 100644 --- a/server_scripts/cbc_melting.js +++ b/server_scripts/cbc_melting.js @@ -2,13 +2,13 @@ ServerEvents.recipes(event => { event.forEachRecipe({ type: 'tfc:heating' }, recipe => { const json = recipe.json if (!json.has('result_fluid')) return - + const resultFluid = json.get('result_fluid') const ingredient = json.get('ingredient') - const ingredientArray = ingredient.isJsonArray() + const ingredientArray = ingredient.isJsonArray() ? JSON.parse(ingredient.toString()) : [JSON.parse(ingredient.toString())] - + const allValid = ingredientArray.every(ing => { if (ing.item) { return Item.exists(ing.item) @@ -18,16 +18,16 @@ ServerEvents.recipes(event => { } return false }) - + if (!allValid) return - + const temperature = json.has('temperature') ? json.get('temperature').getAsFloat() : 0 const heatRequirement = temperature > 1080 ? 'superheated' : 'heated' - + // 基准 1080°C → 20s (400 tick),1500°C → 30s (600 tick),线性插值 // 斜率: (600-400) / (1500-1080) ≈ 0.476 tick/°C const processingTime = Math.round(400 + (temperature - 1080) * (200 / 420)) - + event.custom({ type: 'createbigcannons:melting', heat_requirement: heatRequirement, diff --git a/server_scripts/event_recipes.js b/server_scripts/event_recipes.js index 5b070f1..862fccf 100644 --- a/server_scripts/event_recipes.js +++ b/server_scripts/event_recipes.js @@ -11,6 +11,33 @@ ServerEvents.recipes(event => { B: '#c:gravels' } ) + event.shaped( + Item.of('create:empty_blaze_burner'), + [ + ' A ', + 'ABC', + ' C ' + ], + { + A: '#c:sheets/red_steel', + B: '#c:gravels', + C: '#c:sheets/blue_steel' + } + ) + event.shaped( + Item.of('create:blaze_burner'), + [ + ' A ', + 'ABA', + ' C ' + ], + { + A: '#farmerstfc:magma_block', + B: 'tfc:blast_furnace', + C: 'create:empty_blaze_burner' + } + ) + event.shaped( Item.of('drivebywire:wire'), [ @@ -130,10 +157,5 @@ ServerEvents.recipes(event => { 'minecraft:blast_furnace', 'tfc:blast_furnace' ) - event.replaceInput( - { input: 'create:empty_blaze_burner' }, - 'create:empty_blaze_burner', - 'createlowheated:basic_burner' - ) }) \ No newline at end of file diff --git a/server_scripts/tfc_compact.js b/server_scripts/tfc_compact.js new file mode 100644 index 0000000..2a88aeb --- /dev/null +++ b/server_scripts/tfc_compact.js @@ -0,0 +1,52 @@ +ServerEvents.recipes(event => { + event.shapeless(Item.of('create:andesite_alloy', 8), + [ + '#c:cobblestones', + '#c:ingots/zinc' + ] + ) + event.shapeless(Item.of('create:andesite_alloy', 8), + [ + '#c:cobblestones', + '#c:ingots/iron' + ] + ) + + event.replaceInput( + { input: 'minecraft:slime_ball' }, + 'minecraft:slime_ball', + 'tfc:glue' + ) + + //metal + event.replaceInput( + { input: 'minecraft:iron_ingot' }, + 'minecraft:iron_ingot', + '#c:ingots/wrought_iron' + ) + event.replaceOutput( + { output: 'minecraft:iron_ingot' }, + 'minecraft:iron_ingot', + 'tfc:metal/ingot/wrought_iron' + ) + event.remove({ output: 'minecraft:iron_ingot' }) + event.remove({ output: 'minecraft:gold_ingot' }) + event.remove({ output: 'minecraft:gold_block' }) + event.remove({ output: 'create:brass_block' }) + + event.recipes.tfc.heating( + 'minecraft:iron_nugget', + 1500 + ).fluidOutput(Fluid.of('tfc:metal/cast_iron', 10)) + event.recipes.tfc.heating( + 'minecraft:iron_block', + 1500 + ).fluidOutput(Fluid.of('tfc:metal/cast_iron', 900)) + + + event.replaceInput( + { input: 'minecraft:blast_furnace' }, + 'minecraft:blast_furnace', + 'tfc:blast_furnace' + ) +}) From f20fde6d3cc730e0ca4216a63a2013009aadce76 Mon Sep 17 00:00:00 2001 From: dalizi2333 Date: Mon, 18 May 2026 09:04:14 +0000 Subject: [PATCH 06/10] =?UTF-8?q?=E5=AE=8C=E6=88=90=E4=BA=86=E5=AF=86?= =?UTF-8?q?=E5=B0=81=E5=A4=A7=E6=A1=B6=E9=85=8D=E6=96=B9=E8=BF=81=E7=A7=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...l.js.disable => fermenting_from_barrel.js} | 226 +++++++++++++++--- ...enting_test.js => fermenting_test.js.pass} | 0 2 files changed, 189 insertions(+), 37 deletions(-) rename server_scripts/biodiesel_fix/{fermenting_from_barrel.js.disable => fermenting_from_barrel.js} (56%) rename server_scripts/biodiesel_fix/{fermenting_test.js => fermenting_test.js.pass} (100%) diff --git a/server_scripts/biodiesel_fix/fermenting_from_barrel.js.disable b/server_scripts/biodiesel_fix/fermenting_from_barrel.js similarity index 56% rename from server_scripts/biodiesel_fix/fermenting_from_barrel.js.disable rename to server_scripts/biodiesel_fix/fermenting_from_barrel.js index d344627..9684eeb 100644 --- a/server_scripts/biodiesel_fix/fermenting_from_barrel.js.disable +++ b/server_scripts/biodiesel_fix/fermenting_from_barrel.js @@ -10,6 +10,9 @@ // ============================================================================ // 策略注册表 +// 每个策略包含:condition(recipeData) -> bool 用于判断是否适用 +// handler(data, recipe, recipeData) -> bool 返回true表示已处理,false表示继续 +// 策略按注册顺序执行,前面的策略可以为后面的策略添加标记数据(如bulkParams) // ============================================================================ var recipeStrategies = {}; @@ -25,20 +28,20 @@ function registerStrategy(name, condition, handler) { // 数据结构定义 // ============================================================================ -// 配方转换器数据 +// 配方转换器数据(贯穿整个转换流程的上下文对象) function createConverterData(event) { return { event: event, stats: { - basin: 0, - bulk: 0, - skipped: 0 + basin: 0, // Basin Fermenting 配方生成计数 + bulk: 0, // Bulk Fermenting 配方生成计数 + skipped: 0 // 跳过的配方计数(如带modifiers的配方) }, - FLUID_SLOT_LIMIT: 1000 + FLUID_SLOT_LIMIT: 1000 // Create流体槽上限 (mB) }; } -// 配方数据对象(添加策略标记) +// 配方数据对象(每个TFC配方对应一个实例,策略按需修改其字段) function createRecipeData(json, data, recipe) { var result = { inputItem: null, @@ -46,10 +49,15 @@ function createRecipeData(json, data, recipe) { outputItem: null, outputFluid: null, sealTime: 0, - maxMultiplier: Infinity, - flooredMultiplier: 0, - recipeId: recipe ? recipe.getId() : null, // 添加配方ID - bulkMultiplier: 0 // bulk 倍率标记 + maxMultiplier: Infinity, // 理论最大倍增倍数(受堆叠/流体槽限制) + flooredMultiplier: 0, // 向下取整后的倍数(用于Basin配方) + recipeId: recipe ? recipe.getId() : null, + // bulkParams 由各策略逐步修改,最终用于 Bulk Fermenting 配方生成 + bulkParams: { + itemMultiplier: 0, // 物品倍增倍率 + fluidMultiplier: 0, // 流体倍增倍率(可与物品倍率不同) + fluidAddition: 0 // 额外添加/返还的流体量 (mB) + } }; // 提取数据 @@ -86,6 +94,7 @@ function parseJsonField(json, fieldName) { } // 获取物品最大堆叠数 +// 当输入是tag时,取该tag下所有物品中最小的maxStackSize(保守估计,防止溢出) function getMaxStackSize(itemData) { var itemId = itemData.item || itemData.tag; if (!itemId) return null; @@ -111,7 +120,8 @@ function getMaxStackSize(itemData) { return null; } -// 计算最大倍增倍数 +// 计算最大倍增倍数(取输入物品/输出物品/输入流体/输出流体四项限制的最小值) +// 输入物品受堆叠上限约束,输出物品同理;流体受 FLUID_SLOT_LIMIT (1000mB) 约束 function calculateMaxMultiplier(recipeData, data) { var maxMultiplier = Infinity; @@ -152,7 +162,7 @@ function calculateMaxMultiplier(recipeData, data) { return maxMultiplier; } -// 构建 ingredients +// 构建 Basin Fermenting ingredients(物品和流体使用相同倍率) function buildIngredients(inputItem, inputFluid, multiplier) { var ingredients = []; @@ -195,7 +205,7 @@ function buildIngredients(inputItem, inputFluid, multiplier) { return ingredients; } -// 构建 results +// 构建 Basin Fermenting results(物品和流体使用相同倍率) function buildResults(outputItem, outputFluid, multiplier) { var results = []; @@ -227,11 +237,91 @@ function buildResults(outputItem, outputFluid, multiplier) { return results; } +// 构建 Bulk Fermenting ingredients(支持独立的物品和流体倍率,以及流体返还) +// fluidAddition 用于处理满池减益策略中返还剩余流体的场景 +function buildBulkIngredients(inputItem, inputFluid, bulkParams) { + var ingredients = []; + + if (inputItem) { + var itemMult = bulkParams.itemMultiplier; + for (var i = 0; i < itemMult; i++) { + if (inputItem.type === 'tfc:and' && inputItem.children) { + ingredients.push({ + type: 'tfc:and', + children: inputItem.children + }); + } else if (inputItem.item) { + ingredients.push({ item: inputItem.item }); + } else if (inputItem.tag) { + ingredients.push({ tag: inputItem.tag }); + } + } + } + + if (inputFluid) { + var fluidAmount = inputFluid.amount * bulkParams.fluidMultiplier + bulkParams.fluidAddition; + if (fluidAmount > 0) { + if (inputFluid.fluid) { + ingredients.push({ + type: 'fluid_stack', + fluid: inputFluid.fluid, + amount: fluidAmount + }); + } else if (inputFluid.tag) { + ingredients.push({ + type: 'fluid_tag', + fluid_tag: inputFluid.tag, + amount: fluidAmount + }); + } + } + } + + return ingredients; +} + +// 构建 Bulk Fermenting results(支持独立的物品和流体倍率,以及流体返还) +// outputFluid.amount >= 0 允许零量输出流体(用于满池减益策略的流体返还标记) +function buildBulkResults(outputItem, outputFluid, bulkParams) { + var results = []; + + if (outputItem) { + var itemId = outputItem.id || outputItem.item; + if (itemId) { + var singleResult = { id: itemId }; + var outputCount = (outputItem.count || 1) * bulkParams.itemMultiplier; + if (outputCount > 1) { + singleResult.count = outputCount; + } + if (outputItem.chance) { + singleResult.chance = outputItem.chance; + } + results.push(singleResult); + } + } + + if (outputFluid && outputFluid.amount >= 0) { + var fluidId = outputFluid.id || outputFluid.fluid; + if (fluidId) { + var fluidAmount = outputFluid.amount * bulkParams.fluidMultiplier + bulkParams.fluidAddition; + if (fluidAmount > 0) { + results.push({ + id: fluidId, + amount: fluidAmount + }); + } + } + } + + return results; +} + // ============================================================================ // 策略:配方分析(添加标记) // ============================================================================ -// 策略1:检查原配方输入物品数,计算 bulk 倍率 +// 策略1:计算 bulk 倍率(默认物品和流体同步倍率) +// 逻辑:原配方输入物品数决定每"组"大小,floor(9 / 原物品数) = 每批最多处理几组 registerStrategy('bulk_multiplier_check', function(recipeData) { // 计算原配方输入物品数 var originalItemCount = 0; @@ -240,23 +330,77 @@ registerStrategy('bulk_multiplier_check', function(recipeData) { } // 计算 bulk 倍率:floor(9 / 原物品数) - var bulkMultiplier = Math.floor(9 / originalItemCount); + var multiplier = Math.floor(9 / originalItemCount); - // 将倍率存储到 recipeData 中(作为标记) - recipeData.bulkMultiplier = bulkMultiplier; + // 将倍率参数存储到 recipeData 中(默认同步倍率) + recipeData.bulkParams.itemMultiplier = multiplier; + recipeData.bulkParams.fluidMultiplier = multiplier; + recipeData.bulkParams.fluidAddition = 0; // 如果倍率 > 0,则 bulk_fermenting 可用 - return bulkMultiplier > 0; + return multiplier > 0; }, function(data, recipe, recipeData) { // 这个策略只是添加标记,不做实际处理 return false; // 继续后续策略 }); -// 策略2:检查特殊配方(如 mortar,输出过多需要限制倍率) +// 策略2:流体增益(有流体输出的配方,流体倍率翻倍) +// 原因:输入和输出的流体独立占用流体槽,翻倍可以更好地利用槽位 +registerStrategy('bulk_fluid_bonus', function(recipeData) { + // 条件:有流体输出且输入流体量 > 0 + if (recipeData.outputFluid && recipeData.outputFluid.amount > 0 && + recipeData.inputFluid && recipeData.inputFluid.amount > 0) { + // 流体倍率 = 物品倍率 * 2(确保输入与输出流体同步倍增) + var itemMult = recipeData.bulkParams.itemMultiplier || 1; + recipeData.bulkParams.fluidMultiplier = itemMult * 2; + recipeData.bulkParams.fluidAddition = 0; + return true; + } + return false; +}, function(data, recipe, recipeData) { + // 标记已添加,不做实际处理 + return false; +}); + +// 策略2.1:满池减益(有输入流体但无输出流体,需返还剩余流体) +// 当输入流体 < 1000mB 且配方无输出流体时,bulk 后会产生"空余"流体槽 +// 此策略将剩余的流体返还到输出中(创造一个虚拟输出流体标记) +registerStrategy('bulk_fluid_return', function(recipeData) { + // 条件:有输入流体但无输出流体,且输入流体量 < 1000 + if (recipeData.inputFluid && recipeData.inputFluid.amount > 0 && + (!recipeData.outputFluid || recipeData.outputFluid.amount <= 0) && + recipeData.inputFluid.amount < 1000) { + // 计算返还量:1000 - (输入流体量 * itemMultiplier) + var inputAmount = recipeData.inputFluid.amount; + var itemMult = recipeData.bulkParams.itemMultiplier || 1; + var consumed = inputAmount * itemMult; + var returnAmount = 1000 - consumed; + + // 设置参数:流体倍率与物品倍率相同,添加返还量 + recipeData.bulkParams.fluidMultiplier = itemMult; + recipeData.bulkParams.fluidAddition = returnAmount; + + // 创建虚拟输出流体(用于buildBulkResults处理返还) + var fluidId = recipeData.inputFluid.fluid || recipeData.inputFluid.tag; + if (fluidId) { + recipeData.outputFluid = { id: fluidId, amount: 0 }; + } + + return true; + } + return false; +}, function(data, recipe, recipeData) { + // 标记已添加,不做实际处理 + return false; +}); + +// 策略2.2:特殊配方处理(如 mortar 输出过多,限制倍率为6防止溢出) registerStrategy('bulk_special_recipe', function(recipeData) { // 直接判断配方ID if (recipeData.recipeId === 'tfc:barrel/mortar') { - recipeData.bulkMultiplier = 6; // 特殊倍率 + recipeData.bulkParams.itemMultiplier = 6; // 特殊物品倍率 + recipeData.bulkParams.fluidMultiplier = 6; // 特殊流体倍率 + recipeData.bulkParams.fluidAddition = 0; return true; } return false; @@ -265,7 +409,8 @@ registerStrategy('bulk_special_recipe', function(recipeData) { return false; }); -// 策略2.1:检查陈酿酒配方(输出流体以 tfcagedalcohol:aged 开头) +// 策略2.3:陈酿酒配方(输出流体以 tfcagedalcohol:aged 开头) +// 陈酿酒需要特殊倍率:物品不倍增,仅流体按 3.6 倍处理 registerStrategy('bulk_aged_alcohol', function(recipeData) { // 检查输出流体ID是否以 tfcagedalcohol:aged 开头 var fluidId = null; @@ -273,7 +418,9 @@ registerStrategy('bulk_aged_alcohol', function(recipeData) { fluidId = recipeData.outputFluid.id || recipeData.outputFluid.fluid; } if (fluidId && fluidId.indexOf('tfcagedalcohol:aged') === 0) { - recipeData.bulkMultiplier = 3.6; // 陈酿酒倍率 + recipeData.bulkParams.itemMultiplier = 1; // 物品倍率1 + recipeData.bulkParams.fluidMultiplier = 3.6; // 陈酿酒流体倍率 + recipeData.bulkParams.fluidAddition = 0; return true; } return false; @@ -282,7 +429,7 @@ registerStrategy('bulk_aged_alcohol', function(recipeData) { return false; }); -// 策略3:检查是否需要跳过(带modifiers的配方) +// 策略3:跳过带 modifiers 的配方(如带有NBT标签的输出物,无法在Create配方中表达) registerStrategy('skip_modifiers', function(recipeData) { return recipeData.outputItem && recipeData.outputItem.modifiers; }, function(data, recipe, recipeData) { @@ -290,7 +437,8 @@ registerStrategy('skip_modifiers', function(recipeData) { return true; // 已处理,不再执行后续策略 }); -// 策略4:Basin Fermenting(倍数 >= 1) +// 策略4:Basin Fermenting(处理倍率 >= 1 的配方,物品流体同步倍率) +// 处理时间 = sealTime / 5(最少100tick),用于单槽批量发酵 registerStrategy('basin_fermenting', function(recipeData) { return recipeData.flooredMultiplier >= 1; }, function(data, recipe, recipeData) { @@ -316,23 +464,25 @@ registerStrategy('basin_fermenting', function(recipeData) { return true; }); -// 策略5:Bulk Fermenting(使用 bulkMultiplier 标记) +// 策略5:Bulk Fermenting(使用 bulkParams,物品和流体可独立倍率) +// 处理时间 = sealTime / 4(最少100tick),九个槽位同时发酵 registerStrategy('bulk_fermenting', function(recipeData) { - // 检查是否有 bulkMultiplier 标记且大于0 - return recipeData.bulkMultiplier && recipeData.bulkMultiplier > 0; + // 检查是否有有效的 bulkParams(itemMultiplier > 0) + return recipeData.bulkParams && recipeData.bulkParams.itemMultiplier > 0; }, function(data, recipe, recipeData) { - // 使用标记的倍率(可能是特殊的6,也可能是计算的倍率) - var multiplier = recipeData.bulkMultiplier; + // 获取 bulk 参数 + var bulkParams = recipeData.bulkParams; - var ingredients = buildIngredients(recipeData.inputItem, recipeData.inputFluid, multiplier); - var results = buildResults(recipeData.outputItem, recipeData.outputFluid, multiplier); + // 使用独立的构建函数处理 bulk 配方 + var ingredients = buildBulkIngredients(recipeData.inputItem, recipeData.inputFluid, bulkParams); + var results = buildBulkResults(recipeData.outputItem, recipeData.outputFluid, bulkParams); if (results.length === 0 || ingredients.length === 0) { return false; } var processingTime = Math.max(100, Math.round(recipeData.sealTime / 4)); - var multStr = multiplier.toString(); + var multStr = bulkParams.itemMultiplier.toString() + '_' + bulkParams.fluidMultiplier.toString(); data.event.custom({ type: 'createdieselgenerators:bulk_fermenting', @@ -349,7 +499,8 @@ registerStrategy('bulk_fermenting', function(recipeData) { // 主流程 // ============================================================================ -// 分析配方并添加策略标记 +// 分析配方:计算倍率,然后遍历所有策略的 condition,将适用的策略名存入 recipeData.strategies +// 注意:condition 可能有副作用(如修改 bulkParams),这是设计如此,用于策略间的数据传递 function analyzeRecipe(recipeData, data) { // 计算倍数 recipeData.maxMultiplier = calculateMaxMultiplier(recipeData, data); @@ -367,7 +518,8 @@ function analyzeRecipe(recipeData, data) { } } -// 执行配方的所有策略 +// 按 analyzeRecipe 收集的策略顺序执行所有 handler +// handler 返回 true 表示已处理(如 skip 策略),但目前不影响后续策略继续执行 function executeStrategies(data, recipe, recipeData) { for (var i = 0; i < recipeData.strategies.length; i++) { var strategyName = recipeData.strategies[i]; @@ -382,14 +534,13 @@ function executeStrategies(data, recipe, recipeData) { } } -// 转换单个配方 +// 转换单个配方:解析 → 快速过滤 → 分析策略 → 执行策略 function convertSingleRecipe(data, recipe) { var json = recipe.json; - // 创建配方数据对象 var recipeData = createRecipeData(json, data, recipe); - // 过滤:跳过带modifiers的配方(快速检查) + // 快速过滤:带modifiers的配方无法在Create中表达,提前跳过(与策略3重复但更高效) if (recipeData.outputItem && recipeData.outputItem.modifiers) { data.stats.skipped++; return; @@ -417,6 +568,7 @@ function convertAllRecipes(data) { // ============================================================================ // 执行 +// 入口:遍历所有 tfc:barrel_sealed 配方,逐个转换为 Create 发酵配方 // ============================================================================ ServerEvents.recipes(function(event) { var data = createConverterData(event); diff --git a/server_scripts/biodiesel_fix/fermenting_test.js b/server_scripts/biodiesel_fix/fermenting_test.js.pass similarity index 100% rename from server_scripts/biodiesel_fix/fermenting_test.js rename to server_scripts/biodiesel_fix/fermenting_test.js.pass From 47a85a8ca9f7d4d5955c55d753662ccf61baf5c5 Mon Sep 17 00:00:00 2001 From: dalizi2333 Date: Mon, 18 May 2026 10:42:48 +0000 Subject: [PATCH 07/10] =?UTF-8?q?=E7=AE=80=E5=8C=96=E5=B9=B6=E9=87=8D?= =?UTF-8?q?=E6=9E=84=E5=AF=86=E5=B0=81=E5=A4=A7=E6=A1=B6=E9=85=8D=E6=96=B9?= =?UTF-8?q?=E8=BF=81=E7=A7=BB=E8=84=9A=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../biodiesel_fix/fermenting_from_barrel.js | 635 ++++++++---------- .../biodiesel_fix/fermenting_test.js.pass | 443 ------------ .../test_basin_fermenting_schema.js.faild | 67 -- .../test_fermenting_recipes.js.pass | 96 --- server_scripts/test_large_leather.js.pass | 26 - server_scripts/test_maxstack_debug.js.pass | 138 ---- server_scripts/test_not_rotten.js.pass | 56 -- server_scripts/test_tfc_modifiers.js.faild | 32 - 8 files changed, 278 insertions(+), 1215 deletions(-) delete mode 100644 server_scripts/biodiesel_fix/fermenting_test.js.pass delete mode 100644 server_scripts/test_basin_fermenting_schema.js.faild delete mode 100644 server_scripts/test_fermenting_recipes.js.pass delete mode 100644 server_scripts/test_large_leather.js.pass delete mode 100644 server_scripts/test_maxstack_debug.js.pass delete mode 100644 server_scripts/test_not_rotten.js.pass delete mode 100644 server_scripts/test_tfc_modifiers.js.faild diff --git a/server_scripts/biodiesel_fix/fermenting_from_barrel.js b/server_scripts/biodiesel_fix/fermenting_from_barrel.js index 9684eeb..bae2a36 100644 --- a/server_scripts/biodiesel_fix/fermenting_from_barrel.js +++ b/server_scripts/biodiesel_fix/fermenting_from_barrel.js @@ -1,47 +1,30 @@ // ============================================================================ -// 批量从TFC密封大桶配方创建Create发酵配方(策略模式重构版) -// ============================================================================ -// -// 策略模式实现: -// 1. 分析配方属性,添加策略标记(strategy type) -// 2. 注册不同策略的处理函数 -// 3. 执行时根据标记自动选择并执行对应策略 +// 批量从TFC密封大桶配方创建Create发酵配方 +// 线性流水线:解析 → 过滤 → 计算倍率 → 生成Basin/Bulk配方 // ============================================================================ -// ============================================================================ -// 策略注册表 -// 每个策略包含:condition(recipeData) -> bool 用于判断是否适用 -// handler(data, recipe, recipeData) -> bool 返回true表示已处理,false表示继续 -// 策略按注册顺序执行,前面的策略可以为后面的策略添加标记数据(如bulkParams) -// ============================================================================ -var recipeStrategies = {}; - -// 注册策略 -function registerStrategy(name, condition, handler) { - recipeStrategies[name] = { - condition: condition, - handler: handler - }; -} - -// ============================================================================ -// 数据结构定义 -// ============================================================================ +var BULK_FLUID_LIMIT = 72000; -// 配方转换器数据(贯穿整个转换流程的上下文对象) +/** + * 创建贯穿转换流程的上下文对象 + * @param {Internal.RecipeEventJS} event - 配方事件 + * @returns {Object} 包含事件引用、统计计数器和常量 + */ function createConverterData(event) { return { event: event, - stats: { - basin: 0, // Basin Fermenting 配方生成计数 - bulk: 0, // Bulk Fermenting 配方生成计数 - skipped: 0 // 跳过的配方计数(如带modifiers的配方) - }, - FLUID_SLOT_LIMIT: 1000 // Create流体槽上限 (mB) + stats: { basin: 0, bulk: 0, skipped: 0 }, + FLUID_SLOT_LIMIT: 1000 }; } -// 配方数据对象(每个TFC配方对应一个实例,策略按需修改其字段) +/** + * 从TFC配方JSON中提取关键字段 + * @param {Internal.JsonObject} json - 配方的JSON对象 + * @param {Object} data - 转换上下文 + * @param {Internal.Recipe} recipe - TFC配方 + * @returns {Object} 标准化后的配方数据对象 + */ function createRecipeData(json, data, recipe) { var result = { inputItem: null, @@ -49,39 +32,34 @@ function createRecipeData(json, data, recipe) { outputItem: null, outputFluid: null, sealTime: 0, - maxMultiplier: Infinity, // 理论最大倍增倍数(受堆叠/流体槽限制) - flooredMultiplier: 0, // 向下取整后的倍数(用于Basin配方) + basinMaxMultiplier: Infinity, + basinMultiplier: 0, recipeId: recipe ? recipe.getId() : null, - // bulkParams 由各策略逐步修改,最终用于 Bulk Fermenting 配方生成 - bulkParams: { - itemMultiplier: 0, // 物品倍增倍率 - fluidMultiplier: 0, // 流体倍增倍率(可与物品倍率不同) - fluidAddition: 0 // 额外添加/返还的流体量 (mB) - } + base: 0, + itemMultiplier: 0, + fluidMultiplier: 0, + fluidAddition: 0 }; - - // 提取数据 + result.inputItem = parseJsonField(json, 'input_item'); result.inputFluid = parseJsonField(json, 'input_fluid'); result.outputItem = parseJsonField(json, 'output_item'); result.outputFluid = parseJsonField(json, 'output_fluid'); - // 支持 seal_time 和 duration 两种字段名 if (json.has('seal_time')) { result.sealTime = json.get('seal_time').getAsInt(); } else if (json.has('duration')) { result.sealTime = json.get('duration').getAsInt(); - } else { - result.sealTime = 0; } - + return result; } -// ============================================================================ -// 工具函数 -// ============================================================================ - -// 解析 JSON 字段 +/** + * 安全解析JSON字段 + * @param {Internal.JsonObject} json - JSON对象 + * @param {string} fieldName - 字段名 + * @returns {Object|null} 解析后的对象,失败返回null + */ function parseJsonField(json, fieldName) { if (json.has(fieldName)) { try { @@ -93,12 +71,15 @@ function parseJsonField(json, fieldName) { return null; } -// 获取物品最大堆叠数 -// 当输入是tag时,取该tag下所有物品中最小的maxStackSize(保守估计,防止溢出) +/** + * 获取物品最大堆叠数(tag输入时取该tag下所有物品的最小值) + * @param {Object} itemData - {item/tag, count} + * @returns {number|null} 最大堆叠数 + */ function getMaxStackSize(itemData) { var itemId = itemData.item || itemData.tag; if (!itemId) return null; - + try { if (itemData.tag) { var tagItems = Ingredient.of('#' + itemData.tag).items; @@ -120,11 +101,16 @@ function getMaxStackSize(itemData) { return null; } -// 计算最大倍增倍数(取输入物品/输出物品/输入流体/输出流体四项限制的最小值) -// 输入物品受堆叠上限约束,输出物品同理;流体受 FLUID_SLOT_LIMIT (1000mB) 约束 -function calculateMaxMultiplier(recipeData, data) { +/** + * 计算Basin配方的理论最大倍率 + * 受输入/输出物品堆叠上限和1000mB流体槽限制 + * @param {Object} recipeData - 配方数据 + * @param {Object} data - 转换上下文(提供FLUID_SLOT_LIMIT) + * @returns {number} 理论最大倍率 + */ +function calculateBasinMaxMultiplier(recipeData, data) { var maxMultiplier = Infinity; - + if (recipeData.inputItem) { var itemId = recipeData.inputItem.item || recipeData.inputItem.tag; if (itemId) { @@ -135,7 +121,7 @@ function calculateMaxMultiplier(recipeData, data) { } } } - + if (recipeData.outputItem) { var outputId = recipeData.outputItem.id || recipeData.outputItem.item; if (outputId) { @@ -150,29 +136,125 @@ function calculateMaxMultiplier(recipeData, data) { } } } - + if (recipeData.inputFluid && recipeData.inputFluid.amount > 0) { maxMultiplier = Math.min(maxMultiplier, data.FLUID_SLOT_LIMIT / recipeData.inputFluid.amount); } - + if (recipeData.outputFluid && recipeData.outputFluid.amount > 0) { maxMultiplier = Math.min(maxMultiplier, data.FLUID_SLOT_LIMIT / recipeData.outputFluid.amount); } - + return maxMultiplier; } -// 构建 Basin Fermenting ingredients(物品和流体使用相同倍率) -function buildIngredients(inputItem, inputFluid, multiplier) { +/** + * 计算Bulk配方的基础倍率 + * 公式: floor(9 / 物品数),同时为流体增益×2预留72000上限空间 + * @param {Object} recipeData - 配方数据 + * @returns {number} 基础倍率(为0时无法生成Bulk配方) + */ +function calculateBulkBase(recipeData) { + var originalItemCount = recipeData.inputItem ? 1 : 0; + if (originalItemCount === 0) return 0; + + var base = Math.floor(9 / originalItemCount); + + if (recipeData.inputFluid && recipeData.inputFluid.amount > 0) { + var inputAmt = recipeData.inputFluid.amount; + if (recipeData.outputFluid && recipeData.outputFluid.amount > 0) { + base = Math.min(base, Math.floor(BULK_FLUID_LIMIT / (2 * inputAmt))); + base = Math.min(base, Math.floor(BULK_FLUID_LIMIT / (2 * recipeData.outputFluid.amount))); + } else { + base = Math.min(base, Math.floor(BULK_FLUID_LIMIT / inputAmt)); + } + } + + return base; +} + +/** + * 判断是否为mortar配方(输出过多,需限制倍率为6) + * @param {Object} recipeData - 配方数据 + * @returns {boolean} + */ +function isMortar(recipeData) { + return recipeData.recipeId === 'tfc:barrel/mortar'; +} + +/** + * 判断是否为陈酿酒配方(物品×1,流体×3.6的特殊倍率) + * @param {Object} recipeData - 配方数据 + * @returns {boolean} + */ +function isAgedAlcohol(recipeData) { + var fluidId = null; + if (recipeData.outputFluid) { + fluidId = recipeData.outputFluid.id || recipeData.outputFluid.fluid; + } + return fluidId && fluidId.indexOf('tfcagedalcohol:aged') === 0; +} + +/** + * 解析Bulk配方的倍率参数 + * 特殊配方(mortar/陈酿酒)整体覆盖所有倍率并跳过通用策略; + * 通用配方依次应用流体增益(×2)和满池返还(向上取整到1000的倍数) + * @param {Object} recipeData - 配方数据(会被修改) + */ +function resolveBulkParams(recipeData) { + var base = recipeData.base; + var hasInputFluid = recipeData.inputFluid && recipeData.inputFluid.amount > 0; + var hasOutputFluid = recipeData.outputFluid && recipeData.outputFluid.amount > 0; + + if (isMortar(recipeData)) { + recipeData.itemMultiplier = 6; + recipeData.fluidMultiplier = 6; + recipeData.fluidAddition = 0; + return; + } + + if (isAgedAlcohol(recipeData)) { + recipeData.itemMultiplier = 1; + recipeData.fluidMultiplier = 3.6; + recipeData.fluidAddition = 0; + return; + } + + recipeData.itemMultiplier = base; + recipeData.fluidMultiplier = base; + recipeData.fluidAddition = 0; + + if (hasInputFluid && hasOutputFluid) { + recipeData.fluidMultiplier = base * 2; + } + + if (hasInputFluid && !hasOutputFluid) { + var totalInput = recipeData.inputFluid.amount * recipeData.fluidMultiplier; + var remainder = totalInput % 1000; + if (remainder > 0) { + recipeData.fluidAddition = 1000 - remainder; + var fluidId = recipeData.inputFluid.fluid || recipeData.inputFluid.tag; + if (fluidId) { + recipeData.outputFluid = { id: fluidId, amount: 0 }; + } + } + } +} + +/** + * 构建Basin配方的输入列表(物品和流体使用同一倍率) + * @param {Object} inputItem - 输入物品 + * @param {Object} inputFluid - 输入流体 + * @param {number} multiplier - 倍率 + * @returns {Array} ingredients数组 + */ +function buildBasinIngredients(inputItem, inputFluid, multiplier) { var ingredients = []; - + if (inputItem) { if (inputItem.type === 'tfc:and' && inputItem.children) { for (var i = 0; i < multiplier; i++) { - ingredients.push({ - type: 'tfc:and', - children: inputItem.children - }); + ingredients.push({ type: 'tfc:and', children: inputItem.children }); } } else { for (var i = 0; i < multiplier; i++) { @@ -184,72 +266,64 @@ function buildIngredients(inputItem, inputFluid, multiplier) { } } } - + if (inputFluid) { var amount = inputFluid.amount * multiplier; if (inputFluid.fluid && amount > 0) { - ingredients.push({ - type: 'fluid_stack', - fluid: inputFluid.fluid, - amount: amount - }); + ingredients.push({ type: 'fluid_stack', fluid: inputFluid.fluid, amount: amount }); } else if (inputFluid.tag && amount > 0) { - ingredients.push({ - type: 'fluid_tag', - fluid_tag: inputFluid.tag, - amount: amount - }); + ingredients.push({ type: 'fluid_tag', fluid_tag: inputFluid.tag, amount: amount }); } } - + return ingredients; } -// 构建 Basin Fermenting results(物品和流体使用相同倍率) -function buildResults(outputItem, outputFluid, multiplier) { +/** + * 构建Basin配方的输出列表(物品和流体使用同一倍率) + * @param {Object} outputItem - 输出物品 + * @param {Object} outputFluid - 输出流体 + * @param {number} multiplier - 倍率 + * @returns {Array} results数组 + */ +function buildBasinResults(outputItem, outputFluid, multiplier) { var results = []; - + if (outputItem) { var itemId = outputItem.id || outputItem.item; if (itemId) { var singleResult = { id: itemId }; var outputCount = (outputItem.count || 1) * multiplier; - if (outputCount > 1) { - singleResult.count = outputCount; - } - if (outputItem.chance) { - singleResult.chance = outputItem.chance; - } + if (outputCount > 1) singleResult.count = outputCount; + if (outputItem.chance) singleResult.chance = outputItem.chance; results.push(singleResult); } } - + if (outputFluid) { var fluidId = outputFluid.id || outputFluid.fluid; if (fluidId && outputFluid.amount > 0) { - results.push({ - id: fluidId, - amount: outputFluid.amount * multiplier - }); + results.push({ id: fluidId, amount: outputFluid.amount * multiplier }); } } - + return results; } -// 构建 Bulk Fermenting ingredients(支持独立的物品和流体倍率,以及流体返还) -// fluidAddition 用于处理满池减益策略中返还剩余流体的场景 -function buildBulkIngredients(inputItem, inputFluid, bulkParams) { +/** + * 构建Bulk配方的输入列表(物品/流体独立倍率,含满池返还的fluidAddition) + * @param {Object} recipeData - 配方数据(含itemMultiplier/fluidMultiplier/fluidAddition) + * @returns {Array} ingredients数组 + */ +function buildBulkIngredients(recipeData) { var ingredients = []; - + var inputItem = recipeData.inputItem; + var inputFluid = recipeData.inputFluid; + if (inputItem) { - var itemMult = bulkParams.itemMultiplier; - for (var i = 0; i < itemMult; i++) { + for (var i = 0; i < recipeData.itemMultiplier; i++) { if (inputItem.type === 'tfc:and' && inputItem.children) { - ingredients.push({ - type: 'tfc:and', - children: inputItem.children - }); + ingredients.push({ type: 'tfc:and', children: inputItem.children }); } else if (inputItem.item) { ingredients.push({ item: inputItem.item }); } else if (inputItem.tag) { @@ -257,320 +331,167 @@ function buildBulkIngredients(inputItem, inputFluid, bulkParams) { } } } - + if (inputFluid) { - var fluidAmount = inputFluid.amount * bulkParams.fluidMultiplier + bulkParams.fluidAddition; + var fluidAmount = inputFluid.amount * recipeData.fluidMultiplier + recipeData.fluidAddition; if (fluidAmount > 0) { if (inputFluid.fluid) { - ingredients.push({ - type: 'fluid_stack', - fluid: inputFluid.fluid, - amount: fluidAmount - }); + ingredients.push({ type: 'fluid_stack', fluid: inputFluid.fluid, amount: fluidAmount }); } else if (inputFluid.tag) { - ingredients.push({ - type: 'fluid_tag', - fluid_tag: inputFluid.tag, - amount: fluidAmount - }); + ingredients.push({ type: 'fluid_tag', fluid_tag: inputFluid.tag, amount: fluidAmount }); } } } - + return ingredients; } -// 构建 Bulk Fermenting results(支持独立的物品和流体倍率,以及流体返还) -// outputFluid.amount >= 0 允许零量输出流体(用于满池减益策略的流体返还标记) -function buildBulkResults(outputItem, outputFluid, bulkParams) { +/** + * 构建Bulk配方的输出列表(物品/流体独立倍率,含满池返还的fluidAddition) + * @param {Object} recipeData - 配方数据 + * @returns {Array} results数组 + */ +function buildBulkResults(recipeData) { var results = []; - + var outputItem = recipeData.outputItem; + var outputFluid = recipeData.outputFluid; + if (outputItem) { var itemId = outputItem.id || outputItem.item; if (itemId) { var singleResult = { id: itemId }; - var outputCount = (outputItem.count || 1) * bulkParams.itemMultiplier; - if (outputCount > 1) { - singleResult.count = outputCount; - } - if (outputItem.chance) { - singleResult.chance = outputItem.chance; - } + var outputCount = (outputItem.count || 1) * recipeData.itemMultiplier; + if (outputCount > 1) singleResult.count = outputCount; + if (outputItem.chance) singleResult.chance = outputItem.chance; results.push(singleResult); } } - + if (outputFluid && outputFluid.amount >= 0) { var fluidId = outputFluid.id || outputFluid.fluid; if (fluidId) { - var fluidAmount = outputFluid.amount * bulkParams.fluidMultiplier + bulkParams.fluidAddition; + var fluidAmount = outputFluid.amount * recipeData.fluidMultiplier + recipeData.fluidAddition; if (fluidAmount > 0) { - results.push({ - id: fluidId, - amount: fluidAmount - }); + results.push({ id: fluidId, amount: fluidAmount }); } } } - + return results; } -// ============================================================================ -// 策略:配方分析(添加标记) -// ============================================================================ - -// 策略1:计算 bulk 倍率(默认物品和流体同步倍率) -// 逻辑:原配方输入物品数决定每"组"大小,floor(9 / 原物品数) = 每批最多处理几组 -registerStrategy('bulk_multiplier_check', function(recipeData) { - // 计算原配方输入物品数 - var originalItemCount = 0; - if (recipeData.inputItem) { - originalItemCount = 1; - } - - // 计算 bulk 倍率:floor(9 / 原物品数) - var multiplier = Math.floor(9 / originalItemCount); - - // 将倍率参数存储到 recipeData 中(默认同步倍率) - recipeData.bulkParams.itemMultiplier = multiplier; - recipeData.bulkParams.fluidMultiplier = multiplier; - recipeData.bulkParams.fluidAddition = 0; - - // 如果倍率 > 0,则 bulk_fermenting 可用 - return multiplier > 0; -}, function(data, recipe, recipeData) { - // 这个策略只是添加标记,不做实际处理 - return false; // 继续后续策略 -}); - -// 策略2:流体增益(有流体输出的配方,流体倍率翻倍) -// 原因:输入和输出的流体独立占用流体槽,翻倍可以更好地利用槽位 -registerStrategy('bulk_fluid_bonus', function(recipeData) { - // 条件:有流体输出且输入流体量 > 0 - if (recipeData.outputFluid && recipeData.outputFluid.amount > 0 && - recipeData.inputFluid && recipeData.inputFluid.amount > 0) { - // 流体倍率 = 物品倍率 * 2(确保输入与输出流体同步倍增) - var itemMult = recipeData.bulkParams.itemMultiplier || 1; - recipeData.bulkParams.fluidMultiplier = itemMult * 2; - recipeData.bulkParams.fluidAddition = 0; - return true; - } - return false; -}, function(data, recipe, recipeData) { - // 标记已添加,不做实际处理 - return false; -}); - -// 策略2.1:满池减益(有输入流体但无输出流体,需返还剩余流体) -// 当输入流体 < 1000mB 且配方无输出流体时,bulk 后会产生"空余"流体槽 -// 此策略将剩余的流体返还到输出中(创造一个虚拟输出流体标记) -registerStrategy('bulk_fluid_return', function(recipeData) { - // 条件:有输入流体但无输出流体,且输入流体量 < 1000 - if (recipeData.inputFluid && recipeData.inputFluid.amount > 0 && - (!recipeData.outputFluid || recipeData.outputFluid.amount <= 0) && - recipeData.inputFluid.amount < 1000) { - // 计算返还量:1000 - (输入流体量 * itemMultiplier) - var inputAmount = recipeData.inputFluid.amount; - var itemMult = recipeData.bulkParams.itemMultiplier || 1; - var consumed = inputAmount * itemMult; - var returnAmount = 1000 - consumed; - - // 设置参数:流体倍率与物品倍率相同,添加返还量 - recipeData.bulkParams.fluidMultiplier = itemMult; - recipeData.bulkParams.fluidAddition = returnAmount; - - // 创建虚拟输出流体(用于buildBulkResults处理返还) - var fluidId = recipeData.inputFluid.fluid || recipeData.inputFluid.tag; - if (fluidId) { - recipeData.outputFluid = { id: fluidId, amount: 0 }; - } - - return true; - } - return false; -}, function(data, recipe, recipeData) { - // 标记已添加,不做实际处理 - return false; -}); - -// 策略2.2:特殊配方处理(如 mortar 输出过多,限制倍率为6防止溢出) -registerStrategy('bulk_special_recipe', function(recipeData) { - // 直接判断配方ID - if (recipeData.recipeId === 'tfc:barrel/mortar') { - recipeData.bulkParams.itemMultiplier = 6; // 特殊物品倍率 - recipeData.bulkParams.fluidMultiplier = 6; // 特殊流体倍率 - recipeData.bulkParams.fluidAddition = 0; - return true; - } - return false; -}, function(data, recipe, recipeData) { - // 标记已添加,不做实际处理 - return false; -}); +/** + * 尝试生成Basin Fermenting配方(处理时间=sealTime/5,至少100tick) + * @param {Object} data - 转换上下文 + * @param {Internal.Recipe} recipe - 原TFC配方(用于生成ID) + * @param {Object} recipeData - 配方数据 + */ +function tryBasinFermenting(data, recipe, recipeData) { + if (recipeData.basinMultiplier < 1) return; -// 策略2.3:陈酿酒配方(输出流体以 tfcagedalcohol:aged 开头) -// 陈酿酒需要特殊倍率:物品不倍增,仅流体按 3.6 倍处理 -registerStrategy('bulk_aged_alcohol', function(recipeData) { - // 检查输出流体ID是否以 tfcagedalcohol:aged 开头 - var fluidId = null; - if (recipeData.outputFluid) { - fluidId = recipeData.outputFluid.id || recipeData.outputFluid.fluid; - } - if (fluidId && fluidId.indexOf('tfcagedalcohol:aged') === 0) { - recipeData.bulkParams.itemMultiplier = 1; // 物品倍率1 - recipeData.bulkParams.fluidMultiplier = 3.6; // 陈酿酒流体倍率 - recipeData.bulkParams.fluidAddition = 0; - return true; - } - return false; -}, function(data, recipe, recipeData) { - // 标记已添加,不做实际处理 - return false; -}); + var ingredients = buildBasinIngredients(recipeData.inputItem, recipeData.inputFluid, recipeData.basinMultiplier); + var results = buildBasinResults(recipeData.outputItem, recipeData.outputFluid, recipeData.basinMultiplier); -// 策略3:跳过带 modifiers 的配方(如带有NBT标签的输出物,无法在Create配方中表达) -registerStrategy('skip_modifiers', function(recipeData) { - return recipeData.outputItem && recipeData.outputItem.modifiers; -}, function(data, recipe, recipeData) { - data.stats.skipped++; - return true; // 已处理,不再执行后续策略 -}); + if (results.length === 0 || ingredients.length === 0) return; -// 策略4:Basin Fermenting(处理倍率 >= 1 的配方,物品流体同步倍率) -// 处理时间 = sealTime / 5(最少100tick),用于单槽批量发酵 -registerStrategy('basin_fermenting', function(recipeData) { - return recipeData.flooredMultiplier >= 1; -}, function(data, recipe, recipeData) { - var multiplier = recipeData.flooredMultiplier; - var ingredients = buildIngredients(recipeData.inputItem, recipeData.inputFluid, multiplier); - var results = buildResults(recipeData.outputItem, recipeData.outputFluid, multiplier); - - if (results.length === 0 || ingredients.length === 0) { - return false; - } - var processingTime = Math.max(100, Math.round(recipeData.sealTime / 5)); - var multStr = multiplier.toString(); - + data.event.custom({ type: 'createdieselgenerators:basin_fermenting', ingredients: ingredients, processing_time: processingTime, results: results - }).id('kubejs:tfc_barrel_sealed/basin/' + multStr + '_' + recipe.getId().replace(':', '_')); - + }).id('kubejs:tfc_barrel_sealed/basin/' + recipeData.basinMultiplier + '_' + recipe.getId().replace(':', '_')); + data.stats.basin++; - return true; -}); +} + +/** + * 尝试生成Bulk Fermenting配方(处理时间=sealTime/4,至少100tick) + * @param {Object} data - 转换上下文 + * @param {Internal.Recipe} recipe - 原TFC配方(用于生成ID) + * @param {Object} recipeData - 配方数据 + */ +function tryBulkFermenting(data, recipe, recipeData) { + if (recipeData.itemMultiplier <= 0) return; + + var ingredients = buildBulkIngredients(recipeData); + var results = buildBulkResults(recipeData); + + if (results.length === 0 || ingredients.length === 0) return; -// 策略5:Bulk Fermenting(使用 bulkParams,物品和流体可独立倍率) -// 处理时间 = sealTime / 4(最少100tick),九个槽位同时发酵 -registerStrategy('bulk_fermenting', function(recipeData) { - // 检查是否有有效的 bulkParams(itemMultiplier > 0) - return recipeData.bulkParams && recipeData.bulkParams.itemMultiplier > 0; -}, function(data, recipe, recipeData) { - // 获取 bulk 参数 - var bulkParams = recipeData.bulkParams; - - // 使用独立的构建函数处理 bulk 配方 - var ingredients = buildBulkIngredients(recipeData.inputItem, recipeData.inputFluid, bulkParams); - var results = buildBulkResults(recipeData.outputItem, recipeData.outputFluid, bulkParams); - - if (results.length === 0 || ingredients.length === 0) { - return false; - } - var processingTime = Math.max(100, Math.round(recipeData.sealTime / 4)); - var multStr = bulkParams.itemMultiplier.toString() + '_' + bulkParams.fluidMultiplier.toString(); - + var multStr = recipeData.itemMultiplier + '_' + recipeData.fluidMultiplier; + data.event.custom({ type: 'createdieselgenerators:bulk_fermenting', ingredients: ingredients, processing_time: processingTime, results: results }).id('kubejs:tfc_barrel_sealed/bulk/' + multStr + '_' + recipe.getId().replace(':', '_')); - - data.stats.bulk++; - return true; -}); -// ============================================================================ -// 主流程 -// ============================================================================ - -// 分析配方:计算倍率,然后遍历所有策略的 condition,将适用的策略名存入 recipeData.strategies -// 注意:condition 可能有副作用(如修改 bulkParams),这是设计如此,用于策略间的数据传递 -function analyzeRecipe(recipeData, data) { - // 计算倍数 - recipeData.maxMultiplier = calculateMaxMultiplier(recipeData, data); - recipeData.flooredMultiplier = Math.floor(recipeData.maxMultiplier); - - // 根据条件收集适用的策略 - recipeData.strategies = []; - for (var strategyName in recipeStrategies) { - if (recipeStrategies.hasOwnProperty(strategyName)) { - var strategy = recipeStrategies[strategyName]; - if (strategy.condition(recipeData)) { - recipeData.strategies.push(strategyName); - } - } - } -} - -// 按 analyzeRecipe 收集的策略顺序执行所有 handler -// handler 返回 true 表示已处理(如 skip 策略),但目前不影响后续策略继续执行 -function executeStrategies(data, recipe, recipeData) { - for (var i = 0; i < recipeData.strategies.length; i++) { - var strategyName = recipeData.strategies[i]; - var strategy = recipeStrategies[strategyName]; - if (strategy) { - var result = strategy.handler(data, recipe, recipeData); - if (result === true) { - // 策略已处理,可以选择继续或中断 - // 这里可以根据需要决定是否继续 - } - } - } + data.stats.bulk++; } -// 转换单个配方:解析 → 快速过滤 → 分析策略 → 执行策略 +/** + * 转换单个TFC密封大桶配方:解析 → 过滤modifiers → 计算倍率 → 生成Basin和Bulk配方 + * @param {Object} data - 转换上下文 + * @param {Internal.Recipe} recipe - TFC密封大桶配方 + */ function convertSingleRecipe(data, recipe) { var json = recipe.json; - var recipeData = createRecipeData(json, data, recipe); - - // 快速过滤:带modifiers的配方无法在Create中表达,提前跳过(与策略3重复但更高效) + if (recipeData.outputItem && recipeData.outputItem.modifiers) { data.stats.skipped++; return; } - - // 分析配方,添加策略标记 - analyzeRecipe(recipeData, data); - - // 执行所有适用的策略 - executeStrategies(data, recipe, recipeData); + + recipeData.basinMaxMultiplier = calculateBasinMaxMultiplier(recipeData, data); + recipeData.basinMultiplier = Math.floor(recipeData.basinMaxMultiplier); + + recipeData.base = calculateBulkBase(recipeData); + resolveBulkParams(recipeData); + + tryBasinFermenting(data, recipe, recipeData); + tryBulkFermenting(data, recipe, recipeData); +} + +/** + * 验证TFC堆叠限制是否已正确加载 + * 首次加载时TFC堆叠修改可能尚未生效,getMaxStackSize可能返回错误的64 + * @param {Object} data - 转换上下文 + * @returns {boolean} true=堆叠正确,false=需要重载 + */ +function verifyStackSizeLoaded(data) { + var expected = 32; + var actual = Item.of('minecraft:white_wool', 1).getMaxStackSize(); + + if (actual !== expected) { + var msg = Text.red('[生物柴油修复] 堆叠限制未正确加载(羊毛=' + actual + ',期望=' + expected + '),请执行 /reload 后重试,否则配方倍率可能不准确'); + if (data.event.server) { + data.event.server.tell(msg); + } + console.error('[生物柴油修复] 堆叠限制验证失败:羊毛实际=' + actual + ',期望=' + expected + ',请执行 /reload 后重试,否则配方倍率可能不准确'); + return false; + } + + console.info('[生物柴油修复] 堆叠限制验证通过(羊毛=' + actual + ')'); + return true; } -// 批量转换 +/** + * 批量转换所有TFC密封大桶配方 + * @param {Object} data - 转换上下文 + */ function convertAllRecipes(data) { - console.info('[生物柴油修复] 开始批量转换TFC密封大桶配方...'); - data.event.forEachRecipe({ type: 'tfc:barrel_sealed' }, function(recipe) { convertSingleRecipe(data, recipe); }); - - console.info('[生物柴油修复] 完成!Basin: ' + data.stats.basin + - ', Bulk: ' + data.stats.bulk + - ', 跳过: ' + data.stats.skipped); } -// ============================================================================ -// 执行 -// 入口:遍历所有 tfc:barrel_sealed 配方,逐个转换为 Create 发酵配方 -// ============================================================================ ServerEvents.recipes(function(event) { var data = createConverterData(event); + verifyStackSizeLoaded(data); convertAllRecipes(data); }); diff --git a/server_scripts/biodiesel_fix/fermenting_test.js.pass b/server_scripts/biodiesel_fix/fermenting_test.js.pass deleted file mode 100644 index 9fbc95f..0000000 --- a/server_scripts/biodiesel_fix/fermenting_test.js.pass +++ /dev/null @@ -1,443 +0,0 @@ -// ============================================================================ -// 测试脚本:真正创建配方,测试完整方案 -// ============================================================================ - -ServerEvents.recipes(function(event) { - console.info('[测试] 开始测试4个示例配方(真正创建配方)...'); - - var stats = { basin: 0, bulk: 0, skipped: 0 }; - var FLUID_SLOT_LIMIT = 1000; - - // ============================================================================ - // 工具函数 - // ============================================================================ - - // 计算 basin 倍率:受限的物品堆叠数和流体<1000的同步物体与流体倍率 - function calculateBasinMultiplier(inputItem, inputFluid, outputItem, outputFluid) { - var maxMult = Infinity; - - // 输入物品堆叠限制 - if (inputItem) { - var itemCount = inputItem.count || 1; - var itemId = inputItem.item || inputItem.tag; - if (itemId) { - try { - var maxStack = 64; // 默认值 - if (inputItem.tag) { - var items = Ingredient.of('#' + inputItem.tag).items; - if (items && items.length > 0) { - maxStack = items[0].getMaxStackSize(); - } - } else { - maxStack = Item.of(itemId, 1).getMaxStackSize(); - } - maxMult = Math.min(maxMult, maxStack / itemCount); - } catch (e) { - maxMult = Math.min(maxMult, 64 / itemCount); - } - } - } - - // 输出物品堆叠限制 - if (outputItem) { - var itemCount = outputItem.count || 1; - var itemId = outputItem.id || outputItem.item; - if (itemId) { - try { - var maxStack = Item.of(itemId, 1).getMaxStackSize(); - maxMult = Math.min(maxMult, maxStack / itemCount); - } catch (e) { - maxMult = Math.min(maxMult, 64 / itemCount); - } - } - } - - // 输入流体限制(必须 < 1000) - if (inputFluid && inputFluid.amount > 0) { - maxMult = Math.min(maxMult, 1000 / inputFluid.amount); - } - - // 输出流体限制(必须 < 1000) - if (outputFluid && outputFluid.amount > 0) { - maxMult = Math.min(maxMult, 1000 / outputFluid.amount); - } - - return Math.floor(maxMult); - } - - function buildBasinIngredients(inputItem, inputFluid, multiplier) { - var ingredients = []; - - if (inputItem && multiplier > 0) { - for (var i = 0; i < multiplier; i++) { - if (inputItem.item) { - ingredients.push({ item: inputItem.item }); - } else if (inputItem.tag) { - ingredients.push({ tag: inputItem.tag }); - } - } - } - - if (inputFluid && multiplier > 0) { - var fluidAmount = inputFluid.amount * multiplier; - if (fluidAmount > 0) { - if (inputFluid.fluid) { - ingredients.push({ - type: 'fluid_stack', - fluid: inputFluid.fluid, - amount: fluidAmount - }); - } else if (inputFluid.tag) { - ingredients.push({ - type: 'fluid_tag', - fluid_tag: inputFluid.tag, - amount: fluidAmount - }); - } - } - } - - return ingredients; - } - - function buildBasinResults(outputItem, outputFluid, multiplier) { - var results = []; - - if (outputItem && multiplier > 0) { - var itemId = outputItem.id || outputItem.item; - if (itemId) { - var singleResult = { id: itemId }; - var outputCount = (outputItem.count || 1) * multiplier; - if (outputCount > 1) { - singleResult.count = outputCount; - } - results.push(singleResult); - } - } - - if (outputFluid && outputFluid.amount > 0 && multiplier > 0) { - var fluidId = outputFluid.id || outputFluid.fluid; - if (fluidId) { - var fluidAmount = outputFluid.amount * multiplier; - if (fluidAmount > 0) { - results.push({ - id: fluidId, - amount: fluidAmount - }); - } - } - } - - return results; - } - - function buildBulkIngredients(inputItem, inputFluid, bulkParams) { - var ingredients = []; - - if (inputItem) { - var itemMult = bulkParams.itemMultiplier; - for (var i = 0; i < itemMult; i++) { - if (inputItem.item) { - ingredients.push({ item: inputItem.item }); - } else if (inputItem.tag) { - ingredients.push({ tag: inputItem.tag }); - } - } - } - - if (inputFluid) { - var fluidAmount = inputFluid.amount * bulkParams.fluidMultiplier + bulkParams.fluidAddition; - if (fluidAmount > 0) { - if (inputFluid.fluid) { - ingredients.push({ - type: 'fluid_stack', - fluid: inputFluid.fluid, - amount: fluidAmount - }); - } else if (inputFluid.tag) { - ingredients.push({ - type: 'fluid_tag', - fluid_tag: inputFluid.tag, - amount: fluidAmount - }); - } - } - } - - return ingredients; - } - - function buildBulkResults(outputItem, outputFluid, bulkParams) { - var results = []; - - if (outputItem) { - var itemId = outputItem.id || outputItem.item; - if (itemId) { - var singleResult = { id: itemId }; - var outputCount = (outputItem.count || 1) * bulkParams.itemMultiplier; - if (outputCount > 1) { - singleResult.count = outputCount; - } - results.push(singleResult); - } - } - - if (outputFluid && outputFluid.amount >= 0) { - var fluidId = outputFluid.id || outputFluid.fluid; - if (fluidId) { - var fluidAmount = outputFluid.amount * bulkParams.fluidMultiplier + bulkParams.fluidAddition; - if (fluidAmount > 0) { - results.push({ - id: fluidId, - amount: fluidAmount - }); - } - } - } - - return results; - } - - // ============================================================================ - // 测试用例1:FirmaLife 奶酪 - // ============================================================================ - console.info('--- 测试1:FirmaLife 奶酪 ---'); - - var test1 = { - recipeId: 'firmalife:barrel/cheese', - duration: 1000, - input_item: { count: 1, item: 'firmalife:cheesecloth' }, - input_fluid: { amount: 1000, tag: 'firmalife:milks' }, - output_item: { count: 1, id: 'firmalife:cheesecloth' }, - output_fluid: { amount: 1000, id: 'firmalife:cream' } - }; - - // Basin倍率计算:min(64/1, 64/1, 1000/1000, 1000/1000) = 1 - var basinMult1 = calculateBasinMultiplier(test1.input_item, test1.input_fluid, test1.output_item, test1.output_fluid); - console.info('[测试1] Basin倍率: ' + basinMult1); - - var bulkParams1 = { - itemMultiplier: 9, - fluidMultiplier: 9, - fluidAddition: 0 - }; - - // Basin Fermenting(同步倍率) - var ingredients1_basin = buildBasinIngredients(test1.input_item, test1.input_fluid, basinMult1); - var results1_basin = buildBasinResults(test1.output_item, test1.output_fluid, basinMult1); - - event.custom({ - type: 'createdieselgenerators:basin_fermenting', - ingredients: ingredients1_basin, - processing_time: Math.max(100, Math.round(test1.duration / 5)), - results: results1_basin - }).id('kubejs:test/basin/firmalife_barrel_cheese'); - - stats.basin++; - console.info('[测试] 创建 Basin: ' + test1.recipeId); - console.info(' BasinMultiplier: ' + basinMult1); - console.info(' Ingredients: ' + JSON.stringify(ingredients1_basin)); - console.info(' Results: ' + JSON.stringify(results1_basin)); - - // Bulk Fermenting - var ingredients1_bulk = buildBulkIngredients(test1.input_item, test1.input_fluid, bulkParams1); - var results1_bulk = buildBulkResults(test1.output_item, test1.output_fluid, bulkParams1); - - event.custom({ - type: 'createdieselgenerators:bulk_fermenting', - ingredients: ingredients1_bulk, - processing_time: Math.max(100, Math.round(test1.duration / 4)), - results: results1_bulk - }).id('kubejs:test/bulk/firmalife_barrel_cheese'); - - stats.bulk++; - console.info('[测试] 创建 Bulk: ' + test1.recipeId); - console.info(' BulkParams: ' + JSON.stringify(bulkParams1)); - console.info(' Ingredients: ' + JSON.stringify(ingredients1_bulk)); - console.info(' Results: ' + JSON.stringify(results1_bulk)); - - // ============================================================================ - // 测试用例2:陈酿玉米威士忌 - // ============================================================================ - console.info('--- 测试2:陈酿玉米威士忌 ---'); - - var test2 = { - recipeId: 'tfc:barrel/aged_corn_whiskey', - duration: 691200, - input_fluid: { fluid: 'tfc:corn_whiskey', amount: 10000 }, - output_fluid: { id: 'tfcagedalcohol:aged_corn_whiskey', amount: 10000 } - }; - - // Basin倍率计算:min(1000/10000, 1000/10000) = 0.1 → floor = 0 - var basinMult2 = calculateBasinMultiplier(null, test2.input_fluid, null, test2.output_fluid); - console.info('[测试2] Basin倍率: ' + basinMult2); - - var bulkParams2 = { - itemMultiplier: 1, - fluidMultiplier: 3.6, - fluidAddition: 0 - }; - - // Basin Fermenting(倍率为0,不创建) - if (basinMult2 > 0) { - var ingredients2_basin = buildBasinIngredients(null, test2.input_fluid, basinMult2); - var results2_basin = buildBasinResults(null, test2.output_fluid, basinMult2); - - event.custom({ - type: 'createdieselgenerators:basin_fermenting', - ingredients: ingredients2_basin, - processing_time: Math.max(100, Math.round(test2.duration / 5)), - results: results2_basin - }).id('kubejs:test/basin/tfc_barrel_aged_corn_whiskey'); - - stats.basin++; - console.info('[测试] 创建 Basin: ' + test2.recipeId); - console.info(' BasinMultiplier: ' + basinMult2); - } else { - console.info('[测试] Basin倍率=0,跳过创建 Basin'); - } - - // Bulk Fermenting - var ingredients2_bulk = buildBulkIngredients(null, test2.input_fluid, bulkParams2); - var results2_bulk = buildBulkResults(null, test2.output_fluid, bulkParams2); - - event.custom({ - type: 'createdieselgenerators:bulk_fermenting', - ingredients: ingredients2_bulk, - processing_time: Math.max(100, Math.round(test2.duration / 4)), - results: results2_bulk - }).id('kubejs:test/bulk/tfc_barrel_aged_corn_whiskey'); - - stats.bulk++; - console.info('[测试] 创建 Bulk: ' + test2.recipeId); - console.info(' BulkParams: ' + JSON.stringify(bulkParams2)); - console.info(' Ingredients: ' + JSON.stringify(ingredients2_bulk)); - console.info(' Results: ' + JSON.stringify(results2_bulk)); - - // ============================================================================ - // 测试用例3:black_wool(无流体输出,需返还染料) - // ============================================================================ - console.info('--- 测试3:black_wool ---'); - - var test3 = { - recipeId: 'tfc:barrel/black_wool', - duration: 1200, - input_item: { count: 1, item: 'minecraft:white_wool' }, - input_fluid: { fluid: 'tfc:black_dye', amount: 25 }, - output_item: { count: 1, id: 'minecraft:black_wool' } - }; - - // Basin倍率计算:min(64/1, 1000/25) = 40 - var basinMult3 = calculateBasinMultiplier(test3.input_item, test3.input_fluid, test3.output_item, null); - console.info('[测试3] Basin倍率: ' + basinMult3); - - // 计算返还量:25 * 9 = 225, 1000 - 225 = 775 - var bulkParams3 = { - itemMultiplier: 9, - fluidMultiplier: 9, - fluidAddition: 775 - }; - - // 创建虚拟输出流体(用于buildBulkResults处理返还) - var virtualOutputFluid3 = { id: 'tfc:black_dye', amount: 0 }; - - // Basin Fermenting(无返还逻辑,因为 basin 倍率是受限计算出来的) - var ingredients3_basin = buildBasinIngredients(test3.input_item, test3.input_fluid, basinMult3); - var results3_basin = buildBasinResults(test3.output_item, null, basinMult3); - - if (results3_basin.length > 0 && ingredients3_basin.length > 0) { - event.custom({ - type: 'createdieselgenerators:basin_fermenting', - ingredients: ingredients3_basin, - processing_time: Math.max(100, Math.round(test3.duration / 5)), - results: results3_basin - }).id('kubejs:test/basin/tfc_barrel_black_wool'); - - stats.basin++; - console.info('[测试] 创建 Basin: ' + test3.recipeId); - console.info(' BasinMultiplier: ' + basinMult3); - console.info(' Ingredients: ' + JSON.stringify(ingredients3_basin)); - console.info(' Results: ' + JSON.stringify(results3_basin)); - } - - // Bulk Fermenting(有返还逻辑) - var ingredients3_bulk = buildBulkIngredients(test3.input_item, test3.input_fluid, bulkParams3); - var results3_bulk = buildBulkResults(test3.output_item, virtualOutputFluid3, bulkParams3); - - event.custom({ - type: 'createdieselgenerators:bulk_fermenting', - ingredients: ingredients3_bulk, - processing_time: Math.max(100, Math.round(test3.duration / 4)), - results: results3_bulk - }).id('kubejs:test/bulk/tfc_barrel_black_wool'); - - stats.bulk++; - console.info('[测试] 创建 Bulk: ' + test3.recipeId); - console.info(' BulkParams: ' + JSON.stringify(bulkParams3)); - console.info(' Ingredients: ' + JSON.stringify(ingredients3_bulk)); - console.info(' Results: ' + JSON.stringify(results3_bulk)); - - // ============================================================================ - // 测试用例4:mortar(特殊配方) - // ============================================================================ - console.info('--- 测试4:mortar ---'); - - var test4 = { - recipeId: 'tfc:barrel/mortar', - duration: 7200, - input_item: { count: 1, tag: 'c:sands' }, - input_fluid: { fluid: 'tfc:limewater', amount: 100 }, - output_item: { count: 16, id: 'tfc:mortar' } - }; - - // Basin倍率计算:min(64/1, 64/16, 1000/100) = 4 - var basinMult4 = calculateBasinMultiplier(test4.input_item, test4.input_fluid, test4.output_item, null); - console.info('[测试4] Basin倍率: ' + basinMult4); - - var bulkParams4 = { - itemMultiplier: 6, - fluidMultiplier: 6, - fluidAddition: 0 - }; - - // Basin Fermenting(倍率4,是受限计算得出的) - var ingredients4_basin = buildBasinIngredients(test4.input_item, test4.input_fluid, basinMult4); - var results4_basin = buildBasinResults(test4.output_item, null, basinMult4); - - if (results4_basin.length > 0 && ingredients4_basin.length > 0) { - event.custom({ - type: 'createdieselgenerators:basin_fermenting', - ingredients: ingredients4_basin, - processing_time: Math.max(100, Math.round(test4.duration / 5)), - results: results4_basin - }).id('kubejs:test/basin/tfc_barrel_mortar'); - - stats.basin++; - console.info('[测试] 创建 Basin: ' + test4.recipeId); - console.info(' BasinMultiplier: ' + basinMult4); - console.info(' Ingredients: ' + JSON.stringify(ingredients4_basin)); - console.info(' Results: ' + JSON.stringify(results4_basin)); - } - - // Bulk Fermenting(特殊倍率6) - var ingredients4_bulk = buildBulkIngredients(test4.input_item, test4.input_fluid, bulkParams4); - var results4_bulk = buildBulkResults(test4.output_item, null, bulkParams4); - - event.custom({ - type: 'createdieselgenerators:bulk_fermenting', - ingredients: ingredients4_bulk, - processing_time: Math.max(100, Math.round(test4.duration / 4)), - results: results4_bulk - }).id('kubejs:test/bulk/tfc_barrel_mortar'); - - stats.bulk++; - console.info('[测试] 创建 Bulk: ' + test4.recipeId); - console.info(' BulkParams: ' + JSON.stringify(bulkParams4)); - console.info(' Ingredients: ' + JSON.stringify(ingredients4_bulk)); - console.info(' Results: ' + JSON.stringify(results4_bulk)); - - // ============================================================================ - // 完成 - // ============================================================================ - console.info('[测试] 完成!Basin: ' + stats.basin + ', Bulk: ' + stats.bulk); -}); diff --git a/server_scripts/test_basin_fermenting_schema.js.faild b/server_scripts/test_basin_fermenting_schema.js.faild deleted file mode 100644 index 65eebab..0000000 --- a/server_scripts/test_basin_fermenting_schema.js.faild +++ /dev/null @@ -1,67 +0,0 @@ -// ============================================================================ -// 测试脚本:使用 basin_fermenting 配方 schema -// ============================================================================ - -ServerEvents.recipes(event => { - console.info('[DEBUG] 开始测试 basin_fermenting 配方 schema...'); - - // 测试物品 - let testItemId = 'tfc:food/barley_flour'; - - // 获取堆叠限制 - let actualMaxStack = 64; - try { - actualMaxStack = Item.of(testItemId, 1).getMaxStackSize(); - console.info(`[DEBUG] 获取到 ${testItemId} 的堆叠限制 = ${actualMaxStack}`); - } catch (e) { - console.info(`[DEBUG] 获取堆叠限制失败: ${e.message},使用默认值 64`); - } - - let FLUID_SLOT_LIMIT = 1000; - let maxMultiplier = Infinity; - - // 输入物品: barley_flour, count = 1 - let itemCount = 1; - let itemMultiplier = actualMaxStack / itemCount; - maxMultiplier = Math.min(maxMultiplier, itemMultiplier); - console.info('[DEBUG] 输入物品: ' + testItemId + ', count=' + itemCount + ', maxStack=' + actualMaxStack + ', multiplier=' + itemMultiplier.toFixed(2)); - - // 输入流体: water, amount = 500 - let inputFluidAmount = 500; - let inputFluidMultiplier = FLUID_SLOT_LIMIT / inputFluidAmount; - maxMultiplier = Math.min(maxMultiplier, inputFluidMultiplier); - console.info('[DEBUG] 输入流体: minecraft:water, amount=' + inputFluidAmount + ', multiplier=' + inputFluidMultiplier.toFixed(2)); - - // 输出流体: beer, amount = 500 - let outputFluidAmount = 500; - let outputFluidMultiplier = FLUID_SLOT_LIMIT / outputFluidAmount; - maxMultiplier = Math.min(maxMultiplier, outputFluidMultiplier); - console.info('[DEBUG] 输出流体: tfc:beer, amount=' + outputFluidAmount + ', multiplier=' + outputFluidMultiplier.toFixed(2)); - - let flooredMultiplier = Math.floor(maxMultiplier); - console.info('[DEBUG] 向下取整 flooredMultiplier = ' + flooredMultiplier); - - // 创建测试配方 - 使用新的配方 schema - if (flooredMultiplier >= 1) { - console.info('[DEBUG] 创建测试配方...'); - - let inputItemCount = 1 * flooredMultiplier; - let finalInputFluidAmount = 500 * flooredMultiplier; - let finalOutputFluidAmount = 500 * flooredMultiplier; - - event.recipes.createdieselgenerators.basinFermenting([ - Ingredient.of({ - type: 'tfc:and', - children: [ - { item: testItemId }, - { type: 'tfc:not_rotten' } - ] - }, inputItemCount), - Fluid.of('minecraft:water', finalInputFluidAmount) - ], [ - Fluid.of('tfc:beer', finalOutputFluidAmount) - ]).id('kubejs:test_fermenting/beer/' + flooredMultiplier + '_from_barley_flour'); - - console.info('[DEBUG] 成功创建配方: kubejs:test_fermenting/beer/' + flooredMultiplier + '_from_barley_flour'); - } -}); diff --git a/server_scripts/test_fermenting_recipes.js.pass b/server_scripts/test_fermenting_recipes.js.pass deleted file mode 100644 index 4cf9375..0000000 --- a/server_scripts/test_fermenting_recipes.js.pass +++ /dev/null @@ -1,96 +0,0 @@ -// ============================================================================ -// 手动创建TFC密封大桶配方对应的CDG发酵配方(完全按照参考格式) -// ============================================================================ - -ServerEvents.recipes(event => { - console.info('[生物柴油修复] 开始手动创建测试配方(完全按照参考格式)...'); - - // 1. black_wool - 黑色羊毛染色 - event.custom({ - type: 'createdieselgenerators:basin_fermenting', - ingredients: [ - { item: 'minecraft:white_wool' }, - { - type: 'fluid_stack', - fluid: 'tfc:black_dye', - amount: 25 - } - ], - processing_time: Math.max(100, Math.round(1200 / 5)), - results: [ - { id: 'minecraft:black_wool' } - ] - }).id('kubejs:test/black_wool'); - - // 2. corn_whiskey - 玉米威士忌 - event.custom({ - type: 'createdieselgenerators:basin_fermenting', - ingredients: [ - { - type: 'tfc:and', - children: [ - { item: 'tfc:food/maize_flour' }, - { type: 'tfc:not_rotten' } - ] - }, - { - type: 'fluid_stack', - fluid: 'minecraft:water', - amount: 500 - } - ], - processing_time: Math.max(100, Math.round(72000 / 5)), - results: [ - { - id: 'tfc:corn_whiskey', - amount: 500 - } - ] - }).id('kubejs:test/corn_whiskey'); - - // 3. sugar - 糖 - event.custom({ - type: 'createdieselgenerators:basin_fermenting', - ingredients: [ - { - type: 'tfc:and', - children: [ - { item: 'tfc:food/sugarcane' }, - { type: 'tfc:not_rotten' } - ] - }, - { - type: 'fluid_stack', - fluid: 'minecraft:water', - amount: 600 - } - ], - processing_time: Math.max(100, Math.round(7200 / 5)), - results: [ - { id: 'minecraft:sugar' } - ] - }).id('kubejs:test/sugar'); - - // 4. firmalife_cream - Firmalife奶油制作(使用流体标签格式) - event.custom({ - type: 'createdieselgenerators:basin_fermenting', - ingredients: [ - { item: 'firmalife:cheesecloth' }, - { - type: 'fluid_tag', // ✅ 使用fluid_tag类型 - fluid_tag: 'firmalife:milks', - amount: 1000 - } - ], - processing_time: Math.max(100, Math.round(1000 / 5)), - results: [ - { id: 'firmalife:cheesecloth' }, - { - id: 'firmalife:cream', - amount: 1000 - } - ] - }).id('kubejs:test/firmalife_cream'); - - console.info('[生物柴油修复] 手动测试配方(完全按照参考格式)创建完成!'); -}); diff --git a/server_scripts/test_large_leather.js.pass b/server_scripts/test_large_leather.js.pass deleted file mode 100644 index bb313f2..0000000 --- a/server_scripts/test_large_leather.js.pass +++ /dev/null @@ -1,26 +0,0 @@ -// ============================================================================ -// 测试large_leather和medium_leather配方转换 -// ============================================================================ - -ServerEvents.recipes(event => { - console.info('[测试] 开始测试皮革配方...'); - - // 测试: medium用直接count字段 - event.custom({ - type: 'createdieselgenerators:basin_fermenting', - ingredients: [ - { item: 'tfc:medium_prepared_hide' }, - { - type: 'fluid_stack', - fluid: 'tfc:tannin', - amount: 500 - } - ], - processing_time: Math.max(100, Math.round(7200 / 5)), - results: [ - { id: 'minecraft:leather', count: 2 } - ] - }).id('kubejs:test/medium_leather_count'); - - console.info('[测试] 皮革配方测试创建完成!'); -}); diff --git a/server_scripts/test_maxstack_debug.js.pass b/server_scripts/test_maxstack_debug.js.pass deleted file mode 100644 index 823eda1..0000000 --- a/server_scripts/test_maxstack_debug.js.pass +++ /dev/null @@ -1,138 +0,0 @@ -// ============================================================================ -// 调试脚本:测试获取 tfc:food/barley_flour 的最大堆叠数量 -// ============================================================================ -// 以下注释内容将辅助正式脚本修改过程,不允许删除 -// 重要发现: -// 1. maxMultiplier 初始值问题: -// - 错误:let maxMultiplier = 1.0; -// - 正确:let maxMultiplier = Infinity; -// - 原因:使用 Math.min() 取最小值时,初始值必须大于所有可能的乘数 -// - 示例:若乘数为 64, 2, 2,初始值为 1 会导致结果始终为 1 -// -// 2. 获取堆叠限制的方法: -// - Item.of().getMaxStackSize() 实际上能返回正确的值(包括 TFC 的 Weight 组件影响) -// - 测试结果:barley_flour 返回 32,符合预期 -// -// 3. 新发现 (2026-05-16): -// - event.recipes.createdieselgenerators.basinFermenting() 路线失败 -// - 直接使用 event.custom() 配合 { type: 'tfc:and', children: [...] } 结构成功 -// - 关键:用数组重复代替数量倍增 -// 例如 flooredMultiplier = 2 时,把 { type: 'tfc:and', children: [...] } 重复2次 -// ============================================================================ - -ServerEvents.recipes(event => { - console.info('[DEBUG] ============================================'); - console.info('[DEBUG] 测试配方1: TFC酿酒 (barley_flour + water -> beer)'); - console.info('[DEBUG] ============================================'); - - let testItemId1 = 'tfc:food/barley_flour'; - let inputFluidId1 = 'minecraft:water'; - let outputFluidId1 = 'tfc:beer'; - let inputFluidAmount1 = 500; - let outputFluidAmount1 = 500; - let inputItemCount1 = 1; - - let actualMaxStack1 = Item.of(testItemId1, 1).getMaxStackSize(); - console.info(`[DEBUG] ${testItemId1} 堆叠限制 = ${actualMaxStack1}`); - - let FLUID_SLOT_LIMIT = 1000; - let maxMultiplier1 = Infinity; - let itemMultiplier1 = actualMaxStack1 / inputItemCount1; - let fluidMultiplier1 = FLUID_SLOT_LIMIT / inputFluidAmount1; - let outputFluidMultiplier1 = FLUID_SLOT_LIMIT / outputFluidAmount1; - maxMultiplier1 = Math.min(maxMultiplier1, itemMultiplier1, fluidMultiplier1, outputFluidMultiplier1); - - let flooredMultiplier1 = Math.floor(maxMultiplier1); - console.info(`[DEBUG] maxMultiplier=${maxMultiplier1.toFixed(2)}, flooredMultiplier=${flooredMultiplier1}`); - - if (flooredMultiplier1 >= 1) { - let ingredients1 = []; - let results1 = []; - - // 用数组重复实现物品倍增 - for (let i = 0; i < flooredMultiplier1; i++) { - ingredients1.push({ - type: 'tfc:and', - children: [ - { item: testItemId1 }, - { type: 'tfc:not_rotten' } - ] - }); - } - - // 流体倍增用 amount - ingredients1.push({ - type: 'fluid_stack', - fluid: inputFluidId1, - amount: inputFluidAmount1 * flooredMultiplier1 - }); - - // 输出流体 - results1.push({ - id: outputFluidId1, - amount: outputFluidAmount1 * flooredMultiplier1 - }); - - console.info(`[DEBUG] 创建配方1: ${flooredMultiplier1}x ${testItemId1} + ${inputFluidAmount1 * flooredMultiplier1}mB water -> ${outputFluidAmount1 * flooredMultiplier1}mB beer`); - - event.custom({ - type: 'createdieselgenerators:basin_fermenting', - ingredients: ingredients1, - processing_time: 400, - results: results1 - }).id(`kubejs:test_fermenting/barley_flour_x${flooredMultiplier1}`); - } - - console.info('[DEBUG] ============================================'); - console.info('[DEBUG] 测试配方2: black_wool (white_wool + black_dye -> black_wool)'); - console.info('[DEBUG] ============================================'); - - let testItemId2 = 'minecraft:white_wool'; - let inputFluidId2 = 'tfc:black_dye'; - let outputItemId2 = 'minecraft:black_wool'; - let inputFluidAmount2 = 25; - let inputItemCount2 = 1; - - let actualMaxStack2 = Item.of(testItemId2, 1).getMaxStackSize(); - console.info(`[DEBUG] ${testItemId2} 堆叠限制 = ${actualMaxStack2}`); - - let maxMultiplier2 = Infinity; - let itemMultiplier2 = actualMaxStack2 / inputItemCount2; - let fluidMultiplier2 = FLUID_SLOT_LIMIT / inputFluidAmount2; - maxMultiplier2 = Math.min(maxMultiplier2, itemMultiplier2, fluidMultiplier2); - - let flooredMultiplier2 = Math.floor(maxMultiplier2); - console.info(`[DEBUG] maxMultiplier=${maxMultiplier2.toFixed(2)}, flooredMultiplier=${flooredMultiplier2}`); - - if (flooredMultiplier2 >= 1) { - let ingredients2 = []; - let results2 = []; - - // 用数组重复实现物品倍增 - for (let i = 0; i < flooredMultiplier2; i++) { - ingredients2.push({ item: testItemId2 }); - } - - // 流体倍增用 amount - ingredients2.push({ - type: 'fluid_stack', - fluid: inputFluidId2, - amount: inputFluidAmount2 * flooredMultiplier2 - }); - - // 输出物品 - results2.push({ - id: outputItemId2, - count: flooredMultiplier2 - }); - - console.info(`[DEBUG] 创建配方2: ${flooredMultiplier2}x ${testItemId2} + ${inputFluidAmount2 * flooredMultiplier2}mB ${inputFluidId2} -> ${flooredMultiplier2}x ${outputItemId2}`); - - event.custom({ - type: 'createdieselgenerators:basin_fermenting', - ingredients: ingredients2, - processing_time: 100, - results: results2 - }).id(`kubejs:test_fermenting/wool_x${flooredMultiplier2}`); - } -}); diff --git a/server_scripts/test_not_rotten.js.pass b/server_scripts/test_not_rotten.js.pass deleted file mode 100644 index a2f676b..0000000 --- a/server_scripts/test_not_rotten.js.pass +++ /dev/null @@ -1,56 +0,0 @@ -// ============================================================================ -// 测试脚本:非腐败条件限制器在Create配方中的使用 -// 使用Ingredient.of(物品类型, 数量)的方式实现多物品限制 -// ============================================================================ - -ServerEvents.recipes(event => { - console.info('[生物柴油修复测试] 开始测试非腐败条件限制器...'); - - // 测试1:橄榄塑形配方(10个新鲜橄榄 → 800mb橄榄油) - event.recipes.create.compacting( - [Fluid.of('tfc:olive_oil', 800)], - [ - Ingredient.of({ - type: 'tfc:and', - children: [ - { item: 'tfc:food/olive' }, - { type: 'tfc:not_rotten' } - ] - }, 10) - ], - 100 - ).id('kubejs:test_olive_to_oil_not_rotten'); - - // 测试2:小麦面粉混合配方(16个新鲜小麦面粉 + 水 → 啤酒) - event.recipes.create.mixing( - [Fluid.of('tfc:beer', 1000)], - [ - Ingredient.of({ - type: 'tfc:and', - children: [ - { item: 'tfc:food/wheat_flour' }, - { type: 'tfc:not_rotten' } - ] - }, 16), - Fluid.of('minecraft:water', 1000) - ], - 100 - ).id('kubejs:test_wheat_flour_to_beer_not_rotten'); - - // 测试3:小麦研磨配方(1个新鲜小麦种子 → 面粉) - event.recipes.create.milling( - ['tfc:food/wheat_flour'], - [ - Ingredient.of({ - type: 'tfc:and', - children: [ - { item: 'tfc:food/wheat_grain' }, - { type: 'tfc:not_rotten' } - ] - }) - ], - 50 - ).id('kubejs:test_wheat_grain_to_flour_not_rotten'); - - console.info('[生物柴油修复测试] 所有配方创建完成!'); -}); diff --git a/server_scripts/test_tfc_modifiers.js.faild b/server_scripts/test_tfc_modifiers.js.faild deleted file mode 100644 index f43f517..0000000 --- a/server_scripts/test_tfc_modifiers.js.faild +++ /dev/null @@ -1,32 +0,0 @@ -// ============================================================================ -// 测试TFC修饰符格式是否被CDG支持 -// ============================================================================ - -ServerEvents.recipes(event => { - console.info('[生物柴油修复] 开始测试TFC修饰符格式...'); - - // 测试black_dyeable - 带TFC修饰符的输出 - event.custom({ - type: 'createdieselgenerators:basin_fermenting', - ingredients: [ - { tag: 'minecraft:dyeable' }, - { - type: 'fluid_stack', - fluid: 'tfc:black_dye', - amount: 25 - } - ], - processing_time: Math.max(100, Math.round(1200 / 5)), - results: [ - { - item: 'minecraft:leather', // 试试直接用item字段 - modifiers: [ - { type: 'tfc:copy_input' }, - { type: 'tfc:dye_leather', color: 'black' } - ] - } - ] - }).id('kubejs:test/black_dyeable_with_modifiers'); - - console.info('[生物柴油修复] TFC修饰符格式测试完成!'); -}); From a5d5a31d737b53d6dae9b63387a174849d414d34 Mon Sep 17 00:00:00 2001 From: dalizi2333 Date: Mon, 18 May 2026 13:24:24 +0000 Subject: [PATCH 08/10] =?UTF-8?q?=E5=BA=94=E7=BE=A4=E5=8F=8B=E8=A6=81?= =?UTF-8?q?=E6=B1=82=EF=BC=8C=E4=BF=AE=E6=94=B9=E7=A0=82=E6=B5=86=E7=9A=84?= =?UTF-8?q?=E5=90=88=E6=88=90=E6=96=B9=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fermenting_from_barrel.js | 23 +++++-------------- .../mortar_to_mixing.js | 6 +++++ 2 files changed, 12 insertions(+), 17 deletions(-) rename server_scripts/{biodiesel_fix => barrel_sealed_migration}/fermenting_from_barrel.js (97%) create mode 100644 server_scripts/barrel_sealed_migration/mortar_to_mixing.js diff --git a/server_scripts/biodiesel_fix/fermenting_from_barrel.js b/server_scripts/barrel_sealed_migration/fermenting_from_barrel.js similarity index 97% rename from server_scripts/biodiesel_fix/fermenting_from_barrel.js rename to server_scripts/barrel_sealed_migration/fermenting_from_barrel.js index bae2a36..07e7aed 100644 --- a/server_scripts/biodiesel_fix/fermenting_from_barrel.js +++ b/server_scripts/barrel_sealed_migration/fermenting_from_barrel.js @@ -173,15 +173,6 @@ function calculateBulkBase(recipeData) { return base; } -/** - * 判断是否为mortar配方(输出过多,需限制倍率为6) - * @param {Object} recipeData - 配方数据 - * @returns {boolean} - */ -function isMortar(recipeData) { - return recipeData.recipeId === 'tfc:barrel/mortar'; -} - /** * 判断是否为陈酿酒配方(物品×1,流体×3.6的特殊倍率) * @param {Object} recipeData - 配方数据 @@ -197,7 +188,7 @@ function isAgedAlcohol(recipeData) { /** * 解析Bulk配方的倍率参数 - * 特殊配方(mortar/陈酿酒)整体覆盖所有倍率并跳过通用策略; + * 特殊配方(陈酿酒)整体覆盖所有倍率并跳过通用策略; * 通用配方依次应用流体增益(×2)和满池返还(向上取整到1000的倍数) * @param {Object} recipeData - 配方数据(会被修改) */ @@ -206,13 +197,6 @@ function resolveBulkParams(recipeData) { var hasInputFluid = recipeData.inputFluid && recipeData.inputFluid.amount > 0; var hasOutputFluid = recipeData.outputFluid && recipeData.outputFluid.amount > 0; - if (isMortar(recipeData)) { - recipeData.itemMultiplier = 6; - recipeData.fluidMultiplier = 6; - recipeData.fluidAddition = 0; - return; - } - if (isAgedAlcohol(recipeData)) { recipeData.itemMultiplier = 1; recipeData.fluidMultiplier = 3.6; @@ -447,6 +431,11 @@ function convertSingleRecipe(data, recipe) { return; } + if (recipeData.recipeId === 'tfc:barrel/mortar') { + data.stats.skipped++; + return; + } + recipeData.basinMaxMultiplier = calculateBasinMaxMultiplier(recipeData, data); recipeData.basinMultiplier = Math.floor(recipeData.basinMaxMultiplier); diff --git a/server_scripts/barrel_sealed_migration/mortar_to_mixing.js b/server_scripts/barrel_sealed_migration/mortar_to_mixing.js new file mode 100644 index 0000000..dcf057e --- /dev/null +++ b/server_scripts/barrel_sealed_migration/mortar_to_mixing.js @@ -0,0 +1,6 @@ +ServerEvents.recipes(event => { + event.recipes.create.mixing( + [Item.of('tfc:mortar', 64)], + [Ingredient.of('#c:sands', 4), Fluid.of('tfc:limewater', 400)] + ).id('kubejs:tfc_barrel_sealed/mixing/mortar') +}) From 90322940da845cc92e1d2b031a766c42ce2345ac Mon Sep 17 00:00:00 2001 From: dalizi2333 Date: Mon, 18 May 2026 14:43:20 +0000 Subject: [PATCH 09/10] =?UTF-8?q?=E8=A1=A5=E5=85=85=E9=98=BB=E6=96=AD?= =?UTF-8?q?=E6=97=A0=E8=BE=93=E5=87=BA=E4=BB=85trait=E4=BF=AE=E9=A5=B0?= =?UTF-8?q?=E7=9A=84=E5=AF=86=E5=B0=81=E5=A4=A7=E6=A1=B6=E9=85=8D=E6=96=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../barrel_sealed_migration/fermenting_from_barrel.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/server_scripts/barrel_sealed_migration/fermenting_from_barrel.js b/server_scripts/barrel_sealed_migration/fermenting_from_barrel.js index 07e7aed..081263d 100644 --- a/server_scripts/barrel_sealed_migration/fermenting_from_barrel.js +++ b/server_scripts/barrel_sealed_migration/fermenting_from_barrel.js @@ -431,6 +431,11 @@ function convertSingleRecipe(data, recipe) { return; } + if (!recipeData.outputItem && !recipeData.outputFluid) { + data.stats.skipped++; + return; + } + if (recipeData.recipeId === 'tfc:barrel/mortar') { data.stats.skipped++; return; From 736017c2a11a90289a39157f61a15d464f627b9b Mon Sep 17 00:00:00 2001 From: dalizi2333 Date: Tue, 19 May 2026 12:03:14 +0000 Subject: [PATCH 10/10] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=A0=87=E7=AD=BE?= =?UTF-8?q?=E5=A0=86=E5=8F=A0=E9=99=90=E5=88=B6=E8=8E=B7=E5=8F=96=E5=92=8C?= =?UTF-8?q?children=E7=B1=BB=E5=9E=8B=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fermenting_from_barrel.js | 48 ++++++++++++++----- 1 file changed, 35 insertions(+), 13 deletions(-) diff --git a/server_scripts/barrel_sealed_migration/fermenting_from_barrel.js b/server_scripts/barrel_sealed_migration/fermenting_from_barrel.js index 081263d..8be59ad 100644 --- a/server_scripts/barrel_sealed_migration/fermenting_from_barrel.js +++ b/server_scripts/barrel_sealed_migration/fermenting_from_barrel.js @@ -77,12 +77,26 @@ function parseJsonField(json, fieldName) { * @returns {number|null} 最大堆叠数 */ function getMaxStackSize(itemData) { + if (itemData.children && itemData.children.length > 0) { + var minStack = 64; + for (var i = 0; i < itemData.children.length; i++) { + var child = itemData.children[i]; + if (child.item || child.tag || (child.children && child.children.length > 0)) { + var childStack = getMaxStackSize(child); + if (childStack !== null && childStack < minStack) { + minStack = childStack; + } + } + } + return minStack; + } + var itemId = itemData.item || itemData.tag; if (!itemId) return null; try { if (itemData.tag) { - var tagItems = Ingredient.of('#' + itemData.tag).items; + var tagItems = Ingredient.of('#' + itemData.tag).stackArray; if (tagItems && tagItems.length > 0) { var minStack = tagItems[0].getMaxStackSize(); for (var i = 1; i < tagItems.length; i++) { @@ -112,13 +126,10 @@ function calculateBasinMaxMultiplier(recipeData, data) { var maxMultiplier = Infinity; if (recipeData.inputItem) { - var itemId = recipeData.inputItem.item || recipeData.inputItem.tag; - if (itemId) { + var maxStack = getMaxStackSize(recipeData.inputItem); + if (maxStack) { var count = recipeData.inputItem.count || 1; - var maxStack = getMaxStackSize(recipeData.inputItem); - if (maxStack) { - maxMultiplier = Math.min(maxMultiplier, maxStack / count); - } + maxMultiplier = Math.min(maxMultiplier, maxStack / count); } } @@ -173,6 +184,15 @@ function calculateBulkBase(recipeData) { return base; } +/** + * 判断是否为mortar配方(输出过多,需限制倍率为6) + * @param {Object} recipeData - 配方数据 + * @returns {boolean} + */ +function isMortar(recipeData) { + return recipeData.recipeId === 'tfc:barrel/mortar'; +} + /** * 判断是否为陈酿酒配方(物品×1,流体×3.6的特殊倍率) * @param {Object} recipeData - 配方数据 @@ -188,7 +208,7 @@ function isAgedAlcohol(recipeData) { /** * 解析Bulk配方的倍率参数 - * 特殊配方(陈酿酒)整体覆盖所有倍率并跳过通用策略; + * 特殊配方(mortar/陈酿酒)整体覆盖所有倍率并跳过通用策略; * 通用配方依次应用流体增益(×2)和满池返还(向上取整到1000的倍数) * @param {Object} recipeData - 配方数据(会被修改) */ @@ -197,6 +217,13 @@ function resolveBulkParams(recipeData) { var hasInputFluid = recipeData.inputFluid && recipeData.inputFluid.amount > 0; var hasOutputFluid = recipeData.outputFluid && recipeData.outputFluid.amount > 0; + if (isMortar(recipeData)) { + recipeData.itemMultiplier = 6; + recipeData.fluidMultiplier = 6; + recipeData.fluidAddition = 0; + return; + } + if (isAgedAlcohol(recipeData)) { recipeData.itemMultiplier = 1; recipeData.fluidMultiplier = 3.6; @@ -436,11 +463,6 @@ function convertSingleRecipe(data, recipe) { return; } - if (recipeData.recipeId === 'tfc:barrel/mortar') { - data.stats.skipped++; - return; - } - recipeData.basinMaxMultiplier = calculateBasinMaxMultiplier(recipeData, data); recipeData.basinMultiplier = Math.floor(recipeData.basinMaxMultiplier);