Compare commits

...

26 Commits

Author SHA1 Message Date
s809 44cf6f6955 [skip ci] Incomplete instance based config 2024-09-20 19:49:26 +05:00
s809 00b69dcc68 Fix mixin crashes on 1.16.5 2024-09-18 01:06:06 +05:00
s809 cd74e33c54 Bump protocol version because of removed InvalidSectionPosException 2024-09-17 12:41:52 +05:00
s809 3f14e5dfa5 Fix naming of some things and comments 2024-09-17 09:48:15 +05:00
James Seibel 8c9e6ea79a Fix very high file handler jobs and pool some render data sources 2024-09-16 20:36:10 -05:00
James Seibel c71de31f57 Fix a few pre-processors blocked renamings 2024-09-16 19:37:34 -05:00
James Seibel ac869bf06e Up API version 3.0.1 -> 4.0.0 2024-09-15 21:16:24 -05:00
James Seibel 3175bc0439 Up version 2.2.2 -> 2.3.0 2024-09-15 21:16:13 -05:00
James Seibel 23ac6ec957 merge server side and minor refactoring 2024-09-15 21:15:40 -05:00
James Seibel f080a59b41 Add netty leak detection and server/client folder separation 2024-09-11 17:38:02 -05:00
James Seibel 603200ed8b only log git info on startup in dev builds 2024-09-11 17:19:33 -05:00
James Seibel b0774052a0 add default intellij gradle run scripts 2024-09-11 17:12:34 -05:00
James Seibel 7e163ce626 Add ILevelWrapper.getDimensionName() 2024-09-11 07:18:57 -05:00
James Seibel d19654cf15 Remove unneeded ChunkWrapper lighting checks 2024-09-10 07:35:02 -05:00
James Seibel 838d8be08b minor refactoring and style cleanup 2024-09-10 07:29:42 -05:00
James Seibel 2de82b1223 Add Netty to the build script 2024-09-10 06:55:40 -05:00
James Seibel 650012fb08 allow CI/CD to auto retry if there was a system failure 2024-09-10 06:53:06 -05:00
James Seibel a1ef3466ad Add test scripts folder 2024-09-10 06:52:21 -05:00
James Seibel 97421feb33 Add Oculus 1.7 to the list of incompatible fabric mods 2024-09-09 07:43:24 -05:00
James Seibel 0c90af6515 Fix low quality LODs not loading when flying in a new straight line 2024-09-09 07:41:20 -05:00
James Seibel 9cebd0298c add brown mushrooms to the list of ignored blocks to fix swamp issues 2024-09-07 14:22:45 -05:00
James Seibel 9afcddca4f Add faster sky light engine from Builderb0y
Closes !67
2024-09-07 12:07:59 -05:00
James Seibel 02fb7eedba Add missing LightingTestChunkWrapper methods 2024-09-06 21:55:55 -05:00
James Seibel 4aa9bec15c Fix unit test compiling 2024-09-06 19:36:41 -05:00
James Seibel a6eeaa5b3e Closes #805 (Hide "Distant Horizons overloaded")
Also update chunks closest to the player first
2024-09-06 18:23:04 -05:00
James Seibel c462325ce6 Add BuilderB0y's getBlockState optimization 2024-09-05 07:50:25 -05:00
77 changed files with 1800 additions and 624 deletions
+5
View File
@@ -24,6 +24,11 @@ variables:
- .gradle - .gradle
- cache/ - cache/
allow_failure: true allow_failure: true
retry:
max: 2
when:
- runner_system_failure
- stuck_or_timeout_failure
build: build:
+7
View File
@@ -0,0 +1,7 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Fabric Client &amp; Server" type="CompoundRunConfigurationType">
<toRun name="Fabric Client (:fabric)" type="Application" />
<toRun name="Fabric Server (:fabric)" type="Application" />
<method v="2" />
</configuration>
</component>
+7
View File
@@ -0,0 +1,7 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Forge Client &amp; Server" type="CompoundRunConfigurationType">
<toRun name="Forge Client (gradle)" type="GradleRunConfiguration" />
<toRun name="Forge Server (gradle)" type="GradleRunConfiguration" />
<method v="2" />
</configuration>
</component>
+24
View File
@@ -0,0 +1,24 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Forge Client (gradle)" type="GradleRunConfiguration" factoryName="Gradle">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="forge:runClient" />
</list>
</option>
<option name="vmOptions" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<method v="2" />
</configuration>
</component>
+24
View File
@@ -0,0 +1,24 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Forge Server (gradle)" type="GradleRunConfiguration" factoryName="Gradle">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="forge:runServer" />
</list>
</option>
<option name="vmOptions" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<method v="2" />
</configuration>
</component>
+7
View File
@@ -0,0 +1,7 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Neoforge Client &amp; Server" type="CompoundRunConfigurationType">
<toRun name="Neoforge Client (gradle)" type="GradleRunConfiguration" />
<toRun name="Neoforge Server (gradle)" type="GradleRunConfiguration" />
<method v="2" />
</configuration>
</component>
+24
View File
@@ -0,0 +1,24 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Neoforge Client (gradle)" type="GradleRunConfiguration" factoryName="Gradle">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="neoforge:runClient" />
</list>
</option>
<option name="vmOptions" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<method v="2" />
</configuration>
</component>
+24
View File
@@ -0,0 +1,24 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Neoforge Server (gradle)" type="GradleRunConfiguration" factoryName="Gradle">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="neoforge:runServer" />
</list>
</option>
<option name="vmOptions" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<method v="2" />
</configuration>
</component>
+3 -3
View File
@@ -218,8 +218,7 @@ subprojects { p ->
// forgeShadowMe("com.formdev:svgSalamander:${rootProject.svgSalamander_version}") // forgeShadowMe("com.formdev:svgSalamander:${rootProject.svgSalamander_version}")
// Netty // Netty
// Breaks 1.16.5 implementation("io.netty:netty-buffer:${rootProject.netty_version}")
//forgeShadowMe("io.netty:netty-all:${rootProject.netty_version}")
// Remember, for lwjgl dependencies that arent included in Minecraft, you need to also need to add it to the ShadowJar thing // Remember, for lwjgl dependencies that arent included in Minecraft, you need to also need to add it to the ShadowJar thing
forgeShadowMe("org.lwjgl:lwjgl-jawt:${rootProject.lwjgl_version}") { forgeShadowMe("org.lwjgl:lwjgl-jawt:${rootProject.lwjgl_version}") {
@@ -307,7 +306,8 @@ subprojects { p ->
// relocate "com.kitfox.svg", "${librariesLocation}.kitfox.svg" // relocate "com.kitfox.svg", "${librariesLocation}.kitfox.svg"
// Netty // Netty
relocate "io.netty", "${librariesLocation}.netty" // Don't relocate, it causes problems with using MC's FriendlyByteBufs
// relocate "io.netty", "${librariesLocation}.netty"
mergeServiceFiles() mergeServiceFiles()
} }
+12 -6
View File
@@ -1,7 +1,8 @@
#!/bin/sh #!/bin/sh
echo "==================== Note: All build jars will be in the folder called 'buildAllJars' ====================" echo "==================== Note: All build jars will be in the folder called 'buildAllJars' ===================="
mkdir -p buildAllJars | true mkdir -p buildAllJars
rm -rf buildAllJars/*
# Loop trough everything in the version properties folder # Loop trough everything in the version properties folder
for d in versionProperties/*; do for d in versionProperties/*; do
@@ -11,12 +12,17 @@ for d in versionProperties/*; do
# Clean out the folders, build it, and merge it # Clean out the folders, build it, and merge it
# (We could use "./" to run gradlew, but as it is a shell script im going to be running it with the "sh" command) # (We could use "./" to run gradlew, but as it is a shell script im going to be running it with the "sh" command)
echo "==================== Cleaning workspace to build $version ====================" echo "==================== Cleaning workspace to build $version ===================="
sh gradlew clean -PmcVer=$version --no-daemon || true sh gradlew clean -PmcVer=$version
if [ $? != 0 ]; then continue; fi
echo "====================Building $version ====================" echo "====================Building $version ===================="
sh gradlew build -PmcVer=$version --no-daemon || true sh gradlew build -PmcVer=$version
if [ $? != 0 ]; then continue; fi
echo "==================== Merging $version ====================" echo "==================== Merging $version ===================="
sh gradlew mergeJars -PmcVer=$version --no-daemon || true sh gradlew mergeJars -PmcVer=$version
if [ $? != 0 ]; then continue; fi
echo "==================== Moving jar ====================" echo "==================== Moving jar ===================="
mv Merged/*.jar buildAllJars/ || true mv Merged/*.jar buildAllJars/
# The "| true" at the end of those are just to make sure the script continues even if a build fails
done done
+4 -3
View File
@@ -5,6 +5,7 @@
echo ==================== Note: All build jars will be in the folder called 'buildAllJars' ==================== echo ==================== Note: All build jars will be in the folder called 'buildAllJars' ====================
mkdir buildAllJars mkdir buildAllJars
del buildAllJars/*
@rem Loop trough everything in the version properties folder @rem Loop trough everything in the version properties folder
for %%f in (versionProperties\*) do ( for %%f in (versionProperties\*) do (
@@ -13,11 +14,11 @@ for %%f in (versionProperties\*) do (
@rem Clean out the folders, build it, and merge it @rem Clean out the folders, build it, and merge it
echo ==================== Cleaning workspace to build !version! ==================== echo ==================== Cleaning workspace to build !version! ====================
call .\gradlew.bat clean -PmcVer="!version!" --no-daemon call .\gradlew.bat clean -PmcVer="!version!"
echo ==================== Building !version! ==================== echo ==================== Building !version! ====================
call .\gradlew.bat build -PmcVer="!version!" --no-daemon call .\gradlew.bat build -PmcVer="!version!"
echo ==================== Merging !version! ==================== echo ==================== Merging !version! ====================
call .\gradlew.bat mergeJars -PmcVer="!version!" --no-daemon call .\gradlew.bat mergeJars -PmcVer="!version!"
echo ==================== Moving jar ==================== echo ==================== Moving jar ====================
move Merged\*.jar buildAllJars\ move Merged\*.jar buildAllJars\
) )
+8
View File
@@ -1,3 +1,11 @@
// TODO can this be removed?
//buildscript {
// configurations.configureEach {
// resolutionStrategy {
// force 'org.spongepowered:vanillagradle:0.2.1-20240507.024226-82'
// }
// }
//}
// temporary fix for broken spongepowered version // temporary fix for broken spongepowered version
buildscript { buildscript {
@@ -1,18 +1,28 @@
package com.seibel.distanthorizons.common; package com.seibel.distanthorizons.common;
import com.mojang.brigadier.Command;
import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.arguments.*;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.context.CommandContext;
import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiAfterDhInitEvent; import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiAfterDhInitEvent;
import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiBeforeDhInitEvent; import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiBeforeDhInitEvent;
import com.seibel.distanthorizons.common.wrappers.DependencySetup; import com.seibel.distanthorizons.common.wrappers.DependencySetup;
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftDedicatedServerWrapper; import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftServerWrapper;
import com.seibel.distanthorizons.common.wrappers.misc.ServerPlayerWrapper;
import com.seibel.distanthorizons.core.api.internal.SharedApi; import com.seibel.distanthorizons.core.api.internal.SharedApi;
import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.core.config.ConfigBase; import com.seibel.distanthorizons.core.config.ConfigBase;
import com.seibel.distanthorizons.core.config.eventHandlers.presets.ThreadPresetConfigEventHandler; import com.seibel.distanthorizons.core.config.eventHandlers.presets.ThreadPresetConfigEventHandler;
import com.seibel.distanthorizons.core.config.types.AbstractConfigType;
import com.seibel.distanthorizons.core.config.types.ConfigEntry;
import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector; import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.jar.ModJarInfo; import com.seibel.distanthorizons.core.jar.ModJarInfo;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.network.messages.base.CodecCrashMessage;
import com.seibel.distanthorizons.core.util.objects.Pair;
import com.seibel.distanthorizons.core.world.DhServerWorld;
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IModAccessor; import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IModAccessor;
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IModChecker; import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IModChecker;
import com.seibel.distanthorizons.coreapi.DependencyInjection.ApiEventInjector; import com.seibel.distanthorizons.coreapi.DependencyInjection.ApiEventInjector;
@@ -23,9 +33,25 @@ import net.minecraft.server.dedicated.DedicatedServer;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodHandles;
import java.util.HashMap;
import java.util.Objects;
import java.util.function.BiFunction;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier; import java.util.function.Supplier;
import static com.mojang.brigadier.arguments.DoubleArgumentType.doubleArg;
import static com.mojang.brigadier.arguments.IntegerArgumentType.integer;
import static com.seibel.distanthorizons.core.network.messages.MessageRegistry.DEBUG_CODEC_CRASH_MESSAGE;
import static net.minecraft.commands.Commands.argument;
import static net.minecraft.commands.Commands.literal;
#if MC_VER >= MC_1_19_2
import net.minecraft.network.chat.Component;
#else // < 1.19.2
import net.minecraft.network.chat.TranslatableComponent;
#endif
/** /**
* Base for all mod loader initializers * Base for all mod loader initializers
* and handles most setup. * and handles most setup.
@@ -67,7 +93,7 @@ public abstract class AbstractModInitializer
ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeDhInitEvent.class, null); ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeDhInitEvent.class, null);
this.startup(); this.startup();
this.printModInfo(true); this.logBuildInfo();
this.createClientProxy().registerEvents(); this.createClientProxy().registerEvents();
this.createServerProxy(false).registerEvents(); this.createServerProxy(false).registerEvents();
@@ -91,7 +117,7 @@ public abstract class AbstractModInitializer
ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeDhInitEvent.class, null); ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeDhInitEvent.class, null);
this.startup(); this.startup();
this.printModInfo(false); this.logBuildInfo();
// This prevents returning uninitialized Config values, // This prevents returning uninitialized Config values,
// resulting from a circular reference mid-initialization in a static class // resulting from a circular reference mid-initialization in a static class
@@ -100,6 +126,8 @@ public abstract class AbstractModInitializer
this.createServerProxy(true).registerEvents(); this.createServerProxy(true).registerEvents();
this.initializeModCompat();
LOGGER.info(ModInfo.READABLE_NAME + " Initialized"); LOGGER.info(ModInfo.READABLE_NAME + " Initialized");
ApiEventInjector.INSTANCE.fireAllEvents(DhApiAfterDhInitEvent.class, null); ApiEventInjector.INSTANCE.fireAllEvents(DhApiAfterDhInitEvent.class, null);
@@ -107,7 +135,7 @@ public abstract class AbstractModInitializer
this.subscribeServerStartingEvent(server -> this.subscribeServerStartingEvent(server ->
{ {
MinecraftDedicatedServerWrapper.INSTANCE.dedicatedServer = (DedicatedServer)server; MinecraftServerWrapper.INSTANCE.dedicatedServer = (DedicatedServer)server;
this.initConfig(); this.initConfig();
this.postInit(); this.postInit();
@@ -130,13 +158,13 @@ public abstract class AbstractModInitializer
this.createInitialBindings(); this.createInitialBindings();
} }
private void printModInfo(boolean printGitInfo) private void logBuildInfo()
{ {
LOGGER.info(ModInfo.READABLE_NAME + ", Version: " + ModInfo.VERSION); LOGGER.info(ModInfo.READABLE_NAME + ", Version: " + ModInfo.VERSION);
if (printGitInfo) // if the build is stable the branch/commit/etc shouldn't be needed
if (ModInfo.IS_DEV_BUILD)
{ {
// Useful for dev builds
LOGGER.info("DH Branch: " + ModJarInfo.Git_Branch); LOGGER.info("DH Branch: " + ModJarInfo.Git_Branch);
LOGGER.info("DH Commit: " + ModJarInfo.Git_Commit); LOGGER.info("DH Commit: " + ModJarInfo.Git_Commit);
LOGGER.info("DH Jar Build Source: " + ModJarInfo.Build_Source); LOGGER.info("DH Jar Build Source: " + ModJarInfo.Build_Source);
@@ -166,7 +194,136 @@ public abstract class AbstractModInitializer
LOGGER.info("Mod Post-Initialized"); LOGGER.info("Mod Post-Initialized");
} }
private void initCommands() { /* currently unimplemented */ } @SuppressWarnings({"rawtypes", "unchecked"})
private void initCommands()
{
LiteralArgumentBuilder<CommandSourceStack> builder = literal("dhconfig")
.requires(source -> source.hasPermission(4));
for (AbstractConfigType<?, ?> type : ConfigBase.INSTANCE.entries)
{
if (!(type instanceof ConfigEntry))
{
continue;
}
//noinspection PatternVariableCanBeUsed
ConfigEntry configEntry = (ConfigEntry) type;
if (configEntry.getServersideShortName() == null)
{
continue;
}
Function<
Function<CommandContext<CommandSourceStack>, Object>,
Command<CommandSourceStack>
> makeConfigUpdater = (getter) -> (commandContext) -> {
Object value = getter.apply(commandContext);
commandContext.getSource().sendSuccess(
#if MC_VER >= MC_1_20_1
() -> Component.literal("Changed the value of "+configEntry.getServersideShortName()+" to "+value),
#elif MC_VER >= MC_1_19_2
Component.literal("Changed the value of "+configEntry.getServersideShortName()+" to "+value),
#else
new TranslatableComponent("Changed the value of "+configEntry.getServersideShortName()+" to "+value),
#endif
true);
configEntry.set(value);
return 1;
};
LiteralArgumentBuilder<CommandSourceStack> subcommand = literal(configEntry.getServersideShortName())
.executes((commandContext) -> {
#if MC_VER >= MC_1_20_1
commandContext.getSource().sendSuccess(() -> Component.literal("Current value of "+configEntry.getServersideShortName()+" is "+configEntry.get()), true);
#elif MC_VER >= MC_1_19_2
commandContext.getSource().sendSuccess(Component.literal("Current value of "+configEntry.getServersideShortName()+" is "+configEntry.get()), true);
#else // < 1.19.2
commandContext.getSource().sendSuccess(new TranslatableComponent("Current value of "+configEntry.getServersideShortName()+" is "+configEntry.get()), true);
#endif
return 1;
});
if (Enum.class.isAssignableFrom(configEntry.getType()))
{
for (Object choice : configEntry.getType().getEnumConstants())
{
subcommand.then(
literal(choice.toString())
.executes(makeConfigUpdater.apply(c -> choice))
);
}
}
else
{
boolean setterAdded = false;
for (java.util.Map.Entry<Class<?>, Pair<Supplier<ArgumentType<?>>, BiFunction<CommandContext<?>, String, ?>>> pair : new HashMap<
Class<?>,
Pair<
Supplier<ArgumentType<?>>,
BiFunction<CommandContext<?>, String, ?>>
>() {{
this.put(Integer.class, new Pair<>(() -> integer((int) configEntry.getMin(), (int) configEntry.getMax()), IntegerArgumentType::getInteger));
this.put(Double.class, new Pair<>(() -> doubleArg((double) configEntry.getMin(), (double) configEntry.getMax()), DoubleArgumentType::getDouble));
this.put(Boolean.class, new Pair<>(BoolArgumentType::bool, BoolArgumentType::getBool));
this.put(String.class, new Pair<>(StringArgumentType::string, StringArgumentType::getString));
}}.entrySet())
{
if (!pair.getKey().isAssignableFrom(configEntry.getType()))
{
continue;
}
subcommand.then(argument("value", pair.getValue().first.get())
.executes(makeConfigUpdater.apply(c -> pair.getValue().second.apply(c, "value"))));
setterAdded = true;
break;
}
if (!setterAdded)
{
throw new RuntimeException("Config type of "+type.getName()+" is not supported: "+configEntry.getType().getSimpleName());
}
}
builder.then(subcommand);
}
this.commandDispatcher.register(builder);
if (DEBUG_CODEC_CRASH_MESSAGE)
{
LiteralArgumentBuilder<CommandSourceStack> dhcrash = literal("dhcrash")
.requires(source -> source.hasPermission(4))
.then(literal("encode")
.executes(c -> {
assert SharedApi.getIDhServerWorld() != null;
((DhServerWorld) SharedApi.getIDhServerWorld()).remotePlayerConnectionHandler
#if MC_VER >= MC_1_19_2
.getConnectedPlayer(ServerPlayerWrapper.getWrapper(Objects.requireNonNull(c.getSource().getPlayer())))
#else
.getConnectedPlayer(ServerPlayerWrapper.getWrapper(Objects.requireNonNull(c.getSource().getPlayerOrException())))
#endif
.networkSession.sendMessage(new CodecCrashMessage(CodecCrashMessage.ECrashPhase.ENCODE));
return 1;
}))
.then(literal("decode")
.executes(c -> {
assert SharedApi.getIDhServerWorld() != null;
((DhServerWorld) SharedApi.getIDhServerWorld()).remotePlayerConnectionHandler
#if MC_VER >= MC_1_19_2
.getConnectedPlayer(ServerPlayerWrapper.getWrapper(Objects.requireNonNull(c.getSource().getPlayer())))
#else
.getConnectedPlayer(ServerPlayerWrapper.getWrapper(Objects.requireNonNull(c.getSource().getPlayerOrException())))
#endif
.networkSession.sendMessage(new CodecCrashMessage(CodecCrashMessage.ECrashPhase.DECODE));
return 1;
}));
this.commandDispatcher.register(dhcrash);
}
}
@@ -0,0 +1,113 @@
package com.seibel.distanthorizons.common;
import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.core.logging.ConfigBasedLogger;
import com.seibel.distanthorizons.core.network.event.internal.IncompatibleMessageInternalEvent;
import com.seibel.distanthorizons.core.network.event.internal.ProtocolErrorInternalEvent;
import com.seibel.distanthorizons.core.network.messages.MessageRegistry;
import com.seibel.distanthorizons.core.network.messages.AbstractNetworkMessage;
import com.seibel.distanthorizons.core.network.messages.base.CloseReasonMessage;
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IPluginPacketSender;
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IServerPlayerWrapper;
import com.seibel.distanthorizons.coreapi.ModInfo;
import io.netty.buffer.ByteBufUtil;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerPlayer;
import org.apache.logging.log4j.LogManager;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.util.Objects;
public abstract class AbstractPluginPacketSender implements IPluginPacketSender
{
private static final ConfigBasedLogger LOGGER = new ConfigBasedLogger(LogManager.getLogger(),
() -> Config.Client.Advanced.Logging.logNetworkEvent.get());
#if MC_VER >= MC_1_21_1
public static final ResourceLocation WRAPPER_PACKET_RESOURCE = ResourceLocation.fromNamespaceAndPath(ModInfo.RESOURCE_NAMESPACE, ModInfo.WRAPPER_PACKET_PATH);
#else
public static final ResourceLocation WRAPPER_PACKET_RESOURCE = new ResourceLocation(ModInfo.RESOURCE_NAMESPACE, ModInfo.WRAPPER_PACKET_PATH);
#endif
@Override
public final void sendToClient(IServerPlayerWrapper serverPlayer, AbstractNetworkMessage message)
{
this.sendToClient((ServerPlayer) serverPlayer.getWrappedMcObject(), message);
}
public abstract void sendToClient(ServerPlayer serverPlayer, AbstractNetworkMessage message);
@Override
public abstract void sendToServer(AbstractNetworkMessage message);
public static AbstractNetworkMessage decodeMessage(FriendlyByteBuf in)
{
AbstractNetworkMessage message = null;
try
{
in.markReaderIndex();
int protocolVersion = in.readShort();
if (protocolVersion != ModInfo.PROTOCOL_VERSION)
{
return new IncompatibleMessageInternalEvent(protocolVersion);
}
message = MessageRegistry.INSTANCE.createMessage(in.readUnsignedShort());
message.decode(in);
if (in.isReadable())
{
throw new IOException("Buffer has not been fully read");
}
return message;
}
catch (Exception e)
{
in.resetReaderIndex();
LOGGER.error("Failed to decode message", e);
LOGGER.error("Buffer: ["+in+"]");
LOGGER.error("Buffer contents: ["+ByteBufUtil.hexDump(in)+"]");
return new ProtocolErrorInternalEvent(e, message, true);
}
finally
{
// Prevent connection crashing if not entire buffer has been read
in.readerIndex(in.writerIndex());
}
}
public static void encodeMessage(FriendlyByteBuf out, AbstractNetworkMessage message)
{
// This is intentionally unhandled, because errors related to this are unlikely to appear in wild
Objects.requireNonNull(message);
out.writeShort(ModInfo.PROTOCOL_VERSION);
try
{
out.markWriterIndex();
out.writeShort(MessageRegistry.INSTANCE.getMessageId(message));
message.encode(out);
}
catch (Exception e)
{
LOGGER.error("Failed to encode message", e);
LOGGER.error("Message: ["+message+"]");
message.getSession().tryHandleMessage(new ProtocolErrorInternalEvent(e, message, false));
// Encode close reason message instead
out.resetWriterIndex();
message = new CloseReasonMessage("Internal error on other side");
out.writeShort(MessageRegistry.INSTANCE.getMessageId(message));
message.encode(out);
}
}
}
@@ -0,0 +1,36 @@
package com.seibel.distanthorizons.common;
#if MC_VER >= MC_1_20_6
import com.seibel.distanthorizons.core.network.messages.AbstractNetworkMessage;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public record CommonPacketPayload(@Nullable AbstractNetworkMessage message) implements CustomPacketPayload
{
public static final Type<CommonPacketPayload> TYPE = new Type<>(AbstractPluginPacketSender.WRAPPER_PACKET_RESOURCE);
@NotNull
@Override
public Type<? extends CustomPacketPayload> type() { return TYPE; }
public static class Codec implements StreamCodec<FriendlyByteBuf, CommonPacketPayload>
{
@NotNull
@Override
public CommonPacketPayload decode(@NotNull FriendlyByteBuf in)
{ return new CommonPacketPayload(AbstractPluginPacketSender.decodeMessage(in)); }
@Override
public void encode(@NotNull FriendlyByteBuf out, CommonPacketPayload payload)
{ AbstractPluginPacketSender.encodeMessage(out, payload.message()); }
}
}
#endif
@@ -22,7 +22,7 @@ package com.seibel.distanthorizons.common.wrappers;
import com.seibel.distanthorizons.common.wrappers.gui.ClassicConfigGUI; import com.seibel.distanthorizons.common.wrappers.gui.ClassicConfigGUI;
import com.seibel.distanthorizons.common.wrappers.gui.LangWrapper; import com.seibel.distanthorizons.common.wrappers.gui.LangWrapper;
import com.seibel.distanthorizons.common.wrappers.level.KeyedClientLevelManager; import com.seibel.distanthorizons.common.wrappers.level.KeyedClientLevelManager;
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftDedicatedServerWrapper; import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftServerWrapper;
import com.seibel.distanthorizons.core.level.IKeyedClientLevelManager; import com.seibel.distanthorizons.core.level.IKeyedClientLevelManager;
import com.seibel.distanthorizons.core.wrapperInterfaces.config.IConfigGui; import com.seibel.distanthorizons.core.wrapperInterfaces.config.IConfigGui;
import com.seibel.distanthorizons.core.wrapperInterfaces.config.ILangWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.config.ILangWrapper;
@@ -60,7 +60,7 @@ public class DependencySetup
//@Environment(EnvType.SERVER) //@Environment(EnvType.SERVER)
public static void createServerBindings() public static void createServerBindings()
{ {
SingletonInjector.INSTANCE.bind(IMinecraftSharedWrapper.class, MinecraftDedicatedServerWrapper.INSTANCE); SingletonInjector.INSTANCE.bind(IMinecraftSharedWrapper.class, MinecraftServerWrapper.INSTANCE);
} }
//@Environment(EnvType.CLIENT) //@Environment(EnvType.CLIENT)
@@ -179,19 +179,9 @@ public class WrapperFactory implements IWrapperFactory
// level wrapper // level wrapper
ILevelWrapper levelWrapper; ILevelWrapper levelWrapper = level.isClientSide()
if (level instanceof ServerLevel) ? ClientLevelWrapper.getWrapper((ClientLevel)level)
{ : ServerLevelWrapper.getWrapper((ServerLevel)level);
levelWrapper = ServerLevelWrapper.getWrapper((ServerLevel)level);
}
else if (level instanceof ClientLevel)
{
levelWrapper = ClientLevelWrapper.getWrapper((ClientLevel)level);
}
else
{
throw new ClassCastException(createChunkWrapperErrorMessage(objectArray));
}
return new ChunkWrapper(chunk, lightSource, levelWrapper); return new ChunkWrapper(chunk, lightSource, levelWrapper);
@@ -215,7 +205,7 @@ public class WrapperFactory implements IWrapperFactory
expectedClassNames = new String[] expectedClassNames = new String[]
{ {
ChunkAccess.class.getName(), ChunkAccess.class.getName(),
ServerLevel.class.getName() + "] or [" + ClientLevel.class.getName() "[ServerLevel] or [ClientLevel]" // Classes are not referenced by names to avoid exception when one of them is missing
}; };
//#endif //#endif
@@ -54,7 +54,6 @@ import net.minecraft.core.BlockPos;
import net.minecraft.core.Registry; import net.minecraft.core.Registry;
import net.minecraft.world.level.EmptyBlockGetter; import net.minecraft.world.level.EmptyBlockGetter;
#else #else
import net.minecraft.client.Minecraft;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.registries.Registries; import net.minecraft.core.registries.Registries;
@@ -134,6 +133,26 @@ public class BlockStateWrapper implements IBlockStateWrapper
} }
} }
/**
* Can be faster than {@link BlockStateWrapper#fromBlockState(BlockState, ILevelWrapper)}
* in cases where the same block state is expected to be referenced multiple times.
*/
public static BlockStateWrapper fromBlockState(BlockState blockState, ILevelWrapper levelWrapper, IBlockStateWrapper guess)
{
BlockState guessBlockState = (guess == null || guess.isAir()) ? null : (BlockState) guess.getWrappedMcObject();
BlockState inputBlockState = (blockState == null || blockState.isAir()) ? null : blockState;
if (guess instanceof BlockStateWrapper guessWrapper
&& guessBlockState == inputBlockState)
{
return guessWrapper;
}
else
{
return fromBlockState(blockState, levelWrapper);
}
}
private BlockStateWrapper(BlockState blockState, ILevelWrapper levelWrapper) private BlockStateWrapper(BlockState blockState, ILevelWrapper levelWrapper)
{ {
this.blockState = blockState; this.blockState = blockState;
@@ -542,9 +561,8 @@ public class BlockStateWrapper implements IBlockStateWrapper
{ {
#if MC_VER > MC_1_17_1 #if MC_VER > MC_1_17_1
// use the given level if possible, otherwise try using the currently loaded one LodUtil.assertTrue(levelWrapper != null && levelWrapper.getWrappedMcObject() != null);
Level level = (levelWrapper != null ? (Level) levelWrapper.getWrappedMcObject() : null); Level level = (Level)levelWrapper.getWrappedMcObject();
level = (level == null ? Minecraft.getInstance().level : level);
#endif #endif
Block block; Block block;
@@ -21,13 +21,18 @@ package com.seibel.distanthorizons.common.wrappers.chunk;
import com.seibel.distanthorizons.common.wrappers.block.BiomeWrapper; import com.seibel.distanthorizons.common.wrappers.block.BiomeWrapper;
import com.seibel.distanthorizons.common.wrappers.block.BlockStateWrapper; import com.seibel.distanthorizons.common.wrappers.block.BlockStateWrapper;
import com.seibel.distanthorizons.common.wrappers.misc.MutableBlockPosWrapper;
import com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject.DhLitWorldGenRegion; import com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject.DhLitWorldGenRegion;
import com.seibel.distanthorizons.core.api.internal.SharedApi;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos; import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos;
import com.seibel.distanthorizons.core.pos.DhChunkPos; import com.seibel.distanthorizons.core.pos.DhChunkPos;
import com.seibel.distanthorizons.core.util.LodUtil;
import com.seibel.distanthorizons.core.world.EWorldEnvironment;
import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.ChunkLightStorage; import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.ChunkLightStorage;
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IMutableBlockPosWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IBiomeWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IBiomeWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
@@ -84,6 +89,7 @@ public class ChunkWrapper implements IChunkWrapper
/** can be used for interactions with the underlying chunk where creating new BlockPos objects could cause issues for the garbage collector. */ /** can be used for interactions with the underlying chunk where creating new BlockPos objects could cause issues for the garbage collector. */
private static final ThreadLocal<BlockPos.MutableBlockPos> MUTABLE_BLOCK_POS_REF = ThreadLocal.withInitial(() -> new BlockPos.MutableBlockPos()); private static final ThreadLocal<BlockPos.MutableBlockPos> MUTABLE_BLOCK_POS_REF = ThreadLocal.withInitial(() -> new BlockPos.MutableBlockPos());
private static final ThreadLocal<MutableBlockPosWrapper> MUTABLE_BLOCK_POS_WRAPPER_REF = ThreadLocal.withInitial(() -> new MutableBlockPosWrapper());
private final ChunkAccess chunk; private final ChunkAccess chunk;
@@ -91,7 +97,8 @@ public class ChunkWrapper implements IChunkWrapper
private final LevelReader lightSource; private final LevelReader lightSource;
private final ILevelWrapper wrappedLevel; private final ILevelWrapper wrappedLevel;
private boolean isDhLightCorrect = false; private boolean isDhBlockLightCorrect = false;
private boolean isDhSkyLightCorrect = false;
/** only used when connected to a dedicated server */ /** only used when connected to a dedicated server */
private boolean isMcClientLightingCorrect = false; private boolean isMcClientLightingCorrect = false;
@@ -100,26 +107,9 @@ public class ChunkWrapper implements IChunkWrapper
private ArrayList<DhBlockPos> blockLightPosList = null; private ArrayList<DhBlockPos> blockLightPosList = null;
private boolean useDhLighting;
private int minNonEmptyHeight = Integer.MIN_VALUE; private int minNonEmptyHeight = Integer.MIN_VALUE;
private int maxNonEmptyHeight = Integer.MAX_VALUE; private int maxNonEmptyHeight = Integer.MAX_VALUE;
private int blockBiomeHashCode = 0;
/**
* Due to vanilla `isClientLightReady()` not being designed for use by a non-render thread, it may return 'true'
* before the light engine has ticked, (right after all light changes is marked by the engine to be processed).
* To fix this, on client-only mode, we mixin-redirect the `isClientLightReady()` so that after the call, it will
* trigger a synchronous update of this flag here on all chunks that are wrapped. <br><br>
*
* Note: Using a static weak hash map to store the chunks that need to be updated, as instance of chunk wrapper
* can be duplicated, with same chunk instance. And the data stored here are all temporary, and thus will not be
* visible when a chunk is re-wrapped later. <br>
* (Also, thread safety done via a reader writer lock)
*/
private static final ConcurrentLinkedQueue<ChunkWrapper> chunksNeedingClientLightUpdating = new ConcurrentLinkedQueue<>();
//=============// //=============//
@@ -133,14 +123,6 @@ public class ChunkWrapper implements IChunkWrapper
this.wrappedLevel = wrappedLevel; this.wrappedLevel = wrappedLevel;
this.chunkPos = new DhChunkPos(chunk.getPos().x, chunk.getPos().z); this.chunkPos = new DhChunkPos(chunk.getPos().x, chunk.getPos().z);
// TODO is this the best way to differentiate between when we are generating chunks and when MC gave us a chunk?
boolean isDhGeneratedChunk = (this.lightSource.getClass() == DhLitWorldGenRegion.class);
// MC loaded chunks should get their lighting from MC, DH generated chunks should get their lighting from DH
this.useDhLighting = isDhGeneratedChunk;
// FIXME +1 is to handle the fact that LodDataBuilder adds +1 to all block lighting calculations, also done in the relative position validator
chunksNeedingClientLightUpdating.add(this);
} }
@@ -297,6 +279,22 @@ public class ChunkWrapper implements IChunkWrapper
return BlockStateWrapper.fromBlockState(this.chunk.getBlockState(blockPos), this.wrappedLevel); return BlockStateWrapper.fromBlockState(this.chunk.getBlockState(blockPos), this.wrappedLevel);
} }
@Override
public IBlockStateWrapper getBlockState(int relX, int relY, int relZ, IMutableBlockPosWrapper mcBlockPos, IBlockStateWrapper guess)
{
this.throwIndexOutOfBoundsIfRelativePosOutsideChunkBounds(relX, relY, relZ);
BlockPos.MutableBlockPos pos = (BlockPos.MutableBlockPos)mcBlockPos.getWrappedMcObject();
pos.setX(relX);
pos.setY(relY);
pos.setZ(relZ);
return BlockStateWrapper.fromBlockState(this.chunk.getBlockState(pos), this.wrappedLevel, guess);
}
@Override
public IMutableBlockPosWrapper getMutableBlockPosWrapper() { return MUTABLE_BLOCK_POS_WRAPPER_REF.get(); }
@Override @Override
public DhChunkPos getChunkPos() { return this.chunkPos; } public DhChunkPos getChunkPos() { return this.chunkPos; }
@@ -328,44 +326,14 @@ public class ChunkWrapper implements IChunkWrapper
//==========// //==========//
@Override @Override
public void setIsDhLightCorrect(boolean isDhLightCorrect) { this.isDhLightCorrect = isDhLightCorrect; } public void setIsDhSkyLightCorrect(boolean isDhLightCorrect) { this.isDhSkyLightCorrect = isDhLightCorrect; }
@Override
public void setIsDhBlockLightCorrect(boolean isDhLightCorrect) { this.isDhBlockLightCorrect = isDhLightCorrect; }
@Override @Override
public void setUseDhLighting(boolean useDhLighting) { this.useDhLighting = useDhLighting; } public boolean isDhBlockLightingCorrect() { return this.isDhBlockLightCorrect; }
@Override @Override
public boolean isLightCorrect() public boolean isDhSkyLightCorrect() { return this.isDhSkyLightCorrect; }
{
if (this.useDhLighting)
{
return this.isDhLightCorrect;
}
#if MC_VER == MC_1_16_5 || MC_VER == MC_1_17_1
return false; // MC's lighting engine doesn't work consistently enough to trust for 1.16 or 1.17
#else
if (this.chunk instanceof LevelChunk)
{
LevelChunk levelChunk = (LevelChunk) this.chunk;
if (levelChunk.getLevel() instanceof ClientLevel)
{
// connected to a server
return this.isMcClientLightingCorrect;
}
else
{
// in a single player world
return this.chunk.isLightCorrect() && levelChunk.loaded;
}
}
else
{
// called when in a single player world and the chunk is a proto chunk (in world gen, and not active)
return this.chunk.isLightCorrect();
}
#endif
}
@Override @Override
@@ -420,44 +388,6 @@ public class ChunkWrapper implements IChunkWrapper
public void setSkyLightStorage(ChunkLightStorage lightStorage) { this.skyLightStorage = lightStorage; } public void setSkyLightStorage(ChunkLightStorage lightStorage) { this.skyLightStorage = lightStorage; }
@Override
public int getBlockLight(int relX, int y, int relZ)
{
this.throwIndexOutOfBoundsIfRelativePosOutsideChunkBounds(relX, y, relZ);
// use the full lighting engine when the chunks are within render distance or the config requests it
if (this.useDhLighting)
{
// DH lighting method
return this.getBlockLightStorage().get(relX, y, relZ);
}
else
{
// note: this returns 0 if the chunk is unload
// MC lighting method
return this.lightSource.getBrightness(LightLayer.BLOCK, new BlockPos(relX + this.getMinBlockX(), y, relZ + this.getMinBlockZ()));
}
}
@Override
public int getSkyLight(int relX, int y, int relZ)
{
this.throwIndexOutOfBoundsIfRelativePosOutsideChunkBounds(relX, y, relZ);
// use the full lighting engine when the chunks are within render distance or the config requests it
if (this.useDhLighting)
{
// DH lighting method
return this.getSkyLightStorage().get(relX, y, relZ);
}
else
{
// MC lighting method
return this.lightSource.getBrightness(LightLayer.SKY, new BlockPos(relX + this.getMinBlockX(), y, relZ + this.getMinBlockZ()));
}
}
/** /**
* FIXME synchronized is necessary for a rare issue where this method is called from two separate threads at the same time * FIXME synchronized is necessary for a rare issue where this method is called from two separate threads at the same time
* before the list has finished populating. * before the list has finished populating.
@@ -493,63 +423,6 @@ public class ChunkWrapper implements IChunkWrapper
return this.blockLightPosList; return this.blockLightPosList;
} }
public static void syncedUpdateClientLightStatus()
{
#if MC_VER < MC_1_18_2
// TODO: Check what to do in 1.18.1 and older
// since we don't currently handle this list,
// clear it to prevent memory leaks
chunksNeedingClientLightUpdating.clear();
#else
// update the chunks client lighting
ChunkWrapper chunkWrapper = chunksNeedingClientLightUpdating.poll();
while (chunkWrapper != null)
{
chunkWrapper.updateIsClientLightingCorrect();
chunkWrapper = chunksNeedingClientLightUpdating.poll();
}
#endif
}
/** Should be called after client light updates are triggered. */
private void updateIsClientLightingCorrect()
{
if (this.chunk instanceof LevelChunk && ((LevelChunk) this.chunk).getLevel() instanceof ClientLevel)
{
LevelChunk levelChunk = (LevelChunk) this.chunk;
ClientChunkCache clientChunkCache = ((ClientLevel) levelChunk.getLevel()).getChunkSource();
this.isMcClientLightingCorrect = clientChunkCache.getChunkForLighting(this.chunk.getPos().x, this.chunk.getPos().z) != null &&
#if MC_VER <= MC_1_17_1
levelChunk.isLightCorrect();
#elif MC_VER < MC_1_20_1
levelChunk.isClientLightReady();
#else
checkLightSectionsOnChunk(levelChunk, levelChunk.getLevel().getLightEngine());
#endif
}
}
#if MC_VER >= MC_1_20_1
private static boolean checkLightSectionsOnChunk(LevelChunk chunk, LevelLightEngine engine)
{
LevelChunkSection[] sections = chunk.getSections();
int minY = chunk.getMinSection();
int maxY = chunk.getMaxSection();
for (int y = minY; y < maxY; ++y)
{
LevelChunkSection section = sections[chunk.getSectionIndexFromSectionY(y)];
if (section.hasOnlyAir()) continue;
if (!engine.lightOnInSection(SectionPos.of(chunk.getPos(), y)))
{
return false;
}
}
return true;
}
#endif
//===============// //===============//
@@ -1,21 +1,19 @@
package com.seibel.distanthorizons.common.wrappers.level; 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.IServerKeyedClientLevel;
import com.seibel.distanthorizons.core.level.IKeyedClientLevelManager; import com.seibel.distanthorizons.core.level.IKeyedClientLevelManager;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.multiplayer.ClientLevel;
import org.jetbrains.annotations.Nullable;
import java.util.Objects;
public class KeyedClientLevelManager implements IKeyedClientLevelManager public class KeyedClientLevelManager implements IKeyedClientLevelManager
{ {
public static final KeyedClientLevelManager INSTANCE = new KeyedClientLevelManager(); public static final KeyedClientLevelManager INSTANCE = new KeyedClientLevelManager();
/** This is set and managed by the ClientApi for servers with support for DH. */ /** This is set and managed by the ClientApi for servers with support for DH. */
private IServerKeyedClientLevel overrideWrapper = null; @Nullable
private boolean useOverrideWrapper = false; private IServerKeyedClientLevel serverKeyedLevel = null;
//=============// //=============//
@@ -31,24 +29,20 @@ public class KeyedClientLevelManager implements IKeyedClientLevelManager
//======================// //======================//
@Override @Override
public void setServerKeyedLevel(IServerKeyedClientLevel clientLevel) { this.overrideWrapper = clientLevel; } @Nullable
@Override public IServerKeyedClientLevel getServerKeyedLevel() { return this.serverKeyedLevel; }
public IServerKeyedClientLevel getOverrideWrapper() { return this.overrideWrapper; }
@Override @Override
public IServerKeyedClientLevel getServerKeyedLevel(ILevelWrapper level, String serverLevelKey) public IServerKeyedClientLevel setServerKeyedLevel(IClientLevelWrapper clientLevel, String levelKey)
{ {
Objects.requireNonNull(level); IServerKeyedClientLevel keyedLevel = new ServerKeyedClientLevel((ClientLevel) clientLevel.getWrappedMcObject(), levelKey);
Objects.requireNonNull(serverLevelKey); this.serverKeyedLevel = keyedLevel;
return new ServerKeyedClientLevel((ClientLevel) level.getWrappedMcObject(), serverLevelKey); return keyedLevel;
} }
@Override @Override
public void setUseOverrideWrapper(boolean useOverrideWrapper) { this.useOverrideWrapper = useOverrideWrapper; } public void clearKeyedLevel() { this.serverKeyedLevel = null; }
@Override @Override
public boolean getUseOverrideWrapper() { return this.useOverrideWrapper; } public boolean hasLevelSet() { return this.serverKeyedLevel != null; }
} }
@@ -18,4 +18,7 @@ public class ServerKeyedClientLevel extends ClientLevelWrapper implements IServe
@Override @Override
public String getServerLevelKey() { return this.serverLevelKey; } public String getServerLevelKey() { return this.serverLevelKey; }
@Override
public String getDimensionName() { return this.getServerLevelKey(); }
} }
@@ -44,6 +44,7 @@ import com.seibel.distanthorizons.core.pos.DhChunkPos;
import net.minecraft.CrashReport; import net.minecraft.CrashReport;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.multiplayer.ServerData; import net.minecraft.client.multiplayer.ServerData;
import net.minecraft.client.player.LocalPlayer; import net.minecraft.client.player.LocalPlayer;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
@@ -220,14 +221,19 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
@Nullable @Nullable
@Override @Override
public IClientLevelWrapper getWrappedClientLevel() public IClientLevelWrapper getWrappedClientLevel() { return this.getWrappedClientLevel(false); }
@Override
@Nullable
public IClientLevelWrapper getWrappedClientLevel(boolean bypassLevelKeyManager)
{ {
if (MINECRAFT.level == null) ClientLevel level = MINECRAFT.level;
if (level == null)
{ {
return null; return null;
} }
return ClientLevelWrapper.getWrapperIgnoringOverride(MINECRAFT.level); return ClientLevelWrapper.getWrapper(level, bypassLevelKeyManager);
} }
@Override @Override
@@ -266,7 +272,10 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
public void sendChatMessage(String string) public void sendChatMessage(String string)
{ {
LocalPlayer player = this.getPlayer(); LocalPlayer player = this.getPlayer();
if (player == null) return; if (player == null)
{
return;
}
#if MC_VER < MC_1_19_2 #if MC_VER < MC_1_19_2
player.sendMessage(new TextComponent(string), getPlayer().getUUID()); player.sendMessage(new TextComponent(string), getPlayer().getUUID());
#else #else
@@ -306,4 +315,7 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
@Override @Override
public void executeOnRenderThread(Runnable runnable) { MINECRAFT.execute(runnable); } public void executeOnRenderThread(Runnable runnable) { MINECRAFT.execute(runnable); }
@Override
public boolean isWorldNew() { throw new UnsupportedOperationException("Not Implemented"); }
} }
@@ -6,19 +6,34 @@ import net.minecraft.server.dedicated.DedicatedServer;
import java.io.File; import java.io.File;
//@Environment(EnvType.SERVER) //@Environment(EnvType.SERVER)
public class MinecraftDedicatedServerWrapper implements IMinecraftSharedWrapper public class MinecraftServerWrapper implements IMinecraftSharedWrapper
{ {
public static final MinecraftDedicatedServerWrapper INSTANCE = new MinecraftDedicatedServerWrapper(); public static final MinecraftServerWrapper INSTANCE = new MinecraftServerWrapper();
private MinecraftDedicatedServerWrapper() { }
public DedicatedServer dedicatedServer = null; public DedicatedServer dedicatedServer = null;
//=============//
// constructor //
//=============//
private MinecraftServerWrapper() { }
//=========//
// methods //
//=========//
@Override @Override
public boolean isDedicatedServer() { return true; } public boolean isDedicatedServer() { return true; }
@Override @Override
public File getInstallationDirectory() public File getInstallationDirectory()
{ {
if (this.dedicatedServer == null) if (this.dedicatedServer == null)
{ {
throw new IllegalStateException("Trying to get Installation Direction before Dedicated server complete initialization!"); throw new IllegalStateException("Trying to get Installation Direction before Dedicated server completed initialization!");
} }
#if MC_VER < MC_1_21_1 #if MC_VER < MC_1_21_1
@@ -28,4 +43,8 @@ public class MinecraftDedicatedServerWrapper implements IMinecraftSharedWrapper
#endif #endif
} }
@Override
public boolean isWorldNew()
{ return this.dedicatedServer.getWorldData().overworldData().isInitialized(); }
} }
@@ -0,0 +1,15 @@
package com.seibel.distanthorizons.common.wrappers.misc;
import net.minecraft.server.level.ServerLevel;
import org.jetbrains.annotations.Nullable;
public interface IMixinServerPlayer
{
@Nullable
ServerLevel distantHorizons$getDimensionChangeDestination();
#if MC_VER == MC_1_16_5
void distantHorizons$setDimensionChangeDestination(ServerLevel dimensionChangeDestination);
#endif
}
@@ -0,0 +1,30 @@
package com.seibel.distanthorizons.common.wrappers.misc;
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IMutableBlockPosWrapper;
import net.minecraft.core.BlockPos;
public class MutableBlockPosWrapper implements IMutableBlockPosWrapper
{
public final BlockPos.MutableBlockPos pos;
//=============//
// constructor //
//=============//
public MutableBlockPosWrapper()
{
this.pos = new BlockPos.MutableBlockPos();
}
//===========//
// overrides //
//===========//
@Override
public Object getWrappedMcObject() { return this.pos; }
}
@@ -1,54 +1,115 @@
package com.seibel.distanthorizons.common.wrappers.misc; package com.seibel.distanthorizons.common.wrappers.misc;
import com.google.common.base.Objects;
import com.google.common.collect.MapMaker; import com.google.common.collect.MapMaker;
import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper; import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IServerPlayerWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IServerPlayerWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper;
import com.seibel.distanthorizons.core.util.math.Vec3d;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.network.ServerGamePacketListenerImpl;
import net.minecraft.world.phys.Vec3;
import java.util.UUID; import java.net.SocketAddress;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
/**
* This wrapper transparently ensures that the underlying {@link ServerPlayer} is always valid,
* unless the player has disconnected.
*/
public class ServerPlayerWrapper implements IServerPlayerWrapper public class ServerPlayerWrapper implements IServerPlayerWrapper
{ {
private static final ConcurrentMap<ServerPlayer, ServerPlayerWrapper> private static final ConcurrentMap<ServerGamePacketListenerImpl, ServerPlayerWrapper> serverPlayerWrapperMap = new MapMaker().weakKeys().weakValues().makeMap();
serverPlayerWrapperMap = new MapMaker().weakKeys().makeMap();
private final ServerPlayer serverPlayer; private final ServerGamePacketListenerImpl connection;
//=============//
// constructor //
//=============//
public static ServerPlayerWrapper getWrapper(ServerPlayer serverPlayer) public static ServerPlayerWrapper getWrapper(ServerPlayer serverPlayer)
{ { return serverPlayerWrapperMap.computeIfAbsent(serverPlayer.connection, ignored -> new ServerPlayerWrapper(serverPlayer.connection)); }
return serverPlayerWrapperMap.computeIfAbsent(serverPlayer, ServerPlayerWrapper::new);
}
private ServerPlayerWrapper(ServerPlayer serverPlayer) private ServerPlayerWrapper(ServerGamePacketListenerImpl connection) { this.connection = connection; }
{
this.serverPlayer = serverPlayer;
}
public UUID getUUID()
{
return serverPlayer.getUUID();
}
//=========//
// getters //
//=========//
private ServerPlayer getServerPlayer() { return this.connection.player; }
@Override
public String getName() { return this.getServerPlayer().getName().getString(); }
@Override
public IServerLevelWrapper getLevel() public IServerLevelWrapper getLevel()
{ {
#if MC_VER < MC_1_20_1 ServerLevel level = ((IMixinServerPlayer) this.getServerPlayer()).distantHorizons$getDimensionChangeDestination();
return ServerLevelWrapper.getWrapper(this.serverPlayer.getLevel()); if (level == null)
#else {
return ServerLevelWrapper.getWrapper(this.serverPlayer.serverLevel()); #if MC_VER < MC_1_20_1
#endif level = this.getServerPlayer().getLevel();
} #else
level = this.getServerPlayer().serverLevel();
#endif
}
public Object getWrappedMcObject() return ServerLevelWrapper.getWrapper(level);
{
return serverPlayer;
} }
@Override @Override
public String toString() public Vec3d getPosition()
{ {
return "Wrapped{" + serverPlayer.toString() + "}"; Vec3 position = this.getServerPlayer().position();
return new Vec3d(position.x, position.y, position.z);
} }
@Override
public int getViewDistance() { return this.getServerPlayer().server.getPlayerList().getViewDistance(); }
@Override
public SocketAddress getRemoteAddress()
{
#if MC_VER >= MC_1_19_4
return this.getServerPlayer().connection.getRemoteAddress();
#else // < 1.19.4
return this.getServerPlayer().connection.connection.getRemoteAddress();
#endif
}
//================//
// base overrides //
//================//
@Override
public Object getWrappedMcObject() { return this.getServerPlayer(); }
@Override
public String toString() { return "Wrapped{" + this.getServerPlayer() + "}"; }
@Override
public boolean equals(Object obj)
{
if (this == obj)
{
return true;
}
if (!(obj instanceof ServerPlayerWrapper))
{
return false;
}
ServerPlayerWrapper that = (ServerPlayerWrapper) obj;
return Objects.equal(this.connection, that.connection);
}
@Override
public int hashCode() { return Objects.hashCode(this.connection); }
} }
@@ -9,6 +9,7 @@ import com.seibel.distanthorizons.common.wrappers.block.ClientBlockStateColorCac
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper; import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.level.*; import com.seibel.distanthorizons.core.level.*;
import com.seibel.distanthorizons.core.level.IServerKeyedClientLevel;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos; import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos;
import com.seibel.distanthorizons.core.pos.DhChunkPos; import com.seibel.distanthorizons.core.pos.DhChunkPos;
@@ -69,23 +70,28 @@ public class ClientLevelWrapper implements IClientLevelWrapper
// wrapper logic // // wrapper logic //
//===============// //===============//
public static IClientLevelWrapper getWrapper(@NotNull ClientLevel level) { return getWrapper(level, false); }
@Nullable @Nullable
public static IClientLevelWrapper getWrapper(@Nullable ClientLevel level) public static IClientLevelWrapper getWrapper(@Nullable ClientLevel level, boolean bypassLevelKeyManager)
{ {
if (level == null) if (!bypassLevelKeyManager)
{ {
return null; if (level == null)
{
return null;
}
// used if the client is connected to a server that defines the currently loaded level
IServerKeyedClientLevel overrideLevel = KEYED_CLIENT_LEVEL_MANAGER.getServerKeyedLevel();
if (overrideLevel != null)
{
return overrideLevel;
}
} }
// used if the client is connected to a server that defines the currently loaded level return LEVEL_WRAPPER_BY_CLIENT_LEVEL.computeIfAbsent(level, ClientLevelWrapper::new);
if (KEYED_CLIENT_LEVEL_MANAGER.getUseOverrideWrapper())
{
return KEYED_CLIENT_LEVEL_MANAGER.getOverrideWrapper();
}
return getWrapperIgnoringOverride(level);
} }
public static IClientLevelWrapper getWrapperIgnoringOverride(@NotNull ClientLevel level) { return LEVEL_WRAPPER_BY_CLIENT_LEVEL.computeIfAbsent(level, ClientLevelWrapper::new); }
@Nullable @Nullable
@Override @Override
@@ -118,8 +124,6 @@ public class ClientLevelWrapper implements IClientLevelWrapper
} }
} }
//====================// //====================//
// base level methods // // base level methods //
//====================// //====================//
@@ -180,6 +184,10 @@ public class ClientLevelWrapper implements IClientLevelWrapper
@Override @Override
public IDimensionTypeWrapper getDimensionType() { return DimensionTypeWrapper.getDimensionTypeWrapper(this.level.dimensionType()); } public IDimensionTypeWrapper getDimensionType() { return DimensionTypeWrapper.getDimensionTypeWrapper(this.level.dimensionType()); }
@Override
public String getDimensionName() { return this.level.dimension().location().toString(); }
@Override @Override
public EDhApiLevelType getLevelType() { return EDhApiLevelType.CLIENT_LEVEL; } public EDhApiLevelType getLevelType() { return EDhApiLevelType.CLIENT_LEVEL; }
@@ -288,7 +296,7 @@ public class ClientLevelWrapper implements IClientLevelWrapper
return "Wrapped{null}"; return "Wrapped{null}";
} }
return "Wrapped{" + this.level.toString() + "@" + this.getDimensionType().getDimensionName() + "}"; return "Wrapped{" + this.level.toString() + "@" + this.getDimensionName() + "}";
} }
} }
@@ -44,7 +44,9 @@ public class DimensionTypeWrapper implements IDimensionTypeWrapper
{ {
//first we check if the biome has already been wrapped //first we check if the biome has already been wrapped
if (dimensionTypeWrapperMap.containsKey(dimensionType) && dimensionTypeWrapperMap.get(dimensionType) != null) if (dimensionTypeWrapperMap.containsKey(dimensionType) && dimensionTypeWrapperMap.get(dimensionType) != null)
{
return dimensionTypeWrapperMap.get(dimensionType); return dimensionTypeWrapperMap.get(dimensionType);
}
//if it hasn't been created yet, we create it and save it in the map //if it hasn't been created yet, we create it and save it in the map
@@ -61,22 +63,26 @@ public class DimensionTypeWrapper implements IDimensionTypeWrapper
} }
@Override private String getDimensionName()
public String getDimensionName()
{ {
return dimensionType.effectsLocation().getPath(); #if MC_VER <= MC_1_16_5
// effectsLocation() is marked as client only, so using the backing field directly
return dimensionType.effectsLocation.getPath();
#else
return this.dimensionType.effectsLocation().getPath();
#endif
} }
@Override @Override
public boolean hasCeiling() public boolean hasCeiling()
{ {
return dimensionType.hasCeiling(); return this.dimensionType.hasCeiling();
} }
@Override @Override
public boolean hasSkyLight() public boolean hasSkyLight()
{ {
return dimensionType.hasSkyLight(); return this.dimensionType.hasSkyLight();
} }
@Override @Override
@@ -85,7 +91,9 @@ public class DimensionTypeWrapper implements IDimensionTypeWrapper
return this.dimensionType; return this.dimensionType;
} }
// there's definitely a better way of doing this, but it should work well enough for now
@Override
public boolean isTheEnd() { return this.getDimensionName().equalsIgnoreCase("the_end"); }
@Override @Override
public boolean equals(Object obj) public boolean equals(Object obj)
@@ -81,42 +81,27 @@ public class ServerLevelWrapper implements IServerLevelWrapper
//=========// //=========//
@Override @Override
public File getSaveFolder() public File getSaveFolder() { return this.level.getChunkSource().getDataStorage().dataFolder; }
{
return level.getChunkSource().getDataStorage().dataFolder;
}
@Override @Override
public DimensionTypeWrapper getDimensionType() public DimensionTypeWrapper getDimensionType() { return DimensionTypeWrapper.getDimensionTypeWrapper(this.level.dimensionType()); }
{
return DimensionTypeWrapper.getDimensionTypeWrapper(level.dimensionType()); @Override
} public String getDimensionName() { return this.level.dimension().location().toString(); }
@Override @Override
public EDhApiLevelType getLevelType() { return EDhApiLevelType.SERVER_LEVEL; } public EDhApiLevelType getLevelType() { return EDhApiLevelType.SERVER_LEVEL; }
public ServerLevel getLevel() public ServerLevel getLevel() { return this.level; }
{
return level;
}
@Override @Override
public boolean hasCeiling() public boolean hasCeiling() { return this.level.dimensionType().hasCeiling(); }
{
return level.dimensionType().hasCeiling();
}
@Override @Override
public boolean hasSkyLight() public boolean hasSkyLight() { return this.level.dimensionType().hasSkyLight(); }
{
return level.dimensionType().hasSkyLight();
}
@Override @Override
public int getMaxHeight() public int getMaxHeight() { return this.level.getHeight(); }
{
return level.getHeight();
}
@Override @Override
public int getMinHeight() public int getMinHeight()
@@ -124,37 +109,45 @@ public class ServerLevelWrapper implements IServerLevelWrapper
#if MC_VER < MC_1_17_1 #if MC_VER < MC_1_17_1
return 0; return 0;
#else #else
return level.getMinBuildHeight(); return this.level.getMinBuildHeight();
#endif #endif
} }
@Override @Override
public IChunkWrapper tryGetChunk(DhChunkPos pos) public IChunkWrapper tryGetChunk(DhChunkPos pos)
{ {
if (!level.hasChunk(pos.getX(), pos.getZ())) return null; if (!this.level.hasChunk(pos.getX(), pos.getZ()))
ChunkAccess chunk = level.getChunk(pos.getX(), pos.getZ(), ChunkStatus.FULL, false); {
if (chunk == null) return null; return null;
return new ChunkWrapper(chunk, level, this); }
ChunkAccess chunk = this.level.getChunk(pos.getX(), pos.getZ(), ChunkStatus.FULL, false);
if (chunk == null)
{
return null;
}
return new ChunkWrapper(chunk, this.level, this);
} }
@Override @Override
public boolean hasChunkLoaded(int chunkX, int chunkZ) public boolean hasChunkLoaded(int chunkX, int chunkZ)
{ {
// world.hasChunk(chunkX, chunkZ); THIS DOES NOT WORK FOR CLIENT LEVEL CAUSE MOJANG ALWAYS RETURN TRUE FOR THAT! // world.hasChunk(chunkX, chunkZ); THIS DOES NOT WORK FOR CLIENT LEVEL CAUSE MOJANG ALWAYS RETURN TRUE FOR THAT!
ChunkSource source = level.getChunkSource(); ChunkSource source = this.level.getChunkSource();
return source.hasChunk(chunkX, chunkZ); return source.hasChunk(chunkX, chunkZ);
} }
@Override @Override
public IBlockStateWrapper getBlockState(DhBlockPos pos) public IBlockStateWrapper getBlockState(DhBlockPos pos)
{ {
return BlockStateWrapper.fromBlockState(level.getBlockState(McObjectConverter.Convert(pos)), this); return BlockStateWrapper.fromBlockState(this.level.getBlockState(McObjectConverter.Convert(pos)), this);
} }
@Override @Override
public IBiomeWrapper getBiome(DhBlockPos pos) public IBiomeWrapper getBiome(DhBlockPos pos)
{ {
return BiomeWrapper.getBiomeWrapper(level.getBiome(McObjectConverter.Convert(pos)), this); return BiomeWrapper.getBiomeWrapper(this.level.getBiome(McObjectConverter.Convert(pos)), this);
} }
@Override @Override
@@ -185,6 +178,6 @@ public class ServerLevelWrapper implements IServerLevelWrapper
//================// //================//
@Override @Override
public String toString() { return "Wrapped{" + this.level.toString() + "@" + this.getDimensionType().getDimensionName() + "}"; } public String toString() { return "Wrapped{" + this.level.toString() + "@" + this.getDimensionName() + "}"; }
} }
@@ -134,7 +134,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
{ {
for (int i = 0; i < 11; i++) for (int i = 0; i < 11; i++)
{ {
times.add(new Rolling(SIZE)); this.times.add(new Rolling(SIZE));
} }
} }
@@ -144,19 +144,25 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
{ {
String name = e.name; String name = e.name;
int index = Arrays.asList(TIME_NAMES).indexOf(name); int index = Arrays.asList(TIME_NAMES).indexOf(name);
if (index == -1) continue; if (index == -1)
times.get(index).add(e.timeNs); {
continue;
}
this.times.get(index).add(e.timeNs);
} }
times.get(0).add(event.getTotalTimeNs()); this.times.get(0).add(event.getTotalTimeNs());
} }
public String toString() @Override public String toString()
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
for (int i = 0; i < times.size(); i++) for (int i = 0; i < this.times.size(); i++)
{ {
if (times.get(i).getAverage() == 0) continue; if (this.times.get(i).getAverage() == 0)
sb.append(TIME_NAMES[i]).append(": ").append(times.get(i).getAverage()).append("\n"); {
continue;
}
sb.append(TIME_NAMES[i]).append(": ").append(this.times.get(i).getAverage()).append("\n");
} }
return sb.toString(); return sb.toString();
} }
@@ -186,13 +192,13 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
public RegionFileStorageExternalCache getOrCreateRegionFileCache(RegionFileStorage storage) public RegionFileStorageExternalCache getOrCreateRegionFileCache(RegionFileStorage storage)
{ {
RegionFileStorageExternalCache cache = regionFileStorageCacheRef.get(); RegionFileStorageExternalCache cache = this.regionFileStorageCacheRef.get();
if (cache == null) if (cache == null)
{ {
cache = new RegionFileStorageExternalCache(storage); cache = new RegionFileStorageExternalCache(storage);
if (!regionFileStorageCacheRef.compareAndSet(null, cache)) if (!this.regionFileStorageCacheRef.compareAndSet(null, cache))
{ {
cache = regionFileStorageCacheRef.get(); cache = this.regionFileStorageCacheRef.get();
} }
} }
return cache; return cache;
@@ -304,17 +310,17 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
public <T> T joinSync(CompletableFuture<T> future) public <T> T joinSync(CompletableFuture<T> future)
{ {
if (!unsafeThreadingRecorded && !future.isDone()) if (!this.unsafeThreadingRecorded && !future.isDone())
{ {
EVENT_LOGGER.error("Unsafe MultiThreading in Chunk Generator: ", new RuntimeException("Concurrent future")); EVENT_LOGGER.error("Unsafe MultiThreading in Chunk Generator: ", new RuntimeException("Concurrent future"));
EVENT_LOGGER.error("To increase stability, it is recommended to set world generation threads count to 1."); EVENT_LOGGER.error("To increase stability, it is recommended to set world generation threads count to 1.");
unsafeThreadingRecorded = true; this.unsafeThreadingRecorded = true;
} }
return future.join(); return future.join();
} }
public void updateAllFutures() @Override public void updateAllFutures()
{ {
if (this.unknownExceptionCount > 0) if (this.unknownExceptionCount > 0)
{ {
@@ -488,8 +494,8 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
{ {
chunkWrapper.setBlockLightStorage(chunkBlockLightingByDhPos.get(chunkWrapper.getChunkPos())); chunkWrapper.setBlockLightStorage(chunkBlockLightingByDhPos.get(chunkWrapper.getChunkPos()));
chunkWrapper.setSkyLightStorage(chunkSkyLightingByDhPos.get(chunkWrapper.getChunkPos())); chunkWrapper.setSkyLightStorage(chunkSkyLightingByDhPos.get(chunkWrapper.getChunkPos()));
chunkWrapper.setUseDhLighting(true); chunkWrapper.setIsDhBlockLightCorrect(true);
chunkWrapper.setIsDhLightCorrect(true); chunkWrapper.setIsDhSkyLightCorrect(true);
} }
chunkWrappersByDhPos.put(chunkPos, chunkWrapper); chunkWrappersByDhPos.put(chunkPos, chunkWrapper);
@@ -531,11 +537,6 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
#endif #endif
} }
if (!wrappedChunk.isLightCorrect())
{
throw new RuntimeException("The generated chunk somehow has isLightCorrect() returning false");
}
boolean isFull = ChunkWrapper.getStatus(target) == ChunkStatus.FULL || target instanceof LevelChunk; boolean isFull = ChunkWrapper.getStatus(target) == ChunkStatus.FULL || target instanceof LevelChunk;
#if MC_VER >= MC_1_18_2 #if MC_VER >= MC_1_18_2
boolean isPartial = target.isOldNoiseGeneration(); boolean isPartial = target.isOldNoiseGeneration();
@@ -823,9 +824,9 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
Heightmap.primeHeightmaps(((ChunkWrapper)centerChunk).getChunk(), ChunkStatus.FEATURES.heightmapsAfter()); Heightmap.primeHeightmaps(((ChunkWrapper)centerChunk).getChunk(), ChunkStatus.FEATURES.heightmapsAfter());
// pre-generated chunks should have lighting but new ones won't // pre-generated chunks should have lighting but new ones won't
if (!centerChunk.isLightCorrect()) if (!centerChunk.isDhBlockLightingCorrect())
{ {
DhLightingEngine.INSTANCE.lightChunk(centerChunk, iChunkWrapperList, maxSkyLight); DhLightingEngine.INSTANCE.bakeChunkBlockLighting(centerChunk, iChunkWrapperList, maxSkyLight);
} }
} }
@@ -128,7 +128,7 @@ public class ChunkLoader
ChunkPos actualPos = new ChunkPos(tagLevel.getInt("xPos"), tagLevel.getInt("zPos")); ChunkPos actualPos = new ChunkPos(tagLevel.getInt("xPos"), tagLevel.getInt("zPos"));
if (!Objects.equals(chunkPos, actualPos)) if (!Objects.equals(chunkPos, actualPos))
{ {
#if MC_VER > MC_1_17_1 #if MC_VER >= MC_1_18_2
if (actualPos.equals(ChunkPos.ZERO)) if (actualPos.equals(ChunkPos.ZERO))
#else #else
if (actualPos.equals(ChunkPos.INVALID_CHUNK_POS)) if (actualPos.equals(ChunkPos.INVALID_CHUNK_POS))
@@ -47,4 +47,7 @@ accessible field net/minecraft/client/renderer/texture/TextureAtlasSprite frames
accessible field net/minecraft/client/renderer/texture/TextureAtlasSprite framesY [I accessible field net/minecraft/client/renderer/texture/TextureAtlasSprite framesY [I
accessible field net/minecraft/client/renderer/texture/TextureAtlasSprite mainImage [Lcom/mojang/blaze3d/platform/NativeImage; accessible field net/minecraft/client/renderer/texture/TextureAtlasSprite mainImage [Lcom/mojang/blaze3d/platform/NativeImage;
# DimensionTypeWrapper workaround
accessible field net/minecraft/world/level/dimension/DimensionType effectsLocation Lnet/minecraft/resources/ResourceLocation;
extendable class com/mojang/math/Matrix4f extendable class com/mojang/math/Matrix4f
+11 -3
View File
@@ -10,14 +10,17 @@ loom {
client { client {
client() client()
setConfigName("Fabric Client") setConfigName("Fabric Client")
ideConfigGenerated(true) ideConfigGenerated(true) // When true a run configuration file will be generated for IDE's. By default only set to true for the root project.
runDir("../run") runDir("../run/client")
vmArgs("-Dio.netty.leakDetection.level=advanced") // https://netty.io/wiki/reference-counted-objects.html#leak-detection-levels
programArgs("--username", "Dev")
} }
server { server {
server() server()
setConfigName("Fabric Server") setConfigName("Fabric Server")
ideConfigGenerated(true) ideConfigGenerated(true)
runDir("../run") runDir("../run/server")
vmArgs("-Dio.netty.leakDetection.level=advanced")
} }
} }
} }
@@ -69,6 +72,11 @@ dependencies {
addModJar(fabricApi.module("fabric-events-interaction-v0", rootProject.fabric_api_version)) addModJar(fabricApi.module("fabric-events-interaction-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-rendering-v1", rootProject.fabric_api_version)) // TODO: Remove this as it is only needed in 1 line (FabricClientProxy)
addModJar(fabricApi.module("fabric-networking-api-v1", rootProject.fabric_api_version)) addModJar(fabricApi.module("fabric-networking-api-v1", rootProject.fabric_api_version))
addModJar(fabricApi.module("fabric-entity-events-v1", rootProject.fabric_api_version))
if (minecraft_version >= "1.19.2")
addModJar(fabricApi.module("fabric-command-api-v2", rootProject.fabric_api_version))
else // < 1.19.2
addModJar(fabricApi.module("fabric-command-api-v1", rootProject.fabric_api_version))
// used by mod menu in MC 1.20.6+ // used by mod menu in MC 1.20.6+
addModJar(fabricApi.module("fabric-screen-api-v1", rootProject.fabric_api_version)) addModJar(fabricApi.module("fabric-screen-api-v1", rootProject.fabric_api_version))
@@ -19,9 +19,8 @@
package com.seibel.distanthorizons.fabric; package com.seibel.distanthorizons.fabric;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack;
import com.seibel.distanthorizons.common.AbstractModInitializer; import com.seibel.distanthorizons.common.AbstractModInitializer;
import com.seibel.distanthorizons.common.AbstractPluginPacketSender;
import com.seibel.distanthorizons.common.wrappers.McObjectConverter; import com.seibel.distanthorizons.common.wrappers.McObjectConverter;
import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper; import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper;
import com.seibel.distanthorizons.core.api.internal.ClientApi; import com.seibel.distanthorizons.core.api.internal.ClientApi;
@@ -38,17 +37,24 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.ISodiumAcce
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
import com.seibel.distanthorizons.core.util.math.Mat4f; import com.seibel.distanthorizons.core.util.math.Mat4f;
import com.seibel.distanthorizons.fabric.wrappers.modAccessor.SodiumAccessor; import com.seibel.distanthorizons.fabric.wrappers.modAccessor.SodiumAccessor;
//import io.netty.buffer.ByteBuf;
import net.fabricmc.api.EnvType; import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment; import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientChunkEvents; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientChunkEvents;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents; import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents;
import net.fabricmc.fabric.api.event.player.AttackBlockCallback; import net.fabricmc.fabric.api.event.player.AttackBlockCallback;
import net.fabricmc.fabric.api.event.player.UseBlockCallback; import net.fabricmc.fabric.api.event.player.UseBlockCallback;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screens.TitleScreen; import net.minecraft.client.gui.screens.TitleScreen;
#if MC_VER >= MC_1_20_6
import com.seibel.distanthorizons.common.CommonPacketPayload;
import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry;
#else
import com.seibel.distanthorizons.core.network.messages.AbstractNetworkMessage;
#endif
#if MC_VER < MC_1_19_4 #if MC_VER < MC_1_19_4
import java.nio.FloatBuffer; import java.nio.FloatBuffer;
#endif #endif
@@ -60,7 +66,6 @@ import net.minecraft.world.InteractionResult;
import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.HitResult;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.joml.Matrix4f;
import org.lwjgl.glfw.GLFW; import org.lwjgl.glfw.GLFW;
/** /**
@@ -89,6 +94,7 @@ public class FabricClientProxy implements AbstractModInitializer.IEventProxy
* Registers Fabric Events * Registers Fabric Events
* @author Ran * @author Ran
*/ */
@Override
public void registerEvents() public void registerEvents()
{ {
LOGGER.info("Registering Fabric Client Events"); LOGGER.info("Registering Fabric Client Events");
@@ -246,17 +252,29 @@ public class FabricClientProxy implements AbstractModInitializer.IEventProxy
// networking event // // networking event //
//==================// //==================//
// ClientPlayNetworking.registerGlobalReceiver(new ResourceLocation(ModInfo.NETWORKING_RESOURCE_NAMESPACE, ModInfo.MULTIVERSE_PLUGIN_NAMESPACE), #if MC_VER >= MC_1_20_6
// (Minecraft client, ClientPacketListener handler, FriendlyByteBuf friendlyByteBuf, PacketSender responseSender) -> PayloadTypeRegistry.playC2S().register(CommonPacketPayload.TYPE, new CommonPacketPayload.Codec());
// { PayloadTypeRegistry.playS2C().register(CommonPacketPayload.TYPE, new CommonPacketPayload.Codec());
// // converting to a ByteBuf is necessary otherwise Fabric will complain when the game boots ClientPlayNetworking.registerGlobalReceiver(CommonPacketPayload.TYPE, (payload, context) ->
// ByteBuf nettyByteBuf = friendlyByteBuf.asByteBuf(); {
// if (payload.message() == null)
// // remove the Bukkit/Forge packet ID byte {
// nettyByteBuf.readByte(); return;
// }
// ClientApi.INSTANCE.serverMessageReceived(nettyByteBuf); ClientApi.INSTANCE.pluginMessageReceived(payload.message());
// }); });
#else
ClientPlayNetworking.registerGlobalReceiver(AbstractPluginPacketSender.WRAPPER_PACKET_RESOURCE, (client, handler, buffer, packetSender) ->
{
// Forge packet ID
buffer.readByte();
AbstractNetworkMessage message = AbstractPluginPacketSender.decodeMessage(buffer);
if (message != null)
{
ClientApi.INSTANCE.pluginMessageReceived(message);
}
});
#endif
} }
public void onKeyInput() public void onKeyInput()
@@ -285,14 +303,14 @@ public class FabricClientProxy implements AbstractModInitializer.IEventProxy
// Diff and trigger events // Diff and trigger events
for (int keyCode : currentKeyDown) for (int keyCode : currentKeyDown)
{ {
if (!previouslyPressKeyCodes.contains(keyCode)) if (!this.previouslyPressKeyCodes.contains(keyCode))
{ {
ClientApi.INSTANCE.keyPressedEvent(keyCode); ClientApi.INSTANCE.keyPressedEvent(keyCode);
} }
} }
// Update the set // Update the set
previouslyPressKeyCodes = currentKeyDown; this.previouslyPressKeyCodes = currentKeyDown;
} }
} }
@@ -27,6 +27,7 @@ import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IPluginPacketSender;
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.*; import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.*;
import com.seibel.distanthorizons.coreapi.ModInfo; import com.seibel.distanthorizons.coreapi.ModInfo;
import com.seibel.distanthorizons.fabric.wrappers.modAccessor.*; import com.seibel.distanthorizons.fabric.wrappers.modAccessor.*;
@@ -40,6 +41,12 @@ import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
#if MC_VER >= MC_1_19_2
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
#else // < 1.19.2
import net.fabricmc.fabric.api.command.v1.CommandRegistrationCallback;
#endif
import javax.swing.*; import javax.swing.*;
import java.awt.*; import java.awt.*;
import java.util.function.Consumer; import java.util.function.Consumer;
@@ -51,14 +58,22 @@ import java.util.function.Consumer;
*/ */
public class FabricMain extends AbstractModInitializer implements ClientModInitializer, DedicatedServerModInitializer public class FabricMain extends AbstractModInitializer implements ClientModInitializer, DedicatedServerModInitializer
{ {
private static final ResourceLocation INITIAL_PHASE = ResourceLocation.tryParse("distanthorizons:dedicated_server_initial"); #if MC_VER >= MC_1_21_1
private static final ResourceLocation INITIAL_PHASE = ResourceLocation.fromNamespaceAndPath(ModInfo.RESOURCE_NAMESPACE, ModInfo.DEDICATED_SERVER_INITIAL_PATH);
#else
private static final ResourceLocation INITIAL_PHASE = new ResourceLocation(ModInfo.RESOURCE_NAMESPACE, ModInfo.DEDICATED_SERVER_INITIAL_PATH);
#endif
private static final Logger LOGGER = DhLoggerBuilder.getLogger(); private static final Logger LOGGER = DhLoggerBuilder.getLogger();
@Override @Override
protected void createInitialBindings() { SingletonInjector.INSTANCE.bind(IModChecker.class, ModChecker.INSTANCE); } protected void createInitialBindings()
{
SingletonInjector.INSTANCE.bind(IModChecker.class, ModChecker.INSTANCE);
SingletonInjector.INSTANCE.bind(IPluginPacketSender.class, new FabricPluginPacketSender());
}
@Override @Override
protected IEventProxy createClientProxy() { return new FabricClientProxy(); } protected IEventProxy createClientProxy() { return new FabricClientProxy(); }
@@ -102,7 +117,15 @@ public class FabricMain extends AbstractModInitializer implements ClientModIniti
} }
@Override @Override
protected void subscribeRegisterCommandsEvent(Consumer<CommandDispatcher<CommandSourceStack>> eventHandler) { } protected void subscribeRegisterCommandsEvent(Consumer<CommandDispatcher<CommandSourceStack>> eventHandler)
{
CommandRegistrationCallback.EVENT.register(
(dispatcher, registryAccess #if MC_VER >= MC_1_19_2 , environment #endif ) ->
{
eventHandler.accept(dispatcher);
}
);
}
@Override @Override
protected void subscribeClientStartedEvent(Runnable eventHandler) { ClientLifecycleEvents.CLIENT_STARTED.register((mc) -> eventHandler.run()); } protected void subscribeClientStartedEvent(Runnable eventHandler) { ClientLifecycleEvents.CLIENT_STARTED.register((mc) -> eventHandler.run()); }
@@ -120,15 +143,21 @@ public class FabricMain extends AbstractModInitializer implements ClientModIniti
SingletonInjector.INSTANCE.runDelayedSetup(); SingletonInjector.INSTANCE.runDelayedSetup();
if (Config.Client.Advanced.Graphics.Fog.disableVanillaFog.get() && SingletonInjector.INSTANCE.get(IModChecker.class).isModLoaded("bclib")) if (Config.Client.Advanced.Graphics.Fog.disableVanillaFog.get() && SingletonInjector.INSTANCE.get(IModChecker.class).isModLoaded("bclib"))
{
ModAccessorInjector.INSTANCE.get(IBCLibAccessor.class).setRenderCustomFog(false); // Remove BCLib's fog ModAccessorInjector.INSTANCE.get(IBCLibAccessor.class).setRenderCustomFog(false); // Remove BCLib's fog
}
#if MC_VER >= MC_1_20_1 #if MC_VER >= MC_1_20_1
if (SingletonInjector.INSTANCE.get(IModChecker.class).isModLoaded("sodium")) if (SingletonInjector.INSTANCE.get(IModChecker.class).isModLoaded("sodium"))
{
ModAccessorInjector.INSTANCE.get(ISodiumAccessor.class).setFogOcclusion(false); ModAccessorInjector.INSTANCE.get(ISodiumAccessor.class).setFogOcclusion(false);
}
#endif #endif
if (ConfigBase.INSTANCE == null) if (ConfigBase.INSTANCE == null)
{
throw new IllegalStateException("Config was not initialized. Make sure to call LodCommonMain.initConfig() before calling this method."); throw new IllegalStateException("Config was not initialized. Make sure to call LodCommonMain.initConfig() before calling this method.");
}
} }
} }
@@ -0,0 +1,46 @@
package com.seibel.distanthorizons.fabric;
import com.seibel.distanthorizons.common.AbstractPluginPacketSender;
import com.seibel.distanthorizons.core.network.messages.AbstractNetworkMessage;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
import net.minecraft.server.level.ServerPlayer;
#if MC_VER >= MC_1_20_6
import com.seibel.distanthorizons.common.CommonPacketPayload;
#else // < 1.20.6
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs;
import net.minecraft.network.FriendlyByteBuf;
#endif
public class FabricPluginPacketSender extends AbstractPluginPacketSender
{
@Override
public void sendToServer(AbstractNetworkMessage message)
{
#if MC_VER >= MC_1_20_6
ClientPlayNetworking.send(new CommonPacketPayload(message));
#else // < 1.20.6
FriendlyByteBuf buffer = PacketByteBufs.create();
// Forge packet ID
buffer.writeByte(0);
AbstractPluginPacketSender.encodeMessage(buffer, message);
ClientPlayNetworking.send(WRAPPER_PACKET_RESOURCE, buffer);
#endif
}
@Override
public void sendToClient(ServerPlayer serverPlayer, AbstractNetworkMessage message)
{
#if MC_VER >= MC_1_20_6
ServerPlayNetworking.send(serverPlayer, new CommonPacketPayload(message));
#else // < 1.20.6
FriendlyByteBuf buffer = PacketByteBufs.create();
// Forge packet ID
buffer.writeByte(0);
AbstractPluginPacketSender.encodeMessage(buffer, message);
ServerPlayNetworking.send(serverPlayer, WRAPPER_PACKET_RESOURCE, buffer);
#endif
}
}
@@ -13,11 +13,13 @@ import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
import com.seibel.distanthorizons.fabric.testing.TestWorldGenBindingEvent; import com.seibel.distanthorizons.fabric.testing.TestWorldGenBindingEvent;
import net.fabricmc.fabric.api.entity.event.v1.ServerEntityWorldChangeEvents;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerChunkEvents; 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.ServerLifecycleEvents;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerWorldEvents; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerWorldEvents;
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screens.TitleScreen; import net.minecraft.client.gui.screens.TitleScreen;
import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.multiplayer.ClientLevel;
@@ -25,6 +27,14 @@ import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
#if MC_VER >= MC_1_20_6
import com.seibel.distanthorizons.common.CommonPacketPayload;
import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry;
#else
import com.seibel.distanthorizons.core.network.messages.AbstractNetworkMessage;
import com.seibel.distanthorizons.common.AbstractPluginPacketSender;
#endif
import java.util.function.Supplier; import java.util.function.Supplier;
/** /**
@@ -40,21 +50,26 @@ public class FabricServerProxy implements AbstractModInitializer.IEventProxy
private static final ServerApi SERVER_API = ServerApi.INSTANCE; private static final ServerApi SERVER_API = ServerApi.INSTANCE;
private static final Logger LOGGER = DhLoggerBuilder.getLogger(); private static final Logger LOGGER = DhLoggerBuilder.getLogger();
private final boolean isDedicated; private final boolean isDedicatedServer;
public static Supplier<Boolean> isGenerationThreadChecker = null; public static Supplier<Boolean> isGenerationThreadChecker = null;
public FabricServerProxy(boolean isDedicated) //=============//
// constructor //
//=============//
public FabricServerProxy(boolean isDedicatedServer)
{ {
this.isDedicated = isDedicated; this.isDedicatedServer = isDedicatedServer;
} }
// TODO rename
private boolean isValidTime() private boolean isValidTime()
{ {
if (isDedicated) if (this.isDedicatedServer)
{ {
return true; return true;
} }
@@ -68,6 +83,7 @@ public class FabricServerProxy implements AbstractModInitializer.IEventProxy
private ServerPlayerWrapper getServerPlayerWrapper(ServerPlayer player) { return ServerPlayerWrapper.getWrapper(player); } private ServerPlayerWrapper getServerPlayerWrapper(ServerPlayer player) { return ServerPlayerWrapper.getWrapper(player); }
/** Registers Fabric Events */ /** Registers Fabric Events */
@Override
public void registerEvents() public void registerEvents()
{ {
LOGGER.info("Registering Fabric Server Events"); LOGGER.info("Registering Fabric Server Events");
@@ -90,15 +106,15 @@ public class FabricServerProxy implements AbstractModInitializer.IEventProxy
//TODO: Check if both of these use the correct timed events. (i.e. is it 'ed' or 'ing' one?) //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()) if (this.isValidTime())
{ {
ServerApi.INSTANCE.serverLoadEvent(isDedicated); ServerApi.INSTANCE.serverLoadEvent(this.isDedicatedServer);
} }
}); });
// ServerWorldUnloadEvent // ServerWorldUnloadEvent
ServerLifecycleEvents.SERVER_STOPPED.register((server) -> ServerLifecycleEvents.SERVER_STOPPED.register((server) ->
{ {
if (isValidTime()) if (this.isValidTime())
{ {
ServerApi.INSTANCE.serverUnloadEvent(); ServerApi.INSTANCE.serverUnloadEvent();
} }
@@ -107,25 +123,25 @@ public class FabricServerProxy implements AbstractModInitializer.IEventProxy
// ServerLevelLoadEvent // ServerLevelLoadEvent
ServerWorldEvents.LOAD.register((server, level) -> ServerWorldEvents.LOAD.register((server, level) ->
{ {
if (isValidTime()) if (this.isValidTime())
{ {
ServerApi.INSTANCE.serverLevelLoadEvent(getServerLevelWrapper(level)); ServerApi.INSTANCE.serverLevelLoadEvent(this.getServerLevelWrapper(level));
} }
}); });
// ServerLevelUnloadEvent // ServerLevelUnloadEvent
ServerWorldEvents.UNLOAD.register((server, level) -> ServerWorldEvents.UNLOAD.register((server, level) ->
{ {
if (isValidTime()) if (this.isValidTime())
{ {
ServerApi.INSTANCE.serverLevelUnloadEvent(getServerLevelWrapper(level)); ServerApi.INSTANCE.serverLevelUnloadEvent(this.getServerLevelWrapper(level));
} }
}); });
// ServerChunkLoadEvent // ServerChunkLoadEvent
ServerChunkEvents.CHUNK_LOAD.register((server, chunk) -> ServerChunkEvents.CHUNK_LOAD.register((server, chunk) ->
{ {
ILevelWrapper level = getServerLevelWrapper((ServerLevel) chunk.getLevel()); ILevelWrapper level = this.getServerLevelWrapper((ServerLevel) chunk.getLevel());
if (isValidTime()) if (this.isValidTime())
{ {
ServerApi.INSTANCE.serverChunkLoadEvent( ServerApi.INSTANCE.serverChunkLoadEvent(
new ChunkWrapper(chunk, chunk.getLevel(), level), new ChunkWrapper(chunk, chunk.getLevel(), level),
@@ -136,18 +152,56 @@ public class FabricServerProxy implements AbstractModInitializer.IEventProxy
ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> ServerPlayConnectionEvents.JOIN.register((handler, sender, server) ->
{ {
if (isValidTime()) if (this.isValidTime())
{ {
ServerApi.INSTANCE.serverPlayerJoinEvent(getServerPlayerWrapper(handler.player)); ServerApi.INSTANCE.serverPlayerJoinEvent(this.getServerPlayerWrapper(handler.player));
} }
}); });
ServerPlayConnectionEvents.DISCONNECT.register((handler, server) -> ServerPlayConnectionEvents.DISCONNECT.register((handler, server) ->
{ {
if (isValidTime()) if (this.isValidTime())
{ {
ServerApi.INSTANCE.serverPlayerDisconnectEvent(getServerPlayerWrapper(handler.player)); ServerApi.INSTANCE.serverPlayerDisconnectEvent(this.getServerPlayerWrapper(handler.player));
} }
}); });
ServerEntityWorldChangeEvents.AFTER_PLAYER_CHANGE_WORLD.register((player, originLevel, destinationLevel) ->
{
if (this.isValidTime())
{
ServerApi.INSTANCE.serverPlayerLevelChangeEvent(
this.getServerPlayerWrapper(player),
this.getServerLevelWrapper(originLevel),
this.getServerLevelWrapper(destinationLevel)
);
}
});
if (this.isDedicatedServer)
{
#if MC_VER >= MC_1_20_6
PayloadTypeRegistry.playC2S().register(CommonPacketPayload.TYPE, new CommonPacketPayload.Codec());
PayloadTypeRegistry.playS2C().register(CommonPacketPayload.TYPE, new CommonPacketPayload.Codec());
ServerPlayNetworking.registerGlobalReceiver(CommonPacketPayload.TYPE, (payload, context) ->
{
if (payload.message() == null)
{
return;
}
ServerApi.INSTANCE.pluginMessageReceived(ServerPlayerWrapper.getWrapper(context.player()), payload.message());
});
#else
ServerPlayNetworking.registerGlobalReceiver(AbstractPluginPacketSender.WRAPPER_PACKET_RESOURCE, (server, serverPlayer, handler, buffer, packetSender) ->
{
// Forge packet ID
buffer.readByte();
AbstractNetworkMessage message = AbstractPluginPacketSender.decodeMessage(buffer);
if (message != null)
{
ServerApi.INSTANCE.pluginMessageReceived(ServerPlayerWrapper.getWrapper(serverPlayer), message);
}
});
#endif
}
} }
} }
@@ -21,33 +21,9 @@ import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
@Mixin(ClientPacketListener.class) @Mixin(ClientPacketListener.class)
public class MixinClientPacketListener public class MixinClientPacketListener
{ {
@Shadow
private ClientLevel level;
@Unique
private ClientLevel previousLevel;
@Inject(method = "handleLogin", at = @At("RETURN")) @Inject(method = "handleLogin", at = @At("RETURN"))
void onHandleLoginEnd(CallbackInfo ci) { ClientApi.INSTANCE.onClientOnlyConnected(); } void onHandleLoginEnd(CallbackInfo ci) { ClientApi.INSTANCE.onClientOnlyConnected(); }
@Inject(method = "handleRespawn", at = @At("HEAD"))
void onHandleRespawnStart(CallbackInfo ci) { this.previousLevel = this.level; }
@Inject(method = "handleRespawn", at = @At("RETURN"))
void onHandleRespawnEnd(CallbackInfo ci)
{
// If the player changes dimensions the "this.level" will be changed halfway through the respawn method.
// By checking if the object references are the same, we can see if the previous level should be unloaded
// or if the player just respawned in the same level.
if (this.previousLevel != this.level)
{
ClientApi.INSTANCE.clientLevelUnloadEvent(ClientLevelWrapper.getWrapper(this.previousLevel));
ClientApi.INSTANCE.clientLevelLoadEvent(ClientLevelWrapper.getWrapper(this.level));
}
this.previousLevel = null;
}
#if MC_VER < MC_1_19_4 #if MC_VER < MC_1_19_4
@Inject(method = "cleanup", at = @At("HEAD")) @Inject(method = "cleanup", at = @At("HEAD"))
#else #else
@@ -55,10 +31,6 @@ public class MixinClientPacketListener
#endif #endif
void onCleanupStart(CallbackInfo ci) void onCleanupStart(CallbackInfo ci)
{ {
if (this.level != null)
{
ClientApi.INSTANCE.clientLevelUnloadEvent(ClientLevelWrapper.getWrapper(this.level));
}
ClientApi.INSTANCE.onClientOnlyDisconnected(); ClientApi.INSTANCE.onClientOnlyDisconnected();
} }
@@ -131,22 +131,4 @@ public class MixinLevelRenderer
} }
} }
#if MC_VER < MC_1_19_4
@Inject(at = @At(value = "TAIL", target = "Lnet/minecraft/world/level/lighting/LevelLightEngine;runUpdates(IZZ)I"), method = "renderLevel")
public void callAfterRunUpdates(PoseStack poseStack, float partialTick, long finishNanoTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f projectionMatrix, CallbackInfo ci)
#elif MC_VER < MC_1_20_1
@Inject(at = @At(value = "TAIL", target = "Lnet/minecraft/world/level/lighting/LevelLightEngine;runUpdates(IZZ)I"), method = "renderLevel")
public void callAfterRunUpdates(PoseStack poseStack, float partialTick, long finishNanoTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f projectionMatrix, CallbackInfo ci)
#elif MC_VER < MC_1_20_6
@Inject(at = @At(value = "TAIL", target = "Lnet/minecraft/world/level/lighting/LevelLightEngine;runLightUpdates()I"), method = "renderLevel")
private void callAfterRunUpdates(PoseStack poseStack, float partialTick, long finishNanoTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f projectionMatrix, CallbackInfo ci)
#else
@Inject(at = @At(value = "TAIL", target = "Lnet/minecraft/world/level/lighting/LevelLightEngine;runLightUpdates()I"), method = "renderLevel")
private void callAfterRunUpdates(CallbackInfo ci)
#endif
{
ChunkWrapper.syncedUpdateClientLightStatus();
}
} }
@@ -2,6 +2,8 @@ package com.seibel.distanthorizons.fabric.mixins.client;
import com.seibel.distanthorizons.api.enums.config.EDhApiUpdateBranch; import com.seibel.distanthorizons.api.enums.config.EDhApiUpdateBranch;
import com.seibel.distanthorizons.common.wrappers.gui.updater.UpdateModScreen; import com.seibel.distanthorizons.common.wrappers.gui.updater.UpdateModScreen;
import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper;
import com.seibel.distanthorizons.core.api.internal.ClientApi;
import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.jar.installer.GitlabGetter; import com.seibel.distanthorizons.core.jar.installer.GitlabGetter;
@@ -12,7 +14,9 @@ import com.seibel.distanthorizons.coreapi.ModInfo;
import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screens.TitleScreen; import net.minecraft.client.gui.screens.TitleScreen;
import net.minecraft.client.multiplayer.ClientLevel;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
@@ -25,8 +29,14 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
* @author coolGi * @author coolGi
*/ */
@Mixin(Minecraft.class) @Mixin(Minecraft.class)
public class MixinMinecraft public abstract class MixinMinecraft
{ {
@Shadow
public abstract boolean isLocalServer();
@Unique
private ClientLevel lastLevel;
/** /**
* Can be enabled for testing the auto updater UI. <br/> * Can be enabled for testing the auto updater UI. <br/>
* will always show the auto updater if set to true. * will always show the auto updater if set to true.
@@ -113,6 +123,22 @@ public class MixinMinecraft
} }
#endif #endif
@Inject(at = @At("HEAD"), method = "updateLevelInEngines")
public void updateLevelInEngines(ClientLevel level, CallbackInfo ci)
{
if (this.lastLevel != null && level != this.lastLevel)
{
ClientApi.INSTANCE.clientLevelUnloadEvent(ClientLevelWrapper.getWrapper(this.lastLevel));
}
if (level != null)
{
ClientApi.INSTANCE.clientLevelLoadEvent(ClientLevelWrapper.getWrapper(level, true));
}
this.lastLevel = level;
}
@Inject(at = @At("HEAD"), method = "close()V") @Inject(at = @At("HEAD"), method = "close()V")
public void close(CallbackInfo ci) { SelfUpdater.onClose(); } public void close(CallbackInfo ci) { SelfUpdater.onClose(); }
@@ -0,0 +1,38 @@
#if MC_VER == MC_1_16_5
package com.seibel.distanthorizons.fabric.mixins.server;
import com.seibel.distanthorizons.common.wrappers.misc.IMixinServerPlayer;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.Level;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(Entity.class)
public class MixinEntity
{
@Inject(at = @At("TAIL"), method = "setLevel")
public void setLevel(Level level, CallbackInfo ci)
{
if (this instanceof IMixinServerPlayer)
{
((IMixinServerPlayer) this).distantHorizons$setDimensionChangeDestination((ServerLevel) level);
}
}
}
#else
package com.seibel.distanthorizons.fabric.mixins.server;
import net.minecraft.world.entity.Entity;
import org.spongepowered.asm.mixin.Mixin;
@Mixin(Entity.class)
public class MixinEntity
{
}
#endif
@@ -0,0 +1,76 @@
/*
* This file is part of the Distant Horizons mod
* licensed under the GNU LGPL v3 License.
*
* Copyright (C) 2020-2023 James Seibel
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.distanthorizons.fabric.mixins.server;
import com.seibel.distanthorizons.common.wrappers.misc.IMixinServerPlayer;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.Entity;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
#if MC_VER >= MC_1_21_1
import net.minecraft.world.level.portal.DimensionTransition;
#endif
@Mixin(ServerPlayer.class)
public class MixinServerPlayer implements IMixinServerPlayer
{
@Unique
@Nullable
private ServerLevel dimensionChangeDestination;
@Override
@Nullable
public ServerLevel distantHorizons$getDimensionChangeDestination()
{ return this.dimensionChangeDestination; }
#if MC_VER == MC_1_16_5
@Override
public void distantHorizons$setDimensionChangeDestination(ServerLevel dimensionChangeDestination)
{ this.dimensionChangeDestination = dimensionChangeDestination; }
#endif
@Inject(at = @At("HEAD"), method = "changeDimension")
#if MC_VER >= MC_1_21_1
public void changeDimension(DimensionTransition dimensionTransition, CallbackInfoReturnable<Entity> cir)
{ this.dimensionChangeDestination = dimensionTransition.newLevel(); }
#else
public void changeDimension(ServerLevel destination, CallbackInfoReturnable<Entity> cir)
{ this.dimensionChangeDestination = destination; }
#endif
#if MC_VER >= MC_1_20_1
@Inject(at = @At("RETURN"), method = "setServerLevel")
public void setServerLevel(ServerLevel level, CallbackInfo ci)
{ this.dimensionChangeDestination = null; }
#elif MC_VER >= MC_1_17_1
@Inject(at = @At("RETURN"), method = "setLevel")
public void setLevel(ServerLevel level, CallbackInfo ci)
{ this.dimensionChangeDestination = null; }
#endif
}
@@ -5,7 +5,9 @@
"mixins": [ "mixins": [
"server.MixinChunkGenerator", "server.MixinChunkGenerator",
"server.MixinChunkMap", "server.MixinChunkMap",
"server.MixinUtilBackgroundThread" "server.MixinUtilBackgroundThread",
"server.MixinServerPlayer",
"server.MixinEntity"
], ],
"client": [ "client": [
"client.MixinClientLevel", "client.MixinClientLevel",
+7 -5
View File
@@ -37,15 +37,17 @@ loom {
client { client {
client() client()
setConfigName("Forge Client") setConfigName("Forge Client")
ideConfigGenerated(true) ideConfigGenerated(false) // When true a run configuration file will be generated for IDE's. By default only set to true for the root project.
runDir("../run") runDir("../run/client")
// vmArgs("-XX:-OmitStackTraceInFastThrow", minecraftMemoryJavaArg) vmArgs("-Dio.netty.leakDetection.level=advanced") // https://netty.io/wiki/reference-counted-objects.html#leak-detection-levels
programArgs("--username", "Dev")
} }
server { server {
server() server()
setConfigName("Forge Server") setConfigName("Forge Server")
ideConfigGenerated(true) ideConfigGenerated(false)
runDir("../run") runDir("../run/server")
vmArgs("-Dio.netty.leakDetection.level=advanced")
} }
} }
} }
@@ -33,8 +33,6 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
import com.seibel.distanthorizons.coreapi.ModInfo;
//import io.netty.buffer.ByteBuf;
import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.LevelAccessor;
import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.multiplayer.ClientLevel;
@@ -53,8 +51,6 @@ import net.minecraftforge.event.entity.player.PlayerInteractEvent;
import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.MinecraftForge;
//import net.minecraftforge.network.NetworkRegistry;
//import net.minecraftforge.network.simple.SimpleChannel;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.lwjgl.glfw.GLFW; import org.lwjgl.glfw.GLFW;
@@ -80,8 +76,6 @@ public class ForgeClientProxy implements AbstractModInitializer.IEventProxy
private static final IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class); private static final IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
private static final Logger LOGGER = DhLoggerBuilder.getLogger(); private static final Logger LOGGER = DhLoggerBuilder.getLogger();
// private static SimpleChannel multiversePluginChannel;
#if MC_VER < MC_1_19_2 #if MC_VER < MC_1_19_2
private static LevelAccessor GetEventLevel(WorldEvent e) { return e.getWorld(); } private static LevelAccessor GetEventLevel(WorldEvent e) { return e.getWorld(); }
@@ -95,7 +89,7 @@ public class ForgeClientProxy implements AbstractModInitializer.IEventProxy
public void registerEvents() public void registerEvents()
{ {
MinecraftForge.EVENT_BUS.register(this); MinecraftForge.EVENT_BUS.register(this);
this.setupNetworkingListeners(); ForgePluginPacketSender.setPacketHandler(ClientApi.INSTANCE::pluginMessageReceived);
} }
@@ -139,7 +133,7 @@ public class ForgeClientProxy implements AbstractModInitializer.IEventProxy
} }
ClientLevel clientLevel = (ClientLevel) level; ClientLevel clientLevel = (ClientLevel) level;
IClientLevelWrapper clientLevelWrapper = ClientLevelWrapper.getWrapper(clientLevel); IClientLevelWrapper clientLevelWrapper = ClientLevelWrapper.getWrapper(clientLevel, true);
// TODO this causes a crash due to level being set to null somewhere // TODO this causes a crash due to level being set to null somewhere
ClientApi.INSTANCE.clientLevelLoadEvent(clientLevelWrapper); ClientApi.INSTANCE.clientLevelLoadEvent(clientLevelWrapper);
} }
@@ -270,66 +264,6 @@ public class ForgeClientProxy implements AbstractModInitializer.IEventProxy
} }
//============//
// networking //
//============//
public void setupNetworkingListeners()
{
// multiversePluginChannel = NetworkRegistry.newSimpleChannel(
// new ResourceLocation(ModInfo.NETWORKING_RESOURCE_NAMESPACE, ModInfo.MULTIVERSE_PLUGIN_NAMESPACE),
// // network protocol version
// () -> ModInfo.MULTIVERSE_PLUGIN_PROTOCOL_VERSION +"",
// // client accepted versions
// ForgeClientProxy::isReceivedProtocolVersionAcceptable,
// // server accepted versions
// ForgeClientProxy::isReceivedProtocolVersionAcceptable
// );
//
// multiversePluginChannel.registerMessage(0/*should be incremented for each simple channel we listen to*/, ByteBuf.class,
// // encoder
// (pack, friendlyByteBuf) -> { },
// // decoder
// (friendlyByteBuf) -> friendlyByteBuf.asByteBuf(),
// // message consumer
// (nettyByteBuf, contextRef) ->
// {
// ClientApi.INSTANCE.serverMessageReceived(nettyByteBuf);
// contextRef.get().setPacketHandled(true);
// }
// );
}
public static boolean isReceivedProtocolVersionAcceptable(String versionString)
{
if (versionString.toLowerCase().contains("allowvanilla"))
{
// allow using networking on vanilla servers
return true;
}
else if (versionString.toLowerCase().contains("absent"))
{
// allow using networking even if DH isn't installed on the server
return true;
}
else
{
// DH is installed on the server, check if the version is valid to use
try
{
int version = Integer.parseInt(versionString);
return ModInfo.MULTIVERSE_PLUGIN_PROTOCOL_VERSION == version;
}
catch (NumberFormatException ignored)
{
return false;
}
}
}
//===========// //===========//
// rendering // // rendering //
//===========// //===========//
@@ -25,6 +25,8 @@ import com.seibel.distanthorizons.common.wrappers.gui.GetConfigScreen;
import com.seibel.distanthorizons.core.api.internal.ClientApi; import com.seibel.distanthorizons.core.api.internal.ClientApi;
import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.common.wrappers.gui.GetConfigScreen;
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IPluginPacketSender;
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IModChecker; import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IModChecker;
import com.seibel.distanthorizons.coreapi.ModInfo; import com.seibel.distanthorizons.coreapi.ModInfo;
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IOptifineAccessor; import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IOptifineAccessor;
@@ -36,15 +38,16 @@ import net.minecraft.commands.CommandSourceStack;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.RegisterCommandsEvent; import net.minecraftforge.event.RegisterCommandsEvent;
import net.minecraftforge.eventbus.api.EventPriority;
import net.minecraftforge.fml.ModLoadingContext; import net.minecraftforge.fml.ModLoadingContext;
import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.event.lifecycle.*; import net.minecraftforge.fml.event.lifecycle.*;
#if MC_VER == MC_1_16_5 #if MC_VER == MC_1_16_5
import net.minecraftforge.fml.event.server.FMLServerStartingEvent; import net.minecraftforge.fml.event.server.FMLServerAboutToStartEvent;
#elif MC_VER == MC_1_17_1 #elif MC_VER == MC_1_17_1
import net.minecraftforge.fmlserverevents.FMLServerStartingEvent; import net.minecraftforge.fmlserverevents.FMLServerAboutToStartEvent;
#else #else
import net.minecraftforge.event.server.ServerStartingEvent; import net.minecraftforge.event.server.ServerAboutToStartEvent;
#endif #endif
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
#if MC_VER < MC_1_17_1 #if MC_VER < MC_1_17_1
@@ -83,7 +86,11 @@ public class ForgeMain extends AbstractModInitializer
} }
@Override @Override
protected void createInitialBindings() { SingletonInjector.INSTANCE.bind(IModChecker.class, ModChecker.INSTANCE); } protected void createInitialBindings()
{
SingletonInjector.INSTANCE.bind(IModChecker.class, ModChecker.INSTANCE);
SingletonInjector.INSTANCE.bind(IPluginPacketSender.class, new ForgePluginPacketSender());
}
@Override @Override
protected IEventProxy createClientProxy() { return new ForgeClientProxy(); } protected IEventProxy createClientProxy() { return new ForgeClientProxy(); }
@@ -137,7 +144,7 @@ public class ForgeMain extends AbstractModInitializer
@Override @Override
protected void subscribeServerStartingEvent(Consumer<MinecraftServer> eventHandler) protected void subscribeServerStartingEvent(Consumer<MinecraftServer> eventHandler)
{ {
MinecraftForge.EVENT_BUS.addListener((#if MC_VER >= MC_1_18_2 ServerStartingEvent #else FMLServerStartingEvent #endif e) -> MinecraftForge.EVENT_BUS.addListener(EventPriority.HIGH, (#if MC_VER >= MC_1_18_2 ServerAboutToStartEvent #else FMLServerAboutToStartEvent #endif e) ->
{ {
eventHandler.accept(e.getServer()); eventHandler.accept(e.getServer());
}); });
@@ -0,0 +1,127 @@
package com.seibel.distanthorizons.forge;
import com.seibel.distanthorizons.common.AbstractPluginPacketSender;
import com.seibel.distanthorizons.common.wrappers.misc.ServerPlayerWrapper;
import com.seibel.distanthorizons.core.network.messages.AbstractNetworkMessage;
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IServerPlayerWrapper;
import net.minecraft.server.level.ServerPlayer;
#if MC_VER >= MC_1_20_2
import net.minecraftforge.network.PacketDistributor;
import net.minecraftforge.network.ChannelBuilder;
import net.minecraftforge.network.SimpleChannel;
#elif MC_VER >= MC_1_18_2
import net.minecraftforge.network.PacketDistributor;
import net.minecraftforge.network.NetworkRegistry;
import net.minecraftforge.network.simple.SimpleChannel;
#elif MC_VER >= MC_1_17_1
import net.minecraftforge.fmllegacy.network.NetworkRegistry;
import net.minecraftforge.fmllegacy.network.PacketDistributor;
import net.minecraftforge.fmllegacy.network.simple.SimpleChannel;
#else // < 1.17.1
import net.minecraftforge.fml.network.NetworkRegistry;
import net.minecraftforge.fml.network.simple.SimpleChannel;
import net.minecraftforge.fml.network.PacketDistributor;
#endif
import java.util.function.BiConsumer;
import java.util.function.Consumer;
public class ForgePluginPacketSender extends AbstractPluginPacketSender
{
public static final SimpleChannel PLUGIN_CHANNEL =
#if MC_VER >= MC_1_20_2
ChannelBuilder.named(AbstractPluginPacketSender.WRAPPER_PACKET_RESOURCE)
.networkProtocolVersion(1)
.serverAcceptedVersions((status, version) -> true)
.clientAcceptedVersions((status, version) -> true)
.simpleChannel();
#else // < 1.20.2
NetworkRegistry.newSimpleChannel(
AbstractPluginPacketSender.WRAPPER_PACKET_RESOURCE,
() -> "1",
ignored -> true,
ignored -> true
);
#endif
public static void setPacketHandler(Consumer<AbstractNetworkMessage> consumer)
{
setPacketHandler((player, message) -> consumer.accept(message));
}
public static void setPacketHandler(BiConsumer<IServerPlayerWrapper, AbstractNetworkMessage> consumer)
{
#if MC_VER >= MC_1_20_2
PLUGIN_CHANNEL.messageBuilder(MessageWrapper.class, 0)
.encoder((wrapper, out) -> AbstractPluginPacketSender.encodeMessage(out, wrapper.message))
.decoder(in -> new MessageWrapper(AbstractPluginPacketSender.decodeMessage(in)))
.consumerNetworkThread((wrapper, context) ->
{
if (wrapper.message != null)
{
if (context.getSender() != null)
{
consumer.accept(ServerPlayerWrapper.getWrapper(context.getSender()), wrapper.message);
}
else
{
consumer.accept(null, wrapper.message);
}
}
context.setPacketHandled(true);
})
.add();
#else // < 1.20.2
PLUGIN_CHANNEL.registerMessage(0, MessageWrapper.class,
(wrapper, out) -> AbstractPluginPacketSender.encodeMessage(out, wrapper.message),
in -> new MessageWrapper(AbstractPluginPacketSender.decodeMessage(in)),
(wrapper, context) ->
{
if (wrapper.message != null)
{
if (context.get().getSender() != null)
{
consumer.accept(ServerPlayerWrapper.getWrapper(context.get().getSender()), wrapper.message);
}
else
{
consumer.accept(null, wrapper.message);
}
}
context.get().setPacketHandled(true);
}
);
#endif
}
@Override
public void sendToServer(AbstractNetworkMessage message)
{
#if MC_VER >= MC_1_20_2
PLUGIN_CHANNEL.send(new MessageWrapper(message), PacketDistributor.SERVER.noArg());
#else // < 1.20.2
PLUGIN_CHANNEL.send(PacketDistributor.SERVER.noArg(), new MessageWrapper(message));
#endif
}
@Override
public void sendToClient(ServerPlayer serverPlayer, AbstractNetworkMessage message)
{
#if MC_VER >= MC_1_20_2
PLUGIN_CHANNEL.send(new MessageWrapper(message), PacketDistributor.PLAYER.with(serverPlayer));
#else // < 1.20.2
PLUGIN_CHANNEL.send(PacketDistributor.PLAYER.with(() -> serverPlayer), new MessageWrapper(message));
#endif
}
// Forge doesn't support using abstract classes
@SuppressWarnings({"ClassCanBeRecord", "RedundantSuppression"})
public static class MessageWrapper
{
public final AbstractNetworkMessage message;
public MessageWrapper(AbstractNetworkMessage message) { this.message = message; }
}
}
@@ -3,16 +3,20 @@ package com.seibel.distanthorizons.forge;
import com.seibel.distanthorizons.common.AbstractModInitializer; import com.seibel.distanthorizons.common.AbstractModInitializer;
import com.seibel.distanthorizons.common.util.ProxyUtil; import com.seibel.distanthorizons.common.util.ProxyUtil;
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper; import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
import com.seibel.distanthorizons.common.wrappers.misc.ServerPlayerWrapper;
import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper; import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper;
import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment; import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment;
import com.seibel.distanthorizons.core.api.internal.ServerApi; import com.seibel.distanthorizons.core.api.internal.ServerApi;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.LevelAccessor;
import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.TickEvent; import net.minecraftforge.event.TickEvent;
import net.minecraftforge.event.entity.player.PlayerEvent;
#if MC_VER < MC_1_19_2 #if MC_VER < MC_1_19_2
import net.minecraftforge.event.world.ChunkEvent; import net.minecraftforge.event.world.ChunkEvent;
import net.minecraftforge.event.world.WorldEvent; import net.minecraftforge.event.world.WorldEvent;
@@ -22,6 +26,13 @@ import net.minecraftforge.event.level.LevelEvent;
#endif #endif
import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.eventbus.api.SubscribeEvent;
#if MC_VER >= MC_1_19_4
import net.minecraft.core.registries.Registries;
#else // < 1.19.4
import net.minecraft.core.Registry;
import net.minecraft.core.RegistryAccess;
#endif
#if MC_VER == MC_1_16_5 #if MC_VER == MC_1_16_5
import net.minecraftforge.fml.event.server.FMLServerAboutToStartEvent; import net.minecraftforge.fml.event.server.FMLServerAboutToStartEvent;
import net.minecraftforge.fml.event.server.FMLServerStoppingEvent; import net.minecraftforge.fml.event.server.FMLServerStoppingEvent;
@@ -47,7 +58,6 @@ public class ForgeServerProxy implements AbstractModInitializer.IEventProxy
#endif #endif
private final ServerApi serverApi = ServerApi.INSTANCE; private final ServerApi serverApi = ServerApi.INSTANCE;
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
private final boolean isDedicated; private final boolean isDedicated;
public static Supplier<Boolean> isGenerationThreadChecker = null; public static Supplier<Boolean> isGenerationThreadChecker = null;
@@ -57,6 +67,10 @@ public class ForgeServerProxy implements AbstractModInitializer.IEventProxy
public void registerEvents() public void registerEvents()
{ {
MinecraftForge.EVENT_BUS.register(this); MinecraftForge.EVENT_BUS.register(this);
if (this.isDedicated)
{
ForgePluginPacketSender.setPacketHandler(ServerApi.INSTANCE::pluginMessageReceived);
}
} }
@@ -111,7 +125,7 @@ public class ForgeServerProxy implements AbstractModInitializer.IEventProxy
{ {
if (GetEventLevel(event) instanceof ServerLevel) if (GetEventLevel(event) instanceof ServerLevel)
{ {
this.serverApi.serverLevelLoadEvent(this.getServerLevelWrapper((ServerLevel) GetEventLevel(event))); this.serverApi.serverLevelLoadEvent(getServerLevelWrapper((ServerLevel) GetEventLevel(event)));
} }
} }
@@ -125,7 +139,7 @@ public class ForgeServerProxy implements AbstractModInitializer.IEventProxy
{ {
if (GetEventLevel(event) instanceof ServerLevel) if (GetEventLevel(event) instanceof ServerLevel)
{ {
this.serverApi.serverLevelUnloadEvent(this.getServerLevelWrapper((ServerLevel) GetEventLevel(event))); this.serverApi.serverLevelUnloadEvent(getServerLevelWrapper((ServerLevel) GetEventLevel(event)));
} }
} }
@@ -138,6 +152,22 @@ public class ForgeServerProxy implements AbstractModInitializer.IEventProxy
this.serverApi.serverChunkLoadEvent(chunk, levelWrapper); this.serverApi.serverChunkLoadEvent(chunk, levelWrapper);
} }
@SubscribeEvent
public void playerLoggedInEvent(PlayerEvent.PlayerLoggedInEvent event)
{ this.serverApi.serverPlayerJoinEvent(getServerPlayerWrapper(event)); }
@SubscribeEvent
public void playerLoggedOutEvent(PlayerEvent.PlayerLoggedOutEvent event)
{ this.serverApi.serverPlayerDisconnectEvent(getServerPlayerWrapper(event)); }
@SubscribeEvent
public void playerChangedDimensionEvent(PlayerEvent.PlayerChangedDimensionEvent event)
{
this.serverApi.serverPlayerLevelChangeEvent(
getServerPlayerWrapper(event),
getServerLevelWrapper(event.getFrom(), event),
getServerLevelWrapper(event.getTo(), event)
);
}
//================// //================//
@@ -147,4 +177,20 @@ public class ForgeServerProxy implements AbstractModInitializer.IEventProxy
private static ServerLevelWrapper getServerLevelWrapper(ServerLevel level) { return ServerLevelWrapper.getWrapper(level); } private static ServerLevelWrapper getServerLevelWrapper(ServerLevel level) { return ServerLevelWrapper.getWrapper(level); }
private static ServerLevelWrapper getServerLevelWrapper(ResourceKey<Level> resourceKey, PlayerEvent event)
{
//noinspection DataFlowIssue (possible NPE after getServer())
return getServerLevelWrapper(event.getEntity().getServer().getLevel(resourceKey));
}
private static ServerPlayerWrapper getServerPlayerWrapper(PlayerEvent event) {
return ServerPlayerWrapper.getWrapper(
#if MC_VER >= MC_1_19_2
(ServerPlayer) event.getEntity()
#else
(ServerPlayer) event.getPlayer()
#endif
);
}
} }
@@ -158,18 +158,4 @@ public class MixinLevelRenderer
} }
} }
#if MC_VER < MC_1_19_4
@Inject(at = @At(value = "TAIL", target = "Lnet/minecraft/world/level/lighting/LevelLightEngine;runUpdates(IZZ)I"), method = "renderLevel")
public void callAfterRunUpdates(PoseStack poseStack, float partialTick, long finishNanoTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f projectionMatrix, CallbackInfo ci)
#elif MC_VER < MC_1_20_1
@Inject(at = @At(value = "TAIL", target = "Lnet/minecraft/world/level/lighting/LevelLightEngine;runUpdates(IZZ)I"), method = "renderLevel")
public void callAfterRunUpdates(PoseStack poseStack, float partialTick, long finishNanoTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f projectionMatrix, CallbackInfo ci)
#else
@Inject(at = @At(value = "TAIL", target = "Lnet/minecraft/world/level/lighting/LevelLightEngine;runLightUpdates()I"), method = "renderLevel")
private void callAfterRunUpdates(PoseStack poseStack, float partialTick, long finishNanoTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f projectionMatrix, CallbackInfo ci)
#endif
{
ChunkWrapper.syncedUpdateClientLightStatus();
}
} }
@@ -0,0 +1,39 @@
#if MC_VER == MC_1_16_5
package com.seibel.distanthorizons.forge.mixins.server;
import com.seibel.distanthorizons.common.wrappers.misc.IMixinServerPlayer;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.Level;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(Entity.class)
public class MixinEntity
{
@Inject(at = @At("TAIL"), method = "setLevel")
public void setLevel(Level level, CallbackInfo ci)
{
if (this instanceof IMixinServerPlayer)
{
((IMixinServerPlayer) this).distantHorizons$setDimensionChangeDestination((ServerLevel) level);
}
}
}
#else
package com.seibel.distanthorizons.forge.mixins.server;
import net.minecraft.world.entity.Entity;
import org.spongepowered.asm.mixin.Mixin;
@Mixin(Entity.class)
public class MixinEntity
{
}
#endif
@@ -0,0 +1,68 @@
/*
* This file is part of the Distant Horizons mod
* licensed under the GNU LGPL v3 License.
*
* Copyright (C) 2020-2023 James Seibel
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.distanthorizons.forge.mixins.server;
import com.seibel.distanthorizons.common.wrappers.misc.IMixinServerPlayer;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.Entity;
import net.minecraftforge.common.util.ITeleporter;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(ServerPlayer.class)
public class MixinServerPlayer implements IMixinServerPlayer
{
@Unique
@Nullable
private volatile ServerLevel distantHorizons$dimensionChangeDestination;
@Override
@Nullable
public ServerLevel distantHorizons$getDimensionChangeDestination()
{ return this.distantHorizons$dimensionChangeDestination; }
#if MC_VER == MC_1_16_5
@Override
public void distantHorizons$setDimensionChangeDestination(ServerLevel dimensionChangeDestination)
{ this.distantHorizons$dimensionChangeDestination = dimensionChangeDestination; }
#endif
@Inject(at = @At("HEAD"), method = "changeDimension", remap = false)
public void changeDimension(ServerLevel destination, ITeleporter teleporter, CallbackInfoReturnable<Entity> cir)
{ this.distantHorizons$dimensionChangeDestination = destination; }
#if MC_VER >= MC_1_20_1
@Inject(at = @At("RETURN"), method = "setServerLevel")
public void setServerLevel(ServerLevel level, CallbackInfo ci)
{ this.distantHorizons$dimensionChangeDestination = null; }
#elif MC_VER >= MC_1_17_1
@Inject(at = @At("RETURN"), method = "setLevel")
public void setLevel(ServerLevel level, CallbackInfo ci)
{ this.distantHorizons$dimensionChangeDestination = null; }
#endif
}
@@ -6,7 +6,9 @@
"server.MixinUtilBackgroundThread", "server.MixinUtilBackgroundThread",
"server.MixinChunkGenerator", "server.MixinChunkGenerator",
"server.MixinTFChunkGenerator", "server.MixinTFChunkGenerator",
"server.MixinChunkMap" "server.MixinChunkMap",
"server.MixinServerPlayer",
"server.MixinEntity"
], ],
"client": [ "client": [
"client.MixinClientPacketListener", "client.MixinClientPacketListener",
+2 -3
View File
@@ -5,8 +5,8 @@ org.gradle.caching=true
# Mod Info # Mod Info
mod_name=DistantHorizons mod_name=DistantHorizons
mod_version=2.2.2-a-dev mod_version=2.3.0-a-dev
api_version=3.0.0 api_version=4.0.0
maven_group=com.seibel.distanthorizons maven_group=com.seibel.distanthorizons
mod_readable_name=Distant Horizons mod_readable_name=Distant Horizons
mod_description=This mod generates and renders simplified terrain beyond the normal view distance at a low performance cost. Allowing you to see much farther without turning your game into a slideshow. mod_description=This mod generates and renders simplified terrain beyond the normal view distance at a low performance cost. Allowing you to see much farther without turning your game into a slideshow.
@@ -31,7 +31,6 @@ fastutil_version=8.2.1
# Minecraft related libraries (included in MC's jar) # Minecraft related libraries (included in MC's jar)
log4j_version=2.23.1 log4j_version=2.23.1
netty_version=4.1.94.Final
lwjgl_version=3.3.1 lwjgl_version=3.3.1
joml_version=1.10.2 joml_version=1.10.2
+7 -5
View File
@@ -29,15 +29,17 @@ loom {
client { client {
client() client()
setConfigName("NeoForge Client") setConfigName("NeoForge Client")
ideConfigGenerated(true) ideConfigGenerated(false) // When true a run configuration file will be generated for IDE's. By default only set to true for the root project.
runDir("../run") runDir("../run/client")
//vmArgs("-XX:-OmitStackTraceInFastThrow", minecraftMemoryJavaArg) vmArgs("-Dio.netty.leakDetection.level=advanced") // https://netty.io/wiki/reference-counted-objects.html#leak-detection-levels
programArgs("--username", "Dev")
} }
server { server {
server() server()
setConfigName("NeoForge Server") setConfigName("NeoForge Server")
ideConfigGenerated(true) ideConfigGenerated(false)
runDir("../run") runDir("../run/server")
vmArgs("-Dio.netty.leakDetection.level=advanced")
} }
} }
} }
@@ -35,7 +35,6 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
import com.seibel.distanthorizons.coreapi.ModInfo;
import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.LevelAccessor;
import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.multiplayer.ClientLevel;
@@ -47,8 +46,6 @@ import net.neoforged.neoforge.event.level.LevelEvent;
import net.neoforged.neoforge.event.entity.player.PlayerInteractEvent; import net.neoforged.neoforge.event.entity.player.PlayerInteractEvent;
import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.ChunkAccess;
//import net.neoforged.network.NetworkRegistry;
//import net.neoforged.network.simple.SimpleChannel;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.lwjgl.glfw.GLFW; import org.lwjgl.glfw.GLFW;
@@ -90,11 +87,7 @@ public class NeoforgeClientProxy implements AbstractModInitializer.IEventProxy
@Override @Override
public void registerEvents() public void registerEvents() { NeoForge.EVENT_BUS.register(this); }
{
NeoForge.EVENT_BUS.register(this);
setupNetworkingListeners();
}
@@ -137,7 +130,7 @@ public class NeoforgeClientProxy implements AbstractModInitializer.IEventProxy
} }
ClientLevel clientLevel = (ClientLevel) level; ClientLevel clientLevel = (ClientLevel) level;
IClientLevelWrapper clientLevelWrapper = ClientLevelWrapper.getWrapper(clientLevel); IClientLevelWrapper clientLevelWrapper = ClientLevelWrapper.getWrapper(clientLevel, true);
// TODO this causes a crash due to level being set to null somewhere // TODO this causes a crash due to level being set to null somewhere
ClientApi.INSTANCE.clientLevelLoadEvent(clientLevelWrapper); ClientApi.INSTANCE.clientLevelLoadEvent(clientLevelWrapper);
} }
@@ -246,65 +239,6 @@ public class NeoforgeClientProxy implements AbstractModInitializer.IEventProxy
//============//
// networking //
//============//
public static void setupNetworkingListeners()
{
// multiversePluginChannel = NetworkRegistry.newSimpleChannel(
// new ResourceLocation(ModInfo.NETWORKING_RESOURCE_NAMESPACE, ModInfo.MULTIVERSE_PLUGIN_NAMESPACE),
// // network protocol version
// () -> ModInfo.MULTIVERSE_PLUGIN_PROTOCOL_VERSION +"",
// // client accepted versions
// ForgeClientProxy::isReceivedProtocolVersionAcceptable,
// // server accepted versions
// ForgeClientProxy::isReceivedProtocolVersionAcceptable
// );
//
// multiversePluginChannel.registerMessage(0/*should be incremented for each simple channel we listen to*/, ByteBuf.class,
// // encoder
// (pack, friendlyByteBuf) -> { },
// // decoder
// (friendlyByteBuf) -> friendlyByteBuf.asByteBuf(),
// // message consumer
// (nettyByteBuf, contextRef) ->
// {
// ClientApi.INSTANCE.serverMessageReceived(nettyByteBuf);
// contextRef.get().setPacketHandled(true);
// }
// );
}
public static boolean isReceivedProtocolVersionAcceptable(String versionString)
{
if (versionString.toLowerCase().contains("allowvanilla"))
{
// allow using networking on vanilla servers
return true;
}
else if (versionString.toLowerCase().contains("absent"))
{
// allow using networking even if DH isn't installed on the server
return true;
}
else
{
// DH is installed on the server, check if the version is valid to use
try
{
int version = Integer.parseInt(versionString);
return ModInfo.MULTIVERSE_PLUGIN_PROTOCOL_VERSION == version;
}
catch (NumberFormatException ignored)
{
return false;
}
}
}
//===========// //===========//
// rendering // // rendering //
//===========// //===========//
@@ -24,7 +24,9 @@ import com.seibel.distanthorizons.common.AbstractModInitializer;
import com.seibel.distanthorizons.common.wrappers.gui.GetConfigScreen; import com.seibel.distanthorizons.common.wrappers.gui.GetConfigScreen;
import com.seibel.distanthorizons.core.api.internal.ClientApi; import com.seibel.distanthorizons.core.api.internal.ClientApi;
import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.core.api.internal.ServerApi;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IPluginPacketSender;
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IModChecker; import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IModChecker;
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IOptifineAccessor; import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IOptifineAccessor;
import com.seibel.distanthorizons.coreapi.ModInfo; import com.seibel.distanthorizons.coreapi.ModInfo;
@@ -32,6 +34,7 @@ import com.seibel.distanthorizons.neoforge.wrappers.modAccessor.ModChecker;
import com.seibel.distanthorizons.neoforge.wrappers.modAccessor.OptifineAccessor; import com.seibel.distanthorizons.neoforge.wrappers.modAccessor.OptifineAccessor;
import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.CommandSourceStack;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import net.neoforged.bus.api.EventPriority;
import net.neoforged.bus.api.IEventBus; import net.neoforged.bus.api.IEventBus;
import net.neoforged.fml.ModLoadingContext; import net.neoforged.fml.ModLoadingContext;
import net.neoforged.fml.common.Mod; import net.neoforged.fml.common.Mod;
@@ -40,6 +43,7 @@ import net.neoforged.fml.event.lifecycle.FMLDedicatedServerSetupEvent;
import net.neoforged.neoforge.common.NeoForge; import net.neoforged.neoforge.common.NeoForge;
import net.neoforged.neoforge.event.RegisterCommandsEvent; import net.neoforged.neoforge.event.RegisterCommandsEvent;
import net.neoforged.neoforge.event.server.ServerStartingEvent; import net.neoforged.neoforge.event.server.ServerStartingEvent;
import net.neoforged.neoforge.network.event.RegisterPayloadHandlersEvent;
import java.util.function.Consumer; import java.util.function.Consumer;
@@ -55,19 +59,42 @@ import net.neoforged.neoforge.client.gui.IConfigScreenFactory;
* check out the ClientProxy. * check out the ClientProxy.
*/ */
@Mod(ModInfo.ID) @Mod(ModInfo.ID)
@SuppressWarnings("unused")
public class NeoforgeMain extends AbstractModInitializer public class NeoforgeMain extends AbstractModInitializer
{ {
public NeoforgeMain(IEventBus eventBus) public NeoforgeMain(IEventBus eventBus)
{ {
eventBus.addListener((FMLClientSetupEvent e) -> this.onInitializeClient()); eventBus.addListener((FMLClientSetupEvent e) -> {
eventBus.addListener((FMLDedicatedServerSetupEvent e) -> this.onInitializeServer()); this.onInitializeClient();
eventBus.addListener(this::registerNetworkingClient);
});
eventBus.addListener((FMLDedicatedServerSetupEvent e) -> {
this.onInitializeServer();
eventBus.addListener(this::registerNetworkingServer);
});
} }
//============//
// networking //
//============//
public void registerNetworkingClient(RegisterPayloadHandlersEvent event)
{ NeoforgePluginPacketSender.setPacketHandler(event, ClientApi.INSTANCE::pluginMessageReceived); }
public void registerNetworkingServer(RegisterPayloadHandlersEvent event)
{ NeoforgePluginPacketSender.setPacketHandler(event, ServerApi.INSTANCE::pluginMessageReceived); }
@Override @Override
protected IEventProxy createServerProxy(boolean isDedicated) { return new NeoforgeServerProxy(isDedicated); } protected IEventProxy createServerProxy(boolean isDedicated) { return new NeoforgeServerProxy(isDedicated); }
@Override @Override
protected void createInitialBindings() { SingletonInjector.INSTANCE.bind(IModChecker.class, ModChecker.INSTANCE); } protected void createInitialBindings()
{
SingletonInjector.INSTANCE.bind(IModChecker.class, ModChecker.INSTANCE);
SingletonInjector.INSTANCE.bind(IPluginPacketSender.class, new NeoforgePluginPacketSender());
}
@Override @Override
protected IEventProxy createClientProxy() { return new NeoforgeClientProxy(); } protected IEventProxy createClientProxy() { return new NeoforgeClientProxy(); }
@@ -116,7 +143,7 @@ public class NeoforgeMain extends AbstractModInitializer
@Override @Override
protected void subscribeServerStartingEvent(Consumer<MinecraftServer> eventHandler) protected void subscribeServerStartingEvent(Consumer<MinecraftServer> eventHandler)
{ {
NeoForge.EVENT_BUS.addListener((ServerStartingEvent e) -> { eventHandler.accept(e.getServer()); }); NeoForge.EVENT_BUS.addListener(EventPriority.HIGH, (ServerStartingEvent e) -> { eventHandler.accept(e.getServer()); });
} }
@Override @Override
@@ -0,0 +1,50 @@
package com.seibel.distanthorizons.neoforge;
import com.seibel.distanthorizons.common.CommonPacketPayload;
import com.seibel.distanthorizons.common.wrappers.misc.ServerPlayerWrapper;
import com.seibel.distanthorizons.common.AbstractPluginPacketSender;
import com.seibel.distanthorizons.core.network.messages.AbstractNetworkMessage;
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IServerPlayerWrapper;
import net.minecraft.server.level.ServerPlayer;
import net.neoforged.neoforge.network.PacketDistributor;
import net.neoforged.neoforge.network.event.RegisterPayloadHandlersEvent;
import net.neoforged.neoforge.network.registration.PayloadRegistrar;
import java.util.Optional;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
public class NeoforgePluginPacketSender extends AbstractPluginPacketSender
{
private static BiConsumer<IServerPlayerWrapper, AbstractNetworkMessage> packetConsumer;
public static void setPacketHandler(RegisterPayloadHandlersEvent event, Consumer<AbstractNetworkMessage> consumer)
{ setPacketHandler(event, (player, buffer) -> consumer.accept(buffer)); }
public static void setPacketHandler(RegisterPayloadHandlersEvent event, BiConsumer<IServerPlayerWrapper, AbstractNetworkMessage> consumer)
{
packetConsumer = consumer;
PayloadRegistrar registrar = event.registrar("1").optional();
registrar.playBidirectional(CommonPacketPayload.TYPE, new CommonPacketPayload.Codec(), (payload, context) ->
{
ServerPlayerWrapper serverPlayer = Optional.of(context.player())
.map(player -> player instanceof ServerPlayer ? (ServerPlayer) player : null)
.map(ServerPlayerWrapper::getWrapper)
.orElse(null);
if (payload.message() != null)
{
packetConsumer.accept(serverPlayer, payload.message());
}
});
}
@Override
public void sendToServer(AbstractNetworkMessage message)
{ PacketDistributor.sendToServer(new CommonPacketPayload(message)); }
@Override
public void sendToClient(ServerPlayer serverPlayer, AbstractNetworkMessage message)
{ PacketDistributor.sendToPlayer(serverPlayer, new CommonPacketPayload(message)); }
}
@@ -3,15 +3,20 @@ package com.seibel.distanthorizons.neoforge;
import com.seibel.distanthorizons.common.AbstractModInitializer; import com.seibel.distanthorizons.common.AbstractModInitializer;
import com.seibel.distanthorizons.common.util.ProxyUtil; import com.seibel.distanthorizons.common.util.ProxyUtil;
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper; import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
import com.seibel.distanthorizons.common.wrappers.misc.ServerPlayerWrapper;
import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper; import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper;
import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment; import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment;
import com.seibel.distanthorizons.core.api.internal.ServerApi; import com.seibel.distanthorizons.core.api.internal.ServerApi;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.LevelAccessor;
import net.neoforged.neoforge.common.NeoForge; import net.neoforged.neoforge.common.NeoForge;
import net.neoforged.neoforge.event.entity.player.PlayerEvent;
import net.neoforged.neoforge.event.level.ChunkEvent; import net.neoforged.neoforge.event.level.ChunkEvent;
import net.neoforged.neoforge.event.level.LevelEvent; import net.neoforged.neoforge.event.level.LevelEvent;
import net.neoforged.bus.api.SubscribeEvent; import net.neoforged.bus.api.SubscribeEvent;
@@ -123,6 +128,21 @@ public class NeoforgeServerProxy implements AbstractModInitializer.IEventProxy
this.serverApi.serverChunkLoadEvent(chunk, levelWrapper); this.serverApi.serverChunkLoadEvent(chunk, levelWrapper);
} }
@SubscribeEvent
public void playerLoggedInEvent(PlayerEvent.PlayerLoggedInEvent event) { this.serverApi.serverPlayerJoinEvent(getServerPlayerWrapper(event)); }
@SubscribeEvent
public void playerLoggedOutEvent(PlayerEvent.PlayerLoggedOutEvent event)
{ this.serverApi.serverPlayerDisconnectEvent(getServerPlayerWrapper(event)); }
@SubscribeEvent
public void playerChangedDimensionEvent(PlayerEvent.PlayerChangedDimensionEvent event)
{
this.serverApi.serverPlayerLevelChangeEvent(
getServerPlayerWrapper(event),
getServerLevelWrapper(event.getFrom(), event),
getServerLevelWrapper(event.getTo(), event)
);
}
//================// //================//
@@ -130,6 +150,12 @@ public class NeoforgeServerProxy implements AbstractModInitializer.IEventProxy
//================// //================//
private static ServerLevelWrapper getServerLevelWrapper(ServerLevel level) { return ServerLevelWrapper.getWrapper(level); } private static ServerLevelWrapper getServerLevelWrapper(ServerLevel level) { return ServerLevelWrapper.getWrapper(level); }
private static ServerLevelWrapper getServerLevelWrapper(ResourceKey<Level> resourceKey, PlayerEvent event)
{
//noinspection DataFlowIssue (possible NPE after getServer())
return getServerLevelWrapper(event.getEntity().getServer().getLevel(resourceKey));
}
private static ServerPlayerWrapper getServerPlayerWrapper(PlayerEvent event) { return ServerPlayerWrapper.getWrapper((ServerPlayer) event.getEntity()); }
} }
@@ -1,8 +1,11 @@
package com.seibel.distanthorizons.neoforge.mixins.client; package com.seibel.distanthorizons.neoforge.mixins.client;
import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper;
import com.seibel.distanthorizons.core.api.internal.ClientApi; import com.seibel.distanthorizons.core.api.internal.ClientApi;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.multiplayer.ClientPacketListener; import net.minecraft.client.multiplayer.ClientPacketListener;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@@ -10,10 +13,16 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(ClientPacketListener.class) @Mixin(ClientPacketListener.class)
public class MixinClientPacketListener public class MixinClientPacketListener
{ {
@Shadow
private ClientLevel level;
// TODO update fabric version as well // TODO update fabric version as well
@Inject(method = "handleLogin", at = @At("RETURN")) @Inject(method = "handleLogin", at = @At("RETURN"))
void onHandleLoginEnd(CallbackInfo ci) { ClientApi.INSTANCE.onClientOnlyConnected(); } void onHandleLoginEnd(CallbackInfo ci)
{
ClientApi.INSTANCE.onClientOnlyConnected();
ClientApi.INSTANCE.clientLevelLoadEvent(ClientLevelWrapper.getWrapper(this.level, true));
}
#if MC_VER < MC_1_19_4 #if MC_VER < MC_1_19_4
@Inject(method = "cleanup", at = @At("HEAD")) @Inject(method = "cleanup", at = @At("HEAD"))
@@ -142,22 +142,5 @@ public class MixinLevelRenderer
} }
} }
#if MC_VER < MC_1_19_4
@Inject(at = @At(value = "TAIL", target = "Lnet/minecraft/world/level/lighting/LevelLightEngine;runUpdates(IZZ)I"), method = "renderLevel")
public void callAfterRunUpdates(PoseStack poseStack, float partialTick, long finishNanoTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f projectionMatrix, CallbackInfo ci)
#elif MC_VER < MC_1_20_1
@Inject(at = @At(value = "TAIL", target = "Lnet/minecraft/world/level/lighting/LevelLightEngine;runUpdates(IZZ)I"), method = "renderLevel")
public void callAfterRunUpdates(PoseStack poseStack, float partialTick, long finishNanoTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f projectionMatrix, CallbackInfo ci)
#elif MC_VER < MC_1_20_6
@Inject(at = @At(value = "TAIL", target = "Lnet/minecraft/world/level/lighting/LevelLightEngine;runLightUpdates()I"), method = "renderLevel")
private void callAfterRunUpdates(PoseStack poseStack, float partialTick, long finishNanoTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f projectionMatrix, CallbackInfo ci)
#else
@Inject(at = @At(value = "TAIL", target = "Lnet/minecraft/world/level/lighting/LevelLightEngine;runLightUpdates()I"), method = "renderLevel")
private void callAfterRunUpdates(CallbackInfo ci)
#endif
{
ChunkWrapper.syncedUpdateClientLightStatus();
}
} }
@@ -0,0 +1,73 @@
/*
* This file is part of the Distant Horizons mod
* licensed under the GNU LGPL v3 License.
*
* Copyright (C) 2020-2023 James Seibel
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.distanthorizons.neoforge.mixins.server;
import com.seibel.distanthorizons.common.wrappers.misc.IMixinServerPlayer;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.Entity;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
#if MC_VER >= MC_1_21_1
import net.minecraft.world.level.portal.DimensionTransition;
#endif
@Mixin(ServerPlayer.class)
public class MixinServerPlayer implements IMixinServerPlayer
{
@Unique
@Nullable
private ServerLevel distantHorizons$dimensionChangeDestination;
@Unique
@Override
@Nullable
public ServerLevel distantHorizons$getDimensionChangeDestination()
{ return this.distantHorizons$dimensionChangeDestination; }
@Inject(at = @At("HEAD"), method = "changeDimension")
#if MC_VER >= MC_1_21_1
public void changeDimension(DimensionTransition dimensionTransition, CallbackInfoReturnable<Entity> cir)
{ this.distantHorizons$dimensionChangeDestination = dimensionTransition.newLevel(); }
#else
public void changeDimension(ServerLevel destination, CallbackInfoReturnable<Entity> cir)
{ this.distantHorizons$dimensionChangeDestination = destination; }
#endif
#if MC_VER >= MC_1_20_1
@Inject(at = @At("RETURN"), method = "setServerLevel")
public void setServerLevel(ServerLevel level, CallbackInfo ci)
#else
@Inject(at = @At("RETURN"), method = "setLevel")
public void setLevel(ServerLevel level, CallbackInfo ci)
#endif
{
this.distantHorizons$dimensionChangeDestination = null;
}
}
@@ -6,7 +6,8 @@
"server.MixinUtilBackgroundThread", "server.MixinUtilBackgroundThread",
"server.MixinChunkGenerator", "server.MixinChunkGenerator",
"server.MixinTFChunkGenerator", "server.MixinTFChunkGenerator",
"server.MixinChunkMap" "server.MixinChunkMap",
"server.MixinServerPlayer"
], ],
"client": [ "client": [
"client.MixinClientPacketListener", "client.MixinClientPacketListener",
+57
View File
@@ -0,0 +1,57 @@
# Usage: .\verifyall.ps1 [forge|fabric|whatever to put before ":classes"]
param (
[string]$prefix
)
# Clear the screen
Clear-Host
# Define an array to hold completed builds with color information
$completedBuilds = @()
# Get all version properties files
$versionFiles = Get-ChildItem -Path "./versionProperties/" -Filter "*.properties"
foreach ($versionFile in $versionFiles) {
$version = [System.IO.Path]::GetFileNameWithoutExtension($versionFile.Name)
# Run the gradle command
$gradleCommand = ".\gradlew $($prefix)classes -PmcVer=$version"
$process = Start-Process -FilePath "cmd.exe" -ArgumentList "/c $gradleCommand" -NoNewWindow -PassThru -Wait
# Determine the result color
if ($process.ExitCode -eq 0) {
$color = "Green"
} else {
$color = "Red"
}
# Print the result with formatting
$versionLength = $version.Length
$topChars = ("^" * $versionLength)
$bottomChars = ("=" * $versionLength)
Write-Host "# $topChars" -ForegroundColor $color
Write-Host "# $version" -ForegroundColor $color
Write-Host "# $bottomChars" -ForegroundColor $color
Write-Host
# Add result to completed builds with color
$completedBuilds += @{ Version = $version; Color = $color }
}
# Run clean and classes gradle tasks
Start-Process -FilePath "cmd.exe" -ArgumentList "/c .\gradlew clean" -NoNewWindow -Wait
Start-Process -FilePath "cmd.exe" -ArgumentList "/c .\gradlew classes" -NoNewWindow -Wait
# Print build results
Write-Host
Write-Host "Build results:"
foreach ($build in $completedBuilds) {
Write-Host $build.Version -ForegroundColor $build.Color -NoNewline
Write-Host " " -NoNewline # Add a space between versions
}
Write-Host # End the line after all versions are printed
+43
View File
@@ -0,0 +1,43 @@
#!/bin/bash
# Usage: ./verifyall.sh [forge|fabric|whatever to put before ":classes"]
if [ -n "$1" ]; then
prefix="$1:"
fi
clear
trap "echo; exit" INT
declare -a completed_builds
for version in $(ls ./versionProperties/); do
version=${version%".properties"}
result=""
if ./gradlew "$prefix"classes -PmcVer=$version; then
result+="\e[1;32m"
echo -ne "\e[1;32m"
else
result+="\e[1;31m"
echo -ne "\e[1;31m"
fi
result+=$version
result+="\e[0m"
version_length=${#version}
top_chars=$(printf '^%.0s' $(seq 1 $version_length))
bottom_chars=$(printf '=%.0s' $(seq 1 $version_length))
echo "# $top_chars"
echo "# $version"
echo "# $bottom_chars"
echo -e "\e[0m"
completed_builds+=($result)
done
./gradlew clean
./gradlew classes
echo
echo -e "\e[1mBuild results:\e[0m"
echo -e "${completed_builds[*]}"
+4
View File
@@ -0,0 +1,4 @@
Remove-Item -Recurse -Force "run/client/Distant_Horizons_server_data"
Get-ChildItem -Path "run/server" -Recurse -Filter "Distant_Horizons" | ForEach-Object { Remove-Item -Recurse -Force $_.FullName }
Get-ChildItem -Path "run/server" -Recurse -Filter "DistantHorizons.sqlite" | ForEach-Object { Remove-Item -Force $_.FullName }
+5
View File
@@ -0,0 +1,5 @@
#!/bin/sh
rm -rf run/client/Distant_Horizons_server_data
rm -rf $(find run/server -name "Distant_Horizons")
rm -rf $(find run/server -name "DistantHorizons.sqlite")
+4 -1
View File
@@ -7,6 +7,9 @@ accessWidenerVersion=1_16
builds_for=fabric,forge builds_for=fabric,forge
embed_joml=true embed_joml=true
# Netty
netty_version=4.1.25.Final
# Fabric loader # Fabric loader
fabric_loader_version=0.14.24 fabric_loader_version=0.14.24
fabric_api_version=0.42.0+1.16 fabric_api_version=0.42.0+1.16
@@ -21,7 +24,7 @@ fabric_api_version=0.42.0+1.16
immersive_portals_version= immersive_portals_version=
canvas_version= canvas_version=
fabric_incompatibility_list={ "iris": "*" } fabric_incompatibility_list={ "iris": "*", "oculus": "*" }
fabric_recommend_list={} fabric_recommend_list={}
# Fabric mod run # Fabric mod run
+4 -1
View File
@@ -7,6 +7,9 @@ accessWidenerVersion=1_17
builds_for=fabric,forge builds_for=fabric,forge
embed_joml=true embed_joml=true
# Netty
netty_version=4.1.25.Final
# Fabric loader # Fabric loader
fabric_loader_version=0.14.24 fabric_loader_version=0.14.24
fabric_api_version=0.46.1+1.17 fabric_api_version=0.46.1+1.17
@@ -21,7 +24,7 @@ fabric_api_version=0.46.1+1.17
immersive_portals_version= immersive_portals_version=
canvas_version= canvas_version=
fabric_incompatibility_list={ "iris": "*" } fabric_incompatibility_list={ "iris": "*", "oculus": "*" }
fabric_recommend_list={} fabric_recommend_list={}
# Fabric mod run # Fabric mod run
+4 -1
View File
@@ -7,6 +7,9 @@ accessWidenerVersion=1_18
builds_for=fabric,forge builds_for=fabric,forge
embed_joml=true embed_joml=true
# Netty
netty_version=4.1.68.Final
# Fabric loader # Fabric loader
fabric_loader_version=0.14.24 fabric_loader_version=0.14.24
fabric_api_version=0.76.0+1.18.2 fabric_api_version=0.76.0+1.18.2
@@ -22,7 +25,7 @@ fabric_api_version=0.76.0+1.18.2
immersive_portals_version=v1.4.11-1.18 immersive_portals_version=v1.4.11-1.18
canvas_version=mc118:1.0.2616 canvas_version=mc118:1.0.2616
fabric_incompatibility_list={ "iris": "*" } fabric_incompatibility_list={ "iris": "*", "oculus": "*" }
fabric_recommend_list={} fabric_recommend_list={}
# Fabric mod run # Fabric mod run
+4 -1
View File
@@ -7,6 +7,9 @@ accessWidenerVersion=1_19_2
builds_for=fabric,forge builds_for=fabric,forge
embed_joml=true embed_joml=true
# Netty
netty_version=4.1.77.Final
# Fabric loader # Fabric loader
fabric_loader_version=0.14.24 fabric_loader_version=0.14.24
fabric_api_version=0.76.1+1.19.2 fabric_api_version=0.76.1+1.19.2
@@ -21,7 +24,7 @@ fabric_api_version=0.76.1+1.19.2
immersive_portals_version= immersive_portals_version=
canvas_version=mc119-1.0.2480 canvas_version=mc119-1.0.2480
fabric_incompatibility_list={ "iris": "*" } fabric_incompatibility_list={ "iris": "*", "oculus": "*" }
fabric_recommend_list={} fabric_recommend_list={}
# Fabric mod run # Fabric mod run
+4 -1
View File
@@ -6,6 +6,9 @@ compatible_minecraft_versions=["1.19.4"]
accessWidenerVersion=1_19_4 accessWidenerVersion=1_19_4
builds_for=fabric,forge builds_for=fabric,forge
# Netty
netty_version=4.1.82.Final
# Fabric loader # Fabric loader
fabric_loader_version=0.14.24 fabric_loader_version=0.14.24
fabric_api_version=0.87.1+1.19.4 fabric_api_version=0.87.1+1.19.4
@@ -20,7 +23,7 @@ fabric_api_version=0.87.1+1.19.4
immersive_portals_version= immersive_portals_version=
canvas_version= canvas_version=
fabric_incompatibility_list={ "iris": "*" } fabric_incompatibility_list={ "iris": "*", "oculus": "*" }
fabric_recommend_list={} fabric_recommend_list={}
# Fabric mod run # Fabric mod run
+4 -1
View File
@@ -6,6 +6,9 @@ compatible_minecraft_versions=["1.20", "1.20.1"]
accessWidenerVersion=1_20 accessWidenerVersion=1_20
builds_for=fabric,forge builds_for=fabric,forge
# Netty
netty_version=4.1.82.Final
# Fabric loader # Fabric loader
fabric_loader_version=0.15.6 fabric_loader_version=0.15.6
fabric_api_version=0.90.4+1.20.1 fabric_api_version=0.90.4+1.20.1
@@ -20,7 +23,7 @@ fabric_api_version=0.90.4+1.20.1
immersive_portals_version= immersive_portals_version=
canvas_version= canvas_version=
fabric_incompatibility_list={ "iris": "<=1.7.4" } fabric_incompatibility_list={ "iris": "<=1.7.4", "oculus": "<=1.7.0" }
fabric_recommend_list={} fabric_recommend_list={}
# Fabric mod run # Fabric mod run
+4 -1
View File
@@ -6,6 +6,9 @@ compatible_minecraft_versions=["1.20.2"]
accessWidenerVersion=1_20_2 accessWidenerVersion=1_20_2
builds_for=fabric,forge builds_for=fabric,forge
# Netty
netty_version=4.1.97.Final
# Fabric loader # Fabric loader
fabric_loader_version=0.15.6 fabric_loader_version=0.15.6
fabric_api_version=0.90.4+1.20.2 fabric_api_version=0.90.4+1.20.2
@@ -20,7 +23,7 @@ fabric_api_version=0.90.4+1.20.2
immersive_portals_version= immersive_portals_version=
canvas_version= canvas_version=
fabric_incompatibility_list={ "iris": "<=1.7.4" } fabric_incompatibility_list={ "iris": "<=1.7.4", "oculus": "<=1.7.0" }
fabric_recommend_list={} fabric_recommend_list={}
# Fabric mod run # Fabric mod run
+4 -1
View File
@@ -7,6 +7,9 @@ accessWidenerVersion=1_20_2
builds_for=fabric,forge builds_for=fabric,forge
# neoforge can be added once the issue with mixins has been resolved # neoforge can be added once the issue with mixins has been resolved
# Netty
netty_version=4.1.97.Final
# Fabric loader # Fabric loader
fabric_loader_version=0.15.6 fabric_loader_version=0.15.6
fabric_api_version=0.91.2+1.20.4 fabric_api_version=0.91.2+1.20.4
@@ -21,7 +24,7 @@ fabric_api_version=0.91.2+1.20.4
immersive_portals_version= immersive_portals_version=
canvas_version= canvas_version=
fabric_incompatibility_list={ "iris": "<=1.7.4" } fabric_incompatibility_list={ "iris": "<=1.7.4", "oculus": "<=1.7.0" }
fabric_recommend_list={} fabric_recommend_list={}
# Fabric mod run # Fabric mod run
+4 -1
View File
@@ -7,6 +7,9 @@ accessWidenerVersion=1_20_6
builds_for=fabric,neoforge builds_for=fabric,neoforge
# forge is broken due to gradle/build script issues # forge is broken due to gradle/build script issues
# Netty
netty_version=4.1.97.Final
# Fabric loader # Fabric loader
fabric_loader_version=0.15.10 fabric_loader_version=0.15.10
fabric_api_version=0.97.8+1.20.6 fabric_api_version=0.97.8+1.20.6
@@ -21,7 +24,7 @@ fabric_api_version=0.97.8+1.20.6
immersive_portals_version= immersive_portals_version=
canvas_version= canvas_version=
fabric_incompatibility_list={ "iris": "<=1.7.4" } fabric_incompatibility_list={ "iris": "<=1.7.4", "oculus": "<=1.7.0" }
fabric_recommend_list={} fabric_recommend_list={}
# Fabric mod run # Fabric mod run
+4 -1
View File
@@ -7,6 +7,9 @@ accessWidenerVersion=1_20_6
builds_for=fabric,neoforge builds_for=fabric,neoforge
# forge is broken due to gradle/build script issues # forge is broken due to gradle/build script issues
# Netty
netty_version=4.1.97.Final
# Fabric loader # Fabric loader
fabric_loader_version=0.15.11 fabric_loader_version=0.15.11
fabric_api_version=0.100.1+1.21 fabric_api_version=0.100.1+1.21
@@ -21,7 +24,7 @@ fabric_api_version=0.100.1+1.21
immersive_portals_version= immersive_portals_version=
canvas_version= canvas_version=
fabric_incompatibility_list={ "iris": "<=1.7.4" } fabric_incompatibility_list={ "iris": "<=1.7.4", "oculus": "<=1.7.0" }
fabric_recommend_list={} fabric_recommend_list={}
# Fabric mod run # Fabric mod run