diff --git a/src/main/java/com/livingworld/platform/neoforge/NeoForgePlatformAdapter.java b/src/main/java/com/livingworld/platform/neoforge/NeoForgePlatformAdapter.java new file mode 100644 index 0000000..58d7187 --- /dev/null +++ b/src/main/java/com/livingworld/platform/neoforge/NeoForgePlatformAdapter.java @@ -0,0 +1,97 @@ +package com.livingworld.platform.neoforge; + +import com.livingworld.platform.PlatformAdapter; +import com.mojang.brigadier.CommandDispatcher; +import java.nio.file.Path; +import java.util.Objects; +import java.util.function.Consumer; +import java.util.function.Supplier; +import net.minecraft.SharedConstants; +import net.minecraft.commands.CommandSourceStack; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.fml.ModList; +import net.neoforged.fml.loading.FMLEnvironment; +import net.neoforged.neoforge.common.NeoForge; +import net.neoforged.neoforge.event.RegisterCommandsEvent; +import net.neoforged.neoforge.event.tick.ServerTickEvent; + +/** + * NeoForge implementation of the Living World platform boundary. + */ +public final class NeoForgePlatformAdapter implements PlatformAdapter { + + private static final String NEOFORGE_MOD_ID = "neoforge"; + + private final Supplier worldSaveDirectory; + private final Consumer> commandRegistrar; + private final Runnable serverTickHook; + private boolean commandsRegistered; + private boolean serverTickRegistered; + + public NeoForgePlatformAdapter( + Supplier worldSaveDirectory, + Consumer> commandRegistrar, + Runnable serverTickHook) { + this.worldSaveDirectory = + Objects.requireNonNull(worldSaveDirectory, "worldSaveDirectory"); + this.commandRegistrar = Objects.requireNonNull(commandRegistrar, "commandRegistrar"); + this.serverTickHook = Objects.requireNonNull(serverTickHook, "serverTickHook"); + } + + @Override + public String getPlatformName() { + return "NeoForge"; + } + + @Override + public String getMinecraftVersion() { + return SharedConstants.getCurrentVersion().getName(); + } + + @Override + public String getLoaderVersion() { + return ModList.get() + .getModContainerById(NEOFORGE_MOD_ID) + .map(container -> container.getModInfo().getVersion().toString()) + .orElse("unknown"); + } + + @Override + public boolean isDedicatedServer() { + return FMLEnvironment.dist == Dist.DEDICATED_SERVER; + } + + @Override + public Path getWorldSaveDirectory() { + Path path = worldSaveDirectory.get(); + if (path == null) { + throw new IllegalStateException("world save directory is not available yet"); + } + return path; + } + + @Override + public void registerCommands() { + if (commandsRegistered) { + return; + } + NeoForge.EVENT_BUS.addListener(RegisterCommandsEvent.class, event -> + commandRegistrar.accept(event.getDispatcher())); + commandsRegistered = true; + } + + @Override + public void registerServerTickHook() { + if (serverTickRegistered) { + return; + } + NeoForge.EVENT_BUS.addListener(ServerTickEvent.Post.class, event -> + serverTickHook.run()); + serverTickRegistered = true; + } + + @Override + public void registerPlayerEventHooks() { + // Player activity hooks are intentionally deferred until a module needs them. + } +}