MultiBlockSystem
No reviews yet
Provides the foundation for building multiblocks.
Forge is a popular mod loader for versions 1.1+ of Minecraft.
Community voices
Reviews
Click once to include, again to exclude, again to clear
No reviews yet. Be the first to review this project!
Get it on
Available Platforms
About
Project Details
For authors
Embed Badge
If you're the author of this project, you can embed a live badge anywhere that supports HTML or Markdown. It updates automatically whenever ratings change.
Use HTML for any page that supports it, or Markdown for README files and Markdown-based descriptions.
Identifiers
Platform IDs
Resources
External Links
About
Description
Developers, please run command /mbs display true first.
MultiBlockSystem
MultiBlockSystem is a robust framework designed for modders and pack makers to create, validate, and distribute complex, custom multi-block structures with ease. By providing a streamlined toolset, this mod turns the process of building massive, intricate machines into a secure and highly optimized experience.
✨ Features
Flexible Pattern Design: Utilize a simple, intuitive string-based system to define your multi-block patterns, supporting everything from basic machinery to colossal, multi-layered structures.
Advanced Structure Validation: The system provides powerful visual feedback, allowing builders to toggle validation displays to ensure every block is placed exactly where it needs to be.
High-Performance Scanning: With intelligent, background-based asynchronous scanning, the mod captures massive structure designs without impacting server performance, even for the most complex builds.
Secure Distribution: Built-in obfuscation and compression ensure that your custom structure definitions are compact and secure, making it ideal for modpack developers to include unique, proprietary content.
Modder-Friendly Command Suite: A comprehensive command-line interface allows for rapid exporting, reloading, and configuration management without ever needing to restart the game.
1. 他Modからの登録方法
build.gradle(ソフト依存)
dependencies {
// compileOnly でソフト依存(ゲームにこのModがなくても起動できる)
compileOnly fg.deobf("com.multiblocksystem:multiblocksystem:1.0.0:api")
}
mods.toml
[[dependencies.yourmod]]
modId="multiblocksystem"
mandatory=false # ソフト依存 = このModがなくても起動可能
versionRange="[1.0,)"
ordering="BEFORE"
side="BOTH"
登録コード
// YourMod.java
@Mod("yourmod")
public class YourMod {
public YourMod() {
FMLJavaModLoadingContext.get().getModEventBus()
.addListener(this::onCommonSetup);
}
private void onCommonSetup(FMLCommonSetupEvent event) {
event.enqueueWork(() -> {
if (!ModList.get().isLoaded("multiblocksystem")) return;
YourMultiBlockSetup.register();
});
}
}
// YourMultiBlockSetup.java
public class YourMultiBlockSetup {
public static void register() {
// ===== 1. コントローラーブロックを登録 =====
MultiBlockRegistry.registerAsController(
new ResourceLocation("yourmod", "blast_furnace_controller"),
new BlastFurnaceControllerBehavior()
);
// ===== 2. 自分のブロックを INPUT として登録 =====
// IItemHandler Capability を持つなら1行で OK
MultiBlockRegistry.registerAsLinkable(
new ResourceLocation("yourmod", "input_hopper"),
LinkRole.INPUT,
LinkableBehavior.fromForgeCapability()
);
// ===== 3. バニラのチェストを INPUT として登録 =====
// (バニラブロックも登録できる)
MultiBlockRegistry.registerAsLinkable(
Blocks.CHEST,
LinkRole.INPUT,
LinkableBehavior.fromForgeCapability()
);
// ===== 4. 独自ストレージの場合は自前実装 =====
MultiBlockRegistry.registerAsLinkable(
new ResourceLocation("yourmod", "big_tank"),
LinkRole.FUEL,
new LinkableBehavior() {
@Override
public IFluidStorage getFluidStorage(Level level, BlockPos pos) {
BlockEntity be = level.getBlockEntity(pos);
if (be instanceof BigTankBlockEntity tank) {
return tank.getFluidStorage();
}
return null;
}
@Override
public boolean hasFluidStorage() { return true; }
@Override
public boolean hasItemStorage() { return false; }
}
);
// ===== 5. 構造体形状の登録 =====
MultiBlockRegistry.registerStructure(
new ResourceLocation("yourmod", "blast_furnace"),
StructureDefinition.fromPattern(
List.of(
new String[]{"FFF", "FCF", "FFF"}, // Y=0
new String[]{" ", " . ", " "} // Y=1
),
Map.of(
'F', Blocks.BLAST_FURNACE.defaultBlockState(),
'C', YourBlocks.BLAST_FURNACE_CONTROLLER.get().defaultBlockState()
),
'C'
),
new CapabilitySpec()
.require(LinkRole.INPUT, 1)
.require(LinkRole.OUTPUT, 1)
);
// ===== 6. ポートブロックを登録(4ティア対応) =====
// Tier 1: ブロッククラスに IPortBlock を直接実装する方法
// Tier 2: API で登録する方法(下記)
// Tier 3: Forge Capability があれば自動対応(IItemHandler/IEnergyStorage/IFluidHandler)
// Tier 4: データパックの Block Tags で登録する方法(data/multiblocksystem/tags/blocks/multiblock_ports.json)
MultiBlockRegistry.registerPort(
new ResourceLocation("yourmod", "item_input_port"),
PortRegistry.get(new ResourceLocation("multiblocksystem", "item_input"))
);
MultiBlockRegistry.registerPort(
new ResourceLocation("yourmod", "energy_output_port"),
PortRegistry.get(new ResourceLocation("multiblocksystem", "energy_output"))
);
}
}
2. ControllerBehavior の実装例
public class BlastFurnaceControllerBehavior implements ControllerBehavior {
@Override
public ResourceLocation getDefaultStructureId() {
return new ResourceLocation("yourmod", "blast_furnace");
}
@Override
public void onFormed(Level level, BlockPos pos, IMultiBlockNetwork network) {
BlockEntity be = level.getBlockEntity(pos);
if (be instanceof BlastFurnaceControllerBE ctrl) {
ctrl.setFormed(true);
}
}
@Override
public void onBroken(Level level, BlockPos pos, IMultiBlockNetwork network) {
BlockEntity be = level.getBlockEntity(pos);
if (be instanceof BlastFurnaceControllerBE ctrl) {
ctrl.setFormed(false);
}
}
@Override
public void tick(Level level, BlockPos pos, IMultiBlockNetwork network) {
IItemStorage input = network.getItemStorage(LinkRole.INPUT);
IItemStorage output = network.getItemStorage(LinkRole.OUTPUT);
Amount inputCost = Amount.of(3);
Amount outputYield = Amount.of(5);
boolean canRun = network.canProcess(
List.of(IBigItemStack.of(Items.IRON_ORE, inputCost)),
List.of(IBigItemStack.of(Items.IRON_INGOT, outputYield))
);
if (!canRun) return;
// 1/3 FE/tick 消費するレシピ
Amount energyCost = Amount.of(1, 3);
Amount consumed = network.consumeEnergy(energyCost, true);
if (!consumed.isGreaterThanOrEqual(energyCost)) return;
network.consumeEnergy(energyCost, false);
network.processTransfer(
List.of(IBigItemStack.of(Items.IRON_ORE, inputCost)),
List.of(IBigItemStack.of(Items.IRON_INGOT, outputYield))
);
}
}
3. Amount 計算の具体例
Amount はシールド・インターフェース(sealed interface)であり、 2つの record クラスに実装が限定される:
| 実装 | 内部表現 | 用途 |
|---|---|---|
LongAmount |
long numerator / denominator |
一般的な値(高速) |
BigAmount |
BigInteger numerator / denominator |
long を超える超大値 |
ファクトリメソッド (Amount.of(...)) で自動的に最適な実装が選択され、 計算結果が long の範囲に収まる場合は BigAmount → LongAmount にダウングレードされる。
// 整数
Amount a = Amount.of(100); // → LongAmount(100, 1)
Amount b = Amount.of(3); // → LongAmount(3, 1)
// 分数
Amount oneThird = Amount.of(1, 3); // → LongAmount(1, 3)
Amount twoThirds = Amount.of(2, 3); // → LongAmount(2, 3)
Amount half = Amount.of(1, 2); // → LongAmount(1, 2)
// 四則演算(全て新しい Amount を返す不変操作)
Amount sum = oneThird.add(twoThirds); // 1/3 + 2/3 = 1 → LongAmount(1, 1)
Amount diff = a.subtract(b); // 100 - 3 = 97
Amount product = oneThird.multiply(3); // 1/3 * 3 = 1(誤差ゼロ)
Amount quotient = a.divide(b); // 100 / 3 = 100/3
// 比較
boolean gt = a.isGreaterThan(b); // true
boolean gte = oneThird.isGreaterThanOrEqual(half); // false
boolean eq = product.equals(Amount.ONE); // true
// 変換
BigInteger val1 = product.floor(); // BigInteger(1)
BigInteger val2 = quotient.ceil(); // BigInteger(34)
double val3 = oneThird.toDouble(); // 0.33333...(表示用)
// 表示
System.out.println(oneThird.toDisplayString()); // "1/3 (≈0.333333)"
System.out.println(product.toDisplayString()); // "1"
System.out.println(quotient.toDisplayString()); // "100/3 (≈33.333333)"
// 文字列シリアライズ(JSON 保存用)
String json = oneThird.toSerialString(); // "1/3"
Amount restored = Amount.fromSerialString(json); // → LongAmount(1, 3)
// NBT シリアライズ
CompoundTag tag = oneThird.toNbt();
Amount fromTag = Amount.fromNbt(tag);
// エネルギー効率計算(誤差ゼロ)
Amount efficiency = Amount.of(2, 3); // 66.666...%
Amount baseCost = Amount.of(100);
Amount actualCost = baseCost.multiply(efficiency); // 200/3 FE
long floorCost = actualCost.floor().longValueExact(); // 66(Minecraft へ書き出し時のみ)
LongAmount の自動昇格
LongAmount は Math.multiplyExact / Math.addExact でオーバーフロー検出を行い、 結果が long の範囲外の場合に自動的に BigAmount に昇格する:
Amount huge = Amount.of(Long.MAX_VALUE);
Amount one = Amount.of(1);
Amount result = huge.add(one); // → BigAmount (long に収まらないため自動昇格)
BigAmount の自動ダウングレード
BigAmount は計算結果の分子・分母が共に long の範囲に収まる場合、 自動的に LongAmount にダウングレードする:
Amount big = Amount.of(BigInteger.valueOf(99999999999L), BigInteger.valueOf(3));
Amount small = Amount.of(3);
Amount result = big.multiply(small); // → LongAmount (結果が long に収まるため)
4. /mbs コマンドリファレンス
MultiBlockSystem は以下のサーバーコマンドを提供する:
/mbs export
指定範囲のブロックをスキャンし、マルチブロック定義ファイルを生成する。
/mbs export <pos1> <pos2> <core> <filename> [ex1_pos1] [ex1_pos2] ... [exN_pos1] [exN_pos2]
| 引数 | 型 | 必須 | 説明 |
|---|---|---|---|
pos1 |
BlockPos | はい | スキャン範囲の角座標(相対座標 ~ ~ ~ 対応) |
pos2 |
BlockPos | はい | スキャン範囲のもう一方の角座標 |
core |
BlockPos | はい | コントローラーブロックの座標(相対座標の原点) |
filename |
String | はい | 出力ファイル名(.json 拡張子不要) |
exN_pos1 |
BlockPos | いいえ | 除外範囲 N の角座標(Tab 補完対応) |
exN_pos2 |
BlockPos | いいえ | 除外範囲 N のもう一方の角座標 |
除外範囲: 各 ex_pos1 / ex_pos2 ペアで定義される AABB(軸並行バウンディングボックス)内のブロックはスキャン対象外になる。 最大 200 個の除外範囲を指定可能(Forge のコマンドツリー再帰深度制限による)。
# 基本例
/mbs export ~ ~ ~ ~10 ~10 ~10 ~ ~5 my_structure
# 除外範囲付き例(150階〜300階を除外)
/mbs export 0 0 0 100 300 100 ~ ~150 my_tower 0 150 0 100 300 100
/mbs reload
ディスク上のマルチブロック定義ファイルを再読み込みする。
/mbs reload
multiblocks/ ディレクトリ内の全 .json ファイルを再スキャンし、 構造体定義を更新する。コントローラーやリンクブロックの登録はクリアされない (FMLCommonSetupEvent で一度だけ登録されるため)。
/mbs display
正誤判定の表示フラグを切り替える。
/mbs display [enabled]
| 引数 | 型 | 必須 | 説明 |
|---|---|---|---|
enabled |
boolean | いいえ | true で表示ON、false で表示OFF |
パラメータなしで実行すると現在の状態を表示する。
5. BigInteger ストレージ対応
IBigIntegerItemHandler
IBigIntegerItemHandler は Forge の IItemHandler を BigInteger スケールに拡張する ダック・インターフェース(IItemHandler を直接継承)。
| メソッド | 説明 |
|---|---|
getSlotLimitBig(int slot) |
スロットの最大容量を BigInteger で返す |
insertItemBig(int slot, ItemStack, BigInteger, boolean) |
BigInteger スケールでアイテムを挿入 |
extractItemBig(int slot, Item, BigInteger, boolean) |
BigInteger スケールでアイテムを抽出 |
getTotalCountBig(Item) |
指定アイテムの全スロット合計保有量を BigInteger で返す |
全てのメソッドにデフォルト実装が含まれており、 未実装の IItemHandler でも long ベースのフォールバック動作が保証される。
MixinItemStackHandler
Forge の ItemStackHandler(concrete class)に IBigIntegerItemHandler を 自動的に付与する Mixin。
// multiblocksystem.mixins.json
{
"mixins": ["MixinItemStackHandler"]
}
ItemStackHandler は既に IItemHandler を実装しているため、 IBigIntegerItemHandler のデフォルトメソッドが getSlots(), insertItem(), getSlotLimit() 等を直接呼び出して BigInteger 操作を提供する。 マーカーのみの Mixin で、追加のコードは含まれない。
検出方法:
IItemHandler handler = ...;
if (handler instanceof IBigIntegerItemHandler bigHandler) {
// BigInteger スケールの操作を使用
BigInteger limit = bigHandler.getSlotLimitBig(slot);
} else {
// 通常の IItemHandler — ForgeItemHandlerAdapter が long ベースにフォールバック
}
ForgeItemHandlerAdapter の二重パス
ForgeItemHandlerAdapter は IItemHandler → IItemStorage ブリッジであり、 instanceof IBigIntegerItemHandler チェックで二重パス処理を行う:
- BigInteger 対応時:
IBigIntegerItemHandlerのメソッドを直接呼び出し - 未対応時:
longベースの集計にフォールバック
Forge の標準的な ItemStackHandler は Mixin 経由で自動的に BigInteger 対応となる。 独自の IItemHandler 実装を持つ Mod は IBigIntegerItemHandler を手動実装して BigInteger 操作を有効にできる。
6. KubeJS 統合
MultiBlockSystem は KubeJS に対してオプションなソフト依存として統合されている。 KubeJS が存在しない環境でも Mod は正常に動作する。
6.1 プラグイン登録
KubeJS は src/main/resources/kubejs.plugins.txt からプラグインを自動検出する:
// src/main/resources/kubejs.plugins.txt
com.multiblocksystem.kubejs.MultiBlockKubeJSPlugin multiblocksystem
6.2 KubeJSPlugin(Java側)
package com.multiblocksystem.kubejs;
import dev.latvian.mods.kubejs.KubeJSPlugin;
import dev.latvian.mods.kubejs.script.BindingsEvent;
import dev.latvian.mods.kubejs.script.ScriptType;
import com.multiblocksystem.api.behavior.LinkRole;
import com.multiblocksystem.CapabilitySpec;
public class MultiBlockKubeJSPlugin extends KubeJSPlugin {
@Override
public void registerBindings(BindingsEvent event) {
if (event.getType() != ScriptType.STARTUP) return;
event.add("MultiBlockRegistry", new MultiBlockRegistryJS());
event.add("LinkRole", LinkRole.class);
event.add("CapabilitySpec", CapabilitySpec.class);
}
}
注意: メソッド名は
registerBindingsでありaddBindingsではない。 KubeJS 2001.x (Forge 1.20.1) のKubeJSPluginベースクラスに定義されている。
6.3 登録アダプター(MultiBlockRegistryJS)
KubeJS スクリプトから呼び出されるラッパークラス。 String → ResourceLocation 変換、JS オブジェクト → BlockState 変換を担う。
| メソッド | 説明 |
|---|---|
registerController(String, ControllerBehavior) |
ブロックIDでコントローラーを登録 |
registerController(Block, ControllerBehavior) |
Block オブジェクトでコントローラーを登録 |
registerLinkable(String, LinkRole) |
ブロックIDでリンクブロックを登録(Forge IItemHandler 自動検出) |
registerLinkable(String, LinkRole, LinkableBehavior) |
ブロックIDでリンクブロックを登録(カスタム振る舞い) |
registerLinkable(Block, LinkRole) |
Block オブジェクトでリンクブロックを登録 |
registerPort(String, String) |
ブロックIDとポートTypeIDでポートブロックを登録 |
registerStructure(String, List<String[]>, Map, String) |
KubeJS 風の文字列パターンで構造体を登録 |
registerStructure(String, List<String[]>, Map, String, CapabilitySpec) |
構造体を登録(仕様付き) |
isController(String) |
指定ブロックがコントローラーとして登録されているか |
isLinkable(String) |
指定ブロックがリンクブロックとして登録されているか |
isPort(String) |
指定ブロックがポートとして登録されているか |
6.4 KubeJS スクリプト例(startup_scripts/my_multiblocks.js)
// KubeJS は MultiBlockSystem が読み込まれた後にスクリプトを実行するため、
// StartupEvents.postInit ではなく、直接グローバルから MultiBlockRegistry を使用可能。
// ===== コントローラーブロックを登録 =====
MultiBlockRegistry.registerController(
"mymod:blast_furnace_controller",
{
getDefaultStructureId: () => "mymod:blast_furnace",
onFormed: (level, pos, network) => {
console.log("Blast furnace formed at " + pos);
},
tick: (level, pos, network) => {
const input = network.getItemStorage(LinkRole.INPUT);
const output = network.getItemStorage(LinkRole.OUTPUT);
const cost = Amount.of(3);
const yield = Amount.of(5, 2);
const canRun = network.canProcess(
[{ item: "minecraft:iron_ore", count: cost }],
[{ item: "minecraft:iron_ingot", count: yield }]
);
if (!canRun) return;
network.processTransfer(
[{ item: "minecraft:iron_ore", count: cost }],
[{ item: "minecraft:iron_ingot", count: yield }]
);
}
}
);
// ===== バニラブロックをリンクブロックとして登録 =====
MultiBlockRegistry.registerLinkable("minecraft:chest", LinkRole.INPUT);
MultiBlockRegistry.registerLinkable("minecraft:barrel", LinkRole.OUTPUT);
// ===== ポートブロックを登録 =====
// 既に IPortBlock を実装していないブロックをポートとして認識させる
MultiBlockRegistry.registerPort("mymod:item_input_port", "multiblocksystem:item_input");
MultiBlockRegistry.registerPort("mymod:energy_output_port", "multiblocksystem:energy_output");
// ===== 構造体定義を登録 =====
MultiBlockRegistry.registerStructure(
"mymod:blast_furnace",
[
["FFF", "FCF", "FFF"],
[" ", " . ", " "]
],
{
"F": "minecraft:blast_furnace",
"C": "mymod:blast_furnace_controller"
},
"C",
new CapabilitySpec()
.require(LinkRole.INPUT, 1)
.require(LinkRole.OUTPUT, 1)
);
6.5 build.gradle 設定(KubeJS を使う場合)
repositories {
maven {
url "https://maven.latvian.dev/releases"
content { includeGroup "dev.latvian.mods" }
}
}
dependencies {
// KubeJS は compileOnly(ランタイムでは KubeJS 側が提供)
compileOnly fg.deobf("dev.latvian.mods:kubejs-forge:2001.6.5-build.26") {
transitive = false
}
}
API パッケージ:
dev.latvian.mods.kubejs.*(NOTdev.latvian.kubejs.*) Maven GAV:dev.latvian.mods:kubejs-forge:2001.6.5-build.26
7. Amount 計算の具体例(JS)
// JS 側での Amount 計算例
const a = Amount.of(1, 3); // 1/3
const b = Amount.of(1, 6); // 1/6
const c = a.add(b); // 1/3 + 1/6 = 1/2 ← 完全に正確
const d = a.multiply(3); // 1/3 * 3 = 1 ← 誤差ゼロ
console.log(c.toDisplayString()); // "1/2 (≈0.500000)"
console.log(d.toDisplayString()); // "1"
// エネルギー効率計算
const efficiency = Amount.of(2, 3); // 66.666...% efficiency
const baseCost = Amount.of(100); // 100 FE base cost
const actualCost = baseCost.multiply(efficiency); // 200/3 FE ← 誤差なし
// Minecraft への書き出し時のみ floor/ceil
const longCost = actualCost.floor(); // 66 (BigInteger)
8. 注意点
RegistryImpl.clearStructures() の使い方
/mbs reload では clearStructures() のみ呼ぶこと。 controllers と linkables は FMLCommonSetupEvent で登録されるため サーバーリロードでクリアしてはいけない。
Amount の GCD コス
LongAmount は long ベースの高速 GCD を使用するため、 一般的な値ではほぼ瞬時に計算される。 BigAmount のみ BigInteger.gcd() を使用し、O(log n) のコストがかかる。 毎フレーム大量に呼ぶ場合は final フィールドにキャッシュすること。
ForgeItemHandlerAdapter の集計上限
ForgeItemHandlerAdapter は IBigIntegerItemHandler を実装する IItemHandler を 検出した場合、BigInteger ベースの集計を使用する(理論上の上限なし)。 未対応の IItemHandler の場合は long で集計し、 合計容量は Long.MAX_VALUE(約 9.2×10¹⁸)まで対応している。 ただし個々のスロット操作は Forge の IItemHandler により int に制限されるため、 1スロットあたり Integer.MAX_VALUE 個が上限。 Forge の標準 ItemStackHandler は Mixin 経由で自動的に IBigIntegerItemHandler を 実装するため、デフォルトで BigInteger 対応となる。
StructureDefinition.fromPattern の文字エンコード
| 文字 | 意味 |
|---|---|
(スペース) |
Any(何でも可、判定対象外) |
. (ドット) |
Air(空気が必須) |
| それ以外 | dictionary で指定されたブロックが必須 |
| coreChar | コントローラー位置(相対座標の原点) |
ExcludeRegion の使い方
ExcludeRegion は AABB(軸並行バウンディングボックス)でスキャン対象外の領域を定義する。 /mbs export コマンドの除外引数で指定するか、 ChunkScanTask に List<ExcludeRegion> を渡して手動で使用できる。
9. API リファレンス
9.1 コア型
| クラス | パッケージ | 説明 |
|---|---|---|
Amount |
api.amount | 有理数型シールド・インターフェース。Amount.of(n) / Amount.of(n, d) で生成 |
LongAmount |
api.amount | long 分子/分母の record。オーバーフロー時に自動昇格 |
BigAmount |
api.amount | BigInteger 分子/分母の record。long に収まる結果は自動ダウングレード |
IBigItemStack |
api.amount | Item + Amount の组合。IBigItemStack.of(item, amount) で生成 |
CapabilitySpec |
root | マルチブロック成立に必要なリンク構成。.require(LinkRole, count) で追加 |
ExcludeRegion |
root | スキャン除外範囲(AABB) |
→ 計算例は セクション 3 を参照
9.2 リンクブロック用インターフェース(他Modが実装)
IMultiBlockController — コントローラー BlockEntity が実装
パッケージ: api.compat — セクション 1 の登録コード も参照
| メソッド | 引数 | 説明 |
|---|---|---|
addLink(BlockPos, LinkRole) |
リンクブロック座標, ロール | リンクブロックの接続を記録 |
removeLink(BlockPos) |
リンクブロック座標 | リンクを解除 |
hasLink(BlockPos) |
ブロック座標 | 指定座標がリンク済みか |
getLinkedBlocks() |
— | 全リンク先の Map<BlockPos, LinkRole> を返す |
使い方: 自分の BlockEntity が
AbstractMultiBlockControllerを継承すれば自動実装される。 手動実装する場合はIMultiBlockControllerを直接 implements する。
IMultiBlockLink — リンクブロックの BlockEntity が実装
パッケージ: api.compat
| メソッド | 引数 | 戻り値 | 説明 |
|---|---|---|---|
connectToController(BlockPos, LinkRole) |
コントローラー座標, ロール | void | コントローラーへの接続を記録 |
disconnectController() |
— | void | 接続を解除 |
isConnected() |
— | boolean | コントローラーに接続中か |
getControllerPos() |
— | @Nullable BlockPos |
接続先コントローラー座標 |
getRole() |
— | LinkRole | 現在のロール |
getItemHandler() |
— | IItemHandler | Forge の IItemHandler を返す |
使い方: 自分の BlockEntity が
AbstractLinkBlockEntityを継承すれば自動実装される。
9.3 抽象基底クラス(継承して使う)
AbstractMultiBlockController — コントローラー BlockEntity の基底
パッケージ: com.multiblocksystem(ルート)
| メソッド | 種別 | 説明 |
|---|---|---|
tick() |
concrete | メインループ。40tickごとに構造チェック、成立中に processRecipes() を呼ぶ |
onFormationChanged(boolean formed) |
protected, override推奨 | 構造の成立状態が変化した時のコールバック |
isFormed() |
concrete | 現在構造が成立しているか |
getInventoryForRole(LinkRole) |
concrete | 指定ロールのアグリゲート IItemHandler |
getInputInventory() / getOutputInventory() |
concrete | よく使うロールのショートカット |
getTemplateId() |
concrete | 紐付いた構造定義の ResourceLocation |
setTemplateId(ResourceLocation) |
concrete | 構造定義を手動指定 |
継承時の最低実装:
public class MyControllerBE extends AbstractMultiBlockController {
public MyControllerBE(BlockPos pos, BlockState state) {
super(MY_BE_TYPE.get(), pos, state);
}
@Override
protected void onFormationChanged(boolean formed) {
// 構造が成立/崩壊した時の処理(GUI更新、パーティクル等)
}
}
詳細は セクション 1 の登録コード / セクション 2 の実装例 を参照
AbstractLinkBlockEntity — リンクブロックの BlockEntity の基底
パッケージ: com.multiblocksystem(ルート)
| メソッド | 種別 | 説明 |
|---|---|---|
connectToController(...) / disconnectController() |
concrete | IMultiBlockLink の実装 |
isConnected() / getControllerPos() / getRole() |
concrete | 接続状態の取得 |
getItemHandler() |
concrete | 内部の ItemStackHandler を返す(スロット数: DEFAULT_SLOTS = 9) |
onConnected(LinkRole role) |
protected, override推奨 | 接続時のコールバック |
onDisconnected() |
protected, override推奨 | 切断時のコールバック |
onDestroyed(Level) |
concrete | Block.onRemove から呼ぶとコントローラーへ通知 |
継承時の最低実装:
public class MyLinkBE extends AbstractLinkBlockEntity {
public MyLinkBE(BlockPos pos, BlockState state) {
super(MY_BE_TYPE.get(), pos, state);
}
@Override
protected void onConnected(LinkRole role) {
// 接続時の処理(視覚エフェクト等)
}
}
9.4 振る舞い定義インターフェース(デリゲーション用)
ControllerBehavior — コントローラーの振る舞い
パッケージ: api.behavior — 全メソッドにデフォルト実装あり
| メソッド | 引数 | 説明 |
|---|---|---|
onFormed(Level, BlockPos, IMultiBlockNetwork) |
構造成立時に呼ばれる | |
onBroken(Level, BlockPos, IMultiBlockNetwork) |
構造崩壊時に呼ばれる | |
onLinked(Level, BlockPos, BlockPos, LinkRole, IMultiBlockNetwork) |
リンク接続時に呼ばれる | |
onUnlinked(Level, BlockPos, BlockPos, LinkRole, IMultiBlockNetwork) |
リンク切断時に呼ばれる | |
tick(Level, BlockPos, IMultiBlockNetwork) |
成立中の毎tick呼ばれる | |
getDefaultStructureId() |
担当構造の ID(null で自動判定) | |
getValidStructureIds() |
担当できる構造の ID セット | |
ControllerBehavior.simple(String) |
static | 最小構成のファクトリ |
詳細は セクション 2 を参照
LinkableBehavior — リンクブロックの振る舞い
パッケージ: api.behavior — ストレージ取得は全て @Nullable のデフォルト実装
| メソッド | 戻り値 | 説明 |
|---|---|---|
getItemStorage(Level, BlockPos) |
@Nullable IItemStorage |
アイテムストレージ |
getEnergyStorage(Level, BlockPos) |
@Nullable IEnergyStorage |
エネルギーストレージ |
getFluidStorage(Level, BlockPos) |
@Nullable IFluidStorage |
流体ストレージ |
getGenericStorage(Level, BlockPos, ResourceKey) |
@Nullable IGenericStorage |
汎用ストレージ |
onLinked(Level, BlockPos, LinkRole, IMultiBlockNetwork) |
void | 接続時コールバック |
onUnlinked(Level, BlockPos, LinkRole) |
void | 切断時コールバック |
hasItemStorage() / hasEnergyStorage() / hasFluidStorage() |
boolean | ストレージ有無の事前宣言 |
LinkableBehavior.fromForgeCapability() |
static | Forge IItemHandler を自動ラップ |
詳細は セクション 1 の登録コード を参照
9.5 ネットワーク・登録
| クラス/インターフェース | パッケージ | 説明 |
|---|---|---|
IMultiBlockNetwork |
api.network | コントローラーからネットワーク状態を操作する入口(実装は内部が提供) |
MultiBlockNetwork |
root | コントローラー⇔リンクブロックの接続/切断ロジック(static utility) |
MultiBlockRegistry |
api.registration | API の唯一の登録窓口 |
StructureDefinition |
api.registration | 構造体定義ラッパー |
MultiBlockEvent |
api | Forge イベント(Formed / Destroyed) |
MultiBlockAPI |
api | 内部ランタイムAPI(通常は直接使用しない) |
IPortBlock |
api.port | ポートブロックとして機能するブロックに実装させるインターフェース |
IPortType |
api.port | ポートの種類を定義するインターフェース(getId / getCategory) |
PortRegistry |
api.port | IPortType のグローバルレジストリ |
MultiBlockTags |
api.tags | データパック用タグ定義(MULTIBLOCK_PORTS) |
IMultiBlockNetwork の主なメソッド
| メソッド | 引数 | 戻り値 | 説明 |
|---|---|---|---|
getControllerPos() |
— | BlockPos | コントローラー座標 |
isFormed() |
— | boolean | 構造成立中か |
getItemStorage(LinkRole) |
ロール | IItemStorage | ロール別アイテムストレージ(アグリゲート) |
getAllItemStorage() |
— | IItemStorage | 全ロール横断のストレージ |
getEnergyStorage(LinkRole) |
ロール | IEnergyStorage | エネルギーストレージ |
getFluidStorage(LinkRole) |
ロール | IFluidStorage | 流体ストレージ |
canProcess(List<IBigItemStack>, List<IBigItemStack>) |
入力, 出力 | boolean | 転送可能か確認 |
processTransfer(List<IBigItemStack>, List<IBigItemStack>) |
入力, 出力 | boolean | INPUT→OUTPUT へアイテム転送 |
consumeEnergy(Amount, boolean) |
量, simulate | Amount | エネルギー消費 |
詳細は セクション 2 の実装例 を参照
9.6 ストレージインターフェース
| インターフェース | パッケージ | 主なメソッド |
|---|---|---|
IItemStorage |
api.storage | insert(IBigItemStack, simulate) / extract(Item, Amount, simulate) / getCount(Item) / getCapacity() |
IEnergyStorage |
api.storage | BigInteger ベースのエネルギー |
IFluidStorage |
api.storage | BigInteger ベースの流体 |
IGenericStorage |
api.storage | 汎用リソース(魔力・熱量など) |
9.7 BigInteger 対応(内部仕組み)
| クラス | パッケージ | 説明 |
|---|---|---|
IBigIntegerItemHandler |
api.compat | IItemHandler を BigInteger スケールに拡張するダック・インターフェース |
ForgeItemHandlerAdapter |
api.behavior | IItemHandler → IItemStorage ブリッジ(BigInteger 自動検出) |
MixinItemStackHandler |
mixin | ItemStackHandler に IBigIntegerItemHandler を自動付与するマーカー Mixin |
詳細は セクション 5 を参照
9.8 ポートブロック関連(4ティア検出)
構造体内のポート座標で、プレイヤーが置いたブロックが要求されたポートとして認証されるかを 以下の優先順位で検出する:
| Tier | 検出方法 | 条件 |
|---|---|---|
| Tier 1 | IPortBlock インターフェース |
ブロッククラスが IPortBlock を実装し、getPortType().getId() が一致 |
| Tier 2 | MultiBlockRegistry API 登録 |
registerPort() でブロックIDが登録され、IPortType が一致 |
| Tier 3 | Forge Capability fallback | ブロックの BlockEntity が対応する Forge Capability を持つ(ITEM=IItemHandler, ENERGY=IEnergyStorage, FLUID=IFluidHandler) |
| Tier 4 | Block Tags | ブロックが multiblocksystem:multiblock_ports タグに含まれる(データパックで登録) |
IPortBlock — ブロッククラスが実装
public interface IPortBlock {
IPortType getPortType();
}
IPortType — ポートの種類定義
public interface IPortType {
ResourceLocation getId(); // 例: "multiblocksystem:item_input"
BigInteger getBaseCapacity(); // デフォルト: BigInteger.ZERO
PortCategory getCategory(); // ITEM / FLUID / ENERGY / CUSTOM
}
PortRegistry — グローバルポートレジストリ
PortRegistry.register(IPortType port); // ポート定義を登録
IPortType type = PortRegistry.get(resourceId); // ポート定義を取得
MultiBlockTags — データパック用タグ定義
// Java 側
TagKey<Block> tag = MultiBlockTags.MULTIBLOCK_PORTS;
// data/multiblocksystem/tags/blocks/multiblock_ports.json
// モッドパック作者がポートとして認めたいブロックを追加
{
"replace": false,
"values": [
"minecraft:barrel",
"someothermod:custom_tank"
]
}
Screenshots
Gallery
Versions
Files
Relations
Project Relations
More like this
Similar Mods
Suggestions use data such as tags, dependencies, dependents, descriptions, titles, and more to rank how much they overlap with this mod.
On ModDex
Community snapshot
By the numbers
Statistics
Want to reach Minecraft players?
We're looking for a server hosting partner to feature here and other parts of the site. Interested? Send us a message!
Get in touchGet it on
Available Platforms
On ModDex
Community snapshot
By the numbers
Statistics
Resources