Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 28 additions & 3 deletions .github/workflows/verify.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: neoforge 26.1.2 build and regression
on:
push:
branches: ['neoforge/26.1.2']
branches: ["gui/**", "feature/**", 'neoforge/26.1.2']
pull_request:
branches: ['neoforge/26.1.2']
workflow_dispatch:
Expand All @@ -21,7 +21,8 @@ jobs:
- name: Fetch pinned Streams dependency
run: |
mkdir -p libs
curl --fail --location --retry 3 'https://cdn.modrinth.com/data/oLS8HdJ1/versions/99I1ZRJb/StreamsReflowing-26.1.2-neoforge-2.15.2.jar' -o 'libs/StreamsReflowing-26.1.2-neoforge-2.15.2.jar'
curl --fail --location --retry 3 'https://cdn.modrinth.com/data/oLS8HdJ1/versions/cZobwROy/StreamsReflowing-26.1.2-neoforge-2.16.2.jar' -o 'libs/StreamsReflowing-26.1.2-neoforge-2.16.2.jar'
echo '2f4466515672595c2e366d4e3f181a2b05613040087c003745055f5efc436997 libs/StreamsReflowing-26.1.2-neoforge-2.16.2.jar' | sha256sum --check
- name: Build
run: bash gradlew --no-daemon clean build
- name: Prepare disposable regression world
Expand All @@ -43,8 +44,32 @@ jobs:
if: always()
uses: actions/upload-artifact@v4
with:
name: flow-control-neoforge-26.1.2-0.1.5
name: flow-control-neoforge-26.1.2-0.2.2
path: |
build/libs/*.jar
run/streamcontrol-integration-results.json
run/logs/latest.log

- name: Capture client menus and baked block models
run: |
mkdir -p run-client
printf 'onboardAccessibility:false\nguiScale:3\nfullscreen:false\n' > run-client/options.txt
bash gradlew --no-daemon runServer > client-preview-server.log 2>&1 &
SERVER_PID=$!
trap 'kill "$SERVER_PID" $(jobs -pr) 2>/dev/null || true' EXIT
for attempt in $(seq 1 120); do
if rg -q 'Done \(' client-preview-server.log; then break; fi
if ! kill -0 "$SERVER_PID" 2>/dev/null; then tail -n 40 client-preview-server.log; exit 1; fi
sleep 1
done
timeout 360 xvfb-run -a bash gradlew --no-daemon -Dstreamcontrol.uiPreview=true runClient
test -s run-client/screenshots/flow-control-block-models.png
- name: Upload client screenshots
if: always()
uses: actions/upload-artifact@v4
with:
name: flow-control-0.2.2-neoforge-26.1.2-client
path: |
run-client/screenshots/*.png
run-client/logs/latest.log
client-preview-server.log
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
## 0.1.6 — TNK GUI Rework

![Flow Control](https://i.imgur.com/JGT2lvz.png)

- Restyled Current Generator and Stillwater Anchor using the latest TNK Loot / Progression menu design.
- Slate-blue frames, white outer outlines, inset copper panels and a raised title plate.
- Matching textured buttons, compass selections and slider controls, with visible keyboard focus.
- Embedded the supplied mixed-case menu font for titles; retained Minecraft text for settings and values.
- Preserved eight compass directions, normalized diagonal current strength, connected-water mode, redstone behavior and Apply/Cancel.
- Existing saves, config limits and network packet formats remain compatible with 0.1.5.

# Changelog

## 0.1.5 — Eight-way current compass
Expand Down
15 changes: 12 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,23 @@ plugins {
id 'java-library'
id 'net.neoforged.moddev' version '2.0.148'
}
version = '0.1.5'
version = '0.2.2'
group = 'nl.townsandkingdoms.streamcontrol'
base.archivesName = 'streams-flow-control-neoforge-26.1.2'
java.toolchain.languageVersion = JavaLanguageVersion.of(25)
java.withSourcesJar()
neoForge {
version = '26.1.2.122'
runs {
client {
client()
gameDirectory = file('run-client')
programArgument '--width'
programArgument '960'
programArgument '--height'
programArgument '720'
systemProperty 'streamcontrol.uiPreview', System.getProperty('streamcontrol.uiPreview','false')
}
server {
server()
programArgument '--nogui'
Expand All @@ -21,10 +30,10 @@ neoForge {
mods { streamcontrol { sourceSet sourceSets.main } }
}
dependencies {
implementation files('libs/StreamsReflowing-26.1.2-neoforge-2.15.2.jar')
implementation files('libs/StreamsReflowing-26.1.2-neoforge-2.16.2.jar')

}
tasks.withType(JavaCompile).configureEach { options.encoding = 'UTF-8'; options.release = 25 }
tasks.named('jar') { from('LICENSE') }

tasks.named("jar") { archiveFileName = "flow-control-0.1.5-neoforge-26.1.2.jar" }
tasks.named("jar") { archiveFileName = "flow-control-0.2.2-neoforge-26.1.2.jar" }
Original file line number Diff line number Diff line change
@@ -1,30 +1,18 @@
package nl.townsandkingdoms.streamcontrol;
import com.mojang.brigadier.arguments.*;
import net.minecraft.commands.Commands;
import net.minecraft.core.component.DataComponents;
import net.minecraft.network.chat.Component;
import net.minecraft.world.item.component.CustomData;
import net.neoforged.neoforge.event.RegisterCommandsEvent;
public final class ControlCommands {
public static void register(RegisterCommandsEvent e) {
e.getDispatcher().register(Commands.literal("streamcontrol")
.then(Commands.literal("radius").then(Commands.argument("blocks",IntegerArgumentType.integer(1,32)).executes(c -> {
var p = c.getSource().getPlayerOrException(); var s = p.getMainHandItem();
if (!s.is(StreamControl.WAND.get())) return 0;
var n = FlowWand.settings(s); n.putInt("Radius",ControlConfig.radius(IntegerArgumentType.getInteger(c,"blocks"))); s.set(DataComponents.CUSTOM_DATA,CustomData.of(n)); return 1;
})))
.then(Commands.literal("strength").then(Commands.argument("value",DoubleArgumentType.doubleArg(0.05,2)).executes(c -> {
var p = c.getSource().getPlayerOrException(); var s = p.getMainHandItem(); if (!s.is(StreamControl.WAND.get())) return 0;
var n = FlowWand.settings(s); n.putDouble("Strength",ControlConfig.strength(DoubleArgumentType.getDouble(c,"value"))); s.set(DataComponents.CUSTOM_DATA,CustomData.of(n)); return 1;
})))
.then(Commands.literal("status").executes(c -> {
var p = net.minecraft.core.BlockPos.containing(c.getSource().getPosition()); var data = ControlData.get(c.getSource().getLevel()); var r = data.at(p.getX(),p.getY(),p.getZ());
c.getSource().sendSuccess(() -> Component.literal("Flow Control: " + data.all().size() + " regions; here=" + (r == null ? "natural" : r.still() ? "still" : "directed")),false); return 1;
.then(Commands.literal("status").executes(c->{
var p=net.minecraft.core.BlockPos.containing(c.getSource().getPosition());var data=ControlData.get(c.getSource().getLevel());var r=data.at(p.getX(),p.getY(),p.getZ());
c.getSource().sendSuccess(()->Component.literal("Flow Control: "+data.all().size()+" regions; here="+(r==null?"natural":r.still()?"still":"directed")),false);return 1;
}))
.then(Commands.literal("clear").requires(s -> s.permissions().hasPermission(net.minecraft.server.permissions.Permissions.COMMANDS_GAMEMASTER)).executes(c -> {
var level = c.getSource().getLevel(); var data = ControlData.get(level); int count = 0;
for (var r : data.all()) if (!r.controller()) { data.remove(level,r.key()); count++; }
final int removed = count; c.getSource().sendSuccess(() -> Component.literal("Removed " + removed + " wand regions in this dimension."),true); return count;
.then(Commands.literal("clear").requires(s->s.permissions().hasPermission(net.minecraft.server.permissions.Permissions.COMMANDS_GAMEMASTER)).executes(c->{
var level=c.getSource().getLevel();var data=ControlData.get(level);int count=0;
for(var r:data.all()) if(!r.controller()) { data.remove(level,r.key());count++; }
final int removed=count;c.getSource().sendSuccess(()->Component.literal("Removed "+removed+" legacy wand regions in this dimension."),true);return count;
})));
}
}
17 changes: 13 additions & 4 deletions src/main/java/nl/townsandkingdoms/streamcontrol/ControlConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,30 @@
public final class ControlConfig {
public static final ModConfigSpec SPEC;
public static final ModConfigSpec.BooleanValue ENABLED, WAND_ENABLED, OP_ONLY, PARTICLES;
public static final ModConfigSpec.IntValue MAX_RADIUS, DEFAULT_RADIUS, VERTICAL, MAX_REGIONS, MAX_PLAYER_REGIONS;
public static final ModConfigSpec.DoubleValue SPEED, MAX_SPEED;
public static final ModConfigSpec.IntValue MAX_RADIUS, DEFAULT_RADIUS, VERTICAL, MAX_REGIONS, MAX_PLAYER_REGIONS, MAX_VERTICAL, LINK_RANGE, SENSOR_MAX_RADIUS, SENSOR_MAX_VERTICAL, SENSOR_INTERVAL, MOORING_MAX_RADIUS, MOORING_MAX_VERTICAL;
public static final ModConfigSpec.DoubleValue SPEED, MAX_SPEED, RPM_FULL_STRENGTH, KINETIC_STRESS;
static {
var b = new ModConfigSpec.Builder();
ENABLED = b.comment("Master switch. Overrides remain saved when disabled.").define("enabled", true);
WAND_ENABLED = b.define("wandEnabled", true);
WAND_ENABLED = b.comment("Enable the Flow Calibrator; legacy config key retained.").define("wandEnabled", true);
OP_ONLY = b.define("wandRequiresOperator", false);
PARTICLES = b.define("showWandFeedbackParticles", true);
PARTICLES = b.comment("Show Calibrator range outlines; legacy config key retained.").define("showWandFeedbackParticles", true);
MAX_RADIUS = b.defineInRange("maxRadius", 16, 1, 32);
DEFAULT_RADIUS = b.defineInRange("defaultRadius", 4, 1, 32);
VERTICAL = b.comment("Blocks above and below the selected water or controller that can be affected.").defineInRange("verticalReach", 4, 0, 16);
SPEED = b.comment("Current strength relative to a normal Streams current.").defineInRange("defaultStrength", 1.0, 0.05, 2.0);
MAX_SPEED = b.defineInRange("maxStrength", 2.0, 0.05, 2.0);
MAX_REGIONS = b.defineInRange("maxRegionsPerDimension", 2048, 1, 8192);
MAX_PLAYER_REGIONS = b.defineInRange("maxWandRegionsPerPlayer", 256, 1, 2048);
MAX_VERTICAL = b.defineInRange("maxControllerVerticalReach",16,0,16);
LINK_RANGE = b.defineInRange("maxControllerLinkDistance",64,1,256);
SENSOR_MAX_RADIUS = b.defineInRange("maxSensorRadius",16,1,16);
SENSOR_MAX_VERTICAL = b.defineInRange("maxSensorVerticalReach",16,0,16);
SENSOR_INTERVAL = b.defineInRange("sensorSampleIntervalTicks",20,5,200);
MOORING_MAX_RADIUS = b.defineInRange("maxMooringRadius",8,1,16);
MOORING_MAX_VERTICAL = b.defineInRange("maxMooringVerticalReach",8,0,16);
RPM_FULL_STRENGTH = b.defineInRange("kineticRpmForFullStrength",128.0,1.0,1024.0);
KINETIC_STRESS = b.defineInRange("kineticStressImpact",4.0,0.0,256.0);
SPEC = b.build();
}
public static int radius(int value) { return Math.clamp(value, 1, MAX_RADIUS.get()); }
Expand Down
Loading
Loading