Streamlined internal referencing

- Remove all references to impl from api and lib packages; all internal
interaction with impl now goes through InternalFlywheelApi
- Separate and organize backend and impl mixins and extensions
- Remove camera position component getters from VisualFrameContext
- Improve accuracy of fog data update detection
- Make PoseTransformStack.stack private and add unwrap method
- Rename BackendManager.isOn -> isBackendOn (and associated methods in
other classes)
This commit is contained in:
PepperCode1 2024-01-28 15:27:02 -08:00
parent 9ab8559efe
commit 55254a6876
60 changed files with 552 additions and 384 deletions

View File

@ -94,8 +94,9 @@ test {
mixin { mixin {
add sourceSets.main, 'flywheel.refmap.json' add sourceSets.main, 'flywheel.refmap.json'
config 'flywheel.mixins.json' config 'flywheel.backend.mixins.json'
config 'flywheel.sodium.mixins.json' config 'flywheel.impl.mixins.json'
config 'flywheel.impl.sodium.mixins.json'
debug.verbose = true debug.verbose = true
debug.export = true debug.export = true

View File

@ -16,8 +16,8 @@ import com.jozufozu.flywheel.config.BackendArgument;
import com.jozufozu.flywheel.config.FlwCommands; import com.jozufozu.flywheel.config.FlwCommands;
import com.jozufozu.flywheel.config.FlwConfig; import com.jozufozu.flywheel.config.FlwConfig;
import com.jozufozu.flywheel.impl.BackendManagerImpl; import com.jozufozu.flywheel.impl.BackendManagerImpl;
import com.jozufozu.flywheel.impl.IdRegistryImpl; import com.jozufozu.flywheel.impl.registry.IdRegistryImpl;
import com.jozufozu.flywheel.impl.RegistryImpl; import com.jozufozu.flywheel.impl.registry.RegistryImpl;
import com.jozufozu.flywheel.impl.visualization.VisualizationEventHandler; import com.jozufozu.flywheel.impl.visualization.VisualizationEventHandler;
import com.jozufozu.flywheel.lib.context.Contexts; import com.jozufozu.flywheel.lib.context.Contexts;
import com.jozufozu.flywheel.lib.instance.InstanceTypes; import com.jozufozu.flywheel.lib.instance.InstanceTypes;

View File

@ -1,15 +1,15 @@
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.registry.IdRegistry; import com.jozufozu.flywheel.api.registry.IdRegistry;
import com.jozufozu.flywheel.impl.IdRegistryImpl;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.LevelAccessor;
@BackendImplemented @BackendImplemented
public interface Backend { public interface Backend {
static IdRegistry<Backend> REGISTRY = IdRegistryImpl.create(); static IdRegistry<Backend> REGISTRY = InternalFlywheelApi.INSTANCE.createIdRegistry();
/** /**
* Get a message to display to the user when the engine is enabled. * Get a message to display to the user when the engine is enabled.

View File

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

View File

@ -1,13 +1,13 @@
package com.jozufozu.flywheel.api.context; package com.jozufozu.flywheel.api.context;
import com.jozufozu.flywheel.api.internal.InternalFlywheelApi;
import com.jozufozu.flywheel.api.registry.Registry; import com.jozufozu.flywheel.api.registry.Registry;
import com.jozufozu.flywheel.backend.gl.shader.GlProgram; import com.jozufozu.flywheel.backend.gl.shader.GlProgram;
import com.jozufozu.flywheel.impl.RegistryImpl;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
public interface Context { public interface Context {
static Registry<Context> REGISTRY = RegistryImpl.create(); static Registry<Context> REGISTRY = InternalFlywheelApi.INSTANCE.createRegistry();
void onProgramLink(GlProgram program); void onProgramLink(GlProgram program);

View File

@ -1,8 +1,8 @@
package com.jozufozu.flywheel.api.instance; package com.jozufozu.flywheel.api.instance;
import com.jozufozu.flywheel.api.internal.InternalFlywheelApi;
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;
import com.jozufozu.flywheel.impl.RegistryImpl;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
@ -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 = RegistryImpl.create(); static Registry<InstanceType<?>> REGISTRY = InternalFlywheelApi.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

@ -0,0 +1,99 @@
package com.jozufozu.flywheel.api.internal;
import java.lang.reflect.Constructor;
import org.jetbrains.annotations.Nullable;
import com.jozufozu.flywheel.api.backend.Backend;
import com.jozufozu.flywheel.api.layout.LayoutBuilder;
import com.jozufozu.flywheel.api.registry.IdRegistry;
import com.jozufozu.flywheel.api.registry.Registry;
import com.jozufozu.flywheel.api.vertex.VertexViewProvider;
import com.jozufozu.flywheel.api.visualization.BlockEntityVisualizer;
import com.jozufozu.flywheel.api.visualization.EntityVisualizer;
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 net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
public interface InternalFlywheelApi {
InternalFlywheelApi INSTANCE = load();
// Adapted from https://github.com/CaffeineMC/sodium-fabric/blob/bf4fc9dab16e1cca07b2f23a1201c9bf237c8044/src/api/java/net/caffeinemc/mods/sodium/api/internal/DependencyInjection.java
private static InternalFlywheelApi load() {
Class<InternalFlywheelApi> apiClass = InternalFlywheelApi.class;
Class<?> implClass;
try {
implClass = Class.forName("com.jozufozu.flywheel.impl.InternalFlywheelImpl");
} catch (ReflectiveOperationException e) {
throw new RuntimeException("Could not find implementation", e);
}
if (!apiClass.isAssignableFrom(implClass)) {
throw new RuntimeException("Class %s does not implement interface %s"
.formatted(implClass.getName(), apiClass.getName()));
}
Constructor<?> implConstructor;
try {
implConstructor = implClass.getConstructor();
} catch (ReflectiveOperationException e) {
throw new RuntimeException("Could not find default constructor", e);
}
Object implInstance;
try {
implInstance = implConstructor.newInstance();
} catch (ReflectiveOperationException e) {
throw new RuntimeException("Could not instantiate implementation", e);
}
return apiClass.cast(implInstance);
}
<T> Registry<T> createRegistry();
<T> IdRegistry<T> createIdRegistry();
Backend getBackend();
boolean isBackendOn();
Backend getOffBackend();
Backend getDefaultBackend();
LayoutBuilder createLayoutBuilder();
VertexViewProvider getVertexViewProvider(VertexFormat format);
void setVertexViewProvider(VertexFormat format, VertexViewProvider provider);
boolean supportsVisualization(@Nullable LevelAccessor level);
@Nullable
VisualizationManager getVisualizationManager(@Nullable LevelAccessor level);
VisualizationManager getVisualizationManagerOrThrow(@Nullable LevelAccessor level);
@Nullable
<T extends BlockEntity> BlockEntityVisualizer<? super T> getVisualizer(BlockEntityType<T> type);
@Nullable
<T extends Entity> EntityVisualizer<? super T> getVisualizer(EntityType<T> type);
<T extends BlockEntity> void setVisualizer(BlockEntityType<T> type, BlockEntityVisualizer<? super T> visualizer);
<T extends Entity> void setVisualizer(EntityType<T> type, EntityVisualizer<? super T> visualizer);
PoseTransformStack getPoseTransformStackOf(PoseStack stack);
}

View File

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

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.impl.layout.LayoutBuilderImpl; import com.jozufozu.flywheel.api.internal.InternalFlywheelApi;
@ApiStatus.NonExtendable @ApiStatus.NonExtendable
public interface LayoutBuilder { public interface LayoutBuilder {
@ -18,6 +18,6 @@ public interface LayoutBuilder {
Layout build(); Layout build();
static LayoutBuilder create() { static LayoutBuilder create() {
return new LayoutBuilderImpl(); return InternalFlywheelApi.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.registry.Registry; import com.jozufozu.flywheel.api.registry.Registry;
import com.jozufozu.flywheel.impl.RegistryImpl;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
public interface CutoutShader { public interface CutoutShader {
static Registry<CutoutShader> REGISTRY = RegistryImpl.create(); static Registry<CutoutShader> REGISTRY = InternalFlywheelApi.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.registry.Registry; import com.jozufozu.flywheel.api.registry.Registry;
import com.jozufozu.flywheel.impl.RegistryImpl;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
public interface FogShader { public interface FogShader {
static Registry<FogShader> REGISTRY = RegistryImpl.create(); static Registry<FogShader> REGISTRY = InternalFlywheelApi.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.registry.Registry; import com.jozufozu.flywheel.api.registry.Registry;
import com.jozufozu.flywheel.impl.RegistryImpl;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
public interface MaterialShaders { public interface MaterialShaders {
static Registry<MaterialShaders> REGISTRY = RegistryImpl.create(); static Registry<MaterialShaders> REGISTRY = InternalFlywheelApi.INSTANCE.createRegistry();
ResourceLocation vertexShader(); ResourceLocation vertexShader();

View File

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

View File

@ -7,17 +7,11 @@ import net.minecraft.client.Camera;
@ApiStatus.NonExtendable @ApiStatus.NonExtendable
public interface VisualFrameContext { public interface VisualFrameContext {
double cameraX(); Camera camera();
double cameraY();
double cameraZ();
FrustumIntersection frustum(); FrustumIntersection frustum();
float partialTick(); float partialTick();
DistanceUpdateLimiter limiter(); DistanceUpdateLimiter limiter();
Camera camera();
} }

View File

@ -3,9 +3,9 @@ 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.visual.Effect; import com.jozufozu.flywheel.api.visual.Effect;
import com.jozufozu.flywheel.api.visual.Visual; import com.jozufozu.flywheel.api.visual.Visual;
import com.jozufozu.flywheel.impl.visualization.VisualizationManagerImpl;
import net.minecraft.core.Vec3i; import net.minecraft.core.Vec3i;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
@ -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 VisualizationManagerImpl.supportsVisualization(level); return InternalFlywheelApi.INSTANCE.supportsVisualization(level);
} }
@Nullable @Nullable
static VisualizationManager get(@Nullable LevelAccessor level) { static VisualizationManager get(@Nullable LevelAccessor level) {
return VisualizationManagerImpl.get(level); return InternalFlywheelApi.INSTANCE.getVisualizationManager(level);
} }
static VisualizationManager getOrThrow(@Nullable LevelAccessor level) { static VisualizationManager getOrThrow(@Nullable LevelAccessor level) {
return VisualizationManagerImpl.getOrThrow(level); return InternalFlywheelApi.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.impl.visualization.VisualizerRegistryImpl; import com.jozufozu.flywheel.api.internal.InternalFlywheelApi;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.EntityType;
@ -10,9 +10,12 @@ import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.entity.BlockEntityType;
/** /**
* A utility class for registering and retrieving {@code Visualizer}s. * The registry for {@code Visualizer}s.
*/ */
public final class VisualizerRegistry { public final class VisualizerRegistry {
private VisualizerRegistry() {
}
/** /**
* Gets the visualizer for the given block entity type, if one exists. * Gets the visualizer for the given block entity type, if one exists.
* @param type The block entity type to get the visualizer for. * @param type The block entity type to get the visualizer for.
@ -21,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 VisualizerRegistryImpl.getVisualizer(type); return InternalFlywheelApi.INSTANCE.getVisualizer(type);
} }
/** /**
@ -32,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 VisualizerRegistryImpl.getVisualizer(type); return InternalFlywheelApi.INSTANCE.getVisualizer(type);
} }
/** /**
@ -42,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) {
VisualizerRegistryImpl.setVisualizer(type, visualizer); InternalFlywheelApi.INSTANCE.setVisualizer(type, visualizer);
} }
/** /**
@ -52,9 +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) {
VisualizerRegistryImpl.setVisualizer(type, visualizer); InternalFlywheelApi.INSTANCE.setVisualizer(type, visualizer);
}
private VisualizerRegistry() {
} }
} }

View File

@ -2,6 +2,7 @@ package com.jozufozu.flywheel.backend.engine.uniform;
import com.jozufozu.flywheel.api.event.ReloadLevelRendererEvent; import com.jozufozu.flywheel.api.event.ReloadLevelRendererEvent;
import com.jozufozu.flywheel.api.event.RenderContext; import com.jozufozu.flywheel.api.event.RenderContext;
import com.jozufozu.flywheel.backend.gl.GlStateTracker;
public class Uniforms { public class Uniforms {
public static boolean frustumPaused = false; public static boolean frustumPaused = false;
@ -28,15 +29,21 @@ public class Uniforms {
bindFog(); bindFog();
} }
public static void bindFrame() {
if (frame != null) {
frame.bind();
}
}
public static void bindFog() { public static void bindFog() {
if (fog != null) { if (fog != null) {
fog.bind(); fog.bind();
} }
} }
public static void bindFrame() { public static void onFogUpdate() {
if (frame != null) { try (var restoreState = GlStateTracker.getRestoreState()) {
frame.bind(); fog().update();
} }
} }

View File

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.mixin; package com.jozufozu.flywheel.backend.mixin;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;

View File

@ -0,0 +1,32 @@
package com.jozufozu.flywheel.backend.mixin;
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.backend.engine.uniform.Uniforms;
import com.mojang.blaze3d.systems.RenderSystem;
@Mixin(RenderSystem.class)
abstract class RenderSystemMixin {
@Inject(method = "setShaderFogStart(F)V", at = @At("RETURN"))
private static void flywheel$onSetFogStart(CallbackInfo ci) {
Uniforms.onFogUpdate();
}
@Inject(method = "setShaderFogEnd(F)V", at = @At("RETURN"))
private static void flywheel$onSetFogEnd(CallbackInfo ci) {
Uniforms.onFogUpdate();
}
@Inject(method = "setShaderFogShape(Lcom/mojang/blaze3d/shaders/FogShape;)V", at = @At("RETURN"))
private static void flywheel$onSetFogShape(CallbackInfo ci) {
Uniforms.onFogUpdate();
}
@Inject(method = "setShaderFogColor(FFFF)V", at = @At("RETURN"))
private static void flywheel$onSetFogColor(CallbackInfo ci) {
Uniforms.onFogUpdate();
}
}

View File

@ -21,7 +21,7 @@ import net.minecraftforge.fml.CrashReportCallables;
public final class BackendManagerImpl { public final class BackendManagerImpl {
private static final Logger LOGGER = LogUtils.getLogger(); private static final Logger LOGGER = LogUtils.getLogger();
private static final Backend OFF_BACKEND = SimpleBackend.builder() public static final Backend OFF_BACKEND = SimpleBackend.builder()
.engineMessage(Component.literal("Disabled Flywheel") .engineMessage(Component.literal("Disabled Flywheel")
.withStyle(ChatFormatting.RED)) .withStyle(ChatFormatting.RED))
.engineFactory(level -> { .engineFactory(level -> {
@ -30,7 +30,7 @@ public final class BackendManagerImpl {
.supported(() -> true) .supported(() -> true)
.register(Flywheel.rl("off")); .register(Flywheel.rl("off"));
private static final Backend DEFAULT_BACKEND = findDefaultBackend(); public static final Backend DEFAULT_BACKEND = findDefaultBackend();
private static Backend backend = OFF_BACKEND; private static Backend backend = OFF_BACKEND;
@ -41,18 +41,10 @@ public final class BackendManagerImpl {
return backend; return backend;
} }
public static boolean isOn() { public static boolean isBackendOn() {
return backend != OFF_BACKEND; return backend != OFF_BACKEND;
} }
public static Backend getOffBackend() {
return OFF_BACKEND;
}
public static Backend getDefaultBackend() {
return DEFAULT_BACKEND;
}
private static Backend findDefaultBackend() { private static Backend findDefaultBackend() {
// TODO: Automatically select the best default config based on the user's driver // TODO: Automatically select the best default config based on the user's driver
// TODO: Figure out how this will work if custom backends are registered and without hardcoding the default backends // TODO: Figure out how this will work if custom backends are registered and without hardcoding the default backends

View File

@ -0,0 +1,119 @@
package com.jozufozu.flywheel.impl;
import org.jetbrains.annotations.Nullable;
import com.jozufozu.flywheel.api.backend.Backend;
import com.jozufozu.flywheel.api.internal.InternalFlywheelApi;
import com.jozufozu.flywheel.api.layout.LayoutBuilder;
import com.jozufozu.flywheel.api.registry.IdRegistry;
import com.jozufozu.flywheel.api.registry.Registry;
import com.jozufozu.flywheel.api.vertex.VertexViewProvider;
import com.jozufozu.flywheel.api.visualization.BlockEntityVisualizer;
import com.jozufozu.flywheel.api.visualization.EntityVisualizer;
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.registry.IdRegistryImpl;
import com.jozufozu.flywheel.impl.registry.RegistryImpl;
import com.jozufozu.flywheel.impl.vertex.VertexViewProviderRegistryImpl;
import com.jozufozu.flywheel.impl.visualization.VisualizationManagerImpl;
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 net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
public final class InternalFlywheelImpl implements InternalFlywheelApi {
@Override
public <T> Registry<T> createRegistry() {
return new RegistryImpl<>();
}
@Override
public <T> IdRegistry<T> createIdRegistry() {
return new IdRegistryImpl<>();
}
@Override
public Backend getBackend() {
return BackendManagerImpl.getBackend();
}
@Override
public boolean isBackendOn() {
return BackendManagerImpl.isBackendOn();
}
@Override
public Backend getOffBackend() {
return BackendManagerImpl.OFF_BACKEND;
}
@Override
public Backend getDefaultBackend() {
return BackendManagerImpl.DEFAULT_BACKEND;
}
@Override
public LayoutBuilder createLayoutBuilder() {
return new LayoutBuilderImpl();
}
@Override
public VertexViewProvider getVertexViewProvider(VertexFormat format) {
return VertexViewProviderRegistryImpl.getProvider(format);
}
@Override
public void setVertexViewProvider(VertexFormat format, VertexViewProvider provider) {
VertexViewProviderRegistryImpl.setProvider(format, provider);
}
@Override
public boolean supportsVisualization(@Nullable LevelAccessor level) {
return VisualizationManagerImpl.supportsVisualization(level);
}
@Override
@Nullable
public VisualizationManager getVisualizationManager(@Nullable LevelAccessor level) {
return VisualizationManagerImpl.get(level);
}
@Override
public VisualizationManager getVisualizationManagerOrThrow(@Nullable LevelAccessor level) {
return VisualizationManagerImpl.getOrThrow(level);
}
@Override
@Nullable
public <T extends BlockEntity> BlockEntityVisualizer<? super T> getVisualizer(BlockEntityType<T> type) {
return VisualizerRegistryImpl.getVisualizer(type);
}
@Override
@Nullable
public <T extends Entity> EntityVisualizer<? super T> getVisualizer(EntityType<T> type) {
return VisualizerRegistryImpl.getVisualizer(type);
}
@Override
public <T extends BlockEntity> void setVisualizer(BlockEntityType<T> type, BlockEntityVisualizer<? super T> visualizer) {
VisualizerRegistryImpl.setVisualizer(type, visualizer);
}
@Override
public <T extends Entity> void setVisualizer(EntityType<T> type, EntityVisualizer<? super T> visualizer) {
VisualizerRegistryImpl.setVisualizer(type, visualizer);
}
@Override
public PoseTransformStack getPoseTransformStackOf(PoseStack stack) {
return ((PoseStackExtension) stack).flywheel$transformStack();
}
}

View File

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.extension; package com.jozufozu.flywheel.impl.extension;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;

View File

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.extension; package com.jozufozu.flywheel.impl.extension;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;

View File

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.extension; package com.jozufozu.flywheel.impl.extension;
import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;

View File

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.extension; package com.jozufozu.flywheel.impl.extension;
import com.jozufozu.flywheel.lib.transform.PoseTransformStack; import com.jozufozu.flywheel.lib.transform.PoseTransformStack;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;

View File

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.extension; package com.jozufozu.flywheel.impl.extension;
import com.jozufozu.flywheel.api.vertex.VertexViewProvider; import com.jozufozu.flywheel.api.vertex.VertexViewProvider;
import com.mojang.blaze3d.vertex.VertexFormat; import com.mojang.blaze3d.vertex.VertexFormat;
@ -9,7 +9,6 @@ import com.mojang.blaze3d.vertex.VertexFormat;
* @see VertexFormat * @see VertexFormat
*/ */
public interface VertexFormatExtension { public interface VertexFormatExtension {
/** /**
* @return The VertexViewProvider associated with this VertexFormat. * @return The VertexViewProvider associated with this VertexFormat.
*/ */

View File

@ -1,11 +1,11 @@
package com.jozufozu.flywheel.mixin; package com.jozufozu.flywheel.impl.mixin;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.Unique;
import com.jozufozu.flywheel.api.visualization.BlockEntityVisualizer; import com.jozufozu.flywheel.api.visualization.BlockEntityVisualizer;
import com.jozufozu.flywheel.extension.BlockEntityTypeExtension; import com.jozufozu.flywheel.impl.extension.BlockEntityTypeExtension;
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;

View File

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.mixin; package com.jozufozu.flywheel.impl.mixin;
import java.util.ArrayList; import java.util.ArrayList;

View File

@ -1,11 +1,11 @@
package com.jozufozu.flywheel.mixin; package com.jozufozu.flywheel.impl.mixin;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.Unique;
import com.jozufozu.flywheel.api.visualization.EntityVisualizer; import com.jozufozu.flywheel.api.visualization.EntityVisualizer;
import com.jozufozu.flywheel.extension.EntityTypeExtension; import com.jozufozu.flywheel.impl.extension.EntityTypeExtension;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.EntityType;

View File

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.mixin; package com.jozufozu.flywheel.impl.mixin;
import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
@ -15,26 +15,28 @@ import net.minecraft.world.level.chunk.LightChunkGetter;
import net.minecraft.world.level.lighting.LayerLightSectionStorage; import net.minecraft.world.level.lighting.LayerLightSectionStorage;
@Mixin(LayerLightSectionStorage.class) @Mixin(LayerLightSectionStorage.class)
public abstract class LayerLightSectionStorageMixin { abstract class LayerLightSectionStorageMixin {
@Shadow
@Final
protected LightChunkGetter chunkSource;
@Shadow @Shadow
@Final @Final
protected LongSet sectionsAffectedByLightUpdates; protected LongSet sectionsAffectedByLightUpdates;
@Shadow @Inject(method = "swapSectionMap()V", at = @At("HEAD"))
@Final
protected LightChunkGetter chunkSource;
@Inject(at = @At("HEAD"), method = "swapSectionMap")
private void flywheel$listenForChangedSections(CallbackInfo ci) { private void flywheel$listenForChangedSections(CallbackInfo ci) {
if (this.sectionsAffectedByLightUpdates.isEmpty()) { if (sectionsAffectedByLightUpdates.isEmpty()) {
return; return;
} }
var manager = VisualizationManagerImpl.get((LevelAccessor) this.chunkSource.getLevel()); if (!(chunkSource.getLevel() instanceof LevelAccessor level)) {
return;
}
var manager = VisualizationManagerImpl.get(level);
if (manager != null) { if (manager != null) {
manager.enqueueLightUpdateSections(this.sectionsAffectedByLightUpdates); manager.enqueueLightUpdateSections(sectionsAffectedByLightUpdates);
} }
} }
} }

View File

@ -1,9 +1,9 @@
package com.jozufozu.flywheel.mixin; package com.jozufozu.flywheel.impl.mixin;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
import com.jozufozu.flywheel.extension.LevelExtension; import com.jozufozu.flywheel.impl.extension.LevelExtension;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;

View File

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.mixin; package com.jozufozu.flywheel.impl.mixin;
import java.util.SortedSet; import java.util.SortedSet;

View File

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.mixin; package com.jozufozu.flywheel.impl.mixin;
import java.util.Optional; import java.util.Optional;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;

View File

@ -1,9 +1,9 @@
package com.jozufozu.flywheel.mixin; package com.jozufozu.flywheel.impl.mixin;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.Unique;
import com.jozufozu.flywheel.extension.PoseStackExtension; import com.jozufozu.flywheel.impl.extension.PoseStackExtension;
import com.jozufozu.flywheel.lib.transform.PoseTransformStack; import com.jozufozu.flywheel.lib.transform.PoseTransformStack;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;

View File

@ -1,10 +1,10 @@
package com.jozufozu.flywheel.mixin; package com.jozufozu.flywheel.impl.mixin;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.Unique;
import com.jozufozu.flywheel.api.vertex.VertexViewProvider; import com.jozufozu.flywheel.api.vertex.VertexViewProvider;
import com.jozufozu.flywheel.extension.VertexFormatExtension; import com.jozufozu.flywheel.impl.extension.VertexFormatExtension;
import com.mojang.blaze3d.vertex.VertexFormat; import com.mojang.blaze3d.vertex.VertexFormat;
@Mixin(VertexFormat.class) @Mixin(VertexFormat.class)

View File

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.mixin.fix; package com.jozufozu.flywheel.impl.mixin.fix;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;

View File

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.mixin.fix; package com.jozufozu.flywheel.impl.mixin.fix;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;

View File

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.mixin.sodium; package com.jozufozu.flywheel.impl.mixin.sodium;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;

View File

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.compat; package com.jozufozu.flywheel.impl.mixin.sodium;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;

View File

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.mixin.visualmanage; package com.jozufozu.flywheel.impl.mixin.visualmanage;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
@ -13,7 +13,7 @@ import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntity;
@Mixin(BlockEntity.class) @Mixin(BlockEntity.class)
abstract class VisualRemoveMixin { abstract class BlockEntityMixin {
@Shadow @Shadow
@Nullable @Nullable
protected Level level; protected Level level;

View File

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.mixin.visualmanage; package com.jozufozu.flywheel.impl.mixin.visualmanage;
import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
@ -14,7 +14,7 @@ import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.chunk.LevelChunk;
@Mixin(LevelChunk.class) @Mixin(LevelChunk.class)
abstract class VisualAddMixin { abstract class LevelChunkMixin {
@Shadow @Shadow
@Final @Final
Level level; Level level;

View File

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.mixin.visualmanage; package com.jozufozu.flywheel.impl.mixin.visualmanage;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
@ -15,7 +15,7 @@ import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
@Mixin(LevelRenderer.class) @Mixin(LevelRenderer.class)
abstract class VisualUpdateMixin { abstract class LevelRendererMixin {
@Shadow @Shadow
private ClientLevel level; private ClientLevel level;

View File

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.mixin.visualmanage; package com.jozufozu.flywheel.impl.mixin.visualmanage;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
@ -11,7 +11,7 @@ import com.jozufozu.flywheel.impl.visualization.VisualizationHelper;
import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntity;
@Mixin(targets = "net.minecraft.client.renderer.chunk.ChunkRenderDispatcher$RenderChunk$RebuildTask") @Mixin(targets = "net.minecraft.client.renderer.chunk.ChunkRenderDispatcher$RenderChunk$RebuildTask")
abstract class ChunkRebuildHooksMixin { abstract class RebuildTaskMixin {
@Inject(method = "handleBlockEntity(Lnet/minecraft/client/renderer/chunk/ChunkRenderDispatcher$RenderChunk$RebuildTask$CompileResults;Lnet/minecraft/world/level/block/entity/BlockEntity;)V", at = @At("HEAD"), cancellable = true) @Inject(method = "handleBlockEntity(Lnet/minecraft/client/renderer/chunk/ChunkRenderDispatcher$RenderChunk$RebuildTask$CompileResults;Lnet/minecraft/world/level/block/entity/BlockEntity;)V", at = @At("HEAD"), cancellable = true)
private void flywheel$tryAddBlockEntity(@Coerce Object compileResults, BlockEntity blockEntity, CallbackInfo ci) { private void flywheel$tryAddBlockEntity(@Coerce Object compileResults, BlockEntity blockEntity, CallbackInfo ci) {
if (VisualizationHelper.tryAddBlockEntity(blockEntity)) { if (VisualizationHelper.tryAddBlockEntity(blockEntity)) {

View File

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.impl; package com.jozufozu.flywheel.impl.registry;
import java.util.Collection; import java.util.Collection;
import java.util.Iterator; import java.util.Iterator;
@ -31,14 +31,10 @@ public class IdRegistryImpl<T> implements IdRegistry<T> {
private final ObjectList<Runnable> freezeCallbacks = new ObjectArrayList<>(); private final ObjectList<Runnable> freezeCallbacks = new ObjectArrayList<>();
private boolean frozen; private boolean frozen;
private IdRegistryImpl() { public IdRegistryImpl() {
ALL.add(this); ALL.add(this);
} }
public static <T> IdRegistry<T> create() {
return new IdRegistryImpl<>();
}
@Override @Override
public void register(ResourceLocation id, T object) { public void register(ResourceLocation id, T object) {
if (frozen) { if (frozen) {

View File

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.impl; package com.jozufozu.flywheel.impl.registry;
import java.util.Iterator; import java.util.Iterator;
import java.util.Set; import java.util.Set;
@ -21,14 +21,10 @@ public class RegistryImpl<T> implements Registry<T> {
private final ObjectList<Runnable> freezeCallbacks = new ObjectArrayList<>(); private final ObjectList<Runnable> freezeCallbacks = new ObjectArrayList<>();
private boolean frozen; private boolean frozen;
private RegistryImpl() { public RegistryImpl() {
ALL.add(this); ALL.add(this);
} }
public static <T> Registry<T> create() {
return new RegistryImpl<>();
}
@Override @Override
public void register(T object) { public void register(T object) {
if (frozen) { if (frozen) {

View File

@ -1,11 +1,14 @@
package com.jozufozu.flywheel.impl.vertex; package com.jozufozu.flywheel.impl.vertex;
import com.jozufozu.flywheel.api.vertex.VertexViewProvider; import com.jozufozu.flywheel.api.vertex.VertexViewProvider;
import com.jozufozu.flywheel.extension.VertexFormatExtension; import com.jozufozu.flywheel.impl.extension.VertexFormatExtension;
import com.mojang.blaze3d.vertex.VertexFormat; import com.mojang.blaze3d.vertex.VertexFormat;
// TODO: Add freezing // TODO: Add freezing
public final class VertexListProviderRegistryImpl { public final class VertexViewProviderRegistryImpl {
private VertexViewProviderRegistryImpl() {
}
public static VertexViewProvider getProvider(VertexFormat format) { public static VertexViewProvider getProvider(VertexFormat format) {
VertexFormatExtension extension = (VertexFormatExtension) format; VertexFormatExtension extension = (VertexFormatExtension) format;
VertexViewProvider provider = extension.flywheel$getVertexViewProvider(); VertexViewProvider provider = extension.flywheel$getVertexViewProvider();
@ -19,7 +22,4 @@ public final class VertexListProviderRegistryImpl {
public static void setProvider(VertexFormat format, VertexViewProvider provider) { public static void setProvider(VertexFormat format, VertexViewProvider provider) {
((VertexFormatExtension) format).flywheel$setVertexViewProvider(provider); ((VertexFormatExtension) format).flywheel$setVertexViewProvider(provider);
} }
private VertexListProviderRegistryImpl() {
}
} }

View File

@ -7,7 +7,6 @@ import com.jozufozu.flywheel.api.visual.VisualFrameContext;
import net.minecraft.client.Camera; import net.minecraft.client.Camera;
public record VisualFrameContextImpl(double cameraX, double cameraY, double cameraZ, FrustumIntersection frustum, public record VisualFrameContextImpl(Camera camera, FrustumIntersection frustum,
float partialTick, DistanceUpdateLimiter limiter, float partialTick, DistanceUpdateLimiter limiter) implements VisualFrameContext {
Camera camera) implements VisualFrameContext {
} }

View File

@ -27,7 +27,7 @@ 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.config.FlwConfig;
import com.jozufozu.flywheel.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.VisualFrameContextImpl; import com.jozufozu.flywheel.impl.visual.VisualFrameContextImpl;
import com.jozufozu.flywheel.impl.visual.VisualTickContextImpl; import com.jozufozu.flywheel.impl.visual.VisualTickContextImpl;
@ -102,7 +102,9 @@ public class VisualizationManagerImpl implements VisualizationManager {
.then(RaisePlan.raise(tickFlag)) .then(RaisePlan.raise(tickFlag))
.simplify(); .simplify();
var recreate = SimplePlan.<RenderContext>of(context -> blockEntitiesStorage.recreateAll(context.partialTick()), context -> entitiesStorage.recreateAll(context.partialTick()), context -> effectsStorage.recreateAll(context.partialTick())); var recreate = SimplePlan.<RenderContext>of(context -> blockEntitiesStorage.recreateAll(context.partialTick()),
context -> entitiesStorage.recreateAll(context.partialTick()),
context -> effectsStorage.recreateAll(context.partialTick()));
var update = MapContextPlan.map(this::createVisualFrameContext) var update = MapContextPlan.map(this::createVisualFrameContext)
.to(NestedPlan.of(blockEntities.framePlan(), entities.framePlan(), effects.framePlan())); .to(NestedPlan.of(blockEntities.framePlan(), entities.framePlan(), effects.framePlan()));
@ -126,15 +128,12 @@ public class VisualizationManagerImpl implements VisualizationManager {
Vec3i renderOrigin = engine.renderOrigin(); Vec3i renderOrigin = engine.renderOrigin();
var cameraPos = ctx.camera() var cameraPos = ctx.camera()
.getPosition(); .getPosition();
double cameraX = cameraPos.x;
double cameraY = cameraPos.y;
double cameraZ = cameraPos.z;
Matrix4f viewProjection = new Matrix4f(ctx.viewProjection()); Matrix4f viewProjection = new Matrix4f(ctx.viewProjection());
viewProjection.translate((float) (renderOrigin.getX() - cameraX), (float) (renderOrigin.getY() - cameraY), (float) (renderOrigin.getZ() - cameraZ)); viewProjection.translate((float) (renderOrigin.getX() - cameraPos.x), (float) (renderOrigin.getY() - cameraPos.y), (float) (renderOrigin.getZ() - cameraPos.z));
FrustumIntersection frustum = new FrustumIntersection(viewProjection); FrustumIntersection frustum = new FrustumIntersection(viewProjection);
return new VisualFrameContextImpl(cameraX, cameraY, cameraZ, frustum, ctx.partialTick(), frameLimiter, ctx.camera()); return new VisualFrameContextImpl(ctx.camera(), frustum, ctx.partialTick(), frameLimiter);
} }
protected DistanceUpdateLimiterImpl createUpdateLimiter() { protected DistanceUpdateLimiterImpl createUpdateLimiter() {
@ -148,7 +147,7 @@ public class VisualizationManagerImpl implements VisualizationManager {
@Contract("null -> false") @Contract("null -> false")
public static boolean supportsVisualization(@Nullable LevelAccessor level) { public static boolean supportsVisualization(@Nullable LevelAccessor level) {
if (!BackendManager.isOn()) { if (!BackendManager.isBackendOn()) {
return false; return false;
} }
@ -186,10 +185,10 @@ public class VisualizationManagerImpl implements VisualizationManager {
// TODO: Consider making these reset actions reuse the existing game objects instead of re-adding them // TODO: Consider making these reset actions reuse the existing game objects instead of re-adding them
// potentially by keeping the same VisualizationManagerImpl and deleting the engine and visuals but not the game objects // potentially by keeping the same VisualizationManagerImpl and deleting the engine and visuals but not the game objects
public static void reset(LevelAccessor level) { public static void reset(LevelAccessor level) {
MANAGERS.remove(level); MANAGERS.remove(level);
} }
public static void resetAll() { public static void resetAll() {
MANAGERS.reset(); MANAGERS.reset();
} }

View File

@ -4,8 +4,8 @@ import org.jetbrains.annotations.Nullable;
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.extension.BlockEntityTypeExtension; import com.jozufozu.flywheel.impl.extension.BlockEntityTypeExtension;
import com.jozufozu.flywheel.extension.EntityTypeExtension; import com.jozufozu.flywheel.impl.extension.EntityTypeExtension;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.EntityType;

View File

@ -7,8 +7,6 @@ import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
import org.jetbrains.annotations.NotNull;
import com.jozufozu.flywheel.api.task.Plan; import com.jozufozu.flywheel.api.task.Plan;
import com.jozufozu.flywheel.api.task.TaskExecutor; import com.jozufozu.flywheel.api.task.TaskExecutor;
import com.jozufozu.flywheel.api.visual.LitVisual; import com.jozufozu.flywheel.api.visual.LitVisual;
@ -161,7 +159,6 @@ public class LitVisualStorage {
return -1; return -1;
} }
@NotNull
private static Updater createUpdater(LitVisual visual, int sectionCount) { private static Updater createUpdater(LitVisual visual, int sectionCount) {
if (sectionCount == 1) { if (sectionCount == 1) {
return new Updater.Simple(visual); return new Updater.Simple(visual);

View File

@ -12,8 +12,8 @@ import com.mojang.blaze3d.vertex.PoseStack;
* <br> * <br>
* Only one instance of this class should exist per {@link PoseStack}. * Only one instance of this class should exist per {@link PoseStack}.
*/ */
public class PoseTransformStack implements TransformStack<PoseTransformStack> { public final class PoseTransformStack implements TransformStack<PoseTransformStack> {
public final PoseStack stack; private final PoseStack stack;
@ApiStatus.Internal @ApiStatus.Internal
public PoseTransformStack(PoseStack stack) { public PoseTransformStack(PoseStack stack) {
@ -71,4 +71,8 @@ public class PoseTransformStack implements TransformStack<PoseTransformStack> {
stack.translate(x, y, z); stack.translate(x, y, z);
return this; return this;
} }
public PoseStack unwrap() {
return stack;
}
} }

View File

@ -1,14 +1,14 @@
package com.jozufozu.flywheel.lib.transform; package com.jozufozu.flywheel.lib.transform;
import com.jozufozu.flywheel.extension.PoseStackExtension; import com.jozufozu.flywheel.api.internal.InternalFlywheelApi;
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) {
return InternalFlywheelApi.INSTANCE.getPoseTransformStackOf(stack);
}
Self pushPose(); Self pushPose();
Self popPose(); Self popPose();
static PoseTransformStack of(PoseStack stack) {
return ((PoseStackExtension) stack).flywheel$transformStack();
}
} }

View File

@ -107,6 +107,6 @@ public abstract class AbstractBlockEntityVisual<T extends BlockEntity> extends A
*/ */
public boolean doDistanceLimitThisFrame(VisualFrameContext context) { public boolean doDistanceLimitThisFrame(VisualFrameContext context) {
return !context.limiter() return !context.limiter()
.shouldUpdate(pos.distToCenterSqr(context.cameraX(), context.cameraY(), context.cameraZ())); .shouldUpdate(pos.distToCenterSqr(context.camera().getPosition()));
} }
} }

View File

@ -1,15 +1,10 @@
package com.jozufozu.flywheel.lib.visual; package com.jozufozu.flywheel.lib.visual;
import java.util.Map;
import org.joml.Vector4f; import org.joml.Vector4f;
import org.joml.Vector4fc; import org.joml.Vector4fc;
import com.google.common.collect.ImmutableMap;
import com.jozufozu.flywheel.api.event.RenderStage; import com.jozufozu.flywheel.api.event.RenderStage;
import com.jozufozu.flywheel.api.material.Material; import com.jozufozu.flywheel.api.material.Material;
import com.jozufozu.flywheel.api.model.Mesh;
import com.jozufozu.flywheel.api.model.Model;
import com.jozufozu.flywheel.api.vertex.MutableVertexList; import com.jozufozu.flywheel.api.vertex.MutableVertexList;
import com.jozufozu.flywheel.api.visual.VisualFrameContext; import com.jozufozu.flywheel.api.visual.VisualFrameContext;
import com.jozufozu.flywheel.api.visualization.VisualizationContext; import com.jozufozu.flywheel.api.visualization.VisualizationContext;
@ -19,11 +14,11 @@ import com.jozufozu.flywheel.lib.material.Materials;
import com.jozufozu.flywheel.lib.material.SimpleMaterial; import com.jozufozu.flywheel.lib.material.SimpleMaterial;
import com.jozufozu.flywheel.lib.model.ModelCache; import com.jozufozu.flywheel.lib.model.ModelCache;
import com.jozufozu.flywheel.lib.model.QuadMesh; import com.jozufozu.flywheel.lib.model.QuadMesh;
import com.jozufozu.flywheel.lib.model.SingleMeshModel;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.math.Axis; import com.mojang.math.Axis;
import net.minecraft.client.renderer.LightTexture; import net.minecraft.client.renderer.LightTexture;
import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.resources.model.ModelBakery; import net.minecraft.client.resources.model.ModelBakery;
import net.minecraft.util.Mth; import net.minecraft.util.Mth;
@ -33,6 +28,15 @@ import net.minecraft.world.entity.Entity;
* A component that uses instances to render the fire animation on an entity. * A component that uses instances to render the fire animation on an entity.
*/ */
public class FireComponent { public class FireComponent {
private static final Material FIRE_MATERIAL = SimpleMaterial.builderOf(Materials.CHUNK_CUTOUT_UNSHADED)
.backfaceCulling(false) // Disable backface because we want to be able to flip the model.
.build();
// Parameterize by the material instead of the sprite
// because Material#sprite is a surprisingly heavy operation.
private static final ModelCache<net.minecraft.client.resources.model.Material> FIRE_MODELS = new ModelCache<>(texture -> {
return new SingleMeshModel(new FireMesh(texture.sprite()), FIRE_MATERIAL);
});
private final VisualizationContext context; private final VisualizationContext context;
private final Entity entity; private final Entity entity;
private final PoseStack stack = new PoseStack(); private final PoseStack stack = new PoseStack();
@ -44,12 +48,17 @@ public class FireComponent {
this.context = context; this.context = context;
this.entity = entity; this.entity = entity;
fire0 = new InstanceRecycler<>(() -> context.instancerProvider() fire0 = new InstanceRecycler<>(() -> createInstance(ModelBakery.FIRE_0));
.instancer(InstanceTypes.TRANSFORMED, FireModel.CACHE.get(ModelBakery.FIRE_0), RenderStage.AFTER_BLOCK_ENTITIES) fire1 = new InstanceRecycler<>(() -> createInstance(ModelBakery.FIRE_1));
.createInstance()); }
fire1 = new InstanceRecycler<>(() -> context.instancerProvider()
.instancer(InstanceTypes.TRANSFORMED, FireModel.CACHE.get(ModelBakery.FIRE_1), RenderStage.AFTER_BLOCK_ENTITIES) private TransformedInstance createInstance(net.minecraft.client.resources.model.Material texture) {
.createInstance()); TransformedInstance instance = context.instancerProvider()
.instancer(InstanceTypes.TRANSFORMED, FIRE_MODELS.get(texture), RenderStage.AFTER_ENTITIES)
.createInstance();
instance.setBlockLight(LightTexture.block(LightTexture.FULL_BLOCK));
instance.setChanged();
return instance;
} }
/** /**
@ -100,8 +109,6 @@ public class FireComponent {
instance.scaleX(-1); instance.scaleX(-1);
} }
instance.setBlockLight(LightTexture.block(240));
instance.setChanged(); instance.setChanged();
y += 0.45F; y += 0.45F;
@ -117,25 +124,24 @@ public class FireComponent {
fire1.delete(); fire1.delete();
} }
private static class FireModel implements Model { private record FireMesh(TextureAtlasSprite sprite) implements QuadMesh {
// Parameterize by the material instead of the sprite
// because Material#sprite is a surprisingly heavy operation.
public static final ModelCache<net.minecraft.client.resources.model.Material> CACHE = new ModelCache<>(mat -> new FireModel(mat.sprite()));
public static final Material MATERIAL = SimpleMaterial.builderOf(Materials.CHUNK_CUTOUT_UNSHADED)
.backfaceCulling(false) // Disable backface because we want to be able to flip the model.
.build();
private static final Vector4fc BOUNDING_SPHERE = new Vector4f(0, 0.5f, 0, (float) (Math.sqrt(2) * 0.5)); private static final Vector4fc BOUNDING_SPHERE = new Vector4f(0, 0.5f, 0, (float) (Math.sqrt(2) * 0.5));
private final ImmutableMap<Material, Mesh> meshes; @Override
public int vertexCount() {
private FireModel(TextureAtlasSprite sprite) { return 4;
meshes = ImmutableMap.of(MATERIAL, new FireMesh(sprite));
} }
@Override @Override
public Map<Material, Mesh> meshes() { public void write(MutableVertexList vertexList) {
return meshes; float u0 = sprite.getU0();
float v0 = sprite.getV0();
float u1 = sprite.getU1();
float v1 = sprite.getV1();
writeVertex(vertexList, 0, 0.5f, 0, u1, v1);
writeVertex(vertexList, 1, -0.5f, 0, u0, v1);
writeVertex(vertexList, 2, -0.5f, 1.4f, u0, v0);
writeVertex(vertexList, 3, 0.5f, 1.4f, u1, v0);
} }
@Override @Override
@ -143,62 +149,25 @@ public class FireComponent {
return BOUNDING_SPHERE; return BOUNDING_SPHERE;
} }
@Override
public int vertexCount() {
return 4;
}
@Override @Override
public void delete() { public void delete() {
} }
private record FireMesh(TextureAtlasSprite sprite) implements QuadMesh { // Magic numbers taken from:
@Override // net.minecraft.client.renderer.entity.EntityRenderDispatcher#fireVertex
public int vertexCount() { private static void writeVertex(MutableVertexList vertexList, int i, float x, float y, float u, float v) {
return 4; vertexList.x(i, x);
} vertexList.y(i, y);
vertexList.z(i, 0);
@Override vertexList.r(i, 1);
public void write(MutableVertexList vertexList) { vertexList.g(i, 1);
float u0 = sprite.getU0(); vertexList.b(i, 1);
float v0 = sprite.getV0(); vertexList.u(i, u);
float u1 = sprite.getU1(); vertexList.v(i, v);
float v1 = sprite.getV1(); vertexList.light(i, LightTexture.FULL_BLOCK);
writeVertex(vertexList, 0, 0.5f, 0, u1, v1); vertexList.normalX(i, 0);
writeVertex(vertexList, 1, -0.5f, 0, u0, v1); vertexList.normalY(i, 1);
writeVertex(vertexList, 2, -0.5f, 1.4f, u0, v0); vertexList.normalZ(i, 0);
writeVertex(vertexList, 3, 0.5f, 1.4f, u1, v0);
}
@Override
public Vector4fc boundingSphere() {
return BOUNDING_SPHERE;
}
@Override
public void delete() {
}
// Magic numbers taken from:
// net.minecraft.client.renderer.entity.EntityRenderDispatcher#fireVertex
private static void writeVertex(MutableVertexList vertexList, int i, float x, float y, float u, float v) {
vertexList.x(i, x);
vertexList.y(i, y);
vertexList.z(i, 0);
vertexList.r(i, 1);
vertexList.g(i, 1);
vertexList.b(i, 1);
vertexList.u(i, u);
vertexList.v(i, v);
vertexList.overlay(i, OverlayTexture.NO_OVERLAY);
vertexList.light(i, 240);
vertexList.normalX(i, 0);
vertexList.normalY(i, 1);
vertexList.normalZ(i, 0);
}
} }
} }
} }

View File

@ -15,7 +15,6 @@ import com.jozufozu.flywheel.api.instance.Instance;
* @param <I> The type of instance to recycle. * @param <I> The type of instance to recycle.
*/ */
public class InstanceRecycler<I extends Instance> { public class InstanceRecycler<I extends Instance> {
private final Supplier<I> factory; private final Supplier<I> factory;
private final List<I> instances = new ArrayList<>(); private final List<I> instances = new ArrayList<>();

View File

@ -1,17 +1,13 @@
package com.jozufozu.flywheel.lib.visual; package com.jozufozu.flywheel.lib.visual;
import java.util.Map;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.joml.Vector4f; import org.joml.Vector4f;
import org.joml.Vector4fc; import org.joml.Vector4fc;
import com.google.common.collect.ImmutableMap;
import com.jozufozu.flywheel.api.event.RenderStage; import com.jozufozu.flywheel.api.event.RenderStage;
import com.jozufozu.flywheel.api.material.Material; import com.jozufozu.flywheel.api.material.Material;
import com.jozufozu.flywheel.api.material.Transparency; import com.jozufozu.flywheel.api.material.Transparency;
import com.jozufozu.flywheel.api.material.WriteMask; import com.jozufozu.flywheel.api.material.WriteMask;
import com.jozufozu.flywheel.api.model.Mesh;
import com.jozufozu.flywheel.api.model.Model; import com.jozufozu.flywheel.api.model.Model;
import com.jozufozu.flywheel.api.vertex.MutableVertexList; import com.jozufozu.flywheel.api.vertex.MutableVertexList;
import com.jozufozu.flywheel.api.visual.VisualFrameContext; import com.jozufozu.flywheel.api.visual.VisualFrameContext;
@ -20,18 +16,20 @@ import com.jozufozu.flywheel.lib.instance.InstanceTypes;
import com.jozufozu.flywheel.lib.instance.ShadowInstance; import com.jozufozu.flywheel.lib.instance.ShadowInstance;
import com.jozufozu.flywheel.lib.material.SimpleMaterial; import com.jozufozu.flywheel.lib.material.SimpleMaterial;
import com.jozufozu.flywheel.lib.model.QuadMesh; import com.jozufozu.flywheel.lib.model.QuadMesh;
import com.jozufozu.flywheel.lib.model.SingleMeshModel;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.LightTexture; import net.minecraft.client.renderer.LightTexture;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.BlockPos.MutableBlockPos;
import net.minecraft.core.Direction.Axis;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.Mth; import net.minecraft.util.Mth;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.LevelReader; import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.RenderShape; import net.minecraft.world.level.block.RenderShape;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.shapes.VoxelShape; import net.minecraft.world.phys.shapes.VoxelShape;
/** /**
@ -44,21 +42,44 @@ import net.minecraft.world.phys.shapes.VoxelShape;
* The shadow will be cast on blocks at most {@code min(radius, 2 * strength)} blocks below the entity.</p> * The shadow will be cast on blocks at most {@code min(radius, 2 * strength)} blocks below the entity.</p>
*/ */
public class ShadowComponent { public class ShadowComponent {
private static final Material SHADOW_MATERIAL = SimpleMaterial.builder()
.texture(new ResourceLocation("textures/misc/shadow.png"))
.mipmap(false)
.polygonOffset(true) // vanilla shadows use "view offset" but this seems to work fine
.transparency(Transparency.TRANSLUCENT)
.writeMask(WriteMask.COLOR)
.build();
private static final Model SHADOW_MODEL = new SingleMeshModel(ShadowMesh.INSTANCE, SHADOW_MATERIAL);
private final VisualizationContext context; private final VisualizationContext context;
private final LevelReader level;
private final Entity entity; private final Entity entity;
private final InstanceRecycler<ShadowInstance> instances = new InstanceRecycler<>(this::instance); private final Level level;
private final BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(); private final BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos();
private final InstanceRecycler<ShadowInstance> instances = new InstanceRecycler<>(this::createInstance);
// Defaults taken from EntityRenderer. // Defaults taken from EntityRenderer.
private float radius = 0; private float radius = 0;
private float strength = 1.0F; private float strength = 1.0F;
public ShadowComponent(VisualizationContext context, Entity entity) { public ShadowComponent(VisualizationContext context, Entity entity) {
this.context = context; this.context = context;
this.level = entity.level();
this.entity = entity; this.entity = entity;
this.level = entity.level();
}
private ShadowInstance createInstance() {
return context.instancerProvider()
.instancer(InstanceTypes.SHADOW, SHADOW_MODEL, RenderStage.AFTER_ENTITIES)
.createInstance();
}
public float radius() {
return radius;
}
public float strength() {
return strength;
} }
/** /**
@ -114,18 +135,18 @@ public class ShadowComponent {
for (int z = minZPos; z <= maxZPos; ++z) { for (int z = minZPos; z <= maxZPos; ++z) {
for (int x = minXPos; x <= maxXPos; ++x) { for (int x = minXPos; x <= maxXPos; ++x) {
pos.set(x, 0, z); pos.set(x, 0, z);
ChunkAccess chunkaccess = level.getChunk(pos); ChunkAccess chunk = level.getChunk(pos);
for (int y = minYPos; y <= maxYPos; ++y) { for (int y = minYPos; y <= maxYPos; ++y) {
pos.setY(y); pos.setY(y);
float strengthGivenYFalloff = strength - (float) (entityY - pos.getY()) * 0.5F; float strengthGivenYFalloff = strength - (float) (entityY - pos.getY()) * 0.5F;
maybeSetupShadowInstance(chunkaccess, (float) entityX, (float) entityZ, strengthGivenYFalloff); setupInstance(chunk, pos, (float) entityX, (float) entityZ, strengthGivenYFalloff);
} }
} }
} }
} }
private void maybeSetupShadowInstance(ChunkAccess pChunk, float entityX, float entityZ, float strength) { private void setupInstance(ChunkAccess chunk, MutableBlockPos pos, float entityX, float entityZ, float strength) {
// TODO: cache this? // TODO: cache this?
var maxLocalRawBrightness = level.getMaxLocalRawBrightness(pos); var maxLocalRawBrightness = level.getMaxLocalRawBrightness(pos);
if (maxLocalRawBrightness <= 3) { if (maxLocalRawBrightness <= 3) {
@ -134,7 +155,7 @@ public class ShadowComponent {
} }
float blockBrightness = LightTexture.getBrightness(level.dimensionType(), maxLocalRawBrightness); float blockBrightness = LightTexture.getBrightness(level.dimensionType(), maxLocalRawBrightness);
float alpha = strength * 0.5F * blockBrightness; float alpha = strength * 0.5F * blockBrightness;
if (!(alpha >= 0.0F)) { if (alpha < 0.0F) {
// Too far away/too weak to render. // Too far away/too weak to render.
return; return;
} }
@ -144,9 +165,9 @@ public class ShadowComponent {
// Grab the AABB for the block below the current position. // Grab the AABB for the block below the current position.
pos.setY(pos.getY() - 1); pos.setY(pos.getY() - 1);
var aabb = getAabbForPos(pChunk, pos); var shape = getShapeAt(chunk, pos);
if (aabb == null) { if (shape == null) {
// No aabb means the block shouldn't receive a shadow. // No shape means the block shouldn't receive a shadow.
return; return;
} }
@ -155,11 +176,11 @@ public class ShadowComponent {
int y = pos.getY() - renderOrigin.getY() + 1; // +1 since we moved the pos down. int y = pos.getY() - renderOrigin.getY() + 1; // +1 since we moved the pos down.
int z = pos.getZ() - renderOrigin.getZ(); int z = pos.getZ() - renderOrigin.getZ();
double minX = x + aabb.minX; double minX = x + shape.min(Axis.X);
double minY = y + aabb.minY; double minY = y + shape.min(Axis.Y);
double minZ = z + aabb.minZ; double minZ = z + shape.min(Axis.Z);
double maxX = x + aabb.maxX; double maxX = x + shape.max(Axis.X);
double maxZ = z + aabb.maxZ; double maxZ = z + shape.max(Axis.Z);
var instance = instances.get(); var instance = instances.get();
instance.x = (float) minX; instance.x = (float) minX;
@ -175,48 +196,48 @@ public class ShadowComponent {
} }
@Nullable @Nullable
private AABB getAabbForPos(ChunkAccess pChunk, BlockPos pos) { private VoxelShape getShapeAt(ChunkAccess chunk, BlockPos pos) {
BlockState blockstate = pChunk.getBlockState(pos); BlockState state = chunk.getBlockState(pos);
if (blockstate.getRenderShape() == RenderShape.INVISIBLE) { if (state.getRenderShape() == RenderShape.INVISIBLE) {
return null; return null;
} }
if (!blockstate.isCollisionShapeFullBlock(pChunk, pos)) { if (!state.isCollisionShapeFullBlock(chunk, pos)) {
return null; return null;
} }
VoxelShape voxelshape = blockstate.getShape(pChunk, pos); VoxelShape shape = state.getShape(chunk, pos);
if (voxelshape.isEmpty()) { if (shape.isEmpty()) {
return null; return null;
} }
return voxelshape.bounds(); return shape;
}
private ShadowInstance instance() {
return context.instancerProvider()
.instancer(InstanceTypes.SHADOW, ShadowModel.INSTANCE, RenderStage.AFTER_ENTITIES)
.createInstance();
} }
public void delete() { public void delete() {
instances.delete(); instances.delete();
} }
private static class ShadowModel implements Model { /**
public static final ShadowModel INSTANCE = new ShadowModel(); * A single quad extending from the origin to (1, 0, 1).
public static final Material MATERIAL = SimpleMaterial.builder() * <br>
.transparency(Transparency.TRANSLUCENT) * To be scaled and translated to the correct position and size.
.writeMask(WriteMask.COLOR) */
.polygonOffset(true) // vanilla shadows use "view offset" but this seems to work fine private static class ShadowMesh implements QuadMesh {
.texture(new ResourceLocation("minecraft", "textures/misc/shadow.png"))
.build();
private static final Vector4fc BOUNDING_SPHERE = new Vector4f(0.5f, 0, 0.5f, (float) (Math.sqrt(2) * 0.5)); private static final Vector4fc BOUNDING_SPHERE = new Vector4f(0.5f, 0, 0.5f, (float) (Math.sqrt(2) * 0.5));
private static final ImmutableMap<Material, Mesh> meshes = ImmutableMap.of(MATERIAL, ShadowMesh.INSTANCE); private static final ShadowMesh INSTANCE = new ShadowMesh();
private ShadowModel() { private ShadowMesh() {
} }
@Override @Override
public Map<Material, Mesh> meshes() { public int vertexCount() {
return meshes; return 4;
}
@Override
public void write(MutableVertexList vertexList) {
writeVertex(vertexList, 0, 0, 0);
writeVertex(vertexList, 1, 0, 1);
writeVertex(vertexList, 2, 1, 1);
writeVertex(vertexList, 3, 1, 0);
} }
@Override @Override
@ -224,68 +245,25 @@ public class ShadowComponent {
return BOUNDING_SPHERE; return BOUNDING_SPHERE;
} }
@Override
public int vertexCount() {
return ShadowMesh.INSTANCE.vertexCount();
}
@Override @Override
public void delete() { public void delete() {
} }
/** // Magic numbers taken from:
* A single quad extending from the origin to (1, 0, 1). // net.minecraft.client.renderer.entity.EntityRenderDispatcher#shadowVertex
* <br> private static void writeVertex(MutableVertexList vertexList, int i, float x, float z) {
* To be scaled and translated to the correct position and size. vertexList.x(i, x);
*/ vertexList.y(i, 0);
private static class ShadowMesh implements QuadMesh { vertexList.z(i, z);
public static final ShadowMesh INSTANCE = new ShadowMesh(); vertexList.r(i, 1);
vertexList.g(i, 1);
private ShadowMesh() { vertexList.b(i, 1);
} vertexList.u(i, 0);
vertexList.v(i, 0);
@Override vertexList.light(i, LightTexture.FULL_BRIGHT);
public int vertexCount() { vertexList.normalX(i, 0);
return 4; vertexList.normalY(i, 1);
} vertexList.normalZ(i, 0);
@Override
public void write(MutableVertexList vertexList) {
writeVertex(vertexList, 0, 0, 0);
writeVertex(vertexList, 1, 0, 1);
writeVertex(vertexList, 2, 1, 1);
writeVertex(vertexList, 3, 1, 0);
}
@Override
public Vector4fc boundingSphere() {
return BOUNDING_SPHERE;
}
@Override
public void delete() {
}
// Magic numbers taken from:
// net.minecraft.client.renderer.entity.EntityRenderDispatcher#shadowVertex
private static void writeVertex(MutableVertexList vertexList, int i, float x, float z) {
vertexList.x(i, x);
vertexList.y(i, 0);
vertexList.z(i, z);
vertexList.r(i, 1);
vertexList.g(i, 1);
vertexList.b(i, 1);
vertexList.u(i, 0);
vertexList.v(i, 0);
vertexList.light(i, 15728880);
vertexList.normalX(i, 0);
vertexList.normalY(i, 1);
vertexList.normalZ(i, 0);
}
} }
} }
} }

View File

@ -1,38 +0,0 @@
package com.jozufozu.flywheel.mixin;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
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.backend.engine.uniform.Uniforms;
import com.jozufozu.flywheel.backend.gl.GlStateTracker;
import net.minecraft.client.renderer.FogRenderer;
@Mixin(FogRenderer.class)
abstract class FogUpdateMixin {
@Unique
private static void flywheel$updateFog() {
try (var restoreState = GlStateTracker.getRestoreState()) {
Uniforms.fog()
.update();
}
}
@Inject(method = "setupNoFog()V", at = @At("RETURN"))
private static void flywheel$onNoFog(CallbackInfo ci) {
flywheel$updateFog();
}
@Inject(method = "setupFog(Lnet/minecraft/client/Camera;Lnet/minecraft/client/renderer/FogRenderer$FogMode;FZF)V", at = @At("RETURN"), remap = false)
private static void flywheel$onFog(CallbackInfo ci) {
flywheel$updateFog();
}
@Inject(method = "levelFogColor()V", at = @At("RETURN"))
private static void flywheel$onFogColor(CallbackInfo ci) {
flywheel$updateFog();
}
}

View File

@ -0,0 +1,14 @@
{
"required": true,
"minVersion": "0.8",
"package": "com.jozufozu.flywheel.backend.mixin",
"compatibilityLevel": "JAVA_17",
"refmap": "flywheel.refmap.json",
"client": [
"GlStateManagerMixin",
"RenderSystemMixin"
],
"injectors": {
"defaultRequire": 1
}
}

View File

@ -1,15 +1,13 @@
{ {
"required": true, "required": true,
"minVersion": "0.8", "minVersion": "0.8",
"package": "com.jozufozu.flywheel.mixin", "package": "com.jozufozu.flywheel.impl.mixin",
"compatibilityLevel": "JAVA_17", "compatibilityLevel": "JAVA_17",
"refmap": "flywheel.refmap.json", "refmap": "flywheel.refmap.json",
"client": [ "client": [
"BlockEntityTypeMixin", "BlockEntityTypeMixin",
"ClientLevelMixin", "ClientLevelMixin",
"EntityTypeMixin", "EntityTypeMixin",
"FogUpdateMixin",
"GlStateManagerMixin",
"LayerLightSectionStorageMixin", "LayerLightSectionStorageMixin",
"LevelMixin", "LevelMixin",
"LevelRendererMixin", "LevelRendererMixin",
@ -18,10 +16,10 @@
"VertexFormatMixin", "VertexFormatMixin",
"fix.FixFabulousDepthMixin", "fix.FixFabulousDepthMixin",
"fix.FixNormalScalingMixin", "fix.FixNormalScalingMixin",
"visualmanage.ChunkRebuildHooksMixin", "visualmanage.BlockEntityMixin",
"visualmanage.VisualAddMixin", "visualmanage.LevelChunkMixin",
"visualmanage.VisualRemoveMixin", "visualmanage.LevelRendererMixin",
"visualmanage.VisualUpdateMixin" "visualmanage.RebuildTaskMixin"
], ],
"injectors": { "injectors": {
"defaultRequire": 1 "defaultRequire": 1

View File

@ -1,10 +1,10 @@
{ {
"required": true, "required": true,
"minVersion": "0.8", "minVersion": "0.8",
"package": "com.jozufozu.flywheel.mixin.sodium", "package": "com.jozufozu.flywheel.impl.mixin.sodium",
"compatibilityLevel": "JAVA_17", "compatibilityLevel": "JAVA_17",
"refmap": "flywheel.refmap.json", "refmap": "flywheel.refmap.json",
"plugin": "com.jozufozu.flywheel.compat.SodiumMixinPlugin", "plugin": "com.jozufozu.flywheel.impl.mixin.sodium.SodiumMixinPlugin",
"client": [ "client": [
"ChunkBuilderMeshingTaskMixin" "ChunkBuilderMeshingTaskMixin"
], ],