Skip to content

Add Ex Nihilo Creatio integration - #15

Open
MrKono wants to merge 12 commits into
masterfrom
kono/addExNihiloCreatioIntegration
Open

Add Ex Nihilo Creatio integration#15
MrKono wants to merge 12 commits into
masterfrom
kono/addExNihiloCreatioIntegration

Conversation

@MrKono

@MrKono MrKono commented Aug 4, 2026

Copy link
Copy Markdown
Member
  • add crook
  • add hammering compatibility
  • add sieving compatibility (will be removed)

@MrKono
MrKono requested a review from tier940 August 4, 2026 14:07
builder.outputs(siftable.getDrop().getItemStack());
} else {
builder.chancedOutput(siftable.getDrop().getItemStack(),
(int) (siftable.getChance() * 10000), 500);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[要対応] chance が 0 に丸められるとロード時クラッシュの可能性があります。

register() は Ex Nihilo の SieveRegistry 全体(config で追加した分だけでなく、Ex Nihilo 本体や他 MOD が登録した siftable すべて)をミラーします。そのうち確率が 0.01%(0.0001)未満 のドロップがあると、(int)(siftable.getChance() * 10000)0 に丸められます。

GTCEu の RecipeBuilder.chancedOutputchance <= 0 を渡すと recipeStatus = INVALID をセットし、これが RecipeMap.setFoundInvalidRecipe(true) まで伝播して、通常環境(ignoreErrorOrInvalidRecipes = false)では最終的に LoaderException でロードが中断されます(=ハードクラッシュ)。破棄されるのは該当ドロップだけでなく レシピ1件まるごと です。

同梱 config のデフォルト値は最小 0.0004(→4)なので config 経由では発火しませんが、ミラー対象の確率はランタイムのレジストリ内容に依存するため潜在的です。0.01% 未満の確率を持つ MOD/パックと組み合わせると発火します。

Suggested change
(int) (siftable.getChance() * 10000), 500);
builder.chancedOutput(siftable.getDrop().getItemStack(),
Math.max(1, (int) (siftable.getChance() * 10000)), 500);

(丸めて 0 になるドロップは登録せず continue でスキップする方針でも構いません。)

'R', new UnificationEntry(OrePrefix.stick, Materials.Wood));

ModHandler.removeRecipeByOutput(Mods.ExNihilo.getItem("crook_iron"));
ModHandler.addShapedRecipe("crook_diamond", ExNihiloToolsItems.CROOK.get(Materials.Iron),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[要対応] replaceCrook=true のときレシピ登録名が衝突します(この行は typo で "crook_iron" が正しい)。

registerRecipes()ループ(L19-24)→ replaceCrooks()(L26-28)の順 で実行されます。replaceCrook=true だと crooks() のガード !replaceCrook && ...(L32-33)が早期 return しないため、ループが先に crook_ironcrook_diamond(どちらも出力は CROOK.get(material))を登録します。

GTCEu の ModHandler.addShapedRecipe同名 regName を先勝ちで扱い、後続の登録は WARN ログ(スタックトレース付き)を出して破棄 します(クラッシュも上書きもしません)。そのため replaceCrooks() 内の

  • この行(Iron を、typo で "crook_diamond" 名で登録)
  • L71-74(Diamond を "crook_diamond" 名で登録)

両方ともループ登録済みの crook_diamond に負けて破棄 されます。

一方 Gold / Wood は PropertyKey.TOOL を持たずループに入らないため、crook_gold(L53-56)と crook_wood(L60-64)だけは意図通り登録されます。

→ 実害: replaceCrook=true のとき Iron/Diamond の置換登録が すべて無駄撃ち+ログスパム(結果はループ版と同一なので見た目は動いてしまう)。この行の typo はその症状です。

修正の方向性(いずれか):

  1. crooks() のガードを見直し、replaceCrook=true のときは Iron/Gold/Diamond をループ側でスキップして、登録名の所有権を replaceCrooks() に渡す。
  2. replaceCrooks() を廃止し、置換ロジックをループ本体に一本化する。
  3. 最低限この行を "crook_iron" に直す(ただし上記の実行順序を直さない限り、依然としてループ版に負けて破棄される点に注意)。

}
}
}
SIEVE_DROPS_MAP = null;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[軽微] static マップを null 化するとライフサイクルに脆くなります。

