Most of Fabric

- Organize almost all remaining code into one of four modules
- Fix some incorrect inter-module dependencies
- Get Fabric into a working state
  - The config, client commands, and model builders are still missing and registry freezing happens too late
This commit is contained in:
PepperCode1 2024-04-22 15:36:45 -07:00 committed by Jozufozu
parent 77c2181318
commit 543f759fee
74 changed files with 1030 additions and 623 deletions

View file

@ -3,49 +3,16 @@ package com.jozufozu.flywheel;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.jozufozu.flywheel.backend.Backends;
import com.jozufozu.flywheel.backend.ShaderIndices;
import com.jozufozu.flywheel.impl.BackendManagerImpl;
import com.jozufozu.flywheel.impl.registry.IdRegistryImpl;
import com.jozufozu.flywheel.impl.registry.RegistryImpl;
import com.jozufozu.flywheel.lib.instance.InstanceTypes;
import com.jozufozu.flywheel.lib.material.CutoutShaders;
import com.jozufozu.flywheel.lib.material.FogShaders;
import com.jozufozu.flywheel.lib.material.StandardMaterialShaders;
import com.jozufozu.flywheel.lib.util.ShadersModHandler;
import com.jozufozu.flywheel.vanilla.VanillaVisuals;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
public class Flywheel { public final class Flywheel {
public static final String ID = "flywheel"; public static final String ID = "flywheel";
public static final Logger LOGGER = LoggerFactory.getLogger(ID); public static final Logger LOGGER = LoggerFactory.getLogger(ID);
private Flywheel() {
}
public static ResourceLocation rl(String path) { public static ResourceLocation rl(String path) {
return new ResourceLocation(ID, path); return new ResourceLocation(ID, path);
} }
public static void earlyInit() {
BackendManagerImpl.init();
ShadersModHandler.init();
Backends.init();
}
public static void init() {
InstanceTypes.init();
CutoutShaders.init();
FogShaders.init();
StandardMaterialShaders.init();
ShaderIndices.init();
VanillaVisuals.init();
}
public static void freeze() {
RegistryImpl.freezeAll();
IdRegistryImpl.freezeAll();
}
} }

View file

@ -1,14 +1,14 @@
package com.jozufozu.flywheel.api.backend; package com.jozufozu.flywheel.api.backend;
import com.jozufozu.flywheel.api.BackendImplemented; import com.jozufozu.flywheel.api.BackendImplemented;
import com.jozufozu.flywheel.api.internal.InternalFlywheelApi; import com.jozufozu.flywheel.api.internal.FlwApiLink;
import com.jozufozu.flywheel.api.registry.IdRegistry; import com.jozufozu.flywheel.api.registry.IdRegistry;
import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.LevelAccessor;
@BackendImplemented @BackendImplemented
public interface Backend { public interface Backend {
static IdRegistry<Backend> REGISTRY = InternalFlywheelApi.INSTANCE.createIdRegistry(); static IdRegistry<Backend> REGISTRY = FlwApiLink.INSTANCE.createIdRegistry();
/** /**
* Create a new engine instance. * Create a new engine instance.

View file

@ -1,6 +1,6 @@
package com.jozufozu.flywheel.api.backend; package com.jozufozu.flywheel.api.backend;
import com.jozufozu.flywheel.api.internal.InternalFlywheelApi; import com.jozufozu.flywheel.api.internal.FlwApiLink;
public final class BackendManager { public final class BackendManager {
private BackendManager() { private BackendManager() {
@ -10,18 +10,18 @@ public final class BackendManager {
* Get the current backend. * Get the current backend.
*/ */
public static Backend getBackend() { public static Backend getBackend() {
return InternalFlywheelApi.INSTANCE.getBackend(); return FlwApiLink.INSTANCE.getBackend();
} }
public static boolean isBackendOn() { public static boolean isBackendOn() {
return InternalFlywheelApi.INSTANCE.isBackendOn(); return FlwApiLink.INSTANCE.isBackendOn();
} }
public static Backend getOffBackend() { public static Backend getOffBackend() {
return InternalFlywheelApi.INSTANCE.getOffBackend(); return FlwApiLink.INSTANCE.getOffBackend();
} }
public static Backend getDefaultBackend() { public static Backend getDefaultBackend() {
return InternalFlywheelApi.INSTANCE.getDefaultBackend(); return FlwApiLink.INSTANCE.getDefaultBackend();
} }
} }

View file

@ -1,6 +1,6 @@
package com.jozufozu.flywheel.api.instance; package com.jozufozu.flywheel.api.instance;
import com.jozufozu.flywheel.api.internal.InternalFlywheelApi; import com.jozufozu.flywheel.api.internal.FlwApiLink;
import com.jozufozu.flywheel.api.layout.Layout; import com.jozufozu.flywheel.api.layout.Layout;
import com.jozufozu.flywheel.api.registry.Registry; import com.jozufozu.flywheel.api.registry.Registry;
@ -12,7 +12,7 @@ import net.minecraft.resources.ResourceLocation;
* @param <I> The java representation of the instance. * @param <I> The java representation of the instance.
*/ */
public interface InstanceType<I extends Instance> { public interface InstanceType<I extends Instance> {
static Registry<InstanceType<?>> REGISTRY = InternalFlywheelApi.INSTANCE.createRegistry(); static Registry<InstanceType<?>> REGISTRY = FlwApiLink.INSTANCE.createRegistry();
/** /**
* @param handle A handle that allows you to mark the instance as dirty or deleted. * @param handle A handle that allows you to mark the instance as dirty or deleted.

View file

@ -40,12 +40,12 @@ public final class DependencyInjection {
return apiClass.cast(implInstance); return apiClass.cast(implInstance);
} }
private static InternalFlywheelApi load() { private static FlwApiLink load() {
Class<InternalFlywheelApi> apiClass = InternalFlywheelApi.class; Class<FlwApiLink> apiClass = FlwApiLink.class;
Class<?> implClass; Class<?> implClass;
try { try {
implClass = Class.forName("com.jozufozu.flywheel.impl.InternalFlywheelImpl"); implClass = Class.forName("com.jozufozu.flywheel.impl.FlwApiLinkImpl");
} catch (ReflectiveOperationException e) { } catch (ReflectiveOperationException e) {
throw new RuntimeException("Could not find implementation", e); throw new RuntimeException("Could not find implementation", e);
} }

View file

@ -10,8 +10,6 @@ import com.jozufozu.flywheel.api.vertex.VertexViewProvider;
import com.jozufozu.flywheel.api.visualization.BlockEntityVisualizer; import com.jozufozu.flywheel.api.visualization.BlockEntityVisualizer;
import com.jozufozu.flywheel.api.visualization.EntityVisualizer; import com.jozufozu.flywheel.api.visualization.EntityVisualizer;
import com.jozufozu.flywheel.api.visualization.VisualizationManager; import com.jozufozu.flywheel.api.visualization.VisualizationManager;
import com.jozufozu.flywheel.lib.transform.PoseTransformStack;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexFormat; import com.mojang.blaze3d.vertex.VertexFormat;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
@ -20,8 +18,8 @@ import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.entity.BlockEntityType;
public interface InternalFlywheelApi { public interface FlwApiLink {
InternalFlywheelApi INSTANCE = DependencyInjection.load(InternalFlywheelApi.class, "com.jozufozu.flywheel.impl.InternalFlywheelImpl"); FlwApiLink INSTANCE = DependencyInjection.load(FlwApiLink.class, "com.jozufozu.flywheel.impl.FlwApiLinkImpl");
<T> Registry<T> createRegistry(); <T> Registry<T> createRegistry();
@ -57,6 +55,4 @@ public interface InternalFlywheelApi {
<T extends BlockEntity> void setVisualizer(BlockEntityType<T> type, BlockEntityVisualizer<? super T> visualizer); <T extends BlockEntity> void setVisualizer(BlockEntityType<T> type, BlockEntityVisualizer<? super T> visualizer);
<T extends Entity> void setVisualizer(EntityType<T> type, EntityVisualizer<? super T> visualizer); <T extends Entity> void setVisualizer(EntityType<T> type, EntityVisualizer<? super T> visualizer);
PoseTransformStack getPoseTransformStackOf(PoseStack stack);
} }

View file

@ -3,7 +3,7 @@ package com.jozufozu.flywheel.api.layout;
import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Range; import org.jetbrains.annotations.Range;
import com.jozufozu.flywheel.api.internal.InternalFlywheelApi; import com.jozufozu.flywheel.api.internal.FlwApiLink;
@ApiStatus.NonExtendable @ApiStatus.NonExtendable
public interface LayoutBuilder { public interface LayoutBuilder {
@ -26,6 +26,6 @@ public interface LayoutBuilder {
Layout build(); Layout build();
static LayoutBuilder create() { static LayoutBuilder create() {
return InternalFlywheelApi.INSTANCE.createLayoutBuilder(); return FlwApiLink.INSTANCE.createLayoutBuilder();
} }
} }

View file

@ -1,12 +1,12 @@
package com.jozufozu.flywheel.api.material; package com.jozufozu.flywheel.api.material;
import com.jozufozu.flywheel.api.internal.InternalFlywheelApi; import com.jozufozu.flywheel.api.internal.FlwApiLink;
import com.jozufozu.flywheel.api.registry.Registry; import com.jozufozu.flywheel.api.registry.Registry;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
public interface CutoutShader { public interface CutoutShader {
static Registry<CutoutShader> REGISTRY = InternalFlywheelApi.INSTANCE.createRegistry(); static Registry<CutoutShader> REGISTRY = FlwApiLink.INSTANCE.createRegistry();
ResourceLocation source(); ResourceLocation source();
} }

View file

@ -1,12 +1,12 @@
package com.jozufozu.flywheel.api.material; package com.jozufozu.flywheel.api.material;
import com.jozufozu.flywheel.api.internal.InternalFlywheelApi; import com.jozufozu.flywheel.api.internal.FlwApiLink;
import com.jozufozu.flywheel.api.registry.Registry; import com.jozufozu.flywheel.api.registry.Registry;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
public interface FogShader { public interface FogShader {
static Registry<FogShader> REGISTRY = InternalFlywheelApi.INSTANCE.createRegistry(); static Registry<FogShader> REGISTRY = FlwApiLink.INSTANCE.createRegistry();
ResourceLocation source(); ResourceLocation source();
} }

View file

@ -1,12 +1,12 @@
package com.jozufozu.flywheel.api.material; package com.jozufozu.flywheel.api.material;
import com.jozufozu.flywheel.api.internal.InternalFlywheelApi; import com.jozufozu.flywheel.api.internal.FlwApiLink;
import com.jozufozu.flywheel.api.registry.Registry; import com.jozufozu.flywheel.api.registry.Registry;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
public interface MaterialShaders { public interface MaterialShaders {
static Registry<MaterialShaders> REGISTRY = InternalFlywheelApi.INSTANCE.createRegistry(); static Registry<MaterialShaders> REGISTRY = FlwApiLink.INSTANCE.createRegistry();
ResourceLocation vertexShader(); ResourceLocation vertexShader();

View file

@ -1,6 +1,6 @@
package com.jozufozu.flywheel.api.vertex; package com.jozufozu.flywheel.api.vertex;
import com.jozufozu.flywheel.api.internal.InternalFlywheelApi; import com.jozufozu.flywheel.api.internal.FlwApiLink;
import com.mojang.blaze3d.vertex.VertexFormat; import com.mojang.blaze3d.vertex.VertexFormat;
public final class VertexViewProviderRegistry { public final class VertexViewProviderRegistry {
@ -8,10 +8,10 @@ public final class VertexViewProviderRegistry {
} }
public static VertexViewProvider getProvider(VertexFormat format) { public static VertexViewProvider getProvider(VertexFormat format) {
return InternalFlywheelApi.INSTANCE.getVertexViewProvider(format); return FlwApiLink.INSTANCE.getVertexViewProvider(format);
} }
public static void setProvider(VertexFormat format, VertexViewProvider provider) { public static void setProvider(VertexFormat format, VertexViewProvider provider) {
InternalFlywheelApi.INSTANCE.setVertexViewProvider(format, provider); FlwApiLink.INSTANCE.setVertexViewProvider(format, provider);
} }
} }

View file

@ -3,7 +3,7 @@ package com.jozufozu.flywheel.api.visualization;
import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import com.jozufozu.flywheel.api.internal.InternalFlywheelApi; import com.jozufozu.flywheel.api.internal.FlwApiLink;
import com.jozufozu.flywheel.api.visual.Effect; import com.jozufozu.flywheel.api.visual.Effect;
import com.jozufozu.flywheel.api.visual.Visual; import com.jozufozu.flywheel.api.visual.Visual;
@ -16,16 +16,16 @@ import net.minecraft.world.level.block.entity.BlockEntity;
@ApiStatus.NonExtendable @ApiStatus.NonExtendable
public interface VisualizationManager { public interface VisualizationManager {
static boolean supportsVisualization(@Nullable LevelAccessor level) { static boolean supportsVisualization(@Nullable LevelAccessor level) {
return InternalFlywheelApi.INSTANCE.supportsVisualization(level); return FlwApiLink.INSTANCE.supportsVisualization(level);
} }
@Nullable @Nullable
static VisualizationManager get(@Nullable LevelAccessor level) { static VisualizationManager get(@Nullable LevelAccessor level) {
return InternalFlywheelApi.INSTANCE.getVisualizationManager(level); return FlwApiLink.INSTANCE.getVisualizationManager(level);
} }
static VisualizationManager getOrThrow(@Nullable LevelAccessor level) { static VisualizationManager getOrThrow(@Nullable LevelAccessor level) {
return InternalFlywheelApi.INSTANCE.getVisualizationManagerOrThrow(level); return FlwApiLink.INSTANCE.getVisualizationManagerOrThrow(level);
} }
/** /**

View file

@ -2,7 +2,7 @@ package com.jozufozu.flywheel.api.visualization;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import com.jozufozu.flywheel.api.internal.InternalFlywheelApi; import com.jozufozu.flywheel.api.internal.FlwApiLink;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.EntityType;
@ -24,7 +24,7 @@ public final class VisualizerRegistry {
*/ */
@Nullable @Nullable
public static <T extends BlockEntity> BlockEntityVisualizer<? super T> getVisualizer(BlockEntityType<T> type) { public static <T extends BlockEntity> BlockEntityVisualizer<? super T> getVisualizer(BlockEntityType<T> type) {
return InternalFlywheelApi.INSTANCE.getVisualizer(type); return FlwApiLink.INSTANCE.getVisualizer(type);
} }
/** /**
@ -35,7 +35,7 @@ public final class VisualizerRegistry {
*/ */
@Nullable @Nullable
public static <T extends Entity> EntityVisualizer<? super T> getVisualizer(EntityType<T> type) { public static <T extends Entity> EntityVisualizer<? super T> getVisualizer(EntityType<T> type) {
return InternalFlywheelApi.INSTANCE.getVisualizer(type); return FlwApiLink.INSTANCE.getVisualizer(type);
} }
/** /**
@ -45,7 +45,7 @@ public final class VisualizerRegistry {
* @param <T> The type of the block entity. * @param <T> The type of the block entity.
*/ */
public static <T extends BlockEntity> void setVisualizer(BlockEntityType<T> type, BlockEntityVisualizer<? super T> visualizer) { public static <T extends BlockEntity> void setVisualizer(BlockEntityType<T> type, BlockEntityVisualizer<? super T> visualizer) {
InternalFlywheelApi.INSTANCE.setVisualizer(type, visualizer); FlwApiLink.INSTANCE.setVisualizer(type, visualizer);
} }
/** /**
@ -55,6 +55,6 @@ public final class VisualizerRegistry {
* @param <T> The type of the entity. * @param <T> The type of the entity.
*/ */
public static <T extends Entity> void setVisualizer(EntityType<T> type, EntityVisualizer<? super T> visualizer) { public static <T extends Entity> void setVisualizer(EntityType<T> type, EntityVisualizer<? super T> visualizer) {
InternalFlywheelApi.INSTANCE.setVisualizer(type, visualizer); FlwApiLink.INSTANCE.setVisualizer(type, visualizer);
} }
} }

