MultiBlockSystem

Quick rating

MultiBlockSystem

No reviews yet

Provides the foundation for building multiblocks.

Mod Loaders
Forge
Minecraft

Community voices

Reviews

Versions
Loading versions…
Match includes

Click once to include, again to exclude, again to clear

Rating Any
Any 0.5 1.0 1.5 2.0 2.5 3.0 3.5 4.0 4.5 5.0
Min
Max
Play Status
Reviews
Time Played
hrs+
Verified developers only
Has developer response
List view
Grid view
Compact view
Sort by
Date
Rating
Helpful
Unhelpful
Edited
Sort ascending
Delete this review?

This removes your review from the project. You can write a new review after.

Review submitted for moderation

Your review has been sent to moderators, who will check that it meets our guidelines before it appears publicly.

No reviews yet. Be the first to review this project!

Get it on

Available Platforms

About

Project Details

Type
Mod
Latest Version
multiblocksystem-1.0.7.jar
Authors

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.

Custom banner text
ModDex rating badge preview

Use HTML for any page that supports it, or Markdown for README files and Markdown-based descriptions.

Identifiers

Platform IDs

CurseForge ID

Resources

External Links

Source Issues Wiki Discord

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 の範囲に収まる場合は BigAmountLongAmountダウングレードされる。

// 整数
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 の自動昇格

LongAmountMath.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 の二重パス

ForgeItemHandlerAdapterIItemHandlerIItemStorage ブリッジであり、 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&lt;String[]&gt;, Map, String) KubeJS 風の文字列パターンで構造体を登録
registerStructure(String, List&lt;String[]&gt;, 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.*(NOT dev.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() のみ呼ぶこと。 controllerslinkables は FMLCommonSetupEvent で登録されるため サーバーリロードでクリアしてはいけない。

Amount の GCD コス

LongAmountlong ベースの高速 GCD を使用するため、 一般的な値ではほぼ瞬時に計算される。 BigAmount のみ BigInteger.gcd() を使用し、O(log n) のコストがかかる。 毎フレーム大量に呼ぶ場合は final フィールドにキャッシュすること。

ForgeItemHandlerAdapter の集計上限

ForgeItemHandlerAdapterIBigIntegerItemHandler を実装する 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 コマンドの除外引数で指定するか、 ChunkScanTaskList<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&lt;BlockPos, LinkRole&gt; を返す

使い方: 自分の 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&lt;IBigItemStack&gt;, List&lt;IBigItemStack&gt;) 入力, 出力 boolean 転送可能か確認
processTransfer(List&lt;IBigItemStack&gt;, List&lt;IBigItemStack&gt;) 入力, 出力 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

This project has no gallery images yet.

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

0
Ratings
0
Followers
0
In stacks

By the numbers

Statistics

<1,000
Downloads
Last Updated
Created
Last synced
When ModDex last fetched this project from CurseForge or Modrinth. Every project is re-checked on a schedule, and any project that ships a new file is synced automatically within hours of the release.
New file updates sync automatically
How syncing works