Merge branch 'minecraft-lod-mod-serverCommunication'

This commit is contained in:
James Seibel
2023-07-04 13:43:08 -05:00
11 changed files with 192 additions and 61 deletions
+3 -1
View File
@@ -203,7 +203,9 @@ subprojects { p ->
// SVG
shadowMe("com.formdev:svgSalamander:${rootProject.svgSalamander_version}")
shadowMe("com.formdev:flatlaf-extras:${rootProject.flatlaf_version}")
// Netty
shadowMe("io.netty:netty-all:4.1.94.Final")
// Remember, for lwjgl dependancies that arent included in Minecraft, you need to also need to add it to the ShadowJar thing
shadowMe("org.lwjgl:lwjgl-jawt:3.2.2") {
@@ -20,7 +20,9 @@
package com.seibel.distanthorizons.common.wrappers;
import com.seibel.distanthorizons.common.wrappers.gui.LangWrapper;
import com.seibel.distanthorizons.common.wrappers.level.KeyedClientLevelManager;
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftDedicatedServerWrapper;
import com.seibel.distanthorizons.core.level.IKeyedClientLevelManager;
import com.seibel.distanthorizons.core.wrapperInterfaces.config.ILangWrapper;
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftClientWrapper;
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftRenderWrapper;
@@ -49,6 +51,7 @@ public class DependencySetup {
SingletonInjector.INSTANCE.bind(ILangWrapper.class, LangWrapper.INSTANCE);
SingletonInjector.INSTANCE.bind(IVersionConstants.class, VersionConstants.INSTANCE);
SingletonInjector.INSTANCE.bind(IWrapperFactory.class, WrapperFactory.INSTANCE);
SingletonInjector.INSTANCE.bind(IKeyedClientLevelManager.class, KeyedClientLevelManager.INSTANCE);
DependencySetupDoneCheck.isDone = true;
}
@@ -0,0 +1,54 @@
package com.seibel.distanthorizons.common.wrappers.level;
import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper;
import com.seibel.distanthorizons.core.level.IServerKeyedClientLevel;
import com.seibel.distanthorizons.core.level.IKeyedClientLevelManager;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
import net.minecraft.client.multiplayer.ClientLevel;
import java.util.Objects;
public class KeyedClientLevelManager implements IKeyedClientLevelManager
{
public static final KeyedClientLevelManager INSTANCE = new KeyedClientLevelManager();
/** This is set and managed by the ClientApi for servers with support for DH. */
private IServerKeyedClientLevel overrideWrapper = null;
private boolean useOverrideWrapper = false;
//=============//
// constructor //
//=============//
private KeyedClientLevelManager() { }
//======================//
// level override logic //
//======================//
@Override
public void setServerKeyedLevel(IServerKeyedClientLevel clientLevel) { this.overrideWrapper = clientLevel; }
@Override
public IServerKeyedClientLevel getOverrideWrapper() { return this.overrideWrapper; }
@Override
public IServerKeyedClientLevel getServerKeyedLevel(ILevelWrapper level, String serverLevelKey)
{
Objects.requireNonNull(level);
Objects.requireNonNull(serverLevelKey);
return new ServerKeyedClientLevel((ClientLevel) level.getWrappedMcObject(), serverLevelKey);
}
@Override
public void setUseOverrideWrapper(boolean useOverrideWrapper) { this.useOverrideWrapper = useOverrideWrapper; }
@Override
public boolean getUseOverrideWrapper() { return this.useOverrideWrapper; }
}
@@ -0,0 +1,21 @@
package com.seibel.distanthorizons.common.wrappers.level;
import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper;
import com.seibel.distanthorizons.core.level.IServerKeyedClientLevel;
import net.minecraft.client.multiplayer.ClientLevel;
public class ServerKeyedClientLevel extends ClientLevelWrapper implements IServerKeyedClientLevel
{
/** A unique identifier (generally the level's name) for differentiating multiverse levels */
private final String serverLevelKey;
public ServerKeyedClientLevel(ClientLevel level, String serverLevelKey)
{
super(level);
this.serverLevelKey = serverLevelKey;
}
@Override
public String getServerLevelKey() { return this.serverLevelKey; }
}
@@ -180,7 +180,7 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
return null;
}
return ClientLevelWrapper.getWrapper(mc.level);
return ClientLevelWrapper.getWrapperIgnoringOverride(this.mc.level);
}
/** Please move over to getInstallationDirectory() */
@@ -261,4 +261,8 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
public File getInstallationDirectory() {
return mc.gameDirectory;
}
@Override
public void executeOnRenderThread(Runnable runnable) { this.mc.execute(runnable); }
}
@@ -8,6 +8,8 @@ import com.seibel.distanthorizons.common.wrappers.block.BlockStateWrapper;
import com.seibel.distanthorizons.common.wrappers.block.cache.ClientBlockDetailMap;
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftClientWrapper;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.level.IKeyedClientLevelManager;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.pos.DhBlockPos;
import com.seibel.distanthorizons.core.pos.DhChunkPos;
@@ -28,30 +30,48 @@ import org.jetbrains.annotations.Nullable;
import java.util.concurrent.ConcurrentHashMap;
/**
*
* @version 2023-6-3
*/
public class ClientLevelWrapper implements IClientLevelWrapper
{
private static final Logger LOGGER = DhLoggerBuilder.getLogger(ClientLevelWrapper.class.getSimpleName());
private static final ConcurrentHashMap<ClientLevel, ClientLevelWrapper>
levelWrapperMap = new ConcurrentHashMap<>();
public static ClientLevelWrapper getWrapper(ClientLevel level) {
return levelWrapperMap.computeIfAbsent(level, ClientLevelWrapper::new);
}
public static void closeWrapper(ClientLevel level)
{
levelWrapperMap.remove(level);
}
private ClientLevelWrapper(ClientLevel level) {
this.level = level;
}
final ClientLevel level;
ClientBlockDetailMap blockMap = new ClientBlockDetailMap(this);
@Nullable
private static final ConcurrentHashMap<ClientLevel, ClientLevelWrapper> LEVEL_WRAPPER_BY_CLIENT_LEVEL = new ConcurrentHashMap<>();
private static final IKeyedClientLevelManager KEYED_CLIENT_LEVEL_MANAGER = SingletonInjector.INSTANCE.get(IKeyedClientLevelManager.class);
private final ClientLevel level;
private final ClientBlockDetailMap blockMap = new ClientBlockDetailMap(this);
//=============//
// constructor //
//=============//
protected ClientLevelWrapper(ClientLevel level) { this.level = level; }
//===============//
// wrapper logic //
//===============//
public static IClientLevelWrapper getWrapper(ClientLevel level)
{
// used if the client is connected to a server that defines the currently loaded level
if (KEYED_CLIENT_LEVEL_MANAGER.getUseOverrideWrapper())
{
return KEYED_CLIENT_LEVEL_MANAGER.getOverrideWrapper();
}
return getWrapperIgnoringOverride(level);
}
public static IClientLevelWrapper getWrapperIgnoringOverride(ClientLevel level)
{
return LEVEL_WRAPPER_BY_CLIENT_LEVEL.computeIfAbsent(level, ClientLevelWrapper::new);
}
public static void closeLevel(ClientLevel level) { LEVEL_WRAPPER_BY_CLIENT_LEVEL.remove(level); }
@Nullable
@Override
public IServerLevelWrapper tryGetServerSideWrapper()
{
@@ -89,12 +109,18 @@ public class ClientLevelWrapper implements IClientLevelWrapper
}
}
public static void cleanCheck() {
if (!levelWrapperMap.isEmpty()) {
LOGGER.warn("{} client levels havn't been freed!", levelWrapperMap.size());
levelWrapperMap.clear();
if (!LEVEL_WRAPPER_BY_CLIENT_LEVEL.isEmpty()) {
LOGGER.warn("{} client levels havn't been freed!", LEVEL_WRAPPER_BY_CLIENT_LEVEL.size());
LEVEL_WRAPPER_BY_CLIENT_LEVEL.clear();
}
}
//====================//
// base level methods //
//====================//
@Override
public int computeBaseColor(DhBlockPos pos, IBiomeWrapper biome, IBlockStateWrapper blockState) {
return blockMap.getColor(((BlockStateWrapper)blockState).blockState,
@@ -183,8 +209,14 @@ public class ClientLevelWrapper implements IClientLevelWrapper
}
@Override
public String toString() {
return "Wrapped{" + level.toString() + "@" + getDimensionType().getDimensionName() + "}";
}
public String toString()
{
if (this.level == null)
{
return "Wrapped{null}";
}
return "Wrapped{" + this.level.toString() + "@" + this.getDimensionType().getDimensionName() + "}";
}
}
+1
View File
@@ -60,6 +60,7 @@ dependencies {
addModJar(fabricApi.module("fabric-resource-loader-v0", rootProject.fabric_api_version))
addModJar(fabricApi.module("fabric-rendering-v1", rootProject.fabric_api_version)) // TODO: Remove this as it is only needed in 1 line (FabricClientProxy)
addModJar(fabricApi.module("fabric-api-base", rootProject.fabric_api_version))
addModJar(fabricApi.module("fabric-networking-api-v1", rootProject.fabric_api_version))
// Mod Menu
modImplementation("com.terraformersmc:modmenu:${rootProject.modmenu_version}")
@@ -31,6 +31,7 @@ import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IImmersivePortalsAccessor;
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.ISodiumAccessor;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
import com.seibel.distanthorizons.fabric.wrappers.modAccessor.ImmersivePortalsAccessor;
import com.seibel.distanthorizons.fabric.wrappers.modAccessor.SodiumAccessor;
import net.fabricmc.api.EnvType;
@@ -100,7 +101,7 @@ public class FabricClientProxy
//#if PRE_MC_1_18_2 // in 1.18+, we use mixin hook in setClientLightReady(true)
ClientChunkEvents.CHUNK_LOAD.register((level, chunk) ->
{
ClientLevelWrapper wrappedLevel = ClientLevelWrapper.getWrapper(level);
IClientLevelWrapper wrappedLevel = ClientLevelWrapper.getWrapper(level);
ClientApi.INSTANCE.clientChunkLoadEvent(
new ChunkWrapper(chunk, level, wrappedLevel),
wrappedLevel
@@ -119,7 +120,7 @@ public class FabricClientProxy
{
// LOGGER.info("attack block at blockpos: " + blockPos);
ClientLevelWrapper wrappedLevel = ClientLevelWrapper.getWrapper((ClientLevel) level);
IClientLevelWrapper wrappedLevel = ClientLevelWrapper.getWrapper((ClientLevel) level);
ClientApi.INSTANCE.clientChunkLoadEvent(
new ChunkWrapper(chunk, level, wrappedLevel),
wrappedLevel
@@ -146,7 +147,7 @@ public class FabricClientProxy
{
// LOGGER.info("use block at blockpos: " + hitResult.getBlockPos());
ClientLevelWrapper wrappedLevel = ClientLevelWrapper.getWrapper((ClientLevel) level);
IClientLevelWrapper wrappedLevel = ClientLevelWrapper.getWrapper((ClientLevel) level);
ClientApi.INSTANCE.clientChunkLoadEvent(
new ChunkWrapper(chunk, level, wrappedLevel),
wrappedLevel
@@ -163,7 +164,7 @@ public class FabricClientProxy
// ClientChunkSaveEvent
ClientChunkEvents.CHUNK_UNLOAD.register((level, chunk) ->
{
ClientLevelWrapper wrappedLevel = ClientLevelWrapper.getWrapper(level);
IClientLevelWrapper wrappedLevel = ClientLevelWrapper.getWrapper(level);
ClientApi.INSTANCE.clientChunkSaveEvent(
new ChunkWrapper(chunk, level, wrappedLevel),
wrappedLevel
@@ -5,17 +5,23 @@ import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper;
import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper;
import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment;
import com.seibel.distanthorizons.core.api.internal.ClientApi;
import com.seibel.distanthorizons.core.api.internal.ServerApi;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerChunkEvents;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerWorldEvents;
import net.fabricmc.fabric.api.networking.v1.PacketSender;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screens.TitleScreen;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.multiplayer.ClientPacketListener;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
@@ -35,50 +41,50 @@ public class FabricServerProxy
{
private static final ServerApi SERVER_API = ServerApi.INSTANCE;
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
private final boolean isDedicated;
public static Supplier<Boolean> isGenerationThreadChecker = null;
public FabricServerProxy(boolean isDedicated)
{
this.isDedicated = isDedicated;
}
private boolean isValidTime()
{
if (isDedicated)
{
return true;
}
//FIXME: This may cause init issue...
return !(Minecraft.getInstance().screen instanceof TitleScreen);
}
private ClientLevelWrapper getClientLevelWrapper(ClientLevel level) { return ClientLevelWrapper.getWrapper(level); }
private IClientLevelWrapper getClientLevelWrapper(ClientLevel level) { return ClientLevelWrapper.getWrapper(level); }
private ServerLevelWrapper getServerLevelWrapper(ServerLevel level) { return ServerLevelWrapper.getWrapper(level); }
/** Registers Fabric Events */
public void registerEvents()
{
LOGGER.info("Registering Fabric Server Events");
isGenerationThreadChecker = BatchGenerationEnvironment::isCurrentThreadDistantGeneratorThread;
/* Register the mod needed event callbacks */
// TEST EVENT
//ServerTickEvents.END_SERVER_TICK.register(this::tester);
// ServerTickEvent
ServerTickEvents.END_SERVER_TICK.register((server) -> SERVER_API.serverTickEvent());
// ServerWorldLoadEvent
//TODO: Check if both of these use the correct timed events. (i.e. is it 'ed' or 'ing' one?)
ServerLifecycleEvents.SERVER_STARTING.register((server) ->
ServerLifecycleEvents.SERVER_STARTING.register((server) ->
{
if (isValidTime())
{
@@ -86,16 +92,16 @@ public class FabricServerProxy
}
});
// ServerWorldUnloadEvent
ServerLifecycleEvents.SERVER_STOPPED.register((server) ->
ServerLifecycleEvents.SERVER_STOPPED.register((server) ->
{
if (isValidTime())
{
ServerApi.INSTANCE.serverUnloadEvent();
}
});
// ServerLevelLoadEvent
ServerWorldEvents.LOAD.register((server, level) ->
ServerWorldEvents.LOAD.register((server, level) ->
{
if (isValidTime())
{
@@ -103,16 +109,16 @@ public class FabricServerProxy
}
});
// ServerLevelUnloadEvent
ServerWorldEvents.UNLOAD.register((server, level) ->
ServerWorldEvents.UNLOAD.register((server, level) ->
{
if (isValidTime())
{
ServerApi.INSTANCE.serverLevelUnloadEvent(getServerLevelWrapper(level));
}
});
// ServerChunkLoadEvent
ServerChunkEvents.CHUNK_LOAD.register((server, chunk) ->
ServerChunkEvents.CHUNK_LOAD.register((server, chunk) ->
{
ILevelWrapper level = getServerLevelWrapper((ServerLevel) chunk.getLevel());
if (isValidTime())
@@ -123,8 +129,14 @@ public class FabricServerProxy
}
});
// ServerChunkSaveEvent - Done in MixinChunkMap
ClientPlayNetworking.registerGlobalReceiver(new ResourceLocation("distant_horizons", "world_control"), // TODO move these strings into a constant somewhere
(Minecraft client, ClientPacketListener handler, FriendlyByteBuf byteBuffer, PacketSender responseSender) ->
{
ClientApi.INSTANCE.serverMessageReceived(byteBuffer);
});
}
// This just exists here for testing purposes, it'll be removed in the future
public void tester(MinecraftServer server)
{ // I disabled the Networking functions for now so this will not work atm - coolGi
@@ -136,5 +148,5 @@ public class FabricServerProxy
Networking.send(player, payload);
}
}
}
@@ -24,6 +24,7 @@ import com.seibel.distanthorizons.core.api.internal.ClientApi;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.client.multiplayer.ClientLevel;
@@ -95,7 +96,7 @@ public class ForgeClientProxy
{
if (GetLevel(event) instanceof ClientLevel)
{
ClientLevelWrapper wrappedLevel = ClientLevelWrapper.getWrapper((ClientLevel) GetLevel(event));
IClientLevelWrapper wrappedLevel = ClientLevelWrapper.getWrapper((ClientLevel) GetLevel(event));
IChunkWrapper chunk = new ChunkWrapper(event.getChunk(), GetLevel(event), wrappedLevel);
ClientApi.INSTANCE.clientChunkLoadEvent(chunk, ClientLevelWrapper.getWrapper((ClientLevel) GetLevel(event)));
}
@@ -105,7 +106,7 @@ public class ForgeClientProxy
{
if (GetLevel(event) instanceof ClientLevel)
{
ClientLevelWrapper wrappedLevel = ClientLevelWrapper.getWrapper((ClientLevel) GetLevel(event));
IClientLevelWrapper wrappedLevel = ClientLevelWrapper.getWrapper((ClientLevel) GetLevel(event));
IChunkWrapper chunk = new ChunkWrapper(event.getChunk() , GetLevel(event), wrappedLevel);
ClientApi.INSTANCE.clientChunkSaveEvent(chunk, ClientLevelWrapper.getWrapper((ClientLevel) GetLevel(event)));
}