View file

@ -0,0 +1,13 @@
package com.jozufozu.flywheel.backend;
import com.jozufozu.flywheel.api.internal.DependencyInjection;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.state.BlockState;
public interface FlwBackendXplat {
FlwBackendXplat INSTANCE = DependencyInjection.load(FlwBackendXplat.class, "com.jozufozu.flywheel.backend.FlwBackendXplatImpl");
int getLightEmission(BlockState state, BlockGetter level, BlockPos pos);
}

View file

@ -20,7 +20,6 @@ import com.jozufozu.flywheel.backend.glsl.generate.GlslExpr;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.resources.ResourceManager; import net.minecraft.server.packs.resources.ResourceManager;
import net.minecraft.server.packs.resources.ResourceManagerReloadListener;
public final class FlwPrograms { public final class FlwPrograms {
public static final Logger LOGGER = LoggerFactory.getLogger(Flywheel.ID + "/shaders"); public static final Logger LOGGER = LoggerFactory.getLogger(Flywheel.ID + "/shaders");
@ -31,7 +30,7 @@ public final class FlwPrograms {
private FlwPrograms() { private FlwPrograms() {
} }
private static void reload(ResourceManager resourceManager) { static void reload(ResourceManager resourceManager) {
// Reset the programs in case the ubershader load fails. // Reset the programs in case the ubershader load fails.
InstancingPrograms.setInstance(null); InstancingPrograms.setInstance(null);
IndirectPrograms.setInstance(null); IndirectPrograms.setInstance(null);
@ -119,16 +118,4 @@ public final class FlwPrograms {
.switchOn(GlslExpr.variable("_flw_uberCutoutIndex")) .switchOn(GlslExpr.variable("_flw_uberCutoutIndex"))
.build(loader); .build(loader);
} }
public static class ResourceReloadListener implements ResourceManagerReloadListener {
public static final ResourceReloadListener INSTANCE = new ResourceReloadListener();
private ResourceReloadListener() {
}
@Override
public void onResourceManagerReload(ResourceManager manager) {
FlwPrograms.reload(manager);
}
}
} }

View file

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.impl.layout; package com.jozufozu.flywheel.backend.compile;
import com.jozufozu.flywheel.api.layout.ArrayElementType; import com.jozufozu.flywheel.api.layout.ArrayElementType;
import com.jozufozu.flywheel.api.layout.ElementType; import com.jozufozu.flywheel.api.layout.ElementType;

View file

@ -19,10 +19,10 @@ import com.jozufozu.flywheel.api.layout.ScalarElementType;
import com.jozufozu.flywheel.api.layout.UnsignedIntegerRepr; import com.jozufozu.flywheel.api.layout.UnsignedIntegerRepr;
import com.jozufozu.flywheel.api.layout.ValueRepr; import com.jozufozu.flywheel.api.layout.ValueRepr;
import com.jozufozu.flywheel.api.layout.VectorElementType; import com.jozufozu.flywheel.api.layout.VectorElementType;
import com.jozufozu.flywheel.backend.compile.LayoutInterpreter;
import com.jozufozu.flywheel.backend.glsl.SourceComponent; import com.jozufozu.flywheel.backend.glsl.SourceComponent;
import com.jozufozu.flywheel.backend.glsl.generate.GlslBuilder; import com.jozufozu.flywheel.backend.glsl.generate.GlslBuilder;
import com.jozufozu.flywheel.backend.glsl.generate.GlslExpr; import com.jozufozu.flywheel.backend.glsl.generate.GlslExpr;
import com.jozufozu.flywheel.impl.layout.LayoutInterpreter;
public abstract class InstanceAssemblerComponent implements SourceComponent { public abstract class InstanceAssemblerComponent implements SourceComponent {
protected static final String STRUCT_NAME = "FlwInstance"; protected static final String STRUCT_NAME = "FlwInstance";

View file

@ -6,9 +6,9 @@ import java.util.Collections;
import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.api.instance.InstanceType; import com.jozufozu.flywheel.api.instance.InstanceType;
import com.jozufozu.flywheel.api.layout.Layout; import com.jozufozu.flywheel.api.layout.Layout;
import com.jozufozu.flywheel.backend.compile.LayoutInterpreter;
import com.jozufozu.flywheel.backend.glsl.SourceComponent; import com.jozufozu.flywheel.backend.glsl.SourceComponent;
import com.jozufozu.flywheel.backend.glsl.generate.GlslBuilder; import com.jozufozu.flywheel.backend.glsl.generate.GlslBuilder;
import com.jozufozu.flywheel.impl.layout.LayoutInterpreter;
public class InstanceStructComponent implements SourceComponent { public class InstanceStructComponent implements SourceComponent {
private static final String STRUCT_NAME = "FlwInstance"; private static final String STRUCT_NAME = "FlwInstance";

View file

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.config; package com.jozufozu.flywheel.backend.engine.uniform;
public enum DebugMode { public enum DebugMode {
OFF, OFF,

View file

@ -7,7 +7,6 @@ import org.joml.Vector3f;
import com.jozufozu.flywheel.api.event.RenderContext; import com.jozufozu.flywheel.api.event.RenderContext;
import com.jozufozu.flywheel.api.visualization.VisualizationManager; import com.jozufozu.flywheel.api.visualization.VisualizationManager;
import com.jozufozu.flywheel.backend.mixin.LevelRendererAccessor; import com.jozufozu.flywheel.backend.mixin.LevelRendererAccessor;
import com.jozufozu.flywheel.config.DebugMode;
import com.jozufozu.flywheel.lib.math.MatrixMath; import com.jozufozu.flywheel.lib.math.MatrixMath;
import net.minecraft.client.Camera; import net.minecraft.client.Camera;

View file

@ -3,8 +3,8 @@ package com.jozufozu.flywheel.backend.engine.uniform;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import com.jozufozu.flywheel.api.event.RenderContext; import com.jozufozu.flywheel.api.event.RenderContext;
import com.jozufozu.flywheel.backend.FlwBackendXplat;
import com.jozufozu.flywheel.backend.mixin.AbstractClientPlayerAccessor; import com.jozufozu.flywheel.backend.mixin.AbstractClientPlayerAccessor;
import com.jozufozu.flywheel.platform.ClientPlatform;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.multiplayer.ClientLevel;
@ -94,7 +94,7 @@ public final class PlayerUniforms extends UniformWriter {
Item handItem = player.getItemInHand(hand).getItem(); Item handItem = player.getItemInHand(hand).getItem();
if (handItem instanceof BlockItem blockItem) { if (handItem instanceof BlockItem blockItem) {
Block block = blockItem.getBlock(); Block block = blockItem.getBlock();
int blockLight = ClientPlatform.INSTANCE int blockLight = FlwBackendXplat.INSTANCE
.getLightEmission(block.defaultBlockState(), player.clientLevel, player.blockPosition()); .getLightEmission(block.defaultBlockState(), player.clientLevel, player.blockPosition());
if (heldLight < blockLight) { if (heldLight < blockLight) {
heldLight = blockLight; heldLight = blockLight;

View file

@ -1,17 +0,0 @@
package com.jozufozu.flywheel.config;
import com.jozufozu.flywheel.api.backend.Backend;
import com.jozufozu.flywheel.platform.ClientPlatform;
public interface FlwConfig {
FlwConfig INSTANCE = ClientPlatform.INSTANCE.getConfigInstance();
static FlwConfig get() {
return INSTANCE;
}
Backend backend();
boolean limitUpdates();
int workerThreads();
}

View file

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.config; package com.jozufozu.flywheel.impl;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;

View file

@ -6,7 +6,6 @@ import org.slf4j.Logger;
import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.api.backend.Backend; import com.jozufozu.flywheel.api.backend.Backend;
import com.jozufozu.flywheel.backend.Backends; import com.jozufozu.flywheel.backend.Backends;
import com.jozufozu.flywheel.config.FlwConfig;
import com.jozufozu.flywheel.impl.visualization.VisualizationManagerImpl; import com.jozufozu.flywheel.impl.visualization.VisualizationManagerImpl;
import com.jozufozu.flywheel.lib.backend.SimpleBackend; import com.jozufozu.flywheel.lib.backend.SimpleBackend;
import com.mojang.logging.LogUtils; import com.mojang.logging.LogUtils;
@ -46,7 +45,7 @@ public final class BackendManagerImpl {
} }
private static void chooseBackend() { private static void chooseBackend() {
var preferred = FlwConfig.get().backend(); var preferred = FlwConfig.INSTANCE.backend();
var actual = preferred.findFallback(); var actual = preferred.findFallback();
if (preferred != actual) { if (preferred != actual) {

View file

@ -3,7 +3,7 @@ package com.jozufozu.flywheel.impl;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import com.jozufozu.flywheel.api.backend.Backend; import com.jozufozu.flywheel.api.backend.Backend;
import com.jozufozu.flywheel.api.internal.InternalFlywheelApi; import com.jozufozu.flywheel.api.internal.FlwApiLink;
import com.jozufozu.flywheel.api.layout.LayoutBuilder; import com.jozufozu.flywheel.api.layout.LayoutBuilder;
import com.jozufozu.flywheel.api.registry.IdRegistry; import com.jozufozu.flywheel.api.registry.IdRegistry;
import com.jozufozu.flywheel.api.registry.Registry; import com.jozufozu.flywheel.api.registry.Registry;
@ -11,15 +11,12 @@ import com.jozufozu.flywheel.api.vertex.VertexViewProvider;
import com.jozufozu.flywheel.api.visualization.BlockEntityVisualizer; import com.jozufozu.flywheel.api.visualization.BlockEntityVisualizer;
import com.jozufozu.flywheel.api.visualization.EntityVisualizer; import com.jozufozu.flywheel.api.visualization.EntityVisualizer;
import com.jozufozu.flywheel.api.visualization.VisualizationManager; import com.jozufozu.flywheel.api.visualization.VisualizationManager;
import com.jozufozu.flywheel.impl.extension.PoseStackExtension;
import com.jozufozu.flywheel.impl.layout.LayoutBuilderImpl; import com.jozufozu.flywheel.impl.layout.LayoutBuilderImpl;
import com.jozufozu.flywheel.impl.registry.IdRegistryImpl; import com.jozufozu.flywheel.impl.registry.IdRegistryImpl;
import com.jozufozu.flywheel.impl.registry.RegistryImpl; import com.jozufozu.flywheel.impl.registry.RegistryImpl;
import com.jozufozu.flywheel.impl.vertex.VertexViewProviderRegistryImpl; import com.jozufozu.flywheel.impl.vertex.VertexViewProviderRegistryImpl;
import com.jozufozu.flywheel.impl.visualization.VisualizationManagerImpl; import com.jozufozu.flywheel.impl.visualization.VisualizationManagerImpl;
import com.jozufozu.flywheel.impl.visualization.VisualizerRegistryImpl; import com.jozufozu.flywheel.impl.visualization.VisualizerRegistryImpl;
import com.jozufozu.flywheel.lib.transform.PoseTransformStack;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexFormat; import com.mojang.blaze3d.vertex.VertexFormat;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
@ -28,7 +25,7 @@ import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.entity.BlockEntityType;
public final class InternalFlywheelImpl implements InternalFlywheelApi { public class FlwApiLinkImpl implements FlwApiLink {
@Override @Override
public <T> Registry<T> createRegistry() { public <T> Registry<T> createRegistry() {
return new RegistryImpl<>(); return new RegistryImpl<>();
@ -111,9 +108,4 @@ public final class InternalFlywheelImpl implements InternalFlywheelApi {
public <T extends Entity> void setVisualizer(EntityType<T> type, EntityVisualizer<? super T> visualizer) { public <T extends Entity> void setVisualizer(EntityType<T> type, EntityVisualizer<? super T> visualizer) {
VisualizerRegistryImpl.setVisualizer(type, visualizer); VisualizerRegistryImpl.setVisualizer(type, visualizer);
} }
@Override
public PoseTransformStack getPoseTransformStackOf(PoseStack stack) {
return ((PoseStackExtension) stack).flywheel$transformStack();
}
} }

View file

@ -0,0 +1,13 @@
package com.jozufozu.flywheel.impl;
import com.jozufozu.flywheel.api.backend.Backend;
public interface FlwConfig {
FlwConfig INSTANCE = FlwImplXplat.INSTANCE.getConfig();
Backend backend();
boolean limitUpdates();
int workerThreads();
}

View file

@ -0,0 +1,37 @@
package com.jozufozu.flywheel.impl;
import java.util.List;
import com.jozufozu.flywheel.api.visualization.VisualizationManager;
import com.jozufozu.flywheel.lib.memory.FlwMemoryTracker;
import com.jozufozu.flywheel.lib.util.StringUtil;
import net.minecraft.client.Minecraft;
import net.minecraft.core.Vec3i;
public final class FlwDebugInfo {
private FlwDebugInfo() {
}
public static void addDebugInfo(Minecraft minecraft, List<String> systemInfo) {
if (minecraft.showOnlyReducedInfo()) {
return;
}
systemInfo.add("");
systemInfo.add("Flywheel: " + FlwImplXplat.INSTANCE.getVersionStr());
systemInfo.add("Backend: " + BackendManagerImpl.getBackendString());
systemInfo.add("Update limiting: " + (FlwConfig.INSTANCE.limitUpdates() ? "on" : "off"));
VisualizationManager manager = VisualizationManager.get(minecraft.level);
if (manager != null) {
systemInfo.add("B: " + manager.getBlockEntities().getVisualCount()
+ ", E: " + manager.getEntities().getVisualCount()
+ ", F: " + manager.getEffects().getVisualCount());
Vec3i renderOrigin = manager.getRenderOrigin();
systemInfo.add("Origin: " + renderOrigin.getX() + ", " + renderOrigin.getY() + ", " + renderOrigin.getZ());
}
systemInfo.add("Memory Usage: CPU: " + StringUtil.formatBytes(FlwMemoryTracker.getCPUMemory()) + ", GPU: " + StringUtil.formatBytes(FlwMemoryTracker.getGPUMemory()));
}
}

View file

@ -0,0 +1,23 @@
package com.jozufozu.flywheel.impl;
import org.jetbrains.annotations.Nullable;
import com.jozufozu.flywheel.api.event.RenderContext;
import com.jozufozu.flywheel.api.event.RenderStage;
import com.jozufozu.flywheel.api.internal.DependencyInjection;
import net.minecraft.client.multiplayer.ClientLevel;
public interface FlwImplXplat {
FlwImplXplat INSTANCE = DependencyInjection.load(FlwImplXplat.class, "com.jozufozu.flywheel.impl.FlwImplXplatImpl");
void dispatchBeginFrameEvent(RenderContext context);
void dispatchReloadLevelRendererEvent(@Nullable ClientLevel level);
void dispatchRenderStageEvent(RenderContext context, RenderStage stage);
String getVersionStr();
FlwConfig getConfig();
}

View file

@ -0,0 +1,13 @@
package com.jozufozu.flywheel.impl;
import com.jozufozu.flywheel.impl.extension.PoseStackExtension;
import com.jozufozu.flywheel.lib.internal.FlwLibLink;
import com.jozufozu.flywheel.lib.transform.PoseTransformStack;
import com.mojang.blaze3d.vertex.PoseStack;
public class FlwLibLinkImpl implements FlwLibLink {
@Override
public PoseTransformStack getPoseTransformStackOf(PoseStack stack) {
return ((PoseStackExtension) stack).flywheel$transformStack();
}
}

View file

@ -0,0 +1,41 @@
package com.jozufozu.flywheel.impl;
import com.jozufozu.flywheel.backend.Backends;
import com.jozufozu.flywheel.backend.ShaderIndices;
import com.jozufozu.flywheel.impl.registry.IdRegistryImpl;
import com.jozufozu.flywheel.impl.registry.RegistryImpl;
import com.jozufozu.flywheel.lib.instance.InstanceTypes;
import com.jozufozu.flywheel.lib.material.CutoutShaders;
import com.jozufozu.flywheel.lib.material.FogShaders;
import com.jozufozu.flywheel.lib.material.StandardMaterialShaders;
import com.jozufozu.flywheel.lib.util.ShadersModHandler;
import com.jozufozu.flywheel.vanilla.VanillaVisuals;
public final class FlywheelInit {
private FlywheelInit() {
}
public static void init() {
// impl
BackendManagerImpl.init();
// lib
ShadersModHandler.init();
InstanceTypes.init();
CutoutShaders.init();
FogShaders.init();
StandardMaterialShaders.init();
// backend
ShaderIndices.init();
Backends.init();
// vanilla
VanillaVisuals.init();
}
public static void freezeRegistries() {
RegistryImpl.freezeAll();
IdRegistryImpl.freezeAll();
}
}

View file

@ -11,13 +11,14 @@ import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.At.Shift; import org.spongepowered.asm.mixin.injection.At.Shift;
import org.spongepowered.asm.mixin.injection.Group;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import com.jozufozu.flywheel.api.event.RenderStage; import com.jozufozu.flywheel.api.event.RenderStage;
import com.jozufozu.flywheel.impl.FlwImplXplat;
import com.jozufozu.flywheel.impl.event.RenderContextImpl; import com.jozufozu.flywheel.impl.event.RenderContextImpl;
import com.jozufozu.flywheel.impl.visualization.VisualizationManagerImpl; import com.jozufozu.flywheel.impl.visualization.VisualizationManagerImpl;
import com.jozufozu.flywheel.platform.ClientPlatform;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap; import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
@ -32,6 +33,7 @@ import net.minecraft.server.level.BlockDestructionProgress;
@Mixin(value = LevelRenderer.class, priority = 1001) // Higher priority to go after Sodium @Mixin(value = LevelRenderer.class, priority = 1001) // Higher priority to go after Sodium
abstract class LevelRendererMixin { abstract class LevelRendererMixin {
@Shadow @Shadow
@Nullable
private ClientLevel level; private ClientLevel level;
@Shadow @Shadow
@ -51,7 +53,7 @@ abstract class LevelRendererMixin {
private void flywheel$beginRender(PoseStack poseStack, float partialTick, long finishNanoTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f projectionMatrix, CallbackInfo ci) { private void flywheel$beginRender(PoseStack poseStack, float partialTick, long finishNanoTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f projectionMatrix, CallbackInfo ci) {
flywheel$renderContext = RenderContextImpl.create((LevelRenderer) (Object) this, level, renderBuffers, poseStack, projectionMatrix, camera, partialTick); flywheel$renderContext = RenderContextImpl.create((LevelRenderer) (Object) this, level, renderBuffers, poseStack, projectionMatrix, camera, partialTick);
ClientPlatform.INSTANCE.dispatchBeginFrame(flywheel$renderContext); FlwImplXplat.INSTANCE.dispatchBeginFrameEvent(flywheel$renderContext);
} }
@Inject(method = "renderLevel", at = @At("RETURN")) @Inject(method = "renderLevel", at = @At("RETURN"))
@ -61,7 +63,7 @@ abstract class LevelRendererMixin {
@Inject(method = "allChanged", at = @At("RETURN")) @Inject(method = "allChanged", at = @At("RETURN"))
private void flywheel$refresh(CallbackInfo ci) { private void flywheel$refresh(CallbackInfo ci) {
ClientPlatform.INSTANCE.dispatchReloadLevelRenderer(level); FlwImplXplat.INSTANCE.dispatchReloadLevelRendererEvent(level);
} }
@Inject(method = "renderLevel", at = @At(value = "INVOKE_STRING", target = "Lnet/minecraft/util/profiling/ProfilerFiller;popPush(Ljava/lang/String;)V", args = "ldc=destroyProgress")) @Inject(method = "renderLevel", at = @At(value = "INVOKE_STRING", target = "Lnet/minecraft/util/profiling/ProfilerFiller;popPush(Ljava/lang/String;)V", args = "ldc=destroyProgress"))
@ -81,7 +83,7 @@ abstract class LevelRendererMixin {
@Unique @Unique
private void flywheel$dispatch(RenderStage stage) { private void flywheel$dispatch(RenderStage stage) {
if (flywheel$renderContext != null) { if (flywheel$renderContext != null) {
ClientPlatform.INSTANCE.dispatchRenderStage(flywheel$renderContext, stage); FlwImplXplat.INSTANCE.dispatchRenderStageEvent(flywheel$renderContext, stage);
} }
} }
@ -105,8 +107,15 @@ abstract class LevelRendererMixin {
flywheel$dispatch(RenderStage.AFTER_TRANSLUCENT_TERRAIN); flywheel$dispatch(RenderStage.AFTER_TRANSLUCENT_TERRAIN);
} }
@Group(name = "onStage$afterParticles", min = 1)
@Inject(method = "renderLevel", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/particle/ParticleEngine;render(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource$BufferSource;Lnet/minecraft/client/renderer/LightTexture;Lnet/minecraft/client/Camera;F)V", shift = Shift.AFTER))
private void flywheel$onStage$afterParticles$fabric(CallbackInfo ci) {
flywheel$dispatch(RenderStage.AFTER_PARTICLES);
}
@Group(name = "onStage$afterParticles")
@Inject(method = "renderLevel", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/particle/ParticleEngine;render(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource$BufferSource;Lnet/minecraft/client/renderer/LightTexture;Lnet/minecraft/client/Camera;FLnet/minecraft/client/renderer/culling/Frustum;)V", shift = Shift.AFTER)) @Inject(method = "renderLevel", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/particle/ParticleEngine;render(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource$BufferSource;Lnet/minecraft/client/renderer/LightTexture;Lnet/minecraft/client/Camera;FLnet/minecraft/client/renderer/culling/Frustum;)V", shift = Shift.AFTER))
private void flywheel$onStage$afterParticles(CallbackInfo ci) { private void flywheel$onStage$afterParticles$forge(CallbackInfo ci) {
flywheel$dispatch(RenderStage.AFTER_PARTICLES); flywheel$dispatch(RenderStage.AFTER_PARTICLES);
} }

View file

@ -4,7 +4,7 @@ import org.apache.commons.lang3.concurrent.AtomicSafeInitializer;
import org.apache.commons.lang3.concurrent.ConcurrentUtils; import org.apache.commons.lang3.concurrent.ConcurrentUtils;
import com.jozufozu.flywheel.api.task.TaskExecutor; import com.jozufozu.flywheel.api.task.TaskExecutor;
import com.jozufozu.flywheel.config.FlwConfig; import com.jozufozu.flywheel.impl.FlwConfig;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.util.Mth; import net.minecraft.util.Mth;
@ -39,7 +39,7 @@ public final class FlwTaskExecutor {
private static class Initializer extends AtomicSafeInitializer<TaskExecutor> { private static class Initializer extends AtomicSafeInitializer<TaskExecutor> {
@Override @Override
protected TaskExecutor initialize() { protected TaskExecutor initialize() {
int threadCount = FlwConfig.get() int threadCount = FlwConfig.INSTANCE
.workerThreads(); .workerThreads();
if (threadCount == 0) { if (threadCount == 0) {

View file

@ -0,0 +1,67 @@
package com.jozufozu.flywheel.impl.visualization;
import com.jozufozu.flywheel.api.event.RenderContext;
import com.jozufozu.flywheel.api.event.RenderStage;
import com.jozufozu.flywheel.api.visualization.VisualizationManager;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.Level;
public final class VisualizationEventHandler {
private VisualizationEventHandler() {
}
public static void onClientTick(Minecraft minecraft, Level level) {
// The game won't be paused in the tick event, but let's make sure there's a player.
if (minecraft.player == null) {
return;
}
VisualizationManagerImpl manager = VisualizationManagerImpl.get(level);
if (manager == null) {
return;
}
manager.tick();
}
public static void onBeginFrame(RenderContext context) {
ClientLevel level = context.level();
VisualizationManagerImpl manager = VisualizationManagerImpl.get(level);
if (manager == null) {
return;
}
manager.beginFrame(context);
}
public static void onRenderStage(RenderContext context, RenderStage stage) {
ClientLevel level = context.level();
VisualizationManagerImpl manager = VisualizationManagerImpl.get(level);
if (manager == null) {
return;
}
manager.renderStage(context, stage);
}
public static void onEntityJoinLevel(Level level, Entity entity) {
VisualizationManager manager = VisualizationManager.get(level);
if (manager == null) {
return;
}
manager.getEntities().queueAdd(entity);
}
public static void onEntityLeaveLevel(Level level, Entity entity) {
VisualizationManager manager = VisualizationManager.get(level);
if (manager == null) {
return;
}
manager.getEntities().queueRemove(entity);
}
}

View file

@ -24,7 +24,7 @@ import com.jozufozu.flywheel.api.visualization.VisualManager;
import com.jozufozu.flywheel.api.visualization.VisualizationContext; import com.jozufozu.flywheel.api.visualization.VisualizationContext;
import com.jozufozu.flywheel.api.visualization.VisualizationLevel; import com.jozufozu.flywheel.api.visualization.VisualizationLevel;
import com.jozufozu.flywheel.api.visualization.VisualizationManager; import com.jozufozu.flywheel.api.visualization.VisualizationManager;
import com.jozufozu.flywheel.config.FlwConfig; import com.jozufozu.flywheel.impl.FlwConfig;
import com.jozufozu.flywheel.impl.extension.LevelExtension; import com.jozufozu.flywheel.impl.extension.LevelExtension;
import com.jozufozu.flywheel.impl.task.FlwTaskExecutor; import com.jozufozu.flywheel.impl.task.FlwTaskExecutor;
import com.jozufozu.flywheel.impl.visual.DynamicVisualContextImpl; import com.jozufozu.flywheel.impl.visual.DynamicVisualContextImpl;
@ -133,7 +133,7 @@ public class VisualizationManagerImpl implements VisualizationManager {
} }
protected DistanceUpdateLimiterImpl createUpdateLimiter() { protected DistanceUpdateLimiterImpl createUpdateLimiter() {
if (FlwConfig.get() if (FlwConfig.INSTANCE
.limitUpdates()) { .limitUpdates()) {
return new BandedPrimeLimiter(); return new BandedPrimeLimiter();
} else { } else {

View file

@ -0,0 +1,11 @@
package com.jozufozu.flywheel.lib.internal;
import com.jozufozu.flywheel.api.internal.DependencyInjection;
import com.jozufozu.flywheel.lib.transform.PoseTransformStack;
import com.mojang.blaze3d.vertex.PoseStack;
public interface FlwLibLink {
FlwLibLink INSTANCE = DependencyInjection.load(FlwLibLink.class, "com.jozufozu.flywheel.impl.FlwLibLinkImpl");
PoseTransformStack getPoseTransformStackOf(PoseStack stack);
}

View file

@ -0,0 +1,30 @@
package com.jozufozu.flywheel.lib.internal;
import org.jetbrains.annotations.Nullable;
import com.jozufozu.flywheel.api.internal.DependencyInjection;
import com.jozufozu.flywheel.lib.model.baked.BakedModelBuilder;
import com.jozufozu.flywheel.lib.model.baked.BlockModelBuilder;
import com.jozufozu.flywheel.lib.model.baked.MultiBlockModelBuilder;
import com.jozufozu.flywheel.lib.util.ShadersModHandler;
import net.minecraft.client.renderer.block.BlockRenderDispatcher;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.BlockAndTintGetter;
import net.minecraft.world.level.block.state.BlockState;
public interface FlwLibXplat {
FlwLibXplat INSTANCE = DependencyInjection.load(FlwLibXplat.class, "com.jozufozu.flywheel.impl.FlwLibXplatImpl");
BlockRenderDispatcher createVanillaBlockRenderDispatcher();
BakedModelBuilder createBakedModelBuilder(BakedModel bakedModel);
BlockModelBuilder createBlockModelBuilder(BlockState state);
MultiBlockModelBuilder createMultiBlockModelBuilder(BlockAndTintGetter level, Iterable<BlockPos> positions);
@Nullable
ShadersModHandler.InternalHandler createIrisHandler();
}

View file

@ -0,0 +1,12 @@
@ApiStatus.Internal
@ParametersAreNonnullByDefault
@FieldsAreNonnullByDefault
@MethodsReturnNonnullByDefault
package com.jozufozu.flywheel.lib.internal;
import javax.annotation.ParametersAreNonnullByDefault;
import org.jetbrains.annotations.ApiStatus;
import net.minecraft.FieldsAreNonnullByDefault;
import net.minecraft.MethodsReturnNonnullByDefault;

View file

@ -17,8 +17,11 @@ public class ModelCache<T> {
public ModelCache(Function<T, Model> factory) { public ModelCache(Function<T, Model> factory) {
this.factory = factory; this.factory = factory;
synchronized (ALL) {
ALL.add(this); ALL.add(this);
} }
}
public Model get(T key) { public Model get(T key) {
return map.computeIfAbsent(key, factory); return map.computeIfAbsent(key, factory);

View file

@ -17,8 +17,11 @@ public class ModelHolder {
public ModelHolder(Supplier<Model> factory) { public ModelHolder(Supplier<Model> factory) {
this.factory = factory; this.factory = factory;
synchronized (ALL) {
ALL.add(this); ALL.add(this);
} }
}
public Model get() { public Model get() {
Model model = this.model; Model model = this.model;

View file

@ -14,10 +14,10 @@ import com.jozufozu.flywheel.api.model.Model;
import com.jozufozu.flywheel.api.vertex.VertexList; import com.jozufozu.flywheel.api.vertex.VertexList;
import com.jozufozu.flywheel.api.vertex.VertexView; import com.jozufozu.flywheel.api.vertex.VertexView;
import com.jozufozu.flywheel.api.vertex.VertexViewProviderRegistry; import com.jozufozu.flywheel.api.vertex.VertexViewProviderRegistry;
import com.jozufozu.flywheel.lib.internal.FlwLibXplat;
import com.jozufozu.flywheel.lib.material.Materials; import com.jozufozu.flywheel.lib.material.Materials;
import com.jozufozu.flywheel.lib.memory.MemoryBlock; import com.jozufozu.flywheel.lib.memory.MemoryBlock;
import com.jozufozu.flywheel.lib.vertex.PosVertexView; import com.jozufozu.flywheel.lib.vertex.PosVertexView;
import com.jozufozu.flywheel.platform.ClientPlatform;
import com.mojang.blaze3d.vertex.BufferBuilder; import com.mojang.blaze3d.vertex.BufferBuilder;
import com.mojang.blaze3d.vertex.BufferBuilder.DrawState; import com.mojang.blaze3d.vertex.BufferBuilder.DrawState;
import com.mojang.blaze3d.vertex.VertexFormat; import com.mojang.blaze3d.vertex.VertexFormat;
@ -30,7 +30,7 @@ public final class ModelUtil {
* An alternative BlockRenderDispatcher that circumvents the Forge rendering pipeline to ensure consistency. * An alternative BlockRenderDispatcher that circumvents the Forge rendering pipeline to ensure consistency.
* Meant to be used for virtual rendering. * Meant to be used for virtual rendering.
*/ */
public static final BlockRenderDispatcher VANILLA_RENDERER = ClientPlatform.INSTANCE.createVanillaRenderer(); public static final BlockRenderDispatcher VANILLA_RENDERER = FlwLibXplat.INSTANCE.createVanillaBlockRenderDispatcher();
private static final float BOUNDING_SPHERE_EPSILON = 1e-4f; private static final float BOUNDING_SPHERE_EPSILON = 1e-4f;
private ModelUtil() { private ModelUtil() {

View file

@ -5,8 +5,8 @@ import java.util.function.BiFunction;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import com.jozufozu.flywheel.api.material.Material; import com.jozufozu.flywheel.api.material.Material;
import com.jozufozu.flywheel.lib.internal.FlwLibXplat;
import com.jozufozu.flywheel.lib.model.SimpleModel; import com.jozufozu.flywheel.lib.model.SimpleModel;
import com.jozufozu.flywheel.platform.ClientPlatform;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.RenderType;
@ -26,7 +26,7 @@ public abstract class BakedModelBuilder {
protected BiFunction<RenderType, Boolean, Material> materialFunc; protected BiFunction<RenderType, Boolean, Material> materialFunc;
public static BakedModelBuilder create(BakedModel bakedModel) { public static BakedModelBuilder create(BakedModel bakedModel) {
return ClientPlatform.INSTANCE.bakedModelBuilder(bakedModel); return FlwLibXplat.INSTANCE.createBakedModelBuilder(bakedModel);
} }
protected BakedModelBuilder(BakedModel bakedModel) { protected BakedModelBuilder(BakedModel bakedModel) {

View file

@ -5,8 +5,8 @@ import java.util.function.BiFunction;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import com.jozufozu.flywheel.api.material.Material; import com.jozufozu.flywheel.api.material.Material;
import com.jozufozu.flywheel.lib.internal.FlwLibXplat;
import com.jozufozu.flywheel.lib.model.SimpleModel; import com.jozufozu.flywheel.lib.model.SimpleModel;
import com.jozufozu.flywheel.platform.ClientPlatform;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.RenderType;
@ -23,7 +23,7 @@ public abstract class BlockModelBuilder {
protected BiFunction<RenderType, Boolean, Material> materialFunc; protected BiFunction<RenderType, Boolean, Material> materialFunc;
public static BlockModelBuilder create(BlockState state) { public static BlockModelBuilder create(BlockState state) {
return ClientPlatform.INSTANCE.blockModelBuilder(state); return FlwLibXplat.INSTANCE.createBlockModelBuilder(state);
} }
protected BlockModelBuilder(BlockState state) { protected BlockModelBuilder(BlockState state) {

View file

@ -5,8 +5,8 @@ import java.util.function.BiFunction;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import com.jozufozu.flywheel.api.material.Material; import com.jozufozu.flywheel.api.material.Material;
import com.jozufozu.flywheel.lib.internal.FlwLibXplat;
import com.jozufozu.flywheel.lib.model.SimpleModel; import com.jozufozu.flywheel.lib.model.SimpleModel;
import com.jozufozu.flywheel.platform.ClientPlatform;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.RenderType;
@ -23,7 +23,7 @@ public abstract class MultiBlockModelBuilder {
protected BiFunction<RenderType, Boolean, Material> materialFunc; protected BiFunction<RenderType, Boolean, Material> materialFunc;
public static MultiBlockModelBuilder create(BlockAndTintGetter level, Iterable<BlockPos> positions) { public static MultiBlockModelBuilder create(BlockAndTintGetter level, Iterable<BlockPos> positions) {
return ClientPlatform.INSTANCE.multiBlockModelBuilder(level, positions); return FlwLibXplat.INSTANCE.createMultiBlockModelBuilder(level, positions);
} }
protected MultiBlockModelBuilder(BlockAndTintGetter level, Iterable<BlockPos> positions) { protected MultiBlockModelBuilder(BlockAndTintGetter level, Iterable<BlockPos> positions) {

View file

@ -7,15 +7,13 @@ import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
/** /**
* A helper class for loading and accessing json models. * A helper class for loading and accessing JSON models not directly used by any blocks or items.
* <br> * <br>
* Creating a PartialModel will make the associated modelLocation automatically load. * Creating a PartialModel will make Minecraft automatically load the associated modelLocation.
* PartialModels must be initialized in the mod class constructor. * PartialModels must be initialized before the initial resource reload, otherwise an error will be thrown.
* It is recommended to do this in the client mod initializer on Fabric and the mod class constructor on Forge.
* <br> * <br>
* Once {@link ModelEvent.RegisterAdditional} finishes, all PartialModels (with valid modelLocations) * Once Minecraft has finished baking all models, all PartialModels will have their bakedModel fields populated.
* will have their bakedModel fields populated.
* <br>
* Attempting to create a PartialModel after {@link ModelEvent.RegisterAdditional} will cause an error.
*/ */
public class PartialModel { public class PartialModel {
static final List<PartialModel> ALL = new ArrayList<>(); static final List<PartialModel> ALL = new ArrayList<>();
@ -26,27 +24,30 @@ public class PartialModel {
public PartialModel(ResourceLocation modelLocation) { public PartialModel(ResourceLocation modelLocation) {
if (tooLate) { if (tooLate) {
throw new RuntimeException("PartialModel '" + modelLocation + "' loaded after ModelRegistryEvent"); throw new RuntimeException("Attempted to create PartialModel with location '" + modelLocation + "' after start of initial resource reload!");
} }
this.modelLocation = modelLocation; this.modelLocation = modelLocation;
synchronized (ALL) {
ALL.add(this); ALL.add(this);
} }
}
public ResourceLocation getLocation() {
return modelLocation;
}
public String getName() { public String getName() {
return getLocation() return getLocation()
.toString(); .toString();
} }
public ResourceLocation getLocation() {
return modelLocation;
}
public BakedModel get() { public BakedModel get() {
return bakedModel; return bakedModel;
} }
void set(BakedModel bakedModel) { protected void set(BakedModel bakedModel) {
this.bakedModel = bakedModel; this.bakedModel = bakedModel;
} }
} }

View file

@ -1,11 +1,11 @@
package com.jozufozu.flywheel.lib.transform; package com.jozufozu.flywheel.lib.transform;
import com.jozufozu.flywheel.api.internal.InternalFlywheelApi; import com.jozufozu.flywheel.lib.internal.FlwLibLink;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
public interface TransformStack<Self extends TransformStack<Self>> extends Transform<Self> { public interface TransformStack<Self extends TransformStack<Self>> extends Transform<Self> {
static PoseTransformStack of(PoseStack stack) { static PoseTransformStack of(PoseStack stack) {
return InternalFlywheelApi.INSTANCE.getPoseTransformStackOf(stack); return FlwLibLink.INSTANCE.getPoseTransformStackOf(stack);
} }
Self pushPose(); Self pushPose();

View file

@ -6,7 +6,7 @@ import java.util.function.BooleanSupplier;
import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.ApiStatus;
import org.slf4j.Logger; import org.slf4j.Logger;
import com.jozufozu.flywheel.platform.ClientPlatform; import com.jozufozu.flywheel.lib.internal.FlwLibXplat;
import com.mojang.logging.LogUtils; import com.mojang.logging.LogUtils;
public final class ShadersModHandler { public final class ShadersModHandler {
@ -19,23 +19,23 @@ public final class ShadersModHandler {
private static final InternalHandler INTERNAL_HANDLER; private static final InternalHandler INTERNAL_HANDLER;
static { static {
InternalHandler irisHandler = FlwLibXplat.INSTANCE
.createIrisHandler();
IS_IRIS_LOADED = irisHandler != null;
Package optifinePackage = Package.getPackage(OPTIFINE_ROOT_PACKAGE); Package optifinePackage = Package.getPackage(OPTIFINE_ROOT_PACKAGE);
IS_OPTIFINE_INSTALLED = optifinePackage != null; IS_OPTIFINE_INSTALLED = optifinePackage != null;
var irisOculusHandler = ClientPlatform.INSTANCE
.createIrisOculusHandlerIfPresent();
IS_IRIS_LOADED = irisOculusHandler != null;
// OptiFine and Iris/Oculus are assumed to be mutually exclusive // OptiFine and Iris/Oculus are assumed to be mutually exclusive
if (IS_OPTIFINE_INSTALLED) { if (IS_IRIS_LOADED) {
LOGGER.info("Optifine detected."); LOGGER.debug("Iris detected.");
INTERNAL_HANDLER = new Optifine(); INTERNAL_HANDLER = irisHandler;
} else if (IS_IRIS_LOADED) { } else if (IS_OPTIFINE_INSTALLED) {
LOGGER.info("Iris detected."); LOGGER.debug("OptiFine detected.");
INTERNAL_HANDLER = irisOculusHandler; INTERNAL_HANDLER = new OptifineHandler();
} else { } else {
LOGGER.info("No shaders mod detected."); LOGGER.debug("No shaders mod detected.");
INTERNAL_HANDLER = new InternalHandler() {}; INTERNAL_HANDLER = new InternalHandler() {};
} }
} }
@ -67,19 +67,19 @@ public final class ShadersModHandler {
public interface InternalHandler { public interface InternalHandler {
default boolean isShaderPackInUse() { default boolean isShaderPackInUse() {
return false; return false;
}; }
default boolean isRenderingShadowPass() { default boolean isRenderingShadowPass() {
return false; return false;
}; }
} }
// evil reflection // evil reflection
private static class Optifine implements InternalHandler { private static class OptifineHandler implements InternalHandler {
private final BooleanSupplier shadersEnabledSupplier; private final BooleanSupplier shadersEnabledSupplier;
private final BooleanSupplier shadowPassSupplier; private final BooleanSupplier shadowPassSupplier;
Optifine() { private OptifineHandler() {
shadersEnabledSupplier = createShadersEnabledSupplier(); shadersEnabledSupplier = createShadersEnabledSupplier();
shadowPassSupplier = createShadowPassSupplier(); shadowPassSupplier = createShadowPassSupplier();
} }
@ -102,11 +102,11 @@ public final class ShadersModHandler {
return () -> { return () -> {
try { try {
return field.getBoolean(null); return field.getBoolean(null);
} catch (IllegalAccessException ignored) { } catch (IllegalAccessException e) {
return false; return false;
} }
}; };
} catch (Exception ignored) { } catch (Exception e) {
return () -> false; return () -> false;
} }
} }
@ -119,11 +119,11 @@ public final class ShadersModHandler {
return () -> { return () -> {
try { try {
return field.getBoolean(null); return field.getBoolean(null);
} catch (IllegalAccessException ignored) { } catch (IllegalAccessException e) {
return false; return false;
} }
}; };
} catch (Exception ignored) { } catch (Exception e) {
return () -> false; return () -> false;
} }
} }

View file

@ -3,6 +3,8 @@ package com.jozufozu.flywheel.lib.visual;
import java.util.Objects; import java.util.Objects;
import java.util.function.Predicate; import java.util.function.Predicate;
import org.jetbrains.annotations.Nullable;
import com.jozufozu.flywheel.api.visual.BlockEntityVisual; import com.jozufozu.flywheel.api.visual.BlockEntityVisual;
import com.jozufozu.flywheel.api.visualization.BlockEntityVisualizer; import com.jozufozu.flywheel.api.visualization.BlockEntityVisualizer;
import com.jozufozu.flywheel.api.visualization.VisualizationContext; import com.jozufozu.flywheel.api.visualization.VisualizationContext;
@ -54,7 +56,9 @@ public class SimpleBlockEntityVisualizer<T extends BlockEntity> implements Block
*/ */
public static class Builder<T extends BlockEntity> { public static class Builder<T extends BlockEntity> {
protected BlockEntityType<T> type; protected BlockEntityType<T> type;
@Nullable
protected Factory<T> visualFactory; protected Factory<T> visualFactory;
@Nullable
protected Predicate<T> skipVanillaRender; protected Predicate<T> skipVanillaRender;
public Builder(BlockEntityType<T> type) { public Builder(BlockEntityType<T> type) {

View file

@ -3,6 +3,8 @@ package com.jozufozu.flywheel.lib.visual;
import java.util.Objects; import java.util.Objects;
import java.util.function.Predicate; import java.util.function.Predicate;
import org.jetbrains.annotations.Nullable;
import com.jozufozu.flywheel.api.visual.EntityVisual; import com.jozufozu.flywheel.api.visual.EntityVisual;
import com.jozufozu.flywheel.api.visualization.EntityVisualizer; import com.jozufozu.flywheel.api.visualization.EntityVisualizer;
import com.jozufozu.flywheel.api.visualization.VisualizationContext; import com.jozufozu.flywheel.api.visualization.VisualizationContext;
@ -54,7 +56,9 @@ public class SimpleEntityVisualizer<T extends Entity> implements EntityVisualize
*/ */
public static class Builder<T extends Entity> { public static class Builder<T extends Entity> {
protected EntityType<T> type; protected EntityType<T> type;
@Nullable
protected Factory<T> visualFactory; protected Factory<T> visualFactory;
@Nullable
protected Predicate<T> skipVanillaRender; protected Predicate<T> skipVanillaRender;
public Builder(EntityType<T> type) { public Builder(EntityType<T> type) {

View file

@ -1,47 +0,0 @@
package com.jozufozu.flywheel.platform;
import org.jetbrains.annotations.Nullable;
import com.jozufozu.flywheel.api.event.RenderContext;
import com.jozufozu.flywheel.api.event.RenderStage;
import com.jozufozu.flywheel.api.internal.DependencyInjection;
import com.jozufozu.flywheel.config.FlwConfig;
import com.jozufozu.flywheel.lib.model.baked.BakedModelBuilder;
import com.jozufozu.flywheel.lib.model.baked.BlockModelBuilder;
import com.jozufozu.flywheel.lib.model.baked.MultiBlockModelBuilder;
import com.jozufozu.flywheel.lib.util.ShadersModHandler;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.renderer.block.BlockRenderDispatcher;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.BlockAndTintGetter;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.state.BlockState;
public interface ClientPlatform {
ClientPlatform INSTANCE = DependencyInjection.load(ClientPlatform.class, "com.jozufozu.flywheel.platform.ClientPlatformImpl");
void dispatchReloadLevelRenderer(ClientLevel level);
void dispatchBeginFrame(RenderContext context);
void dispatchRenderStage(RenderContext context, RenderStage stage);
boolean isModLoaded(String modid);
@Nullable
ShadersModHandler.InternalHandler createIrisOculusHandlerIfPresent();
int getLightEmission(BlockState state, BlockGetter level, BlockPos pos);
FlwConfig getConfigInstance();
BlockRenderDispatcher createVanillaRenderer();
BakedModelBuilder bakedModelBuilder(BakedModel bakedModel);
BlockModelBuilder blockModelBuilder(BlockState state);
MultiBlockModelBuilder multiBlockModelBuilder(BlockAndTintGetter level, Iterable<BlockPos> positions);
}

View file

@ -1,5 +1,7 @@
package com.jozufozu.flywheel.api.event; package com.jozufozu.flywheel.api.event;
import org.jetbrains.annotations.Nullable;
import net.fabricmc.fabric.api.event.Event; import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory; import net.fabricmc.fabric.api.event.EventFactory;
import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.multiplayer.ClientLevel;
@ -13,5 +15,5 @@ public interface ReloadLevelRendererCallback {
} }
}); });
void onReloadLevelRenderer(ClientLevel level); void onReloadLevelRenderer(@Nullable ClientLevel level);
} }

View file

@ -0,0 +1,12 @@
package com.jozufozu.flywheel.backend;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.state.BlockState;
public class FlwBackendXplatImpl implements FlwBackendXplat {
@Override
public int getLightEmission(BlockState state, BlockGetter level, BlockPos pos) {
return state.getLightEmission();
}
}

View file

@ -0,0 +1,26 @@
package com.jozufozu.flywheel.backend.compile;
import com.jozufozu.flywheel.Flywheel;
import net.fabricmc.fabric.api.resource.SimpleSynchronousResourceReloadListener;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.resources.ResourceManager;
public final class FlwProgramsReloader implements SimpleSynchronousResourceReloadListener {
public static final FlwProgramsReloader INSTANCE = new FlwProgramsReloader();
public static final ResourceLocation ID = Flywheel.rl("programs");
private FlwProgramsReloader() {
}
@Override
public void onResourceManagerReload(ResourceManager manager) {
FlwPrograms.reload(manager);
}
@Override
public ResourceLocation getFabricId() {
return ID;
}
}

View file

@ -0,0 +1,24 @@
package com.jozufozu.flywheel.impl;
import com.jozufozu.flywheel.api.backend.Backend;
import com.jozufozu.flywheel.backend.Backends;
// TODO: Fabric config
public class FabricFlwConfig implements FlwConfig {
public static final FabricFlwConfig INSTANCE = new FabricFlwConfig();
@Override
public Backend backend() {
return Backends.INDIRECT;
}
@Override
public boolean limitUpdates() {
return true;
}
@Override
public int workerThreads() {
return -1;
}
}

View file

@ -0,0 +1,38 @@
package com.jozufozu.flywheel.impl;
import org.jetbrains.annotations.Nullable;
import com.jozufozu.flywheel.api.event.BeginFrameCallback;
import com.jozufozu.flywheel.api.event.ReloadLevelRendererCallback;
import com.jozufozu.flywheel.api.event.RenderContext;
import com.jozufozu.flywheel.api.event.RenderStage;
import com.jozufozu.flywheel.api.event.RenderStageCallback;
import net.minecraft.client.multiplayer.ClientLevel;
public class FlwImplXplatImpl implements FlwImplXplat {
@Override
public void dispatchBeginFrameEvent(RenderContext context) {
BeginFrameCallback.EVENT.invoker().onBeginFrame(context);
}
@Override
public void dispatchReloadLevelRendererEvent(@Nullable ClientLevel level) {
ReloadLevelRendererCallback.EVENT.invoker().onReloadLevelRenderer(level);
}
@Override
public void dispatchRenderStageEvent(RenderContext context, RenderStage stage) {
RenderStageCallback.EVENT.invoker().onRenderStage(context, stage);
}
@Override
public String getVersionStr() {
return FlywheelFabric.version().getFriendlyString();
}
@Override
public FlwConfig getConfig() {
return FabricFlwConfig.INSTANCE;
}
}

View file

@ -0,0 +1,63 @@
package com.jozufozu.flywheel.impl;
import org.jetbrains.annotations.Nullable;
import com.jozufozu.flywheel.lib.internal.FlwLibXplat;
import com.jozufozu.flywheel.lib.model.baked.BakedModelBuilder;
import com.jozufozu.flywheel.lib.model.baked.BlockModelBuilder;
import com.jozufozu.flywheel.lib.model.baked.MultiBlockModelBuilder;
import com.jozufozu.flywheel.lib.util.ShadersModHandler;
import net.fabricmc.loader.api.FabricLoader;
import net.irisshaders.iris.api.v0.IrisApi;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.block.BlockRenderDispatcher;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.BlockAndTintGetter;
import net.minecraft.world.level.block.state.BlockState;
public class FlwLibXplatImpl implements FlwLibXplat {
@Override
public BlockRenderDispatcher createVanillaBlockRenderDispatcher() {
return Minecraft.getInstance().getBlockRenderer();
}
@Override
public BakedModelBuilder createBakedModelBuilder(BakedModel bakedModel) {
return null;
}
@Override
public BlockModelBuilder createBlockModelBuilder(BlockState state) {
return null;
}
@Override
public MultiBlockModelBuilder createMultiBlockModelBuilder(BlockAndTintGetter level, Iterable<BlockPos> positions) {
return null;
}
@Override
@Nullable
public ShadersModHandler.InternalHandler createIrisHandler() {
if (!FabricLoader.getInstance()
.isModLoaded("iris")) {
return null;
}
return new ShadersModHandler.InternalHandler() {
@Override
public boolean isShaderPackInUse() {
return IrisApi.getInstance()
.isShaderPackInUse();
}
@Override
public boolean isRenderingShadowPass() {
return IrisApi.getInstance()
.isRenderingShadowPass();
}
};
}
}

View file

@ -1,10 +1,94 @@
package com.jozufozu.flywheel.impl; package com.jozufozu.flywheel.impl;
import net.fabricmc.api.ClientModInitializer; import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.api.event.BeginFrameCallback;
import com.jozufozu.flywheel.api.event.EndClientResourceReloadCallback;
import com.jozufozu.flywheel.api.event.ReloadLevelRendererCallback;
import com.jozufozu.flywheel.api.event.RenderStageCallback;
import com.jozufozu.flywheel.backend.compile.FlwProgramsReloader;
import com.jozufozu.flywheel.backend.engine.uniform.Uniforms;
import com.jozufozu.flywheel.impl.visualization.VisualizationEventHandler;
import com.jozufozu.flywheel.lib.model.ModelCache;
import com.jozufozu.flywheel.lib.model.ModelHolder;
import com.jozufozu.flywheel.lib.model.baked.PartialModelEventHandler;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
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.loading.v1.ModelLoadingPlugin;
import net.fabricmc.fabric.api.command.v2.ArgumentTypeRegistry;
import net.fabricmc.fabric.api.resource.ResourceManagerHelper;
import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.loader.api.ModContainer;
import net.fabricmc.loader.api.Version;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.server.packs.PackType;
public final class FlywheelFabric implements ClientModInitializer {
private static Version version;
public class FlywheelFabric implements ClientModInitializer {
@Override @Override
public void onInitializeClient() { public void onInitializeClient() {
ModContainer modContainer = FabricLoader.getInstance().getModContainer(Flywheel.ID).orElseThrow();
version = modContainer.getMetadata().getVersion();
setupImpl();
setupLib();
setupBackend();
FlywheelInit.init();
// FIXME: Registries cannot be frozen this early.
FlywheelInit.freezeRegistries();
}
private static void setupImpl() {
ReloadLevelRendererCallback.EVENT.register(BackendManagerImpl::onReloadLevelRenderer);
// This Fabric event runs slightly later than the Forge event Flywheel uses, but it shouldn't make a difference.
ClientTickEvents.END_CLIENT_TICK.register(minecraft -> {
if (!minecraft.isPaused()) {
ClientLevel level = minecraft.level;
if (level != null) {
VisualizationEventHandler.onClientTick(minecraft, level);
}
}
});
BeginFrameCallback.EVENT.register(VisualizationEventHandler::onBeginFrame);
RenderStageCallback.EVENT.register(VisualizationEventHandler::onRenderStage);
ClientEntityEvents.ENTITY_LOAD.register((entity, level) -> VisualizationEventHandler.onEntityJoinLevel(level, entity));
ClientEntityEvents.ENTITY_UNLOAD.register((entity, level) -> VisualizationEventHandler.onEntityLeaveLevel(level, entity));
ClientCommandRegistrationCallback.EVENT.register((dispatcher, ctx) -> {
// TODO: Fabric client commands
});
EndClientResourceReloadCallback.EVENT.register((minecraft, resourceManager, initialReload, error) ->
BackendManagerImpl.onEndClientResourceReload(error.isPresent()));
ArgumentTypeRegistry.registerArgumentType(Flywheel.rl("backend"), BackendArgument.class, BackendArgument.INFO);
}
private static void setupLib() {
EndClientResourceReloadCallback.EVENT.register((minecraft, resourceManager, initialReload, error) ->
ModelCache.onEndClientResourceReload());
EndClientResourceReloadCallback.EVENT.register((minecraft, resourceManager, initialReload, error) ->
ModelHolder.onEndClientResourceReload());
ModelLoadingPlugin.register(ctx -> {
ctx.addModels(PartialModelEventHandler.onRegisterAdditional());
});
ResourceManagerHelper.get(PackType.CLIENT_RESOURCES).registerReloadListener(PartialModelEventHandler.ReloadListener.INSTANCE);
}
private static void setupBackend() {
ReloadLevelRendererCallback.EVENT.register(level -> Uniforms.onReloadLevelRenderer());
ResourceManagerHelper.get(PackType.CLIENT_RESOURCES).registerReloadListener(FlwProgramsReloader.INSTANCE);
}
public static Version version() {
return version;
} }
} }

View file

@ -0,0 +1,27 @@
package com.jozufozu.flywheel.impl.mixin.fabric;
import java.util.List;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import com.jozufozu.flywheel.impl.FlwDebugInfo;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.components.DebugScreenOverlay;
@Mixin(DebugScreenOverlay.class)
abstract class DebugScreenOverlayMixin {
@Shadow
@Final
private Minecraft minecraft;
@Inject(method = "getSystemInformation", at = @At("RETURN"))
private void flywheel$onGetSystemInformation(CallbackInfoReturnable<List<String>> cir) {
FlwDebugInfo.addDebugInfo(minecraft, cir.getReturnValue());
}
}

View file

@ -0,0 +1,32 @@
package com.jozufozu.flywheel.impl.mixin.fabric;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import com.jozufozu.flywheel.lib.util.LevelAttached;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientLevel;
@Mixin(Minecraft.class)
abstract class MinecraftMixin {
@Shadow
public ClientLevel level;
@Inject(method = "setLevel(Lnet/minecraft/client/multiplayer/ClientLevel;)V", at = @At("HEAD"))
private void flywheel$onSetLevel(CallbackInfo ci) {
if (level != null) {
LevelAttached.invalidateLevel(level);
}
}
@Inject(method = "clearLevel(Lnet/minecraft/client/gui/screens/Screen;)V", at = @At("HEAD"))
private void flywheel$onClearLevel(CallbackInfo ci) {
if (level != null) {
LevelAttached.invalidateLevel(level);
}
}
}

View file

@ -0,0 +1,19 @@
package com.jozufozu.flywheel.impl.mixin.fabric;
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;
import com.jozufozu.flywheel.impl.BackendManagerImpl;
import net.minecraft.SystemReport;
@Mixin(value = SystemReport.class, priority = 1056)
abstract class SystemReportMixin {
@Inject(method = "<init>", at = @At("RETURN"))
private void flywheel$onInit(CallbackInfo ci) {
SystemReport self = (SystemReport) (Object) this;
self.setDetail("Flywheel Backend", BackendManagerImpl::getBackendString);
}
}

View file

@ -0,0 +1,56 @@
package com.jozufozu.flywheel.lib.model.baked;
import java.util.List;
import org.jetbrains.annotations.ApiStatus;
import com.jozufozu.flywheel.Flywheel;
import net.fabricmc.fabric.api.resource.ResourceReloadListenerKeys;
import net.fabricmc.fabric.api.resource.SimpleSynchronousResourceReloadListener;
import net.minecraft.client.Minecraft;
import net.minecraft.client.resources.model.ModelManager;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.resources.ResourceManager;
@ApiStatus.Internal
public final class PartialModelEventHandler {
private PartialModelEventHandler() {
}
public static ResourceLocation[] onRegisterAdditional() {
PartialModel.tooLate = true;
return PartialModel.ALL.stream().map(PartialModel::getLocation).toArray(ResourceLocation[]::new);
}
public static void onBakingCompleted(ModelManager manager) {
for (PartialModel partial : PartialModel.ALL) {
partial.set(manager.getModel(partial.getLocation()));
}
}
public static final class ReloadListener implements SimpleSynchronousResourceReloadListener {
public static final ReloadListener INSTANCE = new ReloadListener();
public static final ResourceLocation ID = Flywheel.rl("partial_models");
public static final List<ResourceLocation> DEPENDENCIES = List.of(ResourceReloadListenerKeys.MODELS);
private ReloadListener() {
}
@Override
public void onResourceManagerReload(ResourceManager resourceManager) {
onBakingCompleted(Minecraft.getInstance().getModelManager());
}
@Override
public ResourceLocation getFabricId() {
return ID;
}
@Override
public List<ResourceLocation> getFabricDependencies() {
return DEPENDENCIES;
}
}
}

View file

@ -1,101 +0,0 @@
package com.jozufozu.flywheel.platform;
import org.jetbrains.annotations.Nullable;
import com.jozufozu.flywheel.api.event.BeginFrameCallback;
import com.jozufozu.flywheel.api.event.ReloadLevelRendererCallback;
import com.jozufozu.flywheel.api.event.RenderContext;
import com.jozufozu.flywheel.api.event.RenderStage;
import com.jozufozu.flywheel.api.event.RenderStageCallback;
import com.jozufozu.flywheel.config.FlwConfig;
import com.jozufozu.flywheel.lib.model.baked.BakedModelBuilder;
import com.jozufozu.flywheel.lib.model.baked.BlockModelBuilder;
import com.jozufozu.flywheel.lib.model.baked.MultiBlockModelBuilder;
import com.jozufozu.flywheel.lib.util.ShadersModHandler;
import net.fabricmc.loader.api.FabricLoader;
import net.irisshaders.iris.api.v0.IrisApi;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.renderer.block.BlockRenderDispatcher;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.BlockAndTintGetter;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.state.BlockState;
public class ClientPlatformImpl implements ClientPlatform {
@Override
public void dispatchReloadLevelRenderer(ClientLevel level) {
ReloadLevelRendererCallback.EVENT.invoker().onReloadLevelRenderer(level);
}
@Override
public void dispatchBeginFrame(RenderContext context) {
BeginFrameCallback.EVENT.invoker().onBeginFrame(context);
}
@Override
public void dispatchRenderStage(RenderContext context, RenderStage stage) {
RenderStageCallback.EVENT.invoker().onRenderStage(context, stage);
}
@Override
public boolean isModLoaded(String modid) {
return FabricLoader.getInstance()
.isModLoaded(modid);
}
@Nullable
@Override
public ShadersModHandler.InternalHandler createIrisOculusHandlerIfPresent() {
if (isModLoaded("iris")) {
return new ShadersModHandler.InternalHandler() {
@Override
public boolean isShaderPackInUse() {
return IrisApi.getInstance()
.isShaderPackInUse();
}
@Override
public boolean isRenderingShadowPass() {
return IrisApi.getInstance()
.isRenderingShadowPass();
}
};
} else {
return null;
}
}
@Override
public int getLightEmission(BlockState state, BlockGetter level, BlockPos pos) {
return state.getLightEmission();
}
@Override
public FlwConfig getConfigInstance() {
// TODO: fabric config
return null;
}
@Override
public BlockRenderDispatcher createVanillaRenderer() {
return Minecraft.getInstance().getBlockRenderer();
}
@Override
public BakedModelBuilder bakedModelBuilder(BakedModel bakedModel) {
return null;
}
@Override
public BlockModelBuilder blockModelBuilder(BlockState state) {
return null;
}
@Override
public MultiBlockModelBuilder multiBlockModelBuilder(BlockAndTintGetter level, Iterable<BlockPos> positions) {
return null;
}
}

View file

@ -24,7 +24,8 @@
"mixins": [ "mixins": [
"flywheel.backend.mixins.json", "flywheel.backend.mixins.json",
"flywheel.impl.mixins.json", "flywheel.impl.mixins.json",
"flywheel.impl.sodium.mixins.json" "flywheel.impl.sodium.mixins.json",
"flywheel.impl.fabric.mixins.json"
], ],
"depends": { "depends": {
"minecraft": "${minecraft_semver_version_range}", "minecraft": "${minecraft_semver_version_range}",

View file

@ -0,0 +1,15 @@
{
"required": true,
"minVersion": "0.8",
"package": "com.jozufozu.flywheel.impl.mixin.fabric",
"compatibilityLevel": "JAVA_17",
"refmap": "flywheel.refmap.json",
"client": [
"DebugScreenOverlayMixin",
"MinecraftMixin",
"SystemReportMixin"
],
"injectors": {
"defaultRequire": 1
}
}

View file

@ -0,0 +1,12 @@
package com.jozufozu.flywheel.backend;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.state.BlockState;
public class FlwBackendXplatImpl implements FlwBackendXplat {
@Override
public int getLightEmission(BlockState state, BlockGetter level, BlockPos pos) {
return state.getLightEmission(level, pos);
}
}

View file

@ -0,0 +1,16 @@
package com.jozufozu.flywheel.backend.compile;
import net.minecraft.server.packs.resources.ResourceManager;
import net.minecraft.server.packs.resources.ResourceManagerReloadListener;
public final class FlwProgramsReloader implements ResourceManagerReloadListener {
public static final FlwProgramsReloader INSTANCE = new FlwProgramsReloader();
private FlwProgramsReloader() {
}
@Override
public void onResourceManagerReload(ResourceManager manager) {
FlwPrograms.reload(manager);
}
}

View file

@ -1,9 +1,10 @@
package com.jozufozu.flywheel.config; package com.jozufozu.flywheel.impl;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import com.jozufozu.flywheel.api.backend.Backend; import com.jozufozu.flywheel.api.backend.Backend;
import com.jozufozu.flywheel.api.backend.BackendManager; import com.jozufozu.flywheel.api.backend.BackendManager;
import com.jozufozu.flywheel.backend.engine.uniform.DebugMode;
import com.jozufozu.flywheel.backend.engine.uniform.FrameUniforms; import com.jozufozu.flywheel.backend.engine.uniform.FrameUniforms;
import com.mojang.brigadier.Command; import com.mojang.brigadier.Command;
import com.mojang.brigadier.arguments.IntegerArgumentType; import com.mojang.brigadier.arguments.IntegerArgumentType;
@ -25,7 +26,7 @@ public final class FlwCommands {
} }
public static void registerClientCommands(RegisterClientCommandsEvent event) { public static void registerClientCommands(RegisterClientCommandsEvent event) {
var config = FlwForgeConfig.INSTANCE; var config = ForgeFlwConfig.INSTANCE;
LiteralArgumentBuilder<CommandSourceStack> command = Commands.literal("flywheel"); LiteralArgumentBuilder<CommandSourceStack> command = Commands.literal("flywheel");

View file

@ -0,0 +1,39 @@
package com.jozufozu.flywheel.impl;
import org.jetbrains.annotations.Nullable;
import com.jozufozu.flywheel.api.event.BeginFrameEvent;
import com.jozufozu.flywheel.api.event.ReloadLevelRendererEvent;
import com.jozufozu.flywheel.api.event.RenderContext;
import com.jozufozu.flywheel.api.event.RenderStage;
import com.jozufozu.flywheel.api.event.RenderStageEvent;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraftforge.common.MinecraftForge;
public class FlwImplXplatImpl implements FlwImplXplat {
@Override
public void dispatchBeginFrameEvent(RenderContext context) {
MinecraftForge.EVENT_BUS.post(new BeginFrameEvent(context));
}
@Override
public void dispatchReloadLevelRendererEvent(@Nullable ClientLevel level) {
MinecraftForge.EVENT_BUS.post(new ReloadLevelRendererEvent(level));
}
@Override
public void dispatchRenderStageEvent(RenderContext context, RenderStage stage) {
MinecraftForge.EVENT_BUS.post(new RenderStageEvent(context, stage));
}
@Override
public String getVersionStr() {
return FlywheelForge.version().toString();
}
@Override
public FlwConfig getConfig() {
return ForgeFlwConfig.INSTANCE;
}
}

View file

@ -0,0 +1,86 @@
package com.jozufozu.flywheel.impl;
import java.lang.reflect.Field;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import com.jozufozu.flywheel.lib.internal.FlwLibXplat;
import com.jozufozu.flywheel.lib.model.baked.BakedModelBuilder;
import com.jozufozu.flywheel.lib.model.baked.BlockModelBuilder;
import com.jozufozu.flywheel.lib.model.baked.ForgeBakedModelBuilder;
import com.jozufozu.flywheel.lib.model.baked.ForgeBlockModelBuilder;
import com.jozufozu.flywheel.lib.model.baked.ForgeMultiBlockModelBuilder;
import com.jozufozu.flywheel.lib.model.baked.MultiBlockModelBuilder;
import com.jozufozu.flywheel.lib.util.ShadersModHandler;
import com.mojang.logging.LogUtils;
import net.irisshaders.iris.api.v0.IrisApi;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.block.BlockRenderDispatcher;
import net.minecraft.client.renderer.block.ModelBlockRenderer;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.BlockAndTintGetter;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraftforge.fml.ModList;
import net.minecraftforge.fml.util.ObfuscationReflectionHelper;
public class FlwLibXplatImpl implements FlwLibXplat {
private static final Logger LOGGER = LogUtils.getLogger();
@Override
public BlockRenderDispatcher createVanillaBlockRenderDispatcher() {
BlockRenderDispatcher defaultDispatcher = Minecraft.getInstance().getBlockRenderer();
BlockRenderDispatcher dispatcher = new BlockRenderDispatcher(null, null, null);
try {
for (Field field : BlockRenderDispatcher.class.getDeclaredFields()) {
field.setAccessible(true);
field.set(dispatcher, field.get(defaultDispatcher));
}
ObfuscationReflectionHelper.setPrivateValue(BlockRenderDispatcher.class, dispatcher, new ModelBlockRenderer(Minecraft.getInstance().getBlockColors()), "f_110900_");
} catch (Exception e) {
LOGGER.error("Failed to initialize vanilla BlockRenderDispatcher!", e);
return defaultDispatcher;
}
return dispatcher;
}
@Override
public BakedModelBuilder createBakedModelBuilder(BakedModel bakedModel) {
return new ForgeBakedModelBuilder(bakedModel);
}
@Override
public BlockModelBuilder createBlockModelBuilder(BlockState state) {
return new ForgeBlockModelBuilder(state);
}
@Override
public MultiBlockModelBuilder createMultiBlockModelBuilder(BlockAndTintGetter level, Iterable<BlockPos> positions) {
return new ForgeMultiBlockModelBuilder(level, positions);
}
@Override
@Nullable
public ShadersModHandler.InternalHandler createIrisHandler() {
if (!ModList.get()
.isLoaded("oculus")) {
return null;
}
return new ShadersModHandler.InternalHandler() {
@Override
public boolean isShaderPackInUse() {
return IrisApi.getInstance()
.isShaderPackInUse();
}
@Override
public boolean isRenderingShadowPass() {
return IrisApi.getInstance()
.isRenderingShadowPass();
}
};
}
}

View file

@ -1,41 +1,36 @@
package com.jozufozu.flywheel.impl; package com.jozufozu.flywheel.impl;
import java.util.ArrayList;
import org.apache.maven.artifact.versioning.ArtifactVersion; import org.apache.maven.artifact.versioning.ArtifactVersion;
import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.api.event.BeginFrameEvent;
import com.jozufozu.flywheel.api.event.EndClientResourceReloadEvent; import com.jozufozu.flywheel.api.event.EndClientResourceReloadEvent;
import com.jozufozu.flywheel.api.event.ReloadLevelRendererEvent; import com.jozufozu.flywheel.api.event.ReloadLevelRendererEvent;
import com.jozufozu.flywheel.api.visualization.VisualizationManager; import com.jozufozu.flywheel.api.event.RenderStageEvent;
import com.jozufozu.flywheel.backend.compile.FlwPrograms; import com.jozufozu.flywheel.backend.compile.FlwProgramsReloader;
import com.jozufozu.flywheel.backend.engine.uniform.Uniforms; import com.jozufozu.flywheel.backend.engine.uniform.Uniforms;
import com.jozufozu.flywheel.config.BackendArgument;
import com.jozufozu.flywheel.config.FlwCommands;
import com.jozufozu.flywheel.config.FlwConfig;
import com.jozufozu.flywheel.config.FlwForgeConfig;
import com.jozufozu.flywheel.impl.visualization.VisualizationEventHandler; import com.jozufozu.flywheel.impl.visualization.VisualizationEventHandler;
import com.jozufozu.flywheel.lib.memory.FlwMemoryTracker;
import com.jozufozu.flywheel.lib.model.ModelCache; import com.jozufozu.flywheel.lib.model.ModelCache;
import com.jozufozu.flywheel.lib.model.ModelHolder; import com.jozufozu.flywheel.lib.model.ModelHolder;
import com.jozufozu.flywheel.lib.model.baked.PartialModelEventHandler; import com.jozufozu.flywheel.lib.model.baked.PartialModelEventHandler;
import com.jozufozu.flywheel.lib.util.LevelAttached; import com.jozufozu.flywheel.lib.util.LevelAttached;
import com.jozufozu.flywheel.lib.util.StringUtil;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.commands.synchronization.ArgumentTypeInfos; import net.minecraft.commands.synchronization.ArgumentTypeInfos;
import net.minecraft.core.Vec3i;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.CustomizeGuiOverlayEvent; import net.minecraftforge.client.event.CustomizeGuiOverlayEvent;
import net.minecraftforge.client.event.RegisterClientReloadListenersEvent; import net.minecraftforge.client.event.RegisterClientReloadListenersEvent;
import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.TickEvent;
import net.minecraftforge.event.entity.EntityJoinLevelEvent;
import net.minecraftforge.event.entity.EntityLeaveLevelEvent;
import net.minecraftforge.event.level.LevelEvent; import net.minecraftforge.event.level.LevelEvent;
import net.minecraftforge.eventbus.api.IEventBus; import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.fml.CrashReportCallables; import net.minecraftforge.fml.CrashReportCallables;
import net.minecraftforge.fml.DistExecutor; import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.fml.LogicalSide;
import net.minecraftforge.fml.ModLoadingContext; import net.minecraftforge.fml.ModLoadingContext;
import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.event.lifecycle.FMLLoadCompleteEvent; import net.minecraftforge.fml.event.lifecycle.FMLLoadCompleteEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
@ -43,7 +38,7 @@ import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.RegisterEvent; import net.minecraftforge.registries.RegisterEvent;
@Mod(Flywheel.ID) @Mod(Flywheel.ID)
public class FlywheelForge { public final class FlywheelForge {
private static ArtifactVersion version; private static ArtifactVersion version;
public FlywheelForge() { public FlywheelForge() {
@ -57,89 +52,80 @@ public class FlywheelForge {
IEventBus forgeEventBus = MinecraftForge.EVENT_BUS; IEventBus forgeEventBus = MinecraftForge.EVENT_BUS;
IEventBus modEventBus = FMLJavaModLoadingContext.get() IEventBus modEventBus = FMLJavaModLoadingContext.get()
.getModEventBus(); .getModEventBus();
modEventBus.addListener(FlywheelForge::onCommonSetup);
modEventBus.addListener(FlywheelForge::onRegister);
FlwForgeConfig.INSTANCE.registerSpecs(modLoadingContext); ForgeFlwConfig.INSTANCE.registerSpecs(modLoadingContext);
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> FlywheelForge.clientInit(forgeEventBus, modEventBus)); DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> FlywheelForge.clientInit(forgeEventBus, modEventBus));
} }
private static void clientInit(IEventBus forgeEventBus, IEventBus modEventBus) { private static void clientInit(IEventBus forgeEventBus, IEventBus modEventBus) {
forgeEventBus.addListener(FlywheelForge::addDebugInfo); registerImplEventListeners(forgeEventBus, modEventBus);
registerLibEventListeners(forgeEventBus, modEventBus);
registerBackendEventListeners(forgeEventBus, modEventBus);
CrashReportCallables.registerCrashCallable("Flywheel Backend", BackendManagerImpl::getBackendString);
FlywheelInit.init();
}
private static void registerImplEventListeners(IEventBus forgeEventBus, IEventBus modEventBus) {
forgeEventBus.addListener((ReloadLevelRendererEvent e) -> BackendManagerImpl.onReloadLevelRenderer(e.level())); forgeEventBus.addListener((ReloadLevelRendererEvent e) -> BackendManagerImpl.onReloadLevelRenderer(e.level()));
forgeEventBus.addListener(VisualizationEventHandler::onClientTick); forgeEventBus.addListener((TickEvent.LevelTickEvent e) -> {
forgeEventBus.addListener(VisualizationEventHandler::onBeginFrame); // Make sure we don't tick on the server somehow.
forgeEventBus.addListener(VisualizationEventHandler::onRenderStage); if (e.phase == TickEvent.Phase.END && e.side == LogicalSide.CLIENT) {
forgeEventBus.addListener(VisualizationEventHandler::onEntityJoinLevel); VisualizationEventHandler.onClientTick(Minecraft.getInstance(), e.level);
forgeEventBus.addListener(VisualizationEventHandler::onEntityLeaveLevel); }
});
forgeEventBus.addListener((BeginFrameEvent e) -> VisualizationEventHandler.onBeginFrame(e.context()));
forgeEventBus.addListener((RenderStageEvent e) -> VisualizationEventHandler.onRenderStage(e.context(), e.stage()));
forgeEventBus.addListener((EntityJoinLevelEvent e) -> VisualizationEventHandler.onEntityJoinLevel(e.getLevel(), e.getEntity()));
forgeEventBus.addListener((EntityLeaveLevelEvent e) -> VisualizationEventHandler.onEntityLeaveLevel(e.getLevel(), e.getEntity()));
forgeEventBus.addListener(FlwCommands::registerClientCommands); forgeEventBus.addListener(FlwCommands::registerClientCommands);
forgeEventBus.addListener((EndClientResourceReloadEvent e) -> Uniforms.onReloadLevelRenderer()); forgeEventBus.addListener((CustomizeGuiOverlayEvent.DebugText e) -> {
Minecraft minecraft = Minecraft.getInstance();
forgeEventBus.addListener((LevelEvent.Unload e) -> LevelAttached.invalidateLevel(e.getLevel())); if (!minecraft.options.renderDebug) {
return;
}
modEventBus.addListener(FlywheelForge::registerClientReloadListeners); FlwDebugInfo.addDebugInfo(minecraft, e.getRight());
modEventBus.addListener(FlywheelForge::onClientSetup); });
modEventBus.addListener(FlywheelForge::onLoadComplete);
modEventBus.addListener((FMLLoadCompleteEvent e) -> FlywheelInit.freezeRegistries());
modEventBus.addListener((EndClientResourceReloadEvent e) -> BackendManagerImpl.onEndClientResourceReload(e.error().isPresent())); modEventBus.addListener((EndClientResourceReloadEvent e) -> BackendManagerImpl.onEndClientResourceReload(e.error().isPresent()));
modEventBus.addListener((FMLCommonSetupEvent e) -> {
ArgumentTypeInfos.registerByClass(BackendArgument.class, BackendArgument.INFO);
});
modEventBus.addListener((RegisterEvent e) -> {
if (e.getRegistryKey().equals(ForgeRegistries.Keys.COMMAND_ARGUMENT_TYPES)) {
e.register(ForgeRegistries.Keys.COMMAND_ARGUMENT_TYPES, Flywheel.rl("backend"), () -> BackendArgument.INFO);
}
});
}
private static void registerLibEventListeners(IEventBus forgeEventBus, IEventBus modEventBus) {
forgeEventBus.addListener((LevelEvent.Unload e) -> LevelAttached.invalidateLevel(e.getLevel()));
modEventBus.addListener((EndClientResourceReloadEvent e) -> ModelCache.onEndClientResourceReload()); modEventBus.addListener((EndClientResourceReloadEvent e) -> ModelCache.onEndClientResourceReload());
modEventBus.addListener((EndClientResourceReloadEvent e) -> ModelHolder.onEndClientResourceReload()); modEventBus.addListener((EndClientResourceReloadEvent e) -> ModelHolder.onEndClientResourceReload());
modEventBus.addListener(PartialModelEventHandler::onModelRegistry); modEventBus.addListener(PartialModelEventHandler::onRegisterAdditional);
modEventBus.addListener(PartialModelEventHandler::onModelBake); modEventBus.addListener(PartialModelEventHandler::onBakingCompleted);
Flywheel.earlyInit();
CrashReportCallables.registerCrashCallable("Flywheel Backend", BackendManagerImpl::getBackendString);
} }
private static void registerClientReloadListeners(RegisterClientReloadListenersEvent event) { private static void registerBackendEventListeners(IEventBus forgeEventBus, IEventBus modEventBus) {
event.registerReloadListener(FlwPrograms.ResourceReloadListener.INSTANCE); forgeEventBus.addListener((ReloadLevelRendererEvent e) -> Uniforms.onReloadLevelRenderer());
modEventBus.addListener((RegisterClientReloadListenersEvent e) -> {
e.registerReloadListener(FlwProgramsReloader.INSTANCE);
});
} }
private static void onClientSetup(FMLClientSetupEvent event) { public static ArtifactVersion version() {
Flywheel.init(); return version;
}
private static void onLoadComplete(FMLLoadCompleteEvent event) {
Flywheel.freeze();
}
private static void onCommonSetup(FMLCommonSetupEvent event) {
ArgumentTypeInfos.registerByClass(BackendArgument.class, BackendArgument.INFO);
}
private static void onRegister(RegisterEvent event) {
event.register(ForgeRegistries.Keys.COMMAND_ARGUMENT_TYPES, Flywheel.rl("backend"), () -> BackendArgument.INFO);
}
private static void addDebugInfo(CustomizeGuiOverlayEvent.DebugText event) {
Minecraft mc = Minecraft.getInstance();
if (!mc.options.renderDebug) {
return;
}
ArrayList<String> info = event.getRight();
info.add("");
info.add("Flywheel: " + version);
info.add("Backend: " + BackendManagerImpl.getBackendString());
info.add("Update limiting: " + (FlwConfig.get().limitUpdates() ? "on" : "off"));
VisualizationManager manager = VisualizationManager.get(mc.level);
if (manager != null) {
info.add("B: " + manager.getBlockEntities().getVisualCount()
+ ", E: " + manager.getEntities().getVisualCount()
+ ", F: " + manager.getEffects().getVisualCount());
Vec3i renderOrigin = manager.getRenderOrigin();
info.add("Origin: " + renderOrigin.getX() + ", " + renderOrigin.getY() + ", " + renderOrigin.getZ());
}
info.add("Memory Usage: CPU: " + StringUtil.formatBytes(FlwMemoryTracker.getCPUMemory()) + ", GPU: " + StringUtil.formatBytes(FlwMemoryTracker.getGPUMemory()));
} }
} }

View file

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.config; package com.jozufozu.flywheel.impl;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@ -14,19 +14,20 @@ import net.minecraftforge.common.ForgeConfigSpec;
import net.minecraftforge.fml.ModLoadingContext; import net.minecraftforge.fml.ModLoadingContext;
import net.minecraftforge.fml.config.ModConfig; import net.minecraftforge.fml.config.ModConfig;
public class FlwForgeConfig implements FlwConfig { public class ForgeFlwConfig implements FlwConfig {
private static final Logger LOGGER = LogUtils.getLogger(); private static final Logger LOGGER = LogUtils.getLogger();
public static final FlwForgeConfig INSTANCE = new FlwForgeConfig(); public static final ForgeFlwConfig INSTANCE = new ForgeFlwConfig();
public final ClientConfig client; public final ClientConfig client;
private final ForgeConfigSpec clientSpec; private final ForgeConfigSpec clientSpec;
private FlwForgeConfig() { private ForgeFlwConfig() {
Pair<ClientConfig, ForgeConfigSpec> clientPair = new ForgeConfigSpec.Builder().configure(ClientConfig::new); Pair<ClientConfig, ForgeConfigSpec> clientPair = new ForgeConfigSpec.Builder().configure(ClientConfig::new);
this.client = clientPair.getLeft(); this.client = clientPair.getLeft();
clientSpec = clientPair.getRight(); clientSpec = clientPair.getRight();
} }
@Override
public Backend backend() { public Backend backend() {
Backend backend = parseBackend(client.backend.get()); Backend backend = parseBackend(client.backend.get());
if (backend == null) { if (backend == null) {
@ -56,10 +57,12 @@ public class FlwForgeConfig implements FlwConfig {
return backend; return backend;
} }
@Override
public boolean limitUpdates() { public boolean limitUpdates() {
return client.limitUpdates.get(); return client.limitUpdates.get();
} }
@Override
public int workerThreads() { public int workerThreads() {
return client.workerThreads.get(); return client.workerThreads.get();
} }

View file

@ -1,80 +0,0 @@
package com.jozufozu.flywheel.impl.visualization;
import com.jozufozu.flywheel.api.event.BeginFrameEvent;
import com.jozufozu.flywheel.api.event.RenderStageEvent;
import com.jozufozu.flywheel.api.visualization.VisualizationManager;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.world.level.Level;
import net.minecraftforge.event.TickEvent;
import net.minecraftforge.event.entity.EntityJoinLevelEvent;
import net.minecraftforge.event.entity.EntityLeaveLevelEvent;
import net.minecraftforge.fml.LogicalSide;
// TODO: fabric event handler
public final class VisualizationEventHandler {
private VisualizationEventHandler() {
}
public static void onClientTick(TickEvent.LevelTickEvent event) {
// Make sure we don't tick on the server somehow.
if (event.phase != TickEvent.Phase.END || event.side != LogicalSide.CLIENT) {
return;
}
// The game won't be paused in the tick event, but let's make sure there's a player.
if (Minecraft.getInstance().player == null) {
return;
}
VisualizationManagerImpl manager = VisualizationManagerImpl.get(event.level);
if (manager == null) {
return;
}
manager.tick();
}
public static void onBeginFrame(BeginFrameEvent event) {
ClientLevel level = event.context()
.level();
VisualizationManagerImpl manager = VisualizationManagerImpl.get(level);
if (manager == null) {
return;
}
manager.beginFrame(event.context());
}
public static void onRenderStage(RenderStageEvent event) {
ClientLevel level = event.context()
.level();
VisualizationManagerImpl manager = VisualizationManagerImpl.get(level);
if (manager == null) {
return;
}
manager.renderStage(event.context(), event.stage());
}
public static void onEntityJoinLevel(EntityJoinLevelEvent event) {
Level level = event.getLevel();
VisualizationManager manager = VisualizationManager.get(level);
if (manager == null) {
return;
}
manager.getEntities().queueAdd(event.getEntity());
}
public static void onEntityLeaveLevel(EntityLeaveLevelEvent event) {
Level level = event.getLevel();
VisualizationManager manager = VisualizationManager.get(level);
if (manager == null) {
return;
}
manager.getEntities().queueRemove(event.getEntity());
}
}

View file

@ -1,9 +1,19 @@
package com.jozufozu.flywheel.lib.model.baked; package com.jozufozu.flywheel.lib.model.baked;
import java.util.Map;
import org.jetbrains.annotations.ApiStatus;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.client.event.ModelEvent; import net.minecraftforge.client.event.ModelEvent;
public class PartialModelEventHandler { @ApiStatus.Internal
public static void onModelRegistry(ModelEvent.RegisterAdditional event) { public final class PartialModelEventHandler {
private PartialModelEventHandler() {
}
public static void onRegisterAdditional(ModelEvent.RegisterAdditional event) {
for (PartialModel partial : PartialModel.ALL) { for (PartialModel partial : PartialModel.ALL) {
event.register(partial.getLocation()); event.register(partial.getLocation());
} }
@ -11,10 +21,11 @@ public class PartialModelEventHandler {
PartialModel.tooLate = true; PartialModel.tooLate = true;
} }
public static void onModelBake(ModelEvent.BakingCompleted event) { public static void onBakingCompleted(ModelEvent.BakingCompleted event) {
var modelRegistry = event.getModels(); Map<ResourceLocation, BakedModel> models = event.getModels();
for (PartialModel partial : PartialModel.ALL) { for (PartialModel partial : PartialModel.ALL) {
partial.set(modelRegistry.get(partial.getLocation())); partial.set(models.get(partial.getLocation()));
} }
} }
} }

View file

@ -1,125 +0,0 @@
package com.jozufozu.flywheel.platform;
import java.lang.reflect.Field;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import com.jozufozu.flywheel.api.event.BeginFrameEvent;
import com.jozufozu.flywheel.api.event.ReloadLevelRendererEvent;
import com.jozufozu.flywheel.api.event.RenderContext;
import com.jozufozu.flywheel.api.event.RenderStage;
import com.jozufozu.flywheel.api.event.RenderStageEvent;
import com.jozufozu.flywheel.config.FlwConfig;
import com.jozufozu.flywheel.config.FlwForgeConfig;
import com.jozufozu.flywheel.lib.model.baked.BakedModelBuilder;
import com.jozufozu.flywheel.lib.model.baked.BlockModelBuilder;
import com.jozufozu.flywheel.lib.model.baked.ForgeBakedModelBuilder;
import com.jozufozu.flywheel.lib.model.baked.ForgeBlockModelBuilder;
import com.jozufozu.flywheel.lib.model.baked.ForgeMultiBlockModelBuilder;
import com.jozufozu.flywheel.lib.model.baked.MultiBlockModelBuilder;
import com.jozufozu.flywheel.lib.util.ShadersModHandler;
import com.mojang.logging.LogUtils;
import net.irisshaders.iris.api.v0.IrisApi;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.renderer.block.BlockRenderDispatcher;
import net.minecraft.client.renderer.block.ModelBlockRenderer;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.BlockAndTintGetter;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.ModList;
import net.minecraftforge.fml.util.ObfuscationReflectionHelper;
public class ClientPlatformImpl implements ClientPlatform {
private static final Logger LOGGER = LogUtils.getLogger();
@Override
public void dispatchReloadLevelRenderer(ClientLevel level) {
MinecraftForge.EVENT_BUS.post(new ReloadLevelRendererEvent(level));
}
@Override
public void dispatchBeginFrame(RenderContext context) {
MinecraftForge.EVENT_BUS.post(new BeginFrameEvent(context));
}
@Override
public void dispatchRenderStage(RenderContext context, RenderStage stage) {
MinecraftForge.EVENT_BUS.post(new RenderStageEvent(context, stage));
}
@Override
public boolean isModLoaded(String modid) {
return ModList.get()
.isLoaded(modid);
}
@Override
@Nullable
public ShadersModHandler.InternalHandler createIrisOculusHandlerIfPresent() {
if (isModLoaded("oculus")) {
return new ShadersModHandler.InternalHandler() {
@Override
public boolean isShaderPackInUse() {
return IrisApi.getInstance()
.isShaderPackInUse();
}
@Override
public boolean isRenderingShadowPass() {
return IrisApi.getInstance()
.isRenderingShadowPass();
}
};
} else {
return null;
}
}
@Override
public int getLightEmission(BlockState state, BlockGetter level, BlockPos pos) {
return state.getLightEmission(level, pos);
}
@Override
public FlwConfig getConfigInstance() {
return FlwForgeConfig.INSTANCE;
}
@Override
public BlockRenderDispatcher createVanillaRenderer() {
BlockRenderDispatcher defaultDispatcher = Minecraft.getInstance().getBlockRenderer();
BlockRenderDispatcher dispatcher = new BlockRenderDispatcher(null, null, null);
try {
for (Field field : BlockRenderDispatcher.class.getDeclaredFields()) {
field.setAccessible(true);
field.set(dispatcher, field.get(defaultDispatcher));
}
ObfuscationReflectionHelper.setPrivateValue(BlockRenderDispatcher.class, dispatcher, new ModelBlockRenderer(Minecraft.getInstance().getBlockColors()), "f_110900_");
} catch (Exception e) {
LOGGER.error("Failed to initialize vanilla BlockRenderDispatcher!", e);
return defaultDispatcher;
}
return dispatcher;
}
@Override
public BakedModelBuilder bakedModelBuilder(BakedModel bakedModel) {
return new ForgeBakedModelBuilder(bakedModel);
}
@Override
public BlockModelBuilder blockModelBuilder(BlockState state) {
return new ForgeBlockModelBuilder(state);
}
@Override
public MultiBlockModelBuilder multiBlockModelBuilder(BlockAndTintGetter level, Iterable<BlockPos> positions) {
return new ForgeMultiBlockModelBuilder(level, positions);
}
}

View file

@ -15,7 +15,7 @@ mod_homepage = https://github.com/Jozufozu/Flywheel
# Mod dependency declarations # Mod dependency declarations
minecraft_semver_version_range = >=1.20.1 <1.20.2 minecraft_semver_version_range = >=1.20.1 <1.20.2
minecraft_maven_version_range = [1.20.1,1.20.2) minecraft_maven_version_range = [1.20.1,1.20.2)
fabric_api_version_range = >=0.84.0 fabric_api_version_range = >=0.86.0
forge_version_range = [47.0.0,) forge_version_range = [47.0.0,)
# General build dependency versions # General build dependency versions