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 {
add sourceSets.main, 'flywheel.refmap.json'
config 'flywheel.mixins.json'
config 'flywheel.sodium.mixins.json'
config 'flywheel.backend.mixins.json'
config 'flywheel.impl.mixins.json'
config 'flywheel.impl.sodium.mixins.json'
debug.verbose = 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.FlwConfig;
import com.jozufozu.flywheel.impl.BackendManagerImpl;
import com.jozufozu.flywheel.impl.IdRegistryImpl;
import com.jozufozu.flywheel.impl.RegistryImpl;
import com.jozufozu.flywheel.impl.registry.IdRegistryImpl;
import com.jozufozu.flywheel.impl.registry.RegistryImpl;
import com.jozufozu.flywheel.impl.visualization.VisualizationEventHandler;
import com.jozufozu.flywheel.lib.context.Contexts;
import com.jozufozu.flywheel.lib.instance.InstanceTypes;

View File

@ -1,15 +1,15 @@
package com.jozufozu.flywheel.api.backend;
import com.jozufozu.flywheel.api.BackendImplemented;
import com.jozufozu.flywheel.api.internal.InternalFlywheelApi;
import com.jozufozu.flywheel.api.registry.IdRegistry;
import com.jozufozu.flywheel.impl.IdRegistryImpl;
import net.minecraft.network.chat.Component;
import net.minecraft.world.level.LevelAccessor;
@BackendImplemented
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.

View File

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

View File

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

View File

@ -1,8 +1,8 @@
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.registry.Registry;
import com.jozufozu.flywheel.impl.RegistryImpl;
import net.minecraft.resources.ResourceLocation;
@ -12,7 +12,7 @@ import net.minecraft.resources.ResourceLocation;
* @param <I> The java representation of the 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.

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.Range;
import com.jozufozu.flywheel.impl.layout.LayoutBuilderImpl;
import com.jozufozu.flywheel.api.internal.InternalFlywheelApi;
@ApiStatus.NonExtendable
public interface LayoutBuilder {
@ -18,6 +18,6 @@ public interface LayoutBuilder {
Layout build();
static LayoutBuilder create() {
return new LayoutBuilderImpl();
return InternalFlywheelApi.INSTANCE.createLayoutBuilder();
}
}

View File

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

View File

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

View File

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

View File

@ -1,17 +1,17 @@
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;
public final class VertexViewProviderRegistry {
private VertexViewProviderRegistry() {
}
public static VertexViewProvider getProvider(VertexFormat format) {
return VertexListProviderRegistryImpl.getProvider(format);
return InternalFlywheelApi.INSTANCE.getVertexViewProvider(format);
}
public static void setProvider(VertexFormat format, VertexViewProvider provider) {
VertexListProviderRegistryImpl.setProvider(format, provider);
}
private VertexViewProviderRegistry() {
InternalFlywheelApi.INSTANCE.setVertexViewProvider(format, provider);
}
}

View File

@ -7,17 +7,11 @@ import net.minecraft.client.Camera;
@ApiStatus.NonExtendable
public interface VisualFrameContext {
double cameraX();
double cameraY();
double cameraZ();
Camera camera();
FrustumIntersection frustum();
float partialTick();
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.Nullable;
import com.jozufozu.flywheel.api.internal.InternalFlywheelApi;
import com.jozufozu.flywheel.api.visual.Effect;
import com.jozufozu.flywheel.api.visual.Visual;
import com.jozufozu.flywheel.impl.visualization.VisualizationManagerImpl;
import net.minecraft.core.Vec3i;
import net.minecraft.world.entity.Entity;
@ -16,16 +16,16 @@ import net.minecraft.world.level.block.entity.BlockEntity;
@ApiStatus.NonExtendable
public interface VisualizationManager {
static boolean supportsVisualization(@Nullable LevelAccessor level) {
return VisualizationManagerImpl.supportsVisualization(level);
return InternalFlywheelApi.INSTANCE.supportsVisualization(level);
}
@Nullable
static VisualizationManager get(@Nullable LevelAccessor level) {
return VisualizationManagerImpl.get(level);
return InternalFlywheelApi.INSTANCE.getVisualizationManager(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 com.jozufozu.flywheel.impl.visualization.VisualizerRegistryImpl;
import com.jozufozu.flywheel.api.internal.InternalFlywheelApi;
import net.minecraft.world.entity.Entity;
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;
/**
* A utility class for registering and retrieving {@code Visualizer}s.
* The registry for {@code Visualizer}s.
*/
public final class VisualizerRegistry {
private VisualizerRegistry() {
}
/**
* Gets the visualizer for the given block entity type, if one exists.
* @param type The block entity type to get the visualizer for.
@ -21,7 +24,7 @@ public final class VisualizerRegistry {
*/
@Nullable
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
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.
*/
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.
*/
public static <T extends Entity> void setVisualizer(EntityType<T> type, EntityVisualizer<? super T> visualizer) {
VisualizerRegistryImpl.setVisualizer(type, visualizer);
}
private VisualizerRegistry() {
InternalFlywheelApi.INSTANCE.setVisualizer(type, visualizer);
}
}

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.RenderContext;
import com.jozufozu.flywheel.backend.gl.GlStateTracker;
public class Uniforms {
public static boolean frustumPaused = false;
@ -28,15 +29,21 @@ public class Uniforms {
bindFog();
}
public static void bindFrame() {
if (frame != null) {
frame.bind();
}
}
public static void bindFog() {
if (fog != null) {
fog.bind();
}
}
public static void bindFrame() {
if (frame != null) {
frame.bind();
public static void onFogUpdate() {
try (var restoreState = GlStateTracker.getRestoreState()) {
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.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 {
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")
.withStyle(ChatFormatting.RED))
.engineFactory(level -> {
@ -30,7 +30,7 @@ public final class BackendManagerImpl {
.supported(() -> true)
.register(Flywheel.rl("off"));
private static final Backend DEFAULT_BACKEND = findDefaultBackend();
public static final Backend DEFAULT_BACKEND = findDefaultBackend();
private static Backend backend = OFF_BACKEND;
@ -41,18 +41,10 @@ public final class BackendManagerImpl {
return backend;
}
public static boolean isOn() {
public static boolean isBackendOn() {
return backend != OFF_BACKEND;
}
public static Backend getOffBackend() {
return OFF_BACKEND;
}
public static Backend getDefaultBackend() {
return DEFAULT_BACKEND;
}
private static Backend findDefaultBackend() {
// 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

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;

View File

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.extension;
package com.jozufozu.flywheel.impl.extension;
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.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.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.mojang.blaze3d.vertex.VertexFormat;
@ -9,7 +9,6 @@ import com.mojang.blaze3d.vertex.VertexFormat;
* @see VertexFormat
*/
public interface VertexFormatExtension {
/**
* @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.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
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.BlockEntityType;

View File

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

View File

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.mixin;
package com.jozufozu.flywheel.impl.mixin;
import java.util.Optional;
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.Unique;
import com.jozufozu.flywheel.extension.PoseStackExtension;
import com.jozufozu.flywheel.impl.extension.PoseStackExtension;
import com.jozufozu.flywheel.lib.transform.PoseTransformStack;
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.Unique;
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;
@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.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.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.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.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.spongepowered.asm.mixin.Mixin;
@ -13,7 +13,7 @@ import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
@Mixin(BlockEntity.class)
abstract class VisualRemoveMixin {
abstract class BlockEntityMixin {
@Shadow
@Nullable
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.Mixin;
@ -14,7 +14,7 @@ import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.chunk.LevelChunk;
@Mixin(LevelChunk.class)
abstract class VisualAddMixin {
abstract class LevelChunkMixin {
@Shadow
@Final
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.Shadow;
@ -15,7 +15,7 @@ import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
@Mixin(LevelRenderer.class)
abstract class VisualUpdateMixin {
abstract class LevelRendererMixin {
@Shadow
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.injection.At;
@ -11,7 +11,7 @@ import com.jozufozu.flywheel.impl.visualization.VisualizationHelper;
import net.minecraft.world.level.block.entity.BlockEntity;
@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)
private void flywheel$tryAddBlockEntity(@Coerce Object compileResults, BlockEntity blockEntity, CallbackInfo ci) {
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.Iterator;
@ -31,14 +31,10 @@ public class IdRegistryImpl<T> implements IdRegistry<T> {
private final ObjectList<Runnable> freezeCallbacks = new ObjectArrayList<>();
private boolean frozen;
private IdRegistryImpl() {
public IdRegistryImpl() {
ALL.add(this);
}
public static <T> IdRegistry<T> create() {
return new IdRegistryImpl<>();
}
@Override
public void register(ResourceLocation id, T object) {
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.Set;
@ -21,14 +21,10 @@ public class RegistryImpl<T> implements Registry<T> {
private final ObjectList<Runnable> freezeCallbacks = new ObjectArrayList<>();
private boolean frozen;
private RegistryImpl() {
public RegistryImpl() {
ALL.add(this);
}
public static <T> Registry<T> create() {
return new RegistryImpl<>();
}
@Override
public void register(T object) {
if (frozen) {

View File

@ -1,11 +1,14 @@
package com.jozufozu.flywheel.impl.vertex;
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;
// TODO: Add freezing
public final class VertexListProviderRegistryImpl {
public final class VertexViewProviderRegistryImpl {
private VertexViewProviderRegistryImpl() {
}
public static VertexViewProvider getProvider(VertexFormat format) {
VertexFormatExtension extension = (VertexFormatExtension) format;
VertexViewProvider provider = extension.flywheel$getVertexViewProvider();
@ -19,7 +22,4 @@ public final class VertexListProviderRegistryImpl {
public static void setProvider(VertexFormat format, VertexViewProvider 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;
public record VisualFrameContextImpl(double cameraX, double cameraY, double cameraZ, FrustumIntersection frustum,
float partialTick, DistanceUpdateLimiter limiter,
Camera camera) implements VisualFrameContext {
public record VisualFrameContextImpl(Camera camera, FrustumIntersection frustum,
float partialTick, DistanceUpdateLimiter limiter) 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.VisualizationManager;
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.visual.VisualFrameContextImpl;
import com.jozufozu.flywheel.impl.visual.VisualTickContextImpl;
@ -102,7 +102,9 @@ public class VisualizationManagerImpl implements VisualizationManager {
.then(RaisePlan.raise(tickFlag))
.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)
.to(NestedPlan.of(blockEntities.framePlan(), entities.framePlan(), effects.framePlan()));
@ -126,15 +128,12 @@ public class VisualizationManagerImpl implements VisualizationManager {
Vec3i renderOrigin = engine.renderOrigin();
var cameraPos = ctx.camera()
.getPosition();
double cameraX = cameraPos.x;
double cameraY = cameraPos.y;
double cameraZ = cameraPos.z;
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);
return new VisualFrameContextImpl(cameraX, cameraY, cameraZ, frustum, ctx.partialTick(), frameLimiter, ctx.camera());
return new VisualFrameContextImpl(ctx.camera(), frustum, ctx.partialTick(), frameLimiter);
}
protected DistanceUpdateLimiterImpl createUpdateLimiter() {
@ -148,7 +147,7 @@ public class VisualizationManagerImpl implements VisualizationManager {
@Contract("null -> false")
public static boolean supportsVisualization(@Nullable LevelAccessor level) {
if (!BackendManager.isOn()) {
if (!BackendManager.isBackendOn()) {
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
// potentially by keeping the same VisualizationManagerImpl and deleting the engine and visuals but not the game objects
public static void reset(LevelAccessor level) {
MANAGERS.remove(level);
}
public static void resetAll() {
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.EntityVisualizer;
import com.jozufozu.flywheel.extension.BlockEntityTypeExtension;
import com.jozufozu.flywheel.extension.EntityTypeExtension;
import com.jozufozu.flywheel.impl.extension.BlockEntityTypeExtension;
import com.jozufozu.flywheel.impl.extension.EntityTypeExtension;
import net.minecraft.world.entity.Entity;
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.atomic.AtomicLong;
import org.jetbrains.annotations.NotNull;
import com.jozufozu.flywheel.api.task.Plan;
import com.jozufozu.flywheel.api.task.TaskExecutor;
import com.jozufozu.flywheel.api.visual.LitVisual;
@ -161,7 +159,6 @@ public class LitVisualStorage {
return -1;
}
@NotNull
private static Updater createUpdater(LitVisual visual, int sectionCount) {
if (sectionCount == 1) {
return new Updater.Simple(visual);

View File

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

View File

@ -1,14 +1,14 @@
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;
public interface TransformStack<Self extends TransformStack<Self>> extends Transform<Self> {
static PoseTransformStack of(PoseStack stack) {
return InternalFlywheelApi.INSTANCE.getPoseTransformStackOf(stack);
}
Self pushPose();
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) {
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;
import java.util.Map;
import org.joml.Vector4f;
import org.joml.Vector4fc;
import com.google.common.collect.ImmutableMap;
import com.jozufozu.flywheel.api.event.RenderStage;
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.visual.VisualFrameContext;
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.model.ModelCache;
import com.jozufozu.flywheel.lib.model.QuadMesh;
import com.jozufozu.flywheel.lib.model.SingleMeshModel;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.math.Axis;
import net.minecraft.client.renderer.LightTexture;
import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.resources.model.ModelBakery;
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.
*/
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 Entity entity;
private final PoseStack stack = new PoseStack();
@ -44,12 +48,17 @@ public class FireComponent {
this.context = context;
this.entity = entity;
fire0 = new InstanceRecycler<>(() -> context.instancerProvider()
.instancer(InstanceTypes.TRANSFORMED, FireModel.CACHE.get(ModelBakery.FIRE_0), RenderStage.AFTER_BLOCK_ENTITIES)
.createInstance());
fire1 = new InstanceRecycler<>(() -> context.instancerProvider()
.instancer(InstanceTypes.TRANSFORMED, FireModel.CACHE.get(ModelBakery.FIRE_1), RenderStage.AFTER_BLOCK_ENTITIES)
.createInstance());
fire0 = new InstanceRecycler<>(() -> createInstance(ModelBakery.FIRE_0));
fire1 = new InstanceRecycler<>(() -> createInstance(ModelBakery.FIRE_1));
}
private TransformedInstance createInstance(net.minecraft.client.resources.model.Material texture) {
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.setBlockLight(LightTexture.block(240));
instance.setChanged();
y += 0.45F;
@ -117,25 +124,24 @@ public class FireComponent {
fire1.delete();
}
private static class FireModel implements Model {
// 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 record FireMesh(TextureAtlasSprite sprite) implements QuadMesh {
private static final Vector4fc BOUNDING_SPHERE = new Vector4f(0, 0.5f, 0, (float) (Math.sqrt(2) * 0.5));
private final ImmutableMap<Material, Mesh> meshes;
private FireModel(TextureAtlasSprite sprite) {
meshes = ImmutableMap.of(MATERIAL, new FireMesh(sprite));
@Override
public int vertexCount() {
return 4;
}
@Override
public Map<Material, Mesh> meshes() {
return meshes;
public void write(MutableVertexList vertexList) {
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
@ -143,62 +149,25 @@ public class FireComponent {
return BOUNDING_SPHERE;
}
@Override
public int vertexCount() {
return 4;
}
@Override
public void delete() {
}
private record FireMesh(TextureAtlasSprite sprite) implements QuadMesh {
@Override
public int vertexCount() {
return 4;
}
@Override
public void write(MutableVertexList vertexList) {
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
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);
}
// 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.light(i, LightTexture.FULL_BLOCK);
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.
*/
public class InstanceRecycler<I extends Instance> {
private final Supplier<I> factory;
private final List<I> instances = new ArrayList<>();

View File

@ -1,17 +1,13 @@
package com.jozufozu.flywheel.lib.visual;
import java.util.Map;
import org.jetbrains.annotations.Nullable;
import org.joml.Vector4f;
import org.joml.Vector4fc;
import com.google.common.collect.ImmutableMap;
import com.jozufozu.flywheel.api.event.RenderStage;
import com.jozufozu.flywheel.api.material.Material;
import com.jozufozu.flywheel.api.material.Transparency;
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.vertex.MutableVertexList;
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.material.SimpleMaterial;
import com.jozufozu.flywheel.lib.model.QuadMesh;
import com.jozufozu.flywheel.lib.model.SingleMeshModel;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.LightTexture;
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.util.Mth;
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.state.BlockState;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.phys.AABB;
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>
*/
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 LevelReader level;
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 InstanceRecycler<ShadowInstance> instances = new InstanceRecycler<>(this::createInstance);
// Defaults taken from EntityRenderer.
private float radius = 0;
private float strength = 1.0F;
public ShadowComponent(VisualizationContext context, Entity entity) {
this.context = context;
this.level = entity.level();
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 x = minXPos; x <= maxXPos; ++x) {
pos.set(x, 0, z);
ChunkAccess chunkaccess = level.getChunk(pos);
ChunkAccess chunk = level.getChunk(pos);
for (int y = minYPos; y <= maxYPos; ++y) {
pos.setY(y);
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?
var maxLocalRawBrightness = level.getMaxLocalRawBrightness(pos);
if (maxLocalRawBrightness <= 3) {
@ -134,7 +155,7 @@ public class ShadowComponent {
}
float blockBrightness = LightTexture.getBrightness(level.dimensionType(), maxLocalRawBrightness);
float alpha = strength * 0.5F * blockBrightness;
if (!(alpha >= 0.0F)) {
if (alpha < 0.0F) {
// Too far away/too weak to render.
return;
}
@ -144,9 +165,9 @@ public class ShadowComponent {
// Grab the AABB for the block below the current position.
pos.setY(pos.getY() - 1);
var aabb = getAabbForPos(pChunk, pos);
if (aabb == null) {
// No aabb means the block shouldn't receive a shadow.
var shape = getShapeAt(chunk, pos);
if (shape == null) {
// No shape means the block shouldn't receive a shadow.
return;
}
@ -155,11 +176,11 @@ public class ShadowComponent {
int y = pos.getY() - renderOrigin.getY() + 1; // +1 since we moved the pos down.
int z = pos.getZ() - renderOrigin.getZ();
double minX = x + aabb.minX;
double minY = y + aabb.minY;
double minZ = z + aabb.minZ;
double maxX = x + aabb.maxX;
double maxZ = z + aabb.maxZ;
double minX = x + shape.min(Axis.X);
double minY = y + shape.min(Axis.Y);
double minZ = z + shape.min(Axis.Z);
double maxX = x + shape.max(Axis.X);
double maxZ = z + shape.max(Axis.Z);
var instance = instances.get();
instance.x = (float) minX;
@ -175,48 +196,48 @@ public class ShadowComponent {
}
@Nullable
private AABB getAabbForPos(ChunkAccess pChunk, BlockPos pos) {
BlockState blockstate = pChunk.getBlockState(pos);
if (blockstate.getRenderShape() == RenderShape.INVISIBLE) {
private VoxelShape getShapeAt(ChunkAccess chunk, BlockPos pos) {
BlockState state = chunk.getBlockState(pos);
if (state.getRenderShape() == RenderShape.INVISIBLE) {
return null;
}
if (!blockstate.isCollisionShapeFullBlock(pChunk, pos)) {
if (!state.isCollisionShapeFullBlock(chunk, pos)) {
return null;
}
VoxelShape voxelshape = blockstate.getShape(pChunk, pos);
if (voxelshape.isEmpty()) {
VoxelShape shape = state.getShape(chunk, pos);
if (shape.isEmpty()) {
return null;
}
return voxelshape.bounds();
}
private ShadowInstance instance() {
return context.instancerProvider()
.instancer(InstanceTypes.SHADOW, ShadowModel.INSTANCE, RenderStage.AFTER_ENTITIES)
.createInstance();
return shape;
}
public void delete() {
instances.delete();
}
private static class ShadowModel implements Model {
public static final ShadowModel INSTANCE = new ShadowModel();
public static final Material MATERIAL = SimpleMaterial.builder()
.transparency(Transparency.TRANSLUCENT)
.writeMask(WriteMask.COLOR)
.polygonOffset(true) // vanilla shadows use "view offset" but this seems to work fine
.texture(new ResourceLocation("minecraft", "textures/misc/shadow.png"))
.build();
/**
* A single quad extending from the origin to (1, 0, 1).
* <br>
* To be scaled and translated to the correct position and size.
*/
private static class ShadowMesh implements QuadMesh {
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
public Map<Material, Mesh> meshes() {
return meshes;
public int vertexCount() {
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
@ -224,68 +245,25 @@ public class ShadowComponent {
return BOUNDING_SPHERE;
}
@Override
public int vertexCount() {
return ShadowMesh.INSTANCE.vertexCount();
}
@Override
public void delete() {
}
/**
* A single quad extending from the origin to (1, 0, 1).
* <br>
* To be scaled and translated to the correct position and size.
*/
private static class ShadowMesh implements QuadMesh {
public static final ShadowMesh INSTANCE = new ShadowMesh();
private ShadowMesh() {
}
@Override
public int vertexCount() {
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
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);
}
// 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, LightTexture.FULL_BRIGHT);
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,
"minVersion": "0.8",
"package": "com.jozufozu.flywheel.mixin",
"package": "com.jozufozu.flywheel.impl.mixin",
"compatibilityLevel": "JAVA_17",
"refmap": "flywheel.refmap.json",
"client": [
"BlockEntityTypeMixin",
"ClientLevelMixin",
"EntityTypeMixin",
"FogUpdateMixin",
"GlStateManagerMixin",
"LayerLightSectionStorageMixin",
"LevelMixin",
"LevelRendererMixin",
@ -18,10 +16,10 @@
"VertexFormatMixin",
"fix.FixFabulousDepthMixin",
"fix.FixNormalScalingMixin",
"visualmanage.ChunkRebuildHooksMixin",
"visualmanage.VisualAddMixin",
"visualmanage.VisualRemoveMixin",
"visualmanage.VisualUpdateMixin"
"visualmanage.BlockEntityMixin",
"visualmanage.LevelChunkMixin",
"visualmanage.LevelRendererMixin",
"visualmanage.RebuildTaskMixin"
],
"injectors": {
"defaultRequire": 1

View File

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