11package 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 ;
64import mekanism .api .MekanismAPI ;
75import mekanism .api .annotations .NothingNullByDefault ;
86import mekanism .api .gear .ModuleData ;
9- import mekanism .api .gear .config .ModuleBooleanConfig ;
10- import mekanism .api .gear .config .ModuleColorConfig ;
117import mekanism .api .gear .config .ModuleConfig ;
12- import mekanism .api .gear .config .ModuleEnumConfig ;
138import mekanism .common .Mekanism ;
149import mekanism .common .content .gear .Module ;
1510import mekanism .common .content .gear .ModuleContainer ;
1914import net .minecraft .network .codec .ByteBufCodecs ;
2015import net .minecraft .network .codec .StreamCodec ;
2116import net .minecraft .network .protocol .common .custom .CustomPacketPayload ;
22- import net .minecraft .util .ByIdMap ;
2317import net .minecraft .world .item .ItemStack ;
2418import net .neoforged .neoforge .network .handling .IPayloadContext ;
2519import 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