Compare commits

..

60 Commits

Author SHA1 Message Date
James Seibel fce2868c62 remove dev from version number for release 2025-03-06 07:41:52 -06:00
James Seibel 0fba015f54 Fix crashing on MC 1.20.1 and older when updates aren't found 2 2025-03-01 09:19:52 -06:00
James Seibel f251c90472 Fix crashing on MC 1.20.1 and older when updates aren't found 2025-03-01 09:13:47 -06:00
s809 492a051a3b Replace chunk counts with speed in pregen 2025-02-27 21:08:31 +05:00
s809 0aa4743c1b Should be division instead of multiplication 2025-02-26 23:17:05 +05:00
s809 85f16944b2 Offset generation bounds by teleportation scale 2025-02-26 22:13:43 +05:00
James Seibel dddb0be2ac duct tape fix to reduce chance of LOD uploading requiring MC reboot 2025-02-25 07:26:12 -06:00
s809 4a3effa2f5 Remember split section responses temporarily 2025-02-22 20:55:18 +05:00
s809 a0a9151bfd Fix foreground thread sometimes blocking server shutdown 2025-02-19 21:17:42 +05:00
s809 aa3d15f38f Show section numbers in pregen 2025-02-19 20:37:29 +05:00
James Seibel adcb2a3a05 Fix IDhApiConfigValue.clearValue() failing for some deprecated functions 2025-02-17 21:16:27 -06:00
James Seibel 78f2cb24cc Fix DB leaks in FullDataV2Repo 2025-02-16 20:07:13 -06:00
James Seibel 67945509ed Fix errors related to player pos being unloaded 2025-02-16 19:54:11 -06:00
James Seibel c653e526a5 Revert 10 minute memoization for world gen 2025-02-15 11:56:25 -06:00
James Seibel 49b50c4c88 Fix beacon culling with auto overdraw prevention 2025-02-15 11:12:57 -06:00
James Seibel 7449f46c5e Add missing cave blocks for cave culling 2025-02-15 11:06:57 -06:00
James Seibel 069fc39aad up fabric api version for 1.21.1 to allow Immersive Portals testing 2025-02-14 07:48:32 -06:00
s809 4979ccf3e2 Invert generateOnlyInHighestDetail and rename to enableNSizedGeneration 2025-02-11 22:08:29 +05:00
James Seibel dd7f9c20b6 Put N-sized generation and upsampling behind experimental configs 2025-02-11 07:47:36 -06:00
James Seibel e96f9de1f0 Fix dimension wrapper creating duplicates for the same name 2025-02-11 07:05:34 -06:00
James Seibel c902e1957f Fix auto updater failing for nightly builds 2025-02-10 07:47:03 -06:00
James Seibel d40afb7a2a Fix C2ME slowdown again 2025-02-08 21:43:49 -06:00
James Seibel 01474d72e3 remove unneeded IVersionConstant methods 2025-02-08 11:39:26 -06:00
James Seibel 7c5af1836b add FIXME comment related to getChunkNbtDataAsync()
this method appears to be called much more often than it should be, very often 25 times per chunk position.
Very strange.
2025-02-08 11:12:06 -06:00
James Seibel a9bf6ae7e4 Merge branch 'main' of gitlab.com:distant-horizons-team/distant-horizons 2025-02-08 10:46:16 -06:00
James Seibel aef3162246 reduce test N-sized generator height 2025-02-08 10:45:55 -06:00
James Seibel 97ce869076 Fix C2ME causing memory use to explode with DH world gen 2025-02-08 10:45:38 -06:00
s809 91b3c83ffd Update core 2025-02-07 23:23:25 +05:00
James Seibel 1522df19cb Attempt to fix threadpool shutdown rejection exception 2025-02-07 07:26:07 -06:00
James Seibel 3845564128 Reduce world gen down time when using extremely fast generators 2025-02-07 07:15:31 -06:00
s809 23ef7cf27a Fix incorrect distance being used in update propagation SQL and reduce queue size 2025-02-07 01:05:18 +05:00
James Seibel bec28a5694 Merge branch 'main' of gitlab.com:distant-horizons-team/distant-horizons 2025-02-05 17:32:37 -06:00
James Seibel 8f20f103ad Fix empty data sources when moving in multiplayer or with N-sized world gen
Increases networking protocol from 9 -> 10
2025-02-05 17:32:30 -06:00
James Seibel 246e77cc56 Fix render enabled config getting set by world gen progress config 2025-02-02 19:55:06 -06:00
James Seibel 87fa29c77a Fix compiling with missing "E" 2025-02-02 15:52:20 -06:00
s809 5010256ce6 Update core 2025-02-02 20:30:57 +05:00
s809 a66ad19343 Balance tasks in thread pool using elapsed time instead of priorities 2025-02-02 20:30:04 +05:00
s809 913a458a1a Auto-move old save data to new location 2025-02-02 15:38:06 +05:00
s809 093d3a801e Remove generationProgressDisableMessageDisplayTimeInSeconds from server config command 2025-02-01 19:38:46 +05:00
s809 61ccf7bf60 Decrease delay between missing generation rechecks 2025-01-31 14:54:32 +05:00
s809 f948072253 Decrease delay between missing generation rechecks 2025-01-31 14:53:57 +05:00
s809 b748f27a1c Fix beacon beams flickering 2025-01-30 22:30:08 +05:00
s809 4dd4bb9ef0 Fix nightly self-updater after moving jars into zip root 2025-01-30 18:11:39 +05:00
s809 5051bde3b0 Add pycache into gitignore 2025-01-30 00:22:03 +05:00
s809 42cf639acc Merge branch 'test/artifacts-in-zip-root' 2025-01-30 00:21:02 +05:00
s809 9e6953a596 Fix relocation breaking runClient & runServer 2025-01-29 23:59:23 +05:00
s809 7f4f8a40eb Merge branch 'experimental/relocate_sqlite' 2025-01-29 23:23:36 +05:00
s809 89ca535a6f Add all the extra comments 2025-01-29 23:23:21 +05:00
s809 145182502e Do not relocate when python is not installed 2025-01-29 23:01:28 +05:00
s809 d61dfc9e03 Revert "Improve chunk processing throughput" 2025-01-28 22:56:52 +05:00
James Seibel 611d7d87ae Fix compiling for MC 1.19.2 and below 2025-01-26 18:12:01 -06:00
James Seibel 2f6a2d99ab Remove unneeded MixinLevelTicks (!73)
https://gitlab.com/distant-horizons-team/distant-horizons/-/merge_requests/73#note_2281882248
2025-01-26 17:47:32 -06:00
James Seibel d88ca0c98d Improve CPU usage and chunk update throughput 2025-01-26 17:13:28 -06:00
James Seibel 521bcdcc0f fix recalculate heightmap breaking stairs, slabs, and glass 2025-01-24 07:24:43 -06:00
s809 e070bf4244 More consistent names but reverse 2025-01-14 21:25:58 +05:00
s809 8287192cd0 More consistent names 2025-01-14 21:15:01 +05:00
s809 d40f4dfe19 Artifacts in zip root 4 2025-01-14 21:01:30 +05:00
s809 595cdf011a Artifacts in zip root 3 2025-01-14 20:56:44 +05:00
s809 96f2f8c3b2 Artifacts in zip root 2 2025-01-14 20:48:17 +05:00
s809 c883ded7c4 Artifacts in zip root 2025-01-14 20:39:21 +05:00
23 changed files with 263 additions and 285 deletions
+1
View File
@@ -27,6 +27,7 @@ Merged/
buildAllJars/
relocate_natives/.venv/
relocate_natives/__pycache__/
relocate_natives/apple-codesign/
relocate_natives/cache/
+11 -24
View File
@@ -44,28 +44,15 @@ build:
- ./gradlew clean -PmcVer="${MC_VER}" -PinfoGitCommit="${CI_COMMIT_SHA}" -PinfoGitBranch="${CI_COMMIT_BRANCH}" -PinfoBuildSource="GitLab CI (${CI_PIPELINE_ID})" --gradle-user-home cache/;
- ./gradlew build -PmcVer="${MC_VER}" -PinfoGitCommit="${CI_COMMIT_SHA}" -PinfoGitBranch="${CI_COMMIT_BRANCH}" -PinfoBuildSource="GitLab CI (${CI_PIPELINE_ID})" --gradle-user-home cache/;
- ./gradlew mergeJars -PmcVer="${MC_VER}" -PinfoGitCommit="${CI_COMMIT_SHA}" -PinfoGitBranch="${CI_COMMIT_BRANCH}" -PinfoBuildSource="GitLab CI (${CI_PIPELINE_ID})" --gradle-user-home cache/;
- cp ./fabric/build/libs/* ./forge/build/libs/* ./neoforge/build/libs/* ./Merged/* . || true
artifacts:
name: "NightlyBuild_${MC_VER}-${CI_COMMIT_SHORT_SHA}-${CI_COMMIT_TIMESTAMP}"
paths:
- Merged/*.jar
- quilt/build/libs/*.jar
- fabric/build/libs/*.jar
- forge/build/libs/*.jar
- neoforge/build/libs/*.jar
- ./*.jar
exclude:
# TODO: There is a lot of duplicate stuff here, try to maybe make it smaller
- fabric/build/libs/*-all.jar
- fabric/build/libs/*-dev.jar
- fabric/build/libs/*-sources.jar
- quilt/build/libs/*-all.jar
- quilt/build/libs/*-dev.jar
- quilt/build/libs/*-sources.jar
- forge/build/libs/*-all.jar
- forge/build/libs/*-dev.jar
- forge/build/libs/*-sources.jar
- neoforge/build/libs/*-all.jar
- neoforge/build/libs/*-dev.jar
- neoforge/build/libs/*-sources.jar
- ./*-all.jar
- ./*-dev.jar
- ./*-sources.jar
expire_in: 14 days
when: always
extends: .build_java
@@ -80,15 +67,15 @@ api:
# this also runs unit tests
- ./gradlew api:build --gradle-user-home cache/;
- ./gradlew api:addSourcesToCompiledJar --gradle-user-home cache/;
- cp ./coreSubProjects/api/build/libs/merged/* .
artifacts:
name: "Api_NightlyBuild-${CI_COMMIT_SHORT_SHA}-${CI_COMMIT_TIMESTAMP}"
name: "NightlyBuild_Api-${CI_COMMIT_SHORT_SHA}-${CI_COMMIT_TIMESTAMP}"
paths:
- coreSubProjects/api/build/libs/merged/*.jar
# can be uncommented if we don't want a jar with the source code
# - coreSubProjects/api/build/libs/*.jar
- ./*.jar
exclude:
- coreSubProjects/api/build/libs/merged/*-all.jar
- coreSubProjects/api/build/libs/merged/*-sources.jar
- ./*-all.jar
- ./*-dev.jar
- ./*-sources.jar
expire_in: 1 day
when: always
extends: .build_java
+19 -9
View File
@@ -78,7 +78,7 @@ forgix {
String loaderHyphenSeparatedList = ((String)gradle.builds_for).replaceAll(",", "-");
group = "com.seibel.distanthorizons"
mergedJarName = "DistantHorizons-${rootProject.versionStr}-${loaderHyphenSeparatedList}.jar"
mergedJarName = "DistantHorizons-${loaderHyphenSeparatedList}-${rootProject.versionStr}.jar"
if (findProject(":forge"))
forge {
@@ -111,10 +111,11 @@ class NativeTransformer implements Transformer {
private final HashMap<String, byte[]> rewrittenFiles = new HashMap()
private var nativeRelocator
public File rootDir
NativeTransformer() {
try {
int exitCode = Runtime.getRuntime().exec(new String[]{"python", "--version"}).waitFor();
int exitCode = Runtime.getRuntime().exec(new String[]{"python", "--version"}).waitFor()
if (exitCode == 0) {
enabled = true
}
@@ -131,6 +132,11 @@ class NativeTransformer implements Transformer {
replacements.put(target, replacement)
}
void before(Closure closure) {
if (enabled)
closure.run()
}
@Override
boolean canTransformResource(@Nonnull FileTreeElement element) {
@@ -145,7 +151,7 @@ class NativeTransformer implements Transformer {
byte[] content = context.is.readAllBytes()
if (nativeRelocator == null) {
nativeRelocator = new NativeRelocator()
nativeRelocator = new NativeRelocator(rootDir.toPath().resolve("relocate_natives"))
}
try {
@@ -388,13 +394,17 @@ subprojects { p ->
// Sqlite Database
// librariesLocation isn't used because it's too long for replacing paths in native libraries
relocate "org.xerial", "dh_sqlite.org.xerial"
relocate "org.sqlite", "dh_sqlite", {
exclude "org/sqlite/native/**"
}
relocate "jdbc:sqlite", "jdbc:dh_sqlite"
// Allowing strings larger than the original string would require shifting the entire binary's contents
transform(NativeTransformer) {
rootDir = project.rootDir
before {
relocate "org.sqlite", "dh_sqlite", {
exclude "org/sqlite/native/**"
}
relocate "jdbc:sqlite", "jdbc:dh_sqlite"
}
relocateNative "org/sqlite", "dh_sqlite"
relocateNative "org_sqlite", "dh_1sqlite"
}
+50 -12
View File
@@ -6,19 +6,27 @@ import java.util.concurrent.CompletableFuture;
class NativeRelocator
{
private static final Path rootDirectory = Path.of(System.getProperty("user.dir"), "relocate_natives");
private static final Path cacheRoot = rootDirectory.resolve("cache");
private final Path rootDirectory;
private final Path cacheRoot;
NativeRelocator() throws Exception
/**
* Initializes the NativeRelocator by preparing the environment if necessary.
* Executes the appropriate preparation script based on the OS.
*
* @throws Exception if the preparation script fails or an unsupported OS is detected.
*/
NativeRelocator(Path rootDirectory) throws Exception
{
if (rootDirectory.resolve(".venv").toFile().exists())
this.rootDirectory = rootDirectory;
this.cacheRoot = this.rootDirectory.resolve("cache");
if (this.rootDirectory.resolve(".venv").toFile().exists())
{
return;
}
ProcessBuilder processBuilder = new ProcessBuilder();
processBuilder.directory(rootDirectory.toFile());
processBuilder.directory(this.rootDirectory.toFile());
String os = System.getProperty("os.name").toLowerCase();
if (os.contains("win"))
@@ -46,7 +54,12 @@ class NativeRelocator
}
}
/**
* Reads and prints the output and error streams of a process asynchronously.
*
* @param process The process whose streams should be read.
* @return A CompletableFuture that completes once all output has been processed.
*/
private static CompletableFuture<Void> readOutputStreams(Process process)
{
return CompletableFuture.runAsync(() -> {
@@ -79,6 +92,14 @@ class NativeRelocator
});
}
/**
* Replaces occurrences of a target string in a byte array, ensuring null termination.
*
* @param byteArray The byte array where replacements should occur.
* @param target The string to replace.
* @param replacement The replacement string (must not be longer than the target).
* @throws IllegalArgumentException if the replacement is longer than the target.
*/
private void replaceInNullTerminatedStrings(byte[] byteArray, String target, String replacement)
{
if (target.length() < replacement.length())
@@ -117,15 +138,23 @@ class NativeRelocator
}
}
/**
* Runs an external script to fix a modified binary and returns the processed content.
*
* @param outputFilePath Path to store the processed binary.
* @param content The original binary content.
* @return The modified binary content.
* @throws Exception if the process execution fails.
*/
public byte[] fixModifiedBinary(Path outputFilePath, byte[] content) throws Exception
{
ProcessBuilder processBuilder = new ProcessBuilder();
processBuilder.directory(rootDirectory.toFile());
processBuilder.directory(this.rootDirectory.toFile());
processBuilder.command(
rootDirectory.resolve(".venv/Scripts").toFile().exists()
? rootDirectory.resolve(".venv/Scripts/python.exe").toString()
: rootDirectory.resolve(".venv/bin/python").toString(),
this.rootDirectory.resolve(".venv/Scripts").toFile().exists()
? this.rootDirectory.resolve(".venv/Scripts/python.exe").toString()
: this.rootDirectory.resolve(".venv/bin/python").toString(),
"./fix_modified_binary.py",
outputFilePath.toString()
);
@@ -147,9 +176,18 @@ class NativeRelocator
return Files.readAllBytes(outputFilePath);
}
/**
* Processes a binary file, applying string replacements and fixing modifications.
*
* @param outputPath The output file path relative to the cache directory.
* @param content The binary content to process.
* @param replacements A map of string replacements to apply.
* @return The modified binary content.
* @throws Exception if processing fails.
*/
public byte[] processBinary(String outputPath, byte[] content, Map<String, String> replacements) throws Exception
{
Path outputFilePath = cacheRoot.resolve(outputPath);
Path outputFilePath = this.cacheRoot.resolve(outputPath);
//noinspection ResultOfMethodCallIgnored
outputFilePath.getParent().toFile().mkdirs();
@@ -38,24 +38,6 @@ public class VersionConstants implements IVersionConstants
}
@Override
public int getMinimumWorldHeight()
{
return 0;
}
@Override
public int getWorldGenerationCountPerThread()
{
return 1;
}
@Override
public boolean isVanillaRenderedChunkSquare()
{
return false;
}
@Override
public String getMinecraftVersion()
{
@@ -43,6 +43,8 @@ import java.util.*;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import org.jetbrains.annotations.Nullable;
#if MC_VER == MC_1_16_5 || MC_VER == MC_1_17_1
import net.minecraft.core.Registry;
import net.minecraft.core.BlockPos;
@@ -90,6 +92,7 @@ public class BlockStateWrapper implements IBlockStateWrapper
// properties //
@Nullable
public final BlockState blockState;
/** technically final, but since it requires a method call to generate it can't be marked as such */
private String serialString;
@@ -350,25 +353,42 @@ public class BlockStateWrapper implements IBlockStateWrapper
}
// get block properties (default to the values used by air)
boolean canOcclude = false;
boolean propagatesSkyLightDown = true;
if (this.blockState != null)
{
canOcclude = this.blockState.canOcclude();
#if MC_VER < MC_1_21_3
propagatesSkyLightDown = this.blockState.propagatesSkylightDown(EmptyBlockGetter.INSTANCE, BlockPos.ZERO);
#else
propagatesSkyLightDown = this.blockState.propagatesSkylightDown();
#endif
}
// this method isn't perfect, but works well enough for our use case
int opacity;
if (this.isAir())
{
opacity = LodUtil.BLOCK_FULLY_TRANSPARENT;
}
else if (this.isLiquid() && !this.blockState.canOcclude())
else if (this.isLiquid() && !canOcclude)
{
// probably not a waterlogged block (which should block light entirely)
// +1 to indicate that the block is translucent (in between transparent and opaque)
opacity = LodUtil.BLOCK_FULLY_TRANSPARENT + 1;
}
#if MC_VER < MC_1_21_3
else if (this.blockState.propagatesSkylightDown(EmptyBlockGetter.INSTANCE, BlockPos.ZERO))
#else
else if (this.blockState.propagatesSkylightDown())
#endif
else if (propagatesSkyLightDown && !canOcclude)
{
// probably glass or some other fully transparent block
// !canOcclude is required to ignore stairs and slabs since
// propagateSkyLightDown is true for them, but they're solid and don't actually let light through
opacity = LodUtil.BLOCK_FULLY_TRANSPARENT;
}
else
@@ -278,14 +278,14 @@ public class ChunkWrapper implements IChunkWrapper
{
// is this block solid?
if (solidHeight == minInclusiveBuildHeight
&& block.isSolid())
&& block.isSolid())
{
solidHeight = y;
}
// is this block light blocking?
if (lightBlockingHeight == minInclusiveBuildHeight
&& block.getOpacity() != LodUtil.BLOCK_FULLY_TRANSPARENT)
&& block.getOpacity() != LodUtil.BLOCK_FULLY_TRANSPARENT)
{
lightBlockingHeight = y;
}
@@ -214,17 +214,29 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
@Override
public DhBlockPos getPlayerBlockPos()
{
BlockPos playerPos = this.getPlayer().blockPosition();
LocalPlayer player = this.getPlayer();
if (player == null)
{
return new DhBlockPos(0, 0, 0);
}
BlockPos playerPos = player.blockPosition();
return new DhBlockPos(playerPos.getX(), playerPos.getY(), playerPos.getZ());
}
@Override
public DhChunkPos getPlayerChunkPos()
{
LocalPlayer player = this.getPlayer();
if (player == null)
{
return new DhChunkPos(0, 0);
}
#if MC_VER < MC_1_17_1
ChunkPos playerPos = new ChunkPos(this.getPlayer().blockPosition());
ChunkPos playerPos = new ChunkPos(player.blockPosition());
#else
ChunkPos playerPos = this.getPlayer().chunkPosition();
ChunkPos playerPos = player.chunkPosition();
#endif
return new DhChunkPos(playerPos.x, playerPos.z);
}
@@ -28,72 +28,80 @@ import net.minecraft.world.level.dimension.DimensionType;
/**
* @author James Seibel
* @version 2022-9-16
*/
public class DimensionTypeWrapper implements IDimensionTypeWrapper
{
private static final ConcurrentMap<DimensionType, DimensionTypeWrapper> dimensionTypeWrapperMap = new ConcurrentHashMap<>();
private static final ConcurrentMap<String, DimensionTypeWrapper> DIMENSION_WRAPPER_BY_NAME = new ConcurrentHashMap<>();
private final DimensionType dimensionType;
public DimensionTypeWrapper(DimensionType dimensionType)
{
this.dimensionType = dimensionType;
}
//=============//
// Constructor //
//=============//
public DimensionTypeWrapper(DimensionType dimensionType) { this.dimensionType = dimensionType; }
public static DimensionTypeWrapper getDimensionTypeWrapper(DimensionType dimensionType)
{
//first we check if the biome has already been wrapped
if (dimensionTypeWrapperMap.containsKey(dimensionType) && dimensionTypeWrapperMap.get(dimensionType) != null)
String dimName = getName(dimensionType);
// check if the dimension has already been wrapped
if (DIMENSION_WRAPPER_BY_NAME.containsKey(dimName)
&& DIMENSION_WRAPPER_BY_NAME.get(dimName) != null)
{
return dimensionTypeWrapperMap.get(dimensionType);
return DIMENSION_WRAPPER_BY_NAME.get(dimName);
}
//if it hasn't been created yet, we create it and save it in the map
// create the missing wrapper
DimensionTypeWrapper dimensionTypeWrapper = new DimensionTypeWrapper(dimensionType);
dimensionTypeWrapperMap.put(dimensionType, dimensionTypeWrapper);
//we return the newly created wrapper
DIMENSION_WRAPPER_BY_NAME.put(dimName, dimensionTypeWrapper);
return dimensionTypeWrapper;
}
public static void clearMap()
{
dimensionTypeWrapperMap.clear();
}
public static void clearMap() { DIMENSION_WRAPPER_BY_NAME.clear(); }
private String getDimensionName()
//=================//
// wrapper methods //
//=================//
@Override
public String getName() { return getName(this.dimensionType); }
public static String getName(DimensionType dimensionType)
{
#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();
return dimensionType.effectsLocation().getPath();
#endif
}
@Override
public boolean hasCeiling()
{
return this.dimensionType.hasCeiling();
}
public boolean hasCeiling() { return this.dimensionType.hasCeiling(); }
@Override
public boolean hasSkyLight()
{
return this.dimensionType.hasSkyLight();
}
public boolean hasSkyLight() { return this.dimensionType.hasSkyLight(); }
@Override
public Object getWrappedMcObject()
{
return this.dimensionType;
}
public Object getWrappedMcObject() { 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"); }
public boolean isTheEnd() { return this.getName().equalsIgnoreCase("the_end"); }
@Override
public double getCoordinateScale() { return this.dimensionType.coordinateScale(); }
//================//
// base overrides //
//================//
@Override
public boolean equals(Object obj)
@@ -105,9 +113,10 @@ public class DimensionTypeWrapper implements IDimensionTypeWrapper
else
{
DimensionTypeWrapper other = (DimensionTypeWrapper) obj;
return other.getDimensionName().equals(this.getDimensionName());
return other.getName().equals(this.getName());
}
}
}
@@ -125,7 +125,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
* pull chunks using their async method), or if there
* was an issue with the sync pulling method.
*/
private boolean pullExistingChunkAsync = false;
private boolean pullExistingChunkUsingMcAsyncMethod = false;
@@ -241,19 +241,10 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
if (MOD_CHECKER.isModLoaded("c2me"))
{
EVENT_LOGGER.info("C2ME detected: DH's pre-existing chunk accessing will use async methods handled by C2ME.");
this.pullExistingChunkAsync = true;
EVENT_LOGGER.info("C2ME detected: DH's pre-existing chunk accessing will use methods handled by C2ME.");
this.pullExistingChunkUsingMcAsyncMethod = true;
}
//IOWorker ioWorker = level.getChunkSource().chunkMap.worker;
//
// #if MC_VER <= MC_1_18_2
// return CompletableFuture.completedFuture(ioWorker.load(chunkPos));
// #else
//
//// storage will be null if C2ME is installed
//if (ioWorker.storage != null)
this.params = new GlobalParameters(serverlevel);
}
@@ -342,6 +333,8 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
// world generation //
//==================//
// TODO this is already being run on a generator thread,
// why are we passing in an executor?
/** @throws RejectedExecutionException if the given {@link Executor} is cancelled. */
public CompletableFuture<Void> generateLodFromListAsync(GenerationEvent genEvent, Executor executor) throws RejectedExecutionException, InterruptedException
{
@@ -385,10 +378,12 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
.map((chunkPos) -> this.createEmptyOrPreExistingChunkAsync(chunkPos.x, chunkPos.z, chunkSkyLightingByDhPos, chunkBlockLightingByDhPos, generatedChunkByDhPos))
.toArray(CompletableFuture[]::new);
// join to prevent an issue where DH queues too many tasks or something(?)
// also allows file IO to run in parallel so no one thread is waiting on disk IO (this is only an issue when C2ME is present)
CompletableFuture.allOf(readFutures).join();
// future chain for generation
return CompletableFuture.allOf(readFutures)
.thenRunAsync(() ->
return CompletableFuture.runAsync(() ->
{
// offset 1 chunk in both X and Z direction so we can generate an even number of chunks wide
// while still submitting an odd number width to MC's internal generators
@@ -592,6 +587,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
return newChunk;
});
}
// TODO FIXME this method can be called up to 25 times for the same chunk position, why?
private CompletableFuture<CompoundTag> getChunkNbtDataAsync(ChunkPos chunkPos)
{
ServerLevel level = this.params.level;
@@ -610,7 +606,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
#else
// storage will be null if C2ME is installed
if (!this.pullExistingChunkAsync && ioWorker.storage != null)
if (!this.pullExistingChunkUsingMcAsyncMethod && ioWorker.storage != null)
{
try
{
@@ -624,7 +620,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
// ioWorker.storage
// but just in case
EVENT_LOGGER.error("Unexpected issue pulling pre-existing chunk ["+chunkPos+"], falling back to async chunk pulling. This may cause server-tick lag.", e);
this.pullExistingChunkAsync = true;
this.pullExistingChunkUsingMcAsyncMethod = true;
// try again now using the async method
return this.getChunkNbtDataAsync(chunkPos);
@@ -633,32 +629,42 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
else
{
// log if we unexpectedly weren't able to run the sync chunk pulling
if (!this.pullExistingChunkAsync)
if (!this.pullExistingChunkUsingMcAsyncMethod)
{
// this shouldn't happen, but just in case
EVENT_LOGGER.info("Unable to pull pre-existing chunk using synchronous method. Falling back to async method. this may cause server-tick lag.");
this.pullExistingChunkAsync = true;
this.pullExistingChunkUsingMcAsyncMethod = true;
}
//GET_CHUNK_COUNT_REF.incrementAndGet();
// When running in vanilla MC on versions before 1.21.4,
// DH would attempt to run loadAsync on this same thread via a threading mixin,
// to prevent causing lag on the server thread.
// However, if a mod like C2ME is installed this will run on a C2ME thread instead.
return ioWorker.loadAsync(chunkPos)
.thenApply(optional -> optional.orElse(null))
.exceptionally((throwable) ->
{
// unwrap the CompletionException if necessary
Throwable actualThrowable = throwable;
while (actualThrowable instanceof CompletionException completionException)
.thenApply(optional ->
{
actualThrowable = completionException.getCause();
}
LOAD_LOGGER.warn("DistantHorizons: Couldn't load or make chunk ["+chunkPos+"], error: ["+actualThrowable.getMessage()+"].", actualThrowable);
return null;
});
// Debugging note:
// If there are reports of extreme memory use when C2ME is installed, that probably means
// this method is queuing a lot of tasks (1,000+), which causes C2ME to explode.
//GET_CHUNK_COUNT_REF.decrementAndGet();
//PREF_LOGGER.info("chunk getter count ["+F3Screen.NUMBER_FORMAT.format(GET_CHUNK_COUNT_REF.get())+"]");
return optional.orElse(null);
})
.exceptionally((throwable) ->
{
// unwrap the CompletionException if necessary
Throwable actualThrowable = throwable;
while (actualThrowable instanceof CompletionException completionException)
{
actualThrowable = completionException.getCause();
}
LOAD_LOGGER.warn("DistantHorizons: Couldn't load or make chunk ["+chunkPos+"], error: ["+actualThrowable.getMessage()+"].", actualThrowable);
return null;
});
}
#endif
}
@@ -76,15 +76,25 @@ public abstract class MixinMinecraft
if (SelfUpdater.onStart() || DEBUG_ALWAYS_SHOW_UPDATER)
{
instance.setScreen(new UpdateModScreen(
new TitleScreen(false), // We don't want to use the vanilla title screen as it would fade the buttons
(Config.Client.Advanced.AutoUpdater.updateBranch.get() == EDhApiUpdateBranch.STABLE ? ModrinthGetter.getLatestIDForVersion(SingletonInjector.INSTANCE.get(IVersionConstants.class).getMinecraftVersion()): GitlabGetter.INSTANCE.projectPipelines.get(0).get("sha"))
));
}
else
{
instance.setScreen(guiScreen); // Sets the screen back to the vanilla screen as if nothing ever happened
try
{
instance.setScreen(new UpdateModScreen(
new TitleScreen(false), // We don't want to use the vanilla title screen as it would fade the buttons
(Config.Client.Advanced.AutoUpdater.updateBranch.get() == EDhApiUpdateBranch.STABLE ? ModrinthGetter.getLatestIDForVersion(SingletonInjector.INSTANCE.get(IVersionConstants.class).getMinecraftVersion()): GitlabGetter.INSTANCE.projectPipelines.get(0).get("sha"))
));
return;
}
catch (Exception e)
{
// info instead of error since this can be ignored and probably just means
// there isn't a new DH version available
LOGGER.info("Unable to show DH update screen, reason: ["+e.getMessage()+"].");
}
}
// Sets the screen back to the vanilla screen as if nothing ever happened
// if not done the game will crash
instance.setScreen(guiScreen);
}
#endif
@@ -124,14 +134,13 @@ public abstract class MixinMinecraft
{
try
{
Minecraft.getInstance().setScreen(new UpdateModScreen(
// TODO: Change to runnable, instead of tittle screen
new TitleScreen(false), // We don't want to use the vanilla title screen as it would fade the buttons
versionId
));
}
catch (IllegalArgumentException e)
catch (Exception e)
{
// info instead of error since this can be ignored and probably just means
// there isn't a new DH version available
@@ -1,55 +0,0 @@
package com.seibel.distanthorizons.fabric.mixins.server;
#if MC_VER < MC_1_21_3
import net.minecraft.Util;
import net.minecraft.world.entity.Entity;
import org.spongepowered.asm.mixin.Mixin;
/**
* {@link MixinUtilBackgroundThread} was used for versions before 1.21.3
* This is just a dummy class/mixin to make the compiler happy.
*
* @see MixinUtilBackgroundThread
*/
//@Mixin(net.minecraft.minecraft.class) // TODO we should allow version specific mixins so we don't have to create dummy mixins that exist for all MC versions
@Mixin(Util.class)
public class MixinLevelTicks
{
}
#else
import com.seibel.distanthorizons.common.wrappers.DependencySetupDoneCheck;
import net.minecraft.world.ticks.LevelTicks;
import net.minecraft.world.ticks.ScheduledTick;
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(LevelTicks.class)
public class MixinLevelTicks<T>
{
// TODO put in a common location
private static boolean isWorldGenThread()
{ return DependencySetupDoneCheck.isDone && DependencySetupDoneCheck.getIsCurrentThreadDistantGeneratorThread.get(); }
@Inject(method = "schedule", at = @At(value = "HEAD"), cancellable = true)
private void schedule(ScheduledTick<T> tick, CallbackInfo ci)
{
// In MC 1.21.4 an error check was added to log attempting to schedule ticks for unloaded chunks
// this caused a lot of unnecessary errors when generating sand (FallingBlock.class).
if (isWorldGenThread())
{
ci.cancel();
}
}
}
#endif
@@ -105,43 +105,43 @@ public class TestGenericWorldGenerator implements IDhApiWorldGenerator
{
case 0:
blockResourceLocation = "minecraft:red_wool";
maxHeight = 60;
maxHeight = 20;
break;
case 1:
blockResourceLocation = "minecraft:orange_wool";
maxHeight = 70;
maxHeight = 30;
break;
case 2:
blockResourceLocation = "minecraft:yellow_wool";
maxHeight = 80;
maxHeight = 40;
break;
case 3:
blockResourceLocation = "minecraft:lime_wool";
maxHeight = 90;
maxHeight = 50;
break;
case 4:
blockResourceLocation = "minecraft:cyan_wool";
maxHeight = 100;
maxHeight = 60;
break;
case 5:
blockResourceLocation = "minecraft:blue_wool";
maxHeight = 100;
maxHeight = 70;
break;
case 6:
blockResourceLocation = "minecraft:magenta_wool";
maxHeight = 110;
maxHeight = 80;
break;
case 7:
blockResourceLocation = "minecraft:white_wool";
maxHeight = 120;
maxHeight = 90;
break;
case 8:
blockResourceLocation = "minecraft:gray_wool";
maxHeight = 120;
maxHeight = 100;
break;
default:
blockResourceLocation = "minecraft:black_wool";
maxHeight = 140;
maxHeight = 110;
break;
}
@@ -25,7 +25,7 @@ public class TestWorldGenBindingEvent extends DhApiLevelLoadEvent
ServerLevel level = (ServerLevel) event.value.levelWrapper.getWrappedMcObject();
// override the core DH world generator for this level
//IDhApiWorldGenerator exampleWorldGen = new TestChunkWorldGenerator(level);
//IDhApiWorldGenerator exampleWorldGen = new TestChunkWorldGenerator(level); // TODO biomes are broken for some reason
IDhApiWorldGenerator exampleWorldGen = new TestGenericWorldGenerator(event.value.levelWrapper);
DhApi.worldGenOverrides.registerWorldGeneratorOverride(event.value.levelWrapper, exampleWorldGen);
}
@@ -8,8 +8,7 @@
"server.MixinEntity",
"server.MixinServerPlayer",
"server.MixinTracingExecutor",
"server.MixinUtilBackgroundThread",
"server.MixinLevelTicks"
"server.MixinUtilBackgroundThread"
],
"client": [
"client.MixinClientLevel",
@@ -57,15 +57,25 @@ public class MixinMinecraft
if (SelfUpdater.onStart())
{
instance.setScreen(new UpdateModScreen(
new TitleScreen(false), // We don't want to use the vanilla title screen as it would fade the buttons
(Config.Client.Advanced.AutoUpdater.updateBranch.get() == EDhApiUpdateBranch.STABLE ? ModrinthGetter.getLatestIDForVersion(SingletonInjector.INSTANCE.get(IVersionConstants.class).getMinecraftVersion()): GitlabGetter.INSTANCE.projectPipelines.get(0).get("sha"))
));
}
else
{
instance.setScreen(guiScreen); // Sets the screen back to the vanilla screen as if nothing ever happened
try
{
instance.setScreen(new UpdateModScreen(
new TitleScreen(false), // We don't want to use the vanilla title screen as it would fade the buttons
(Config.Client.Advanced.AutoUpdater.updateBranch.get() == EDhApiUpdateBranch.STABLE ? ModrinthGetter.getLatestIDForVersion(SingletonInjector.INSTANCE.get(IVersionConstants.class).getMinecraftVersion()): GitlabGetter.INSTANCE.projectPipelines.get(0).get("sha"))
));
return;
}
catch (Exception e)
{
// info instead of error since this can be ignored and probably just means
// there isn't a new DH version available
LOGGER.info("Unable to show DH update screen, reason: ["+e.getMessage()+"].");
}
}
// Sets the screen back to the vanilla screen as if nothing ever happened
// if not done the game will crash
instance.setScreen(guiScreen);
}
#endif
@@ -108,7 +118,7 @@ public class MixinMinecraft
versionId
));
}
catch (IllegalArgumentException e)
catch (Exception e)
{
// info instead of error since this can be ignored and probably just means
// there isn't a new DH version available
+1 -1
View File
@@ -5,7 +5,7 @@ org.gradle.caching=true
# Mod Info
mod_name=DistantHorizons
mod_version=2.3.0-b-dev
mod_version=2.3.0-b
api_version=4.0.0
maven_group=com.seibel.distanthorizons
mod_readable_name=Distant Horizons
@@ -76,14 +76,13 @@ public class MixinMinecraft
{
try
{
Minecraft.getInstance().setScreen(new UpdateModScreen(
// TODO: Change to runnable, instead of tittle screen
new TitleScreen(false), // We don't want to use the vanilla title screen as it would fade the buttons
versionId
));
}
catch (IllegalArgumentException e)
catch (Exception e)
{
// info instead of error since this can be ignored and probably just means
// there isn't a new DH version available
@@ -1,53 +0,0 @@
package com.seibel.distanthorizons.neoforge.mixins.server;
#if MC_VER < MC_1_21_3
import net.minecraft.Util;
import org.spongepowered.asm.mixin.Mixin;
/**
* {@link MixinUtilBackgroundThread} was used for versions before 1.21.3
* This is just a dummy class/mixin to make the compiler happy.
*
* @see MixinUtilBackgroundThread
*/
@Mixin(Util.class) // TODO we should allow version specific mixins so we don't have to create dummy mixins that exist for all MC versions
public class MixinLevelTicks<T>
{
}
#else
import com.seibel.distanthorizons.common.wrappers.DependencySetupDoneCheck;
import net.minecraft.world.ticks.LevelTicks;
import net.minecraft.world.ticks.ScheduledTick;
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(LevelTicks.class)
public class MixinLevelTicks<T>
{
// TODO put in a common location
private static boolean isWorldGenThread()
{ return DependencySetupDoneCheck.isDone && DependencySetupDoneCheck.getIsCurrentThreadDistantGeneratorThread.get(); }
@Inject(method = "schedule", at = @At(value = "HEAD"), cancellable = true)
private void schedule(ScheduledTick<T> tick, CallbackInfo ci)
{
// In MC 1.21.4 an error check was added to log attempting to schedule ticks for unloaded chunks
// this caused a lot of unnecessary errors when generating sand (FallingBlock.class).
if (isWorldGenThread())
{
ci.cancel();
}
}
}
#endif
@@ -8,8 +8,7 @@
"server.MixinServerPlayer",
"server.MixinTFChunkGenerator",
"server.MixinTracingExecutor",
"server.MixinUtilBackgroundThread",
"server.MixinLevelTicks"
"server.MixinUtilBackgroundThread"
],
"client": [
"client.MixinClientPacketListener",
+6 -1
View File
@@ -4,23 +4,28 @@ import subprocess
import download_codesign
from pathlib import Path
# Parse the input binary & xit if binary is invalid
output_path = sys.argv[1]
binary = lief.parse(sys.stdin.buffer.read())
if binary is None:
exit(1)
# Remove signature from Mac binaries
if isinstance(binary, lief.MachO.Binary):
binary.remove_signature()
# Write the modified binary to the output path
binary.write(output_path)
# Sign Mac binaries (required to make them usable because apple)
if isinstance(binary, lief.MachO.Binary):
print(f"Signing {output_path}...")
# Check if the Apple code-signing files are available, if not, download them
if not Path("./apple-codesign/COPYING").exists():
download_codesign.download_and_unpack()
# Run the code-signing process
sign_process = subprocess.Popen(["./apple-codesign/rcodesign", "sign", output_path], shell=False,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
sign_process.wait()
+1 -1
View File
@@ -12,7 +12,7 @@ netty_version=4.1.97.Final
# Fabric loader
fabric_loader_version=0.16.9
fabric_api_version=0.107.0+1.21.1
fabric_api_version=0.115.0+1.21.1
# Fabric mod versions
modmenu_version=11.0.0-beta.1
starlight_version_fabric=