mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2025-02-28 20:54:40 +01:00
Merge remote-tracking branch 'origin/1.18/dev' into 1.18/fabric/dev
Conflicts: src/main/java/com/jozufozu/flywheel/Flywheel.java src/main/java/com/jozufozu/flywheel/FlywheelClient.java src/main/java/com/jozufozu/flywheel/backend/Backend.java src/main/java/com/jozufozu/flywheel/backend/Loader.java src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java src/main/java/com/jozufozu/flywheel/config/FlwCommands.java src/main/java/com/jozufozu/flywheel/config/FlwConfig.java src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java
This commit is contained in:
commit
8fcc1df383
24 changed files with 246 additions and 156 deletions
|
@ -2,7 +2,7 @@ org.gradle.jvmargs = -Xmx3G
|
||||||
org.gradle.daemon = false
|
org.gradle.daemon = false
|
||||||
|
|
||||||
# mod version info
|
# mod version info
|
||||||
mod_version = 0.6.0
|
mod_version = 0.6.1
|
||||||
mc_update_version = 1.18
|
mc_update_version = 1.18
|
||||||
minecraft_version = 1.18.1
|
minecraft_version = 1.18.1
|
||||||
loader_version = 0.12.12
|
loader_version = 0.12.12
|
||||||
|
|
|
@ -3,18 +3,42 @@ package com.jozufozu.flywheel;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.backend.Backend;
|
||||||
|
import com.jozufozu.flywheel.backend.Loader;
|
||||||
|
import com.jozufozu.flywheel.backend.RenderWork;
|
||||||
|
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
|
||||||
|
import com.jozufozu.flywheel.config.FlwConfig;
|
||||||
|
import com.jozufozu.flywheel.core.Contexts;
|
||||||
|
import com.jozufozu.flywheel.core.PartialModel;
|
||||||
|
import com.jozufozu.flywheel.core.QuadConverter;
|
||||||
|
import com.jozufozu.flywheel.core.compile.ProgramCompiler;
|
||||||
|
import com.jozufozu.flywheel.core.crumbling.CrumblingRenderer;
|
||||||
|
import com.jozufozu.flywheel.event.EntityWorldHandler;
|
||||||
|
import com.jozufozu.flywheel.event.ForgeEvents;
|
||||||
|
import com.jozufozu.flywheel.fabric.event.FlywheelEvents;
|
||||||
|
import com.jozufozu.flywheel.mixin.PausedPartialTickAccessor;
|
||||||
|
import com.jozufozu.flywheel.vanilla.VanillaInstances;
|
||||||
|
|
||||||
|
import net.fabricmc.api.ClientModInitializer;
|
||||||
|
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientEntityEvents;
|
||||||
|
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
|
||||||
|
import net.fabricmc.fabric.api.client.model.ModelLoadingRegistry;
|
||||||
|
import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents;
|
||||||
|
import net.fabricmc.fabric.api.resource.ResourceManagerHelper;
|
||||||
import net.fabricmc.loader.api.FabricLoader;
|
import net.fabricmc.loader.api.FabricLoader;
|
||||||
import net.fabricmc.loader.api.SemanticVersion;
|
import net.fabricmc.loader.api.SemanticVersion;
|
||||||
import net.fabricmc.loader.api.Version;
|
import net.fabricmc.loader.api.Version;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.server.packs.PackType;
|
||||||
|
|
||||||
public class Flywheel {
|
public class Flywheel implements ClientModInitializer {
|
||||||
|
|
||||||
public static final String ID = "flywheel";
|
public static final String ID = "flywheel";
|
||||||
public static final Logger LOGGER = LogManager.getLogger(Flywheel.class);
|
public static final Logger LOGGER = LogManager.getLogger(Flywheel.class);
|
||||||
public static SemanticVersion VERSION;
|
private static SemanticVersion version;
|
||||||
|
|
||||||
static void initVersion() {
|
@Override
|
||||||
|
public void onInitializeClient() {
|
||||||
Version version = FabricLoader.getInstance()
|
Version version = FabricLoader.getInstance()
|
||||||
.getModContainer(ID)
|
.getModContainer(ID)
|
||||||
.orElseThrow(() -> new IllegalStateException("Could not get the mod container for Flywheel!"))
|
.orElseThrow(() -> new IllegalStateException("Could not get the mod container for Flywheel!"))
|
||||||
|
@ -23,7 +47,43 @@ public class Flywheel {
|
||||||
if (!(version instanceof SemanticVersion semver)) {
|
if (!(version instanceof SemanticVersion semver)) {
|
||||||
throw new IllegalStateException("Got non-semantic version for Flywheel!");
|
throw new IllegalStateException("Got non-semantic version for Flywheel!");
|
||||||
}
|
}
|
||||||
VERSION = semver;
|
Flywheel.version = semver;
|
||||||
|
|
||||||
|
FlwConfig.init();
|
||||||
|
|
||||||
|
Backend.init();
|
||||||
|
|
||||||
|
FlywheelEvents.GATHER_CONTEXT.register(Contexts::flwInit);
|
||||||
|
ModelLoadingRegistry.INSTANCE.registerModelProvider(PartialModel::onModelRegistry);
|
||||||
|
ResourceManagerHelper.get(PackType.CLIENT_RESOURCES).registerReloadListener(PartialModel.ResourceReloadListener.INSTANCE);
|
||||||
|
|
||||||
|
FlywheelEvents.RELOAD_RENDERERS.register(ProgramCompiler::invalidateAll);
|
||||||
|
|
||||||
|
ResourceManagerHelper.get(PackType.CLIENT_RESOURCES).registerReloadListener(Loader.ResourceReloadListener.INSTANCE);
|
||||||
|
|
||||||
|
WorldRenderEvents.END.register(RenderWork::onRenderWorldLast);
|
||||||
|
ClientTickEvents.END_CLIENT_TICK.register(InstancedRenderDispatcher::tick);
|
||||||
|
FlywheelEvents.BEGIN_FRAME.register(InstancedRenderDispatcher::onBeginFrame);
|
||||||
|
FlywheelEvents.RENDER_LAYER.register(InstancedRenderDispatcher::renderLayer);
|
||||||
|
FlywheelEvents.RELOAD_RENDERERS.register(InstancedRenderDispatcher::onReloadRenderers);
|
||||||
|
FlywheelEvents.RELOAD_RENDERERS.register(QuadConverter::onRendererReload);
|
||||||
|
FlywheelEvents.RELOAD_RENDERERS.register(CrumblingRenderer::onReloadRenderers);
|
||||||
|
ClientEntityEvents.ENTITY_LOAD.register(EntityWorldHandler::onEntityJoinWorld);
|
||||||
|
ClientEntityEvents.ENTITY_UNLOAD.register(EntityWorldHandler::onEntityLeaveWorld);
|
||||||
|
ClientTickEvents.END_CLIENT_TICK.register(ForgeEvents::tickLight);
|
||||||
|
|
||||||
|
VanillaInstances.init();
|
||||||
|
|
||||||
|
// https://github.com/Jozufozu/Flywheel/issues/69
|
||||||
|
// Weird issue with accessor loading.
|
||||||
|
// Only thing I've seen that's close to a fix is to force the class to load before trying to use it.
|
||||||
|
// From the SpongePowered discord:
|
||||||
|
// https://discord.com/channels/142425412096491520/626802111455297538/675007581168599041
|
||||||
|
LOGGER.debug("Successfully loaded {}", PausedPartialTickAccessor.class.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SemanticVersion getVersion() {
|
||||||
|
return version;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ResourceLocation rl(String path) {
|
public static ResourceLocation rl(String path) {
|
||||||
|
|
|
@ -1,65 +0,0 @@
|
||||||
package com.jozufozu.flywheel;
|
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.Backend;
|
|
||||||
import com.jozufozu.flywheel.backend.Loader;
|
|
||||||
import com.jozufozu.flywheel.backend.RenderWork;
|
|
||||||
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
|
|
||||||
import com.jozufozu.flywheel.config.FlwConfig;
|
|
||||||
import com.jozufozu.flywheel.core.Contexts;
|
|
||||||
import com.jozufozu.flywheel.core.PartialModel;
|
|
||||||
import com.jozufozu.flywheel.core.QuadConverter;
|
|
||||||
import com.jozufozu.flywheel.core.compile.ProgramCompiler;
|
|
||||||
import com.jozufozu.flywheel.core.crumbling.CrumblingRenderer;
|
|
||||||
import com.jozufozu.flywheel.event.EntityWorldHandler;
|
|
||||||
import com.jozufozu.flywheel.event.ForgeEvents;
|
|
||||||
import com.jozufozu.flywheel.fabric.event.FlywheelEvents;
|
|
||||||
import com.jozufozu.flywheel.mixin.PausedPartialTickAccessor;
|
|
||||||
import com.jozufozu.flywheel.vanilla.VanillaInstances;
|
|
||||||
|
|
||||||
import net.fabricmc.api.ClientModInitializer;
|
|
||||||
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientEntityEvents;
|
|
||||||
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
|
|
||||||
import net.fabricmc.fabric.api.client.model.ModelLoadingRegistry;
|
|
||||||
import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents;
|
|
||||||
import net.fabricmc.fabric.api.resource.ResourceManagerHelper;
|
|
||||||
import net.minecraft.server.packs.PackType;
|
|
||||||
|
|
||||||
public class FlywheelClient implements ClientModInitializer {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onInitializeClient() {
|
|
||||||
Flywheel.initVersion();
|
|
||||||
|
|
||||||
Backend.init();
|
|
||||||
|
|
||||||
FlywheelEvents.GATHER_CONTEXT.register(Contexts::flwInit);
|
|
||||||
ModelLoadingRegistry.INSTANCE.registerModelProvider(PartialModel::onModelRegistry);
|
|
||||||
ResourceManagerHelper.get(PackType.CLIENT_RESOURCES).registerReloadListener(PartialModel.ResourceReloadListener.INSTANCE);
|
|
||||||
|
|
||||||
FlywheelEvents.RELOAD_RENDERERS.register(ProgramCompiler::invalidateAll);
|
|
||||||
|
|
||||||
VanillaInstances.init();
|
|
||||||
|
|
||||||
ResourceManagerHelper.get(PackType.CLIENT_RESOURCES).registerReloadListener(Loader.ResourceReloadListener.INSTANCE);
|
|
||||||
|
|
||||||
WorldRenderEvents.END.register(RenderWork::onRenderWorldLast);
|
|
||||||
ClientTickEvents.END_CLIENT_TICK.register(InstancedRenderDispatcher::tick);
|
|
||||||
FlywheelEvents.BEGIN_FRAME.register(InstancedRenderDispatcher::onBeginFrame);
|
|
||||||
FlywheelEvents.RENDER_LAYER.register(InstancedRenderDispatcher::renderLayer);
|
|
||||||
FlywheelEvents.RELOAD_RENDERERS.register(InstancedRenderDispatcher::onReloadRenderers);
|
|
||||||
FlywheelEvents.RELOAD_RENDERERS.register(QuadConverter::onRendererReload);
|
|
||||||
FlywheelEvents.RELOAD_RENDERERS.register(CrumblingRenderer::onReloadRenderers);
|
|
||||||
ClientEntityEvents.ENTITY_LOAD.register(EntityWorldHandler::onEntityJoinWorld);
|
|
||||||
ClientEntityEvents.ENTITY_UNLOAD.register(EntityWorldHandler::onEntityLeaveWorld);
|
|
||||||
ClientTickEvents.END_CLIENT_TICK.register(ForgeEvents::tickLight);
|
|
||||||
|
|
||||||
FlwConfig.init();
|
|
||||||
|
|
||||||
// https://github.com/Jozufozu/Flywheel/issues/69
|
|
||||||
// Weird issue with accessor loading.
|
|
||||||
// Only thing I've seen that's close to a fix is to force the class to load before trying to use it.
|
|
||||||
// From the SpongePowered discord:
|
|
||||||
// https://discord.com/channels/142425412096491520/626802111455297538/675007581168599041
|
|
||||||
Flywheel.LOGGER.info("Successfully loaded {}", PausedPartialTickAccessor.class.getName());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -21,8 +21,6 @@ public class Backend {
|
||||||
|
|
||||||
private static FlwEngine engine;
|
private static FlwEngine engine;
|
||||||
|
|
||||||
public static GlCompat compat;
|
|
||||||
|
|
||||||
private static final Loader loader = new Loader();
|
private static final Loader loader = new Loader();
|
||||||
|
|
||||||
public static FlwEngine getEngine() {
|
public static FlwEngine getEngine() {
|
||||||
|
@ -43,9 +41,7 @@ public class Backend {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void refresh() {
|
public static void refresh() {
|
||||||
compat = new GlCompat();
|
engine = chooseEngine();
|
||||||
|
|
||||||
engine = chooseEngine(compat);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isOn() {
|
public static boolean isOn() {
|
||||||
|
@ -77,7 +73,7 @@ public class Backend {
|
||||||
RenderWork.enqueue(Minecraft.getInstance().levelRenderer::allChanged);
|
RenderWork.enqueue(Minecraft.getInstance().levelRenderer::allChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static FlwEngine chooseEngine(GlCompat compat) {
|
private static FlwEngine chooseEngine() {
|
||||||
FlwEngine preferredChoice = FlwConfig.get()
|
FlwEngine preferredChoice = FlwConfig.get()
|
||||||
.getEngine();
|
.getEngine();
|
||||||
|
|
||||||
|
@ -85,7 +81,7 @@ public class Backend {
|
||||||
boolean canUseEngine = switch (preferredChoice) {
|
boolean canUseEngine = switch (preferredChoice) {
|
||||||
case OFF -> true;
|
case OFF -> true;
|
||||||
case BATCHING -> !usingShaders;
|
case BATCHING -> !usingShaders;
|
||||||
case INSTANCING -> !usingShaders && compat.instancedArraysSupported();
|
case INSTANCING -> !usingShaders && GlCompat.getInstance().instancedArraysSupported();
|
||||||
};
|
};
|
||||||
|
|
||||||
return canUseEngine ? preferredChoice : FlwEngine.OFF;
|
return canUseEngine ? preferredChoice : FlwEngine.OFF;
|
||||||
|
|
|
@ -47,7 +47,7 @@ public class Loader {
|
||||||
public static final String PROGRAM_DIR = "flywheel/programs/";
|
public static final String PROGRAM_DIR = "flywheel/programs/";
|
||||||
private static final Gson GSON = new GsonBuilder().create();
|
private static final Gson GSON = new GsonBuilder().create();
|
||||||
|
|
||||||
private final Map<ResourceLocation, ProgramSpec> programSpecRegistry = new HashMap<>();
|
private final Map<ResourceLocation, ProgramSpec> programs = new HashMap<>();
|
||||||
|
|
||||||
private boolean firstLoad = true;
|
private boolean firstLoad = true;
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ public class Loader {
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public ProgramSpec get(ResourceLocation name) {
|
public ProgramSpec get(ResourceLocation name) {
|
||||||
return programSpecRegistry.get(name);
|
return programs.get(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onResourceManagerReload(ResourceManager manager) {
|
public void onResourceManagerReload(ResourceManager manager) {
|
||||||
|
@ -88,6 +88,8 @@ public class Loader {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadProgramSpecs(ResourceManager manager) {
|
private void loadProgramSpecs(ResourceManager manager) {
|
||||||
|
programs.clear();
|
||||||
|
|
||||||
Collection<ResourceLocation> programSpecs = manager.listResources(PROGRAM_DIR, s -> s.endsWith(".json"));
|
Collection<ResourceLocation> programSpecs = manager.listResources(PROGRAM_DIR, s -> s.endsWith(".json"));
|
||||||
|
|
||||||
for (ResourceLocation location : programSpecs) {
|
for (ResourceLocation location : programSpecs) {
|
||||||
|
@ -106,24 +108,17 @@ public class Loader {
|
||||||
|
|
||||||
spec.setName(specName);
|
spec.setName(specName);
|
||||||
|
|
||||||
register(spec);
|
if (programs.containsKey(specName)) {
|
||||||
|
throw new IllegalStateException("Program spec '" + specName + "' already registered.");
|
||||||
|
}
|
||||||
|
programs.put(specName, spec);
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Backend.LOGGER.error(e);
|
Backend.LOGGER.error(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Register a shader program.
|
|
||||||
*/
|
|
||||||
private void register(ProgramSpec spec) {
|
|
||||||
ResourceLocation name = spec.name;
|
|
||||||
if (programSpecRegistry.containsKey(name)) {
|
|
||||||
throw new IllegalStateException("Program spec '" + name + "' already registered.");
|
|
||||||
}
|
|
||||||
programSpecRegistry.put(name, spec);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ResourceReloadListener implements ResourceManagerReloadListener, IdentifiableResourceReloadListener {
|
public static class ResourceReloadListener implements ResourceManagerReloadListener, IdentifiableResourceReloadListener {
|
||||||
public static final ResourceReloadListener INSTANCE = new ResourceReloadListener();
|
public static final ResourceReloadListener INSTANCE = new ResourceReloadListener();
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,8 @@ import java.nio.ByteBuffer;
|
||||||
|
|
||||||
import org.lwjgl.opengl.GL20;
|
import org.lwjgl.opengl.GL20;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.Backend;
|
|
||||||
import com.jozufozu.flywheel.backend.gl.GlObject;
|
import com.jozufozu.flywheel.backend.gl.GlObject;
|
||||||
|
import com.jozufozu.flywheel.backend.gl.versioned.GlCompat;
|
||||||
|
|
||||||
public abstract class GlBuffer extends GlObject {
|
public abstract class GlBuffer extends GlObject {
|
||||||
|
|
||||||
|
@ -21,7 +21,8 @@ public abstract class GlBuffer extends GlObject {
|
||||||
* @return A buffer that will be persistent if the driver supports it.
|
* @return A buffer that will be persistent if the driver supports it.
|
||||||
*/
|
*/
|
||||||
public static GlBuffer requestPersistent(GlBufferType type) {
|
public static GlBuffer requestPersistent(GlBufferType type) {
|
||||||
if (Backend.compat.bufferStorageSupported()) {
|
if (GlCompat.getInstance()
|
||||||
|
.bufferStorageSupported()) {
|
||||||
return new PersistentGlBuffer(type);
|
return new PersistentGlBuffer(type);
|
||||||
} else {
|
} else {
|
||||||
return new MappedGlBuffer(type);
|
return new MappedGlBuffer(type);
|
||||||
|
|
|
@ -8,10 +8,10 @@ import java.nio.ByteBuffer;
|
||||||
|
|
||||||
import org.lwjgl.opengl.GL30;
|
import org.lwjgl.opengl.GL30;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.Backend;
|
|
||||||
import com.jozufozu.flywheel.backend.gl.GlFence;
|
import com.jozufozu.flywheel.backend.gl.GlFence;
|
||||||
import com.jozufozu.flywheel.backend.gl.error.GlError;
|
import com.jozufozu.flywheel.backend.gl.error.GlError;
|
||||||
import com.jozufozu.flywheel.backend.gl.error.GlException;
|
import com.jozufozu.flywheel.backend.gl.error.GlException;
|
||||||
|
import com.jozufozu.flywheel.backend.gl.versioned.GlCompat;
|
||||||
|
|
||||||
public class PersistentGlBuffer extends GlBuffer implements Mappable {
|
public class PersistentGlBuffer extends GlBuffer implements Mappable {
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ public class PersistentGlBuffer extends GlBuffer implements Mappable {
|
||||||
|
|
||||||
fence.clear();
|
fence.clear();
|
||||||
|
|
||||||
Backend.compat.bufferStorage.bufferStorage(type, size, flags);
|
GlCompat.getInstance().bufferStorage.bufferStorage(type, size, flags);
|
||||||
|
|
||||||
ByteBuffer byteBuffer = GL30.glMapBufferRange(type.glEnum, 0, size, flags);
|
ByteBuffer byteBuffer = GL30.glMapBufferRange(type.glEnum, 0, size, flags);
|
||||||
|
|
||||||
|
|
|
@ -20,11 +20,20 @@ import net.minecraft.Util;
|
||||||
*/
|
*/
|
||||||
public class GlCompat {
|
public class GlCompat {
|
||||||
|
|
||||||
|
private static GlCompat instance;
|
||||||
|
|
||||||
|
public static GlCompat getInstance() {
|
||||||
|
if (instance == null) {
|
||||||
|
instance = new GlCompat();
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
public final InstancedArrays instancedArrays;
|
public final InstancedArrays instancedArrays;
|
||||||
public final BufferStorage bufferStorage;
|
public final BufferStorage bufferStorage;
|
||||||
public final boolean amd;
|
public final boolean amd;
|
||||||
|
|
||||||
public GlCompat() {
|
private GlCompat() {
|
||||||
GLCapabilities caps = GL.createCapabilities();
|
GLCapabilities caps = GL.createCapabilities();
|
||||||
instancedArrays = getLatest(InstancedArrays.class, caps);
|
instancedArrays = getLatest(InstancedArrays.class, caps);
|
||||||
bufferStorage = getLatest(BufferStorage.class, caps);
|
bufferStorage = getLatest(BufferStorage.class, caps);
|
||||||
|
|
|
@ -14,13 +14,16 @@ import com.jozufozu.flywheel.api.instance.DynamicInstance;
|
||||||
import com.jozufozu.flywheel.api.instance.TickableInstance;
|
import com.jozufozu.flywheel.api.instance.TickableInstance;
|
||||||
import com.jozufozu.flywheel.backend.Backend;
|
import com.jozufozu.flywheel.backend.Backend;
|
||||||
import com.jozufozu.flywheel.backend.instancing.instancing.InstancingEngine;
|
import com.jozufozu.flywheel.backend.instancing.instancing.InstancingEngine;
|
||||||
|
import com.jozufozu.flywheel.backend.instancing.ratelimit.BandedPrimeLimiter;
|
||||||
|
import com.jozufozu.flywheel.backend.instancing.ratelimit.DistanceUpdateLimiter;
|
||||||
|
import com.jozufozu.flywheel.backend.instancing.ratelimit.NonLimiter;
|
||||||
|
import com.jozufozu.flywheel.config.FlwConfig;
|
||||||
import com.jozufozu.flywheel.light.LightUpdater;
|
import com.jozufozu.flywheel.light.LightUpdater;
|
||||||
import com.mojang.math.Vector3f;
|
import com.mojang.math.Vector3f;
|
||||||
|
|
||||||
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
||||||
import net.minecraft.client.Camera;
|
import net.minecraft.client.Camera;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.util.Mth;
|
|
||||||
|
|
||||||
public abstract class InstanceManager<T> implements InstancingEngine.OriginShiftListener {
|
public abstract class InstanceManager<T> implements InstancingEngine.OriginShiftListener {
|
||||||
|
|
||||||
|
@ -33,8 +36,8 @@ public abstract class InstanceManager<T> implements InstancingEngine.OriginShift
|
||||||
protected final Object2ObjectOpenHashMap<T, TickableInstance> tickableInstances;
|
protected final Object2ObjectOpenHashMap<T, TickableInstance> tickableInstances;
|
||||||
protected final Object2ObjectOpenHashMap<T, DynamicInstance> dynamicInstances;
|
protected final Object2ObjectOpenHashMap<T, DynamicInstance> dynamicInstances;
|
||||||
|
|
||||||
protected int frame;
|
protected DistanceUpdateLimiter frame;
|
||||||
protected int tick;
|
protected DistanceUpdateLimiter tick;
|
||||||
|
|
||||||
public InstanceManager(MaterialManager materialManager) {
|
public InstanceManager(MaterialManager materialManager) {
|
||||||
this.materialManager = materialManager;
|
this.materialManager = materialManager;
|
||||||
|
@ -44,6 +47,17 @@ public abstract class InstanceManager<T> implements InstancingEngine.OriginShift
|
||||||
|
|
||||||
this.dynamicInstances = new Object2ObjectOpenHashMap<>();
|
this.dynamicInstances = new Object2ObjectOpenHashMap<>();
|
||||||
this.tickableInstances = new Object2ObjectOpenHashMap<>();
|
this.tickableInstances = new Object2ObjectOpenHashMap<>();
|
||||||
|
|
||||||
|
frame = createUpdateLimiter();
|
||||||
|
tick = createUpdateLimiter();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected DistanceUpdateLimiter createUpdateLimiter() {
|
||||||
|
if (FlwConfig.get().limitUpdates()) {
|
||||||
|
return new BandedPrimeLimiter();
|
||||||
|
} else {
|
||||||
|
return new NonLimiter();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -86,7 +100,7 @@ public abstract class InstanceManager<T> implements InstancingEngine.OriginShift
|
||||||
* </p>
|
* </p>
|
||||||
*/
|
*/
|
||||||
public void tick(TaskEngine taskEngine, double cameraX, double cameraY, double cameraZ) {
|
public void tick(TaskEngine taskEngine, double cameraX, double cameraY, double cameraZ) {
|
||||||
tick++;
|
tick.tick();
|
||||||
processQueuedUpdates();
|
processQueuedUpdates();
|
||||||
|
|
||||||
// integer camera pos as a micro-optimization
|
// integer camera pos as a micro-optimization
|
||||||
|
@ -112,7 +126,7 @@ public abstract class InstanceManager<T> implements InstancingEngine.OriginShift
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void tickInstance(int cX, int cY, int cZ, TickableInstance instance) {
|
protected void tickInstance(int cX, int cY, int cZ, TickableInstance instance) {
|
||||||
if (!instance.decreaseTickRateWithDistance()) {
|
if (!instance.decreaseTickRateWithDistance()) {
|
||||||
instance.tick();
|
instance.tick();
|
||||||
return;
|
return;
|
||||||
|
@ -124,11 +138,11 @@ public abstract class InstanceManager<T> implements InstancingEngine.OriginShift
|
||||||
int dY = pos.getY() - cY;
|
int dY = pos.getY() - cY;
|
||||||
int dZ = pos.getZ() - cZ;
|
int dZ = pos.getZ() - cZ;
|
||||||
|
|
||||||
if ((tick % getUpdateDivisor(dX, dY, dZ)) == 0) instance.tick();
|
if (tick.shouldUpdate(dX, dY, dZ)) instance.tick();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void beginFrame(TaskEngine taskEngine, Camera info) {
|
public void beginFrame(TaskEngine taskEngine, Camera info) {
|
||||||
frame++;
|
frame.tick();
|
||||||
processQueuedAdditions();
|
processQueuedAdditions();
|
||||||
|
|
||||||
Vector3f look = info.getLookVector();
|
Vector3f look = info.getLookVector();
|
||||||
|
@ -151,8 +165,7 @@ public abstract class InstanceManager<T> implements InstancingEngine.OriginShift
|
||||||
List<DynamicInstance> sub = instances.subList(start, end);
|
List<DynamicInstance> sub = instances.subList(start, end);
|
||||||
taskEngine.submit(() -> {
|
taskEngine.submit(() -> {
|
||||||
for (DynamicInstance dyn : sub) {
|
for (DynamicInstance dyn : sub) {
|
||||||
if (!dyn.decreaseFramerateWithDistance() || shouldFrameUpdate(dyn.getWorldPosition(), lookX, lookY, lookZ, cX, cY, cZ))
|
updateInstance(dyn, lookX, lookY, lookZ, cX, cY, cZ);
|
||||||
dyn.beginFrame();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -160,6 +173,28 @@ public abstract class InstanceManager<T> implements InstancingEngine.OriginShift
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void updateInstance(DynamicInstance dyn, float lookX, float lookY, float lookZ, int cX, int cY, int cZ) {
|
||||||
|
if (!dyn.decreaseFramerateWithDistance()) {
|
||||||
|
dyn.beginFrame();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockPos worldPos = dyn.getWorldPosition();
|
||||||
|
int dX = worldPos.getX() - cX;
|
||||||
|
int dY = worldPos.getY() - cY;
|
||||||
|
int dZ = worldPos.getZ() - cZ;
|
||||||
|
|
||||||
|
// is it more than 2 blocks behind the camera?
|
||||||
|
int dist = 2;
|
||||||
|
float dot = (dX + lookX * dist) * lookX + (dY + lookY * dist) * lookY + (dZ + lookZ * dist) * lookZ;
|
||||||
|
if (dot < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (frame.shouldUpdate(dX, dY, dZ))
|
||||||
|
dyn.beginFrame();
|
||||||
|
}
|
||||||
|
|
||||||
public void add(T obj) {
|
public void add(T obj) {
|
||||||
if (!Backend.isOn()) return;
|
if (!Backend.isOn()) return;
|
||||||
|
|
||||||
|
@ -268,29 +303,6 @@ public abstract class InstanceManager<T> implements InstancingEngine.OriginShift
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean shouldFrameUpdate(BlockPos worldPos, float lookX, float lookY, float lookZ, int cX, int cY, int cZ) {
|
|
||||||
int dX = worldPos.getX() - cX;
|
|
||||||
int dY = worldPos.getY() - cY;
|
|
||||||
int dZ = worldPos.getZ() - cZ;
|
|
||||||
|
|
||||||
// is it more than 2 blocks behind the camera?
|
|
||||||
int dist = 2;
|
|
||||||
float dot = (dX + lookX * dist) * lookX + (dY + lookY * dist) * lookY + (dZ + lookZ * dist) * lookZ;
|
|
||||||
if (dot < 0) return false;
|
|
||||||
|
|
||||||
return (frame % getUpdateDivisor(dX, dY, dZ)) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 1 followed by the prime numbers
|
|
||||||
private static final int[] divisorSequence = new int[] { 1, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31 };
|
|
||||||
protected int getUpdateDivisor(int dX, int dY, int dZ) {
|
|
||||||
int dSq = dX * dX + dY * dY + dZ * dZ;
|
|
||||||
|
|
||||||
int i = (dSq / 2048);
|
|
||||||
|
|
||||||
return divisorSequence[Mth.clamp(i, 0, divisorSequence.length - 1)];
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void addInternal(T obj) {
|
protected void addInternal(T obj) {
|
||||||
if (!Backend.isOn()) return;
|
if (!Backend.isOn()) return;
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
package com.jozufozu.flywheel.backend.instancing;
|
package com.jozufozu.flywheel.backend.instancing;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import com.jozufozu.flywheel.Flywheel;
|
|
||||||
import com.jozufozu.flywheel.api.instance.DynamicInstance;
|
import com.jozufozu.flywheel.api.instance.DynamicInstance;
|
||||||
import com.jozufozu.flywheel.api.instance.TickableInstance;
|
import com.jozufozu.flywheel.api.instance.TickableInstance;
|
||||||
import com.jozufozu.flywheel.backend.Backend;
|
import com.jozufozu.flywheel.backend.Backend;
|
||||||
|
@ -137,10 +134,4 @@ public class InstanceWorld {
|
||||||
.forEach(entityInstanceManager::add);
|
.forEach(entityInstanceManager::add);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void getDebugString(List<String> debug) {
|
|
||||||
debug.add("");
|
|
||||||
debug.add("Flywheel: " + Flywheel.VERSION);
|
|
||||||
debug.add("B: " + blockEntityInstanceManager.getObjectCount() + ", E: " + entityInstanceManager.getObjectCount());
|
|
||||||
engine.addDebugInfo(debug);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,10 @@ package com.jozufozu.flywheel.backend.instancing;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.Flywheel;
|
||||||
import com.jozufozu.flywheel.backend.Backend;
|
import com.jozufozu.flywheel.backend.Backend;
|
||||||
|
import com.jozufozu.flywheel.config.FlwCommands;
|
||||||
|
import com.jozufozu.flywheel.config.FlwConfig;
|
||||||
import com.jozufozu.flywheel.event.BeginFrameEvent;
|
import com.jozufozu.flywheel.event.BeginFrameEvent;
|
||||||
import com.jozufozu.flywheel.event.ReloadRenderersEvent;
|
import com.jozufozu.flywheel.event.ReloadRenderersEvent;
|
||||||
import com.jozufozu.flywheel.event.RenderLayerEvent;
|
import com.jozufozu.flywheel.event.RenderLayerEvent;
|
||||||
|
@ -62,7 +65,6 @@ public class InstancedRenderDispatcher {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void tick(Minecraft mc) {
|
public static void tick(Minecraft mc) {
|
||||||
|
|
||||||
if (!Backend.isGameActive()) {
|
if (!Backend.isGameActive()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -104,7 +106,17 @@ public class InstancedRenderDispatcher {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void getDebugString(List<String> debug) {
|
public static void getDebugString(List<String> debug) {
|
||||||
instanceWorlds.get(Minecraft.getInstance().level)
|
debug.add("");
|
||||||
.getDebugString(debug);
|
debug.add("Flywheel: " + Flywheel.getVersion());
|
||||||
|
|
||||||
|
if (Backend.isOn()) {
|
||||||
|
InstanceWorld instanceWorld = instanceWorlds.get(Minecraft.getInstance().level);
|
||||||
|
|
||||||
|
debug.add("Update limiting: " + FlwCommands.boolToText(FlwConfig.get().limitUpdates()).getString());
|
||||||
|
debug.add("B: " + instanceWorld.blockEntityInstanceManager.getObjectCount() + ", E: " + instanceWorld.entityInstanceManager.getObjectCount());
|
||||||
|
instanceWorld.engine.addDebugInfo(debug);
|
||||||
|
} else {
|
||||||
|
debug.add("Disabled");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,11 +6,11 @@ import com.jozufozu.flywheel.Flywheel;
|
||||||
import com.jozufozu.flywheel.api.InstanceData;
|
import com.jozufozu.flywheel.api.InstanceData;
|
||||||
import com.jozufozu.flywheel.api.struct.Instanced;
|
import com.jozufozu.flywheel.api.struct.Instanced;
|
||||||
import com.jozufozu.flywheel.api.struct.StructWriter;
|
import com.jozufozu.flywheel.api.struct.StructWriter;
|
||||||
import com.jozufozu.flywheel.backend.Backend;
|
|
||||||
import com.jozufozu.flywheel.backend.gl.GlVertexArray;
|
import com.jozufozu.flywheel.backend.gl.GlVertexArray;
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer;
|
import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer;
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
|
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer;
|
import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer;
|
||||||
|
import com.jozufozu.flywheel.backend.gl.versioned.GlCompat;
|
||||||
import com.jozufozu.flywheel.backend.instancing.AbstractInstancer;
|
import com.jozufozu.flywheel.backend.instancing.AbstractInstancer;
|
||||||
import com.jozufozu.flywheel.backend.model.BufferedModel;
|
import com.jozufozu.flywheel.backend.model.BufferedModel;
|
||||||
import com.jozufozu.flywheel.backend.model.ModelAllocator;
|
import com.jozufozu.flywheel.backend.model.ModelAllocator;
|
||||||
|
@ -198,7 +198,7 @@ public class GPUInstancer<D extends InstanceData> extends AbstractInstancer<D> {
|
||||||
vao.bindAttributes(attributeBaseIndex, instanceFormat);
|
vao.bindAttributes(attributeBaseIndex, instanceFormat);
|
||||||
|
|
||||||
for (int i = 0; i < instanceFormat.getAttributeCount(); i++) {
|
for (int i = 0; i < instanceFormat.getAttributeCount(); i++) {
|
||||||
Backend.compat.instancedArrays.vertexAttribDivisor(attributeBaseIndex + i, 1);
|
GlCompat.getInstance().instancedArrays.vertexAttribDivisor(attributeBaseIndex + i, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,8 +7,8 @@ import com.jozufozu.flywheel.api.InstanceData;
|
||||||
import com.jozufozu.flywheel.api.MaterialGroup;
|
import com.jozufozu.flywheel.api.MaterialGroup;
|
||||||
import com.jozufozu.flywheel.api.struct.Instanced;
|
import com.jozufozu.flywheel.api.struct.Instanced;
|
||||||
import com.jozufozu.flywheel.api.struct.StructType;
|
import com.jozufozu.flywheel.api.struct.StructType;
|
||||||
import com.jozufozu.flywheel.backend.Backend;
|
|
||||||
import com.jozufozu.flywheel.backend.RenderLayer;
|
import com.jozufozu.flywheel.backend.RenderLayer;
|
||||||
|
import com.jozufozu.flywheel.backend.gl.versioned.GlCompat;
|
||||||
import com.jozufozu.flywheel.backend.model.FallbackAllocator;
|
import com.jozufozu.flywheel.backend.model.FallbackAllocator;
|
||||||
import com.jozufozu.flywheel.backend.model.ModelAllocator;
|
import com.jozufozu.flywheel.backend.model.ModelAllocator;
|
||||||
import com.jozufozu.flywheel.backend.model.ModelPool;
|
import com.jozufozu.flywheel.backend.model.ModelPool;
|
||||||
|
@ -40,7 +40,8 @@ public class InstancedMaterialGroup<P extends WorldProgram> implements MaterialG
|
||||||
public InstancedMaterialGroup(InstancingEngine<P> owner, RenderType type) {
|
public InstancedMaterialGroup(InstancingEngine<P> owner, RenderType type) {
|
||||||
this.owner = owner;
|
this.owner = owner;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
if (Backend.compat.onAMDWindows()) {
|
if (GlCompat.getInstance()
|
||||||
|
.onAMDWindows()) {
|
||||||
this.allocator = FallbackAllocator.INSTANCE;
|
this.allocator = FallbackAllocator.INSTANCE;
|
||||||
} else {
|
} else {
|
||||||
this.allocator = new ModelPool(Formats.POS_TEX_NORMAL, 2048);
|
this.allocator = new ModelPool(Formats.POS_TEX_NORMAL, 2048);
|
||||||
|
|
|
@ -155,9 +155,9 @@ public class InstancingEngine<P extends WorldProgram> implements Engine {
|
||||||
@Override
|
@Override
|
||||||
public void addDebugInfo(List<String> info) {
|
public void addDebugInfo(List<String> info) {
|
||||||
info.add("GL33 Instanced Arrays");
|
info.add("GL33 Instanced Arrays");
|
||||||
info.add("Origin: " + originCoordinate.getX() + ", " + originCoordinate.getY() + ", " + originCoordinate.getZ());
|
|
||||||
info.add("Instances: " + getGroupsToRender(null).mapToInt(InstancedMaterialGroup::getInstanceCount).sum());
|
info.add("Instances: " + getGroupsToRender(null).mapToInt(InstancedMaterialGroup::getInstanceCount).sum());
|
||||||
info.add("Vertices: " + getGroupsToRender(null).mapToInt(InstancedMaterialGroup::getVertexCount).sum());
|
info.add("Vertices: " + getGroupsToRender(null).mapToInt(InstancedMaterialGroup::getVertexCount).sum());
|
||||||
|
info.add("Origin: " + originCoordinate.getX() + ", " + originCoordinate.getY() + ", " + originCoordinate.getZ());
|
||||||
}
|
}
|
||||||
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
package com.jozufozu.flywheel.backend.instancing.ratelimit;
|
||||||
|
|
||||||
|
import net.minecraft.util.Mth;
|
||||||
|
|
||||||
|
public class BandedPrimeLimiter implements DistanceUpdateLimiter {
|
||||||
|
// 1 followed by the prime numbers
|
||||||
|
private static final int[] divisorSequence = new int[] { 1, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31 };
|
||||||
|
|
||||||
|
private int tickCount = 0;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tick() {
|
||||||
|
tickCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shouldUpdate(int dX, int dY, int dZ) {
|
||||||
|
return (tickCount % getUpdateDivisor(dX, dY, dZ)) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int getUpdateDivisor(int dX, int dY, int dZ) {
|
||||||
|
int dSq = dX * dX + dY * dY + dZ * dZ;
|
||||||
|
|
||||||
|
int i = (dSq / 2048);
|
||||||
|
|
||||||
|
return divisorSequence[Mth.clamp(i, 0, divisorSequence.length - 1)];
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
package com.jozufozu.flywheel.backend.instancing.ratelimit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for rate-limiting updates based on an object's distance from the camera.
|
||||||
|
*/
|
||||||
|
public interface DistanceUpdateLimiter {
|
||||||
|
/**
|
||||||
|
* Call this before every update.
|
||||||
|
*/
|
||||||
|
void tick();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check to see if an object at the given position relative to the camera should be updated.
|
||||||
|
* @param dX The X distance from the camera.
|
||||||
|
* @param dY The Y distance from the camera.
|
||||||
|
* @param dZ The Z distance from the camera.
|
||||||
|
* @return {@code true} if the object should be updated, {@code false} otherwise.
|
||||||
|
*/
|
||||||
|
boolean shouldUpdate(int dX, int dY, int dZ);
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
package com.jozufozu.flywheel.backend.instancing.ratelimit;
|
||||||
|
|
||||||
|
public class NonLimiter implements DistanceUpdateLimiter {
|
||||||
|
@Override
|
||||||
|
public void tick() {
|
||||||
|
// noop
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shouldUpdate(int dX, int dY, int dZ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,7 +18,7 @@ import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.network.chat.MutableComponent;
|
import net.minecraft.network.chat.MutableComponent;
|
||||||
import net.minecraft.network.chat.TextComponent;
|
import net.minecraft.network.chat.TextComponent;
|
||||||
|
|
||||||
public final class ConfigCommands {
|
public final class FlwCommands {
|
||||||
public static void init(FlwConfig config) {
|
public static void init(FlwConfig config) {
|
||||||
ConfigCommandBuilder commandBuilder = new ConfigCommandBuilder("flywheel");
|
ConfigCommandBuilder commandBuilder = new ConfigCommandBuilder("flywheel");
|
||||||
|
|
||||||
|
@ -44,6 +44,17 @@ public final class ConfigCommands {
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
|
||||||
|
commandBuilder.addOption(config.limitUpdates, (builder, option) -> booleanOptionCommand(builder, config, option,
|
||||||
|
(source, value) -> {
|
||||||
|
Component text = new TextComponent("Update limiting is currently: ").append(boolToText(value));
|
||||||
|
source.sendFeedback(text);
|
||||||
|
},
|
||||||
|
(source, value) -> {
|
||||||
|
Component text = boolToText(value).append(new TextComponent(" update limiting.").withStyle(ChatFormatting.WHITE));
|
||||||
|
source.sendFeedback(text);
|
||||||
|
}
|
||||||
|
));
|
||||||
|
|
||||||
commandBuilder.build();
|
commandBuilder.build();
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,8 @@ public class FlwConfig {
|
||||||
public final EnumOption<FlwEngine> engine = addOption(new EnumOption<>("engine", FlwEngine.INSTANCING));
|
public final EnumOption<FlwEngine> engine = addOption(new EnumOption<>("engine", FlwEngine.INSTANCING));
|
||||||
/** Enable or disable a debug overlay that colors pixels by their normal */
|
/** Enable or disable a debug overlay that colors pixels by their normal */
|
||||||
public final BooleanOption debugNormals = addOption(new BooleanOption("debugNormals", false));
|
public final BooleanOption debugNormals = addOption(new BooleanOption("debugNormals", false));
|
||||||
|
/** Enable or disable instance update limiting with distance. */
|
||||||
|
public final BooleanOption limitUpdates = addOption(new BooleanOption("limitUpdates", true));
|
||||||
|
|
||||||
public FlwConfig(File file) {
|
public FlwConfig(File file) {
|
||||||
this.file = file;
|
this.file = file;
|
||||||
|
@ -49,7 +51,7 @@ public class FlwConfig {
|
||||||
|
|
||||||
public static void init() {
|
public static void init() {
|
||||||
INSTANCE.load();
|
INSTANCE.load();
|
||||||
ConfigCommands.init(INSTANCE);
|
FlwCommands.init(INSTANCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public FlwEngine getEngine() {
|
public FlwEngine getEngine() {
|
||||||
|
@ -60,6 +62,10 @@ public class FlwConfig {
|
||||||
return debugNormals.get();
|
return debugNormals.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean limitUpdates() {
|
||||||
|
return limitUpdates.get();
|
||||||
|
}
|
||||||
|
|
||||||
public void load() {
|
public void load() {
|
||||||
if (file.exists()) {
|
if (file.exists()) {
|
||||||
try (FileReader reader = new FileReader(file)) {
|
try (FileReader reader = new FileReader(file)) {
|
||||||
|
|
|
@ -54,6 +54,7 @@ public class ProgramCompiler<P extends GlProgram> extends Memoizer<ProgramContex
|
||||||
return super.get(ctx);
|
return super.get(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void invalidate() {
|
public void invalidate() {
|
||||||
super.invalidate();
|
super.invalidate();
|
||||||
vertexCompiler.invalidate();
|
vertexCompiler.invalidate();
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
package com.jozufozu.flywheel.core.crumbling;
|
package com.jozufozu.flywheel.core.crumbling;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.api.MaterialManager;
|
import com.jozufozu.flywheel.api.MaterialManager;
|
||||||
|
import com.jozufozu.flywheel.api.instance.DynamicInstance;
|
||||||
import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstanceManager;
|
import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstanceManager;
|
||||||
|
|
||||||
import net.minecraft.core.BlockPos;
|
|
||||||
|
|
||||||
public class CrumblingInstanceManager extends BlockEntityInstanceManager {
|
public class CrumblingInstanceManager extends BlockEntityInstanceManager {
|
||||||
|
|
||||||
public CrumblingInstanceManager(MaterialManager materialManager) {
|
public CrumblingInstanceManager(MaterialManager materialManager) {
|
||||||
|
@ -12,7 +11,7 @@ public class CrumblingInstanceManager extends BlockEntityInstanceManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean shouldFrameUpdate(BlockPos worldPos, float lookX, float lookY, float lookZ, int cX, int cY, int cZ) {
|
protected void updateInstance(DynamicInstance dyn, float lookX, float lookY, float lookZ, int cX, int cY, int cZ) {
|
||||||
return true;
|
dyn.beginFrame();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,9 +12,9 @@ import net.minecraft.client.multiplayer.ClientLevel;
|
||||||
|
|
||||||
public class ForgeEvents {
|
public class ForgeEvents {
|
||||||
|
|
||||||
public static void addToDebugScreen(List<String> left) {
|
public static void addToDebugScreen(List<String> right) {
|
||||||
|
|
||||||
InstancedRenderDispatcher.getDebugString(left);
|
InstancedRenderDispatcher.getDebugString(right);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void unloadWorld(ClientLevel world) {
|
public static void unloadWorld(ClientLevel world) {
|
||||||
|
|
|
@ -14,8 +14,8 @@ import net.minecraft.client.gui.components.DebugScreenOverlay;
|
||||||
|
|
||||||
@Mixin(DebugScreenOverlay.class)
|
@Mixin(DebugScreenOverlay.class)
|
||||||
public abstract class DebugScreenOverlayMixin extends GuiComponent {
|
public abstract class DebugScreenOverlayMixin extends GuiComponent {
|
||||||
@Inject(method = "getGameInformation", at = @At("RETURN"))
|
@Inject(method = "getSystemInformation", at = @At("RETURN"))
|
||||||
private void modifyLeftText(CallbackInfoReturnable<List<String>> cir) {
|
private void modifyRightText(CallbackInfoReturnable<List<String>> cir) {
|
||||||
ForgeEvents.addToDebugScreen(cir.getReturnValue());
|
ForgeEvents.addToDebugScreen(cir.getReturnValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
"environment": "client",
|
"environment": "client",
|
||||||
"entrypoints": {
|
"entrypoints": {
|
||||||
"client": [
|
"client": [
|
||||||
"com.jozufozu.flywheel.FlywheelClient"
|
"com.jozufozu.flywheel.Flywheel"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"mixins": [
|
"mixins": [
|
||||||
|
|
Loading…
Add table
Reference in a new issue