Skip to content

Commit cb28bf4

Browse files
committed
Split client and server configs (unfinished)
1 parent 731981f commit cb28bf4

File tree

8 files changed

+280
-21
lines changed

8 files changed

+280
-21
lines changed

build.gradle

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@ dependencies {
5050
[
5151
"fabric-api-base",
5252
"fabric-registry-sync-v0",
53-
"fabric-lifecycle-events-v1"
53+
"fabric-lifecycle-events-v1",
54+
"fabric-networking-api-v1"
5455
].forEach { modImplementation fabricApi.module(it, project.fabric_api_version) }
5556

5657
modCompileOnly "io.github.fourmisain:TaxFreeLevels-fabric:$project.tax_free_levels_version"

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,5 @@ org.gradle.jvmargs=-Xmx1G
1414

1515
# Dependencies
1616
fabric_api_version=0.110.0+1.21.4
17-
codec_config_api_version=2.1.0+1.21.3
17+
codec_config_api_version=3.0.0+1.21.3
1818
tax_free_levels_version=1.4.1-fabric-1.21.1

src/main/java/de/mschae23/grindenchantments/GrindEnchantmentsMod.java

Lines changed: 95 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,28 @@
2525
import java.nio.file.Path;
2626
import java.nio.file.Paths;
2727
import java.util.Optional;
28+
import net.minecraft.registry.RegistryOps;
29+
import net.minecraft.registry.RegistryWrapper;
2830
import net.minecraft.util.Identifier;
31+
import net.fabricmc.api.EnvType;
32+
import net.fabricmc.api.Environment;
2933
import net.fabricmc.api.ModInitializer;
34+
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents;
35+
import net.fabricmc.fabric.api.client.networking.v1.ClientConfigurationConnectionEvents;
36+
import net.fabricmc.fabric.api.client.networking.v1.ClientConfigurationNetworking;
37+
import net.fabricmc.fabric.api.client.networking.v1.ClientLoginConnectionEvents;
38+
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
39+
import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry;
3040
import net.fabricmc.loader.api.FabricLoader;
41+
import com.google.gson.JsonElement;
3142
import com.mojang.serialization.Codec;
43+
import com.mojang.serialization.DynamicOps;
3244
import com.mojang.serialization.JsonOps;
33-
import com.mojang.serialization.MapCodec;
45+
import de.mschae23.config.api.ConfigIo;
3446
import de.mschae23.config.api.ModConfig;
3547
import de.mschae23.config.api.exception.ConfigException;
36-
import de.mschae23.config.impl.ConfigUtil;
48+
import de.mschae23.grindenchantments.config.ClientConfig;
49+
import de.mschae23.grindenchantments.config.ServerConfig;
3750
import de.mschae23.grindenchantments.config.legacy.v1.GrindEnchantmentsConfigV1;
3851
import de.mschae23.grindenchantments.config.legacy.v2.GrindEnchantmentsConfigV2;
3952
import de.mschae23.grindenchantments.config.legacy.v3.GrindEnchantmentsConfigV3;
@@ -43,6 +56,7 @@
4356
import de.mschae23.grindenchantments.impl.DisenchantOperation;
4457
import de.mschae23.grindenchantments.impl.MoveOperation;
4558
import de.mschae23.grindenchantments.impl.ResetRepairCostOperation;
59+
import de.mschae23.grindenchantments.network.s2c.ServerConfigS2CPayload;
4660
import de.mschae23.grindenchantments.registry.GrindEnchantmentsRegistries;
4761
import io.github.fourmisain.taxfreelevels.TaxFreeLevels;
4862
import org.apache.logging.log4j.Level;
@@ -55,9 +69,32 @@ public class GrindEnchantmentsMod implements ModInitializer {
5569
public static final Logger LOGGER = LogManager.getLogger("Grind Enchantments");
5670

5771
private static GrindEnchantmentsConfigV3 LEGACY_CONFIG = GrindEnchantmentsConfigV3.DEFAULT;
72+
@Nullable
73+
private static ServerConfig SERVER_CONFIG = null;
74+
@Nullable
75+
private static ClientConfig CLIENT_CONFIG = null;
5876

5977
@Override
6078
public void onInitialize() {
79+
// Singleplayer
80+
ServerLifecycleEvents.SERVER_STARTING.register(server -> readServerConfig(server.getRegistryManager())
81+
.ifPresent(config -> SERVER_CONFIG = config));
82+
ServerLifecycleEvents.SERVER_STOPPING.register(server -> SERVER_CONFIG = null);
83+
84+
// Multiplayer
85+
PayloadTypeRegistry.configurationS2C().register(ServerConfigS2CPayload.ID, ServerConfigS2CPayload.CODEC);
86+
87+
ClientLifecycleEvents.CLIENT_STARTED.register(client -> {
88+
CLIENT_CONFIG = GrindEnchantmentsMod.readClientConfig().orElse(ClientConfig.DEFAULT);
89+
90+
ClientConfigurationNetworking.registerGlobalReceiver(ServerConfigS2CPayload.ID, (payload, context) -> {
91+
//noinspection resource
92+
context.client().execute(() -> {
93+
// TODO
94+
});
95+
});
96+
});
97+
6198
LEGACY_CONFIG = readLegacyConfig().orElse(GrindEnchantmentsConfigV3.DEFAULT);
6299

63100
GrindEnchantmentsRegistries.init();
@@ -85,29 +122,74 @@ public void onInitialize() {
85122
}
86123
}
87124

88-
private static <T extends ModConfig<T>> ModConfig.Type<T, ?> getConfigType(int versionOffset, MapCodec<? extends ModConfig<T>>[] codecs, int version) {
89-
for (int i = codecs.length; i > 0; i--) {
90-
if (version == i) {
91-
return new ModConfig.Type<>(i + versionOffset, codecs[i - 1]);
125+
public static ServerConfig getServerConfig() {
126+
return SERVER_CONFIG == null ? ServerConfig.DEFAULT : SERVER_CONFIG;
127+
}
128+
129+
public static ClientConfig getClientConfig() {
130+
return CLIENT_CONFIG == null ? ClientConfig.DEFAULT : CLIENT_CONFIG;
131+
}
132+
133+
@Deprecated
134+
public static GrindEnchantmentsConfigV3 getLegacyConfig() {
135+
return LEGACY_CONFIG;
136+
}
137+
138+
private static <C extends ModConfig<C>> ModConfig.Type<C, ? extends ModConfig<C>> getConfigType(ModConfig.Type<C, ? extends ModConfig<C>>[] versions, int version) {
139+
for (int i = versions.length - 1; i >= 0; i--) {
140+
ModConfig.Type<C, ? extends ModConfig<C>> v = versions[i];
141+
142+
if (version == v.version()) {
143+
return v;
144+
}
145+
}
146+
147+
return versions[versions.length - 1];
148+
}
149+
150+
private static <C extends ModConfig<C>> Optional<C> readGenericConfig(Path configName, Codec<ModConfig<C>> codec,
151+
DynamicOps<JsonElement> ops, String kind) {
152+
Path filePath = FabricLoader.getInstance().getConfigDir().resolve(MODID).resolve(configName);
153+
@Nullable
154+
C config = null;
155+
156+
if (Files.exists(filePath) && Files.isRegularFile(filePath)) {
157+
try (InputStream input = Files.newInputStream(filePath)) {
158+
log(Level.INFO, "Reading " + kind + " config.");
159+
160+
ModConfig<C> readConfig = ConfigIo.decodeConfig(input, codec, ops);
161+
config = readConfig.latest();
162+
} catch (IOException e) {
163+
log(Level.ERROR, "IO exception while trying to read " + kind + " config: " + e.getLocalizedMessage());
164+
} catch (ConfigException e) {
165+
log(Level.ERROR, e.getLocalizedMessage());
92166
}
93167
}
94168

95-
return new ModConfig.Type<>(codecs.length + versionOffset, codecs[codecs.length - 1]);
169+
return Optional.ofNullable(config);
170+
}
171+
172+
public static Optional<ClientConfig> readClientConfig() {
173+
return readGenericConfig(Path.of("client.json"), ModConfig.<ClientConfig>createCodec(ClientConfig.TYPE.version(), version ->
174+
getConfigType(ClientConfig.VERSIONS, version)), JsonOps.INSTANCE, "client");
175+
}
176+
177+
private static Optional<ServerConfig> readServerConfig(RegistryWrapper.WrapperLookup wrapperLookup) {
178+
return readGenericConfig(Path.of("server.json"), ModConfig.<ServerConfig>createCodec(ServerConfig.TYPE.version(), version ->
179+
getConfigType(ServerConfig.VERSIONS, version)), RegistryOps.of(JsonOps.INSTANCE, wrapperLookup), "server");
96180
}
97181

98182
@SuppressWarnings("deprecation")
99183
private static Optional<GrindEnchantmentsConfigV3> readLegacyConfig() {
100184
final GrindEnchantmentsConfigV3 legacyLatestConfigDefault = GrindEnchantmentsConfigV3.DEFAULT;
101185
final int legacyLatestConfigVersion = legacyLatestConfigDefault.version();
102186
@SuppressWarnings({"unchecked", "deprecation"})
103-
final MapCodec<? extends ModConfig<GrindEnchantmentsConfigV3>>[] legacyConfigCodecs = new MapCodec[] {
104-
GrindEnchantmentsConfigV1.TYPE_CODEC, GrindEnchantmentsConfigV2.TYPE_CODEC, GrindEnchantmentsConfigV3.TYPE_CODEC
187+
final ModConfig.Type<GrindEnchantmentsConfigV3, ? extends ModConfig<GrindEnchantmentsConfigV3>>[] legacyConfigCodecs = new ModConfig.Type[] {
188+
GrindEnchantmentsConfigV1.TYPE, GrindEnchantmentsConfigV2.TYPE, GrindEnchantmentsConfigV3.TYPE
105189
};
106190

107191
final Codec<ModConfig<GrindEnchantmentsConfigV3>> legacyConfigCodec = ModConfig.createCodec(legacyLatestConfigVersion, version ->
108-
getConfigType(0, legacyConfigCodecs, version));
109-
110-
// Unfortunately, this requires some manual work and usage of codec config API's internals
192+
getConfigType(legacyConfigCodecs, version));
111193

112194
Path configPath = FabricLoader.getInstance().getConfigDir().resolve(Paths.get(MODID + ".json"));
113195
@Nullable
@@ -117,8 +199,7 @@ private static Optional<GrindEnchantmentsConfigV3> readLegacyConfig() {
117199
try (InputStream input = Files.newInputStream(configPath)) {
118200
log(Level.INFO, "Reading legacy config.");
119201

120-
@SuppressWarnings("UnstableApiUsage")
121-
ModConfig<GrindEnchantmentsConfigV3> readConfig = ConfigUtil.decodeConfig(input, legacyConfigCodec, JsonOps.INSTANCE);
202+
ModConfig<GrindEnchantmentsConfigV3> readConfig = ConfigIo.decodeConfig(input, legacyConfigCodec, JsonOps.INSTANCE);
122203
config = readConfig.latest();
123204
} catch (IOException e) {
124205
log(Level.ERROR, "IO exception while trying to read config: " + e.getLocalizedMessage());
@@ -130,10 +211,6 @@ private static Optional<GrindEnchantmentsConfigV3> readLegacyConfig() {
130211
return Optional.ofNullable(config);
131212
}
132213

133-
public static GrindEnchantmentsConfigV3 getConfig() {
134-
return LEGACY_CONFIG;
135-
}
136-
137214
public static void log(Level level, Object message) {
138215
LOGGER.log(level, "[Grind Enchantments] {}", message);
139216
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Copyright (C) 2024 mschae23
3+
*
4+
* This file is part of Grind enchantments.
5+
*
6+
* Grind enchantments is free software: you can redistribute it and/or modify
7+
* it under the terms of the GNU Lesser General Public License as published by
8+
* the Free Software Foundation, either version 3 of the License, or
9+
* (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU Lesser General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Lesser General Public License
17+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
18+
*/
19+
20+
package de.mschae23.grindenchantments.config;
21+
22+
import com.mojang.serialization.Codec;
23+
import com.mojang.serialization.MapCodec;
24+
import com.mojang.serialization.codecs.RecordCodecBuilder;
25+
import de.mschae23.config.api.ModConfig;
26+
27+
public record ClientConfig(boolean showLevelCost) implements ModConfig<ClientConfig> {
28+
public static final MapCodec<ClientConfig> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
29+
Codec.BOOL.fieldOf("show_enchantment_cost").forGetter(ClientConfig::showLevelCost)
30+
).apply(instance, instance.stable(ClientConfig::new)));
31+
32+
public static final ModConfig.Type<ClientConfig, ClientConfig> TYPE = new ModConfig.Type<>(4, CODEC);
33+
public static final ClientConfig DEFAULT = new ClientConfig(true);
34+
35+
@SuppressWarnings("unchecked")
36+
public static final ModConfig.Type<ClientConfig, ? extends ModConfig<ClientConfig>>[] VERSIONS = new ModConfig.Type[] { TYPE, };
37+
38+
@Override
39+
public Type<ClientConfig, ?> type() {
40+
return TYPE;
41+
}
42+
43+
@Override
44+
public ClientConfig latest() {
45+
return this;
46+
}
47+
48+
@Override
49+
public boolean shouldUpdate() {
50+
return true;
51+
}
52+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* Copyright (C) 2024 mschae23
3+
*
4+
* This file is part of Grind enchantments.
5+
*
6+
* Grind enchantments is free software: you can redistribute it and/or modify
7+
* it under the terms of the GNU Lesser General Public License as published by
8+
* the Free Software Foundation, either version 3 of the License, or
9+
* (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU Lesser General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Lesser General Public License
17+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
18+
*/
19+
20+
package de.mschae23.grindenchantments.config;
21+
22+
import com.mojang.serialization.Codec;
23+
import com.mojang.serialization.codecs.RecordCodecBuilder;
24+
25+
public record DedicatedServerConfig(boolean alternativeCostDisplay) {
26+
public static final Codec<DedicatedServerConfig> CODEC = RecordCodecBuilder.create(instance -> instance.group(
27+
Codec.BOOL.fieldOf("alternative_cost_display_enabled").forGetter(DedicatedServerConfig::alternativeCostDisplay)
28+
).apply(instance, instance.stable(DedicatedServerConfig::new)));
29+
30+
public static final DedicatedServerConfig DEFAULT = new DedicatedServerConfig(false);
31+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
* Copyright (C) 2024 mschae23
3+
*
4+
* This file is part of Grind enchantments.
5+
*
6+
* Grind enchantments is free software: you can redistribute it and/or modify
7+
* it under the terms of the GNU Lesser General Public License as published by
8+
* the Free Software Foundation, either version 3 of the License, or
9+
* (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU Lesser General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Lesser General Public License
17+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
18+
*/
19+
20+
package de.mschae23.grindenchantments.config;
21+
22+
import com.mojang.serialization.MapCodec;
23+
import com.mojang.serialization.codecs.RecordCodecBuilder;
24+
import de.mschae23.config.api.ModConfig;
25+
26+
public record ServerConfig(DisenchantConfig disenchant, MoveConfig move, ResetRepairCostConfig resetRepairCost,
27+
FilterConfig filter,
28+
DedicatedServerConfig dedicatedServerConfig) implements ModConfig<ServerConfig> {
29+
public static final MapCodec<ServerConfig> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
30+
DisenchantConfig.CODEC.fieldOf("disenchant_to_book").forGetter(ServerConfig::disenchant),
31+
MoveConfig.CODEC.fieldOf("move_enchantments").forGetter(ServerConfig::move),
32+
ResetRepairCostConfig.CODEC.fieldOf("reset_repair_cost").forGetter(ServerConfig::resetRepairCost),
33+
FilterConfig.CODEC.fieldOf("filter").forGetter(ServerConfig::filter),
34+
DedicatedServerConfig.CODEC.orElse(DedicatedServerConfig.DEFAULT).fieldOf("dedicated_server_options").forGetter(ServerConfig::dedicatedServerConfig)
35+
).apply(instance, instance.stable(ServerConfig::new)));
36+
37+
public static final ModConfig.Type<ServerConfig, ServerConfig> TYPE = new ModConfig.Type<>(4, CODEC);
38+
public static final ServerConfig DEFAULT = new ServerConfig(DisenchantConfig.DEFAULT, MoveConfig.DEFAULT,
39+
ResetRepairCostConfig.DEFAULT, FilterConfig.DEFAULT, DedicatedServerConfig.DEFAULT);
40+
41+
@SuppressWarnings("unchecked")
42+
public static final ModConfig.Type<ServerConfig, ? extends ModConfig<ServerConfig>>[] VERSIONS = new ModConfig.Type[] { TYPE, };
43+
44+
@Override
45+
public Type<ServerConfig, ?> type() {
46+
return TYPE;
47+
}
48+
49+
@Override
50+
public ServerConfig latest() {
51+
return this;
52+
}
53+
54+
@Override
55+
public boolean shouldUpdate() {
56+
return true;
57+
}
58+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* Copyright (C) 2024 mschae23
3+
*
4+
* This file is part of Grind enchantments.
5+
*
6+
* Grind enchantments is free software: you can redistribute it and/or modify
7+
* it under the terms of the GNU Lesser General Public License as published by
8+
* the Free Software Foundation, either version 3 of the License, or
9+
* (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU Lesser General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Lesser General Public License
17+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
18+
*/
19+
20+
package de.mschae23.grindenchantments.network.s2c;
21+
22+
import net.minecraft.network.PacketByteBuf;
23+
import net.minecraft.network.codec.PacketCodec;
24+
import net.minecraft.network.packet.CustomPayload;
25+
import net.minecraft.util.Identifier;
26+
import de.mschae23.grindenchantments.GrindEnchantmentsMod;
27+
28+
public record ServerConfigS2CPayload() implements CustomPayload {
29+
public static final Identifier PACKET_ID = GrindEnchantmentsMod.id("server_config");
30+
public static final CustomPayload.Id<ServerConfigS2CPayload> ID = new CustomPayload.Id<>(PACKET_ID);
31+
32+
public static final PacketCodec<PacketByteBuf, ServerConfigS2CPayload> CODEC = PacketCodec.unit(new ServerConfigS2CPayload());
33+
34+
@Override
35+
public Id<? extends CustomPayload> getId() {
36+
return ID;
37+
}
38+
}

src/main/resources/fabric.mod.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@
3434
"java": ">=21",
3535

3636
"fabric-api-base": "*",
37-
"fabric-registry-sync-v0": "*"
37+
"fabric-registry-sync-v0": "*",
38+
"fabric-lifecycle-events-v1": "*",
39+
"fabric-networking-api-v1": "*"
3840
},
3941
"suggests": {
4042
},

0 commit comments

Comments
 (0)