pause world gen when moving quickly
This commit is contained in:
@@ -36,7 +36,6 @@ import com.seibel.distanthorizons.core.world.AbstractDhWorld;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||
import com.seibel.distanthorizons.coreapi.util.StringUtil;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||
|
||||
import java.text.NumberFormat;
|
||||
@@ -219,7 +218,11 @@ public class F3Screen
|
||||
// active threads
|
||||
int activeThreadCount = pool.getRunningTaskCount();
|
||||
int threadCount = pool.getPoolSize();
|
||||
message += ", Active: "+activeThreadCount+"/"+threadCount;
|
||||
|
||||
boolean threadPoolActive = pool.canRun();
|
||||
String poolActiveString = threadPoolActive ? "Active" : "Paused";
|
||||
|
||||
message += ", "+poolActiveString+": "+activeThreadCount+"/"+threadCount;
|
||||
|
||||
// thread runtime
|
||||
String runTimeAvgStr;
|
||||
|
||||
@@ -85,17 +85,10 @@ public class LodUtil
|
||||
/** the opacity value returned by {@link IBlockStateWrapper#getOpacity()} if a block is fully opaque */
|
||||
public static final int BLOCK_FULLY_OPAQUE = 16;
|
||||
|
||||
/**
|
||||
* List of every block that can be used in a beacon's base. <br>
|
||||
* Should be all lowercase
|
||||
*/
|
||||
public static final List<String> BEACON_BASE_BLOCK_NAME_LIST = Arrays.asList(
|
||||
"iron_block",
|
||||
"gold_block",
|
||||
"diamond_block",
|
||||
"emerald_block",
|
||||
"netherite_block"
|
||||
);
|
||||
public static final double WALKING_SPEED_IN_BLOCKS_PER_SEC = 4.1;
|
||||
public static final double SPRINTING_SPEED_IN_BLOCKS_PER_SEC = 7.1;
|
||||
public static final double ROCKET_ELYTRA_SPEED_IN_BLOCKS_PER_SEC = 30.0;
|
||||
public static final double MAX_SPECTATOR_SPEED_IN_BLOCKS_PER_SEC = 100.0;
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -37,16 +37,18 @@ public class RenderUtil
|
||||
private static final IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
|
||||
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
|
||||
|
||||
/** all speeds are measured in blocks per second */
|
||||
/**
|
||||
* all speeds are measured in blocks per second
|
||||
*
|
||||
* @see LodUtil#WALKING_SPEED_IN_BLOCKS_PER_SEC
|
||||
* @see LodUtil#SPRINTING_SPEED_IN_BLOCKS_PER_SEC
|
||||
* @see LodUtil#ROCKET_ELYTRA_SPEED_IN_BLOCKS_PER_SEC
|
||||
* @see LodUtil#MAX_SPECTATOR_SPEED_IN_BLOCKS_PER_SEC
|
||||
*/
|
||||
private static class DynamicOverdraw
|
||||
{
|
||||
/**
|
||||
* A walking player moves around 4.1 blocks/sec
|
||||
* A sprint jumping player around 7.1 blocks/sec
|
||||
*/
|
||||
public static final float MIN_SPEED = 10.0f;
|
||||
/** a max speed spectator player can move just shy of 100 blocks/sec */
|
||||
public static final float MAX_SPEED = 100.0f;
|
||||
public static final float MIN_SPEED = 10.0f; // a little faster than sprinting (7)
|
||||
public static final float MAX_SPEED = (float)LodUtil.MAX_SPECTATOR_SPEED_IN_BLOCKS_PER_SEC;
|
||||
public static final float MIN_OVERDRAW_RATIO = 0.2f;
|
||||
}
|
||||
|
||||
|
||||
+55
-3
@@ -6,6 +6,7 @@ import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.util.objects.RollingAverage;
|
||||
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
@@ -39,10 +40,12 @@ public class PriorityTaskPicker
|
||||
//==========//
|
||||
// executor //
|
||||
//==========//
|
||||
///region
|
||||
|
||||
public Executor createExecutor(String name)
|
||||
public Executor createExecutor(String name) { return this.createExecutor(name, null); }
|
||||
public Executor createExecutor(String name, @Nullable PriorityTaskPicker.IExecutorCanRunFunc canRunFunc)
|
||||
{
|
||||
Executor executor = new Executor(this, name);
|
||||
Executor executor = new Executor(this, name, canRunFunc);
|
||||
this.executors.add(executor);
|
||||
return executor;
|
||||
}
|
||||
@@ -73,6 +76,13 @@ public class PriorityTaskPicker
|
||||
while (iterator.hasNext())
|
||||
{
|
||||
Executor executor = iterator.next();
|
||||
|
||||
// skip executors that are paused
|
||||
if (!executor.canRun())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
int queuedTaskCount = 0;
|
||||
|
||||
TrackedRunnable task;
|
||||
@@ -142,11 +152,14 @@ public class PriorityTaskPicker
|
||||
}
|
||||
}
|
||||
|
||||
///endregion
|
||||
|
||||
|
||||
|
||||
//================//
|
||||
// helper classes //
|
||||
//================//
|
||||
///region
|
||||
|
||||
/**
|
||||
* Each executor handles a specific type of work that DH needs done.
|
||||
@@ -167,6 +180,9 @@ public class PriorityTaskPicker
|
||||
/** used for performance logging */
|
||||
private final RollingAverage runTimeInMsRollingAverage = new RollingAverage(200);
|
||||
|
||||
@Nullable
|
||||
private final PriorityTaskPicker.IExecutorCanRunFunc canRunFunc;
|
||||
|
||||
/** holds the threads this {@link Executor} can run */
|
||||
private RateLimitedThreadPoolExecutor threadPoolExecutor;
|
||||
|
||||
@@ -175,11 +191,13 @@ public class PriorityTaskPicker
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
///region
|
||||
|
||||
public Executor(PriorityTaskPicker parentTaskPicker, String name)
|
||||
public Executor(PriorityTaskPicker parentTaskPicker, String name, @Nullable PriorityTaskPicker.IExecutorCanRunFunc canRunFunc)
|
||||
{
|
||||
this.parentTaskPicker = parentTaskPicker;
|
||||
this.name = name;
|
||||
this.canRunFunc = canRunFunc;
|
||||
|
||||
this.threadPoolExecutor = this.createThreadPool();
|
||||
|
||||
@@ -195,11 +213,14 @@ public class PriorityTaskPicker
|
||||
);
|
||||
}
|
||||
|
||||
///endregion
|
||||
|
||||
|
||||
|
||||
//=================//
|
||||
// config handling //
|
||||
//=================//
|
||||
///region
|
||||
|
||||
@Override
|
||||
public void onConfigValueSet()
|
||||
@@ -215,11 +236,14 @@ public class PriorityTaskPicker
|
||||
}
|
||||
}
|
||||
|
||||
///endregion
|
||||
|
||||
|
||||
|
||||
//=====================//
|
||||
// task queue handling //
|
||||
//=====================//
|
||||
///region
|
||||
|
||||
@Override
|
||||
public void execute(@NotNull Runnable command)
|
||||
@@ -258,11 +282,25 @@ public class PriorityTaskPicker
|
||||
|
||||
public void clearQueue() { this.taskQueue.clear(); }
|
||||
|
||||
public boolean canRun()
|
||||
{
|
||||
if (this.canRunFunc == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return this.canRunFunc.canRun();
|
||||
}
|
||||
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//==========//
|
||||
// shutdown //
|
||||
//==========//
|
||||
///region
|
||||
|
||||
@Override
|
||||
public void shutdown() { this.threadPoolExecutor.shutdown(); }
|
||||
@@ -279,6 +317,8 @@ public class PriorityTaskPicker
|
||||
public boolean awaitTermination(long timeout, @NotNull TimeUnit unit) throws InterruptedException
|
||||
{ return this.threadPoolExecutor.awaitTermination(timeout, unit); }
|
||||
|
||||
///endregion
|
||||
|
||||
}
|
||||
|
||||
/** used so we can {@link PriorityTaskPicker.Executor#remove(Runnable)} using the original {@link Runnable} */
|
||||
@@ -334,6 +374,18 @@ public class PriorityTaskPicker
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a way to dynamically enable/disable
|
||||
* certain {@link PriorityTaskPicker.Executor}'s.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface IExecutorCanRunFunc
|
||||
{
|
||||
boolean canRun();
|
||||
}
|
||||
|
||||
///endregion
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
+44
-2
@@ -19,6 +19,8 @@
|
||||
|
||||
package com.seibel.distanthorizons.core.util.threading;
|
||||
|
||||
import com.seibel.distanthorizons.core.api.internal.ClientApi;
|
||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||
import com.seibel.distanthorizons.core.util.ThreadUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -94,6 +96,7 @@ public class ThreadPoolUtil
|
||||
//=================//
|
||||
// setup / cleanup //
|
||||
//=================//
|
||||
///region
|
||||
|
||||
public static void setupThreadPools()
|
||||
{
|
||||
@@ -112,8 +115,9 @@ public class ThreadPoolUtil
|
||||
fileHandlerThreadPool = taskPicker.createExecutor("IO");
|
||||
renderSectionLoadThreadPool = taskPicker.createExecutor("Render Loader");
|
||||
chunkToLodBuilderThreadPool = taskPicker.createExecutor("LOD Builder");
|
||||
updatePropagatorThreadPool = taskPicker.createExecutor("Update Propagator");
|
||||
worldGenThreadPool = taskPicker.createExecutor("World Gen");
|
||||
updatePropagatorThreadPool = taskPicker.createExecutor("Update Propagator", ThreadPoolUtil::onlyRunThreadIfCameraMovingSlowly);
|
||||
worldGenThreadPool = taskPicker.createExecutor("World Gen", ThreadPoolUtil::onlyRunThreadIfCameraMovingSlowly);
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -144,4 +148,42 @@ public class ThreadPoolUtil
|
||||
fullDataMigrationThreadPool.shutdown();
|
||||
}
|
||||
|
||||
///endregion
|
||||
|
||||
|
||||
|
||||
//================//
|
||||
// helper methods //
|
||||
//================//
|
||||
///region
|
||||
|
||||
/**
|
||||
* Some thread pools are very heavy (IE world gen)
|
||||
* making LOD load times slower. Pausing those
|
||||
* threads when the player is moving can provide a better experience. <br><br>
|
||||
*
|
||||
* all speeds are measured in blocks per second
|
||||
*
|
||||
* @see LodUtil#WALKING_SPEED_IN_BLOCKS_PER_SEC
|
||||
* @see LodUtil#SPRINTING_SPEED_IN_BLOCKS_PER_SEC
|
||||
* @see LodUtil#ROCKET_ELYTRA_SPEED_IN_BLOCKS_PER_SEC
|
||||
* @see LodUtil#MAX_SPECTATOR_SPEED_IN_BLOCKS_PER_SEC
|
||||
*/
|
||||
public static boolean onlyRunThreadIfCameraMovingSlowly()
|
||||
{
|
||||
double cameraSpeed = ClientApi.INSTANCE.cameraSpeedRollingAverage.getAverage();
|
||||
double maxAllowedSpeed = (LodUtil.ROCKET_ELYTRA_SPEED_IN_BLOCKS_PER_SEC - 10.0);
|
||||
if (cameraSpeed > maxAllowedSpeed)
|
||||
{
|
||||
// pause this thread pool if the user is moving too fast
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
///endregion
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user