registerRecipeDefaults() の末尾で SIEVE_DROPS_MAPnull にしていますが、もし readSieveDropsFromConfig()(L46)が何らかの理由で再度呼ばれると、putIfAbsent(L66-67)で NullPointerException になります。static な可変状態+呼び出し順序への暗黙依存で、将来の変更に弱いです。

提案: null 代入の代わりに SIEVE_DROPS_MAP.clear() を使う、または「消費済み」フラグを別に持って二重実行を冪等にする。

registry.register(drops.getKey().getName(), new ItemInfo(stack.getItem(), stack.getMetadata()),
drop.getChance(), drop.getMeshLevel());
} else {
registry.register(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[軽微] explicitInput 系がデッドコードで、ロジックが二重管理になっています。

enum に explicitInput フィールドと hasExplicitInput()(L200-202)/ getExplicitInput()(L204-206)を用意しているのに、この L152-159 の分岐はそれらを使わず、SieveDropType.END / NETHERRACK を直接比較して三項演算子で ModBlocks.endstoneCrushed / netherrackCrushed を参照しています。

そのため enum のフィールド/メソッドは未使用のデッドコードになり、「どの入力ブロックを使うか」のロジックが enum 定義側と分岐側の2箇所に分散しています。

提案: この分岐を type.hasExplicitInput() / type.getExplicitInput() を使う形に統一するか、使わないなら enum 側の未使用フィールド・メソッドを削除する。

public static final String ENDER_MACHINES = "enderiomachines";
public static final String ENDER_CONDUITS = "enderioconduits";
public static final String ENDER_AE2_CONDUITS = "enderioconduitsappliedenergistics";
public static final String EX_NIHOLO = "exnihilocreatio";

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nit] 定数名のスペルミス: EX_NIHOLOEX_NIHILO

値は "exnihilocreatio" で正しいので動作には影響ありませんが、NIHILO の綴りが NIHOLO になっています。直す場合は参照側(L47 ExNihilo(Names.EX_NIHOLO))も併せて更新が必要です。

@tier940

tier940 commented Aug 4, 2026

Copy link
Copy Markdown
Member

Ex Nihilo Creatio 連携、丁寧に作られていて良いと思います 👍(モジュール分割・LICENSE 表記・README/CHANGELOG・en/ja 両対応・config 経由の Sieve ドロップ設定・診断用 VeinProbabilityReporter など)。

GTCEu 側のソース(ModHandler / RecipeBuilder / StoneVariantBlock / Materials)を実際に確認したうえで、いくつか指摘を残します。

要対応

  • [1] ExNihiloSieveRecipe: chancedOutput に確率0が渡ると GTCEu 側でレシピ全体が INVALID 破棄 → デフォルト環境でロード時クラッシュの可能性(潜在)。
  • [2] ExNihiloToolRecipe: replaceCrook=true のときレシピ登録名が衝突し、replaceCrooks() の Iron/Diamond 分は破棄される(L67 は typo)。

軽微

  • [3] VeinProbabilityReporter(Overflow) ラベルがラッチする(ログのみ)
  • [4] SieveDrops の static マップ null 化がライフサイクルに脆い
  • [5] SieveDropType.explicitInput 系がデッドコード+ロジック重複
  • [6] Mods.EX_NIHOLO のスペルミス(nit)

確認済みで問題なし: pebble→cobble のマッピングは StoneVariantBlock.StoneType の並び(BLACK_GRANITE, RED_GRANITE, MARBLE, BASALT)と一致しており正しいです。

詳細は各行のコメントに記載しました。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants