Skip to content

Commit 9bbfef8

Browse files
committed
feat: Add loading of rules on clients
1 parent e0115b9 commit 9bbfef8

9 files changed

Lines changed: 173 additions & 44 deletions

File tree

api/src/main/java/net/blay09/mods/shogi/scope/ShogiScope.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,27 @@ default void registerEffect(Identifier id, MapCodec<? extends ShogiEffect<?>> ef
121121
*/
122122
void setDefaultNamespaces(List<String> namespaces);
123123

124+
/**
125+
* Marks this scope to load rules on the client as well.
126+
*
127+
* @return this scope
128+
*/
129+
ShogiScope loadOnClient();
130+
131+
/**
132+
* Returns whether this scope loads rules on clients.
133+
*
134+
* @return true if this scope is loaded on clients
135+
*/
136+
boolean isLoadedOnClient();
137+
138+
/**
139+
* Returns whether this scope loads rules on servers.
140+
*
141+
* @return true if this scope is loaded on servers
142+
*/
143+
boolean isLoadedOnServer();
144+
124145
/**
125146
* Creates an integer value backed by this scope.
126147
*
@@ -234,4 +255,5 @@ default <TContext> ShogiValue<TContext, Component> componentValue(Identifier ide
234255
* @return network cache implementation
235256
*/
236257
ShogiNetworkCache getNetworkCache();
258+
237259
}

