Skip to content

Commit

Permalink
Interface groups
Browse files Browse the repository at this point in the history
  • Loading branch information
MattiDragon committed Jan 19, 2024
1 parent 646fa1b commit 5003769
Show file tree
Hide file tree
Showing 28 changed files with 412 additions and 253 deletions.
4 changes: 3 additions & 1 deletion changelog/3.1.0+1.20.4.md
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
* Make interfaces use names from attached containers as fallback
* Make interfaces use names from attached containers as fallback
* Add interface groups
* They allow you to interact with multiple interfaces as one
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,11 @@ public void onInitializeClient() {
ClientPlayNetworking.registerGlobalReceiver(RequestInterfacesPacket.RESPONSE_ID, (client, handler, buf, responseSender) -> {
var syncId = buf.readByte();
var interfaces = buf.readMap(PacketByteBuf::readString, PacketByteBuf::readText);
var groups = buf.readMap(PacketByteBuf::readString, buf1 -> buf1.readList(PacketByteBuf::readString));

client.execute(() -> {
if (client.player != null && client.player.currentScreenHandler.syncId == syncId && client.currentScreen instanceof InterfaceNodeConfigScreen<?> configScreen) {
configScreen.setInterfaces(interfaces);
configScreen.setInterfaces(interfaces, groups);
}
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public class CableConfigScreen extends Screen {
private Direction side;
private InterfaceType type;
private String name;
private String group;
private boolean adventureModeAccessAllowed;

public CableConfigScreen(BlockPos pos, Direction side, CableBlockEntity cable) {
Expand All @@ -35,6 +36,7 @@ public CableConfigScreen(BlockPos pos, Direction side, CableBlockEntity cable) {
this.cable = cable;
this.type = getType();
this.name = getName();
this.group = getGroup();
}

private InterfaceType getType() {
Expand All @@ -45,6 +47,10 @@ private String getName() {
return this.cable.getName(this.side);
}

private String getGroup() {
return this.cable.getGroup(this.side);
}

@Override
protected void init() {
var interfaceTypeButton = addDrawableChild(CyclingButtonWidget.<InterfaceType>builder(type -> Text.translatable("screen.advanced_networking.cable_config.interface_type." + type.id))
Expand All @@ -57,20 +63,26 @@ protected void init() {
nameField.setPlaceholder(cable.getBackupName(side).copy().formatted(Formatting.GRAY));
nameField.setChangedListener(value -> name = value.trim());

var groupField = addDrawableChild(new TextFieldWidget(textRenderer, calcRightX() - 100, 90, 100, 20, Text.empty()));
groupField.setText(group);
groupField.setChangedListener(value -> group = value.trim());

var buttons = new ButtonWidget[6];
for (int i = 0; i < 6; i++) {
var direction = Direction.byId(i);
var button = ButtonWidget.builder(Text.translatable("side.advanced_networking." + direction.asString()), button1 -> {
button1.active = false;
buttons[side.getId()].active = true;

ClientPlayNetworking.send(new UpdateInterfacePacket(pos, side, type, name));
ClientPlayNetworking.send(new UpdateInterfacePacket(pos, side, type, name, group));
side = direction;
type = getType();
name = getName();
group = getGroup();
interfaceTypeButton.setValue(type);
nameField.setText(name);
nameField.setPlaceholder(cable.getBackupName(side).copy().formatted(Formatting.GRAY));
groupField.setText(group);
}).width(100).position(calcLeftX(), 40 + 20 * i).build();
addDrawableChild(button);
buttons[i] = button;
Expand All @@ -95,7 +107,7 @@ public boolean shouldPause() {
@Override
public void close() {
super.close();
ClientPlayNetworking.send(new UpdateInterfacePacket(pos, side, type, name));
ClientPlayNetworking.send(new UpdateInterfacePacket(pos, side, type, name, group));
}

private int calcLeftX() {
Expand All @@ -115,11 +127,13 @@ public void render(DrawContext context, int mouseX, int mouseY, float delta) {
context.drawText(textRenderer, title, (width - textRenderer.getWidth(title.asOrderedText())) / 2, 10, 0xffffff, false);

// Info rows
context.drawText(textRenderer, Text.translatable("screen.advanced_networking.cable_config.pos", pos.getX(), pos.getY(), pos.getZ()), calcRightX() - 150, 100, 0xffffff, false);
context.drawText(textRenderer, Text.translatable("screen.advanced_networking.cable_config.id", CableBlock.calcInterfaceId(pos, side)), calcRightX() - 150, 110, 0xffffff, false);
context.drawText(textRenderer, Text.translatable("screen.advanced_networking.cable_config.pos", pos.getX(), pos.getY(), pos.getZ()), calcRightX() - 150, 120, 0xffffff, false);
context.drawText(textRenderer, Text.translatable("screen.advanced_networking.cable_config.id", CableBlock.calcInterfaceId(pos, side)), calcRightX() - 150, 130, 0xffffff, false);

// Name field tag
var nameText = Text.translatable("screen.advanced_networking.cable_config.name");
context.drawText(textRenderer, nameText, calcRightX() - 110 - textRenderer.getWidth(nameText), 75, 0xffffff, false);
var groupText = Text.translatable("screen.advanced_networking.cable_config.group");
context.drawText(textRenderer, groupText, calcRightX() - 110 - textRenderer.getWidth(groupText), 95, 0xffffff, false);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@
import net.minecraft.client.gui.widget.CheckboxWidget;
import net.minecraft.client.gui.widget.ElementListWidget;
import net.minecraft.text.Text;
import org.jetbrains.annotations.NotNull;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

Expand All @@ -39,29 +41,76 @@ protected void init() {
ClientPlayNetworking.send(RequestInterfacesPacket.ID, buf);
}

public void setInterfaces(Map<String, Text> interfaces) {
public void setInterfaces(Map<String, Text> interfaces, Map<String, List<String>> groups) {
interfaceList.children().clear();
if (interfaces.isEmpty())
if (interfaces.isEmpty()) {
this.interfaceList.children().add(interfaceList.new MessageEntry(Text.translatable("node.advanced_networking.interface.no_interfaces")));
return;
}

interface Sortable extends Comparable<Sortable> {
String getName();

for (var entry : interfaces.entrySet()) {
var interfaceEntry = interfaceList.new InterfaceEntry(new Interface(entry.getKey(), entry.getValue()));
this.interfaceList.children().add(interfaceEntry);
if (entry.getKey().equals(owner.interfaceId))
interfaceEntry.checkbox.onPress();
@Override
default int compareTo(@NotNull Sortable o) {
return getName().compareTo(o.getName());
}
}
interfaceList.children().sort((first, second) -> {
if (first instanceof InterfaceList.InterfaceEntry firstInterface) {
if (second instanceof InterfaceList.InterfaceEntry secondInterface) {
return firstInterface.value.name.getString().compareTo(secondInterface.value.name.getString());
}
return -1;

record Single(String id, Text name) implements Sortable {
@Override
public String getName() {
return name.getString();
}
}

record Group(String id, List<Single> interfaces) implements Sortable {
@Override
public String getName() {
return id;
}
return second instanceof InterfaceList.InterfaceEntry ? 1 : 0;
}

var entries = new ArrayList<Sortable>();
interfaces.keySet()
.stream()
.filter(id -> groups.values().stream().noneMatch(group -> group.contains(id)))
.forEach(id -> entries.add(new Single(id, interfaces.get(id))));

groups.forEach((id, groupEntries) -> {
var filtered = groupEntries.stream().filter(interfaces::containsKey).toList();
if (filtered.isEmpty()) return;
var convertedEntries = filtered.stream()
.map(entry -> new Single(entry, interfaces.get(entry)))
.sorted()
.toList();
entries.add(new Group(id, convertedEntries));
});
}

record Interface(String id, Text name) {
entries.sort(null);

for (var entry : entries) {
if (entry instanceof Single single) {
var added = interfaceList.new InterfaceEntry(single.id(), single.name(), false, false);
interfaceList.children().add(added);
if (!owner.isGroup && owner.interfaceId.equals(single.id)) {
((CheckboxWidgetAccess) added.checkbox).setChecked(true);
}
} else if (entry instanceof Group group) {
var groupEntry = interfaceList.new InterfaceEntry(group.id(), Text.literal(group.id()), true, false);
interfaceList.children().add(groupEntry);
for (var child : group.interfaces()) {
var childEntry = interfaceList.new InterfaceEntry(child.id(), child.name(), false, true);
interfaceList.children().add(childEntry);
if (!owner.isGroup && owner.interfaceId.equals(child.id)) {
((CheckboxWidgetAccess) childEntry.checkbox).setChecked(true);
}
}
if (owner.isGroup && owner.interfaceId.equals(group.id)) {
((CheckboxWidgetAccess) groupEntry.checkbox).setChecked(true);
}
}
}
}

private class InterfaceList extends ElementListWidget<InterfaceList.Entry> {
Expand Down Expand Up @@ -111,24 +160,25 @@ public void render(DrawContext context, int index, int y, int x, int entryWidth,
}

private class InterfaceEntry extends InterfaceList.Entry {
private final Interface value;
private final CheckboxWidget checkbox;
private final boolean isUnderGroup;

private InterfaceEntry(Interface value) {
this.value = value;
this.checkbox = CheckboxWidget.builder(value.name, textRenderer)
private InterfaceEntry(String id, Text name, boolean isGroup, boolean isUnderGroup) {
this.checkbox = CheckboxWidget.builder(name, textRenderer)
.callback((clickedBox, checked) -> {
for (int i = 0; i < getEntryCount(); i++) {
if (getEntry(i) instanceof InterfaceList.InterfaceEntry entry && entry.checkbox != clickedBox) {
((CheckboxWidgetAccess) entry.checkbox).setChecked(false);
}
}

owner.interfaceId = value.id;
owner.interfaceId = id;
owner.isGroup = isGroup;
})
.build();
checkbox.setWidth(150);
checkbox.setWidth(isUnderGroup ? 130 : 150);
checkbox.setHeight(20);
this.isUnderGroup = isUnderGroup;
}

@Override
Expand All @@ -143,7 +193,7 @@ public List<? extends Element> children() {

@Override
public void render(DrawContext context, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) {
checkbox.setX(x);
checkbox.setX(isUnderGroup ? x + 20 : x);
checkbox.setY(y);
checkbox.render(context, mouseX, mouseY, tickDelta);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,13 @@
public class CableBlockEntity extends BlockEntity implements AdventureModeAccessBlockEntity {
private final int[] power = new int[6];
private final String[] names = new String[6];
private final String[] groups = new String[6];
private boolean allowAdventureModeAccess = false;

public CableBlockEntity(BlockPos pos, BlockState state) {
super(ModBlocks.CABLE_BLOCK_ENTITY, pos, state);
Arrays.fill(names, "");
Arrays.fill(groups, "");
}

public void setPower(Direction direction, int power) {
Expand All @@ -40,6 +42,17 @@ public int getPower(Direction direction) {
return this.power[direction.getId()];
}

public void setGroup(Direction direction, String group) {
this.groups[direction.getId()] = group;
markDirty();
if (world instanceof ServerWorld serverWorld)
serverWorld.getChunkManager().markForUpdate(pos);
}

public String getGroup(Direction direction) {
return groups[direction.getId()];
}

public void setName(Direction direction, String name) {
this.names[direction.getId()] = name;
markDirty();
Expand Down Expand Up @@ -88,6 +101,11 @@ public void readNbt(NbtCompound nbt) {
for (int i = 0; i < Math.min(names.size(), 6); i++) {
this.names[i] = names.get(i).asString();
}

var groups = nbt.getList("groups", NbtElement.STRING_TYPE);
for (int i = 0; i < Math.min(groups.size(), 6); i++) {
this.groups[i] = groups.get(i).asString();
}
}

@Override
Expand All @@ -101,6 +119,12 @@ protected void writeNbt(NbtCompound nbt) {
names.add(NbtString.of(name));
}
nbt.put("names", names);

var groups = new NbtList();
for (var group : this.groups) {
groups.add(NbtString.of(group));
}
nbt.put("groups", groups);
}

public boolean isAdventureModeAccessAllowed() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package io.github.mattidragon.advancednetworking.graph.node.base;

import com.mojang.datafixers.util.Either;
import io.github.mattidragon.advancednetworking.graph.NetworkControllerContext;
import io.github.mattidragon.nodeflow.graph.Connector;
import io.github.mattidragon.nodeflow.graph.Graph;
import io.github.mattidragon.nodeflow.graph.context.ContextType;
import io.github.mattidragon.nodeflow.graph.data.DataType;
import io.github.mattidragon.nodeflow.graph.data.DataValue;
import io.github.mattidragon.nodeflow.graph.node.NodeType;
import net.fabricmc.fabric.api.lookup.v1.block.BlockApiLookup;
import net.fabricmc.fabric.api.transfer.v1.storage.Storage;
import net.fabricmc.fabric.api.transfer.v1.storage.StorageView;
import net.fabricmc.fabric.api.transfer.v1.storage.TransferVariant;
import net.minecraft.text.Text;
import net.minecraft.util.math.Direction;
import org.jetbrains.annotations.Nullable;

import java.util.List;
import java.util.Objects;
import java.util.stream.StreamSupport;

public class CapacityNode<R, V extends TransferVariant<R>> extends InterfaceNode {
private final BlockApiLookup<Storage<V>, @Nullable Direction> lookup;

public CapacityNode(NodeType<?> type, Graph graph, BlockApiLookup<Storage<V>, @Nullable Direction> lookup) {
super(type, List.of(NetworkControllerContext.TYPE, ContextType.SERVER_WORLD), graph);
this.lookup = lookup;
}

@Override
public Connector<?>[] getOutputs() {
return new Connector[] { DataType.NUMBER.makeRequiredOutput("capacity", this) };
}

@Override
public Connector<?>[] getInputs() {
return new Connector[0];
}

@Override
protected Either<DataValue<?>[], Text> process(DataValue<?>[] inputs, ContextProvider context) {
var controller = context.get(NetworkControllerContext.TYPE);
var world = context.get(ContextType.SERVER_WORLD);
var positions = findInterfaces(world, controller.graphId());

var capacity = positions.stream()
.map(sidePos -> {
var pos = sidePos.pos();
var side = sidePos.side();
return lookup.find(world, pos.offset(side), side.getOpposite());
})
.filter(Objects::nonNull)
.flatMap(storage -> StreamSupport.stream(storage.spliterator(), false))
.mapToLong(StorageView::getCapacity)
.sum();

return Either.left(new DataValue<?>[] { DataType.NUMBER.makeValue((double) capacity) });
}
}
Loading

0 comments on commit 5003769

Please sign in to comment.