mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2024-11-10 12:34:11 +01:00
Re-reload
- Rename ReloadRenderersEvent to ReloadLevelRendererEvent - Rename Engine#renderCrumblingInstances to #renderCrumbling - Make all mixin classes package-private and abstract - Make all event classes final and document which event bus they are posted on - Add EndClientResourceReloadEvent - Replace some usages of ReloadLevelRendererEvent with EndClientResourceReloadEvent, including ModelHolder and ModelCache - Always add all existing entities from world to VisualizationManagerImpl on construction if level is instanceof Level - Delete all VisualizationManagerImpls on resource reload - Improve MemoryBlock utility - Add MemoryBlock#copyTo(MemoryBlock) - Remove MemoryBlock#reallocTracked and make #realloc create a tracked block if and only if the existing block is tracked - Fix reallocating a debug memory block creating a regular memory block - Change BakedModelBufferer to only invoke the result consumer if the data is not empty - Improve BackendArgument - Fix classloading BackendArgument early causing it to return incomplete suggestions - Always allow specifying namespace, allow matching only by path, and always display suggested IDs with namespace
This commit is contained in:
parent
7bae0f4d8c
commit
f72abf8e1d
@ -5,10 +5,10 @@ import java.util.ArrayList;
|
||||
import org.apache.maven.artifact.versioning.ArtifactVersion;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import com.jozufozu.flywheel.api.event.ReloadRenderersEvent;
|
||||
import com.jozufozu.flywheel.api.event.EndClientResourceReloadEvent;
|
||||
import com.jozufozu.flywheel.api.visualization.VisualizationManager;
|
||||
import com.jozufozu.flywheel.backend.Backends;
|
||||
import com.jozufozu.flywheel.backend.Loader;
|
||||
import com.jozufozu.flywheel.backend.compile.FlwPrograms;
|
||||
import com.jozufozu.flywheel.backend.compile.Pipelines;
|
||||
import com.jozufozu.flywheel.backend.engine.UniformBuffer;
|
||||
import com.jozufozu.flywheel.backend.engine.batching.DrawBuffer;
|
||||
@ -70,7 +70,7 @@ public class Flywheel {
|
||||
IEventBus forgeEventBus = MinecraftForge.EVENT_BUS;
|
||||
IEventBus modEventBus = FMLJavaModLoadingContext.get()
|
||||
.getModEventBus();
|
||||
modEventBus.addListener(Flywheel::setup);
|
||||
modEventBus.addListener(Flywheel::onCommonSetup);
|
||||
|
||||
FlwConfig.get().registerSpecs(modLoadingContext);
|
||||
|
||||
@ -85,7 +85,7 @@ public class Flywheel {
|
||||
private static void clientInit(IEventBus forgeEventBus, IEventBus modEventBus) {
|
||||
forgeEventBus.addListener(Flywheel::addDebugInfo);
|
||||
|
||||
forgeEventBus.addListener(BackendManagerImpl::onReloadRenderers);
|
||||
forgeEventBus.addListener(BackendManagerImpl::onReloadLevelRenderer);
|
||||
|
||||
forgeEventBus.addListener(VisualizationEventHandler::onClientTick);
|
||||
forgeEventBus.addListener(VisualizationEventHandler::onBeginFrame);
|
||||
@ -96,14 +96,17 @@ public class Flywheel {
|
||||
forgeEventBus.addListener(FlwCommands::registerClientCommands);
|
||||
|
||||
forgeEventBus.addListener(DrawBuffer::onReloadRenderers);
|
||||
forgeEventBus.addListener(UniformBuffer::onReloadRenderers);
|
||||
forgeEventBus.addListener(UniformBuffer::onReloadLevelRenderer);
|
||||
|
||||
forgeEventBus.addListener(LightUpdater::onClientTick);
|
||||
forgeEventBus.addListener((ReloadRenderersEvent e) -> ModelCache.onReloadRenderers(e));
|
||||
forgeEventBus.addListener(ModelHolder::onReloadRenderers);
|
||||
forgeEventBus.addListener((LevelEvent.Unload e) -> LevelAttached.onUnloadLevel(e));
|
||||
|
||||
modEventBus.addListener(Flywheel::lateInit);
|
||||
modEventBus.addListener(Flywheel::onClientSetup);
|
||||
|
||||
modEventBus.addListener(BackendManagerImpl::onEndClientResourceReload);
|
||||
|
||||
modEventBus.addListener((EndClientResourceReloadEvent e) -> ModelCache.onEndClientResourceReload(e));
|
||||
modEventBus.addListener(ModelHolder::onEndClientResourceReload);
|
||||
|
||||
modEventBus.addListener(PartialModel::onModelRegistry);
|
||||
modEventBus.addListener(PartialModel::onModelBake);
|
||||
@ -115,12 +118,12 @@ public class Flywheel {
|
||||
|
||||
Pipelines.init();
|
||||
Backends.init();
|
||||
Loader.init();
|
||||
FlwPrograms.ResourceReloadListener.register();
|
||||
|
||||
ShadersModHandler.init();
|
||||
}
|
||||
|
||||
private static void lateInit(final FMLClientSetupEvent event) {
|
||||
private static void onClientSetup(FMLClientSetupEvent event) {
|
||||
VertexTypes.init();
|
||||
InstanceTypes.init();
|
||||
Materials.init();
|
||||
@ -134,7 +137,8 @@ public class Flywheel {
|
||||
IdRegistryImpl.freezeAll();
|
||||
}
|
||||
|
||||
private static void setup(final FMLCommonSetupEvent event) {
|
||||
private static void onCommonSetup(FMLCommonSetupEvent event) {
|
||||
// FIXME: argument types also need to be registered to BuiltInRegistries.COMMAND_ARGUMENT_TYPE
|
||||
ArgumentTypeInfos.registerByClass(BackendArgument.class, SingletonArgumentInfo.contextFree(() -> BackendArgument.INSTANCE));
|
||||
}
|
||||
|
||||
|
@ -31,13 +31,13 @@ public interface Engine extends InstancerProvider {
|
||||
/**
|
||||
* Render the given instances as a crumbling overlay.
|
||||
* <br>
|
||||
* This is guaranteed to be called between the first and last calls to {@link #renderStage}.
|
||||
* This is guaranteed to be called between the first and last calls to {@link #renderStage} for the current frame.
|
||||
*
|
||||
* @param executor The task executor running the frame plan.
|
||||
* @param context The render context for this frame.
|
||||
* @param crumblingBlocks The instances to render.
|
||||
* @param crumblingBlocks The instances to render. This list is never empty.
|
||||
*/
|
||||
void renderCrumblingInstances(TaskExecutor executor, RenderContext context, List<CrumblingBlock> crumblingBlocks);
|
||||
void renderCrumbling(TaskExecutor executor, RenderContext context, List<CrumblingBlock> crumblingBlocks);
|
||||
|
||||
/**
|
||||
* Maintain the render origin to be within a certain distance from the camera in all directions,
|
||||
|
@ -2,7 +2,10 @@ package com.jozufozu.flywheel.api.event;
|
||||
|
||||
import net.minecraftforge.eventbus.api.Event;
|
||||
|
||||
public class BeginFrameEvent extends Event {
|
||||
/**
|
||||
* This event is posted to the Forge event bus.
|
||||
*/
|
||||
public final class BeginFrameEvent extends Event {
|
||||
private final RenderContext context;
|
||||
|
||||
public BeginFrameEvent(RenderContext context) {
|
||||
|
@ -0,0 +1,42 @@
|
||||
package com.jozufozu.flywheel.api.event;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.server.packs.resources.ResourceManager;
|
||||
import net.minecraftforge.eventbus.api.Event;
|
||||
import net.minecraftforge.fml.event.IModBusEvent;
|
||||
|
||||
/**
|
||||
* This event is posted to mod event buses.
|
||||
*/
|
||||
// TODO: This should not be a mod bus event. However, currently, it cannot be a Forge bus event since that bus is not started by the time this event needs to be posted.
|
||||
public final class EndClientResourceReloadEvent extends Event implements IModBusEvent {
|
||||
private final Minecraft minecraft;
|
||||
private final ResourceManager resourceManager;
|
||||
private final boolean initialReload;
|
||||
private final Optional<Throwable> error;
|
||||
|
||||
public EndClientResourceReloadEvent(Minecraft minecraft, ResourceManager resourceManager, boolean initialReload, Optional<Throwable> error) {
|
||||
this.minecraft = minecraft;
|
||||
this.resourceManager = resourceManager;
|
||||
this.initialReload = initialReload;
|
||||
this.error = error;
|
||||
}
|
||||
|
||||
public Minecraft getMinecraft() {
|
||||
return minecraft;
|
||||
}
|
||||
|
||||
public ResourceManager getResourceManager() {
|
||||
return resourceManager;
|
||||
}
|
||||
|
||||
public boolean isInitialReload() {
|
||||
return initialReload;
|
||||
}
|
||||
|
||||
public Optional<Throwable> getError() {
|
||||
return error;
|
||||
}
|
||||
}
|
@ -5,10 +5,14 @@ import org.jetbrains.annotations.Nullable;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraftforge.eventbus.api.Event;
|
||||
|
||||
public class ReloadRenderersEvent extends Event {
|
||||
/**
|
||||
* This event is posted to the Forge event bus.
|
||||
*/
|
||||
public final class ReloadLevelRendererEvent extends Event {
|
||||
@Nullable
|
||||
private final ClientLevel level;
|
||||
|
||||
public ReloadRenderersEvent(ClientLevel level) {
|
||||
public ReloadLevelRendererEvent(@Nullable ClientLevel level) {
|
||||
this.level = level;
|
||||
}
|
||||
|
@ -9,7 +9,10 @@ import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.client.renderer.RenderBuffers;
|
||||
import net.minecraftforge.eventbus.api.Event;
|
||||
|
||||
public class RenderStageEvent extends Event {
|
||||
/**
|
||||
* This event is posted to the Forge event bus.
|
||||
*/
|
||||
public final class RenderStageEvent extends Event {
|
||||
private final RenderContext context;
|
||||
private final RenderStage stage;
|
||||
|
||||
|
@ -1,46 +0,0 @@
|
||||
package com.jozufozu.flywheel.backend;
|
||||
|
||||
import com.jozufozu.flywheel.backend.compile.FlwPrograms;
|
||||
import com.jozufozu.flywheel.impl.BackendManagerImpl;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.server.packs.resources.ReloadableResourceManager;
|
||||
import net.minecraft.server.packs.resources.ResourceManager;
|
||||
import net.minecraft.server.packs.resources.ResourceManagerReloadListener;
|
||||
|
||||
/**
|
||||
* The main entity for loading shaders.
|
||||
*
|
||||
* <p>
|
||||
* This class is responsible for invoking the loading, parsing, and compilation stages.
|
||||
* </p>
|
||||
*/
|
||||
public class Loader implements ResourceManagerReloadListener {
|
||||
public static final Loader INSTANCE = new Loader();
|
||||
|
||||
private Loader() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResourceManagerReload(ResourceManager manager) {
|
||||
FlwPrograms.reload(manager);
|
||||
|
||||
// TODO: Move this to the impl package
|
||||
// TODO: To ensure this runs after all backends are ready, inject into Minecraft after the reload and before levelRenderer.allChanged()
|
||||
// Alternatively, consider adding API
|
||||
// TODO: This should reset all VisualizationManagerImpls, not just the one for the static client level
|
||||
BackendManagerImpl.refresh(Minecraft.getInstance().level);
|
||||
}
|
||||
|
||||
public static void init() {
|
||||
// Can be null when running data generators due to the unfortunate time we call this
|
||||
Minecraft minecraft = Minecraft.getInstance();
|
||||
if (minecraft == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (minecraft.getResourceManager() instanceof ReloadableResourceManager reloadable) {
|
||||
reloadable.registerReloadListener(INSTANCE);
|
||||
}
|
||||
}
|
||||
}
|
@ -14,7 +14,10 @@ import com.jozufozu.flywheel.glsl.generate.FnSignature;
|
||||
import com.jozufozu.flywheel.glsl.generate.GlslExpr;
|
||||
import com.jozufozu.flywheel.lib.material.MaterialIndices;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.server.packs.resources.ReloadableResourceManager;
|
||||
import net.minecraft.server.packs.resources.ResourceManager;
|
||||
import net.minecraft.server.packs.resources.ResourceManagerReloadListener;
|
||||
|
||||
public class FlwPrograms {
|
||||
private FlwPrograms() {
|
||||
@ -86,4 +89,28 @@ public class FlwPrograms {
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
public static class ResourceReloadListener implements ResourceManagerReloadListener {
|
||||
public static final ResourceReloadListener INSTANCE = new ResourceReloadListener();
|
||||
|
||||
private ResourceReloadListener() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResourceManagerReload(ResourceManager manager) {
|
||||
FlwPrograms.reload(manager);
|
||||
}
|
||||
|
||||
public static void register() {
|
||||
// Can be null when running data generators due to the unfortunate time we call this
|
||||
Minecraft minecraft = Minecraft.getInstance();
|
||||
if (minecraft == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (minecraft.getResourceManager() instanceof ReloadableResourceManager reloadable) {
|
||||
reloadable.registerReloadListener(INSTANCE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -104,12 +104,11 @@ public abstract class AbstractInstancer<I extends Instance> implements Instancer
|
||||
deleted.clear();
|
||||
}
|
||||
|
||||
public void delete() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AbstractInstancer[" + getInstanceCount() + ']';
|
||||
}
|
||||
|
||||
public void delete() {
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -33,7 +33,6 @@ public abstract class InstancerStorage<N extends AbstractInstancer<?>> {
|
||||
*/
|
||||
private final Object creationLock = new Object();
|
||||
|
||||
|
||||
/**
|
||||
* A list of initialized instancers.
|
||||
* <br>
|
||||
|
@ -6,7 +6,7 @@ import java.util.Set;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.jozufozu.flywheel.api.event.ReloadRenderersEvent;
|
||||
import com.jozufozu.flywheel.api.event.ReloadLevelRendererEvent;
|
||||
import com.jozufozu.flywheel.api.uniform.ShaderUniforms;
|
||||
import com.jozufozu.flywheel.gl.buffer.GlBuffer;
|
||||
import com.jozufozu.flywheel.gl.shader.GlProgram;
|
||||
@ -66,7 +66,7 @@ public class UniformBuffer {
|
||||
buffer.delete();
|
||||
}
|
||||
|
||||
public static void onReloadRenderers(ReloadRenderersEvent event) {
|
||||
public static void onReloadLevelRenderer(ReloadLevelRendererEvent event) {
|
||||
if (instance != null) {
|
||||
instance.delete();
|
||||
instance = null;
|
||||
|
@ -44,7 +44,7 @@ public class BatchingEngine extends AbstractEngine {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderCrumblingInstances(TaskExecutor executor, RenderContext context, List<CrumblingBlock> crumblingBlocks) {
|
||||
public void renderCrumbling(TaskExecutor executor, RenderContext context, List<CrumblingBlock> crumblingBlocks) {
|
||||
executor.syncUntil(flushFlag::isRaised);
|
||||
|
||||
var batchContext = BatchContext.create(context, this.renderOrigin);
|
||||
|
@ -4,7 +4,7 @@ import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.jozufozu.flywheel.api.event.ReloadRenderersEvent;
|
||||
import com.jozufozu.flywheel.api.event.ReloadLevelRendererEvent;
|
||||
import com.jozufozu.flywheel.api.event.RenderStage;
|
||||
import com.jozufozu.flywheel.api.vertex.ReusableVertexList;
|
||||
import com.jozufozu.flywheel.api.vertex.VertexListProvider;
|
||||
@ -172,7 +172,7 @@ public class DrawBuffer {
|
||||
buffer = null;
|
||||
}
|
||||
|
||||
public static void onReloadRenderers(ReloadRenderersEvent event) {
|
||||
public static void onReloadRenderers(ReloadLevelRendererEvent event) {
|
||||
ALL.forEach(DrawBuffer::free);
|
||||
}
|
||||
|
||||
|
@ -15,31 +15,6 @@ import com.jozufozu.flywheel.lib.util.Pair;
|
||||
public class IndirectDrawManager extends InstancerStorage<IndirectInstancer<?>> {
|
||||
public final Map<Pair<InstanceType<?>, VertexType>, IndirectCullingGroup<?>> renderLists = new HashMap<>();
|
||||
|
||||
public void flush() {
|
||||
super.flush();
|
||||
|
||||
for (IndirectCullingGroup<?> value : renderLists.values()) {
|
||||
value.beginFrame();
|
||||
}
|
||||
}
|
||||
|
||||
public void invalidate() {
|
||||
super.invalidate();
|
||||
|
||||
renderLists.values()
|
||||
.forEach(IndirectCullingGroup::delete);
|
||||
renderLists.clear();
|
||||
}
|
||||
|
||||
public boolean hasStage(RenderStage stage) {
|
||||
for (var list : renderLists.values()) {
|
||||
if (list.hasStage(stage)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <I extends Instance> IndirectInstancer<?> create(InstanceType<I> type) {
|
||||
return new IndirectInstancer<>(type);
|
||||
@ -59,4 +34,31 @@ public class IndirectDrawManager extends InstancerStorage<IndirectInstancer<?>>
|
||||
break; // TODO: support multiple meshes per model
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasStage(RenderStage stage) {
|
||||
for (var list : renderLists.values()) {
|
||||
if (list.hasStage(stage)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() {
|
||||
super.flush();
|
||||
|
||||
for (IndirectCullingGroup<?> value : renderLists.values()) {
|
||||
value.beginFrame();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidate() {
|
||||
super.invalidate();
|
||||
|
||||
renderLists.values()
|
||||
.forEach(IndirectCullingGroup::delete);
|
||||
renderLists.clear();
|
||||
}
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ public class IndirectEngine extends AbstractEngine {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderCrumblingInstances(TaskExecutor executor, RenderContext context, List<CrumblingBlock> crumblingBlocks) {
|
||||
public void renderCrumbling(TaskExecutor executor, RenderContext context, List<CrumblingBlock> crumblingBlocks) {
|
||||
// TODO: implement
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,6 @@ import com.jozufozu.flywheel.backend.engine.InstancerKey;
|
||||
import com.jozufozu.flywheel.backend.engine.InstancerStorage;
|
||||
|
||||
public class InstancedDrawManager extends InstancerStorage<InstancedInstancer<?>> {
|
||||
|
||||
/**
|
||||
* The set of draw calls to make in each {@link RenderStage}.
|
||||
*/
|
||||
|
@ -79,7 +79,7 @@ public class InstancedInstancer<I extends Instance> extends AbstractInstancer<I>
|
||||
|
||||
changed.clear();
|
||||
} catch (Exception e) {
|
||||
Flywheel.LOGGER.error("Error updating GPUInstancer:", e);
|
||||
Flywheel.LOGGER.error("Error updating InstancedInstancer:", e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -111,6 +111,7 @@ public class InstancedInstancer<I extends Instance> extends AbstractInstancer<I>
|
||||
vao.bindAttributes(1, startAttrib, instanceFormat.attributes());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete() {
|
||||
vbo.delete();
|
||||
vbo = null;
|
||||
|
@ -68,11 +68,7 @@ public class InstancingEngine extends AbstractEngine {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderCrumblingInstances(TaskExecutor executor, RenderContext context, List<CrumblingBlock> crumblingBlocks) {
|
||||
if (crumblingBlocks.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
public void renderCrumbling(TaskExecutor executor, RenderContext context, List<CrumblingBlock> crumblingBlocks) {
|
||||
// Need to wait for flush before we can inspect instancer state.
|
||||
executor.syncUntil(flushFlag::isRaised);
|
||||
|
||||
|
@ -2,11 +2,9 @@ package com.jozufozu.flywheel.config;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import com.jozufozu.flywheel.Flywheel;
|
||||
import com.jozufozu.flywheel.api.backend.Backend;
|
||||
import com.jozufozu.flywheel.lib.util.ResourceUtil;
|
||||
import com.mojang.brigadier.StringReader;
|
||||
@ -14,31 +12,17 @@ import com.mojang.brigadier.arguments.ArgumentType;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import com.mojang.brigadier.exceptions.DynamicCommandExceptionType;
|
||||
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
|
||||
import com.mojang.brigadier.suggestion.Suggestions;
|
||||
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
|
||||
|
||||
import net.minecraft.ResourceLocationException;
|
||||
import net.minecraft.commands.SharedSuggestionProvider;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
public class BackendArgument implements ArgumentType<Backend> {
|
||||
private static final List<String> STRING_IDS = Backend.REGISTRY.getAllIds()
|
||||
.stream()
|
||||
.map(rl -> {
|
||||
if (Flywheel.ID
|
||||
.equals(rl.getNamespace())) {
|
||||
return rl.getPath();
|
||||
} else {
|
||||
return rl.toString();
|
||||
}
|
||||
})
|
||||
.toList();
|
||||
private static final List<String> EXAMPLES = List.of("off", "flywheel:off", "instancing");
|
||||
|
||||
private static final SimpleCommandExceptionType ERROR_INVALID = new SimpleCommandExceptionType(Component.translatable("argument.id.invalid"));
|
||||
|
||||
public static final DynamicCommandExceptionType ERROR_UNKNOWN_BACKEND = new DynamicCommandExceptionType(arg -> {
|
||||
private static final DynamicCommandExceptionType ERROR_UNKNOWN_BACKEND = new DynamicCommandExceptionType(arg -> {
|
||||
return Component.literal("Unknown backend '" + arg + "'");
|
||||
});
|
||||
|
||||
@ -46,7 +30,7 @@ public class BackendArgument implements ArgumentType<Backend> {
|
||||
|
||||
@Override
|
||||
public Backend parse(StringReader reader) throws CommandSyntaxException {
|
||||
ResourceLocation id = getRead(reader);
|
||||
ResourceLocation id = ResourceUtil.readFlywheelDefault(reader);
|
||||
Backend backend = Backend.REGISTRY.get(id);
|
||||
|
||||
if (backend == null) {
|
||||
@ -56,34 +40,20 @@ public class BackendArgument implements ArgumentType<Backend> {
|
||||
return backend;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copied from {@link ResourceLocation#read}, but defaults to flywheel namespace.
|
||||
*/
|
||||
@NotNull
|
||||
private static ResourceLocation getRead(StringReader reader) throws CommandSyntaxException {
|
||||
int i = reader.getCursor();
|
||||
|
||||
while(reader.canRead() && ResourceLocation.isAllowedInResourceLocation(reader.peek())) {
|
||||
reader.skip();
|
||||
}
|
||||
|
||||
String s = reader.getString().substring(i, reader.getCursor());
|
||||
|
||||
try {
|
||||
return ResourceUtil.defaultToFlywheelNamespace(s);
|
||||
} catch (ResourceLocationException resourcelocationexception) {
|
||||
reader.setCursor(i);
|
||||
throw ERROR_INVALID.createWithContext(reader);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <S> CompletableFuture<Suggestions> listSuggestions(CommandContext<S> context, SuggestionsBuilder builder) {
|
||||
return SharedSuggestionProvider.suggest(STRING_IDS, builder);
|
||||
String input = builder.getRemaining().toLowerCase(Locale.ROOT);
|
||||
for (ResourceLocation id : Backend.REGISTRY.getAllIds()) {
|
||||
String idStr = id.toString();
|
||||
if (SharedSuggestionProvider.matchesSubStr(input, idStr) || SharedSuggestionProvider.matchesSubStr(input, id.getPath())) {
|
||||
builder.suggest(idStr);
|
||||
}
|
||||
}
|
||||
return builder.buildFuture();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> getExamples() {
|
||||
return STRING_IDS;
|
||||
return EXAMPLES;
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ public class FlwConfig {
|
||||
public final ClientConfig client;
|
||||
private final ForgeConfigSpec clientSpec;
|
||||
|
||||
public FlwConfig() {
|
||||
private FlwConfig() {
|
||||
Pair<ClientConfig, ForgeConfigSpec> clientPair = new ForgeConfigSpec.Builder().configure(ClientConfig::new);
|
||||
this.client = clientPair.getLeft();
|
||||
clientSpec = clientPair.getRight();
|
||||
@ -74,7 +74,7 @@ public class FlwConfig {
|
||||
public final ConfigValue<String> backend;
|
||||
public final BooleanValue limitUpdates;
|
||||
|
||||
public ClientConfig(ForgeConfigSpec.Builder builder) {
|
||||
private ClientConfig(ForgeConfigSpec.Builder builder) {
|
||||
backend = builder.comment("Select the backend to use.")
|
||||
.define("backend", Backend.REGISTRY.getIdOrThrow(BackendManager.getDefaultBackend()).toString());
|
||||
|
||||
|
@ -2,21 +2,21 @@ package com.jozufozu.flywheel.extension;
|
||||
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.level.Level;
|
||||
|
||||
public interface ClientLevelExtension {
|
||||
|
||||
public interface LevelExtension {
|
||||
/**
|
||||
* Get an iterator over all entities in this level.
|
||||
*
|
||||
* <p>
|
||||
* Normally, this would be accomplished by {@link ClientLevel#entitiesForRendering()}, but the output of that
|
||||
* method is filtered of entities that are rendered by flywheel. This interface provides a workaround.
|
||||
* Normally, this would be accomplished by {@link ClientLevel#entitiesForRendering}, but the output of that
|
||||
* method does not include entities that are rendered by Flywheel. This interface provides a workaround.
|
||||
* </p>
|
||||
* @return An iterator over all entities in the level, including entities that are rendered by flywheel.
|
||||
* @return An iterator over all entities in the level, including entities that are rendered by Flywheel.
|
||||
*/
|
||||
Iterable<Entity> flywheel$getAllLoadedEntities();
|
||||
|
||||
static Iterable<Entity> getAllLoadedEntities(ClientLevel level) {
|
||||
return ((ClientLevelExtension) level).flywheel$getAllLoadedEntities();
|
||||
static Iterable<Entity> getAllLoadedEntities(Level level) {
|
||||
return ((LevelExtension) level).flywheel$getAllLoadedEntities();
|
||||
}
|
||||
}
|
@ -85,7 +85,7 @@ public class SourceFile implements SourceComponent {
|
||||
|
||||
ResourceLocation location;
|
||||
try {
|
||||
location = ResourceUtil.defaultToFlywheelNamespace(string);
|
||||
location = ResourceUtil.parseFlywheelDefault(string);
|
||||
} catch (ResourceLocationException e) {
|
||||
failures.add(Pair.of(fileSpan, new LoadError.MalformedInclude(e)));
|
||||
continue;
|
||||
|
@ -1,11 +1,11 @@
|
||||
package com.jozufozu.flywheel.impl;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import com.jozufozu.flywheel.Flywheel;
|
||||
import com.jozufozu.flywheel.api.backend.Backend;
|
||||
import com.jozufozu.flywheel.api.event.ReloadRenderersEvent;
|
||||
import com.jozufozu.flywheel.api.event.EndClientResourceReloadEvent;
|
||||
import com.jozufozu.flywheel.api.event.ReloadLevelRendererEvent;
|
||||
import com.jozufozu.flywheel.backend.Backends;
|
||||
import com.jozufozu.flywheel.config.FlwConfig;
|
||||
import com.jozufozu.flywheel.impl.visualization.VisualizationManagerImpl;
|
||||
@ -59,19 +59,7 @@ public final class BackendManagerImpl {
|
||||
return Backends.INDIRECT;
|
||||
}
|
||||
|
||||
public static void onReloadRenderers(ReloadRenderersEvent event) {
|
||||
refresh(event.getLevel());
|
||||
}
|
||||
|
||||
public static void refresh(@Nullable ClientLevel level) {
|
||||
backend = chooseBackend();
|
||||
|
||||
if (level != null) {
|
||||
VisualizationManagerImpl.reset(level);
|
||||
}
|
||||
}
|
||||
|
||||
private static Backend chooseBackend() {
|
||||
private static void chooseBackend() {
|
||||
var preferred = FlwConfig.get().getBackend();
|
||||
var actual = preferred.findFallback();
|
||||
|
||||
@ -79,7 +67,7 @@ public final class BackendManagerImpl {
|
||||
LOGGER.warn("Flywheel backend fell back from '{}' to '{}'", Backend.REGISTRY.getIdOrThrow(preferred), Backend.REGISTRY.getIdOrThrow(actual));
|
||||
}
|
||||
|
||||
return actual;
|
||||
backend = actual;
|
||||
}
|
||||
|
||||
public static String getBackendString() {
|
||||
@ -93,4 +81,22 @@ public final class BackendManagerImpl {
|
||||
public static void init() {
|
||||
CrashReportCallables.registerCrashCallable("Flywheel Backend", BackendManagerImpl::getBackendString);
|
||||
}
|
||||
|
||||
public static void onEndClientResourceReload(EndClientResourceReloadEvent event) {
|
||||
if (event.getError().isPresent()) {
|
||||
return;
|
||||
}
|
||||
|
||||
chooseBackend();
|
||||
VisualizationManagerImpl.resetAll();
|
||||
}
|
||||
|
||||
public static void onReloadLevelRenderer(ReloadLevelRendererEvent event) {
|
||||
chooseBackend();
|
||||
|
||||
ClientLevel level = event.getLevel();
|
||||
if (level != null) {
|
||||
VisualizationManagerImpl.reset(level);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ import com.jozufozu.flywheel.api.visual.TickableVisual;
|
||||
import com.jozufozu.flywheel.api.visualization.VisualManager;
|
||||
import com.jozufozu.flywheel.api.visualization.VisualizationLevel;
|
||||
import com.jozufozu.flywheel.api.visualization.VisualizationManager;
|
||||
import com.jozufozu.flywheel.extension.ClientLevelExtension;
|
||||
import com.jozufozu.flywheel.extension.LevelExtension;
|
||||
import com.jozufozu.flywheel.impl.task.FlwTaskExecutor;
|
||||
import com.jozufozu.flywheel.impl.visualization.manager.BlockEntityVisualManager;
|
||||
import com.jozufozu.flywheel.impl.visualization.manager.EffectVisualManager;
|
||||
@ -32,10 +32,10 @@ import com.jozufozu.flywheel.lib.util.LevelAttached;
|
||||
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.core.Vec3i;
|
||||
import net.minecraft.server.level.BlockDestructionProgress;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
|
||||
@ -88,6 +88,11 @@ public class VisualizationManagerImpl implements VisualizationManager {
|
||||
.then(engine.createFramePlan())
|
||||
.then(RaisePlan.raise(frameFlag))
|
||||
.simplify();
|
||||
|
||||
if (level instanceof Level l) {
|
||||
LevelExtension.getAllLoadedEntities(l)
|
||||
.forEach(entities::queueAdd);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean supportsVisualization(@Nullable LevelAccessor level) {
|
||||
@ -127,19 +132,14 @@ public class VisualizationManagerImpl implements VisualizationManager {
|
||||
return MANAGERS.get(level);
|
||||
}
|
||||
|
||||
// TODO: Consider making this reset action reuse the existing added game objects instead of readding them, potentially by keeping the same VisualizationManagerImpl and not fully deleting it
|
||||
// TODO: Consider changing parameter type to Level since it is also possible to get all entities from it
|
||||
public static void reset(ClientLevel level) {
|
||||
// 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);
|
||||
VisualizationManagerImpl manager = get(level);
|
||||
if (manager == null) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Block entities are loaded while chunks are baked.
|
||||
// Entities are loaded with the level, so when chunks are reloaded they need to be re-added.
|
||||
ClientLevelExtension.getAllLoadedEntities(level)
|
||||
.forEach(manager.getEntities()::queueAdd);
|
||||
public static void resetAll() {
|
||||
MANAGERS.reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -239,7 +239,9 @@ public class VisualizationManagerImpl implements VisualizationManager {
|
||||
crumblingBlocks.add(new Engine.CrumblingBlock(maxDestruction.getProgress(), maxDestruction.getPos(), instances));
|
||||
}
|
||||
|
||||
engine.renderCrumblingInstances(taskExecutor, context, crumblingBlocks);
|
||||
if (!crumblingBlocks.isEmpty()) {
|
||||
engine.renderCrumbling(taskExecutor, context, crumblingBlocks);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -0,0 +1,76 @@
|
||||
package com.jozufozu.flywheel.lib.memory;
|
||||
|
||||
import java.lang.ref.Cleaner;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
non-sealed abstract class AbstractMemoryBlockImpl implements MemoryBlock {
|
||||
static final Cleaner CLEANER = Cleaner.create();
|
||||
|
||||
final long ptr;
|
||||
final long size;
|
||||
|
||||
boolean freed;
|
||||
|
||||
AbstractMemoryBlockImpl(long ptr, long size) {
|
||||
this.ptr = ptr;
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long ptr() {
|
||||
return ptr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFreed() {
|
||||
return freed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void copyTo(MemoryBlock block) {
|
||||
long bytes = Math.min(size, block.size());
|
||||
copyTo(block.ptr(), bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void copyTo(long ptr, long bytes) {
|
||||
MemoryUtil.memCopy(this.ptr, ptr, bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void copyTo(long ptr) {
|
||||
copyTo(ptr, size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
MemoryUtil.memSet(ptr, 0, size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer asBuffer() {
|
||||
int intSize = (int) size;
|
||||
if (intSize != size) {
|
||||
throw new UnsupportedOperationException("Cannot create buffer with long capacity!");
|
||||
}
|
||||
return MemoryUtil.memByteBuffer(ptr, intSize);
|
||||
}
|
||||
|
||||
void freeInner() {
|
||||
FlwMemoryTracker._freeCPUMemory(size);
|
||||
freed = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void free() {
|
||||
FlwMemoryTracker.free(ptr);
|
||||
freeInner();
|
||||
}
|
||||
}
|
@ -5,16 +5,23 @@ import java.lang.ref.Cleaner;
|
||||
import com.jozufozu.flywheel.Flywheel;
|
||||
import com.jozufozu.flywheel.lib.util.StringUtil;
|
||||
|
||||
class DebugMemoryBlockImpl extends MemoryBlockImpl {
|
||||
class DebugMemoryBlockImpl extends AbstractMemoryBlockImpl {
|
||||
final Cleaner cleaner;
|
||||
final CleaningAction cleaningAction;
|
||||
final Cleaner.Cleanable cleanable;
|
||||
|
||||
DebugMemoryBlockImpl(long ptr, long size, Cleaner cleaner) {
|
||||
DebugMemoryBlockImpl(long ptr, long size, Cleaner cleaner, int skipFrames) {
|
||||
super(ptr, size);
|
||||
cleaningAction = new CleaningAction(ptr, size, getStackTrace());
|
||||
this.cleaner = cleaner;
|
||||
cleaningAction = new CleaningAction(ptr, size, getStackTrace(skipFrames + 1));
|
||||
cleanable = cleaner.register(this, cleaningAction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTracked() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
void freeInner() {
|
||||
super.freeInner();
|
||||
@ -22,24 +29,37 @@ class DebugMemoryBlockImpl extends MemoryBlockImpl {
|
||||
cleanable.clean();
|
||||
}
|
||||
|
||||
static StackWalker.StackFrame[] getStackTrace() {
|
||||
// skip 4 frames to get to the caller:
|
||||
@Override
|
||||
public MemoryBlock realloc(long size) {
|
||||
MemoryBlock block = new DebugMemoryBlockImpl(FlwMemoryTracker.realloc(ptr, size), size, cleaner, 1);
|
||||
FlwMemoryTracker._allocCPUMemory(block.size());
|
||||
freeInner();
|
||||
return block;
|
||||
}
|
||||
|
||||
static StackWalker.StackFrame[] getStackTrace(int skipFrames) {
|
||||
// for DebugMemoryBlockImpl::realloc, skip 3 frames to get the allocation site:
|
||||
// - this method
|
||||
// - DebugMemoryBlockImpl::new
|
||||
// - DebugMemoryBlockImpl::realloc
|
||||
// - {caller is here}
|
||||
// for DebugMemoryBlockImpl::malloc/calloc, skip 4 frames to get the allocation site:
|
||||
// - this method
|
||||
// - DebugMemoryBlockImpl::new
|
||||
// - DebugMemoryBlockImpl::malloc/calloc
|
||||
// - MemoryBlock::malloc/calloc
|
||||
// - {caller is here}
|
||||
return StackWalker.getInstance().walk(s -> s.skip(4).toArray(StackWalker.StackFrame[]::new));
|
||||
return StackWalker.getInstance().walk(s -> s.skip(skipFrames + 1).toArray(StackWalker.StackFrame[]::new));
|
||||
}
|
||||
|
||||
static MemoryBlock malloc(long size) {
|
||||
MemoryBlock block = new DebugMemoryBlockImpl(FlwMemoryTracker.malloc(size), size, FlwMemoryTracker.CLEANER);
|
||||
MemoryBlock block = new DebugMemoryBlockImpl(FlwMemoryTracker.malloc(size), size, CLEANER, 2);
|
||||
FlwMemoryTracker._allocCPUMemory(block.size());
|
||||
return block;
|
||||
}
|
||||
|
||||
static MemoryBlock calloc(long num, long size) {
|
||||
MemoryBlock block = new DebugMemoryBlockImpl(FlwMemoryTracker.calloc(num, size), num * size, FlwMemoryTracker.CLEANER);
|
||||
MemoryBlock block = new DebugMemoryBlockImpl(FlwMemoryTracker.calloc(num, size), num * size, CLEANER, 2);
|
||||
FlwMemoryTracker._allocCPUMemory(block.size());
|
||||
return block;
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
package com.jozufozu.flywheel.lib.memory;
|
||||
|
||||
import java.lang.ref.Cleaner;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
@ -10,8 +9,6 @@ import com.jozufozu.flywheel.lib.util.StringUtil;
|
||||
public final class FlwMemoryTracker {
|
||||
public static final boolean DEBUG_MEMORY_SAFETY = System.getProperty("flw.debugMemorySafety") != null;
|
||||
|
||||
static final Cleaner CLEANER = Cleaner.create();
|
||||
|
||||
private static final AtomicLong CPU_MEMORY = new AtomicLong(0);
|
||||
private static final AtomicLong GPU_MEMORY = new AtomicLong(0);
|
||||
|
||||
|
@ -2,7 +2,7 @@ package com.jozufozu.flywheel.lib.memory;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public sealed interface MemoryBlock permits MemoryBlockImpl {
|
||||
public sealed interface MemoryBlock permits AbstractMemoryBlockImpl {
|
||||
long ptr();
|
||||
|
||||
long size();
|
||||
@ -11,6 +11,8 @@ public sealed interface MemoryBlock permits MemoryBlockImpl {
|
||||
|
||||
boolean isTracked();
|
||||
|
||||
void copyTo(MemoryBlock block);
|
||||
|
||||
void copyTo(long ptr, long bytes);
|
||||
|
||||
void copyTo(long ptr);
|
||||
@ -21,8 +23,6 @@ public sealed interface MemoryBlock permits MemoryBlockImpl {
|
||||
|
||||
MemoryBlock realloc(long size);
|
||||
|
||||
MemoryBlock reallocTracked(long size);
|
||||
|
||||
void free();
|
||||
|
||||
static MemoryBlock malloc(long size) {
|
||||
|
@ -1,33 +1,8 @@
|
||||
package com.jozufozu.flywheel.lib.memory;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
non-sealed class MemoryBlockImpl implements MemoryBlock {
|
||||
final long ptr;
|
||||
final long size;
|
||||
|
||||
boolean freed;
|
||||
|
||||
class MemoryBlockImpl extends AbstractMemoryBlockImpl {
|
||||
MemoryBlockImpl(long ptr, long size) {
|
||||
this.ptr = ptr;
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long ptr() {
|
||||
return ptr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFreed() {
|
||||
return freed;
|
||||
super(ptr, size);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -35,35 +10,6 @@ non-sealed class MemoryBlockImpl implements MemoryBlock {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void copyTo(long ptr, long bytes) {
|
||||
MemoryUtil.memCopy(this.ptr, ptr, bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void copyTo(long ptr) {
|
||||
copyTo(ptr, size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
MemoryUtil.memSet(ptr, 0, size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer asBuffer() {
|
||||
int intSize = (int) size;
|
||||
if (intSize != size) {
|
||||
throw new UnsupportedOperationException("Cannot create buffer with long capacity!");
|
||||
}
|
||||
return MemoryUtil.memByteBuffer(ptr, intSize);
|
||||
}
|
||||
|
||||
void freeInner() {
|
||||
FlwMemoryTracker._freeCPUMemory(size);
|
||||
freed = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MemoryBlock realloc(long size) {
|
||||
MemoryBlock block = new MemoryBlockImpl(FlwMemoryTracker.realloc(ptr, size), size);
|
||||
@ -72,20 +18,6 @@ non-sealed class MemoryBlockImpl implements MemoryBlock {
|
||||
return block;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MemoryBlock reallocTracked(long size) {
|
||||
MemoryBlock block = new TrackedMemoryBlockImpl(FlwMemoryTracker.realloc(ptr, size), size, FlwMemoryTracker.CLEANER);
|
||||
FlwMemoryTracker._allocCPUMemory(block.size());
|
||||
freeInner();
|
||||
return block;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void free() {
|
||||
FlwMemoryTracker.free(ptr);
|
||||
freeInner();
|
||||
}
|
||||
|
||||
static MemoryBlock malloc(long size) {
|
||||
MemoryBlock block = new MemoryBlockImpl(FlwMemoryTracker.malloc(size), size);
|
||||
FlwMemoryTracker._allocCPUMemory(block.size());
|
||||
|
@ -2,12 +2,14 @@ package com.jozufozu.flywheel.lib.memory;
|
||||
|
||||
import java.lang.ref.Cleaner;
|
||||
|
||||
class TrackedMemoryBlockImpl extends MemoryBlockImpl {
|
||||
class TrackedMemoryBlockImpl extends AbstractMemoryBlockImpl {
|
||||
final Cleaner cleaner;
|
||||
final CleaningAction cleaningAction;
|
||||
final Cleaner.Cleanable cleanable;
|
||||
|
||||
TrackedMemoryBlockImpl(long ptr, long size, Cleaner cleaner) {
|
||||
super(ptr, size);
|
||||
this.cleaner = cleaner;
|
||||
cleaningAction = new CleaningAction(ptr, size);
|
||||
cleanable = cleaner.register(this, cleaningAction);
|
||||
}
|
||||
@ -24,14 +26,22 @@ class TrackedMemoryBlockImpl extends MemoryBlockImpl {
|
||||
cleanable.clean();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MemoryBlock realloc(long size) {
|
||||
MemoryBlock block = new TrackedMemoryBlockImpl(FlwMemoryTracker.realloc(ptr, size), size, cleaner);
|
||||
FlwMemoryTracker._allocCPUMemory(block.size());
|
||||
freeInner();
|
||||
return block;
|
||||
}
|
||||
|
||||
static MemoryBlock malloc(long size) {
|
||||
MemoryBlock block = new TrackedMemoryBlockImpl(FlwMemoryTracker.malloc(size), size, FlwMemoryTracker.CLEANER);
|
||||
MemoryBlock block = new TrackedMemoryBlockImpl(FlwMemoryTracker.malloc(size), size, CLEANER);
|
||||
FlwMemoryTracker._allocCPUMemory(block.size());
|
||||
return block;
|
||||
}
|
||||
|
||||
static MemoryBlock calloc(long num, long size) {
|
||||
MemoryBlock block = new TrackedMemoryBlockImpl(FlwMemoryTracker.calloc(num, size), num * size, FlwMemoryTracker.CLEANER);
|
||||
MemoryBlock block = new TrackedMemoryBlockImpl(FlwMemoryTracker.calloc(num, size), num * size, CLEANER);
|
||||
FlwMemoryTracker._allocCPUMemory(block.size());
|
||||
return block;
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ import java.util.function.Function;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import com.jozufozu.flywheel.api.event.ReloadRenderersEvent;
|
||||
import com.jozufozu.flywheel.api.event.EndClientResourceReloadEvent;
|
||||
import com.jozufozu.flywheel.api.model.Model;
|
||||
|
||||
public class ModelCache<T> {
|
||||
@ -31,7 +31,7 @@ public class ModelCache<T> {
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static void onReloadRenderers(ReloadRenderersEvent event) {
|
||||
public static void onEndClientResourceReload(EndClientResourceReloadEvent event) {
|
||||
for (ModelCache<?> cache : ALL) {
|
||||
cache.clear();
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ import java.util.function.Supplier;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.jozufozu.flywheel.api.event.ReloadRenderersEvent;
|
||||
import com.jozufozu.flywheel.api.event.EndClientResourceReloadEvent;
|
||||
import com.jozufozu.flywheel.api.model.Model;
|
||||
|
||||
public class ModelHolder {
|
||||
@ -51,7 +51,7 @@ public class ModelHolder {
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static void onReloadRenderers(ReloadRenderersEvent event) {
|
||||
public static void onEndClientResourceReload(EndClientResourceReloadEvent event) {
|
||||
for (ModelHolder holder : ALL) {
|
||||
holder.clear();
|
||||
}
|
||||
|
@ -56,9 +56,11 @@ public final class BakedModelBufferer {
|
||||
blockRenderer.tesselateBlock(renderWorld, model, state, BlockPos.ZERO, poseStack, buffer, false, random, 42L, OverlayTexture.NO_OVERLAY, modelData, renderType);
|
||||
poseStack.popPose();
|
||||
|
||||
RenderedBuffer data = buffer.end();
|
||||
resultConsumer.accept(renderType, data);
|
||||
data.release();
|
||||
RenderedBuffer data = buffer.endOrDiscardIfEmpty();
|
||||
if (data != null) {
|
||||
resultConsumer.accept(renderType, data);
|
||||
data.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -89,12 +91,16 @@ public final class BakedModelBufferer {
|
||||
blockRenderer.tesselateBlock(renderWorld, model, state, BlockPos.ZERO, poseStack, shadeSeparatingWrapper, false, random, 42L, OverlayTexture.NO_OVERLAY, modelData, renderType);
|
||||
poseStack.popPose();
|
||||
|
||||
RenderedBuffer shadedData = shadedBuffer.end();
|
||||
RenderedBuffer unshadedData = unshadedBuffer.end();
|
||||
resultConsumer.accept(renderType, true, shadedData);
|
||||
shadedData.release();
|
||||
resultConsumer.accept(renderType, false, unshadedData);
|
||||
unshadedData.release();
|
||||
RenderedBuffer shadedData = shadedBuffer.endOrDiscardIfEmpty();
|
||||
if (shadedData != null) {
|
||||
resultConsumer.accept(renderType, true, shadedData);
|
||||
shadedData.release();
|
||||
}
|
||||
RenderedBuffer unshadedData = unshadedBuffer.endOrDiscardIfEmpty();
|
||||
if (unshadedData != null) {
|
||||
resultConsumer.accept(renderType, false, unshadedData);
|
||||
unshadedData.release();
|
||||
}
|
||||
}
|
||||
|
||||
shadeSeparatingWrapper.clear();
|
||||
@ -163,9 +169,11 @@ public final class BakedModelBufferer {
|
||||
for (int layerIndex = 0; layerIndex < CHUNK_LAYER_AMOUNT; layerIndex++) {
|
||||
RenderType renderType = CHUNK_LAYERS[layerIndex];
|
||||
BufferBuilder buffer = buffers[layerIndex];
|
||||
RenderedBuffer data = buffer.end();
|
||||
resultConsumer.accept(renderType, data);
|
||||
data.release();
|
||||
RenderedBuffer data = buffer.endOrDiscardIfEmpty();
|
||||
if (data != null) {
|
||||
resultConsumer.accept(renderType, data);
|
||||
data.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -224,12 +232,16 @@ public final class BakedModelBufferer {
|
||||
RenderType renderType = CHUNK_LAYERS[layerIndex];
|
||||
BufferBuilder shadedBuffer = shadedBuffers[layerIndex];
|
||||
BufferBuilder unshadedBuffer = unshadedBuffers[layerIndex];
|
||||
RenderedBuffer shadedData = shadedBuffer.end();
|
||||
RenderedBuffer unshadedData = unshadedBuffer.end();
|
||||
resultConsumer.accept(renderType, true, shadedData);
|
||||
shadedData.release();
|
||||
resultConsumer.accept(renderType, false, unshadedData);
|
||||
unshadedData.release();
|
||||
RenderedBuffer shadedData = shadedBuffer.endOrDiscardIfEmpty();
|
||||
if (shadedData != null) {
|
||||
resultConsumer.accept(renderType, true, shadedData);
|
||||
shadedData.release();
|
||||
}
|
||||
RenderedBuffer unshadedData = unshadedBuffer.endOrDiscardIfEmpty();
|
||||
if (unshadedBuffer != null) {
|
||||
resultConsumer.accept(renderType, false, unshadedData);
|
||||
unshadedData.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -81,23 +81,19 @@ public class BakedModelBuilder {
|
||||
|
||||
if (shadeSeparated) {
|
||||
ShadeSeparatedResultConsumer resultConsumer = (renderType, shaded, data) -> {
|
||||
if (!data.isEmpty()) {
|
||||
Material material = materialFunc.apply(renderType, shaded);
|
||||
if (material != null) {
|
||||
MemoryBlock meshData = ModelUtil.convertVanillaBuffer(data, VertexTypes.BLOCK);
|
||||
meshMapBuilder.put(material, new SimpleMesh(VertexTypes.BLOCK, meshData, "source=BakedModelBuilder," + "bakedModel=" + bakedModel + ",renderType=" + renderType + ",shaded=" + shaded));
|
||||
}
|
||||
Material material = materialFunc.apply(renderType, shaded);
|
||||
if (material != null) {
|
||||
MemoryBlock meshData = ModelUtil.convertVanillaBuffer(data, VertexTypes.BLOCK);
|
||||
meshMapBuilder.put(material, new SimpleMesh(VertexTypes.BLOCK, meshData, "source=BakedModelBuilder," + "bakedModel=" + bakedModel + ",renderType=" + renderType + ",shaded=" + shaded));
|
||||
}
|
||||
};
|
||||
BakedModelBufferer.bufferSingleShadeSeparated(ModelUtil.VANILLA_RENDERER.getModelRenderer(), renderWorld, bakedModel, blockState, poseStack, modelData, resultConsumer);
|
||||
} else {
|
||||
ResultConsumer resultConsumer = (renderType, data) -> {
|
||||
if (!data.isEmpty()) {
|
||||
Material material = materialFunc.apply(renderType, true);
|
||||
if (material != null) {
|
||||
MemoryBlock meshData = ModelUtil.convertVanillaBuffer(data, VertexTypes.BLOCK);
|
||||
meshMapBuilder.put(material, new SimpleMesh(VertexTypes.BLOCK, meshData, "source=BakedModelBuilder," + "bakedModel=" + bakedModel + ",renderType=" + renderType));
|
||||
}
|
||||
Material material = materialFunc.apply(renderType, true);
|
||||
if (material != null) {
|
||||
MemoryBlock meshData = ModelUtil.convertVanillaBuffer(data, VertexTypes.BLOCK);
|
||||
meshMapBuilder.put(material, new SimpleMesh(VertexTypes.BLOCK, meshData, "source=BakedModelBuilder," + "bakedModel=" + bakedModel + ",renderType=" + renderType));
|
||||
}
|
||||
};
|
||||
BakedModelBufferer.bufferSingle(ModelUtil.VANILLA_RENDERER.getModelRenderer(), renderWorld, bakedModel, blockState, poseStack, modelData, resultConsumer);
|
||||
|
@ -70,23 +70,19 @@ public class BlockModelBuilder {
|
||||
|
||||
if (shadeSeparated) {
|
||||
ShadeSeparatedResultConsumer resultConsumer = (renderType, shaded, data) -> {
|
||||
if (!data.isEmpty()) {
|
||||
Material material = materialFunc.apply(renderType, shaded);
|
||||
if (material != null) {
|
||||
MemoryBlock meshData = ModelUtil.convertVanillaBuffer(data, VertexTypes.BLOCK);
|
||||
meshMapBuilder.put(material, new SimpleMesh(VertexTypes.BLOCK, meshData, "source=BlockModelBuilder," + "blockState=" + state + ",renderType=" + renderType + ",shaded=" + shaded));
|
||||
}
|
||||
Material material = materialFunc.apply(renderType, shaded);
|
||||
if (material != null) {
|
||||
MemoryBlock meshData = ModelUtil.convertVanillaBuffer(data, VertexTypes.BLOCK);
|
||||
meshMapBuilder.put(material, new SimpleMesh(VertexTypes.BLOCK, meshData, "source=BlockModelBuilder," + "blockState=" + state + ",renderType=" + renderType + ",shaded=" + shaded));
|
||||
}
|
||||
};
|
||||
BakedModelBufferer.bufferBlockShadeSeparated(ModelUtil.VANILLA_RENDERER, renderWorld, state, poseStack, modelData, resultConsumer);
|
||||
} else {
|
||||
ResultConsumer resultConsumer = (renderType, data) -> {
|
||||
if (!data.isEmpty()) {
|
||||
Material material = materialFunc.apply(renderType, true);
|
||||
if (material != null) {
|
||||
MemoryBlock meshData = ModelUtil.convertVanillaBuffer(data, VertexTypes.BLOCK);
|
||||
meshMapBuilder.put(material, new SimpleMesh(VertexTypes.BLOCK, meshData, "source=BlockModelBuilder," + "blockState=" + state + ",renderType=" + renderType));
|
||||
}
|
||||
Material material = materialFunc.apply(renderType, true);
|
||||
if (material != null) {
|
||||
MemoryBlock meshData = ModelUtil.convertVanillaBuffer(data, VertexTypes.BLOCK);
|
||||
meshMapBuilder.put(material, new SimpleMesh(VertexTypes.BLOCK, meshData, "source=BlockModelBuilder," + "blockState=" + state + ",renderType=" + renderType));
|
||||
}
|
||||
};
|
||||
BakedModelBufferer.bufferBlock(ModelUtil.VANILLA_RENDERER, renderWorld, state, poseStack, modelData, resultConsumer);
|
||||
|
@ -74,23 +74,19 @@ public class MultiBlockModelBuilder {
|
||||
|
||||
if (shadeSeparated) {
|
||||
ShadeSeparatedResultConsumer resultConsumer = (renderType, shaded, data) -> {
|
||||
if (!data.isEmpty()) {
|
||||
Material material = materialFunc.apply(renderType, shaded);
|
||||
if (material != null) {
|
||||
MemoryBlock meshData = ModelUtil.convertVanillaBuffer(data, VertexTypes.BLOCK);
|
||||
meshMapBuilder.put(material, new SimpleMesh(VertexTypes.BLOCK, meshData, "source=MultiBlockModelBuilder," + "renderType=" + renderType + ",shaded=" + shaded));
|
||||
}
|
||||
Material material = materialFunc.apply(renderType, shaded);
|
||||
if (material != null) {
|
||||
MemoryBlock meshData = ModelUtil.convertVanillaBuffer(data, VertexTypes.BLOCK);
|
||||
meshMapBuilder.put(material, new SimpleMesh(VertexTypes.BLOCK, meshData, "source=MultiBlockModelBuilder," + "renderType=" + renderType + ",shaded=" + shaded));
|
||||
}
|
||||
};
|
||||
BakedModelBufferer.bufferMultiBlockShadeSeparated(blocks, ModelUtil.VANILLA_RENDERER, renderWorld, poseStack, modelDataMap, resultConsumer);
|
||||
} else {
|
||||
ResultConsumer resultConsumer = (renderType, data) -> {
|
||||
if (!data.isEmpty()) {
|
||||
Material material = materialFunc.apply(renderType, true);
|
||||
if (material != null) {
|
||||
MemoryBlock meshData = ModelUtil.convertVanillaBuffer(data, VertexTypes.BLOCK);
|
||||
meshMapBuilder.put(material, new SimpleMesh(VertexTypes.BLOCK, meshData, "source=MultiBlockModelBuilder," + "renderType=" + renderType));
|
||||
}
|
||||
Material material = materialFunc.apply(renderType, true);
|
||||
if (material != null) {
|
||||
MemoryBlock meshData = ModelUtil.convertVanillaBuffer(data, VertexTypes.BLOCK);
|
||||
meshMapBuilder.put(material, new SimpleMesh(VertexTypes.BLOCK, meshData, "source=MultiBlockModelBuilder," + "renderType=" + renderType));
|
||||
}
|
||||
};
|
||||
BakedModelBufferer.bufferMultiBlock(blocks, ModelUtil.VANILLA_RENDERER, renderWorld, poseStack, modelDataMap, resultConsumer);
|
||||
|
@ -126,7 +126,7 @@ class VertexWriter implements VertexConsumer {
|
||||
|
||||
public MemoryBlock copyDataAndReset() {
|
||||
MemoryBlock dataCopy = MemoryBlock.malloc(vertexCount * STRIDE);
|
||||
data.copyTo(dataCopy.ptr(), dataCopy.size());
|
||||
data.copyTo(dataCopy);
|
||||
|
||||
vertexCount = 0;
|
||||
filledPosition = false;
|
||||
|
@ -1,11 +1,24 @@
|
||||
package com.jozufozu.flywheel.lib.util;
|
||||
|
||||
import com.jozufozu.flywheel.Flywheel;
|
||||
import com.mojang.brigadier.StringReader;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
|
||||
|
||||
import net.minecraft.ResourceLocationException;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
public class ResourceUtil {
|
||||
public static ResourceLocation defaultToFlywheelNamespace(String location) {
|
||||
public final class ResourceUtil {
|
||||
private static final SimpleCommandExceptionType ERROR_INVALID = new SimpleCommandExceptionType(Component.translatable("argument.id.invalid"));
|
||||
|
||||
private ResourceUtil() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as {@link ResourceLocation#ResourceLocation(String)}, but defaults to Flywheel namespace.
|
||||
*/
|
||||
public static ResourceLocation parseFlywheelDefault(String location) {
|
||||
String namespace = Flywheel.ID;
|
||||
String path = location;
|
||||
|
||||
@ -19,4 +32,24 @@ public class ResourceUtil {
|
||||
|
||||
return new ResourceLocation(namespace, path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as {@link ResourceLocation#read(StringReader)}, but defaults to Flywheel namespace.
|
||||
*/
|
||||
public static ResourceLocation readFlywheelDefault(StringReader reader) throws CommandSyntaxException {
|
||||
int i = reader.getCursor();
|
||||
|
||||
while (reader.canRead() && ResourceLocation.isAllowedInResourceLocation(reader.peek())) {
|
||||
reader.skip();
|
||||
}
|
||||
|
||||
String s = reader.getString().substring(i, reader.getCursor());
|
||||
|
||||
try {
|
||||
return parseFlywheelDefault(s);
|
||||
} catch (ResourceLocationException resourcelocationexception) {
|
||||
reader.setCursor(i);
|
||||
throw ERROR_INVALID.createWithContext(reader);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
|
||||
@Mixin(BlockEntityType.class)
|
||||
public class BlockEntityTypeMixin<T extends BlockEntity> implements BlockEntityTypeExtension<T> {
|
||||
abstract class BlockEntityTypeMixin<T extends BlockEntity> implements BlockEntityTypeExtension<T> {
|
||||
@Unique
|
||||
private BlockEntityVisualizer<? super T> flywheel$visualizer;
|
||||
|
||||
|
@ -14,7 +14,7 @@ import com.mojang.blaze3d.vertex.VertexFormat;
|
||||
import com.mojang.blaze3d.vertex.VertexFormatElement;
|
||||
|
||||
@Mixin(BufferBuilder.class)
|
||||
public abstract class BufferBuilderMixin implements BufferBuilderExtension {
|
||||
abstract class BufferBuilderMixin implements BufferBuilderExtension {
|
||||
@Shadow
|
||||
private ByteBuffer buffer;
|
||||
|
||||
|
@ -3,30 +3,19 @@ package com.jozufozu.flywheel.mixin;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.jozufozu.flywheel.api.visualization.VisualizationManager;
|
||||
import com.jozufozu.flywheel.extension.ClientLevelExtension;
|
||||
import com.jozufozu.flywheel.impl.visualization.VisualizationHelper;
|
||||
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.level.entity.LevelEntityGetter;
|
||||
|
||||
@Mixin(ClientLevel.class)
|
||||
public abstract class ClientLevelMixin implements ClientLevelExtension {
|
||||
@Shadow
|
||||
protected abstract LevelEntityGetter<Entity> getEntities();
|
||||
|
||||
@Override
|
||||
public Iterable<Entity> flywheel$getAllLoadedEntities() {
|
||||
return getEntities().getAll();
|
||||
}
|
||||
|
||||
abstract class ClientLevelMixin {
|
||||
@Inject(method = "entitiesForRendering()Ljava/lang/Iterable;", at = @At("RETURN"), cancellable = true)
|
||||
private void flywheel$filterEntities(CallbackInfoReturnable<Iterable<Entity>> cir) {
|
||||
if (!VisualizationManager.supportsVisualization((ClientLevel) (Object) this)) {
|
||||
|
@ -11,7 +11,7 @@ import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
|
||||
@Mixin(EntityType.class)
|
||||
public class EntityTypeMixin<T extends Entity> implements EntityTypeExtension<T> {
|
||||
abstract class EntityTypeMixin<T extends Entity> implements EntityTypeExtension<T> {
|
||||
@Unique
|
||||
private EntityVisualizer<? super T> flywheel$visualizer;
|
||||
|
||||
|
@ -11,7 +11,7 @@ import com.jozufozu.flywheel.lib.uniform.FlwShaderUniforms;
|
||||
import net.minecraft.client.renderer.FogRenderer;
|
||||
|
||||
@Mixin(FogRenderer.class)
|
||||
public class FogUpdateMixin {
|
||||
abstract class FogUpdateMixin {
|
||||
@Unique
|
||||
private static void flywheel$updateFog() {
|
||||
FlwShaderUniforms.FOG_UPDATE = true;
|
||||
|
@ -10,7 +10,7 @@ import com.jozufozu.flywheel.gl.buffer.GlBufferType;
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
|
||||
@Mixin(GlStateManager.class)
|
||||
public class GlStateManagerMixin {
|
||||
abstract class GlStateManagerMixin {
|
||||
@Inject(method = "_glBindBuffer(II)V", at = @At("RETURN"))
|
||||
private static void flywheel$onBindBuffer(int target, int buffer, CallbackInfo ci) {
|
||||
GlStateTracker._setBuffer(GlBufferType.fromTarget(target), buffer);
|
||||
|
21
src/main/java/com/jozufozu/flywheel/mixin/LevelMixin.java
Normal file
21
src/main/java/com/jozufozu/flywheel/mixin/LevelMixin.java
Normal file
@ -0,0 +1,21 @@
|
||||
package com.jozufozu.flywheel.mixin;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
|
||||
import com.jozufozu.flywheel.extension.LevelExtension;
|
||||
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.entity.LevelEntityGetter;
|
||||
|
||||
@Mixin(Level.class)
|
||||
abstract class LevelMixin implements LevelExtension {
|
||||
@Shadow
|
||||
protected abstract LevelEntityGetter<Entity> getEntities();
|
||||
|
||||
@Override
|
||||
public Iterable<Entity> flywheel$getAllLoadedEntities() {
|
||||
return getEntities().getAll();
|
||||
}
|
||||
}
|
@ -14,7 +14,7 @@ import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import com.jozufozu.flywheel.api.event.BeginFrameEvent;
|
||||
import com.jozufozu.flywheel.api.event.ReloadRenderersEvent;
|
||||
import com.jozufozu.flywheel.api.event.ReloadLevelRendererEvent;
|
||||
import com.jozufozu.flywheel.api.event.RenderContext;
|
||||
import com.jozufozu.flywheel.api.event.RenderStage;
|
||||
import com.jozufozu.flywheel.api.event.RenderStageEvent;
|
||||
@ -32,7 +32,7 @@ import net.minecraft.server.level.BlockDestructionProgress;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
|
||||
@Mixin(value = LevelRenderer.class, priority = 1001) // Higher priority to go after Sodium
|
||||
public class LevelRendererMixin {
|
||||
abstract class LevelRendererMixin {
|
||||
@Shadow
|
||||
private ClientLevel level;
|
||||
|
||||
@ -61,7 +61,7 @@ public class LevelRendererMixin {
|
||||
|
||||
@Inject(method = "allChanged", at = @At("RETURN"))
|
||||
private void flywheel$refresh(CallbackInfo ci) {
|
||||
MinecraftForge.EVENT_BUS.post(new ReloadRenderersEvent(level));
|
||||
MinecraftForge.EVENT_BUS.post(new ReloadLevelRendererEvent(level));
|
||||
}
|
||||
|
||||
@Inject(method = "renderLevel", at = @At(value = "INVOKE_STRING", target = "Lnet/minecraft/util/profiling/ProfilerFiller;popPush(Ljava/lang/String;)V", args = "ldc=destroyProgress"))
|
||||
|
@ -16,7 +16,7 @@ import net.minecraft.world.level.LightLayer;
|
||||
import net.minecraft.world.level.chunk.ChunkSource;
|
||||
|
||||
@Mixin(ClientChunkCache.class)
|
||||
public abstract class LightUpdateMixin extends ChunkSource {
|
||||
abstract class LightUpdateMixin extends ChunkSource {
|
||||
@Shadow
|
||||
@Final
|
||||
ClientLevel level;
|
||||
|
@ -0,0 +1,37 @@
|
||||
package com.jozufozu.flywheel.mixin;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import com.jozufozu.flywheel.api.event.EndClientResourceReloadEvent;
|
||||
import com.mojang.realmsclient.client.RealmsClient;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.main.GameConfig;
|
||||
import net.minecraft.server.packs.resources.ReloadInstance;
|
||||
import net.minecraft.server.packs.resources.ReloadableResourceManager;
|
||||
import net.minecraftforge.fml.ModLoader;
|
||||
|
||||
@Mixin(Minecraft.class)
|
||||
abstract class MinecraftMixin {
|
||||
@Shadow
|
||||
@Final
|
||||
private ReloadableResourceManager resourceManager;
|
||||
|
||||
@Inject(method = "lambda$new$5", at = @At("HEAD"))
|
||||
private void flywheel$onEndInitialResourceReload(RealmsClient realmsClient, ReloadInstance reloadInstance, GameConfig gameConfig, Optional<Throwable> error, CallbackInfo ci) {
|
||||
ModLoader.get().postEvent(new EndClientResourceReloadEvent((Minecraft) (Object) this, resourceManager, true, error));
|
||||
}
|
||||
|
||||
@Inject(method = "lambda$reloadResourcePacks$28", at = @At("HEAD"))
|
||||
private void flywheel$onEndManualResourceReload(boolean recovery, CompletableFuture<Void> future, Optional<Throwable> error, CallbackInfo ci) {
|
||||
ModLoader.get().postEvent(new EndClientResourceReloadEvent((Minecraft) (Object) this, resourceManager, false, error));
|
||||
}
|
||||
}
|
@ -7,7 +7,7 @@ import com.jozufozu.flywheel.lib.transform.TransformStack;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
|
||||
@Mixin(PoseStack.class)
|
||||
public abstract class PoseStackMixin implements TransformStack {
|
||||
abstract class PoseStackMixin implements TransformStack {
|
||||
@Override
|
||||
public TransformStack pushPose() {
|
||||
((PoseStack) (Object) this).pushPose();
|
||||
|
@ -12,10 +12,11 @@ import com.jozufozu.flywheel.extension.RenderTypeExtension;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
|
||||
@Mixin(RenderType.class)
|
||||
public class RenderTypeMixin implements RenderTypeExtension {
|
||||
abstract class RenderTypeMixin implements RenderTypeExtension {
|
||||
@Shadow
|
||||
@Final
|
||||
private boolean sortOnUpload;
|
||||
|
||||
@Unique
|
||||
private DrawBufferSet flywheel$drawBufferSet;
|
||||
|
||||
|
@ -8,7 +8,7 @@ import com.jozufozu.flywheel.extension.VertexFormatExtension;
|
||||
import com.mojang.blaze3d.vertex.VertexFormat;
|
||||
|
||||
@Mixin(VertexFormat.class)
|
||||
public class VertexFormatMixin implements VertexFormatExtension {
|
||||
abstract class VertexFormatMixin implements VertexFormatExtension {
|
||||
@Unique
|
||||
private VertexListProvider flywheel$vertexListProvider;
|
||||
|
||||
|
@ -10,7 +10,7 @@ import com.mojang.blaze3d.platform.GlStateManager;
|
||||
import net.minecraft.client.renderer.LevelRenderer;
|
||||
|
||||
@Mixin(LevelRenderer.class)
|
||||
public class FixFabulousDepthMixin {
|
||||
abstract class FixFabulousDepthMixin {
|
||||
@Inject(method = "renderLevel", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/PostChain;process(F)V", ordinal = 1))
|
||||
private void flywheel$disableTransparencyShaderDepth(CallbackInfo ci) {
|
||||
GlStateManager._depthMask(false);
|
||||
|
@ -10,7 +10,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
|
||||
@Mixin(PoseStack.class)
|
||||
public class FixNormalScalingMixin {
|
||||
abstract class FixNormalScalingMixin {
|
||||
/**
|
||||
* Minecraft negates the normal matrix if all scales are equal and negative, but
|
||||
* does not return afterward. This allows the rest of the method's logic to be
|
||||
|
@ -12,7 +12,7 @@ import net.minecraft.client.renderer.blockentity.BlockEntityRenderer;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
|
||||
@Mixin(value = ChunkBuilderMeshingTask.class, remap = false)
|
||||
public class ChunkBuilderMeshingTaskMixin {
|
||||
abstract class ChunkBuilderMeshingTaskMixin {
|
||||
@Redirect(method = "execute", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/blockentity/BlockEntityRenderDispatcher;getRenderer(Lnet/minecraft/world/level/block/entity/BlockEntity;)Lnet/minecraft/client/renderer/blockentity/BlockEntityRenderer;", remap = true))
|
||||
private BlockEntityRenderer<?> flywheel$redirectGetRenderer(BlockEntityRenderDispatcher dispatcher, BlockEntity blockEntity) {
|
||||
if (VisualizationHelper.tryAddBlockEntity(blockEntity)) {
|
||||
@ -20,4 +20,4 @@ public class ChunkBuilderMeshingTaskMixin {
|
||||
}
|
||||
return dispatcher.getRenderer(blockEntity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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")
|
||||
public class ChunkRebuildHooksMixin {
|
||||
abstract class ChunkRebuildHooksMixin {
|
||||
@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)) {
|
||||
|
@ -14,7 +14,7 @@ import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.chunk.LevelChunk;
|
||||
|
||||
@Mixin(LevelChunk.class)
|
||||
public class VisualAddMixin {
|
||||
abstract class VisualAddMixin {
|
||||
@Shadow
|
||||
@Final
|
||||
Level level;
|
||||
|
@ -13,7 +13,7 @@ import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
|
||||
@Mixin(BlockEntity.class)
|
||||
public class VisualRemoveMixin {
|
||||
abstract class VisualRemoveMixin {
|
||||
@Shadow
|
||||
@Nullable
|
||||
protected Level level;
|
||||
|
@ -15,7 +15,7 @@ import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
||||
@Mixin(LevelRenderer.class)
|
||||
public class VisualUpdateMixin {
|
||||
abstract class VisualUpdateMixin {
|
||||
@Shadow
|
||||
private ClientLevel level;
|
||||
|
||||
|
@ -5,7 +5,7 @@ import java.util.List;
|
||||
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import com.jozufozu.flywheel.api.event.ReloadRenderersEvent;
|
||||
import com.jozufozu.flywheel.api.event.ReloadLevelRendererEvent;
|
||||
import com.jozufozu.flywheel.api.event.RenderStage;
|
||||
import com.jozufozu.flywheel.api.task.Plan;
|
||||
import com.jozufozu.flywheel.api.visual.Effect;
|
||||
@ -65,7 +65,7 @@ public class ExampleEffect implements Effect {
|
||||
trySpawnNewEffect();
|
||||
}
|
||||
|
||||
public static void onReload(ReloadRenderersEvent event) {
|
||||
public static void onReloadLevelRenderer(ReloadLevelRendererEvent event) {
|
||||
ALL_EFFECTS.clear();
|
||||
}
|
||||
|
||||
|
@ -11,8 +11,10 @@
|
||||
"EntityTypeMixin",
|
||||
"FogUpdateMixin",
|
||||
"GlStateManagerMixin",
|
||||
"LevelMixin",
|
||||
"LevelRendererMixin",
|
||||
"LightUpdateMixin",
|
||||
"MinecraftMixin",
|
||||
"PoseStackMixin",
|
||||
"RenderTypeMixin",
|
||||
"VertexFormatMixin",
|
||||
|
Loading…
Reference in New Issue
Block a user