api/src/main/java/net/blay09/mods/shogi/scope/internal/ShogiScopeImpl.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
public class ShogiScopeImpl implements ShogiScope {
2020
private final Identifier identifier;
2121
private List<String> defaultNamespaces;
22+
private boolean loadedOnClient;
2223

2324
public ShogiScopeImpl(Identifier identifier) {
2425
this.identifier = identifier;
@@ -117,6 +118,22 @@ public void setDefaultNamespaces(List<String> namespaces) {
117118
defaultNamespaces = List.copyOf(deduplicated);
118119
}
119120

121+
@Override
122+
public ShogiScope loadOnClient() {
123+
loadedOnClient = true;
124+
return this;
125+
}
126+
127+
@Override
128+
public boolean isLoadedOnClient() {
129+
return loadedOnClient;
130+
}
131+
132+
@Override
133+
public boolean isLoadedOnServer() {
134+
return true;
135+
}
136+
120137
@Override
121138
public <TContext, TSuccess> Either<?, ?> resolve(Identifier identifier, TContext context, Function<TContext, Either<TSuccess, ?>> defaultProvider) {
122139
final var normalizedContext = MutableShogiContext.of(context);
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package net.blay09.mods.shogi.common;
2+
3+
import net.blay09.mods.shogi.common.scope.ShogiRuleRepositories;
4+
import net.blay09.mods.shogi.common.scope.ShogiRuleRepository;
5+
import net.blay09.mods.shogi.effect.ShogiEffect;
6+
import net.blay09.mods.shogi.internal.ShogiScopeRegistry;
7+
import net.blay09.mods.shogi.scope.ShogiScope;
8+
import net.minecraft.core.HolderLookup;
9+
import net.minecraft.resources.Identifier;
10+
import net.minecraft.server.packs.resources.ResourceManager;
11+
import net.minecraft.server.packs.resources.SimplePreparableReloadListener;
12+
import net.minecraft.util.profiling.ProfilerFiller;
13+
import org.jspecify.annotations.Nullable;
14+
15+
import java.nio.file.Path;
16+
import java.util.ArrayList;
17+
import java.util.List;
18+
import java.util.Map;
19+
import java.util.function.Predicate;
20+
import java.util.function.Supplier;
21+
22+
abstract class AbstractShogiRuleReloadListener extends SimplePreparableReloadListener<List<AbstractShogiRuleReloadListener.ScopeRules>> {
23+
24+
private final Supplier<HolderLookup.@Nullable Provider> registriesSupplier;
25+
private final Path configDirectory;
26+
private final Predicate<ShogiScope> scopeFilter;
27+
28+
protected AbstractShogiRuleReloadListener(Supplier<HolderLookup.@Nullable Provider> registriesSupplier, Path configDirectory, Predicate<ShogiScope> scopeFilter) {
29+
this.registriesSupplier = registriesSupplier;
30+
this.configDirectory = configDirectory;
31+
this.scopeFilter = scopeFilter;
32+
}
33+
34+
@Override
35+
protected List<ScopeRules> prepare(ResourceManager resourceManager, ProfilerFiller profiler) {
36+
final var registries = registriesSupplier.get();
37+
if (registries == null) {
38+
return List.of();
39+
}
40+
41+
final List<ScopeRules> loadedRules = new ArrayList<>();
42+
for (final var scope : ShogiScopeRegistry.getAll()) {
43+
if (!scopeFilter.test(scope)) {
44+
continue;
45+
}
46+
47+
final var repository = ShogiRuleRepositories.get(scope).orElse(null);
48+
if (repository == null) {
49+
continue;
50+
}
51+
52+
final var configRules = ShogiRuleLoader.loadConfigRules(registries, scope, configDirectory);
53+
final var datapackRules = ShogiRuleLoader.loadDatapackRules(registries, scope, resourceManager);
54+
loadedRules.add(new ScopeRules(repository, configRules, datapackRules));
55+
}
56+
return loadedRules;
57+
}
58+
59+
@Override
60+
protected void apply(List<ScopeRules> loadedRules, ResourceManager resourceManager, ProfilerFiller profiler) {
61+
loadedRules.forEach(it -> it.repository().apply(it.configRules(), it.datapackRules()));
62+
}
63+
64+
protected record ScopeRules(ShogiRuleRepository repository, Map<Identifier, ShogiEffect<?>> configRules, Map<Identifier, ShogiEffect<?>> datapackRules) {
65+
}
66+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package net.blay09.mods.shogi.common;
2+
3+
import net.blay09.mods.shogi.scope.ShogiScope;
4+
import net.minecraft.core.HolderLookup;
5+
import org.jspecify.annotations.Nullable;
6+
7+
import java.nio.file.Path;
8+
import java.util.function.Supplier;
9+
10+
public class ShogiClientRuleReloadListener extends AbstractShogiRuleReloadListener {
11+
static boolean loadsScopeOnClient(ShogiScope scope) {
12+
return scope.isLoadedOnClient();
13+
}
14+
15+
public ShogiClientRuleReloadListener(Path configDirectory, Supplier<HolderLookup.@Nullable Provider> registriesSupplier) {
16+
super(registriesSupplier, configDirectory, ShogiClientRuleReloadListener::loadsScopeOnClient);
17+
}
18+
}

common/src/main/java/net/blay09/mods/shogi/common/ShogiRuleLoader.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ private static String datapackScopePrefix(ShogiScope scope) {
9090
return scopeIdentifier.getNamespace() + "/" + scopeIdentifier.getPath();
9191
}
9292

93-
private static Path configPath(Path configDirectory, ShogiScope scope) {
93+
static Path configPath(Path configDirectory, ShogiScope scope) {
9494
final var scopeIdentifier = scope.identifier();
9595
final var normalizedScopePath = scopeIdentifier.getPath().replace('/', '.');
9696
return configDirectory.resolve(scopeIdentifier.getNamespace() + "." + normalizedScopePath + ".json");
Lines changed: 6 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,15 @@
11
package net.blay09.mods.shogi.common;
22

3-
import net.blay09.mods.shogi.common.scope.ShogiRuleRepositories;
4-
import net.blay09.mods.shogi.common.scope.ShogiRuleRepository;
5-
import net.blay09.mods.shogi.effect.ShogiEffect;
6-
import net.blay09.mods.shogi.internal.ShogiScopeRegistry;
3+
import net.blay09.mods.shogi.scope.ShogiScope;
74
import net.minecraft.core.HolderLookup;
8-
import net.minecraft.resources.Identifier;
9-
import net.minecraft.server.packs.resources.ResourceManager;
10-
import net.minecraft.server.packs.resources.SimplePreparableReloadListener;
11-
import net.minecraft.util.profiling.ProfilerFiller;
12-
135
import java.nio.file.Path;
14-
import java.util.ArrayList;
15-
import java.util.List;
16-
import java.util.Map;
17-
18-
public class ShogiRuleReloadListener extends SimplePreparableReloadListener<List<ShogiRuleReloadListener.ScopeRules>> {
19-
20-
private final HolderLookup.Provider registries;
21-
private final Path configDirectory;
22-
23-
public ShogiRuleReloadListener(HolderLookup.Provider registries, Path configDirectory) {
24-
this.registries = registries;
25-
this.configDirectory = configDirectory;
26-
}
27-
28-
@Override
29-
protected List<ScopeRules> prepare(ResourceManager resourceManager, ProfilerFiller profiler) {
30-
final List<ScopeRules> loadedRules = new ArrayList<>();
31-
for (final var scope : ShogiScopeRegistry.getAll()) {
32-
final var repository = ShogiRuleRepositories.get(scope).orElse(null);
33-
if (repository == null) {
34-
continue;
35-
}
366

37-
final var configRules = ShogiRuleLoader.loadConfigRules(registries, scope, configDirectory);
38-
final var datapackRules = ShogiRuleLoader.loadDatapackRules(registries, scope, resourceManager);
39-
loadedRules.add(new ScopeRules(repository, configRules, datapackRules));
40-
}
41-
return loadedRules;
7+
public class ShogiRuleReloadListener extends AbstractShogiRuleReloadListener {
8+
static boolean loadsScopeOnServer(ShogiScope scope) {
9+
return !scope.isLoadedOnServer();
4210
}
4311

44-
@Override
45-
protected void apply(List<ScopeRules> loadedRules, ResourceManager resourceManager, ProfilerFiller profiler) {
46-
loadedRules.forEach(it -> it.repository().apply(it.configRules(), it.datapackRules()));
47-
}
48-
49-
protected record ScopeRules(ShogiRuleRepository repository, Map<Identifier, ShogiEffect<?>> configRules, Map<Identifier, ShogiEffect<?>> datapackRules) {
12+
public ShogiRuleReloadListener(HolderLookup.Provider registries, Path configDirectory) {
13+
super(() -> registries, configDirectory, ShogiRuleReloadListener::loadsScopeOnServer);
5014
}
5115
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,36 @@
11
package net.blay09.mods.shogi.fabric.client;
22

33
import net.blay09.mods.shogi.client.ShogiClient;
4+
import net.blay09.mods.shogi.common.ShogiClientRuleReloadListener;
5+
import net.blay09.mods.shogi.common.ShogiCommon;
46
import net.blay09.mods.shogi.common.network.ShogiValueResultPayload;
7+
import net.blay09.mods.shogi.common.platform.ShogiRuntimeSpi;
58
import net.blay09.mods.shogi.network.ShogiStreamCodecs;
69
import net.fabricmc.api.ClientModInitializer;
710
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents;
811
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
12+
import net.fabricmc.fabric.api.resource.v1.ResourceLoader;
13+
import net.minecraft.client.Minecraft;
14+
import net.minecraft.server.packs.PackType;
915

1016
public class FabricShogiClient implements ClientModInitializer {
1117
@Override
1218
public void onInitializeClient() {
1319
final var events = ShogiClient.initialize();
20+
final var runtime = ShogiRuntimeSpi.get();
1421
ClientPlayNetworking.registerGlobalReceiver(ShogiValueResultPayload.TYPE, (payload, context) -> context.client().schedule(() -> {
1522
if (!ShogiStreamCodecs.containsUnknown(payload.payload())) {
1623
events.onValueReceived(payload.scope(), payload.identifier(), payload.payload());
1724
}
1825
}));
1926

2027
ClientPlayConnectionEvents.DISCONNECT.register((_, _) -> events.onDisconnected());
28+
ResourceLoader.get(PackType.CLIENT_RESOURCES).registerReloadListener(
29+
ShogiCommon.id("client_rule_reloader"),
30+
new ShogiClientRuleReloadListener(runtime.getConfigDirectory(), () -> {
31+
final var connection = Minecraft.getInstance().getConnection();
32+
return connection != null ? connection.registryAccess() : null;
33+
})
34+
);
2135
}
2236
}

forge/src/main/java/net/blay09/mods/shogi/forge/client/ForgeShogiClient.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,13 @@
22

33
import net.blay09.mods.shogi.client.ShogiClient;
44
import net.blay09.mods.shogi.client.platform.ShogiClientEventListener;
5+
import net.blay09.mods.shogi.common.ShogiClientRuleReloadListener;
6+
import net.blay09.mods.shogi.common.ShogiCommon;
57
import net.blay09.mods.shogi.common.network.ShogiValueResultPayload;
6-
import net.blay09.mods.shogi.sync.ShogiStreamCodecs;
8+
import net.blay09.mods.shogi.common.platform.ShogiRuntimeSpi;
9+
import net.blay09.mods.shogi.network.ShogiStreamCodecs;
10+
import net.minecraft.client.Minecraft;
11+
import net.minecraftforge.client.event.RegisterClientReloadListenersEvent;
712
import net.minecraftforge.common.MinecraftForge;
813
import net.minecraftforge.client.event.ClientPlayerNetworkEvent;
914
import net.minecraftforge.client.network.event.RegisterClientPayloadHandlersEvent;
@@ -15,6 +20,7 @@ public class ForgeShogiClient {
1520
public static void init(IEventBus modEventBus) {
1621
events = ShogiClient.initialize();
1722
modEventBus.addListener(ForgeShogiClient::onRegisterClientPayloadHandlers);
23+
modEventBus.addListener(ForgeShogiClient::onRegisterClientReloadListeners);
1824
MinecraftForge.EVENT_BUS.addListener(ForgeShogiClient::onClientLoggedOut);
1925
}
2026

@@ -29,4 +35,12 @@ private static void onRegisterClientPayloadHandlers(RegisterClientPayloadHandler
2935
private static void onClientLoggedOut(ClientPlayerNetworkEvent.LoggingOut event) {
3036
events.onDisconnected();
3137
}
38+
39+
private static void onRegisterClientReloadListeners(RegisterClientReloadListenersEvent event) {
40+
final var runtime = ShogiRuntimeSpi.get();
41+
event.registerReloadListener(new ShogiClientRuleReloadListener(runtime.getConfigDirectory(), () -> {
42+
final var connection = Minecraft.getInstance().getConnection();
43+
return connection != null ? connection.registryAccess() : null;
44+
}));
45+
}
3246
}

neoforge/src/main/java/net/blay09/mods/shogi/neoforge/client/NeoForgeShogiClient.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,17 @@
22

33
import net.blay09.mods.shogi.client.ShogiClient;
44
import net.blay09.mods.shogi.client.platform.ShogiClientEventListener;
5+
import net.blay09.mods.shogi.common.ShogiClientRuleReloadListener;
6+
import net.blay09.mods.shogi.common.ShogiCommon;
57
import net.blay09.mods.shogi.common.network.ShogiValueResultPayload;
68
import net.blay09.mods.shogi.network.ShogiStreamCodecs;
9+
import net.blay09.mods.shogi.common.platform.ShogiRuntimeSpi;
10+
import net.minecraft.client.Minecraft;
711
import net.neoforged.api.distmarker.Dist;
812
import net.neoforged.bus.api.IEventBus;
913
import net.neoforged.fml.ModContainer;
1014
import net.neoforged.fml.common.Mod;
15+
import net.neoforged.neoforge.client.event.AddClientReloadListenersEvent;
1116
import net.neoforged.neoforge.client.event.ClientPlayerNetworkEvent;
1217
import net.neoforged.neoforge.client.network.event.RegisterClientPayloadHandlersEvent;
1318
import net.neoforged.neoforge.common.NeoForge;
@@ -19,6 +24,7 @@ public class NeoForgeShogiClient {
1924
public NeoForgeShogiClient(ModContainer modContainer, IEventBus modEventBus) {
2025
events = ShogiClient.initialize();
2126
modEventBus.addListener(this::onRegisterClientPayloadHandlers);
27+
modEventBus.addListener(this::onAddClientReloadListeners);
2228
NeoForge.EVENT_BUS.addListener(this::onClientLoggedOut);
2329
}
2430

@@ -33,4 +39,12 @@ private void onRegisterClientPayloadHandlers(RegisterClientPayloadHandlersEvent
3339
private void onClientLoggedOut(ClientPlayerNetworkEvent.LoggingOut event) {
3440
events.onDisconnected();
3541
}
42+
43+
private void onAddClientReloadListeners(AddClientReloadListenersEvent event) {
44+
final var runtime = ShogiRuntimeSpi.get();
45+
event.addListener(ShogiCommon.id("client_rule_reloader"), new ShogiClientRuleReloadListener(runtime.getConfigDirectory(), () -> {
46+
final var connection = Minecraft.getInstance().getConnection();
47+
return connection != null ? connection.registryAccess() : null;
48+
}));
49+
}
3650
}

0 commit comments

Comments
 (0)