Skip to content

Commit e03d8d3

Browse files
committed
Give update module setting sync control to the config elements themselves
1 parent 34f4f09 commit e03d8d3

File tree

8 files changed

+77
-85
lines changed

8 files changed

+77
-85
lines changed

src/api/java/mekanism/api/gear/ModuleData.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,18 @@ public void encode(RegistryFriendlyByteBuf buffer, List<ModuleConfig<?>> configs
172172
};
173173
}
174174

175+
//TODO - 1.20.5: Docs
176+
@Nullable
177+
public final ModuleConfig<?> getNamedConfig(int installed, String name) {
178+
ConfigData data = this.configData.get(installed);
179+
for (ModuleConfig<?> config : data.configs()) {
180+
if (config.name().equals(name)) {
181+
return config;
182+
}
183+
}
184+
return null;
185+
}
186+
175187
//TODO - 1.20.5: Docs
176188
public final List<ModuleConfig<?>> defaultConfigs(int installed) {
177189
return this.configData.get(installed).configs();

src/api/java/mekanism/api/gear/config/ModuleBooleanConfig.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ public ModuleBooleanConfig(String name, boolean value) {
2929
this.value = value;
3030
}
3131

32+
@Override
33+
public StreamCodec<ByteBuf, ModuleConfig<Boolean>> namedStreamCodec(String name) {
34+
return ByteBufCodecs.BOOL.map(val -> new ModuleBooleanConfig(name, val), ModuleConfig::get);
35+
}
36+
3237
@Override
3338
public Boolean get() {
3439
return value;

src/api/java/mekanism/api/gear/config/ModuleColorConfig.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,16 @@ public boolean supportsAlpha() {
8888
return supportsAlpha;
8989
}
9090

91+
@Override
92+
public StreamCodec<ByteBuf, ModuleConfig<Integer>> namedStreamCodec(String name) {
93+
if (supportsAlpha) {
94+
//Note: We don't do varint as we include alpha data
95+
return ByteBufCodecs.INT.map(val -> ModuleColorConfig.argb(name, val), ModuleConfig::get);
96+
}
97+
//Note: We can use var int here and just not send the alpha data over the network
98+
return ByteBufCodecs.VAR_INT.map(val -> ModuleColorConfig.rgb(name, val), module -> module.get() & 0x00FFFFFF);
99+
}
100+
91101
@Override
92102
public Integer get() {
93103
return value;

src/api/java/mekanism/api/gear/config/ModuleConfig.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
import java.util.Objects;
77
import mekanism.api.NBTConstants;
88
import mekanism.api.annotations.NothingNullByDefault;
9+
import net.minecraft.network.RegistryFriendlyByteBuf;
10+
import net.minecraft.network.codec.StreamCodec;
911
import net.minecraft.util.ExtraCodecs;
1012

1113
//TODO - 1.20.5: Docs
@@ -35,6 +37,8 @@ public final String name() {
3537
return name;
3638
}
3739

40+
public abstract StreamCodec<? super RegistryFriendlyByteBuf, ModuleConfig<DATA>> namedStreamCodec(String name);
41+
3842
public abstract DATA get();
3943

4044
public abstract ModuleConfig<DATA> with(DATA value);

src/api/java/mekanism/api/gear/config/ModuleEnumConfig.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@
99
import mekanism.api.NBTConstants;
1010
import mekanism.api.annotations.NothingNullByDefault;
1111
import mekanism.api.text.IHasTextComponent;
12+
import net.minecraft.network.FriendlyByteBuf;
1213
import net.minecraft.network.codec.ByteBufCodecs;
1314
import net.minecraft.network.codec.StreamCodec;
15+
import net.neoforged.neoforge.network.codec.NeoForgeStreamCodecs;
1416

1517
//TODO - 1.20.5: Docs
1618
@NothingNullByDefault
@@ -99,6 +101,14 @@ private ModuleEnumConfig(String name, TYPE value, List<TYPE> enumConstants) {
99101
this.enumConstants = enumConstants;
100102
}
101103

104+
@Override
105+
public StreamCodec<FriendlyByteBuf, ModuleConfig<TYPE>> namedStreamCodec(String name) {
106+
return NeoForgeStreamCodecs.enumCodec(value.getDeclaringClass()).map(
107+
value -> new ModuleEnumConfig<>(name, value, enumConstants),
108+
ModuleConfig::get
109+
);
110+
}
111+
102112
@Override
103113
public TYPE get() {
104114
return value;

src/main/java/mekanism/client/gui/GuiModuleTweaker.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ public GuiModuleTweaker(ModuleTweakerContainer container, Inventory inv, Compone
5757
IModule<?> module = moduleScreen.getCurrentModule();
5858
if (module != null && selected != -1) {//Shouldn't be null but validate just in case
5959
int slotIndex = menu.slots.get(selected).getSlotIndex();
60-
PacketUtils.sendToServer(PacketUpdateModuleSettings.create(slotIndex, module.getData(), configItem));
60+
PacketUtils.sendToServer(PacketUpdateModuleSettings.create(slotIndex, module.getData(), module.getInstalledCount(), configItem));
6161
}
6262
}
6363
};

src/main/java/mekanism/common/content/gear/mekatool/ModuleVeinMiningUnit.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,11 @@ public ModuleExtendedModeConfig(String name, boolean value) {
264264
super(name, value);
265265
}
266266

267+
@Override
268+
public StreamCodec<ByteBuf, ModuleConfig<Boolean>> namedStreamCodec(String name) {
269+
return ByteBufCodecs.BOOL.map(val -> new ModuleExtendedModeConfig(name, val), ModuleConfig::get);
270+
}
271+
267272
@Override
268273
public ModuleBooleanConfig with(Boolean value) {
269274
Objects.requireNonNull(value, "Value cannot be null.");
Lines changed: 30 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,10 @@
11
package mekanism.common.network.to_server;
22

3-
import io.netty.buffer.ByteBuf;
4-
import java.util.function.IntFunction;
5-
import java.util.function.Predicate;
3+
import io.netty.handler.codec.DecoderException;
64
import mekanism.api.MekanismAPI;
75
import mekanism.api.annotations.NothingNullByDefault;
86
import mekanism.api.gear.ModuleData;
9-
import mekanism.api.gear.config.ModuleBooleanConfig;
10-
import mekanism.api.gear.config.ModuleColorConfig;
117
import mekanism.api.gear.config.ModuleConfig;
12-
import mekanism.api.gear.config.ModuleEnumConfig;
138
import mekanism.common.Mekanism;
149
import mekanism.common.content.gear.Module;
1510
import mekanism.common.content.gear.ModuleContainer;
@@ -19,40 +14,24 @@
1914
import net.minecraft.network.codec.ByteBufCodecs;
2015
import net.minecraft.network.codec.StreamCodec;
2116
import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
22-
import net.minecraft.util.ByIdMap;
2317
import net.minecraft.world.item.ItemStack;
2418
import net.neoforged.neoforge.network.handling.IPayloadContext;
2519
import org.jetbrains.annotations.NotNull;
26-
import org.jetbrains.annotations.Nullable;
2720

2821
//TODO: Eventually it would be nice to make this more generic in terms of how it can sync module data so that we can support custom types
2922
// though given the module tweaker screen doesn't currently have a way to support custom types it isn't that big a deal to make this support it yet either
3023
@NothingNullByDefault
31-
public record PacketUpdateModuleSettings(int slotId, ModuleData<?> moduleType, String data, TypedValue value) implements IMekanismPacket {
24+
public record PacketUpdateModuleSettings(int slotId, ModuleConfigTarget<?> target) implements IMekanismPacket {
3225

3326
public static final CustomPacketPayload.Type<PacketUpdateModuleSettings> TYPE = new CustomPacketPayload.Type<>(Mekanism.rl("update_module"));
3427
public static final StreamCodec<RegistryFriendlyByteBuf, PacketUpdateModuleSettings> STREAM_CODEC = StreamCodec.composite(
3528
ByteBufCodecs.VAR_INT, PacketUpdateModuleSettings::slotId,
36-
ByteBufCodecs.registry(MekanismAPI.MODULE_REGISTRY_NAME), PacketUpdateModuleSettings::moduleType,
37-
ByteBufCodecs.STRING_UTF8, PacketUpdateModuleSettings::data,
38-
TypedValue.STREAM_CODEC, PacketUpdateModuleSettings::value,
29+
ModuleConfigTarget.STREAM_CODEC, PacketUpdateModuleSettings::target,
3930
PacketUpdateModuleSettings::new
4031
);
4132

42-
private PacketUpdateModuleSettings(int slotId, ModuleData<?> moduleType, String data, ModuleDataType dataType, Object value) {
43-
this(slotId, moduleType, data, new TypedValue(dataType, value));
44-
}
45-
46-
public static PacketUpdateModuleSettings create(int slotId, ModuleData<?> moduleType, ModuleConfig<?> config) {
47-
if (config instanceof ModuleEnumConfig<?> enumData) {
48-
return new PacketUpdateModuleSettings(slotId, moduleType, config.name(), ModuleDataType.ENUM, enumData.get().ordinal());
49-
}
50-
for (ModuleDataType type : ModuleDataType.VALUES) {
51-
if (type.typeMatches(config)) {
52-
return new PacketUpdateModuleSettings(slotId, moduleType, config.name(), type, config.get());
53-
}
54-
}
55-
throw new IllegalArgumentException("Unknown config data type for config with name: " + config.name());
33+
public static PacketUpdateModuleSettings create(int slotId, ModuleData<?> moduleType, int installed, ModuleConfig<?> config) {
34+
return new PacketUpdateModuleSettings(slotId, new ModuleConfigTarget<>(moduleType, installed, config));
5635
}
5736

5837
@NotNull
@@ -63,72 +42,39 @@ public CustomPacketPayload.Type<PacketUpdateModuleSettings> type() {
6342

6443
@Override
6544
public void handle(IPayloadContext context) {
66-
if (!data.isBlank()) {
67-
ItemStack stack = context.player().getInventory().getItem(slotId);
68-
ModuleContainer container = ModuleHelper.get().getModuleContainer(stack);
69-
if (container != null) {
70-
Module<?> module = container.get(moduleType);
71-
if (module != null) {
72-
ModuleConfig<?> config = updateConfig(module.getConfig(data));
73-
if (config != null) {
74-
container.replaceModuleConfig(stack, moduleType, config);
75-
}
76-
}
77-
}
78-
}
79-
}
80-
81-
@Nullable
82-
private <TYPE> ModuleConfig<?> updateConfig(@Nullable ModuleConfig<TYPE> configData) {
83-
if (configData != null) {
84-
try {
85-
if (configData instanceof ModuleEnumConfig<?> config && value.type() == ModuleDataType.ENUM) {
86-
return config.with((int) value.value());
87-
} else if (value.type().typeMatches(configData)) {
88-
//noinspection unchecked
89-
return configData.with((TYPE) value.value());
90-
}
91-
} catch (IllegalArgumentException ignored) {
92-
//Ideally we will never have this be thrown, but if for some reason we get bad data it might be, and then we want to ignore it
93-
//TODO - 1.20.5: Instead of just ignoring this maybe we should disconnect the client via the IPayloadContext?
45+
ItemStack stack = context.player().getInventory().getItem(slotId);
46+
ModuleContainer container = ModuleHelper.get().getModuleContainer(stack);
47+
if (container != null) {
48+
Module<?> module = container.get(target.moduleType());
49+
if (module != null) {
50+
//TODO - 1.20.5: Validate the config is at a valid level/in bounds for it, such as if it is a limited range enum value
51+
// maybe we want the server to do a config.with itself?
52+
container.replaceModuleConfig(stack, target.moduleType(), target.config());
9453
}
9554
}
96-
return null;
9755
}
9856

99-
private enum ModuleDataType {
100-
//TODO - 1.20.5: Can we make use of the module config stream codecs somehow?
101-
BOOLEAN(data -> data instanceof ModuleBooleanConfig, ByteBufCodecs.BOOL),
102-
//Must be above integer, so it uses the color type as ModuleColorData extends ModuleIntegerData
103-
COLOR(data -> data instanceof ModuleColorConfig, ByteBufCodecs.INT),
104-
ENUM(data -> data instanceof ModuleEnumConfig, ByteBufCodecs.VAR_INT);
57+
public record ModuleConfigTarget<C>(ModuleData<?> moduleType, int installed, ModuleConfig<C> config) {
10558

106-
public static final IntFunction<ModuleDataType> BY_ID = ByIdMap.continuous(ModuleDataType::ordinal, values(), ByIdMap.OutOfBoundsStrategy.WRAP);
107-
public static final StreamCodec<ByteBuf, ModuleDataType> STREAM_CODEC = ByteBufCodecs.idMapper(BY_ID, ModuleDataType::ordinal);
59+
private static final StreamCodec<RegistryFriendlyByteBuf, ModuleData<?>> REGISTRY_CODEC = ByteBufCodecs.registry(MekanismAPI.MODULE_REGISTRY_NAME);
60+
public static final StreamCodec<RegistryFriendlyByteBuf, ModuleConfigTarget<?>> STREAM_CODEC = StreamCodec.ofMember(ModuleConfigTarget::encode, ModuleConfigTarget::decode);
10861

109-
//DO NOT MODIFY
110-
private static final ModuleDataType[] VALUES = values();
111-
112-
private final Predicate<ModuleConfig<?>> configDataPredicate;
113-
private final StreamCodec<ByteBuf, Object> streamCodec;
114-
115-
ModuleDataType(Predicate<ModuleConfig<?>> configDataPredicate, StreamCodec<ByteBuf, ?> streamCodec) {
116-
this.configDataPredicate = configDataPredicate;
117-
this.streamCodec = (StreamCodec<ByteBuf, Object>) streamCodec;
118-
}
119-
120-
public boolean typeMatches(ModuleConfig<?> data) {
121-
return configDataPredicate.test(data);
62+
private static ModuleConfigTarget<?> decode(RegistryFriendlyByteBuf buffer) {
63+
ModuleData<?> moduleType = REGISTRY_CODEC.decode(buffer);
64+
int installed = buffer.readVarInt();
65+
String name = buffer.readUtf();
66+
ModuleConfig<?> defaultConfig = moduleType.getNamedConfig(installed, name);
67+
if (defaultConfig == null) {
68+
throw new DecoderException("Unknown config " + name + " for module type: " + moduleType + " with " + installed + " modules installed");
69+
}
70+
return new ModuleConfigTarget<>(moduleType, installed, defaultConfig.namedStreamCodec(name).decode(buffer));
12271
}
12372

124-
public StreamCodec<ByteBuf, Object> streamCodec() {
125-
return streamCodec;
73+
private void encode(RegistryFriendlyByteBuf buffer) {
74+
REGISTRY_CODEC.encode(buffer, moduleType);
75+
buffer.writeVarInt(installed);
76+
buffer.writeUtf(config.name());
77+
config.namedStreamCodec(config.name()).encode(buffer, config);
12678
}
12779
}
128-
129-
private record TypedValue(ModuleDataType type, Object value) {
130-
131-
private static final StreamCodec<ByteBuf, TypedValue> STREAM_CODEC = ModuleDataType.STREAM_CODEC.dispatch(TypedValue::type,
132-
type -> type.streamCodec().map(value -> new TypedValue(type, value), TypedValue::value));
133-
}
13480
}

0 commit comments

Comments
 (0)