mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2025-01-30 06:44:58 +01:00
Merge remote-tracking branch 'origin/1.19/dev' into 1.19/fabric/dev
Conflicts: build.gradle gradle.properties src/main/java/com/jozufozu/flywheel/Flywheel.java src/main/java/com/jozufozu/flywheel/backend/Loader.java src/main/java/com/jozufozu/flywheel/config/FlwCommands.java src/main/java/com/jozufozu/flywheel/core/PartialModel.java src/main/java/com/jozufozu/flywheel/core/model/BakedModelBuilder.java src/main/java/com/jozufozu/flywheel/core/model/ModelUtil.java src/main/java/com/jozufozu/flywheel/core/model/ShadeSeparatedBufferBuilder.java src/main/java/com/jozufozu/flywheel/core/model/WorldModelBuilder.java src/main/java/com/jozufozu/flywheel/core/vertex/BlockVertex.java src/main/java/com/jozufozu/flywheel/event/EntityWorldHandler.java src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java src/main/java/com/jozufozu/flywheel/util/RenderMath.java src/main/resources/META-INF/mods.toml src/main/resources/pack.mcmeta
This commit is contained in:
commit
954d1d77fb
30 changed files with 393 additions and 187 deletions
|
@ -61,7 +61,8 @@ dependencies {
|
||||||
// Fabric API
|
// Fabric API
|
||||||
modImplementation "net.fabricmc.fabric-api:fabric-api:${fabric_version}"
|
modImplementation "net.fabricmc.fabric-api:fabric-api:${fabric_version}"
|
||||||
|
|
||||||
modCompileOnly 'curse.maven:starlight-521783:3667443'
|
// switch to implementation for debugging
|
||||||
|
modCompileOnly 'maven.modrinth:starlight:1.1.1+1.19'
|
||||||
|
|
||||||
modCompileOnly 'maven.modrinth:iris:1.18.x-v1.2.5'
|
modCompileOnly 'maven.modrinth:iris:1.18.x-v1.2.5'
|
||||||
modCompileOnly 'maven.modrinth:sodium:mc1.18.2-0.4.1'
|
modCompileOnly 'maven.modrinth:sodium:mc1.18.2-0.4.1'
|
||||||
|
@ -155,6 +156,6 @@ curseforge {
|
||||||
changelog = file('changelog.txt')
|
changelog = file('changelog.txt')
|
||||||
releaseType = project.curse_type
|
releaseType = project.curse_type
|
||||||
mainArtifact jar
|
mainArtifact jar
|
||||||
addGameVersion '1.18.2'
|
addGameVersion '1.19.2'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,11 +3,11 @@ org.gradle.daemon = false
|
||||||
|
|
||||||
# mod version info
|
# mod version info
|
||||||
mod_version = 0.6.8
|
mod_version = 0.6.8
|
||||||
artifact_minecraft_version = 1.18.2
|
artifact_minecraft_version = 1.19.2
|
||||||
|
|
||||||
minecraft_version = 1.18.2
|
minecraft_version = 1.19.2
|
||||||
loader_version = 0.14.9
|
loader_version = 0.14.9
|
||||||
fabric_version = 0.66.0+1.18.2
|
fabric_version = 0.66.0+1.19.2
|
||||||
|
|
||||||
# build dependency versions
|
# build dependency versions
|
||||||
loom_version = 1.0-SNAPSHOT
|
loom_version = 1.0-SNAPSHOT
|
||||||
|
|
|
@ -7,6 +7,7 @@ import com.jozufozu.flywheel.backend.Loader;
|
||||||
import com.jozufozu.flywheel.backend.RenderWork;
|
import com.jozufozu.flywheel.backend.RenderWork;
|
||||||
import com.jozufozu.flywheel.backend.ShadersModHandler;
|
import com.jozufozu.flywheel.backend.ShadersModHandler;
|
||||||
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
|
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
|
||||||
|
import com.jozufozu.flywheel.config.FlwCommands;
|
||||||
import com.jozufozu.flywheel.config.FlwConfig;
|
import com.jozufozu.flywheel.config.FlwConfig;
|
||||||
import com.jozufozu.flywheel.core.Contexts;
|
import com.jozufozu.flywheel.core.Contexts;
|
||||||
import com.jozufozu.flywheel.core.PartialModel;
|
import com.jozufozu.flywheel.core.PartialModel;
|
||||||
|
@ -21,6 +22,7 @@ import com.jozufozu.flywheel.vanilla.VanillaInstances;
|
||||||
import com.mojang.logging.LogUtils;
|
import com.mojang.logging.LogUtils;
|
||||||
|
|
||||||
import net.fabricmc.api.ClientModInitializer;
|
import net.fabricmc.api.ClientModInitializer;
|
||||||
|
import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
|
||||||
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientEntityEvents;
|
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientEntityEvents;
|
||||||
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
|
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
|
||||||
import net.fabricmc.fabric.api.client.model.ModelLoadingRegistry;
|
import net.fabricmc.fabric.api.client.model.ModelLoadingRegistry;
|
||||||
|
@ -55,6 +57,7 @@ public class Flywheel implements ClientModInitializer {
|
||||||
ShadersModHandler.init();
|
ShadersModHandler.init();
|
||||||
Backend.init();
|
Backend.init();
|
||||||
|
|
||||||
|
ClientCommandRegistrationCallback.EVENT.register(FlwCommands::registerClientCommands);
|
||||||
FlywheelEvents.RELOAD_RENDERERS.register(ProgramCompiler::invalidateAll);
|
FlywheelEvents.RELOAD_RENDERERS.register(ProgramCompiler::invalidateAll);
|
||||||
|
|
||||||
FlywheelEvents.GATHER_CONTEXT.register(Contexts::flwInit);
|
FlywheelEvents.GATHER_CONTEXT.register(Contexts::flwInit);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package com.jozufozu.flywheel.backend;
|
package com.jozufozu.flywheel.backend;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -90,11 +90,11 @@ public class Loader {
|
||||||
private void loadProgramSpecs(ResourceManager manager) {
|
private void loadProgramSpecs(ResourceManager manager) {
|
||||||
programs.clear();
|
programs.clear();
|
||||||
|
|
||||||
Collection<ResourceLocation> programSpecs = manager.listResources(PROGRAM_DIR, s -> s.endsWith(".json"));
|
Map<ResourceLocation, Resource> programSpecs = manager.listResources(PROGRAM_DIR, loc -> loc.getPath().endsWith(".json"));
|
||||||
|
|
||||||
for (ResourceLocation location : programSpecs) {
|
programSpecs.forEach((location, resource) -> {
|
||||||
try (Resource resource = manager.getResource(location)) {
|
try (InputStream inputStream = resource.open()) {
|
||||||
String s = StringUtil.readToString(resource.getInputStream());
|
String s = StringUtil.readToString(inputStream);
|
||||||
|
|
||||||
ResourceLocation specName = ResourceUtil.trim(location, PROGRAM_DIR, ".json");
|
ResourceLocation specName = ResourceUtil.trim(location, PROGRAM_DIR, ".json");
|
||||||
|
|
||||||
|
@ -114,7 +114,7 @@ public class Loader {
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Backend.LOGGER.error("Could not load program " + location, e);
|
Backend.LOGGER.error("Could not load program " + location, e);
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ResourceReloadListener implements ResourceManagerReloadListener, IdentifiableResourceReloadListener {
|
public static class ResourceReloadListener implements ResourceManagerReloadListener, IdentifiableResourceReloadListener {
|
||||||
|
|
|
@ -1,50 +0,0 @@
|
||||||
package com.jozufozu.flywheel.config;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
|
||||||
|
|
||||||
import com.mojang.brigadier.StringReader;
|
|
||||||
import com.mojang.brigadier.arguments.ArgumentType;
|
|
||||||
import com.mojang.brigadier.context.CommandContext;
|
|
||||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
|
||||||
import com.mojang.brigadier.exceptions.Dynamic2CommandExceptionType;
|
|
||||||
import com.mojang.brigadier.suggestion.Suggestions;
|
|
||||||
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
|
|
||||||
|
|
||||||
import net.minecraft.commands.SharedSuggestionProvider;
|
|
||||||
import net.minecraft.network.chat.TranslatableComponent;
|
|
||||||
|
|
||||||
public enum BackendTypeArgument implements ArgumentType<BackendType> {
|
|
||||||
INSTANCE;
|
|
||||||
|
|
||||||
private static final Dynamic2CommandExceptionType INVALID = new Dynamic2CommandExceptionType((found, constants) -> {
|
|
||||||
// TODO: don't steal lang
|
|
||||||
return new TranslatableComponent("commands.forge.arguments.enum.invalid", constants, found);
|
|
||||||
});
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BackendType parse(StringReader reader) throws CommandSyntaxException {
|
|
||||||
String string = reader.readUnquotedString();
|
|
||||||
|
|
||||||
BackendType engine = BackendType.byName(string);
|
|
||||||
|
|
||||||
if (engine == null) {
|
|
||||||
throw INVALID.createWithContext(reader, string, BackendType.validNames());
|
|
||||||
}
|
|
||||||
|
|
||||||
return engine;
|
|
||||||
}
|
|
||||||
|
|
||||||
public <S> CompletableFuture<Suggestions> listSuggestions(CommandContext<S> context, SuggestionsBuilder builder) {
|
|
||||||
return SharedSuggestionProvider.suggest(BackendType.validNames(), builder);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Collection<String> getExamples() {
|
|
||||||
return BackendType.validNames();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static BackendTypeArgument getInstance() {
|
|
||||||
return INSTANCE;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -8,17 +8,20 @@ import org.jetbrains.annotations.NotNull;
|
||||||
import com.jozufozu.flywheel.backend.Backend;
|
import com.jozufozu.flywheel.backend.Backend;
|
||||||
import com.jozufozu.flywheel.config.Option.EnumOption;
|
import com.jozufozu.flywheel.config.Option.EnumOption;
|
||||||
import com.mojang.brigadier.Command;
|
import com.mojang.brigadier.Command;
|
||||||
|
import com.mojang.brigadier.CommandDispatcher;
|
||||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||||
|
|
||||||
import net.fabricmc.fabric.api.client.command.v1.ClientCommandManager;
|
import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager;
|
||||||
import net.fabricmc.fabric.api.client.command.v1.FabricClientCommandSource;
|
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
|
||||||
import net.minecraft.ChatFormatting;
|
import net.minecraft.ChatFormatting;
|
||||||
|
import net.minecraft.commands.CommandBuildContext;
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.network.chat.MutableComponent;
|
import net.minecraft.network.chat.MutableComponent;
|
||||||
import net.minecraft.network.chat.TextComponent;
|
|
||||||
|
|
||||||
public final class FlwCommands {
|
public final class FlwCommands {
|
||||||
public static void init(FlwConfig config) {
|
public static void registerClientCommands(CommandDispatcher<FabricClientCommandSource> dispatcher, CommandBuildContext context) {
|
||||||
|
FlwConfig config = FlwConfig.get();
|
||||||
|
|
||||||
ConfigCommandBuilder commandBuilder = new ConfigCommandBuilder("flywheel");
|
ConfigCommandBuilder commandBuilder = new ConfigCommandBuilder("flywheel");
|
||||||
|
|
||||||
commandBuilder.addOption(config.backend, (builder, option) -> enumOptionCommand(builder, config, option,
|
commandBuilder.addOption(config.backend, (builder, option) -> enumOptionCommand(builder, config, option,
|
||||||
|
@ -34,27 +37,27 @@ public final class FlwCommands {
|
||||||
|
|
||||||
commandBuilder.addOption(config.debugNormals, (builder, option) -> booleanOptionCommand(builder, config, option,
|
commandBuilder.addOption(config.debugNormals, (builder, option) -> booleanOptionCommand(builder, config, option,
|
||||||
(source, value) -> {
|
(source, value) -> {
|
||||||
Component text = new TextComponent("Normal debug mode is currently: ").append(boolToText(value));
|
Component text = Component.literal("Normal debug mode is currently: ").append(boolToText(value));
|
||||||
source.sendFeedback(text);
|
source.sendFeedback(text);
|
||||||
},
|
},
|
||||||
(source, value) -> {
|
(source, value) -> {
|
||||||
Component text = boolToText(value).append(new TextComponent(" normal debug mode").withStyle(ChatFormatting.WHITE));
|
Component text = boolToText(value).append(Component.literal(" normal debug mode").withStyle(ChatFormatting.WHITE));
|
||||||
source.sendFeedback(text);
|
source.sendFeedback(text);
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
|
||||||
commandBuilder.addOption(config.limitUpdates, (builder, option) -> booleanOptionCommand(builder, config, option,
|
commandBuilder.addOption(config.limitUpdates, (builder, option) -> booleanOptionCommand(builder, config, option,
|
||||||
(source, value) -> {
|
(source, value) -> {
|
||||||
Component text = new TextComponent("Update limiting is currently: ").append(boolToText(value));
|
Component text = Component.literal("Update limiting is currently: ").append(boolToText(value));
|
||||||
source.sendFeedback(text);
|
source.sendFeedback(text);
|
||||||
},
|
},
|
||||||
(source, value) -> {
|
(source, value) -> {
|
||||||
Component text = boolToText(value).append(new TextComponent(" update limiting.").withStyle(ChatFormatting.WHITE));
|
Component text = boolToText(value).append(Component.literal(" update limiting.").withStyle(ChatFormatting.WHITE));
|
||||||
source.sendFeedback(text);
|
source.sendFeedback(text);
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
|
||||||
commandBuilder.build();
|
commandBuilder.build(dispatcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void booleanOptionCommand(LiteralArgumentBuilder<FabricClientCommandSource> builder, FlwConfig config, Option<Boolean> option, BiConsumer<FabricClientCommandSource, Boolean> displayAction, BiConsumer<FabricClientCommandSource, Boolean> setAction) {
|
public static void booleanOptionCommand(LiteralArgumentBuilder<FabricClientCommandSource> builder, FlwConfig config, Option<Boolean> option, BiConsumer<FabricClientCommandSource, Boolean> displayAction, BiConsumer<FabricClientCommandSource, Boolean> setAction) {
|
||||||
|
@ -96,14 +99,14 @@ public final class FlwCommands {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MutableComponent boolToText(boolean b) {
|
public static MutableComponent boolToText(boolean b) {
|
||||||
return b ? new TextComponent("enabled").withStyle(ChatFormatting.DARK_GREEN) : new TextComponent("disabled").withStyle(ChatFormatting.RED);
|
return b ? Component.literal("enabled").withStyle(ChatFormatting.DARK_GREEN) : Component.literal("disabled").withStyle(ChatFormatting.RED);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Component getEngineMessage(@NotNull BackendType type) {
|
public static Component getEngineMessage(@NotNull BackendType type) {
|
||||||
return switch (type) {
|
return switch (type) {
|
||||||
case OFF -> new TextComponent("Disabled Flywheel").withStyle(ChatFormatting.RED);
|
case OFF -> Component.literal("Disabled Flywheel").withStyle(ChatFormatting.RED);
|
||||||
case INSTANCING -> new TextComponent("Using Instancing Engine").withStyle(ChatFormatting.GREEN);
|
case INSTANCING -> Component.literal("Using Instancing Engine").withStyle(ChatFormatting.GREEN);
|
||||||
case BATCHING -> new TextComponent("Using Batching Engine").withStyle(ChatFormatting.GREEN);
|
case BATCHING -> Component.literal("Using Batching Engine").withStyle(ChatFormatting.GREEN);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,8 +127,8 @@ public final class FlwCommands {
|
||||||
command.then(builder);
|
command.then(builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void build() {
|
public void build(CommandDispatcher<FabricClientCommandSource> dispatcher) {
|
||||||
ClientCommandManager.DISPATCHER.register(command);
|
dispatcher.register(command);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,7 +51,6 @@ public class FlwConfig {
|
||||||
|
|
||||||
public static void init() {
|
public static void init() {
|
||||||
INSTANCE.load();
|
INSTANCE.load();
|
||||||
FlwCommands.init(INSTANCE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public BackendType getBackendType() {
|
public BackendType getBackendType() {
|
||||||
|
|
|
@ -22,10 +22,10 @@ import net.minecraft.server.packs.resources.ResourceManagerReloadListener;
|
||||||
* Creating a PartialModel will make the associated modelLocation automatically load.
|
* Creating a PartialModel will make the associated modelLocation automatically load.
|
||||||
* PartialModels must be initialized the mod class constructor.
|
* PartialModels must be initialized the mod class constructor.
|
||||||
* <br>
|
* <br>
|
||||||
* Once {@link ModelBakeEvent} finishes, all PartialModels (with valid modelLocations)
|
* Once {@link ModelEvent.BakingCompleted} finishes, all PartialModels (with valid modelLocations)
|
||||||
* will have their bakedModel fields populated.
|
* will have their bakedModel fields populated.
|
||||||
* <br>
|
* <br>
|
||||||
* Attempting to create a PartialModel after {@link ModelRegistryEvent} will cause an error.
|
* Attempting to create a PartialModel after {@link ModelEvent.RegisterAdditional} will cause an error.
|
||||||
*/
|
*/
|
||||||
public class PartialModel {
|
public class PartialModel {
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ public class PartialModel {
|
||||||
protected BakedModel bakedModel;
|
protected BakedModel bakedModel;
|
||||||
|
|
||||||
public PartialModel(ResourceLocation modelLocation) {
|
public PartialModel(ResourceLocation modelLocation) {
|
||||||
if (tooLate) throw new RuntimeException("PartialModel '" + modelLocation + "' loaded after ModelRegistryEvent");
|
if (tooLate) throw new RuntimeException("PartialModel '" + modelLocation + "' loaded after ModelEvent.RegisterAdditional");
|
||||||
|
|
||||||
this.modelLocation = modelLocation;
|
this.modelLocation = modelLocation;
|
||||||
ALL.add(this);
|
ALL.add(this);
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
|
|
||||||
package com.jozufozu.flywheel.core.model;
|
package com.jozufozu.flywheel.core.model;
|
||||||
|
|
||||||
import java.util.Random;
|
|
||||||
|
|
||||||
import com.jozufozu.flywheel.core.virtual.VirtualEmptyBlockGetter;
|
import com.jozufozu.flywheel.core.virtual.VirtualEmptyBlockGetter;
|
||||||
import com.jozufozu.flywheel.fabric.model.DefaultLayerFilteringBakedModel;
|
import com.jozufozu.flywheel.fabric.model.DefaultLayerFilteringBakedModel;
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
@ -12,6 +10,7 @@ import net.minecraft.client.renderer.block.ModelBlockRenderer;
|
||||||
import net.minecraft.client.renderer.texture.OverlayTexture;
|
import net.minecraft.client.renderer.texture.OverlayTexture;
|
||||||
import net.minecraft.client.resources.model.BakedModel;
|
import net.minecraft.client.resources.model.BakedModel;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.util.RandomSource;
|
||||||
import net.minecraft.world.level.BlockAndTintGetter;
|
import net.minecraft.world.level.BlockAndTintGetter;
|
||||||
import net.minecraft.world.level.block.Blocks;
|
import net.minecraft.world.level.block.Blocks;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
@ -42,7 +41,7 @@ public final class BakedModelBuilder implements Bufferable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void bufferInto(ModelBlockRenderer blockRenderer, VertexConsumer consumer, Random random) {
|
public void bufferInto(ModelBlockRenderer blockRenderer, VertexConsumer consumer, RandomSource random) {
|
||||||
BakedModel model = DefaultLayerFilteringBakedModel.wrap(this.model);
|
BakedModel model = DefaultLayerFilteringBakedModel.wrap(this.model);
|
||||||
if (consumer instanceof ShadeSeparatingVertexConsumer shadeSeparatingWrapper) {
|
if (consumer instanceof ShadeSeparatingVertexConsumer shadeSeparatingWrapper) {
|
||||||
model = shadeSeparatingWrapper.wrapModel(model);
|
model = shadeSeparatingWrapper.wrapModel(model);
|
||||||
|
|
|
@ -1,9 +1,25 @@
|
||||||
package com.jozufozu.flywheel.core.model;
|
package com.jozufozu.flywheel.core.model;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import org.lwjgl.opengl.GL15;
|
||||||
|
import org.lwjgl.opengl.GL32;
|
||||||
|
import org.lwjgl.system.MemoryUtil;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.api.vertex.VertexList;
|
import com.jozufozu.flywheel.api.vertex.VertexList;
|
||||||
import com.jozufozu.flywheel.api.vertex.VertexType;
|
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||||
|
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
|
||||||
|
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferUsage;
|
||||||
|
import com.jozufozu.flywheel.backend.model.ElementBuffer;
|
||||||
import com.jozufozu.flywheel.core.Formats;
|
import com.jozufozu.flywheel.core.Formats;
|
||||||
|
import com.jozufozu.flywheel.core.QuadConverter;
|
||||||
|
import com.jozufozu.flywheel.util.Pair;
|
||||||
|
import com.mojang.blaze3d.platform.MemoryTracker;
|
||||||
|
import com.mojang.blaze3d.vertex.BufferBuilder;
|
||||||
|
import com.mojang.blaze3d.vertex.BufferBuilder.RenderedBuffer;
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
import com.mojang.blaze3d.vertex.VertexFormat.IndexType;
|
||||||
|
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.resources.model.BakedModel;
|
import net.minecraft.client.resources.model.BakedModel;
|
||||||
|
@ -16,6 +32,7 @@ public class BlockModel implements Model {
|
||||||
|
|
||||||
private final VertexList reader;
|
private final VertexList reader;
|
||||||
private final String name;
|
private final String name;
|
||||||
|
private final EBOSupplier eboSupplier;
|
||||||
|
|
||||||
public BlockModel(BlockState state) {
|
public BlockModel(BlockState state) {
|
||||||
this(Minecraft.getInstance()
|
this(Minecraft.getInstance()
|
||||||
|
@ -36,9 +53,19 @@ public class BlockModel implements Model {
|
||||||
this(bufferable.build(), name);
|
this(bufferable.build(), name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public BlockModel(ShadeSeparatedBufferBuilder bufferBuilder, String name) {
|
public BlockModel(Pair<RenderedBuffer, Integer> pair, String name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
reader = Formats.BLOCK.createReader(bufferBuilder);
|
|
||||||
|
RenderedBuffer renderedBuffer = pair.first();
|
||||||
|
BufferBuilder.DrawState drawState = renderedBuffer.drawState();
|
||||||
|
reader = Formats.BLOCK.createReader(renderedBuffer, pair.second());
|
||||||
|
|
||||||
|
if (!drawState.sequentialIndex()) {
|
||||||
|
eboSupplier = new BufferEBOSupplier(renderedBuffer.indexBuffer(), drawState.indexCount(), drawState.indexType());
|
||||||
|
} else {
|
||||||
|
eboSupplier = () -> QuadConverter.getInstance()
|
||||||
|
.quads2Tris(vertexCount() / 4);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -56,6 +83,11 @@ public class BlockModel implements Model {
|
||||||
return reader;
|
return reader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ElementBuffer createEBO() {
|
||||||
|
return eboSupplier.get();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public VertexType getType() {
|
public VertexType getType() {
|
||||||
return Formats.BLOCK;
|
return Formats.BLOCK;
|
||||||
|
@ -70,5 +102,55 @@ public class BlockModel implements Model {
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
eboSupplier.delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
private interface EBOSupplier extends Supplier<ElementBuffer> {
|
||||||
|
default void delete() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class BufferEBOSupplier implements EBOSupplier {
|
||||||
|
private final ByteBuffer indexBuffer;
|
||||||
|
private final int indexCount;
|
||||||
|
private final IndexType indexType;
|
||||||
|
|
||||||
|
private int eboName = -1;
|
||||||
|
private ElementBuffer ebo;
|
||||||
|
|
||||||
|
public BufferEBOSupplier(ByteBuffer indexBufferSrc, int indexCount, IndexType indexType) {
|
||||||
|
indexBuffer = MemoryTracker.create(indexBufferSrc.capacity());
|
||||||
|
MemoryUtil.memCopy(indexBufferSrc, indexBuffer);
|
||||||
|
this.indexCount = indexCount;
|
||||||
|
this.indexType = indexType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ElementBuffer get() {
|
||||||
|
if (eboName == -1) {
|
||||||
|
eboName = createEBO();
|
||||||
|
ebo = new ElementBuffer(eboName, indexCount, indexType);
|
||||||
|
MemoryUtil.memFree(indexBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ebo;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int createEBO() {
|
||||||
|
int vbo = GL32.glGenBuffers();
|
||||||
|
|
||||||
|
// XXX ARRAY_BUFFER is bound and restored
|
||||||
|
var bufferType = GlBufferType.ARRAY_BUFFER;
|
||||||
|
var oldBuffer = bufferType.getBoundBuffer();
|
||||||
|
bufferType.bind(vbo);
|
||||||
|
GL15.glBufferData(bufferType.glEnum, indexBuffer, GlBufferUsage.STATIC_DRAW.glEnum);
|
||||||
|
bufferType.bind(oldBuffer);
|
||||||
|
return vbo;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void delete() {
|
||||||
|
GL32.glDeleteBuffers(eboName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,20 @@
|
||||||
|
|
||||||
package com.jozufozu.flywheel.core.model;
|
package com.jozufozu.flywheel.core.model;
|
||||||
|
|
||||||
import java.util.Random;
|
import com.jozufozu.flywheel.util.Pair;
|
||||||
|
import com.mojang.blaze3d.vertex.BufferBuilder.RenderedBuffer;
|
||||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||||
|
|
||||||
import net.minecraft.client.renderer.block.ModelBlockRenderer;
|
import net.minecraft.client.renderer.block.ModelBlockRenderer;
|
||||||
|
import net.minecraft.util.RandomSource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An interface for objects that can "rendered" into a BufferBuilder.
|
* An interface for objects that can "rendered" into a BufferBuilder.
|
||||||
*/
|
*/
|
||||||
public interface Bufferable {
|
public interface Bufferable {
|
||||||
void bufferInto(ModelBlockRenderer renderer, VertexConsumer consumer, Random random);
|
void bufferInto(ModelBlockRenderer renderer, VertexConsumer consumer, RandomSource random);
|
||||||
|
|
||||||
default ShadeSeparatedBufferBuilder build() {
|
default Pair<RenderedBuffer, Integer> build() {
|
||||||
return ModelUtil.getBufferBuilder(this);
|
return ModelUtil.getRenderedBuffer(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
package com.jozufozu.flywheel.core.model;
|
package com.jozufozu.flywheel.core.model;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Random;
|
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.backend.model.BufferBuilderExtension;
|
||||||
|
import com.jozufozu.flywheel.util.Pair;
|
||||||
import com.jozufozu.flywheel.util.transform.TransformStack;
|
import com.jozufozu.flywheel.util.transform.TransformStack;
|
||||||
import com.mojang.blaze3d.vertex.BufferBuilder;
|
import com.mojang.blaze3d.vertex.BufferBuilder;
|
||||||
|
import com.mojang.blaze3d.vertex.BufferBuilder.RenderedBuffer;
|
||||||
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
|
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
import com.mojang.blaze3d.vertex.VertexFormat;
|
import com.mojang.blaze3d.vertex.VertexFormat;
|
||||||
|
@ -15,6 +17,7 @@ import net.minecraft.client.renderer.RenderType;
|
||||||
import net.minecraft.client.renderer.block.ModelBlockRenderer;
|
import net.minecraft.client.renderer.block.ModelBlockRenderer;
|
||||||
import net.minecraft.client.resources.model.BakedModel;
|
import net.minecraft.client.resources.model.BakedModel;
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
|
import net.minecraft.util.RandomSource;
|
||||||
import net.minecraft.world.level.BlockAndTintGetter;
|
import net.minecraft.world.level.BlockAndTintGetter;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate;
|
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate;
|
||||||
|
@ -22,7 +25,18 @@ import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemp
|
||||||
public class ModelUtil {
|
public class ModelUtil {
|
||||||
private static final ThreadLocal<ThreadLocalObjects> THREAD_LOCAL_OBJECTS = ThreadLocal.withInitial(ThreadLocalObjects::new);
|
private static final ThreadLocal<ThreadLocalObjects> THREAD_LOCAL_OBJECTS = ThreadLocal.withInitial(ThreadLocalObjects::new);
|
||||||
|
|
||||||
public static ShadeSeparatedBufferBuilder getBufferBuilder(Bufferable bufferable) {
|
public static Pair<RenderedBuffer, Integer> endShadeSeparated(BufferBuilder shadedBuilder, BufferBuilder unshadedBuilder) {
|
||||||
|
int unshadedStartVertex = ((BufferBuilderExtension) shadedBuilder).flywheel$getVertices();
|
||||||
|
RenderedBuffer unshadedBuffer = unshadedBuilder.endOrDiscardIfEmpty();
|
||||||
|
if (unshadedBuffer != null) {
|
||||||
|
// FIXME: Unshaded indices
|
||||||
|
((BufferBuilderExtension) shadedBuilder).flywheel$appendBufferUnsafe(unshadedBuffer.vertexBuffer());
|
||||||
|
}
|
||||||
|
RenderedBuffer buffer = shadedBuilder.end();
|
||||||
|
return Pair.of(buffer, unshadedStartVertex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Pair<RenderedBuffer, Integer> getRenderedBuffer(Bufferable bufferable) {
|
||||||
ModelBlockRenderer blockRenderer = Minecraft.getInstance().getBlockRenderer().getModelRenderer();
|
ModelBlockRenderer blockRenderer = Minecraft.getInstance().getBlockRenderer().getModelRenderer();
|
||||||
ThreadLocalObjects objects = THREAD_LOCAL_OBJECTS.get();
|
ThreadLocalObjects objects = THREAD_LOCAL_OBJECTS.get();
|
||||||
|
|
||||||
|
@ -30,31 +44,29 @@ public class ModelUtil {
|
||||||
|
|
||||||
bufferable.bufferInto(blockRenderer, objects.shadeSeparatingWrapper, objects.random);
|
bufferable.bufferInto(blockRenderer, objects.shadeSeparatingWrapper, objects.random);
|
||||||
|
|
||||||
objects.end();
|
return objects.end();
|
||||||
|
|
||||||
return objects.separatedBufferBuilder;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ShadeSeparatedBufferBuilder getBufferBuilder(BakedModel model, BlockState referenceState, PoseStack poseStack) {
|
public static Pair<RenderedBuffer, Integer> getBufferBuilder(BakedModel model, BlockState referenceState, PoseStack poseStack) {
|
||||||
return new BakedModelBuilder(model).withReferenceState(referenceState)
|
return new BakedModelBuilder(model).withReferenceState(referenceState)
|
||||||
.withPoseStack(poseStack)
|
.withPoseStack(poseStack)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ShadeSeparatedBufferBuilder getBufferBuilder(BlockAndTintGetter renderWorld, BakedModel model, BlockState referenceState, PoseStack poseStack) {
|
public static Pair<RenderedBuffer, Integer> getBufferBuilder(BlockAndTintGetter renderWorld, BakedModel model, BlockState referenceState, PoseStack poseStack) {
|
||||||
return new BakedModelBuilder(model).withReferenceState(referenceState)
|
return new BakedModelBuilder(model).withReferenceState(referenceState)
|
||||||
.withPoseStack(poseStack)
|
.withPoseStack(poseStack)
|
||||||
.withRenderWorld(renderWorld)
|
.withRenderWorld(renderWorld)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ShadeSeparatedBufferBuilder getBufferBuilderFromTemplate(BlockAndTintGetter renderWorld, RenderType layer, Collection<StructureTemplate.StructureBlockInfo> blocks) {
|
public static Pair<RenderedBuffer, Integer> getBufferBuilderFromTemplate(BlockAndTintGetter renderWorld, RenderType layer, Collection<StructureTemplate.StructureBlockInfo> blocks) {
|
||||||
return new WorldModelBuilder(layer).withRenderWorld(renderWorld)
|
return new WorldModelBuilder(layer).withRenderWorld(renderWorld)
|
||||||
.withBlocks(blocks)
|
.withBlocks(blocks)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ShadeSeparatedBufferBuilder getBufferBuilderFromTemplate(BlockAndTintGetter renderWorld, RenderType layer, Collection<StructureTemplate.StructureBlockInfo> blocks, PoseStack poseStack) {
|
public static Pair<RenderedBuffer, Integer> getBufferBuilderFromTemplate(BlockAndTintGetter renderWorld, RenderType layer, Collection<StructureTemplate.StructureBlockInfo> blocks, PoseStack poseStack) {
|
||||||
return new WorldModelBuilder(layer).withRenderWorld(renderWorld)
|
return new WorldModelBuilder(layer).withRenderWorld(renderWorld)
|
||||||
.withBlocks(blocks)
|
.withBlocks(blocks)
|
||||||
.withPoseStack(poseStack)
|
.withPoseStack(poseStack)
|
||||||
|
@ -73,22 +85,20 @@ public class ModelUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class ThreadLocalObjects {
|
private static class ThreadLocalObjects {
|
||||||
public final Random random = new Random();
|
public final RandomSource random = RandomSource.create();
|
||||||
public final ShadeSeparatingVertexConsumer shadeSeparatingWrapper = new ShadeSeparatingVertexConsumer();
|
public final ShadeSeparatingVertexConsumer shadeSeparatingWrapper = new ShadeSeparatingVertexConsumer();
|
||||||
public final ShadeSeparatedBufferBuilder separatedBufferBuilder = new ShadeSeparatedBufferBuilder(512);
|
public final BufferBuilder shadedBuilder = new BufferBuilder(512);
|
||||||
public final BufferBuilder unshadedBuilder = new BufferBuilder(512);
|
public final BufferBuilder unshadedBuilder = new BufferBuilder(512);
|
||||||
|
|
||||||
private void begin() {
|
private void begin() {
|
||||||
this.separatedBufferBuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
|
this.shadedBuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
|
||||||
this.unshadedBuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
|
this.unshadedBuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
|
||||||
this.shadeSeparatingWrapper.prepare(this.separatedBufferBuilder, this.unshadedBuilder);
|
this.shadeSeparatingWrapper.prepare(this.shadedBuilder, this.unshadedBuilder);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void end() {
|
private Pair<RenderedBuffer, Integer> end() {
|
||||||
this.shadeSeparatingWrapper.clear();
|
this.shadeSeparatingWrapper.clear();
|
||||||
this.unshadedBuilder.end();
|
return ModelUtil.endShadeSeparated(shadedBuilder, unshadedBuilder);
|
||||||
this.separatedBufferBuilder.appendUnshadedVertices(this.unshadedBuilder);
|
|
||||||
this.separatedBufferBuilder.end();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,28 +0,0 @@
|
||||||
package com.jozufozu.flywheel.core.model;
|
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.model.BufferBuilderExtension;
|
|
||||||
import com.jozufozu.flywheel.fabric.helper.BufferBuilderHelper;
|
|
||||||
import com.mojang.blaze3d.vertex.BufferBuilder;
|
|
||||||
import com.mojang.datafixers.util.Pair;
|
|
||||||
|
|
||||||
public class ShadeSeparatedBufferBuilder extends BufferBuilder {
|
|
||||||
protected int unshadedStartVertex;
|
|
||||||
|
|
||||||
public ShadeSeparatedBufferBuilder(int capacity) {
|
|
||||||
super(capacity);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void appendUnshadedVertices(BufferBuilder unshadedBuilder) {
|
|
||||||
Pair<DrawState, ByteBuffer> data = unshadedBuilder.popNextBuffer();
|
|
||||||
ByteBuffer buffer = data.getSecond();
|
|
||||||
BufferBuilderHelper.fixByteOrder(unshadedBuilder, buffer);
|
|
||||||
unshadedStartVertex = ((BufferBuilderExtension) this).flywheel$getVertices();
|
|
||||||
((BufferBuilderExtension) this).flywheel$appendBufferUnsafe(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getUnshadedStartVertex() {
|
|
||||||
return unshadedStartVertex;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,6 +1,5 @@
|
||||||
package com.jozufozu.flywheel.core.model;
|
package com.jozufozu.flywheel.core.model;
|
||||||
|
|
||||||
import java.util.Random;
|
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.fabric.model.FabricModelUtil;
|
import com.jozufozu.flywheel.fabric.model.FabricModelUtil;
|
||||||
|
@ -13,6 +12,7 @@ import net.fabricmc.fabric.api.renderer.v1.render.RenderContext.QuadTransform;
|
||||||
import net.minecraft.client.renderer.block.model.BakedQuad;
|
import net.minecraft.client.renderer.block.model.BakedQuad;
|
||||||
import net.minecraft.client.resources.model.BakedModel;
|
import net.minecraft.client.resources.model.BakedModel;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.util.RandomSource;
|
||||||
import net.minecraft.world.level.BlockAndTintGetter;
|
import net.minecraft.world.level.BlockAndTintGetter;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
|
||||||
|
@ -113,7 +113,7 @@ public class ShadeSeparatingVertexConsumer implements VertexConsumer {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void emitBlockQuads(BlockAndTintGetter blockView, BlockState state, BlockPos pos, Supplier<Random> randomSupplier, RenderContext context) {
|
public void emitBlockQuads(BlockAndTintGetter blockView, BlockState state, BlockPos pos, Supplier<RandomSource> randomSupplier, RenderContext context) {
|
||||||
context.pushTransform(quadTransform);
|
context.pushTransform(quadTransform);
|
||||||
super.emitBlockQuads(blockView, state, pos, randomSupplier, context);
|
super.emitBlockQuads(blockView, state, pos, randomSupplier, context);
|
||||||
context.popTransform();
|
context.popTransform();
|
||||||
|
|
|
@ -2,7 +2,6 @@ package com.jozufozu.flywheel.core.model;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Random;
|
|
||||||
|
|
||||||
import com.jozufozu.flywheel.core.virtual.VirtualEmptyBlockGetter;
|
import com.jozufozu.flywheel.core.virtual.VirtualEmptyBlockGetter;
|
||||||
import com.jozufozu.flywheel.fabric.model.CullingBakedModel;
|
import com.jozufozu.flywheel.fabric.model.CullingBakedModel;
|
||||||
|
@ -19,6 +18,7 @@ import net.minecraft.client.renderer.block.ModelBlockRenderer;
|
||||||
import net.minecraft.client.renderer.texture.OverlayTexture;
|
import net.minecraft.client.renderer.texture.OverlayTexture;
|
||||||
import net.minecraft.client.resources.model.BakedModel;
|
import net.minecraft.client.resources.model.BakedModel;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.util.RandomSource;
|
||||||
import net.minecraft.world.level.BlockAndTintGetter;
|
import net.minecraft.world.level.BlockAndTintGetter;
|
||||||
import net.minecraft.world.level.block.RenderShape;
|
import net.minecraft.world.level.block.RenderShape;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
@ -36,7 +36,7 @@ public final class WorldModelBuilder implements Bufferable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void bufferInto(ModelBlockRenderer modelRenderer, VertexConsumer consumer, Random random) {
|
public void bufferInto(ModelBlockRenderer modelRenderer, VertexConsumer consumer, RandomSource random) {
|
||||||
BlockRenderDispatcher dispatcher = Minecraft.getInstance().getBlockRenderer();
|
BlockRenderDispatcher dispatcher = Minecraft.getInstance().getBlockRenderer();
|
||||||
|
|
||||||
ModelBlockRenderer.enableCaching();
|
ModelBlockRenderer.enableCaching();
|
||||||
|
@ -87,6 +87,6 @@ public final class WorldModelBuilder implements Bufferable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public BlockModel intoMesh(String name) {
|
public BlockModel intoMesh(String name) {
|
||||||
return new BlockModel(ModelUtil.getBufferBuilder(this), name);
|
return new BlockModel(this, name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package com.jozufozu.flywheel.core.source;
|
package com.jozufozu.flywheel.core.source;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@ -28,24 +28,25 @@ public class ShaderSources implements SourceFinder {
|
||||||
public final Index index;
|
public final Index index;
|
||||||
|
|
||||||
public ShaderSources(ResourceManager manager) {
|
public ShaderSources(ResourceManager manager) {
|
||||||
Collection<ResourceLocation> allShaders = manager.listResources(SHADER_DIR, s -> {
|
Map<ResourceLocation, Resource> allShaders = manager.listResources(SHADER_DIR, loc -> {
|
||||||
|
String path = loc.getPath();
|
||||||
for (String ext : EXTENSIONS) {
|
for (String ext : EXTENSIONS) {
|
||||||
if (s.endsWith(ext)) return true;
|
if (path.endsWith(ext)) return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
for (ResourceLocation location : allShaders) {
|
allShaders.forEach((location, resource) -> {
|
||||||
try (Resource resource = manager.getResource(location)) {
|
try (InputStream inputStream = resource.open()) {
|
||||||
String source = StringUtil.readToString(resource.getInputStream());
|
String source = StringUtil.readToString(inputStream);
|
||||||
|
|
||||||
ResourceLocation name = ResourceUtil.removePrefixUnchecked(location, SHADER_DIR);
|
ResourceLocation name = ResourceUtil.removePrefixUnchecked(location, SHADER_DIR);
|
||||||
|
|
||||||
shaderSources.put(name, new SourceFile(this, name, source));
|
shaderSources.put(name, new SourceFile(this, name, source));
|
||||||
} catch (IOException e) {
|
} catch (IOException ignored) {
|
||||||
//
|
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
index = new Index(shaderSources);
|
index = new Index(shaderSources);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,11 +6,8 @@ import com.jozufozu.flywheel.api.vertex.VertexList;
|
||||||
import com.jozufozu.flywheel.api.vertex.VertexType;
|
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||||
import com.jozufozu.flywheel.core.layout.BufferLayout;
|
import com.jozufozu.flywheel.core.layout.BufferLayout;
|
||||||
import com.jozufozu.flywheel.core.layout.CommonItems;
|
import com.jozufozu.flywheel.core.layout.CommonItems;
|
||||||
import com.jozufozu.flywheel.core.model.ShadeSeparatedBufferBuilder;
|
|
||||||
import com.jozufozu.flywheel.fabric.helper.BufferBuilderHelper;
|
|
||||||
import com.mojang.blaze3d.vertex.BufferBuilder;
|
import com.mojang.blaze3d.vertex.BufferBuilder;
|
||||||
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
|
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
|
||||||
import com.mojang.datafixers.util.Pair;
|
|
||||||
|
|
||||||
public class BlockVertex implements VertexType {
|
public class BlockVertex implements VertexType {
|
||||||
|
|
||||||
|
@ -63,21 +60,21 @@ Vertex FLWCreateVertex() {
|
||||||
return new BlockVertexListUnsafe.Shaded(buffer, vertexCount, unshadedStartVertex);
|
return new BlockVertexListUnsafe.Shaded(buffer, vertexCount, unshadedStartVertex);
|
||||||
}
|
}
|
||||||
|
|
||||||
public VertexList createReader(BufferBuilder bufferBuilder) {
|
public VertexList createReader(BufferBuilder.RenderedBuffer renderedBuffer, int unshadedStartVertex) {
|
||||||
|
|
||||||
// TODO: try to avoid virtual model rendering
|
// TODO: try to avoid virtual model rendering
|
||||||
Pair<BufferBuilder.DrawState, ByteBuffer> pair = bufferBuilder.popNextBuffer();
|
BufferBuilder.DrawState drawState = renderedBuffer.drawState();
|
||||||
BufferBuilder.DrawState drawState = pair.getFirst();
|
|
||||||
|
|
||||||
if (drawState.format() != DefaultVertexFormat.BLOCK) {
|
if (drawState.format() != DefaultVertexFormat.BLOCK) {
|
||||||
throw new RuntimeException("Cannot use BufferBuilder with " + drawState.format());
|
throw new RuntimeException("Cannot use BufferBuilder with " + drawState.format());
|
||||||
}
|
}
|
||||||
|
ByteBuffer vertexBuffer = renderedBuffer.vertexBuffer();
|
||||||
|
|
||||||
ByteBuffer buffer = pair.getSecond();
|
int vertexCount = drawState.vertexCount();
|
||||||
BufferBuilderHelper.fixByteOrder(bufferBuilder, buffer);
|
if (unshadedStartVertex >= 0 && unshadedStartVertex < vertexCount) {
|
||||||
if (bufferBuilder instanceof ShadeSeparatedBufferBuilder separated) {
|
return createReader(vertexBuffer, vertexCount, unshadedStartVertex);
|
||||||
return createReader(buffer, drawState.vertexCount(), separated.getUnshadedStartVertex());
|
|
||||||
} else {
|
} else {
|
||||||
return createReader(buffer, drawState.vertexCount());
|
return createReader(vertexBuffer, vertexCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ import net.minecraft.world.level.chunk.ChunkStatus;
|
||||||
import net.minecraft.world.level.chunk.LevelChunkSection;
|
import net.minecraft.world.level.chunk.LevelChunkSection;
|
||||||
import net.minecraft.world.level.chunk.UpgradeData;
|
import net.minecraft.world.level.chunk.UpgradeData;
|
||||||
import net.minecraft.world.level.levelgen.Heightmap;
|
import net.minecraft.world.level.levelgen.Heightmap;
|
||||||
import net.minecraft.world.level.levelgen.feature.ConfiguredStructureFeature;
|
import net.minecraft.world.level.levelgen.structure.Structure;
|
||||||
import net.minecraft.world.level.levelgen.structure.StructureStart;
|
import net.minecraft.world.level.levelgen.structure.StructureStart;
|
||||||
import net.minecraft.world.level.material.Fluid;
|
import net.minecraft.world.level.material.Fluid;
|
||||||
import net.minecraft.world.level.material.FluidState;
|
import net.minecraft.world.level.material.FluidState;
|
||||||
|
@ -194,39 +194,39 @@ public class VirtualChunk extends ChunkAccess {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Nullable
|
@Nullable
|
||||||
public StructureStart getStartForFeature(ConfiguredStructureFeature<?, ?> pStructure) {
|
public StructureStart getStartForStructure(Structure structure) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setStartForFeature(ConfiguredStructureFeature<?, ?> pStructure, StructureStart pStart) {
|
public void setStartForStructure(Structure structure, StructureStart start) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<ConfiguredStructureFeature<?, ?>, StructureStart> getAllStarts() {
|
public Map<Structure, StructureStart> getAllStarts() {
|
||||||
return Collections.emptyMap();
|
return Collections.emptyMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setAllStarts(Map<ConfiguredStructureFeature<?, ?>, StructureStart> pStructureStarts) {
|
public void setAllStarts(Map<Structure, StructureStart> structureStarts) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LongSet getReferencesForFeature(ConfiguredStructureFeature<?, ?> pStructure) {
|
public LongSet getReferencesForStructure(Structure structure) {
|
||||||
return LongSets.emptySet();
|
return LongSets.emptySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addReferenceForFeature(ConfiguredStructureFeature<?, ?> pStructure, long pReference) {
|
public void addReferenceForStructure(Structure structure, long reference) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<ConfiguredStructureFeature<?, ?>, LongSet> getAllReferences() {
|
public Map<Structure, LongSet> getAllReferences() {
|
||||||
return Collections.emptyMap();
|
return Collections.emptyMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setAllReferences(Map<ConfiguredStructureFeature<?, ?>, LongSet> pStructureReferences) {
|
public void setAllReferences(Map<Structure, LongSet> structureReferences) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -36,10 +36,12 @@ import net.minecraft.world.level.chunk.ChunkSource;
|
||||||
import net.minecraft.world.level.chunk.LevelChunk;
|
import net.minecraft.world.level.chunk.LevelChunk;
|
||||||
import net.minecraft.world.level.entity.LevelEntityGetter;
|
import net.minecraft.world.level.entity.LevelEntityGetter;
|
||||||
import net.minecraft.world.level.gameevent.GameEvent;
|
import net.minecraft.world.level.gameevent.GameEvent;
|
||||||
|
import net.minecraft.world.level.gameevent.GameEvent.Context;
|
||||||
import net.minecraft.world.level.lighting.LevelLightEngine;
|
import net.minecraft.world.level.lighting.LevelLightEngine;
|
||||||
import net.minecraft.world.level.material.Fluid;
|
import net.minecraft.world.level.material.Fluid;
|
||||||
import net.minecraft.world.level.saveddata.maps.MapItemSavedData;
|
import net.minecraft.world.level.saveddata.maps.MapItemSavedData;
|
||||||
import net.minecraft.world.level.storage.WritableLevelData;
|
import net.minecraft.world.level.storage.WritableLevelData;
|
||||||
|
import net.minecraft.world.phys.Vec3;
|
||||||
import net.minecraft.world.scores.Scoreboard;
|
import net.minecraft.world.scores.Scoreboard;
|
||||||
import net.minecraft.world.ticks.LevelTickAccess;
|
import net.minecraft.world.ticks.LevelTickAccess;
|
||||||
|
|
||||||
|
@ -68,7 +70,7 @@ public class VirtualRenderWorld extends Level implements FlywheelWorld {
|
||||||
|
|
||||||
public VirtualRenderWorld(Level level, Vec3i biomeOffset, int height, int minBuildHeight) {
|
public VirtualRenderWorld(Level level, Vec3i biomeOffset, int height, int minBuildHeight) {
|
||||||
super((WritableLevelData) level.getLevelData(), level.dimension(), level.dimensionTypeRegistration(), level::getProfiler,
|
super((WritableLevelData) level.getLevelData(), level.dimension(), level.dimensionTypeRegistration(), level::getProfiler,
|
||||||
true, false, 0);
|
true, false, 0, 0);
|
||||||
this.biomeOffset = biomeOffset;
|
this.biomeOffset = biomeOffset;
|
||||||
this.level = level;
|
this.level = level;
|
||||||
this.height = nextMultipleOf16(height);
|
this.height = nextMultipleOf16(height);
|
||||||
|
@ -289,6 +291,17 @@ public class VirtualRenderWorld extends Level implements FlywheelWorld {
|
||||||
@Override
|
@Override
|
||||||
public void levelEvent(@Nullable Player player, int type, BlockPos pos, int data) {}
|
public void levelEvent(@Nullable Player player, int type, BlockPos pos, int data) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void gameEvent(GameEvent p_220404_, Vec3 p_220405_, Context p_220406_) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void playSeededSound(Player p_220363_, double p_220364_, double p_220365_, double p_220366_,
|
||||||
|
SoundEvent p_220367_, SoundSource p_220368_, float p_220369_, float p_220370_, long p_220371_) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void playSeededSound(Player p_220372_, Entity p_220373_, SoundEvent p_220374_, SoundSource p_220375_,
|
||||||
|
float p_220376_, float p_220377_, long p_220378_) {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void playSound(@Nullable Player player, double x, double y, double z, SoundEvent soundIn,
|
public void playSound(@Nullable Player player, double x, double y, double z, SoundEvent soundIn,
|
||||||
SoundSource category, float volume, float pitch) {}
|
SoundSource category, float volume, float pitch) {}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package com.jozufozu.flywheel.fabric.model;
|
package com.jozufozu.flywheel.fabric.model;
|
||||||
|
|
||||||
import java.util.Random;
|
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import net.fabricmc.fabric.api.renderer.v1.model.ForwardingBakedModel;
|
import net.fabricmc.fabric.api.renderer.v1.model.ForwardingBakedModel;
|
||||||
|
@ -8,6 +7,7 @@ import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
|
||||||
import net.minecraft.client.resources.model.BakedModel;
|
import net.minecraft.client.resources.model.BakedModel;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
|
import net.minecraft.util.RandomSource;
|
||||||
import net.minecraft.world.level.BlockAndTintGetter;
|
import net.minecraft.world.level.BlockAndTintGetter;
|
||||||
import net.minecraft.world.level.block.Block;
|
import net.minecraft.world.level.block.Block;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
@ -33,7 +33,7 @@ public class CullingBakedModel extends ForwardingBakedModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void emitBlockQuads(BlockAndTintGetter blockView, BlockState state, BlockPos pos, Supplier<Random> randomSupplier, RenderContext context) {
|
public void emitBlockQuads(BlockAndTintGetter blockView, BlockState state, BlockPos pos, Supplier<RandomSource> randomSupplier, RenderContext context) {
|
||||||
completionFlags = 0;
|
completionFlags = 0;
|
||||||
resultFlags = 0;
|
resultFlags = 0;
|
||||||
context.pushTransform(quad -> {
|
context.pushTransform(quad -> {
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package com.jozufozu.flywheel.fabric.model;
|
package com.jozufozu.flywheel.fabric.model;
|
||||||
|
|
||||||
import java.util.Random;
|
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import net.fabricmc.fabric.api.renderer.v1.material.BlendMode;
|
import net.fabricmc.fabric.api.renderer.v1.material.BlendMode;
|
||||||
|
@ -10,6 +9,7 @@ import net.fabricmc.fabric.api.renderer.v1.model.ForwardingBakedModel;
|
||||||
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
|
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
|
||||||
import net.minecraft.client.resources.model.BakedModel;
|
import net.minecraft.client.resources.model.BakedModel;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.util.RandomSource;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
import net.minecraft.world.level.BlockAndTintGetter;
|
import net.minecraft.world.level.BlockAndTintGetter;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
@ -30,14 +30,14 @@ public class DefaultLayerFilteringBakedModel extends ForwardingBakedModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void emitBlockQuads(BlockAndTintGetter blockView, BlockState state, BlockPos pos, Supplier<Random> randomSupplier, RenderContext context) {
|
public void emitBlockQuads(BlockAndTintGetter blockView, BlockState state, BlockPos pos, Supplier<RandomSource> randomSupplier, RenderContext context) {
|
||||||
context.pushTransform(DefaultLayerFilteringBakedModel::hasDefaultBlendMode);
|
context.pushTransform(DefaultLayerFilteringBakedModel::hasDefaultBlendMode);
|
||||||
super.emitBlockQuads(blockView, state, pos, randomSupplier, context);
|
super.emitBlockQuads(blockView, state, pos, randomSupplier, context);
|
||||||
context.popTransform();
|
context.popTransform();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void emitItemQuads(ItemStack stack, Supplier<Random> randomSupplier, RenderContext context) {
|
public void emitItemQuads(ItemStack stack, Supplier<RandomSource> randomSupplier, RenderContext context) {
|
||||||
context.pushTransform(DefaultLayerFilteringBakedModel::hasDefaultBlendMode);
|
context.pushTransform(DefaultLayerFilteringBakedModel::hasDefaultBlendMode);
|
||||||
super.emitItemQuads(stack, randomSupplier, context);
|
super.emitItemQuads(stack, randomSupplier, context);
|
||||||
context.popTransform();
|
context.popTransform();
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package com.jozufozu.flywheel.fabric.model;
|
package com.jozufozu.flywheel.fabric.model;
|
||||||
|
|
||||||
import java.util.Random;
|
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import net.fabricmc.fabric.api.renderer.v1.model.ForwardingBakedModel;
|
import net.fabricmc.fabric.api.renderer.v1.model.ForwardingBakedModel;
|
||||||
|
@ -9,6 +8,7 @@ import net.minecraft.client.renderer.ItemBlockRenderTypes;
|
||||||
import net.minecraft.client.renderer.RenderType;
|
import net.minecraft.client.renderer.RenderType;
|
||||||
import net.minecraft.client.resources.model.BakedModel;
|
import net.minecraft.client.resources.model.BakedModel;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.util.RandomSource;
|
||||||
import net.minecraft.world.level.BlockAndTintGetter;
|
import net.minecraft.world.level.BlockAndTintGetter;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ public class LayerFilteringBakedModel extends ForwardingBakedModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void emitBlockQuads(BlockAndTintGetter blockView, BlockState state, BlockPos pos, Supplier<Random> randomSupplier, RenderContext context) {
|
public void emitBlockQuads(BlockAndTintGetter blockView, BlockState state, BlockPos pos, Supplier<RandomSource> randomSupplier, RenderContext context) {
|
||||||
RenderType defaultLayer = ItemBlockRenderTypes.getChunkRenderType(state);
|
RenderType defaultLayer = ItemBlockRenderTypes.getChunkRenderType(state);
|
||||||
if (super.isVanillaAdapter()) {
|
if (super.isVanillaAdapter()) {
|
||||||
if (defaultLayer == targetLayer) {
|
if (defaultLayer == targetLayer) {
|
||||||
|
|
|
@ -1,30 +1,78 @@
|
||||||
package com.jozufozu.flywheel.mixin.instancemanage;
|
package com.jozufozu.flywheel.mixin.instancemanage;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.spongepowered.asm.mixin.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.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.Backend;
|
import com.jozufozu.flywheel.backend.Backend;
|
||||||
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
|
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
|
||||||
import com.jozufozu.flywheel.backend.instancing.InstancedRenderRegistry;
|
import com.jozufozu.flywheel.backend.instancing.InstancedRenderRegistry;
|
||||||
|
import com.jozufozu.flywheel.util.RenderChunkExtension;
|
||||||
|
|
||||||
import net.minecraft.client.renderer.chunk.ChunkRenderDispatcher;
|
import net.minecraft.client.renderer.chunk.ChunkRenderDispatcher;
|
||||||
|
import net.minecraft.client.renderer.chunk.RenderChunkRegion;
|
||||||
|
import net.minecraft.world.level.Level;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
|
|
||||||
@Mixin(targets = "net.minecraft.client.renderer.chunk.ChunkRenderDispatcher$RenderChunk$RebuildTask")
|
@Mixin(targets = "net.minecraft.client.renderer.chunk.ChunkRenderDispatcher$RenderChunk$RebuildTask")
|
||||||
public class ChunkRebuildHooksMixin {
|
public abstract class ChunkRebuildHooksMixin {
|
||||||
|
@Unique
|
||||||
|
private Level flywheel$level;
|
||||||
|
|
||||||
@Inject(method = "handleBlockEntity", at = @At("HEAD"), cancellable = true)
|
@Inject(method = "<init>(Lnet/minecraft/client/renderer/chunk/ChunkRenderDispatcher$RenderChunk;DLnet/minecraft/client/renderer/chunk/RenderChunkRegion;Z)V", at = @At("RETURN"))
|
||||||
private <E extends BlockEntity> void addAndFilterBEs(ChunkRenderDispatcher.CompiledChunk compiledChunk, Set<BlockEntity> set, E be, CallbackInfo ci) {
|
private void setLevel(ChunkRenderDispatcher.RenderChunk this$1, double p_194427_, RenderChunkRegion region, boolean p_194429_, CallbackInfo ci) {
|
||||||
if (Backend.canUseInstancing(be.getLevel())) {
|
flywheel$level = ((RenderChunkExtension) this$1).flywheel$getLevel();
|
||||||
if (InstancedRenderRegistry.canInstance(be.getType()))
|
}
|
||||||
InstancedRenderDispatcher.getBlockEntities(be.getLevel()).queueAdd(be);
|
|
||||||
|
|
||||||
if (InstancedRenderRegistry.shouldSkipRender(be))
|
@Redirect(method = "doTask", at = @At(value = "INVOKE", target = "Ljava/util/List;addAll(Ljava/util/Collection;)Z"))
|
||||||
ci.cancel();
|
private <E extends BlockEntity> boolean addAndFilterBEs(List<BlockEntity> self, Collection<? extends E> es) {
|
||||||
|
if (!Backend.canUseInstancing(flywheel$level)) {
|
||||||
|
return self.addAll(es);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean added = false;
|
||||||
|
var instanced = new ArrayList<BlockEntity>();
|
||||||
|
for (E be : es) {
|
||||||
|
if (InstancedRenderRegistry.canInstance(be.getType())) {
|
||||||
|
instanced.add(be);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!InstancedRenderRegistry.shouldSkipRender(be)) {
|
||||||
|
self.add(be);
|
||||||
|
added = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
InstancedRenderDispatcher.getBlockEntities(flywheel$level).queueAddAll(instanced);
|
||||||
|
return added;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Redirect(method = "doTask", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/chunk/ChunkRenderDispatcher$RenderChunk;updateGlobalBlockEntities(Ljava/util/Collection;)V"))
|
||||||
|
private void addAndFilterBEs(ChunkRenderDispatcher.RenderChunk self, Collection<BlockEntity> bes) {
|
||||||
|
if (!Backend.canUseInstancing(flywheel$level)) {
|
||||||
|
((RenderChunkAccessor) self).flywheel$updateGlobalBlockEntities(bes);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var global = new ArrayList<BlockEntity>();
|
||||||
|
var instanced = new ArrayList<BlockEntity>();
|
||||||
|
for (BlockEntity be : bes) {
|
||||||
|
if (InstancedRenderRegistry.canInstance(be.getType())) {
|
||||||
|
instanced.add(be);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!InstancedRenderRegistry.shouldSkipRender(be)) {
|
||||||
|
global.add(be);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
InstancedRenderDispatcher.getBlockEntities(flywheel$level).queueAddAll(instanced);
|
||||||
|
((RenderChunkAccessor) self).flywheel$updateGlobalBlockEntities(global);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
package com.jozufozu.flywheel.mixin.instancemanage;
|
||||||
|
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||||
|
|
||||||
|
import net.minecraft.client.multiplayer.ClientLevel;
|
||||||
|
import net.minecraft.client.renderer.chunk.ChunkRenderDispatcher;
|
||||||
|
|
||||||
|
@Mixin(ChunkRenderDispatcher.class)
|
||||||
|
public interface ChunkRenderDispatcherAccessor {
|
||||||
|
|
||||||
|
@Accessor
|
||||||
|
ClientLevel getLevel();
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package com.jozufozu.flywheel.mixin.instancemanage;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.gen.Invoker;
|
||||||
|
|
||||||
|
import net.minecraft.client.renderer.chunk.ChunkRenderDispatcher;
|
||||||
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For use in {@link ChunkRebuildHooksMixin#addAndFilterBEs(ChunkRenderDispatcher.RenderChunk, Collection)}
|
||||||
|
*/
|
||||||
|
@Mixin(ChunkRenderDispatcher.RenderChunk.class)
|
||||||
|
public interface RenderChunkAccessor {
|
||||||
|
|
||||||
|
@Invoker("updateGlobalBlockEntities")
|
||||||
|
void flywheel$updateGlobalBlockEntities(Collection<BlockEntity> blockEntities);
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package com.jozufozu.flywheel.mixin.instancemanage;
|
||||||
|
|
||||||
|
import org.spongepowered.asm.mixin.Final;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
|
|
||||||
|
import net.minecraft.client.multiplayer.ClientLevel;
|
||||||
|
import net.minecraft.client.renderer.chunk.ChunkRenderDispatcher;
|
||||||
|
|
||||||
|
@Mixin(ChunkRenderDispatcher.RenderChunk.class)
|
||||||
|
public class RenderChunkMixin implements com.jozufozu.flywheel.util.RenderChunkExtension {
|
||||||
|
|
||||||
|
@Shadow(aliases = {"this$0", "field_20833", "f_dssekupm"}) // Optifine does not use the obfuscated name so the mapped name must be included as an alias
|
||||||
|
@Final
|
||||||
|
private ChunkRenderDispatcher this$0;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ClientLevel flywheel$getLevel() {
|
||||||
|
return ((ChunkRenderDispatcherAccessor) this$0).getLevel();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
package com.jozufozu.flywheel.mixin.instancemanage;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
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 org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.backend.Backend;
|
||||||
|
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
|
||||||
|
import com.jozufozu.flywheel.backend.instancing.InstancedRenderRegistry;
|
||||||
|
|
||||||
|
import me.jellysquid.mods.sodium.client.render.chunk.data.ChunkRenderData;
|
||||||
|
import net.minecraft.world.level.Level;
|
||||||
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
|
|
||||||
|
@Mixin(targets = "me.jellysquid.mods.sodium.client.render.chunk.data.ChunkRenderData$Builder", remap = false)
|
||||||
|
public class SodiumChunkRenderDataMixin {
|
||||||
|
|
||||||
|
@Unique
|
||||||
|
private List<BlockEntity> flywheel$blockEntities;
|
||||||
|
@Unique
|
||||||
|
private Level flywheel$level;
|
||||||
|
|
||||||
|
@Inject(method = "addBlockEntity", at = @At("HEAD"), cancellable = true, require = 0)
|
||||||
|
private void flywheel$onAddBlockEntity(BlockEntity be, boolean cull, CallbackInfo ci) {
|
||||||
|
if (flywheel$level == null) {
|
||||||
|
flywheel$level = be.getLevel();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Backend.canUseInstancing(flywheel$level)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (InstancedRenderRegistry.canInstance(be.getType())) {
|
||||||
|
if (flywheel$blockEntities == null) {
|
||||||
|
flywheel$blockEntities = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Collect BEs in a temporary list to avoid excessive synchronization in InstancedRenderDispatcher.
|
||||||
|
flywheel$blockEntities.add(be);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (InstancedRenderRegistry.shouldSkipRender(be)) {
|
||||||
|
ci.cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject(method = "build", at = @At("HEAD"))
|
||||||
|
private void flywheel$onBuild(CallbackInfoReturnable<ChunkRenderData> cir) {
|
||||||
|
if (flywheel$level == null || flywheel$blockEntities == null || !Backend.canUseInstancing(flywheel$level)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
InstancedRenderDispatcher.getBlockEntities(flywheel$level)
|
||||||
|
.queueAddAll(flywheel$blockEntities);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package com.jozufozu.flywheel.util;
|
||||||
|
|
||||||
|
import net.minecraft.client.multiplayer.ClientLevel;
|
||||||
|
|
||||||
|
public interface RenderChunkExtension {
|
||||||
|
ClientLevel flywheel$getLevel();
|
||||||
|
}
|
|
@ -33,7 +33,7 @@
|
||||||
"depends": {
|
"depends": {
|
||||||
"fabricloader": ">=0.11.3",
|
"fabricloader": ">=0.11.3",
|
||||||
"fabric": "*",
|
"fabric": "*",
|
||||||
"minecraft": ">=1.18.2",
|
"minecraft": ">=1.19.2",
|
||||||
"java": ">=17"
|
"java": ">=17"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,8 +22,12 @@
|
||||||
"atlas.AtlasDataMixin",
|
"atlas.AtlasDataMixin",
|
||||||
"atlas.SheetDataAccessor",
|
"atlas.SheetDataAccessor",
|
||||||
"instancemanage.ChunkRebuildHooksMixin",
|
"instancemanage.ChunkRebuildHooksMixin",
|
||||||
|
"instancemanage.ChunkRenderDispatcherAccessor",
|
||||||
"instancemanage.InstanceAddMixin",
|
"instancemanage.InstanceAddMixin",
|
||||||
"instancemanage.InstanceRemoveMixin",
|
"instancemanage.InstanceRemoveMixin",
|
||||||
|
"instancemanage.RenderChunkAccessor",
|
||||||
|
"instancemanage.RenderChunkMixin",
|
||||||
|
"instancemanage.SodiumChunkRenderDataMixin",
|
||||||
"light.LightUpdateMixin",
|
"light.LightUpdateMixin",
|
||||||
"light.NetworkLightUpdateMixin",
|
"light.NetworkLightUpdateMixin",
|
||||||
"matrix.Matrix3fMixin",
|
"matrix.Matrix3fMixin",
|
||||||
|
|
Loading…
Reference in a new issue