mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2024-12-27 23:47:09 +01:00
Better config/backend to account for multiple engines
- Rename probably too many things - Needs to be tested with Optifine
This commit is contained in:
parent
a1bf03689c
commit
d78f030264
18 changed files with 195 additions and 168 deletions
|
@ -3,10 +3,12 @@ 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.config.EngineArgument;
|
||||||
import com.jozufozu.flywheel.config.FlwCommands;
|
import com.jozufozu.flywheel.config.FlwCommands;
|
||||||
import com.jozufozu.flywheel.config.FlwConfig;
|
import com.jozufozu.flywheel.config.FlwConfig;
|
||||||
import com.jozufozu.flywheel.config.FlwPackets;
|
import com.jozufozu.flywheel.config.FlwPackets;
|
||||||
|
|
||||||
|
import net.minecraft.commands.synchronization.ArgumentTypes;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraftforge.api.distmarker.Dist;
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
import net.minecraftforge.common.MinecraftForge;
|
import net.minecraftforge.common.MinecraftForge;
|
||||||
|
@ -39,5 +41,6 @@ public class Flywheel {
|
||||||
|
|
||||||
private void setup(final FMLCommonSetupEvent event) {
|
private void setup(final FMLCommonSetupEvent event) {
|
||||||
FlwPackets.registerPackets();
|
FlwPackets.registerPackets();
|
||||||
|
ArgumentTypes.register("flywheel:engine", EngineArgument.class, EngineArgument.SERIALIZER);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,13 +17,11 @@ import com.jozufozu.flywheel.api.FlywheelWorld;
|
||||||
import com.jozufozu.flywheel.api.InstanceData;
|
import com.jozufozu.flywheel.api.InstanceData;
|
||||||
import com.jozufozu.flywheel.api.struct.StructType;
|
import com.jozufozu.flywheel.api.struct.StructType;
|
||||||
import com.jozufozu.flywheel.backend.gl.versioned.GlCompat;
|
import com.jozufozu.flywheel.backend.gl.versioned.GlCompat;
|
||||||
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
|
|
||||||
import com.jozufozu.flywheel.config.FlwConfig;
|
import com.jozufozu.flywheel.config.FlwConfig;
|
||||||
import com.jozufozu.flywheel.config.FlwEngine;
|
import com.jozufozu.flywheel.config.FlwEngine;
|
||||||
import com.jozufozu.flywheel.core.shader.spec.ProgramSpec;
|
import com.jozufozu.flywheel.core.shader.spec.ProgramSpec;
|
||||||
|
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.multiplayer.ClientLevel;
|
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
import net.minecraft.world.level.LevelAccessor;
|
import net.minecraft.world.level.LevelAccessor;
|
||||||
|
@ -32,20 +30,18 @@ public class Backend {
|
||||||
public static final Logger log = LogManager.getLogger(Backend.class);
|
public static final Logger log = LogManager.getLogger(Backend.class);
|
||||||
|
|
||||||
protected static final Backend INSTANCE = new Backend();
|
protected static final Backend INSTANCE = new Backend();
|
||||||
private FlwEngine engine;
|
|
||||||
|
|
||||||
public static Backend getInstance() {
|
public static Backend getInstance() {
|
||||||
return INSTANCE;
|
return INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final Loader loader;
|
private FlwEngine engine;
|
||||||
|
|
||||||
public GLCapabilities capabilities;
|
public GLCapabilities capabilities;
|
||||||
public GlCompat compat;
|
public GlCompat compat;
|
||||||
|
|
||||||
private boolean instancedArrays;
|
|
||||||
private boolean enabled;
|
private boolean enabled;
|
||||||
|
|
||||||
|
public final Loader loader;
|
||||||
private final List<ShaderContext<?>> contexts = new ArrayList<>();
|
private final List<ShaderContext<?>> contexts = new ArrayList<>();
|
||||||
private final Map<ResourceLocation, StructType<?>> materialRegistry = new HashMap<>();
|
private final Map<ResourceLocation, StructType<?>> materialRegistry = new HashMap<>();
|
||||||
private final Map<ResourceLocation, ProgramSpec> programSpecRegistry = new HashMap<>();
|
private final Map<ResourceLocation, ProgramSpec> programSpecRegistry = new HashMap<>();
|
||||||
|
@ -61,16 +57,11 @@ public class Backend {
|
||||||
* (Meshlet, MDI, GL31 Draw Instanced are planned), this will name which one is in use.
|
* (Meshlet, MDI, GL31 Draw Instanced are planned), this will name which one is in use.
|
||||||
*/
|
*/
|
||||||
public String getBackendDescriptor() {
|
public String getBackendDescriptor() {
|
||||||
if (enabled) {
|
return engine.getProperName();
|
||||||
ClientLevel level = Minecraft.getInstance().level;
|
}
|
||||||
|
|
||||||
if (level == null) {
|
public FlwEngine getEngine() {
|
||||||
return "Invalid";
|
return engine;
|
||||||
}
|
|
||||||
return InstancedRenderDispatcher.getEngineName(level);
|
|
||||||
}
|
|
||||||
|
|
||||||
return "Disabled";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -111,41 +102,22 @@ public class Backend {
|
||||||
return programSpecRegistry.get(name);
|
return programSpecRegistry.get(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean available() {
|
|
||||||
return canUseVBOs();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean canUseInstancing() {
|
|
||||||
return enabled && instancedArrays;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean canUseVBOs() {
|
|
||||||
return enabled && gl20();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean gl33() {
|
|
||||||
return capabilities.OpenGL33;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean gl20() {
|
|
||||||
return capabilities.OpenGL20;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void refresh() {
|
public void refresh() {
|
||||||
OptifineHandler.refresh();
|
OptifineHandler.refresh();
|
||||||
|
boolean usingShaders = OptifineHandler.usingShaders();
|
||||||
|
|
||||||
capabilities = GL.createCapabilities();
|
capabilities = GL.createCapabilities();
|
||||||
|
|
||||||
compat = new GlCompat(capabilities);
|
compat = new GlCompat(capabilities);
|
||||||
|
|
||||||
instancedArrays = compat.instancedArraysSupported();
|
engine = FlwConfig.get()
|
||||||
|
.getEngine();
|
||||||
|
|
||||||
FlwConfig config = FlwConfig.get();
|
enabled = switch (engine) {
|
||||||
enabled = config.enabled() && !OptifineHandler.usingShaders();
|
case OFF -> false;
|
||||||
engine = config.client.engine.get();
|
case BATCHING -> true;
|
||||||
}
|
case INSTANCING -> !usingShaders && compat.instancedArraysSupported();
|
||||||
|
};
|
||||||
public boolean canUseInstancing(@Nullable Level world) {
|
|
||||||
return canUseInstancing() && isFlywheelWorld(world);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<StructType<?>> allMaterials() {
|
public Collection<StructType<?>> allMaterials() {
|
||||||
|
@ -160,6 +132,14 @@ public class Backend {
|
||||||
return contexts;
|
return contexts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isOn() {
|
||||||
|
return getInstance().enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean canUseInstancing(@Nullable Level world) {
|
||||||
|
return isOn() && isFlywheelWorld(world);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to avoid calling Flywheel functions on (fake) worlds that don't specifically support it.
|
* Used to avoid calling Flywheel functions on (fake) worlds that don't specifically support it.
|
||||||
*/
|
*/
|
||||||
|
@ -184,7 +164,7 @@ public class Backend {
|
||||||
/**
|
/**
|
||||||
* INTERNAL USE ONLY
|
* INTERNAL USE ONLY
|
||||||
*/
|
*/
|
||||||
public void _clearContexts() {
|
void _clearContexts() {
|
||||||
GameStateRegistry.clear();
|
GameStateRegistry.clear();
|
||||||
programSpecRegistry.clear();
|
programSpecRegistry.clear();
|
||||||
contexts.forEach(ShaderContext::delete);
|
contexts.forEach(ShaderContext::delete);
|
||||||
|
@ -194,8 +174,4 @@ public class Backend {
|
||||||
|
|
||||||
public static void init() {
|
public static void init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public FlwEngine getEngine() {
|
|
||||||
return engine;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,36 +64,34 @@ public class Loader implements ResourceManagerReloadListener {
|
||||||
public void onResourceManagerReload(ResourceManager manager) {
|
public void onResourceManagerReload(ResourceManager manager) {
|
||||||
backend.refresh();
|
backend.refresh();
|
||||||
|
|
||||||
if (backend.gl20()) {
|
shouldCrash = false;
|
||||||
shouldCrash = false;
|
backend._clearContexts();
|
||||||
backend._clearContexts();
|
|
||||||
|
|
||||||
Resolver.INSTANCE.invalidate();
|
Resolver.INSTANCE.invalidate();
|
||||||
ModLoader.get()
|
ModLoader.get()
|
||||||
.postEvent(new GatherContextEvent(backend, firstLoad));
|
.postEvent(new GatherContextEvent(backend, firstLoad));
|
||||||
|
|
||||||
ShaderSources sources = new ShaderSources(manager);
|
ShaderSources sources = new ShaderSources(manager);
|
||||||
|
|
||||||
loadProgramSpecs(manager);
|
loadProgramSpecs(manager);
|
||||||
|
|
||||||
Resolver.INSTANCE.resolve(sources);
|
Resolver.INSTANCE.resolve(sources);
|
||||||
|
|
||||||
for (ShaderContext<?> context : backend.allContexts()) {
|
for (ShaderContext<?> context : backend.allContexts()) {
|
||||||
context.load();
|
context.load();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shouldCrash) {
|
if (shouldCrash) {
|
||||||
throw new ShaderLoadingException("Could not load all shaders, see log for details");
|
throw new ShaderLoadingException("Could not load all shaders, see log for details");
|
||||||
}
|
}
|
||||||
|
|
||||||
Backend.log.info("Loaded all shader programs.");
|
Backend.log.info("Loaded all shader programs.");
|
||||||
|
|
||||||
ClientLevel world = Minecraft.getInstance().level;
|
ClientLevel world = Minecraft.getInstance().level;
|
||||||
if (Backend.isFlywheelWorld(world)) {
|
if (Backend.isFlywheelWorld(world)) {
|
||||||
// TODO: looks like it might be good to have another event here
|
// TODO: looks like it might be good to have another event here
|
||||||
InstancedRenderDispatcher.resetInstanceWorld(world);
|
InstancedRenderDispatcher.resetInstanceWorld(world);
|
||||||
CrumblingRenderer.reset();
|
CrumblingRenderer.reset();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
firstLoad = false;
|
firstLoad = false;
|
||||||
|
|
|
@ -154,8 +154,7 @@ public abstract class InstanceManager<T> implements InstancingEngine.OriginShift
|
||||||
}
|
}
|
||||||
|
|
||||||
public void add(T obj) {
|
public void add(T obj) {
|
||||||
if (!Backend.getInstance()
|
if (!Backend.isOn()) return;
|
||||||
.canUseInstancing()) return;
|
|
||||||
|
|
||||||
if (canInstance(obj)) {
|
if (canInstance(obj)) {
|
||||||
addInternal(obj);
|
addInternal(obj);
|
||||||
|
@ -163,8 +162,7 @@ public abstract class InstanceManager<T> implements InstancingEngine.OriginShift
|
||||||
}
|
}
|
||||||
|
|
||||||
public void queueAdd(T obj) {
|
public void queueAdd(T obj) {
|
||||||
if (!Backend.getInstance()
|
if (!Backend.isOn()) return;
|
||||||
.canUseInstancing()) return;
|
|
||||||
|
|
||||||
synchronized (queuedAdditions) {
|
synchronized (queuedAdditions) {
|
||||||
queuedAdditions.add(obj);
|
queuedAdditions.add(obj);
|
||||||
|
@ -172,8 +170,7 @@ public abstract class InstanceManager<T> implements InstancingEngine.OriginShift
|
||||||
}
|
}
|
||||||
|
|
||||||
public void queueUpdate(T obj) {
|
public void queueUpdate(T obj) {
|
||||||
if (!Backend.getInstance()
|
if (!Backend.isOn()) return;
|
||||||
.canUseInstancing()) return;
|
|
||||||
synchronized (queuedUpdates) {
|
synchronized (queuedUpdates) {
|
||||||
queuedUpdates.add(obj);
|
queuedUpdates.add(obj);
|
||||||
}
|
}
|
||||||
|
@ -191,8 +188,7 @@ public abstract class InstanceManager<T> implements InstancingEngine.OriginShift
|
||||||
* @param obj the object to update.
|
* @param obj the object to update.
|
||||||
*/
|
*/
|
||||||
public void update(T obj) {
|
public void update(T obj) {
|
||||||
if (!Backend.getInstance()
|
if (!Backend.isOn()) return;
|
||||||
.canUseInstancing()) return;
|
|
||||||
|
|
||||||
if (canInstance(obj)) {
|
if (canInstance(obj)) {
|
||||||
AbstractInstance instance = getInstance(obj);
|
AbstractInstance instance = getInstance(obj);
|
||||||
|
@ -213,8 +209,7 @@ public abstract class InstanceManager<T> implements InstancingEngine.OriginShift
|
||||||
}
|
}
|
||||||
|
|
||||||
public void remove(T obj) {
|
public void remove(T obj) {
|
||||||
if (!Backend.getInstance()
|
if (!Backend.isOn()) return;
|
||||||
.canUseInstancing()) return;
|
|
||||||
|
|
||||||
if (canInstance(obj)) {
|
if (canInstance(obj)) {
|
||||||
AbstractInstance instance = getInstance(obj);
|
AbstractInstance instance = getInstance(obj);
|
||||||
|
@ -231,8 +226,7 @@ public abstract class InstanceManager<T> implements InstancingEngine.OriginShift
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
protected <I extends T> AbstractInstance getInstance(I obj) {
|
protected <I extends T> AbstractInstance getInstance(I obj) {
|
||||||
if (!Backend.getInstance()
|
if (!Backend.isOn()) return null;
|
||||||
.canUseInstancing()) return null;
|
|
||||||
|
|
||||||
return instances.get(obj);
|
return instances.get(obj);
|
||||||
}
|
}
|
||||||
|
@ -291,8 +285,7 @@ public abstract class InstanceManager<T> implements InstancingEngine.OriginShift
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void addInternal(T obj) {
|
protected void addInternal(T obj) {
|
||||||
if (!Backend.getInstance()
|
if (!Backend.isOn()) return;
|
||||||
.canUseInstancing()) return;
|
|
||||||
|
|
||||||
AbstractInstance instance = instances.get(obj);
|
AbstractInstance instance = instances.get(obj);
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ public class InstanceWorld {
|
||||||
.getEngine();
|
.getEngine();
|
||||||
|
|
||||||
switch (engine) {
|
switch (engine) {
|
||||||
case GL33 -> {
|
case INSTANCING -> {
|
||||||
InstancingEngine<WorldProgram> manager = InstancingEngine.builder(Contexts.WORLD)
|
InstancingEngine<WorldProgram> manager = InstancingEngine.builder(Contexts.WORLD)
|
||||||
.build(this.taskEngine);
|
.build(this.taskEngine);
|
||||||
|
|
||||||
|
|
|
@ -41,10 +41,6 @@ public class InstancedRenderDispatcher {
|
||||||
getEntities(entity.level).queueUpdate(entity);
|
getEntities(entity.level).queueUpdate(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getEngineName(LevelAccessor world) {
|
|
||||||
return instanceWorlds.get(world).engine.getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static InstanceManager<BlockEntity> getTiles(LevelAccessor world) {
|
public static InstanceManager<BlockEntity> getTiles(LevelAccessor world) {
|
||||||
return instanceWorlds.get(world)
|
return instanceWorlds.get(world)
|
||||||
.getTileEntityInstanceManager();
|
.getTileEntityInstanceManager();
|
||||||
|
@ -81,8 +77,7 @@ public class InstancedRenderDispatcher {
|
||||||
if (event.layer == null) return;
|
if (event.layer == null) return;
|
||||||
|
|
||||||
ClientLevel world = event.getWorld();
|
ClientLevel world = event.getWorld();
|
||||||
if (!Backend.getInstance()
|
if (!Backend.canUseInstancing(world)) return;
|
||||||
.canUseInstancing(world)) return;
|
|
||||||
|
|
||||||
instanceWorlds.get(world).renderLayer(event);
|
instanceWorlds.get(world).renderLayer(event);
|
||||||
}
|
}
|
||||||
|
@ -90,8 +85,7 @@ public class InstancedRenderDispatcher {
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
public static void onReloadRenderers(ReloadRenderersEvent event) {
|
public static void onReloadRenderers(ReloadRenderersEvent event) {
|
||||||
ClientLevel world = event.getWorld();
|
ClientLevel world = event.getWorld();
|
||||||
if (Backend.getInstance()
|
if (Backend.isOn() && world != null) {
|
||||||
.canUseInstancing() && world != null) {
|
|
||||||
resetInstanceWorld(world);
|
resetInstanceWorld(world);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,6 @@ import net.minecraftforge.api.distmarker.Dist;
|
||||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
|
||||||
public enum BooleanConfig {
|
public enum BooleanConfig {
|
||||||
ENGINE(() -> BooleanConfig::enabled),
|
|
||||||
NORMAL_OVERLAY(() -> BooleanConfig::normalOverlay),
|
NORMAL_OVERLAY(() -> BooleanConfig::normalOverlay),
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -52,29 +51,6 @@ public enum BooleanConfig {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnlyIn(Dist.CLIENT)
|
|
||||||
private static void enabled(BooleanDirective state) {
|
|
||||||
LocalPlayer player = Minecraft.getInstance().player;
|
|
||||||
if (player == null || state == null) return;
|
|
||||||
|
|
||||||
if (state == BooleanDirective.DISPLAY) {
|
|
||||||
Component text = new TextComponent("Flywheel renderer is currently: ").append(boolToText(FlwConfig.get().enabled()));
|
|
||||||
player.displayClientMessage(text, false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean enabled = state.get();
|
|
||||||
boolean cannotUse = OptifineHandler.usingShaders() && enabled;
|
|
||||||
|
|
||||||
FlwConfig.get().client.enabled.set(enabled);
|
|
||||||
|
|
||||||
Component text = boolToText(FlwConfig.get().enabled()).append(new TextComponent(" Flywheel renderer").withStyle(ChatFormatting.WHITE));
|
|
||||||
Component error = new TextComponent("Flywheel renderer does not support Optifine Shaders").withStyle(ChatFormatting.RED);
|
|
||||||
|
|
||||||
player.displayClientMessage(cannotUse ? error : text, false);
|
|
||||||
Backend.reloadWorldRenderers();
|
|
||||||
}
|
|
||||||
|
|
||||||
@OnlyIn(Dist.CLIENT)
|
@OnlyIn(Dist.CLIENT)
|
||||||
private static void normalOverlay(BooleanDirective state) {
|
private static void normalOverlay(BooleanDirective state) {
|
||||||
LocalPlayer player = Minecraft.getInstance().player;
|
LocalPlayer player = Minecraft.getInstance().player;
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
package com.jozufozu.flywheel.config;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.mojang.brigadier.StringReader;
|
||||||
|
import com.mojang.brigadier.arguments.ArgumentType;
|
||||||
|
import com.mojang.brigadier.context.CommandContext;
|
||||||
|
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||||
|
import com.mojang.brigadier.exceptions.Dynamic2CommandExceptionType;
|
||||||
|
import com.mojang.brigadier.suggestion.Suggestions;
|
||||||
|
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
|
||||||
|
|
||||||
|
import net.minecraft.commands.SharedSuggestionProvider;
|
||||||
|
import net.minecraft.commands.synchronization.ArgumentSerializer;
|
||||||
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
|
import net.minecraft.network.chat.TranslatableComponent;
|
||||||
|
|
||||||
|
public class EngineArgument implements ArgumentType<FlwEngine> {
|
||||||
|
|
||||||
|
public static final EngineArgument INSTANCE = new EngineArgument();
|
||||||
|
public static final Serializer SERIALIZER = new Serializer();
|
||||||
|
|
||||||
|
private static final Dynamic2CommandExceptionType INVALID = new Dynamic2CommandExceptionType((found, constants) -> {
|
||||||
|
return new TranslatableComponent("commands.forge.arguments.enum.invalid", constants, found);
|
||||||
|
});
|
||||||
|
|
||||||
|
private EngineArgument() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FlwEngine parse(StringReader reader) throws CommandSyntaxException {
|
||||||
|
String string = reader.readUnquotedString();
|
||||||
|
|
||||||
|
FlwEngine engine = FlwEngine.byName(string);
|
||||||
|
|
||||||
|
if (engine == null) {
|
||||||
|
throw INVALID.createWithContext(reader, string, FlwEngine.validNames());
|
||||||
|
}
|
||||||
|
|
||||||
|
return engine;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <S> CompletableFuture<Suggestions> listSuggestions(CommandContext<S> context, SuggestionsBuilder builder) {
|
||||||
|
return SharedSuggestionProvider.suggest(FlwEngine.validNames(), builder);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<String> getExamples() {
|
||||||
|
return FlwEngine.validNames();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Serializer implements ArgumentSerializer<EngineArgument> {
|
||||||
|
private Serializer() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void serializeToNetwork(EngineArgument argument, FriendlyByteBuf buffer) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public EngineArgument deserializeFromNetwork(FriendlyByteBuf buffer) {
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void serializeToJson(EngineArgument argument, JsonObject json) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,15 +10,15 @@ import net.minecraftforge.network.PacketDistributor;
|
||||||
import net.minecraftforge.server.command.EnumArgument;
|
import net.minecraftforge.server.command.EnumArgument;
|
||||||
|
|
||||||
public class EngineConfigCommand {
|
public class EngineConfigCommand {
|
||||||
public ArgumentBuilder<CommandSourceStack, ?> register() {
|
public static ArgumentBuilder<CommandSourceStack, ?> register() {
|
||||||
return Commands.literal("engine")
|
return Commands.literal("backend")
|
||||||
.executes(context -> {
|
.executes(context -> {
|
||||||
ServerPlayer player = context.getSource()
|
ServerPlayer player = context.getSource()
|
||||||
.getPlayerOrException();
|
.getPlayerOrException();
|
||||||
FlwPackets.channel.send(PacketDistributor.PLAYER.with(() -> player), new SConfigureEnginePacket());
|
FlwPackets.channel.send(PacketDistributor.PLAYER.with(() -> player), new SConfigureEnginePacket());
|
||||||
return Command.SINGLE_SUCCESS;
|
return Command.SINGLE_SUCCESS;
|
||||||
})
|
})
|
||||||
.then(Commands.argument("type", EnumArgument.enumArgument(FlwEngine.class))
|
.then(Commands.argument("type", EngineArgument.INSTANCE)
|
||||||
.executes(context -> {
|
.executes(context -> {
|
||||||
FlwEngine type = context.getArgument("type", FlwEngine.class);
|
FlwEngine type = context.getArgument("type", FlwEngine.class);
|
||||||
|
|
||||||
|
|
|
@ -15,9 +15,8 @@ public class FlwCommands {
|
||||||
.getDispatcher();
|
.getDispatcher();
|
||||||
|
|
||||||
dispatcher.register(Commands.literal("flywheel")
|
dispatcher.register(Commands.literal("flywheel")
|
||||||
.then(new BooleanConfigCommand("backend", BooleanConfig.ENGINE).register())
|
|
||||||
.then(new BooleanConfigCommand("debugNormals", BooleanConfig.NORMAL_OVERLAY).register())
|
.then(new BooleanConfigCommand("debugNormals", BooleanConfig.NORMAL_OVERLAY).register())
|
||||||
.then(new EngineConfigCommand().register())
|
.then(EngineConfigCommand.register())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,8 +26,8 @@ public class FlwConfig {
|
||||||
return INSTANCE;
|
return INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean enabled() {
|
public FlwEngine getEngine() {
|
||||||
return client.enabled.get();
|
return client.engine.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean debugNormals() {
|
public boolean debugNormals() {
|
||||||
|
@ -38,17 +38,13 @@ public class FlwConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ClientConfig {
|
public static class ClientConfig {
|
||||||
public final BooleanValue enabled;
|
|
||||||
public final ForgeConfigSpec.EnumValue<FlwEngine> engine;
|
public final ForgeConfigSpec.EnumValue<FlwEngine> engine;
|
||||||
public final BooleanValue debugNormals;
|
public final BooleanValue debugNormals;
|
||||||
|
|
||||||
public ClientConfig(ForgeConfigSpec.Builder builder) {
|
public ClientConfig(ForgeConfigSpec.Builder builder) {
|
||||||
|
|
||||||
enabled = builder.comment("Enable or disable the entire engine")
|
|
||||||
.define("enabled", true);
|
|
||||||
|
|
||||||
engine = builder.comment("Enable or disable the entire engine")
|
engine = builder.comment("Enable or disable the entire engine")
|
||||||
.defineEnum("backend", FlwEngine.GL33);
|
.defineEnum("backend", FlwEngine.INSTANCING);
|
||||||
|
|
||||||
debugNormals = builder.comment("Enable or disable a debug overlay that colors pixels by their normal")
|
debugNormals = builder.comment("Enable or disable a debug overlay that colors pixels by their normal")
|
||||||
.define("debugNormals", false);
|
.define("debugNormals", false);
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
package com.jozufozu.flywheel.config;
|
package com.jozufozu.flywheel.config;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.Backend;
|
import com.jozufozu.flywheel.backend.Backend;
|
||||||
import com.jozufozu.flywheel.backend.OptifineHandler;
|
|
||||||
|
|
||||||
import net.minecraft.ChatFormatting;
|
import net.minecraft.ChatFormatting;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
|
@ -13,15 +16,50 @@ import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.network.chat.TextComponent;
|
import net.minecraft.network.chat.TextComponent;
|
||||||
|
|
||||||
public enum FlwEngine {
|
public enum FlwEngine {
|
||||||
BATCHING(new TextComponent("Batching").withStyle(ChatFormatting.BLUE)),
|
OFF("off", "Off", new TextComponent("Disabled Flywheel").withStyle(ChatFormatting.RED)),
|
||||||
GL33(new TextComponent("GL 3.3 Instanced Arrays").withStyle(ChatFormatting.GREEN)),
|
BATCHING("batching", "Parallel Batching", new TextComponent("Using Batching Engine").withStyle(ChatFormatting.GREEN)),
|
||||||
|
INSTANCING("instancing", "GL33 Instanced Arrays", new TextComponent("Using Instancing Engine").withStyle(ChatFormatting.GREEN)),
|
||||||
;
|
;
|
||||||
|
|
||||||
private final Component name;
|
private static final Map<String, FlwEngine> lookup;
|
||||||
|
|
||||||
FlwEngine(Component name) {
|
static {
|
||||||
this.name = name;
|
lookup = new HashMap<>();
|
||||||
|
for (FlwEngine value : values()) {
|
||||||
|
lookup.put(value.shortName, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Component message;
|
||||||
|
private final String shortName;
|
||||||
|
private final String properName;
|
||||||
|
|
||||||
|
FlwEngine(String shortName, String properName, Component message) {
|
||||||
|
this.shortName = shortName;
|
||||||
|
this.properName = properName;
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getProperName() {
|
||||||
|
return properName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void encode(FriendlyByteBuf buffer) {
|
||||||
|
buffer.writeByte(this.ordinal());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void handle(@Nullable FlwEngine type) {
|
||||||
|
LocalPlayer player = Minecraft.getInstance().player;
|
||||||
|
if (player == null) return;
|
||||||
|
|
||||||
|
if (type != null) {
|
||||||
|
FlwConfig.get().client.engine.set(type);
|
||||||
|
|
||||||
|
player.displayClientMessage(type.message, false);
|
||||||
|
Backend.reloadWorldRenderers();
|
||||||
|
} else {
|
||||||
|
player.displayClientMessage(FlwConfig.get().getEngine().message, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
|
@ -33,25 +71,12 @@ public enum FlwEngine {
|
||||||
return values()[b];
|
return values()[b];
|
||||||
}
|
}
|
||||||
|
|
||||||
public void encode(FriendlyByteBuf buffer) {
|
@Nullable
|
||||||
buffer.writeByte(this.ordinal());
|
public static FlwEngine byName(String name) {
|
||||||
|
return lookup.get(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void switchTo() {
|
public static Collection<String> validNames() {
|
||||||
LocalPlayer player = Minecraft.getInstance().player;
|
return lookup.keySet();
|
||||||
if (player == null) return;
|
|
||||||
|
|
||||||
// if (state == BooleanDirective.DISPLAY) {
|
|
||||||
// Component text = new TextComponent("Flywheel renderer is currently: ").append(boolToText(FlwConfig.get().enabled()));
|
|
||||||
// player.displayClientMessage(text, false);
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
FlwConfig.get().client.engine.set(this);
|
|
||||||
|
|
||||||
Component text = new TextComponent("Using ").withStyle(ChatFormatting.WHITE).append(name);
|
|
||||||
|
|
||||||
player.displayClientMessage(text, false);
|
|
||||||
Backend.reloadWorldRenderers();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,9 +29,7 @@ public class SConfigureEnginePacket {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void execute(Supplier<NetworkEvent.Context> ctx) {
|
public void execute(Supplier<NetworkEvent.Context> ctx) {
|
||||||
if (type != null) {
|
FlwEngine.handle(type);
|
||||||
type.switchTo();
|
|
||||||
}
|
|
||||||
ctx.get()
|
ctx.get()
|
||||||
.setPacketHandled(true);
|
.setPacketHandled(true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
@ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault
|
||||||
|
package com.jozufozu.flywheel.config;
|
||||||
|
|
||||||
|
import javax.annotation.ParametersAreNonnullByDefault;
|
||||||
|
|
||||||
|
import net.minecraft.MethodsReturnNonnullByDefault;
|
|
@ -54,8 +54,7 @@ public class CrumblingRenderer {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void renderBreaking(RenderLayerEvent event) {
|
public static void renderBreaking(RenderLayerEvent event) {
|
||||||
if (!Backend.getInstance()
|
if (!Backend.canUseInstancing(event.getWorld())) return;
|
||||||
.canUseInstancing(event.getWorld())) return;
|
|
||||||
|
|
||||||
Int2ObjectMap<List<BlockEntity>> activeStages = getActiveStageTiles(event.getWorld());
|
Int2ObjectMap<List<BlockEntity>> activeStages = getActiveStageTiles(event.getWorld());
|
||||||
|
|
||||||
|
@ -120,8 +119,7 @@ public class CrumblingRenderer {
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
public static void onReloadRenderers(ReloadRenderersEvent event) {
|
public static void onReloadRenderers(ReloadRenderersEvent event) {
|
||||||
ClientLevel world = event.getWorld();
|
ClientLevel world = event.getWorld();
|
||||||
if (Backend.getInstance()
|
if (Backend.isOn() && world != null) {
|
||||||
.canUseInstancing() && world != null) {
|
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,8 +23,7 @@ public class CancelEntityRenderMixin {
|
||||||
@Redirect(method = "renderLevel", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/multiplayer/ClientLevel;entitiesForRendering()Ljava/lang/Iterable;"))
|
@Redirect(method = "renderLevel", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/multiplayer/ClientLevel;entitiesForRendering()Ljava/lang/Iterable;"))
|
||||||
private Iterable<Entity> filterEntities(ClientLevel world) {
|
private Iterable<Entity> filterEntities(ClientLevel world) {
|
||||||
Iterable<Entity> entities = world.entitiesForRendering();
|
Iterable<Entity> entities = world.entitiesForRendering();
|
||||||
if (Backend.getInstance()
|
if (Backend.isOn()) {
|
||||||
.canUseInstancing()) {
|
|
||||||
|
|
||||||
ArrayList<Entity> filtered = Lists.newArrayList(entities);
|
ArrayList<Entity> filtered = Lists.newArrayList(entities);
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ public class ChunkRebuildHooksMixin {
|
||||||
@Inject(method = "handleBlockEntity", at = @At("HEAD"), cancellable = true)
|
@Inject(method = "handleBlockEntity", at = @At("HEAD"), cancellable = true)
|
||||||
private <E extends BlockEntity> void addAndFilterBEs(ChunkRenderDispatcher.CompiledChunk compiledChunk, Set<BlockEntity> set, E be, CallbackInfo ci) {
|
private <E extends BlockEntity> void addAndFilterBEs(ChunkRenderDispatcher.CompiledChunk compiledChunk, Set<BlockEntity> set, E be, CallbackInfo ci) {
|
||||||
|
|
||||||
if (Backend.getInstance().canUseInstancing() && Backend.isFlywheelWorld(be.getLevel())) {
|
if (Backend.isOn() && Backend.isFlywheelWorld(be.getLevel())) {
|
||||||
|
|
||||||
InstancedRenderRegistry registry = InstancedRenderRegistry.getInstance();
|
InstancedRenderRegistry registry = InstancedRenderRegistry.getInstance();
|
||||||
if (registry.canInstance(be.getType()))
|
if (registry.canInstance(be.getType()))
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package com.jozufozu.flywheel.mixin;
|
package com.jozufozu.flywheel.mixin;
|
||||||
|
|
||||||
import org.lwjgl.opengl.GL20;
|
|
||||||
import org.spongepowered.asm.mixin.Final;
|
import org.spongepowered.asm.mixin.Final;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
|
@ -9,7 +8,6 @@ import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.Backend;
|
import com.jozufozu.flywheel.backend.Backend;
|
||||||
import com.jozufozu.flywheel.backend.OptifineHandler;
|
|
||||||
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
|
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
|
||||||
import com.jozufozu.flywheel.core.crumbling.CrumblingRenderer;
|
import com.jozufozu.flywheel.core.crumbling.CrumblingRenderer;
|
||||||
import com.jozufozu.flywheel.event.BeginFrameEvent;
|
import com.jozufozu.flywheel.event.BeginFrameEvent;
|
||||||
|
@ -74,8 +72,7 @@ public class RenderHooksMixin {
|
||||||
@Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/LevelRenderer;checkPoseStack(Lcom/mojang/blaze3d/vertex/PoseStack;)V", ordinal = 2 // after the game renders the breaking overlay normally
|
@Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/LevelRenderer;checkPoseStack(Lcom/mojang/blaze3d/vertex/PoseStack;)V", ordinal = 2 // after the game renders the breaking overlay normally
|
||||||
), method = "renderLevel")
|
), method = "renderLevel")
|
||||||
private void renderBlockBreaking(PoseStack stack, float p_228426_2_, long p_228426_3_, boolean p_228426_5_, Camera info, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f p_228426_9_, CallbackInfo ci) {
|
private void renderBlockBreaking(PoseStack stack, float p_228426_2_, long p_228426_3_, boolean p_228426_5_, Camera info, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f p_228426_9_, CallbackInfo ci) {
|
||||||
if (!Backend.getInstance()
|
if (!Backend.isOn()) return;
|
||||||
.available()) return;
|
|
||||||
|
|
||||||
Vec3 cameraPos = info.getPosition();
|
Vec3 cameraPos = info.getPosition();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue