diff --git a/build.gradle b/build.gradle
index 49826ad0..eaac73ed 100644
--- a/build.gradle
+++ b/build.gradle
@@ -9,6 +9,7 @@ plugins {
// Import-block step for Spotless and its fixture tests (docs/code-format.md).
apply from: 'gradle/import-blocks.gradle'
+apply from: 'gradle/line-limit.gradle'
def env = System.getenv()
def tag = providers.environmentVariable('TAG')
@@ -216,12 +217,18 @@ tasks.named('javadoc', Javadoc) {
}
// Formatting (docs/code-format.md): Eclipse JDT with the shared profile in
-// gradle/java-formatter.xml (VS Code uses the same one), then the import-block step.
+// gradle/java-formatter.xml (VS Code uses the same one), then the import-block step. Lines the
+// formatter can't wrap below 80 may run to 120; `lineLimit` (gradle/line-limit.gradle) warns past
+// that, without failing.
// Ratcheted: only files changed since the base branch are checked and formatted, so code is
// brought over to this style as it is next edited. Never reformat unrelated files in a change.
// spotlessCheck is part of check/build; `./gradlew spotlessApply` (or `format`) fixes files.
+// `-PformatAll` drops the ratchet, so the whole tree is checked or formatted: use it once after
+// changing the style, in its own commit (listed in .git-blame-ignore-revs).
spotless {
- ratchetFrom 'origin/master-2.0-1.21.1-neo'
+ if (!providers.gradleProperty('formatAll').isPresent()) {
+ ratchetFrom 'origin/master-2.0-1.21.1-neo'
+ }
java {
target 'src/**/*.java'
eclipse('4.35')
diff --git a/docs/code-format.md b/docs/code-format.md
index c91daa3c..a5b4b5c6 100644
--- a/docs/code-format.md
+++ b/docs/code-format.md
@@ -4,9 +4,16 @@ Java follows the [Google Java Style Guide](https://google.github.io/styleguide/j
with these overrides:
- **Indentation: 4 spaces for both blocks and continuations.** Wrapped expressions and array
- initializers add one four-space level, not eight spaces. Existing explicit line breaks are kept
- where the formatter supports it. The 100-column limit and the other Google conventions (brace
- style, one statement per line, naming, `@Override` always, no wildcard imports, ...) still apply.
+ initializers add one four-space level, not eight spaces.
+- **Lines aim for 80 columns.** Parameter, argument and record component lists are packed up to
+ the limit and wrapped only where needed, never one per line; breaks that fit are rejoined.
+- **Up to 120 columns for what can't be wrapped**, such as a long string constant. Past 120,
+ `./gradlew lineLimit` (part of `check`) warns with the file and line. It never fails the build:
+ some lines read worse split than long.
+- **Wildcard imports are allowed**, static or not; in a mod they usually mean less code.
+- **Keep methods short**: aim for 25 to 30 lines. This is a review guideline; no tool enforces it.
+- The other Google conventions (brace style, one statement per line, naming, `@Override` always,
+ ...) still apply.
- **Imports are split into blocks, one per second-level package, separated by a single blank
line.** Order:
1. All static imports, as one block.
@@ -15,7 +22,8 @@ with these overrides:
`mezz.jei`, `net.minecraft`, `net.neoforged`, `org.slf4j`, ...).
4. MMDLib's own imports (`zone.moddev.*`, the library and the companion) last, as one block.
- Within a block, imports are ASCII-sorted. Example:
+ Within a block, imports are ASCII-sorted, so a wildcard comes before that package's single-type
+ imports. Example:
```java
import java.util.List;
@@ -35,11 +43,11 @@ with these overrides:
import zone.moddev.mc.lib.MMDLib;
```
-## Code written before this style
+## Changing the style
-Most of the code predates this style: it uses google-java-format's 2-space indentation. It is
-**not** reformatted in bulk. A file is brought over to the new style when it is next edited, as
-part of that change, and only then. Don't reformat files a change doesn't otherwise touch.
+Day to day, formatting only touches the files a change edits (see the ratchet below); don't
+reformat files a change doesn't otherwise touch. When the style itself changes, reformat the whole
+tree once, as described under Tools.
## Tools
@@ -53,11 +61,15 @@ Both are **ratcheted** from `origin/master-2.0-1.21.1-neo`: they only look at fi
from that branch, which is how older files are left alone until edited. Keep that branch fetched;
CI checks out with full history for this reason.
+After changing the style, `./gradlew spotlessApply -PformatAll` drops the ratchet and formats the
+whole tree. Commit that on its own and add the commit to `.git-blame-ignore-revs`, so `git blame`
+skips it.
+
The Java formatter is Eclipse JDT with the `MMDLib` profile in `gradle/java-formatter.xml`. Imports
are regrouped afterwards by a custom step, `gradle/import-blocks.gradle`, since Spotless's own
`importOrder` can't express rule 3. The step refuses, with the line number, input it can't rewrite
-safely: comments between imports, more than one import or a trailing comment on a line, and
-wildcard imports. Its fixtures in `gradle/import-blocks/` run as `testImportBlocks`, part of
+safely: comments between imports, and more than one import or a trailing comment on a line. Its
+fixtures in `gradle/import-blocks/` run as `testImportBlocks`, part of
`check`.
### VS Code
@@ -69,6 +81,7 @@ The same profile formats in VS Code. `.vscode/` is not committed, so add this to
"java.format.settings.url": "gradle/java-formatter.xml",
"java.format.settings.profile": "MMDLib",
"[java]": {
+ "editor.rulers": [80, 120],
"editor.tabSize": 4,
"editor.insertSpaces": true
}
diff --git a/gradle/import-blocks.gradle b/gradle/import-blocks.gradle
index c198ae0d..615926f5 100644
--- a/gradle/import-blocks.gradle
+++ b/gradle/import-blocks.gradle
@@ -15,9 +15,11 @@
* this is a custom step.
*
* Input the step can't rewrite safely is rejected with an error naming the line, never guessed at:
- * comments between imports (they would lose their position), more than one import or a trailing
- * comment on an import line, and wildcard imports (forbidden by Google style, which
- * docs/code-format.md follows).
+ * comments between imports (they would lose their position), and more than one import or a
+ * trailing comment on an import line.
+ *
+ * Wildcard imports, static or not, are allowed (unlike Google style): they go in their package's
+ * block like any other import, and sort ahead of that package's single-type imports.
*
* Applied from build.gradle, this script exposes:
* - `importBlocksStep`: a closure for `spotless { java { custom 'importBlocks', ... } } }`;
@@ -89,10 +91,6 @@ class ImportBlocks {
+ "import statement with nothing else on the line, found: ${line.trim()}")
}
String name = match.group(2)
- if (match.group(3) != null) {
- throw new IllegalArgumentException("line ${lineNumber}: wildcard imports are not "
- + "allowed (Google style, docs/code-format.md): ${line.trim()}")
- }
if (match.group(1) != null) {
statics.add("import static ${name};".toString())
} else {
diff --git a/gradle/import-blocks/static-wildcard.error.txt b/gradle/import-blocks/static-wildcard.error.txt
deleted file mode 100644
index 0de2a0c7..00000000
--- a/gradle/import-blocks/static-wildcard.error.txt
+++ /dev/null
@@ -1 +0,0 @@
-line 3: wildcard imports are not allowed
diff --git a/gradle/import-blocks/wildcard-with-single-types.expected.txt b/gradle/import-blocks/wildcard-with-single-types.expected.txt
new file mode 100644
index 00000000..8c62a2b2
--- /dev/null
+++ b/gradle/import-blocks/wildcard-with-single-types.expected.txt
@@ -0,0 +1,13 @@
+package zone.moddev.mc.lib;
+
+import static net.minecraft.core.Direction.*;
+
+import java.util.*;
+import java.util.List;
+
+import net.minecraft.world.item.*;
+import net.minecraft.world.item.ItemStack;
+
+import zone.moddev.mc.lib.api.*;
+
+public final class Example {}
diff --git a/gradle/import-blocks/wildcard-with-single-types.input.txt b/gradle/import-blocks/wildcard-with-single-types.input.txt
new file mode 100644
index 00000000..84d7efad
--- /dev/null
+++ b/gradle/import-blocks/wildcard-with-single-types.input.txt
@@ -0,0 +1,10 @@
+package zone.moddev.mc.lib;
+
+import net.minecraft.world.item.ItemStack;
+import static net.minecraft.core.Direction.*;
+import zone.moddev.mc.lib.api.*;
+import java.util.List;
+import net.minecraft.world.item.*;
+import java.util.*;
+
+public final class Example {}
diff --git a/gradle/import-blocks/wildcard.error.txt b/gradle/import-blocks/wildcard.error.txt
deleted file mode 100644
index 0de2a0c7..00000000
--- a/gradle/import-blocks/wildcard.error.txt
+++ /dev/null
@@ -1 +0,0 @@
-line 3: wildcard imports are not allowed
diff --git a/gradle/java-formatter.xml b/gradle/java-formatter.xml
index 49fe2bdc..71e00fc2 100644
--- a/gradle/java-formatter.xml
+++ b/gradle/java-formatter.xml
@@ -10,9 +10,22 @@
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/gradle/line-limit.gradle b/gradle/line-limit.gradle
new file mode 100644
index 00000000..2d4b7b8d
--- /dev/null
+++ b/gradle/line-limit.gradle
@@ -0,0 +1,34 @@
+/*
+ * Soft line-length limit (docs/code-format.md). The Eclipse profile wraps at 80 columns, but it
+ * never splits what can't be split, such as a long string constant, and leaves such a line long.
+ * Up to 120 columns is fine for those. Past that, `lineLimit` warns, naming the file and line; it
+ * never fails the build, since some lines can't be shortened without hurting readability.
+ *
+ * Applied from build.gradle; `check` runs it.
+ */
+
+def lineLimitSources = fileTree('src') { include '**/*.java' }
+
+tasks.register('lineLimit') {
+ group = 'verification'
+ description = 'Warns about Java lines longer than 120 columns (never fails).'
+ // No outputs: always runs, so the warnings are shown on every check, not only the first.
+ doLast {
+ int count = 0
+ lineLimitSources.files.sort().each { File file ->
+ file.readLines('UTF-8').eachWithIndex { String line, int index ->
+ if (line.length() > 120) {
+ def path = project.relativePath(file)
+ logger.warn("${path}:${index + 1}: warning: line is ${line.length()} columns"
+ + ' (limit 120)')
+ count++
+ }
+ }
+ }
+ if (count > 0) logger.warn("${count} line(s) over 120 columns")
+ }
+}
+
+tasks.named('check') {
+ dependsOn 'lineLimit'
+}
diff --git a/src/clientSmoke/java/zone/moddev/mc/lib/smoke/CraftTweakerClientSmoke.java b/src/clientSmoke/java/zone/moddev/mc/lib/smoke/CraftTweakerClientSmoke.java
index 5cb6424a..4b9ca2c0 100644
--- a/src/clientSmoke/java/zone/moddev/mc/lib/smoke/CraftTweakerClientSmoke.java
+++ b/src/clientSmoke/java/zone/moddev/mc/lib/smoke/CraftTweakerClientSmoke.java
@@ -17,150 +17,261 @@
import net.minecraft.world.level.*;
import net.minecraft.world.level.levelgen.WorldOptions;
import net.minecraft.world.level.levelgen.presets.WorldPresets;
+
import net.neoforged.api.distmarker.Dist;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.ModList;
import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.neoforge.client.event.ClientTickEvent;
import net.neoforged.neoforge.client.event.RenderFrameEvent;
+
import zone.moddev.mc.lib.MMDLib;
import zone.moddev.mc.lib.common.runtime.RedstoneBlock;
-/** Opt-in real-client validation; injected only by crafttweaker-smoke.init.gradle. */
+/**
+ * Opt-in real-client validation; injected only by
+ * crafttweaker-smoke.init.gradle.
+ */
@EventBusSubscriber(modid = "mmdlib", value = Dist.CLIENT)
public final class CraftTweakerClientSmoke {
- private static boolean started, requested, finished;
- private static volatile boolean ready;
- private static int ticks, frames, stage;
- private static final long DEADLINE = System.currentTimeMillis() + 240_000;
- private static final BlockPos POS = new BlockPos(0, 100, 0);
- private static final String[] ITEMS = {"client_alloy_ingot", "client_alloy_pickaxe", "client_alloy_block", "client_gate", "client_widget"};
+ private static boolean started, requested, finished;
+ private static volatile boolean ready;
+ private static int ticks, frames, stage;
+ private static final long DEADLINE = System.currentTimeMillis() + 240_000;
+ private static final BlockPos POS = new BlockPos(0, 100, 0);
+ private static final String[] ITEMS = {"client_alloy_ingot",
+ "client_alloy_pickaxe", "client_alloy_block", "client_gate",
+ "client_widget"};
- private static ResourceLocation id(String path) { return ResourceLocation.parse("mmdlib:" + path); }
- private static void require(boolean condition, String message) { if (!condition) throw new AssertionError(message); }
- private static boolean present() { return ModList.get().isLoaded("crafttweaker"); }
+ private static ResourceLocation id(String path) {
+ return ResourceLocation.parse("mmdlib:" + path);
+ }
+ private static void require(boolean condition, String message) {
+ if (!condition)
+ throw new AssertionError(message);
+ }
+ private static boolean present() {
+ return ModList.get().isLoaded("crafttweaker");
+ }
- @SubscribeEvent
- public static void tick(ClientTickEvent.Post event) {
- if (!Boolean.getBoolean("mmdlib.craftTweakerSmoke") || finished) return;
- var mc = Minecraft.getInstance();
- try {
- require(System.currentTimeMillis() < DEADLINE, "client smoke timed out: " + mc.screen);
- if (!started && mc.screen instanceof TitleScreen) {
- started = true;
- require(BuiltInRegistries.ITEM.containsKey(id("client_widget")) == present(), "optional integration registry boundary");
- var settings = new LevelSettings("CT smoke", GameType.CREATIVE, false, Difficulty.PEACEFUL, true, new GameRules(), WorldDataConfiguration.DEFAULT);
- mc.createWorldOpenFlows().createFreshLevel("ct-smoke-" + System.currentTimeMillis(), settings,
- new WorldOptions(1, false, false), r -> r.registryOrThrow(Registries.WORLD_PRESET)
- .getHolderOrThrow(WorldPresets.FLAT).value().createWorldDimensions(), mc.screen);
- }
- if (mc.player == null || mc.level == null) return;
- if (!requested) {
- requested = true;
- mc.getSingleplayerServer().execute(() -> {
- try {
- var player = mc.getSingleplayerServer().getPlayerList().getPlayers().getFirst();
- var level = player.serverLevel();
- level.setDayTime(6000);
- for (int x = -6; x <= 6; x++) for (int z = -2; z <= 8; z++)
- level.setBlock(POS.offset(x, -1, z), net.minecraft.world.level.block.Blocks.STONE.defaultBlockState(), 3);
- if (present()) {
- int x = -3;
- for (var direction : Direction.Plane.HORIZONTAL) {
- level.setBlock(POS.offset(x, 0, 0), BuiltInRegistries.BLOCK.get(id("client_gate"))
- .defaultBlockState().setValue(RedstoneBlock.FACING, direction), 3);
- x += 2;
- }
- level.setBlock(POS.offset(0, 0, -2), BuiltInRegistries.BLOCK.get(id("client_alloy_block")).defaultBlockState(), 3);
+ @SubscribeEvent
+ public static void tick(ClientTickEvent.Post event) {
+ if (!Boolean.getBoolean("mmdlib.craftTweakerSmoke") || finished)
+ return;
+ var mc = Minecraft.getInstance();
+ try {
+ require(System.currentTimeMillis() < DEADLINE,
+ "client smoke timed out: " + mc.screen);
+ if (!started && mc.screen instanceof TitleScreen) {
+ started = true;
+ require(
+ BuiltInRegistries.ITEM
+ .containsKey(id("client_widget")) == present(),
+ "optional integration registry boundary");
+ var settings = new LevelSettings("CT smoke", GameType.CREATIVE,
+ false, Difficulty.PEACEFUL, true, new GameRules(),
+ WorldDataConfiguration.DEFAULT);
+ mc.createWorldOpenFlows().createFreshLevel(
+ "ct-smoke-" + System.currentTimeMillis(), settings,
+ new WorldOptions(1, false, false),
+ r -> r.registryOrThrow(Registries.WORLD_PRESET)
+ .getHolderOrThrow(WorldPresets.FLAT).value()
+ .createWorldDimensions(),
+ mc.screen);
+ }
+ if (mc.player == null || mc.level == null)
+ return;
+ if (!requested) {
+ requested = true;
+ mc.getSingleplayerServer().execute(() -> {
+ try {
+ var player = mc.getSingleplayerServer().getPlayerList()
+ .getPlayers().getFirst();
+ var level = player.serverLevel();
+ level.setDayTime(6000);
+ for (int x = -6; x <= 6; x++)
+ for (int z = -2; z <= 8; z++)
+ level.setBlock(POS.offset(x, -1, z),
+ net.minecraft.world.level.block.Blocks.STONE
+ .defaultBlockState(),
+ 3);
+ if (present()) {
+ int x = -3;
+ for (var direction : Direction.Plane.HORIZONTAL) {
+ level.setBlock(POS.offset(x, 0, 0),
+ BuiltInRegistries.BLOCK
+ .get(id("client_gate"))
+ .defaultBlockState().setValue(
+ RedstoneBlock.FACING, direction),
+ 3);
+ x += 2;
+ }
+ level.setBlock(POS.offset(0, 0, -2),
+ BuiltInRegistries.BLOCK
+ .get(id("client_alloy_block"))
+ .defaultBlockState(),
+ 3);
+ }
+ player.teleportTo(.5, 103, 7.5);
+ player.setYRot(180);
+ player.setXRot(22);
+ if (present()) {
+ checkRecipes(mc);
+ var server = mc.getSingleplayerServer();
+ server
+ .reloadResources(
+ server.getPackRepository().getSelectedIds())
+ .thenRunAsync(() -> {
+ try {
+ checkRecipes(mc);
+ MMDLib.LOGGER.info(
+ "MMDLIB_CT_RECIPES_RELOAD_PASS");
+ ready = true;
+ } catch (Throwable error) {
+ fail(error);
+ }
+ }, server).exceptionally(error -> {
+ fail(error);
+ return null;
+ });
+ } else
+ ready = true;
+ } catch (Throwable error) {
+ fail(error);
+ }
+ });
}
- player.teleportTo(.5, 103, 7.5);
- player.setYRot(180); player.setXRot(22);
+ if (!ready || ++ticks < 100 || stage != 0)
+ return;
if (present()) {
- checkRecipes(mc);
- var server = mc.getSingleplayerServer();
- server.reloadResources(server.getPackRepository().getSelectedIds()).thenRunAsync(() -> {
- try {
- checkRecipes(mc);
- MMDLib.LOGGER.info("MMDLIB_CT_RECIPES_RELOAD_PASS");
- ready = true;
- } catch (Throwable error) { fail(error); }
- }, server).exceptionally(error -> { fail(error); return null; });
- } else ready = true;
- } catch (Throwable error) { fail(error); }
- });
- }
- if (!ready || ++ticks < 100 || stage != 0) return;
- if (present()) {
- require(new ItemStack(BuiltInRegistries.ITEM.get(id("client_widget"))).getHoverName().getString().equals("Named Test Widget"), "English name override");
- require(new ItemStack(BuiltInRegistries.ITEM.get(id("client_alloy_ingot"))).getHoverName().getString().equals("Amber Alloy Ingot"), "material English name");
- for (String name : ITEMS) {
- var model = mc.getItemRenderer().getModel(new ItemStack(BuiltInRegistries.ITEM.get(id(name))), mc.level, mc.player, 0);
- require(model != mc.getModelManager().getMissingModel(), "missing item model: " + name);
- require(!model.getParticleIcon().contents().name().getPath().equals("missingno"), "missing texture: " + name);
- }
- var block = BuiltInRegistries.BLOCK.get(id("client_gate"));
- for (var direction : Direction.Plane.HORIZONTAL) {
- var state = block.defaultBlockState().setValue(RedstoneBlock.FACING, direction);
- var model = mc.getBlockRenderer().getBlockModel(state);
- require(model.getQuads(state, direction, RandomSource.create(1)).stream()
- .anyMatch(q -> q.getSprite().contents().name().equals(id("block/client_gate_front"))), "front model rotation: " + direction);
+ require(
+ new ItemStack(
+ BuiltInRegistries.ITEM.get(id("client_widget")))
+ .getHoverName().getString().equals("Named Test Widget"),
+ "English name override");
+ require(
+ new ItemStack(
+ BuiltInRegistries.ITEM.get(id("client_alloy_ingot")))
+ .getHoverName().getString().equals("Amber Alloy Ingot"),
+ "material English name");
+ for (String name : ITEMS) {
+ var model = mc.getItemRenderer().getModel(
+ new ItemStack(BuiltInRegistries.ITEM.get(id(name))),
+ mc.level, mc.player, 0);
+ require(model != mc.getModelManager().getMissingModel(),
+ "missing item model: " + name);
+ require(!model.getParticleIcon().contents().name().getPath()
+ .equals("missingno"), "missing texture: " + name);
+ }
+ var block = BuiltInRegistries.BLOCK.get(id("client_gate"));
+ for (var direction : Direction.Plane.HORIZONTAL) {
+ var state = block.defaultBlockState()
+ .setValue(RedstoneBlock.FACING, direction);
+ var model = mc.getBlockRenderer().getBlockModel(state);
+ require(
+ model.getQuads(state, direction, RandomSource.create(1))
+ .stream()
+ .anyMatch(q -> q.getSprite().contents().name()
+ .equals(id("block/client_gate_front"))),
+ "front model rotation: " + direction);
+ }
+ }
+ mc.options.hideGui = true;
+ mc.player.setYRot(180);
+ mc.player.setXRot(22);
+ mc.setScreen(null);
+ stage = 1;
+ frames = 0;
+ } catch (Throwable error) {
+ fail(error);
}
- }
- mc.options.hideGui = true;
- mc.player.setYRot(180); mc.player.setXRot(22);
- mc.setScreen(null);
- stage = 1; frames = 0;
- } catch (Throwable error) { fail(error); }
- }
+ }
- private static void checkRecipes(Minecraft mc) {
- var server = mc.getSingleplayerServer();
- var manager = server.getRecipeManager();
- var recipe = manager.byKey(ResourceLocation.parse("crafttweaker:ct_crusher_added")).orElseThrow().value();
- var output = recipe.getResultItem(server.registryAccess());
- require(output.is(net.minecraft.world.item.Items.DIAMOND) && output.getCount() == 2, "recipe survives reload");
- require(manager.byKey(ResourceLocation.parse("crafttweaker:ct_crusher_removed")).isEmpty(), "removal survives reload");
- long count = manager.getAllRecipesFor(zone.moddev.mc.lib.common.recipes.CrushingRecipe.TYPE.get())
- .stream().filter(holder -> holder.id().toString().equals("crafttweaker:ct_crusher_added")).count();
- require(count == 1, "recipe reload does not duplicate IDs");
- }
+ private static void checkRecipes(Minecraft mc) {
+ var server = mc.getSingleplayerServer();
+ var manager = server.getRecipeManager();
+ var recipe = manager
+ .byKey(ResourceLocation.parse("crafttweaker:ct_crusher_added"))
+ .orElseThrow().value();
+ var output = recipe.getResultItem(server.registryAccess());
+ require(output.is(net.minecraft.world.item.Items.DIAMOND)
+ && output.getCount() == 2, "recipe survives reload");
+ require(manager
+ .byKey(ResourceLocation.parse("crafttweaker:ct_crusher_removed"))
+ .isEmpty(), "removal survives reload");
+ long count = manager
+ .getAllRecipesFor(
+ zone.moddev.mc.lib.common.recipes.CrushingRecipe.TYPE.get())
+ .stream().filter(holder -> holder.id().toString()
+ .equals("crafttweaker:ct_crusher_added"))
+ .count();
+ require(count == 1, "recipe reload does not duplicate IDs");
+ }
- @SubscribeEvent
- public static void frame(RenderFrameEvent.Post event) {
- if (!Boolean.getBoolean("mmdlib.craftTweakerSmoke") || finished || stage == 0) return;
- var mc = Minecraft.getInstance();
- try {
- if (++frames < 30) return;
- if (stage == 1) {
- Screenshot.grab(mc.gameDirectory, "ct-directional-world.png", mc.getMainRenderTarget(), message -> {});
- if (present()) { mc.setScreen(new Gallery()); stage = 2; frames = 0; return; }
- } else Screenshot.grab(mc.gameDirectory, "ct-items-and-names.png", mc.getMainRenderTarget(), message -> {});
- MMDLib.LOGGER.info("MMDLIB_CT_CLIENT_PASS: CraftTweaker installed={}, integrated world, resource checks and captures complete", present());
- finished = true;
- mc.stop();
- } catch (Throwable error) { fail(error); }
- }
+ @SubscribeEvent
+ public static void frame(RenderFrameEvent.Post event) {
+ if (!Boolean.getBoolean("mmdlib.craftTweakerSmoke") || finished
+ || stage == 0)
+ return;
+ var mc = Minecraft.getInstance();
+ try {
+ if (++frames < 30)
+ return;
+ if (stage == 1) {
+ Screenshot.grab(mc.gameDirectory, "ct-directional-world.png",
+ mc.getMainRenderTarget(), message -> {
+ });
+ if (present()) {
+ mc.setScreen(new Gallery());
+ stage = 2;
+ frames = 0;
+ return;
+ }
+ } else
+ Screenshot.grab(mc.gameDirectory, "ct-items-and-names.png",
+ mc.getMainRenderTarget(), message -> {
+ });
+ MMDLib.LOGGER.info(
+ "MMDLIB_CT_CLIENT_PASS: CraftTweaker installed={}, integrated world, resource checks and captures complete",
+ present());
+ finished = true;
+ mc.stop();
+ } catch (Throwable error) {
+ fail(error);
+ }
+ }
- private static void fail(Throwable error) {
- finished = true;
- MMDLib.LOGGER.error("MMDLIB_CT_CLIENT_FAIL", error);
- Minecraft.getInstance().execute(() -> Minecraft.getInstance().stop());
- }
+ private static void fail(Throwable error) {
+ finished = true;
+ MMDLib.LOGGER.error("MMDLIB_CT_CLIENT_FAIL", error);
+ Minecraft.getInstance().execute(() -> Minecraft.getInstance().stop());
+ }
- private static final class Gallery extends Screen {
- Gallery() { super(Component.literal("CraftTweaker content smoke")); }
- @Override public boolean isPauseScreen() { return false; }
- @Override public void render(GuiGraphics g, int mouseX, int mouseY, float partialTick) {
- g.fill(0, 0, width, height, 0xFF26313C);
- g.drawString(font, title, 30, 25, 0xFFFFFFFF);
- int y = 65;
- for (String name : ITEMS) {
- var stack = new ItemStack(BuiltInRegistries.ITEM.get(id(name)));
- g.pose().pushPose(); g.pose().translate(35, y, 0); g.pose().scale(2, 2, 2);
- g.renderItem(stack, 0, 0); g.pose().popPose();
- g.drawString(font, stack.getHoverName(), 90, y + 10, 0xFFFFFFFF);
- y += 62;
- }
+ private static final class Gallery extends Screen {
+ Gallery() {
+ super(Component.literal("CraftTweaker content smoke"));
+ }
+ @Override
+ public boolean isPauseScreen() {
+ return false;
+ }
+ @Override
+ public void render(GuiGraphics g, int mouseX, int mouseY,
+ float partialTick) {
+ g.fill(0, 0, width, height, 0xFF26313C);
+ g.drawString(font, title, 30, 25, 0xFFFFFFFF);
+ int y = 65;
+ for (String name : ITEMS) {
+ var stack = new ItemStack(BuiltInRegistries.ITEM.get(id(name)));
+ g.pose().pushPose();
+ g.pose().translate(35, y, 0);
+ g.pose().scale(2, 2, 2);
+ g.renderItem(stack, 0, 0);
+ g.pose().popPose();
+ g.drawString(font, stack.getHoverName(), 90, y + 10,
+ 0xFFFFFFFF);
+ y += 62;
+ }
+ }
}
- }
}
diff --git a/src/companion/java/zone/moddev/mc/companion/CompanionAddons.java b/src/companion/java/zone/moddev/mc/companion/CompanionAddons.java
index 9f11af46..962804e3 100644
--- a/src/companion/java/zone/moddev/mc/companion/CompanionAddons.java
+++ b/src/companion/java/zone/moddev/mc/companion/CompanionAddons.java
@@ -17,151 +17,140 @@
import zone.moddev.mc.lib.api.automation.*;
import zone.moddev.mc.lib.api.capabilities.IoMode;
-/** Companion content demonstrates capabilities: the library does not register concrete addons. */
+/**
+ * Companion content demonstrates capabilities: the library does not register
+ * concrete addons.
+ */
public final class CompanionAddons {
- private static final DeferredRegister- ITEMS =
- DeferredRegister.create(Registries.ITEM, CompanionMod.ID);
- public static final DeferredHolder
- RECOVERY_CAPSULE =
- ITEMS.register("recovery_capsule", RecoveryCapsuleItem::new);
- private static final Map, InventoryAddon> ADDONS =
- new LinkedHashMap<>();
- private static final Map, InventoryFilter> FILTERS =
- new LinkedHashMap<>();
- public static final FilterWidgetType TAG_MODE =
- FilterWidgetType.register(
- CompanionMod.id("tag_mode"),
- com.mojang.serialization.Codec.BOOL,
- (config, deny) -> {
- config.putBoolean("deny", deny);
- return true;
- });
- public static final DeferredHolder
- PULLER =
- addon("mechanical_puller", ResourceType.ITEMS, IoMode.INPUT, 8, 20, 4, true);
- public static final DeferredHolder
- PUSHER =
- addon("mechanical_pusher", ResourceType.ITEMS, IoMode.OUTPUT, 8, 20, 4, true);
- public static final DeferredHolder
- INPUT_PUMP =
- addon("input_pump", ResourceType.FLUIDS, IoMode.INPUT, 250, 10, 1, true);
- public static final DeferredHolder
- OUTPUT_PUMP =
- addon("output_pump", ResourceType.FLUIDS, IoMode.OUTPUT, 250, 10, 1, true);
- public static final DeferredHolder
- IMPORT_RELAY =
- addon("import_relay", ResourceType.ENERGY, IoMode.INPUT, 1000, 5, 0, false);
- public static final DeferredHolder
- EXPORT_RELAY =
- addon("export_relay", ResourceType.ENERGY, IoMode.OUTPUT, 1000, 5, 0, false);
- public static final DeferredHolder
- ITEM_FILTER =
- filter("item_filter", ResourceType.ITEMS, 8, false);
- public static final DeferredHolder
- LARGE_FILTER =
- filter("large_item_filter", ResourceType.ITEMS, 36, false);
- public static final DeferredHolder
- TAG_FILTER =
- filter("tag_filter", ResourceType.ITEMS, 0, true);
- public static final DeferredHolder
- FLUID_FILTER =
- filter("fluid_filter", ResourceType.FLUIDS, 6, false);
+ private static final DeferredRegister
- ITEMS = DeferredRegister
+ .create(Registries.ITEM, CompanionMod.ID);
+ public static final DeferredHolder
- RECOVERY_CAPSULE = ITEMS
+ .register("recovery_capsule", RecoveryCapsuleItem::new);
+ private static final Map, InventoryAddon> ADDONS = new LinkedHashMap<>();
+ private static final Map, InventoryFilter> FILTERS = new LinkedHashMap<>();
+ public static final FilterWidgetType TAG_MODE = FilterWidgetType
+ .register(CompanionMod.id("tag_mode"),
+ com.mojang.serialization.Codec.BOOL, (config, deny) -> {
+ config.putBoolean("deny", deny);
+ return true;
+ });
+ public static final DeferredHolder
- PULLER = addon(
+ "mechanical_puller", ResourceType.ITEMS, IoMode.INPUT, 8, 20, 4, true);
+ public static final DeferredHolder
- PUSHER = addon(
+ "mechanical_pusher", ResourceType.ITEMS, IoMode.OUTPUT, 8, 20, 4, true);
+ public static final DeferredHolder
- INPUT_PUMP = addon(
+ "input_pump", ResourceType.FLUIDS, IoMode.INPUT, 250, 10, 1, true);
+ public static final DeferredHolder
- OUTPUT_PUMP = addon(
+ "output_pump", ResourceType.FLUIDS, IoMode.OUTPUT, 250, 10, 1, true);
+ public static final DeferredHolder
- IMPORT_RELAY = addon(
+ "import_relay", ResourceType.ENERGY, IoMode.INPUT, 1000, 5, 0, false);
+ public static final DeferredHolder
- EXPORT_RELAY = addon(
+ "export_relay", ResourceType.ENERGY, IoMode.OUTPUT, 1000, 5, 0, false);
+ public static final DeferredHolder
- ITEM_FILTER = filter(
+ "item_filter", ResourceType.ITEMS, 8, false);
+ public static final DeferredHolder
- LARGE_FILTER = filter(
+ "large_item_filter", ResourceType.ITEMS, 36, false);
+ public static final DeferredHolder
- TAG_FILTER = filter(
+ "tag_filter", ResourceType.ITEMS, 0, true);
+ public static final DeferredHolder
- FLUID_FILTER = filter(
+ "fluid_filter", ResourceType.FLUIDS, 6, false);
- private static DeferredHolder
- addon(
- String name,
- ResourceType> type,
- IoMode direction,
- int batch,
- int interval,
- long cost,
- boolean filters) {
- var item = ITEMS.register(name, () -> new Item(new Item.Properties().stacksTo(1)));
- var spec =
- new AddonSpec(CompanionMod.id(name), type, direction, batch, interval, cost, filters);
- ADDONS.put(item, stack -> spec);
- return item;
- }
+ private static DeferredHolder
- addon(String name,
+ ResourceType> type, IoMode direction, int batch, int interval,
+ long cost, boolean filters) {
+ var item = ITEMS.register(name,
+ () -> new Item(new Item.Properties().stacksTo(1)));
+ var spec = new AddonSpec(CompanionMod.id(name), type, direction, batch,
+ interval, cost, filters);
+ ADDONS.put(item, stack -> spec);
+ return item;
+ }
- private static DeferredHolder
- filter(
- String name, ResourceType> type, int size, boolean tag) {
- var item = ITEMS.register(name, () -> new Item(new Item.Properties().stacksTo(1)));
- FILTERS.put(
- item,
- new InventoryFilter() {
- public ResourceType> resource(ItemStack stack) {
- return type;
- }
+ private static DeferredHolder
- filter(String name,
+ ResourceType> type, int size, boolean tag) {
+ var item = ITEMS.register(name,
+ () -> new Item(new Item.Properties().stacksTo(1)));
+ FILTERS.put(item, new InventoryFilter() {
+ public ResourceType> resource(ItemStack stack) {
+ return type;
+ }
- public ResourceLocation editorType(ItemStack stack) {
- return CompanionMod.id(name);
- }
+ public ResourceLocation editorType(ItemStack stack) {
+ return CompanionMod.id(name);
+ }
- public FilterControl controls(ItemStack stack) {
- return new FilterControl.Box(
- "root",
- false,
- List.of(
- tag
- ? new FilterControl.Custom("deny", TAG_MODE, 14)
- : new FilterControl.Toggle(
- "deny",
- ResourceLocation.parse("mmdlib:icon_filter_whitelist"),
- ResourceLocation.parse("mmdlib:icon_filter_blacklist"),
- Component.translatable("screen.mmdlib_companion.filter.whitelist"),
- Component.translatable("screen.mmdlib_companion.filter.blacklist")),
+ public FilterControl controls(ItemStack stack) {
+ return new FilterControl.Box("root", false, List.of(tag
+ ? new FilterControl.Custom("deny", TAG_MODE, 14)
+ : new FilterControl.Toggle("deny",
+ ResourceLocation.parse("mmdlib:icon_filter_whitelist"),
+ ResourceLocation.parse("mmdlib:icon_filter_blacklist"),
+ Component.translatable(
+ "screen.mmdlib_companion.filter.whitelist"),
+ Component.translatable(
+ "screen.mmdlib_companion.filter.blacklist")),
tag
- ? new FilterControl.Text(
- "tag",
- 128,
- Component.translatable("screen.mmdlib_companion.filter.tag"))
+ ? new FilterControl.Text("tag", 128,
+ Component.translatable(
+ "screen.mmdlib_companion.filter.tag"))
: new FilterControl.Samples("samples", size, type)));
- }
+ }
- public boolean validate(
- ItemStack stack,
- net.minecraft.nbt.CompoundTag config,
- HolderLookup.Provider registries) {
- if (!tag || config.getString("tag").isEmpty()) return true;
- var id = ResourceLocation.tryParse(config.getString("tag"));
- return id != null
- && registries
- .lookupOrThrow(Registries.ITEM)
- .get(TagKey.create(Registries.ITEM, id))
- .isPresent();
- }
+ public boolean validate(ItemStack stack,
+ net.minecraft.nbt.CompoundTag config,
+ HolderLookup.Provider registries) {
+ if (!tag || config.getString("tag").isEmpty())
+ return true;
+ var id = ResourceLocation.tryParse(config.getString("tag"));
+ return id != null && registries.lookupOrThrow(Registries.ITEM)
+ .get(TagKey.create(Registries.ITEM, id)).isPresent();
+ }
- public boolean matches(
- ItemStack stack, Object candidate, HolderLookup.Provider registries) {
- var config = configuration(stack);
- boolean match = false;
- if (tag && candidate instanceof ItemStack item) {
- var id = ResourceLocation.tryParse(config.getString("tag"));
- match = id != null && item.is(TagKey.create(Registries.ITEM, id));
- } else {
- String id =
- candidate instanceof ItemStack item
- ? BuiltInRegistries.ITEM.getKey(item.getItem()).toString()
- : candidate instanceof FluidStack fluid
- ? BuiltInRegistries.FLUID.getKey(fluid.getFluid()).toString()
- : "";
- var samples = config.getList("samples", net.minecraft.nbt.Tag.TAG_STRING);
- for (int i = 0; i < Math.min(size, samples.size()); i++)
- if (samples.getString(i).equals(id)) {
- match = true;
- break;
+ public boolean matches(ItemStack stack, Object candidate,
+ HolderLookup.Provider registries) {
+ var config = configuration(stack);
+ boolean match = false;
+ if (tag && candidate instanceof ItemStack item) {
+ var id = ResourceLocation.tryParse(config.getString("tag"));
+ match = id != null
+ && item.is(TagKey.create(Registries.ITEM, id));
+ } else {
+ String id = candidate instanceof ItemStack item
+ ? BuiltInRegistries.ITEM.getKey(item.getItem())
+ .toString()
+ : candidate instanceof FluidStack fluid
+ ? BuiltInRegistries.FLUID.getKey(fluid.getFluid())
+ .toString()
+ : "";
+ var samples = config.getList("samples",
+ net.minecraft.nbt.Tag.TAG_STRING);
+ for (int i = 0; i < Math.min(size, samples.size()); i++)
+ if (samples.getString(i).equals(id)) {
+ match = true;
+ break;
+ }
}
+ return config.getBoolean("deny") ? !match : match;
}
- return config.getBoolean("deny") ? !match : match;
- }
});
- return item;
- }
+ return item;
+ }
- public static List> items() {
- var result = new ArrayList<>(ADDONS.keySet());
- result.addAll(FILTERS.keySet());
- return List.copyOf(result);
- }
+ public static List> items() {
+ var result = new ArrayList<>(ADDONS.keySet());
+ result.addAll(FILTERS.keySet());
+ return List.copyOf(result);
+ }
- public static void register(IEventBus bus) {
- ITEMS.register(bus);
- }
+ public static void register(IEventBus bus) {
+ ITEMS.register(bus);
+ }
- public static void capabilities(RegisterCapabilitiesEvent event) {
- ADDONS.forEach(
- (item, provider) ->
- event.registerItem(AddonCapabilities.ADDON, (stack, context) -> provider, item.get()));
- FILTERS.forEach(
- (item, provider) ->
- event.registerItem(AddonCapabilities.FILTER, (stack, context) -> provider, item.get()));
- }
+ public static void capabilities(RegisterCapabilitiesEvent event) {
+ ADDONS.forEach((item, provider) -> event.registerItem(
+ AddonCapabilities.ADDON, (stack, context) -> provider, item.get()));
+ FILTERS.forEach(
+ (item, provider) -> event.registerItem(AddonCapabilities.FILTER,
+ (stack, context) -> provider, item.get()));
+ }
}
diff --git a/src/companion/java/zone/moddev/mc/companion/CompanionMod.java b/src/companion/java/zone/moddev/mc/companion/CompanionMod.java
index 01e9d15c..3ce00712 100644
--- a/src/companion/java/zone/moddev/mc/companion/CompanionMod.java
+++ b/src/companion/java/zone/moddev/mc/companion/CompanionMod.java
@@ -35,10 +35,10 @@
@Mod(CompanionMod.ID)
public final class CompanionMod {
public static final String ID = "mmdlib_companion";
- private static final DeferredRegister BLOCKS = DeferredRegister.create(Registries.BLOCK,
- ID);
- private static final DeferredRegister
- ITEMS = DeferredRegister.create(Registries.ITEM,
- ID);
+ private static final DeferredRegister BLOCKS = DeferredRegister
+ .create(Registries.BLOCK, ID);
+ private static final DeferredRegister
- ITEMS = DeferredRegister
+ .create(Registries.ITEM, ID);
private static final DeferredRegister> ENTITIES = DeferredRegister
.create(Registries.BLOCK_ENTITY_TYPE, ID);
private static final DeferredRegister> RECIPE_TYPES = DeferredRegister
@@ -48,33 +48,34 @@ public final class CompanionMod {
private static final DeferredRegister TABS = DeferredRegister
.create(Registries.CREATIVE_MODE_TAB, ID);
- public static final MachineRecipeType CRUSHING = MachineRecipeTypes.register(RECIPE_TYPES,
- SERIALIZERS, "crushing");
- public static final MachineRecipeType TRANSMUTING = MachineRecipeTypes.register(RECIPE_TYPES,
- SERIALIZERS, "transmuting");
- public static final Machine CRUSHER = new Machine("crusher", ProcessorEntity.Kind.CRUSHER);
+ public static final MachineRecipeType CRUSHING = MachineRecipeTypes
+ .register(RECIPE_TYPES, SERIALIZERS, "crushing");
+ public static final MachineRecipeType TRANSMUTING = MachineRecipeTypes
+ .register(RECIPE_TYPES, SERIALIZERS, "transmuting");
+ public static final Machine CRUSHER = new Machine("crusher",
+ ProcessorEntity.Kind.CRUSHER);
public static final Machine TRANSMUTER = new Machine("transmuter",
ProcessorEntity.Kind.TRANSMUTER);
public static final Machine DUAL_CRUSHER = new Machine("dual_crusher",
ProcessorEntity.Kind.DUAL);
- public static final Machine CREATIVE_POWER = new Machine("creative_power", null);
+ public static final Machine CREATIVE_POWER = new Machine("creative_power",
+ null);
public static final Machine LOGISTICS = new Machine("logistics",
ProcessorEntity.Kind.LOGISTICS);
- public static final List MACHINES = List.of(CRUSHER, TRANSMUTER, DUAL_CRUSHER,
- CREATIVE_POWER, LOGISTICS);
+ public static final List MACHINES = List.of(CRUSHER, TRANSMUTER,
+ DUAL_CRUSHER, CREATIVE_POWER, LOGISTICS);
static {
- TABS.register(
- "machines",
+ TABS.register("machines",
() -> CreativeModeTab.builder()
.title(Component.translatable("itemGroup.mmdlib_companion"))
.icon(() -> new ItemStack(CRUSHER.block.get()))
- .displayItems(
- (parameters, output) -> {
- MACHINES.forEach(machine -> output.accept(machine.block.get()));
- CompanionAddons.items().forEach(item -> output.accept(item.get()));
- })
- .build());
+ .displayItems((parameters, output) -> {
+ MACHINES
+ .forEach(machine -> output.accept(machine.block.get()));
+ CompanionAddons.items()
+ .forEach(item -> output.accept(item.get()));
+ }).build());
}
public CompanionMod(IEventBus bus) {
@@ -87,64 +88,54 @@ public CompanionMod(IEventBus bus) {
SERIALIZERS.register(bus);
TABS.register(bus);
bus.addListener(CompanionMod::capabilities);
- // The custom progress dial remains clickable; processor buttons have a library-owned
+ // The custom progress dial remains clickable; processor buttons have a
+ // library-owned
// action.
- MaterialExtensions.GLOBAL
- .events()
- .registerCallback(
- id("toggle_0"),
- MaterialEventTypes.GUI_CLICK,
- click -> {
- if (click.menu().blockEntity instanceof ProcessorEntity machine)
- machine.toggle(0);
- });
+ MaterialExtensions.GLOBAL.events().registerCallback(id("toggle_0"),
+ MaterialEventTypes.GUI_CLICK, click -> {
+ if (click.menu().blockEntity instanceof ProcessorEntity machine)
+ machine.toggle(0);
+ });
}
private static void capabilities(RegisterCapabilitiesEvent event) {
CompanionAddons.capabilities(event);
for (var machine : MACHINES) {
if (machine == CREATIVE_POWER) {
- MachineCapabilities.energy(
- event,
- machine.type.get(),
+ MachineCapabilities.energy(event, machine.type.get(),
entity -> entity.energy,
- (entity, side) -> ((CreativePowerEntity) entity).automation.mode(
- zone.moddev.mc.lib.api.automation.ResourceType.ENERGY, 0, side));
+ (entity, side) -> ((CreativePowerEntity) entity).automation
+ .mode(
+ zone.moddev.mc.lib.api.automation.ResourceType.ENERGY,
+ 0, side));
continue;
}
- event.registerBlockEntity(
- Capabilities.ItemHandler.BLOCK,
- machine.type.get(),
- (entity, side) -> {
+ event.registerBlockEntity(Capabilities.ItemHandler.BLOCK,
+ machine.type.get(), (entity, side) -> {
var p = (ProcessorEntity) entity;
- return p.items.view(
- slot -> p.automation.mode(
- zone.moddev.mc.lib.api.automation.ResourceType.ITEMS,
- p.items.address(slot).inventory(),
- p.items.address(slot).slot(),
- side));
+ return p.items.view(slot -> p.automation.mode(
+ zone.moddev.mc.lib.api.automation.ResourceType.ITEMS,
+ p.items.address(slot).inventory(),
+ p.items.address(slot).slot(), side));
});
- event.registerBlockEntity(
- Capabilities.FluidHandler.BLOCK,
- machine.type.get(),
- (entity, side) -> {
+ event.registerBlockEntity(Capabilities.FluidHandler.BLOCK,
+ machine.type.get(), (entity, side) -> {
var p = (ProcessorEntity) entity;
return p.hasTank()
- ? p.fluids.view(
- tank -> p.automation.mode(
- zone.moddev.mc.lib.api.automation.ResourceType.FLUIDS, tank, side))
+ ? p.fluids.view(tank -> p.automation.mode(
+ zone.moddev.mc.lib.api.automation.ResourceType.FLUIDS,
+ tank, side))
: null;
});
- event.registerBlockEntity(
- Capabilities.EnergyStorage.BLOCK,
- machine.type.get(),
- (entity, side) -> {
+ event.registerBlockEntity(Capabilities.EnergyStorage.BLOCK,
+ machine.type.get(), (entity, side) -> {
var p = (ProcessorEntity) entity;
return side == null
- ? p.energy.view(zone.moddev.mc.lib.api.capabilities.IoMode.BOTH)
- : p.energy.view(
- () -> p.automation.mode(
- zone.moddev.mc.lib.api.automation.ResourceType.ENERGY, 0, side));
+ ? p.energy.view(
+ zone.moddev.mc.lib.api.capabilities.IoMode.BOTH)
+ : p.energy.view(() -> p.automation.mode(
+ zone.moddev.mc.lib.api.automation.ResourceType.ENERGY,
+ 0, side));
});
}
}
@@ -153,7 +144,10 @@ public static ResourceLocation id(String path) {
return ResourceLocation.fromNamespaceAndPath(ID, path);
}
- /** Each block has its own type and XML screen, while processors share one implementation. */
+ /**
+ * Each block has its own type and XML screen, while processors share one
+ * implementation.
+ */
public static final class Machine {
public final DeferredHolder block;
public final DeferredHolder, BlockEntityType> type;
@@ -161,14 +155,14 @@ public static final class Machine {
private Machine(String name, ProcessorEntity.Kind kind) {
this.kind = kind;
- block = BLOCKS.register(
- name,
- () -> new DemoBlock(
- BlockBehaviour.Properties.of().strength(3.5F).requiresCorrectToolForDrops(),
+ block = BLOCKS.register(name,
+ () -> new DemoBlock(BlockBehaviour.Properties.of()
+ .strength(3.5F).requiresCorrectToolForDrops(),
this::entityType));
- type = ENTITIES.register(
- name, () -> BlockEntityType.Builder.of(this::create, block.get()).build(null));
- ITEMS.register(name, () -> new BlockItem(block.get(), new Item.Properties()));
+ type = ENTITIES.register(name, () -> BlockEntityType.Builder
+ .of(this::create, block.get()).build(null));
+ ITEMS.register(name,
+ () -> new BlockItem(block.get(), new Item.Properties()));
}
private BlockEntityType entityType() {
diff --git a/src/companion/java/zone/moddev/mc/companion/CompanionWidgets.java b/src/companion/java/zone/moddev/mc/companion/CompanionWidgets.java
index 574a2615..d41f5c10 100644
--- a/src/companion/java/zone/moddev/mc/companion/CompanionWidgets.java
+++ b/src/companion/java/zone/moddev/mc/companion/CompanionWidgets.java
@@ -9,46 +9,53 @@
import zone.moddev.mc.lib.gui.WidgetTypes;
import zone.moddev.mc.lib.gui.value.ValueTypes;
-/** A consuming mod owns the widget contract; no client class is referenced here. */
+/**
+ * A consuming mod owns the widget contract; no client class is referenced here.
+ */
public final class CompanionWidgets {
- public static final ResourceLocation PROGRESS_DIAL = CompanionMod.id("progress_dial");
- public static final ResourceLocation NAME_EDITOR = CompanionMod.id("name_editor");
- public static final ResourceLocation RESERVE_SLIDER = CompanionMod.id("reserve_slider");
- public static final ResourceLocation LANE_SELECTOR = CompanionMod.id("lane_selector");
+ public static final ResourceLocation PROGRESS_DIAL = CompanionMod
+ .id("progress_dial");
+ public static final ResourceLocation NAME_EDITOR = CompanionMod
+ .id("name_editor");
+ public static final ResourceLocation RESERVE_SLIDER = CompanionMod
+ .id("reserve_slider");
+ public static final ResourceLocation LANE_SELECTOR = CompanionMod
+ .id("lane_selector");
public static final WidgetAction RENAME = new WidgetAction<>(
CompanionMod.id("rename"),
- net.minecraft.network.codec.StreamCodec.of(
- (b, value) -> b.writeUtf(value, 32), b -> b.readUtf(32)),
+ net.minecraft.network.codec.StreamCodec
+ .of((b, value) -> b.writeUtf(value, 32), b -> b.readUtf(32)),
132,
- (context, value) -> context.menu().blockEntity instanceof ProcessorEntity machine
- && machine.rename(value));
+ (context,
+ value) -> context
+ .menu().blockEntity instanceof ProcessorEntity machine
+ && machine.rename(value));
public static final WidgetAction RESERVE = new WidgetAction<>(
CompanionMod.id("reserve"),
- net.minecraft.network.codec.StreamCodec.of(
- (b, value) -> b.writeVarInt(value), b -> b.readVarInt()),
+ net.minecraft.network.codec.StreamCodec
+ .of((b, value) -> b.writeVarInt(value), b -> b.readVarInt()),
5,
- (context, value) -> context.menu().blockEntity instanceof ProcessorEntity machine
- && machine.setReservePercent(value));
+ (context,
+ value) -> context
+ .menu().blockEntity instanceof ProcessorEntity machine
+ && machine.setReservePercent(value));
public record LaneSetting(int lane, boolean paused) {
}
public static final WidgetAction SET_LANE = new WidgetAction<>(
CompanionMod.id("set_lane"),
- net.minecraft.network.codec.StreamCodec.of(
- (b, value) -> {
- b.writeVarInt(value.lane());
- b.writeBoolean(value.paused());
- },
- b -> new LaneSetting(b.readVarInt(), b.readBoolean())),
- 6,
+ net.minecraft.network.codec.StreamCodec.of((b, value) -> {
+ b.writeVarInt(value.lane());
+ b.writeBoolean(value.paused());
+ }, b -> new LaneSetting(b.readVarInt(), b.readBoolean())), 6,
(context, value) -> {
if (!(context.menu().blockEntity instanceof ProcessorEntity machine)
- || value.lane() != Integer.parseInt(context.widget().properties().get("lane"))
- || value.lane() < 0
- || value.lane() >= machine.lanes.size())
+ || value.lane() != Integer
+ .parseInt(context.widget().properties().get("lane"))
+ || value.lane() < 0 || value.lane() >= machine.lanes.size())
return false;
if (machine.lanes.get(value.lane()).paused() != value.paused())
machine.toggle(value.lane());
@@ -59,35 +66,27 @@ private CompanionWidgets() {
}
public static void register() {
- WidgetTypes.GLOBAL.register(
- NAME_EDITOR,
- new WidgetType(
- Set.of(ValueTypes.TEXT),
+ WidgetTypes.GLOBAL.register(NAME_EDITOR,
+ new WidgetType(Set.of(ValueTypes.TEXT),
widget -> validateEditor(widget, 140, 42, Set.of()),
java.util.List.of(RENAME)));
- WidgetTypes.GLOBAL.register(
- RESERVE_SLIDER,
- new WidgetType(
- Set.of(ValueTypes.WHOLE),
+ WidgetTypes.GLOBAL.register(RESERVE_SLIDER,
+ new WidgetType(Set.of(ValueTypes.WHOLE),
widget -> validateEditor(widget, 100, 30, Set.of()),
java.util.List.of(RESERVE)));
- WidgetTypes.GLOBAL.register(
- LANE_SELECTOR,
- new WidgetType(
- Set.of(ValueTypes.BOOLEAN),
- widget -> {
- validateEditor(widget, 100, 30, Set.of("lane"));
- String lane = widget.properties().get("lane");
- if (!"0".equals(lane) && !"1".equals(lane))
- throw new IllegalArgumentException("lane must be 0 or 1");
- },
- java.util.List.of(SET_LANE)));
- WidgetTypes.GLOBAL.register(
- PROGRESS_DIAL,
+ WidgetTypes.GLOBAL.register(LANE_SELECTOR,
+ new WidgetType(Set.of(ValueTypes.BOOLEAN), widget -> {
+ validateEditor(widget, 100, 30, Set.of("lane"));
+ String lane = widget.properties().get("lane");
+ if (!"0".equals(lane) && !"1".equals(lane))
+ throw new IllegalArgumentException("lane must be 0 or 1");
+ }, java.util.List.of(SET_LANE)));
+ WidgetTypes.GLOBAL.register(PROGRESS_DIAL,
new WidgetType(
Set.of(ValueTypes.WHOLE, ValueTypes.DECIMAL, ValueTypes.NUMBER),
widget -> {
- if (widget.common().value().isEmpty() || widget.common().max().isEmpty())
+ if (widget.common().value().isEmpty()
+ || widget.common().max().isEmpty())
throw new IllegalArgumentException(
"A progress dial needs value and max getters");
if (widget.width() < 16 || widget.height() < 16)
@@ -95,18 +94,19 @@ public static void register() {
"A progress dial needs at least 16 x 16 px");
for (var name : widget.properties().keySet())
if (!name.equals("color"))
- throw new IllegalArgumentException("Unknown property: " + name);
- String color = widget.properties().getOrDefault("color", "#55CC88");
+ throw new IllegalArgumentException(
+ "Unknown property: " + name);
+ String color = widget.properties().getOrDefault("color",
+ "#55CC88");
if (!color.matches("#[0-9a-fA-F]{6}"))
- throw new IllegalArgumentException("color must be #RRGGBB");
+ throw new IllegalArgumentException(
+ "color must be #RRGGBB");
}));
}
private static void validateEditor(
- zone.moddev.mc.lib.gui.model.elements.CustomElement widget,
- int width,
- int height,
- Set properties) {
+ zone.moddev.mc.lib.gui.model.elements.CustomElement widget, int width,
+ int height, Set properties) {
if (widget.common().value().isEmpty())
throw new IllegalArgumentException("Editor needs a value getter");
if (widget.width() < width || widget.height() < height)
diff --git a/src/companion/java/zone/moddev/mc/companion/CreativePowerEntity.java b/src/companion/java/zone/moddev/mc/companion/CreativePowerEntity.java
index 3167c694..21078f36 100644
--- a/src/companion/java/zone/moddev/mc/companion/CreativePowerEntity.java
+++ b/src/companion/java/zone/moddev/mc/companion/CreativePowerEntity.java
@@ -21,72 +21,64 @@
/** Refills each tick and supplies up to 1,000 FE per adjacent face per tick. */
public final class CreativePowerEntity extends BasePoweredMachine {
- private final ItemStorage empty = new ItemStorage(0);
- public final AutomationInventory automation;
- private final MachineInventoryLifecycle inventoryLifecycle;
+ private final ItemStorage empty = new ItemStorage(0);
+ public final AutomationInventory automation;
+ private final MachineInventoryLifecycle inventoryLifecycle;
- public CreativePowerEntity(BlockEntityType> type, BlockPos pos, BlockState state) {
- super(type, pos, state, 100_000, 0, 1_000);
- energy.setStored(energy.capacity());
- var group =
- new ResourceGroup<>(
- "energy",
+ public CreativePowerEntity(BlockEntityType> type, BlockPos pos,
+ BlockState state) {
+ super(type, pos, state, 100_000, 0, 1_000);
+ energy.setStored(energy.capacity());
+ var group = new ResourceGroup<>("energy",
Component.translatable("screen.mmdlib_companion.group.energy"),
- 0xd85b5b,
- ResourceType.ENERGY,
- IoMode.OUTPUT,
- java.util.List.of(0),
- java.util.List.of("energy"),
- new SideConfig(IoMode.OUTPUT));
- automation =
- new zone.moddev.mc.lib.machine.neoforge.MachineResources(this, this::facing)
- .energy(group, energy)
- .build()
- .automation();
- inventoryLifecycle = poweredInventory(automation);
- zone.moddev.mc.lib.gui.runtime.ScreenInventoryValidation.validate(this);
- }
+ 0xd85b5b, ResourceType.ENERGY, IoMode.OUTPUT, java.util.List.of(0),
+ java.util.List.of("energy"), new SideConfig(IoMode.OUTPUT));
+ automation = new zone.moddev.mc.lib.machine.neoforge.MachineResources(
+ this, this::facing).energy(group, energy).build().automation();
+ inventoryLifecycle = poweredInventory(automation);
+ zone.moddev.mc.lib.gui.runtime.ScreenInventoryValidation.validate(this);
+ }
- @Override
- protected void beforeMachineTick() {
- energy.insert(energy.space(), false);
- }
+ @Override
+ protected void beforeMachineTick() {
+ energy.insert(energy.space(), false);
+ }
- @Override
- protected void afterMachineTick() {
- for (var side : Direction.values()) {
- if (!automation.mode(ResourceType.ENERGY, 0, side).canExtract()) continue;
- var target = worldPosition.relative(side);
- if (!level.hasChunkAt(target)) continue;
- var receiver =
- level.getCapability(Capabilities.EnergyStorage.BLOCK, target, side.getOpposite());
- if (receiver != null && receiver.canReceive())
- energy.extract(receiver.receiveEnergy(1_000, false), false);
+ @Override
+ protected void afterMachineTick() {
+ for (var side : Direction.values()) {
+ if (!automation.mode(ResourceType.ENERGY, 0, side).canExtract())
+ continue;
+ var target = worldPosition.relative(side);
+ if (!level.hasChunkAt(target))
+ continue;
+ var receiver = level.getCapability(Capabilities.EnergyStorage.BLOCK,
+ target, side.getOpposite());
+ if (receiver != null && receiver.canReceive())
+ energy.extract(receiver.receiveEnergy(1_000, false), false);
+ }
}
- }
- @Override
- public ItemStorage screenItems() {
- return empty;
- }
+ @Override
+ public ItemStorage screenItems() {
+ return empty;
+ }
- @Override
- public boolean screenAutomationAddons() {
- return false;
- }
+ @Override
+ public boolean screenAutomationAddons() {
+ return false;
+ }
- @Override
- protected MachineInventoryLifecycle machineInventory() {
- return inventoryLifecycle;
- }
+ @Override
+ protected MachineInventoryLifecycle machineInventory() {
+ return inventoryLifecycle;
+ }
- @Override
- protected void recoverResources(Level level, BlockPos pos, CompoundTag payload) {
- net.minecraft.world.Containers.dropItemStack(
- level,
- pos.getX() + .5,
- pos.getY() + .5,
- pos.getZ() + .5,
- RecoveryCapsuleItem.create(payload));
- }
+ @Override
+ protected void recoverResources(Level level, BlockPos pos,
+ CompoundTag payload) {
+ net.minecraft.world.Containers.dropItemStack(level, pos.getX() + .5,
+ pos.getY() + .5, pos.getZ() + .5,
+ RecoveryCapsuleItem.create(payload));
+ }
}
diff --git a/src/companion/java/zone/moddev/mc/companion/DemoBlock.java b/src/companion/java/zone/moddev/mc/companion/DemoBlock.java
index 1575391b..93f02ec4 100644
--- a/src/companion/java/zone/moddev/mc/companion/DemoBlock.java
+++ b/src/companion/java/zone/moddev/mc/companion/DemoBlock.java
@@ -38,20 +38,24 @@ public final class DemoBlock extends Block implements EntityBlock {
public static final DirectionProperty FACING = BlockStateProperties.HORIZONTAL_FACING;
private final Supplier> type;
- public DemoBlock(Properties properties, Supplier> type) {
+ public DemoBlock(Properties properties,
+ Supplier> type) {
super(properties);
this.type = type;
- registerDefaultState(stateDefinition.any().setValue(FACING, Direction.NORTH));
+ registerDefaultState(
+ stateDefinition.any().setValue(FACING, Direction.NORTH));
}
@Override
- protected void createBlockStateDefinition(StateDefinition.Builder builder) {
+ protected void createBlockStateDefinition(
+ StateDefinition.Builder builder) {
builder.add(FACING);
}
@Override
public BlockState getStateForPlacement(BlockPlaceContext context) {
- return defaultBlockState().setValue(FACING, context.getHorizontalDirection().getOpposite());
+ return defaultBlockState().setValue(FACING,
+ context.getHorizontalDirection().getOpposite());
}
@Override
@@ -70,17 +74,15 @@ protected boolean isSignalSource(BlockState state) {
}
@Override
- public boolean canConnectRedstone(
- BlockState state, BlockGetter level, BlockPos pos, @Nullable Direction side) {
+ public boolean canConnectRedstone(BlockState state, BlockGetter level,
+ BlockPos pos, @Nullable Direction side) {
return level.getBlockEntity(pos) instanceof ProcessorEntity entity
&& entity.redstone.connects(side);
}
@Override
- protected int getSignal(
- BlockState state,
- net.minecraft.world.level.BlockGetter level,
- BlockPos pos,
+ protected int getSignal(BlockState state,
+ net.minecraft.world.level.BlockGetter level, BlockPos pos,
net.minecraft.core.Direction side) {
return level.getBlockEntity(pos) instanceof ProcessorEntity entity
? entity.redstone.signal(side)
@@ -93,21 +95,17 @@ public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
}
@Override
- public BlockEntityTicker getTicker(
- Level level, BlockState state, BlockEntityType requested) {
+ public BlockEntityTicker getTicker(Level level,
+ BlockState state, BlockEntityType requested) {
if (level.isClientSide() || requested != type.get())
return null;
- return (world, pos, blockState, entity) -> ((BasePoweredMachine) entity).serverTick();
+ return (world, pos, blockState, entity) -> ((BasePoweredMachine) entity)
+ .serverTick();
}
@Override
- protected ItemInteractionResult useItemOn(
- ItemStack stack,
- BlockState state,
- Level level,
- BlockPos pos,
- Player player,
- InteractionHand hand,
+ protected ItemInteractionResult useItemOn(ItemStack stack, BlockState state,
+ Level level, BlockPos pos, Player player, InteractionHand hand,
BlockHitResult hit) {
if (stack.is(CompanionAddons.RECOVERY_CAPSULE.get())
&& level.getBlockEntity(pos) instanceof ProcessorEntity machine) {
@@ -122,19 +120,22 @@ protected ItemInteractionResult useItemOn(
&& FluidUtil.getFluidHandler(stack).isPresent()) {
if (level.isClientSide())
return ItemInteractionResult.SUCCESS;
- if (FluidUtil.interactWithFluidHandler(player, hand, machine.fluids))
+ if (FluidUtil.interactWithFluidHandler(player, hand,
+ machine.fluids))
return ItemInteractionResult.CONSUME;
player.displayClientMessage(
- Component.translatable("screen.mmdlib_companion.tank.refused"), true);
- // Do not let a rejected bucket spill its contents beside the machine.
+ Component.translatable("screen.mmdlib_companion.tank.refused"),
+ true);
+ // Do not let a rejected bucket spill its contents beside the
+ // machine.
return ItemInteractionResult.FAIL;
}
return ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION;
}
@Override
- protected InteractionResult useWithoutItem(
- BlockState state, Level level, BlockPos pos, Player player, BlockHitResult hit) {
+ protected InteractionResult useWithoutItem(BlockState state, Level level,
+ BlockPos pos, Player player, BlockHitResult hit) {
return level.getBlockEntity(pos) instanceof BasePoweredMachine machine
&& machine.openScreen(player)
? InteractionResult.sidedSuccess(level.isClientSide())
@@ -142,8 +143,8 @@ protected InteractionResult useWithoutItem(
}
@Override
- protected void onRemove(
- BlockState state, Level level, BlockPos pos, BlockState replacement, boolean moved) {
+ protected void onRemove(BlockState state, Level level, BlockPos pos,
+ BlockState replacement, boolean moved) {
DropsContents.onRemove(state, level, pos, replacement);
super.onRemove(state, level, pos, replacement, moved);
}
diff --git a/src/companion/java/zone/moddev/mc/companion/ProcessorEntity.java b/src/companion/java/zone/moddev/mc/companion/ProcessorEntity.java
index 2cbb208c..02d5b7b1 100644
--- a/src/companion/java/zone/moddev/mc/companion/ProcessorEntity.java
+++ b/src/companion/java/zone/moddev/mc/companion/ProcessorEntity.java
@@ -28,7 +28,10 @@
import zone.moddev.mc.lib.machine.neoforge.MachineInventoryLifecycle;
import zone.moddev.mc.lib.machine.neoforge.MachineResources;
-/** The dual crusher deliberately runs two lanes over the same input and output groups. */
+/**
+ * The dual crusher deliberately runs two lanes over the same input and output
+ * groups.
+ */
public final class ProcessorEntity extends BasePoweredMachine {
public enum Kind {
CRUSHER, TRANSMUTER, DUAL, LOGISTICS
@@ -38,7 +41,8 @@ public enum Kind {
public final AutomationInventory automation;
public final MachineResources resources;
public final MachineInventoryLifecycle inventoryLifecycle;
- public final FluidStorage fluids = new FluidStorage().onChange(this::setChanged);
+ public final FluidStorage fluids = new FluidStorage()
+ .onChange(this::setChanged);
public final List lanes;
private final Kind kind;
public final RedstoneControl redstone;
@@ -70,124 +74,122 @@ public boolean setReservePercent(int value) {
return true;
}
- public ProcessorEntity(BlockEntityType> type, BlockPos pos, BlockState state, Kind kind) {
+ public ProcessorEntity(BlockEntityType> type, BlockPos pos,
+ BlockState state, Kind kind) {
super(type, pos, state);
this.kind = kind;
if (kind == Kind.CRUSHER)
- fluids.addTank(
- 4_000,
- Role.STORAGE,
- fluid -> fluid.getFluid() == Fluids.WATER || fluid.getFluid() == Fluids.LAVA);
+ fluids.addTank(4_000, Role.STORAGE,
+ fluid -> fluid.getFluid() == Fluids.WATER
+ || fluid.getFluid() == Fluids.LAVA);
if (kind == Kind.LOGISTICS)
for (int i = 0; i < 4; i++)
fluids.addTank(4000, i < 2 ? Role.INPUT : Role.OUTPUT);
- int[] outputSlots = kind == Kind.CRUSHER ? new int[]{1, 2} : new int[]{1};
+ int[] outputSlots = kind == Kind.CRUSHER
+ ? new int[]{1, 2}
+ : new int[]{1};
resources = new MachineResources(this, this::facing);
if (kind == Kind.TRANSMUTER) {
- // One key, and one item: the recipe consumes the whole slot before inserting gold.
+ // One key, and one item: the recipe consumes the whole slot before
+ // inserting gold.
items = ItemInventories.partition(List.of("input")).limit(1, 0)
.onChange(this::setChanged);
} else {
- items = ItemInventories.partition(
- java.util.stream.IntStream.range(0, 1 + outputSlots.length)
- .mapToObj(i -> i == 0 ? "input" : "output")
- .toList())
+ items = ItemInventories
+ .partition(
+ java.util.stream.IntStream.range(0, 1 + outputSlots.length)
+ .mapToObj(i -> i == 0 ? "input" : "output").toList())
.role(Role.INPUT, 0)
- .role(kind == Kind.CRUSHER ? Role.STORAGE : Role.OUTPUT, outputSlots)
+ .role(kind == Kind.CRUSHER ? Role.STORAGE : Role.OUTPUT,
+ outputSlots)
.onChange(this::setChanged);
}
- var recipeType = kind == Kind.TRANSMUTER ? CompanionMod.TRANSMUTING : CompanionMod.CRUSHING;
+ var recipeType = kind == Kind.TRANSMUTER
+ ? CompanionMod.TRANSMUTING
+ : CompanionMod.CRUSHING;
resources.items(
- itemGroup("input", 0x568bd8, kind == Kind.TRANSMUTER ? IoMode.BOTH : IoMode.INPUT, 0),
+ itemGroup("input", 0x568bd8,
+ kind == Kind.TRANSMUTER ? IoMode.BOTH : IoMode.INPUT, 0),
items.inventory("input"));
if (kind != Kind.TRANSMUTER)
- resources.items(
- itemGroup(
- "output",
- 0xe48f45,
- kind == Kind.CRUSHER ? IoMode.BOTH : IoMode.OUTPUT,
- java.util.stream.IntStream.range(0, outputSlots.length).toArray()),
+ resources.items(itemGroup("output", 0xe48f45,
+ kind == Kind.CRUSHER ? IoMode.BOTH : IoMode.OUTPUT,
+ java.util.stream.IntStream.range(0, outputSlots.length)
+ .toArray()),
items.inventory("output"));
items.slotId(0, "input");
for (int i = 1; i < items.getSlots(); i++)
items.slotId(i, "output_" + i);
int[] colours = {0x64bfc1, 0xa678cb, 0xe0c55d, 0xce668e};
for (int i = 0; i < fluids.getTanks(); i++) {
- var group = new ResourceGroup<>(
- "tank_" + i,
- Component.translatable("screen.mmdlib_companion.group.tank", i + 1),
- colours[i],
- ResourceType.FLUIDS,
- kind == Kind.CRUSHER ? IoMode.BOTH : (i < 2 ? IoMode.INPUT : IoMode.OUTPUT),
- List.of(i),
- List.of(i == 0 ? "tank" : "tank_" + i),
- new SideConfig(
- kind == Kind.CRUSHER ? IoMode.BOTH : (i < 2 ? IoMode.INPUT : IoMode.OUTPUT)));
+ var group = new ResourceGroup<>("tank_" + i,
+ Component
+ .translatable("screen.mmdlib_companion.group.tank", i + 1),
+ colours[i], ResourceType.FLUIDS,
+ kind == Kind.CRUSHER
+ ? IoMode.BOTH
+ : (i < 2 ? IoMode.INPUT : IoMode.OUTPUT),
+ List.of(i), List.of(i == 0 ? "tank" : "tank_" + i),
+ new SideConfig(kind == Kind.CRUSHER
+ ? IoMode.BOTH
+ : (i < 2 ? IoMode.INPUT : IoMode.OUTPUT)));
resources.fluids(group, fluids);
fluids.tankId(i, group.id());
}
- var energyGroup = new ResourceGroup<>(
- "energy",
+ var energyGroup = new ResourceGroup<>("energy",
Component.translatable("screen.mmdlib_companion.group.energy"),
- 0xd85b5b,
- ResourceType.ENERGY,
- kind == Kind.LOGISTICS ? IoMode.BOTH : IoMode.INPUT,
- List.of(0),
- List.of("energy"),
- new SideConfig(kind == Kind.LOGISTICS ? IoMode.BOTH : IoMode.INPUT));
+ 0xd85b5b, ResourceType.ENERGY,
+ kind == Kind.LOGISTICS ? IoMode.BOTH : IoMode.INPUT, List.of(0),
+ List.of("energy"), new SideConfig(
+ kind == Kind.LOGISTICS ? IoMode.BOTH : IoMode.INPUT));
if (kind == Kind.LOGISTICS)
energy.setRates(1000, 1000);
resources.energy(energyGroup, energy);
if (kind == Kind.TRANSMUTER)
resources.recipeGroup("slot", "input");
if (kind != Kind.LOGISTICS)
- resources.recipeInputs(recipeType, kind == Kind.TRANSMUTER ? "slot" : "input");
+ resources.recipeInputs(recipeType,
+ kind == Kind.TRANSMUTER ? "slot" : "input");
resources.build();
automation = resources.automation();
var processors = new ArrayList();
for (int i = 0; i < (kind == Kind.DUAL ? 2 : 1); i++) {
- var processor = new RecipeProcessor(
- "lane_" + i,
- recipeType,
- resources.recipes(),
- Component.translatable("screen.mmdlib_companion.processor", i + 1));
+ var processor = new RecipeProcessor("lane_" + i, recipeType,
+ resources.recipes(), Component
+ .translatable("screen.mmdlib_companion.processor", i + 1));
processors.add(processor);
features.add(processor);
}
lanes = List.copyOf(processors);
- inventoryLifecycle = poweredInventory(automation).items("items", items).fluids("fluids",
- fluids);
+ inventoryLifecycle = poweredInventory(automation).items("items", items)
+ .fluids("fluids", fluids);
var outputParts = new ArrayList