Port to Fabric

This commit is contained in:
PepperBell 2021-10-14 16:20:56 -07:00
parent 0bbfb60d0c
commit 9a1c381f70
63 changed files with 830 additions and 743 deletions

View file

@ -1,24 +1,9 @@
buildscript {
repositories {
maven { url = 'https://maven.minecraftforge.net' }
jcenter()
mavenCentral()
maven { url = 'https://repo.spongepowered.org/repository/maven-public/' }
}
dependencies {
classpath group: 'net.minecraftforge.gradle', name: 'ForgeGradle', version: '5.1.+', changing: true
classpath group: 'org.spongepowered', name: 'mixingradle', version: '0.7-SNAPSHOT'
}
}
plugins {
id 'fabric-loom' version '0.10-SNAPSHOT'
id 'maven-publish'
id 'com.matthewprenger.cursegradle' version '1.4.0'
}
apply plugin: 'net.minecraftforge.gradle'
apply plugin: 'eclipse'
apply plugin: 'maven-publish'
apply plugin: 'org.spongepowered.mixin'
boolean dev = System.getenv('RELEASE') == null || System.getenv('RELEASE').equalsIgnoreCase('false');
ext.buildnumber = 0
@ -28,67 +13,12 @@ version = "${mc_update_version}-${mod_version}" + (dev ? ".${buildnumber}" : '')
group = 'com.jozufozu.flywheel'
archivesBaseName = 'flywheel'
sourceCompatibility = JavaVersion.VERSION_16
targetCompatibility = JavaVersion.VERSION_16
java.toolchain.languageVersion = JavaLanguageVersion.of(16)
println('Java: ' + System.getProperty('java.version') + ' JVM: ' + System.getProperty('java.vm.version') + '(' + System.getProperty('java.vendor') + ') Arch: ' + System.getProperty('os.arch'))
minecraft {
mappings channel: 'official', version: "${minecraft_version}"
//accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg')
runs {
client {
workingDirectory project.file('run')
property 'forge.logging.markers', ''
property 'forge.logging.console.level', 'debug'
property 'fml.earlyprogresswindow', 'false'
property 'mixin.debug.export', 'true'
arg "-mixin.config=flywheel.mixins.json"
mods {
flywheel {
source sourceSets.main
}
}
}
server {
workingDirectory project.file('run')
property 'forge.logging.markers', 'REGISTRIES'
property 'forge.logging.console.level', 'debug'
arg "-mixin.config=flywheel.mixins.json"
mods {
flywheel {
source sourceSets.main
}
}
}
data {
workingDirectory project.file('run')
property 'forge.logging.markers', 'REGISTRIES'
property 'forge.logging.console.level', 'debug'
// Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources.
args '--mod', 'flywheel', '--all', '--output', file('src/generated/resources/'), '--existing', file('src/main/resources/')
mods {
flywheel {
source sourceSets.main
}
}
}
}
}
mixin {
add sourceSets.main, "flywheel.refmap.json"
}
repositories {
maven {
@ -98,11 +28,47 @@ repositories {
}
dependencies {
minecraft "net.minecraftforge:forge:${minecraft_version}-${forge_version}"
// To change the versions see the gradle.properties file
minecraft "com.mojang:minecraft:${project.minecraft_version}"
mappings loom.officialMojangMappings()
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
//implementation "org.joml:joml:1.10.1"
// Fabric API
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
annotationProcessor 'org.spongepowered:mixin:0.8.4:processor'
implementation 'com.google.code.findbugs:jsr305:3.0.2'
}
processResources {
inputs.property 'version', project.version
filesMatching('fabric.mod.json') {
expand 'version': project.version
}
}
tasks.withType(JavaCompile).configureEach {
// ensure that the encoding is set to UTF-8, no matter what the system default is
// this fixes some edge cases with special characters not displaying correctly
// see http://yodaconditions.net/blog/fix-for-java-file-encoding-problems-with-gradle.html
// If Javadoc is generated, this must be specified in that task too.
it.options.encoding = 'UTF-8'
// Minecraft 1.17 (21w19a) upwards uses Java 16.
it.options.release = 16
}
java {
// Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task
// if it is present.
// If you remove this line, sources will not be generated.
withSourcesJar()
}
jar {
from('LICENSE') {
rename { "${it}_${project.archivesBaseName}" }
}
}
// Example for how to get properties into the manifest for reading by the runtime..
@ -121,36 +87,29 @@ jar {
}
}
jar.finalizedBy('reobfJar')
javadoc {
source = [sourceSets.main.allJava]
// prevent java 8's strict doclint for javadocs from failing builds
options.addStringOption('Xdoclint:none', '-quiet')
}
task sourcesJar(type: Jar) {
from sourceSets.main.allSource
archiveBaseName.set(project.archivesBaseName)
archiveVersion.set("${project.version}")
archiveClassifier.set('sources')
}
task javadocJar(type: Jar, dependsOn: javadoc) {
from javadoc.destinationDir
archiveClassifier.set('javadoc')
}
artifacts {
archives jar, sourcesJar, javadocJar
archives remapJar, sourcesJar, javadocJar
}
publishing {
tasks.publish.dependsOn 'build'
publications {
mavenJava(MavenPublication) {
artifact jar
artifact sourcesJar
artifact remapJar
artifact(sourcesJar) {
builtBy remapSourcesJar
}
artifact javadocJar
}
}

View file

@ -4,7 +4,8 @@ org.gradle.daemon=false
mod_version=0.3.0
mc_update_version=1.17
minecraft_version=1.17.1
forge_version=37.0.59
loader_version=0.12.1
fabric_version=0.40.8+1.17
# curseforge info
projectId=486392

View file

@ -1 +1,11 @@
pluginManagement {
repositories {
maven {
name = 'Fabric'
url = 'https://maven.fabricmc.net/'
}
gradlePluginPortal()
}
}
rootProject.name = 'Flywheel'

View file

@ -1,39 +1,12 @@
package com.jozufozu.flywheel;
import com.jozufozu.flywheel.config.FlwCommands;
import com.jozufozu.flywheel.config.FlwConfig;
import com.jozufozu.flywheel.config.FlwPackets;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
@Mod("flywheel")
public class Flywheel {
public static final String ID = "flywheel";
public Flywheel() {
FMLJavaModLoadingContext.get()
.getModEventBus()
.addListener(this::setup);
MinecraftForge.EVENT_BUS.addListener(FlwCommands::onServerStarting);
FlwConfig.init();
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> FlywheelClient::clientInit);
}
public static ResourceLocation rl(String path) {
return new ResourceLocation(ID, path);
}
private void setup(final FMLCommonSetupEvent event) {
FlwPackets.registerPackets();
}
}

View file

@ -1,30 +1,60 @@
package com.jozufozu.flywheel;
import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.Loader;
import com.jozufozu.flywheel.backend.RenderWork;
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
import com.jozufozu.flywheel.config.FlwConfig;
import com.jozufozu.flywheel.core.AtlasStitcher;
import com.jozufozu.flywheel.core.Contexts;
import com.jozufozu.flywheel.core.Materials;
import com.jozufozu.flywheel.core.PartialModel;
import com.jozufozu.flywheel.core.QuadConverter;
import com.jozufozu.flywheel.core.crumbling.CrumblingRenderer;
import com.jozufozu.flywheel.event.EntityWorldHandler;
import com.jozufozu.flywheel.event.ForgeEvents;
import com.jozufozu.flywheel.fabric.event.FlywheelEvents;
import com.jozufozu.flywheel.vanilla.VanillaInstances;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientEntityEvents;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
import net.fabricmc.fabric.api.client.model.ModelLoadingRegistry;
import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents;
import net.fabricmc.fabric.api.event.client.ClientSpriteRegistryCallback;
import net.fabricmc.fabric.api.resource.ResourceManagerHelper;
import net.minecraft.server.packs.PackType;
import net.minecraft.world.inventory.InventoryMenu;
public class FlywheelClient {
public class FlywheelClient implements ClientModInitializer {
public static void clientInit() {
@Override
public void onInitializeClient() {
Backend.init();
IEventBus modEventBus = FMLJavaModLoadingContext.get()
.getModEventBus();
modEventBus.addListener(AtlasStitcher.getInstance()::onTextureStitch);
ClientSpriteRegistryCallback.event(InventoryMenu.BLOCK_ATLAS).register(AtlasStitcher.getInstance()::onTextureStitch);
modEventBus.addListener(Contexts::flwInit);
modEventBus.addListener(Materials::flwInit);
modEventBus.addListener(PartialModel::onModelRegistry);
modEventBus.addListener(PartialModel::onModelBake);
FlywheelEvents.GATHER_CONTEXT.register(Contexts::flwInit);
FlywheelEvents.GATHER_CONTEXT.register(Materials::flwInit);
ModelLoadingRegistry.INSTANCE.registerModelProvider(PartialModel::onModelRegistry);
ResourceManagerHelper.get(PackType.CLIENT_RESOURCES).registerReloadListener(PartialModel.ResourceReloadListener.INSTANCE);
VanillaInstances.init();
ResourceManagerHelper.get(PackType.CLIENT_RESOURCES).registerReloadListener(Loader.ResourceReloadListener.INSTANCE);
WorldRenderEvents.END.register(RenderWork::onRenderWorldLast);
ClientTickEvents.END_CLIENT_TICK.register(InstancedRenderDispatcher::tick);
FlywheelEvents.BEGIN_FRAME.register(InstancedRenderDispatcher::onBeginFrame);
FlywheelEvents.RENDER_LAYER.register(InstancedRenderDispatcher::renderLayer);
FlywheelEvents.RELOAD_RENDERERS.register(InstancedRenderDispatcher::onReloadRenderers);
FlywheelEvents.RELOAD_RENDERERS.register(QuadConverter::onRendererReload);
FlywheelEvents.RELOAD_RENDERERS.register(CrumblingRenderer::onReloadRenderers);
ClientEntityEvents.ENTITY_LOAD.register(EntityWorldHandler::onEntityJoinWorld);
ClientEntityEvents.ENTITY_UNLOAD.register(EntityWorldHandler::onEntityLeaveWorld);
ClientTickEvents.END_CLIENT_TICK.register(ForgeEvents::tickLight);
FlwConfig.init();
}
}

View file

@ -1,8 +1,14 @@
package com.jozufozu.flywheel.backend;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.function.Consumer;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
import com.jozufozu.flywheel.backend.source.Resolver;
import com.jozufozu.flywheel.backend.source.ShaderLoadingException;
@ -10,26 +16,21 @@ import com.jozufozu.flywheel.backend.source.ShaderSources;
import com.jozufozu.flywheel.core.crumbling.CrumblingRenderer;
import com.jozufozu.flywheel.core.shader.spec.ProgramSpec;
import com.jozufozu.flywheel.event.GatherContextEvent;
import com.jozufozu.flywheel.fabric.event.FlywheelEvents;
import com.jozufozu.flywheel.util.ResourceUtil;
import com.jozufozu.flywheel.util.StreamUtil;
import com.mojang.datafixers.util.Pair;
import com.mojang.serialization.DataResult;
import com.mojang.serialization.JsonOps;
import net.fabricmc.fabric.api.resource.IdentifiableResourceReloadListener;
import net.fabricmc.fabric.api.resource.ResourceReloadListenerKeys;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.resources.ReloadableResourceManager;
import net.minecraft.server.packs.resources.Resource;
import net.minecraft.server.packs.resources.ResourceManager;
import net.minecraft.server.packs.resources.ResourceManagerReloadListener;
import net.minecraftforge.fml.ModLoader;
import net.minecraftforge.resource.IResourceType;
import net.minecraftforge.resource.VanillaResourceType;
import javax.annotation.Nullable;
import java.util.Collection;
/**
* The main entity for loading shaders.
@ -38,7 +39,7 @@ import java.util.Collection;
* This class is responsible for invoking the loading, parsing, and compilation stages.
* </p>
*/
public class Loader implements ResourceManagerReloadListener {
public class Loader {
public static final String PROGRAM_DIR = "flywheel/programs/";
private static final Gson GSON = new GsonBuilder().create();
@ -50,21 +51,13 @@ public class Loader implements ResourceManagerReloadListener {
public Loader(Backend backend) {
this.backend = backend;
// Can be null when running datagenerators due to the unfortunate time we call this
Minecraft minecraft = Minecraft.getInstance();
if (minecraft != null) {
ResourceManager manager = minecraft.getResourceManager();
if (manager instanceof ReloadableResourceManager) {
((ReloadableResourceManager) manager).registerReloadListener(this);
}
}
ResourceReloadListener.INSTANCE.addCallback(this::onResourceManagerReload);
}
public void notifyError() {
shouldCrash = true;
}
@Override
public void onResourceManagerReload(ResourceManager manager) {
backend.refresh();
@ -73,8 +66,8 @@ public class Loader implements ResourceManagerReloadListener {
backend._clearContexts();
Resolver.INSTANCE.invalidate();
ModLoader.get()
.postEvent(new GatherContextEvent(backend, firstLoad));
FlywheelEvents.GATHER_CONTEXT.invoker()
.handleEvent(new GatherContextEvent(backend, firstLoad));
ShaderSources sources = new ShaderSources(manager);
@ -129,9 +122,31 @@ public class Loader implements ResourceManagerReloadListener {
}
}
@Nullable
@Override
public IResourceType getResourceType() {
return VanillaResourceType.SHADERS;
public static class ResourceReloadListener implements ResourceManagerReloadListener, IdentifiableResourceReloadListener {
public static final ResourceReloadListener INSTANCE = new ResourceReloadListener();
public static final ResourceLocation ID = Flywheel.rl("loaders");
public static final List<ResourceLocation> DEPENDENCIES = List.of(ResourceReloadListenerKeys.TEXTURES, ResourceReloadListenerKeys.MODELS);
private final List<Consumer<ResourceManager>> callbacks = new ArrayList<>();
@Override
public void onResourceManagerReload(ResourceManager resourceManager) {
callbacks.forEach(callback -> callback.accept(resourceManager));
}
@Override
public ResourceLocation getFabricId() {
return ID;
}
@Override
public List<ResourceLocation> getFabricDependencies() {
return DEPENDENCIES;
}
protected void addCallback(Consumer<ResourceManager> callback) {
callbacks.add(callback);
}
}
}

View file

@ -3,19 +3,13 @@ package com.jozufozu.flywheel.backend;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.RenderWorldLastEvent;
import net.minecraftforge.eventbus.api.EventPriority;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext;
@Mod.EventBusSubscriber(value = Dist.CLIENT)
public class RenderWork {
private static final Queue<Runnable> runs = new ConcurrentLinkedQueue<>();
@SubscribeEvent(priority = EventPriority.LOWEST)
public static void onRenderWorldLast(RenderWorldLastEvent event) {
public static void onRenderWorldLast(WorldRenderContext context) {
while (!runs.isEmpty()) {
runs.remove()
.run();

View file

@ -10,10 +10,6 @@ import javax.annotation.Nullable;
import org.lwjgl.opengl.GL11;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@OnlyIn(Dist.CLIENT)
public enum GlNumericType {
FLOAT(4, "float", GL11.GL_FLOAT),
UBYTE(1, "ubyte", GL11.GL_UNSIGNED_BYTE),

View file

@ -10,16 +10,9 @@ import com.jozufozu.flywheel.util.WorldAttached;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.LevelAccessor;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.event.TickEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraft.world.level.block.entity.BlockEntity;
@OnlyIn(Dist.CLIENT)
@Mod.EventBusSubscriber(Dist.CLIENT)
public class InstancedRenderDispatcher {
private static final WorldAttached<InstanceWorld> instanceWorlds = new WorldAttached<>($ -> new InstanceWorld());
@ -50,20 +43,17 @@ public class InstancedRenderDispatcher {
.getEntityInstanceManager();
}
@SubscribeEvent
public static void tick(TickEvent.ClientTickEvent event) {
public static void tick(Minecraft mc) {
if (!Backend.isGameActive() || event.phase == TickEvent.Phase.START) {
if (!Backend.isGameActive()) {
return;
}
Minecraft mc = Minecraft.getInstance();
ClientLevel world = mc.level;
AnimationTickHolder.tick();
instanceWorlds.get(world).tick();
}
@SubscribeEvent
public static void onBeginFrame(BeginFrameEvent event) {
if (Backend.isGameActive()) {
instanceWorlds.get(event.getWorld())
@ -71,7 +61,6 @@ public class InstancedRenderDispatcher {
}
}
@SubscribeEvent
public static void renderLayer(RenderLayerEvent event) {
if (event.layer == null) return;
@ -82,7 +71,6 @@ public class InstancedRenderDispatcher {
instanceWorlds.get(world).renderLayer(event);
}
@SubscribeEvent
public static void onReloadRenderers(ReloadRenderersEvent event) {
ClientLevel world = event.getWorld();
if (Backend.getInstance()

View file

@ -9,14 +9,15 @@ import com.jozufozu.flywheel.backend.state.IRenderState;
import com.jozufozu.flywheel.backend.state.RenderLayer;
import com.jozufozu.flywheel.core.WorldContext;
import com.jozufozu.flywheel.core.shader.WorldProgram;
import com.jozufozu.flywheel.fabric.helper.Matrix4fHelper;
import com.jozufozu.flywheel.util.WeakHashSet;
import com.mojang.math.Matrix4f;
import net.minecraft.client.Camera;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.core.BlockPos;
import net.minecraft.util.Mth;
import com.mojang.math.Matrix4f;
import net.minecraft.core.Vec3i;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.Mth;
public class MaterialManagerImpl<P extends WorldProgram> implements MaterialManager {
@ -78,7 +79,7 @@ public class MaterialManagerImpl<P extends WorldProgram> implements MaterialMana
Matrix4f translate = Matrix4f.createTranslateMatrix((float) -camX, (float) -camY, (float) -camZ);
translate.multiplyBackward(viewProjection);
Matrix4fHelper.multiplyBackward(translate, viewProjection);
viewProjection = translate;
}

View file

@ -1,97 +0,0 @@
package com.jozufozu.flywheel.config;
import java.util.function.Consumer;
import java.util.function.Supplier;
import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.OptifineHandler;
import net.minecraft.client.Minecraft;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.network.chat.MutableComponent;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.ChatFormatting;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
public enum BooleanConfig {
ENGINE(() -> BooleanConfig::enabled),
NORMAL_OVERLAY(() -> BooleanConfig::normalOverlay),
CHUNK_CACHING(() -> BooleanConfig::chunkCaching),
;
final Supplier<Consumer<BooleanDirective>> receiver;
BooleanConfig(Supplier<Consumer<BooleanDirective>> receiver) {
this.receiver = receiver;
}
public SConfigureBooleanPacket packet(BooleanDirective directive) {
return new SConfigureBooleanPacket(this, directive);
}
@OnlyIn(Dist.CLIENT)
private static void enabled(BooleanDirective state) {
LocalPlayer player = Minecraft.getInstance().player;
if (player == null || state == null) return;
if (state == BooleanDirective.DISPLAY) {
Component text = new TextComponent("Flywheel renderer is currently: ").append(boolToText(FlwConfig.get().client.enabled.get()));
player.displayClientMessage(text, false);
return;
}
boolean enabled = state.get();
boolean cannotUse = OptifineHandler.usingShaders() && enabled;
FlwConfig.get().client.enabled.set(enabled);
Component text = boolToText(FlwConfig.get().client.enabled.get()).append(new TextComponent(" Flywheel renderer").withStyle(ChatFormatting.WHITE));
Component error = new TextComponent("Flywheel renderer does not support Optifine Shaders").withStyle(ChatFormatting.RED);
player.displayClientMessage(cannotUse ? error : text, false);
Backend.reloadWorldRenderers();
}
@OnlyIn(Dist.CLIENT)
private static void normalOverlay(BooleanDirective state) {
LocalPlayer player = Minecraft.getInstance().player;
if (player == null || state == null) return;
if (state == BooleanDirective.DISPLAY) {
Component text = new TextComponent("Normal debug mode is currently: ").append(boolToText(FlwConfig.get().client.debugNormals.get()));
player.displayClientMessage(text, false);
return;
}
FlwConfig.get().client.debugNormals.set(state.get());
Component text = boolToText(FlwConfig.get().client.debugNormals.get()).append(new TextComponent(" normal debug mode").withStyle(ChatFormatting.WHITE));
player.displayClientMessage(text, false);
}
@OnlyIn(Dist.CLIENT)
private static void chunkCaching(BooleanDirective state) {
LocalPlayer player = Minecraft.getInstance().player;
if (player == null || state == null) return;
if (state == BooleanDirective.DISPLAY) {
Component text = new TextComponent("Chunk caching is currently: ").append(boolToText(FlwConfig.get().client.chunkCaching.get()));
player.displayClientMessage(text, false);
return;
}
FlwConfig.get().client.chunkCaching.set(state.get());
Component text = boolToText(FlwConfig.get().client.chunkCaching.get()).append(new TextComponent(" chunk caching").withStyle(ChatFormatting.WHITE));
player.displayClientMessage(text, false);
Backend.reloadWorldRenderers();
}
private static MutableComponent boolToText(boolean b) {
return b ? new TextComponent("enabled").withStyle(ChatFormatting.DARK_GREEN) : new TextComponent("disabled").withStyle(ChatFormatting.RED);
}
}

View file

@ -1,45 +0,0 @@
package com.jozufozu.flywheel.config;
import com.mojang.brigadier.Command;
import com.mojang.brigadier.builder.ArgumentBuilder;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
import net.minecraft.server.level.ServerPlayer;
import net.minecraftforge.fmllegacy.network.PacketDistributor;
public class BooleanConfigCommand {
private final String name;
private final BooleanConfig value;
public BooleanConfigCommand(String name, BooleanConfig value) {
this.name = name;
this.value = value;
}
public ArgumentBuilder<CommandSourceStack, ?> register() {
return Commands.literal(name)
.executes(context -> {
ServerPlayer player = context.getSource()
.getPlayerOrException();
FlwPackets.channel.send(PacketDistributor.PLAYER.with(() -> player), new SConfigureBooleanPacket(value, BooleanDirective.DISPLAY));
return Command.SINGLE_SUCCESS;
})
.then(Commands.literal("on")
.executes(context -> {
ServerPlayer player = context.getSource()
.getPlayerOrException();
FlwPackets.channel.send(PacketDistributor.PLAYER.with(() -> player), new SConfigureBooleanPacket(value, BooleanDirective.TRUE));
return Command.SINGLE_SUCCESS;
}))
.then(Commands.literal("off")
.executes(context -> {
ServerPlayer player = context.getSource()
.getPlayerOrException();
FlwPackets.channel.send(PacketDistributor.PLAYER.with(() -> player), new SConfigureBooleanPacket(value, BooleanDirective.FALSE));
return Command.SINGLE_SUCCESS;
}));
}
}

View file

@ -1,22 +0,0 @@
package com.jozufozu.flywheel.config;
public enum BooleanDirective {
TRUE(true),
FALSE(false),
/**
* Don't change anything, just display what the value currently is.
*/
DISPLAY(true),
;
private final boolean b;
BooleanDirective(boolean b) {
this.b = b;
}
public boolean get() {
if (this == DISPLAY) throw new IllegalStateException("Cannot get value from DISPLAY directive");
return b;
}
}

View file

@ -0,0 +1,107 @@
package com.jozufozu.flywheel.config;
import java.util.function.BiConsumer;
import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.OptifineHandler;
import com.mojang.brigadier.Command;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import net.fabricmc.fabric.api.client.command.v1.ClientCommandManager;
import net.fabricmc.fabric.api.client.command.v1.FabricClientCommandSource;
import net.minecraft.ChatFormatting;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.MutableComponent;
import net.minecraft.network.chat.TextComponent;
public final class ConfigCommands {
public static void init(FlwConfig config) {
ConfigCommandBuilder commandBuilder = new ConfigCommandBuilder("flywheel");
commandBuilder.addOption(config.enabled, (builder, option) -> booleanOptionCommand(builder, config, option,
(source, value) -> {
Component text = new TextComponent("Flywheel renderer is currently: ").append(boolToText(value));
source.sendFeedback(text);
},
(source, value) -> {
Component text;
if (OptifineHandler.usingShaders() && value) {
text = new TextComponent("Flywheel renderer does not support Optifine Shaders").withStyle(ChatFormatting.RED);
} else {
text = boolToText(value).append(new TextComponent(" Flywheel renderer").withStyle(ChatFormatting.WHITE));
}
source.sendFeedback(text);
Backend.reloadWorldRenderers();
}
));
commandBuilder.addOption(config.debugNormals, (builder, option) -> booleanOptionCommand(builder, config, option,
(source, value) -> {
Component text = new TextComponent("Normal debug mode is currently: ").append(boolToText(value));
source.sendFeedback(text);
},
(source, value) -> {
Component text = boolToText(value).append(new TextComponent(" normal debug mode").withStyle(ChatFormatting.WHITE));
source.sendFeedback(text);
}
));
commandBuilder.addOption(config.chunkCaching, (builder, option) -> booleanOptionCommand(builder, config, option,
(source, value) -> {
Component text = new TextComponent("Chunk caching is currently: ").append(boolToText(value));
source.sendFeedback(text);
},
(source, value) -> {
Component text = boolToText(value).append(new TextComponent(" chunk caching").withStyle(ChatFormatting.WHITE));
source.sendFeedback(text);
Backend.reloadWorldRenderers();
}
));
commandBuilder.build();
}
public static void booleanOptionCommand(LiteralArgumentBuilder<FabricClientCommandSource> builder, FlwConfig config, Option<Boolean> option, BiConsumer<FabricClientCommandSource, Boolean> displayAction, BiConsumer<FabricClientCommandSource, Boolean> setAction) {
builder
.executes(context -> {
displayAction.accept(context.getSource(), option.get());
return Command.SINGLE_SUCCESS;
})
.then(ClientCommandManager.literal("on")
.executes(context -> {
option.set(true);
setAction.accept(context.getSource(), option.get());
config.save();
return Command.SINGLE_SUCCESS;
}))
.then(ClientCommandManager.literal("off")
.executes(context -> {
option.set(false);
setAction.accept(context.getSource(), option.get());
config.save();
return Command.SINGLE_SUCCESS;
}));
}
public static MutableComponent boolToText(boolean b) {
return b ? new TextComponent("enabled").withStyle(ChatFormatting.DARK_GREEN) : new TextComponent("disabled").withStyle(ChatFormatting.RED);
}
public static class ConfigCommandBuilder {
protected LiteralArgumentBuilder<FabricClientCommandSource> command;
public ConfigCommandBuilder(String baseLiteral) {
command = ClientCommandManager.literal(baseLiteral);
}
public <T extends Option<?>> void addOption(T option, BiConsumer<LiteralArgumentBuilder<FabricClientCommandSource>, T> consumer) {
LiteralArgumentBuilder<FabricClientCommandSource> builder = ClientCommandManager.literal(option.getKey());
consumer.accept(builder, option);
command.then(builder);
}
public void build() {
ClientCommandManager.DISPATCHER.register(command);
}
}
}

View file

@ -1,23 +0,0 @@
package com.jozufozu.flywheel.config;
import com.mojang.brigadier.CommandDispatcher;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fmlserverevents.FMLServerStartingEvent;
public class FlwCommands {
@SubscribeEvent
public static void onServerStarting(FMLServerStartingEvent event) {
CommandDispatcher<CommandSourceStack> dispatcher = event.getServer()
.getCommands()
.getDispatcher();
dispatcher.register(Commands.literal("flywheel")
.then(new BooleanConfigCommand("backend", BooleanConfig.ENGINE).register())
.then(new BooleanConfigCommand("debugNormals", BooleanConfig.NORMAL_OVERLAY).register())
.then(new BooleanConfigCommand("chunkCaching", BooleanConfig.CHUNK_CACHING).register())
);
}
}

View file

@ -1,61 +1,130 @@
package com.jozufozu.flywheel.config;
import org.apache.commons.lang3.tuple.Pair;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.Collections;
import java.util.Map;
import net.minecraftforge.common.ForgeConfigSpec;
import net.minecraftforge.common.ForgeConfigSpec.BooleanValue;
import net.minecraftforge.fml.ModLoadingContext;
import net.minecraftforge.fml.config.ModConfig;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jetbrains.annotations.Nullable;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonParser;
import com.jozufozu.flywheel.config.Option.BooleanOption;
import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
import it.unimi.dsi.fastutil.objects.ObjectBidirectionalIterator;
import net.fabricmc.loader.api.FabricLoader;
public class FlwConfig {
protected static final Logger LOGGER = LogManager.getLogger("Flywheel Config");
protected static final JsonParser PARSER = new JsonParser();
protected static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
private static final FlwConfig INSTANCE = new FlwConfig();
private static final FlwConfig INSTANCE = new FlwConfig(FabricLoader.getInstance().getConfigDir().resolve("flywheel.json").toFile());
public final ClientConfig client;
protected final File file;
protected final Object2ObjectLinkedOpenHashMap<String, Option<?>> optionMap = new Object2ObjectLinkedOpenHashMap<>();
protected final Map<String, Option<?>> optionMapView = Collections.unmodifiableMap(optionMap);
public FlwConfig() {
Pair<ClientConfig, ForgeConfigSpec> client = new ForgeConfigSpec.Builder().configure(ClientConfig::new);
/** Enable or disable the entire engine */
public final BooleanOption enabled = addOption(new BooleanOption("enabled", true));
/** Enable or disable a debug overlay that colors pixels by their normal */
public final BooleanOption debugNormals = addOption(new BooleanOption("debugNormals", false));
/** Cache chunk lookups to improve performance. */
public final BooleanOption chunkCaching = addOption(new BooleanOption("chunkCaching", true));
this.client = client.getLeft();
ModLoadingContext.get()
.registerConfig(ModConfig.Type.CLIENT, client.getRight());
public FlwConfig(File file) {
this.file = file;
}
public static FlwConfig get() {
return INSTANCE;
}
public static void init() {
INSTANCE.load();
ConfigCommands.init(INSTANCE);
}
public boolean enabled() {
return client.enabled.get();
return enabled.get();
}
public boolean debugNormals() {
return client.debugNormals.get();
return debugNormals.get();
}
public boolean chunkCaching() {
return client.chunkCaching.get();
return chunkCaching.get();
}
public static void init() {
public void load() {
if (file.exists()) {
try (FileReader reader = new FileReader(file)) {
fromJson(PARSER.parse(reader));
} catch (Exception e) {
LOGGER.error("Could not load config from file '" + file.getAbsolutePath() + "'", e);
}
}
save();
}
public static class ClientConfig {
public final BooleanValue enabled;
public final BooleanValue debugNormals;
public final BooleanValue chunkCaching;
public ClientConfig(ForgeConfigSpec.Builder builder) {
enabled = builder.comment("Enable or disable the entire engine")
.define("enabled", true);
debugNormals = builder.comment("Enable or disable a debug overlay that colors pixels by their normal")
.define("debugNormals", false);
chunkCaching = builder.comment("Cache chunk lookups to improve performance.")
.define("chunkCaching", true);
public void save() {
try (FileWriter writer = new FileWriter(file)) {
GSON.toJson(toJson(), writer);
} catch (Exception e) {
LOGGER.error("Could not save config to file '" + file.getAbsolutePath() + "'", e);
}
}
protected void fromJson(JsonElement json) throws JsonParseException {
if (json.isJsonObject()) {
JsonObject object = json.getAsJsonObject();
ObjectBidirectionalIterator<Object2ObjectMap.Entry<String, Option<?>>> iterator = optionMap.object2ObjectEntrySet().fastIterator();
while (iterator.hasNext()) {
Object2ObjectMap.Entry<String, Option<?>> entry = iterator.next();
JsonElement element = object.get(entry.getKey());
if (element != null) {
entry.getValue().fromJson(element);
}
}
} else {
throw new JsonParseException("Json must be an object");
}
}
protected JsonElement toJson() {
JsonObject object = new JsonObject();
ObjectBidirectionalIterator<Object2ObjectMap.Entry<String, Option<?>>> iterator = optionMap.object2ObjectEntrySet().fastIterator();
while (iterator.hasNext()) {
Object2ObjectMap.Entry<String, Option<?>> entry = iterator.next();
object.add(entry.getKey(), entry.getValue().toJson());
}
return object;
}
protected <T extends Option<?>> T addOption(T option) {
Option<?> old = optionMap.put(option.getKey(), option);
if (old != null) {
LOGGER.warn("Option with key '" + old.getKey() + "' was overridden");
}
return option;
}
@Nullable
public Option<?> getOption(String key) {
return optionMap.get(key);
}
public Map<String, Option<?>> getOptionMapView() {
return optionMapView;
}
}

View file

@ -1,28 +0,0 @@
package com.jozufozu.flywheel.config;
import com.jozufozu.flywheel.Flywheel;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.fmllegacy.network.NetworkDirection;
import net.minecraftforge.fmllegacy.network.NetworkRegistry;
import net.minecraftforge.fmllegacy.network.simple.SimpleChannel;
public class FlwPackets {
public static final ResourceLocation CHANNEL_NAME = new ResourceLocation(Flywheel.ID, "network");
public static final String NETWORK_VERSION = new ResourceLocation(Flywheel.ID, "1").toString();
public static SimpleChannel channel;
public static void registerPackets() {
channel = NetworkRegistry.ChannelBuilder.named(CHANNEL_NAME)
.serverAcceptedVersions(NETWORK_VERSION::equals)
.clientAcceptedVersions(NETWORK_VERSION::equals)
.networkProtocolVersion(() -> NETWORK_VERSION)
.simpleChannel();
channel.messageBuilder(SConfigureBooleanPacket.class, 0, NetworkDirection.PLAY_TO_CLIENT)
.decoder(SConfigureBooleanPacket::new)
.encoder(SConfigureBooleanPacket::encode)
.consumer(SConfigureBooleanPacket::execute)
.add();
}
}

View file

@ -0,0 +1,58 @@
package com.jozufozu.flywheel.config;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
public interface Option<T> {
String getKey();
T get();
void set(T value);
JsonElement toJson();
void fromJson(JsonElement json) throws JsonParseException;
public abstract class BaseOption<T> implements Option<T> {
protected String key;
protected T value;
public BaseOption(String key, T defaultValue) {
this.key = key;
value = defaultValue;
}
@Override
public String getKey() {
return key;
}
@Override
public T get() {
return value;
}
@Override
public void set(T value) {
this.value = value;
}
}
public class BooleanOption extends BaseOption<Boolean> {
public BooleanOption(String id, Boolean defaultValue) {
super(id, defaultValue);
}
@Override
public JsonElement toJson() {
return new JsonPrimitive(get());
}
@Override
public void fromJson(JsonElement json) throws JsonParseException {
set(json.getAsBoolean());
}
}
}

View file

@ -1,39 +0,0 @@
package com.jozufozu.flywheel.config;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraftforge.fmllegacy.network.NetworkEvent;
import java.util.function.Supplier;
/**
* Thanks, @zelophed
*/
public class SConfigureBooleanPacket {
private final BooleanConfig target;
private final BooleanDirective directive;
public SConfigureBooleanPacket(BooleanConfig target, BooleanDirective directive) {
this.target = target;
this.directive = directive;
}
public SConfigureBooleanPacket(FriendlyByteBuf buffer) {
target = BooleanConfig.values()[buffer.readByte()];
directive = BooleanDirective.values()[buffer.readByte()];
}
public void encode(FriendlyByteBuf buffer) {
buffer.writeByte(target.ordinal());
buffer.writeByte(directive.ordinal());
}
public void execute(Supplier<NetworkEvent.Context> ctx) {
target.receiver.get()
.accept(directive);
ctx.get()
.setPacketHandled(true);
}
}

View file

@ -3,9 +3,9 @@ package com.jozufozu.flywheel.core;
import java.util.ArrayList;
import java.util.List;
import net.minecraft.world.inventory.InventoryMenu;
import net.fabricmc.fabric.api.event.client.ClientSpriteRegistryCallback.Registry;
import net.minecraft.client.renderer.texture.TextureAtlas;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.client.event.TextureStitchEvent;
/**
* This is primarily for hacking entity textures into the block atlas.
@ -27,14 +27,10 @@ public class AtlasStitcher {
return sprite;
}
public void onTextureStitch(TextureStitchEvent.Pre event) {
if (!event.getMap()
.location()
.equals(InventoryMenu.BLOCK_ATLAS)) return;
public void onTextureStitch(TextureAtlas atlasTexture, Registry registry) {
sprites.forEach(StitchedSprite::reset);
sprites.stream()
.map(StitchedSprite::getLoc)
.forEach(event::addSprite);
.forEach(registry::register);
}
}

View file

@ -15,10 +15,7 @@ import com.jozufozu.flywheel.event.GatherContextEvent;
import com.jozufozu.flywheel.util.ResourceUtil;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@OnlyIn(Dist.CLIENT)
public class Contexts {
public static WorldContext<WorldProgram> WORLD;

View file

@ -9,10 +9,7 @@ import com.jozufozu.flywheel.core.materials.oriented.OrientedType;
import com.jozufozu.flywheel.event.GatherContextEvent;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@OnlyIn(Dist.CLIENT)
public class Materials {
public static final StructType<OrientedData> ORIENTED_TYPE = new OrientedType();
public static final StructType<ModelData> TRANSFORMED_TYPE = new ModelType();

View file

@ -2,13 +2,19 @@ package com.jozufozu.flywheel.core;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import com.jozufozu.flywheel.Flywheel;
import net.fabricmc.fabric.api.client.model.BakedModelManagerHelper;
import net.fabricmc.fabric.api.resource.IdentifiableResourceReloadListener;
import net.fabricmc.fabric.api.resource.ResourceReloadListenerKeys;
import net.minecraft.client.Minecraft;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.client.resources.model.ModelManager;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.client.event.ModelBakeEvent;
import net.minecraftforge.client.event.ModelRegistryEvent;
import net.minecraftforge.client.model.ModelLoader;
import net.minecraft.server.packs.resources.ResourceManager;
import net.minecraft.server.packs.resources.ResourceManagerReloadListener;
/**
* A helper class for loading and accessing json models.
@ -23,7 +29,6 @@ import net.minecraftforge.client.model.ModelLoader;
*/
public class PartialModel {
private static boolean tooLate = false;
private static final List<PartialModel> all = new ArrayList<>();
protected final ResourceLocation modelLocation;
@ -31,27 +36,44 @@ public class PartialModel {
public PartialModel(ResourceLocation modelLocation) {
if (tooLate) throw new RuntimeException("PartialModel '" + modelLocation + "' loaded after ModelRegistryEvent");
this.modelLocation = modelLocation;
all.add(this);
}
public static void onModelRegistry(ModelRegistryEvent event) {
public static void onModelRegistry(ResourceManager manager, Consumer<ResourceLocation> out) {
for (PartialModel partial : all)
ModelLoader.addSpecialModel(partial.modelLocation);
tooLate = true;
out.accept(partial.modelLocation);
}
public static void onModelBake(ModelBakeEvent event) {
Map<ResourceLocation, BakedModel> modelRegistry = event.getModelRegistry();
public static void onModelBake(ModelManager manager) {
for (PartialModel partial : all)
partial.bakedModel = modelRegistry.get(partial.modelLocation);
partial.bakedModel = BakedModelManagerHelper.getModel(manager, partial.modelLocation);
}
public BakedModel get() {
return bakedModel;
}
public static class ResourceReloadListener implements ResourceManagerReloadListener, IdentifiableResourceReloadListener {
public static final ResourceReloadListener INSTANCE = new ResourceReloadListener();
public static final ResourceLocation ID = Flywheel.rl("partial_models");
public static final List<ResourceLocation> DEPENDENCIES = List.of(ResourceReloadListenerKeys.MODELS);
@Override
public void onResourceManagerReload(ResourceManager resourceManager) {
onModelBake(Minecraft.getInstance().getModelManager());
}
@Override
public ResourceLocation getFabricId() {
return ID;
}
@Override
public List<ResourceLocation> getFabricDependencies() {
return DEPENDENCIES;
}
}
}

View file

@ -19,15 +19,9 @@ import com.jozufozu.flywheel.backend.gl.buffer.MappedGlBuffer;
import com.jozufozu.flywheel.backend.model.ElementBuffer;
import com.jozufozu.flywheel.event.ReloadRenderersEvent;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.eventbus.api.EventPriority;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
/**
* A class to manage EBOs that index quads as triangles.
*/
@Mod.EventBusSubscriber(Dist.CLIENT)
public class QuadConverter {
public static final int STARTING_CAPACITY = 42; // 255 / 6 = 42
@ -170,7 +164,6 @@ public class QuadConverter {
}
// make sure this gets reset first so it has a chance to repopulate
@SubscribeEvent(priority = EventPriority.HIGHEST)
public static void onRendererReload(ReloadRenderersEvent event) {
if (INSTANCE != null) INSTANCE.delete();
}

View file

@ -17,31 +17,25 @@ import com.jozufozu.flywheel.event.ReloadRenderersEvent;
import com.jozufozu.flywheel.mixin.LevelRendererAccessor;
import com.jozufozu.flywheel.util.Lazy;
import com.jozufozu.flywheel.util.Pair;
import com.mojang.math.Matrix4f;
import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import net.minecraft.client.Minecraft;
import net.minecraft.client.Camera;
import net.minecraft.server.level.BlockDestructionProgress;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.resources.model.ModelBakery;
import net.minecraft.client.renderer.texture.AbstractTexture;
import net.minecraft.client.renderer.texture.TextureManager;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.client.resources.model.ModelBakery;
import net.minecraft.core.BlockPos;
import com.mojang.math.Matrix4f;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraft.server.level.BlockDestructionProgress;
import net.minecraft.world.level.block.entity.BlockEntity;
/**
* Responsible for rendering the block breaking overlay for instanced tiles.
*/
@OnlyIn(Dist.CLIENT)
@Mod.EventBusSubscriber(Dist.CLIENT)
public class CrumblingRenderer {
private static final Lazy<State> STATE;
@ -127,7 +121,6 @@ public class CrumblingRenderer {
return breakingEntities;
}
@SubscribeEvent
public static void onReloadRenderers(ReloadRenderersEvent event) {
ClientLevel world = event.getWorld();
if (Backend.getInstance()

View file

@ -14,15 +14,13 @@ import org.lwjgl.system.MemoryStack;
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer;
import com.jozufozu.flywheel.core.Formats;
import com.jozufozu.flywheel.util.VirtualEmptyModelData;
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import com.mojang.math.Vector3f;
import net.minecraft.client.Minecraft;
import net.minecraft.client.color.item.ItemColors;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.resources.model.BakedModel;
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import net.minecraft.core.Direction;
import com.mojang.math.Vector3f;
import net.minecraft.core.Vec3i;
public class BakedModelModel implements IModel {
@ -48,7 +46,8 @@ public class BakedModelModel implements IModel {
for (Direction dir : dirs) {
random.setSeed(42);
List<BakedQuad> quads = model.getQuads(null, dir, random, VirtualEmptyModelData.INSTANCE);
// TODO
List<BakedQuad> quads = model.getQuads(null, dir, random/*, VirtualEmptyModelData.INSTANCE*/);
numQuads += quads.size();
}
@ -61,13 +60,14 @@ public class BakedModelModel implements IModel {
Minecraft mc = Minecraft.getInstance();
ItemColors itemColors = mc.getItemColors();
// ItemColors itemColors = mc.getItemColors();
Random random = new Random();
for (Direction dir : dirs) {
random.setSeed(42);
List<BakedQuad> quads = model.getQuads(null, dir, random, VirtualEmptyModelData.INSTANCE);
// TODO
List<BakedQuad> quads = model.getQuads(null, dir, random/*, VirtualEmptyModelData.INSTANCE*/);
for (BakedQuad bakedQuad : quads) {
// int i = -1;

View file

@ -2,25 +2,22 @@ package com.jozufozu.flywheel.core.model;
import java.util.Arrays;
import org.lwjgl.opengl.GL11;
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer;
import com.jozufozu.flywheel.core.Formats;
import com.jozufozu.flywheel.util.BufferBuilderReader;
import com.jozufozu.flywheel.util.VirtualEmptyModelData;
import com.mojang.blaze3d.vertex.BufferBuilder;
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.block.ModelBlockRenderer;
import net.minecraft.client.renderer.block.BlockRenderDispatcher;
import com.mojang.blaze3d.vertex.BufferBuilder;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.client.renderer.block.ModelBlockRenderer;
import net.minecraft.client.renderer.texture.OverlayTexture;
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import net.minecraft.core.Direction;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.level.block.state.BlockState;
/**
* A model of a single block.
@ -82,7 +79,8 @@ public class BlockModel implements IModel {
// .collect(Collectors.toList());
builder.begin(com.mojang.blaze3d.vertex.VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
blockRenderer.tesselateBlock(mc.level, model, referenceState, BlockPos.ZERO.above(255), ms, builder, true, mc.level.random, 42, OverlayTexture.NO_OVERLAY, VirtualEmptyModelData.INSTANCE);
// TODO
blockRenderer.tesselateBlock(mc.level, model, referenceState, BlockPos.ZERO.above(255), ms, builder, true, mc.level.random, 42, OverlayTexture.NO_OVERLAY/*, VirtualEmptyModelData.INSTANCE*/);
builder.end();
return builder;
}

View file

@ -1,48 +1,47 @@
package com.jozufozu.flywheel.core.model;
import static com.mojang.blaze3d.vertex.VertexFormat.Mode.QUADS;
import static org.lwjgl.opengl.GL11.GL_QUADS;
import java.util.Collection;
import java.util.Random;
import com.jozufozu.flywheel.util.Lazy;
import com.mojang.blaze3d.vertex.BufferBuilder;
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.world.level.block.RenderShape;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.block.ModelBlockRenderer;
import net.minecraft.client.renderer.block.BlockModelShaper;
import com.mojang.blaze3d.vertex.BufferBuilder;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.ItemBlockRenderTypes;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.block.BlockModelShaper;
import net.minecraft.client.renderer.block.ModelBlockRenderer;
import net.minecraft.client.renderer.texture.OverlayTexture;
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.BlockAndTintGetter;
import net.minecraft.world.level.block.RenderShape;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate;
import net.minecraftforge.client.ForgeHooksClient;
import net.minecraftforge.client.model.data.EmptyModelData;
public class ModelUtil {
private static final Lazy<ModelBlockRenderer> MODEL_RENDERER = Lazy.of(() -> new ModelBlockRenderer(Minecraft.getInstance().getBlockColors()));
private static final Lazy<BlockModelShaper> BLOCK_MODELS = Lazy.of(() -> Minecraft.getInstance().getModelManager().getBlockModelShaper());
// TODO
public static BufferBuilder getBufferBuilderFromTemplate(BlockAndTintGetter renderWorld, RenderType layer, Collection<StructureTemplate.StructureBlockInfo> blocks) {
PoseStack ms = new PoseStack();
Random random = new Random();
BufferBuilder builder = new BufferBuilder(DefaultVertexFormat.BLOCK.getIntegerSize());
builder.begin(QUADS, DefaultVertexFormat.BLOCK);
ForgeHooksClient.setRenderLayer(layer);
// ForgeHooksClient.setRenderLayer(layer);
ModelBlockRenderer.enableCaching();
for (StructureTemplate.StructureBlockInfo info : blocks) {
BlockState state = info.state;
if (state.getRenderShape() != RenderShape.MODEL)
continue;
if (!ItemBlockRenderTypes.canRenderInLayer(state, layer))
// if (!ItemBlockRenderTypes.canRenderInLayer(state, layer))
if (ItemBlockRenderTypes.getChunkRenderType(state) != layer)
continue;
BlockPos pos = info.pos;
@ -50,11 +49,11 @@ public class ModelUtil {
ms.pushPose();
ms.translate(pos.getX(), pos.getY(), pos.getZ());
MODEL_RENDERER.get().tesselateBlock(renderWorld, BLOCK_MODELS.get().getBlockModel(state), state, pos, ms, builder, true,
random, 42, OverlayTexture.NO_OVERLAY, EmptyModelData.INSTANCE);
random, 42, OverlayTexture.NO_OVERLAY/*, EmptyModelData.INSTANCE*/);
ms.popPose();
}
ModelBlockRenderer.clearCache();
ForgeHooksClient.setRenderLayer(null);
// ForgeHooksClient.setRenderLayer(null);
builder.end();
return builder;

View file

@ -1,12 +1,13 @@
package com.jozufozu.flywheel.event;
import net.minecraft.client.Camera;
import net.minecraft.client.renderer.culling.Frustum;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.eventbus.api.Event;
import com.jozufozu.flywheel.fabric.event.EventContext;
public class BeginFrameEvent extends Event {
import net.minecraft.client.Camera;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.renderer.culling.Frustum;
import net.minecraft.world.phys.Vec3;
public class BeginFrameEvent extends EventContext {
private final ClientLevel world;
private final Camera info;
private final Frustum clippingHelper;

View file

@ -2,24 +2,18 @@ package com.jozufozu.flywheel.event;
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.event.entity.EntityJoinWorldEvent;
import net.minecraftforge.event.entity.EntityLeaveWorldEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.world.entity.Entity;
@Mod.EventBusSubscriber(Dist.CLIENT)
public class EntityWorldHandler {
@SubscribeEvent
public static void onEntityJoinWorld(EntityJoinWorldEvent event) {
if (event.getWorld().isClientSide) InstancedRenderDispatcher.getEntities(event.getWorld())
.queueAdd(event.getEntity());
public static void onEntityJoinWorld(Entity entity, ClientLevel level) {
InstancedRenderDispatcher.getEntities(level)
.queueAdd(entity);
}
@SubscribeEvent
public static void onEntityLeaveWorld(EntityLeaveWorldEvent event) {
if (event.getWorld().isClientSide) InstancedRenderDispatcher.getEntities(event.getWorld())
.remove(event.getEntity());
public static void onEntityLeaveWorld(Entity entity, ClientLevel level) {
InstancedRenderDispatcher.getEntities(level)
.remove(entity);
}
}

View file

@ -1,6 +1,6 @@
package com.jozufozu.flywheel.event;
import java.util.ArrayList;
import java.util.List;
import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
@ -9,55 +9,35 @@ import com.jozufozu.flywheel.util.ChunkIter;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.world.level.LevelAccessor;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.RenderGameOverlayEvent;
import net.minecraftforge.event.TickEvent;
import net.minecraftforge.event.world.WorldEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
@Mod.EventBusSubscriber(Dist.CLIENT)
public class ForgeEvents {
@SubscribeEvent
public static void addToDebugScreen(RenderGameOverlayEvent.Text event) {
public static void addToDebugScreen(List<String> right) {
if (Minecraft.getInstance().options.renderDebug) {
ArrayList<String> right = event.getRight();
String text = "Flywheel: " + Backend.getInstance()
.getBackendDescriptor();
if (right.size() < 10) {
right.add("");
right.add(text);
} else {
right.add(9, "");
right.add(10, text);
}
String text = "Flywheel: " + Backend.getInstance()
.getBackendDescriptor();
if (right.size() < 10) {
right.add("");
right.add(text);
} else {
right.add(9, "");
right.add(10, text);
}
}
@SubscribeEvent
public static void onLoadWorld(WorldEvent.Load event) {
LevelAccessor world = event.getWorld();
public static void onLoadWorld(ClientLevel world) {
if (Backend.isFlywheelWorld(world)) {
InstancedRenderDispatcher.loadAllInWorld((ClientLevel) world);
}
}
@SubscribeEvent
public static void unloadWorld(WorldEvent.Unload event) {
LevelAccessor world = event.getWorld();
public static void unloadWorld(ClientLevel world) {
ChunkIter._unload(world);
}
@SubscribeEvent
public static void tickLight(TickEvent.ClientTickEvent e) {
if (e.phase == TickEvent.Phase.END && Backend.isGameActive())
LightUpdater.get(Minecraft.getInstance().level).tick();
public static void tickLight(Minecraft mc) {
if (Backend.isGameActive())
LightUpdater.get(mc.level).tick();
}
}

View file

@ -1,11 +1,9 @@
package com.jozufozu.flywheel.event;
import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.fabric.event.EventContext;
import net.minecraftforge.eventbus.api.Event;
import net.minecraftforge.fml.event.IModBusEvent;
public class GatherContextEvent extends Event implements IModBusEvent {
public class GatherContextEvent extends EventContext {
private final Backend backend;
private final boolean firstLoad;

View file

@ -2,10 +2,11 @@ package com.jozufozu.flywheel.event;
import javax.annotation.Nullable;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraftforge.eventbus.api.Event;
import com.jozufozu.flywheel.fabric.event.EventContext;
public class ReloadRenderersEvent extends Event {
import net.minecraft.client.multiplayer.ClientLevel;
public class ReloadRenderersEvent extends EventContext {
private final ClientLevel world;
public ReloadRenderersEvent(ClientLevel world) {

View file

@ -3,16 +3,17 @@ package com.jozufozu.flywheel.event;
import javax.annotation.Nullable;
import com.jozufozu.flywheel.backend.state.RenderLayer;
import com.jozufozu.flywheel.fabric.event.EventContext;
import com.jozufozu.flywheel.fabric.helper.Matrix4fHelper;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.RenderBuffers;
import net.minecraft.client.multiplayer.ClientLevel;
import com.mojang.math.Matrix4f;
import net.minecraftforge.eventbus.api.Event;
public class RenderLayerEvent extends Event {
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.renderer.RenderBuffers;
import net.minecraft.client.renderer.RenderType;
public class RenderLayerEvent extends EventContext {
private final ClientLevel world;
public final RenderType type;
public final PoseStack stack;
@ -31,7 +32,7 @@ public class RenderLayerEvent extends Event {
viewProjection = stack.last()
.pose()
.copy();
viewProjection.multiplyBackward(RenderSystem.getProjectionMatrix());
Matrix4fHelper.multiplyBackward(viewProjection, RenderSystem.getProjectionMatrix());
this.buffers = buffers;
this.camX = camX;

View file

@ -0,0 +1,24 @@
package com.jozufozu.flywheel.fabric.event;
public class EventContext {
protected boolean isCanceled = false;
public boolean isCancelable() {
return false;
}
public boolean isCanceled() {
return isCanceled;
}
public void setCanceled(boolean canceled) {
if (!isCancelable()) {
throw new UnsupportedOperationException("Cannot cancel event of class " + getClass().getName());
}
isCanceled = canceled;
}
public interface Listener<C extends EventContext> {
void handleEvent(C context);
}
}

View file

@ -0,0 +1,27 @@
package com.jozufozu.flywheel.fabric.event;
import com.jozufozu.flywheel.event.BeginFrameEvent;
import com.jozufozu.flywheel.event.GatherContextEvent;
import com.jozufozu.flywheel.event.ReloadRenderersEvent;
import com.jozufozu.flywheel.event.RenderLayerEvent;
import com.jozufozu.flywheel.fabric.event.EventContext.Listener;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
public final class FlywheelEvents {
public static final Event<Listener<BeginFrameEvent>> BEGIN_FRAME = createSimple();
public static final Event<Listener<GatherContextEvent>> GATHER_CONTEXT = createSimple();
public static final Event<Listener<ReloadRenderersEvent>> RELOAD_RENDERERS = createSimple();
public static final Event<Listener<RenderLayerEvent>> RENDER_LAYER = createSimple();
private static <C extends EventContext> Event<Listener<C>> createSimple() {
return EventFactory.createArrayBacked(Listener.class,
listeners -> context -> {
for (Listener<C> listener : listeners) {
listener.handleEvent(context);
}
}
);
}
}

View file

@ -0,0 +1,5 @@
package com.jozufozu.flywheel.fabric.extension;
public interface Matrix4fExtension {
void setTranslation(float x, float y, float z);
}

View file

@ -0,0 +1,11 @@
package com.jozufozu.flywheel.fabric.helper;
import com.jozufozu.flywheel.mixin.fabric.BufferBuilderAccessor;
import com.mojang.blaze3d.vertex.BufferBuilder;
import com.mojang.blaze3d.vertex.VertexFormat;
public final class BufferBuilderHelper {
public static VertexFormat getVertexFormat(BufferBuilder self) {
return ((BufferBuilderAccessor) self).getFormat();
}
}

View file

@ -0,0 +1,16 @@
package com.jozufozu.flywheel.fabric.helper;
import com.jozufozu.flywheel.fabric.extension.Matrix4fExtension;
import com.mojang.math.Matrix4f;
public final class Matrix4fHelper {
public static void multiplyBackward(Matrix4f self, Matrix4f other) {
Matrix4f copy = other.copy();
copy.multiply(self);
self.load(copy);
}
public static void setTranslation(Matrix4f self, float x, float y, float z) {
((Matrix4fExtension) (Object) self).setTranslation(x, y, z);
}
}

View file

@ -0,0 +1,10 @@
package com.jozufozu.flywheel.fabric.helper;
import com.jozufozu.flywheel.mixin.fabric.VertexFormatAccessor;
import com.mojang.blaze3d.vertex.VertexFormat;
public final class VertexFormatHelper {
public static int getOffset(VertexFormat self, int index) {
return ((VertexFormatAccessor) self).getOffsets().getInt(index);
}
}

View file

@ -12,10 +12,7 @@ import com.jozufozu.flywheel.backend.instancing.InstancedRenderRegistry;
import net.minecraft.client.renderer.chunk.ChunkRenderDispatcher;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@OnlyIn(Dist.CLIENT)
@Mixin(targets = "net.minecraft.client.renderer.chunk.ChunkRenderDispatcher$RenderChunk$RebuildTask")
public class ChunkRebuildHooksMixin {

View file

@ -13,10 +13,7 @@ import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.client.renderer.LightTexture;
import net.minecraft.client.renderer.LevelRenderer;
import com.mojang.math.Matrix4f;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@OnlyIn(Dist.CLIENT)
@Mixin(LevelRenderer.class)
public class FixFabulousDepthMixin {

View file

@ -12,10 +12,7 @@ import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@OnlyIn(Dist.CLIENT)
@Mixin(LevelChunk.class)
public class InstanceAddMixin {

View file

@ -13,8 +13,6 @@ import com.jozufozu.flywheel.util.ChunkIter;
import net.minecraft.client.multiplayer.ClientChunkCache;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
/**
* In order to iterate over all loaded chunks, we do something absolutely foul.
@ -24,7 +22,6 @@ import net.minecraftforge.api.distmarker.OnlyIn;
* access to the full array of loaded chunks.
* </p>
*/
@OnlyIn(Dist.CLIENT)
@Mixin(targets = "net.minecraft.client.multiplayer.ClientChunkCache$Storage")
public class LeakChunkStorageArrayMixin {

View file

@ -15,26 +15,24 @@ import com.jozufozu.flywheel.core.crumbling.CrumblingRenderer;
import com.jozufozu.flywheel.event.BeginFrameEvent;
import com.jozufozu.flywheel.event.ReloadRenderersEvent;
import com.jozufozu.flywheel.event.RenderLayerEvent;
import com.jozufozu.flywheel.fabric.event.FlywheelEvents;
import com.jozufozu.flywheel.fabric.helper.Matrix4fHelper;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.client.Camera;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.client.renderer.LightTexture;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.RenderBuffers;
import net.minecraft.client.renderer.LevelRenderer;
import net.minecraft.client.renderer.culling.Frustum;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.core.BlockPos;
import com.mojang.math.Matrix4f;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.common.MinecraftForge;
@OnlyIn(Dist.CLIENT)
import net.minecraft.client.Camera;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.client.renderer.LevelRenderer;
import net.minecraft.client.renderer.LightTexture;
import net.minecraft.client.renderer.RenderBuffers;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.culling.Frustum;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.Vec3;
@Mixin(LevelRenderer.class)
public class RenderHooksMixin {
@ -47,7 +45,7 @@ public class RenderHooksMixin {
@Inject(at = @At("HEAD"), method = "setupRender")
private void setupRender(Camera info, Frustum clippingHelper, boolean p_228437_3_, int frameCount, boolean isSpectator, CallbackInfo ci) {
MinecraftForge.EVENT_BUS.post(new BeginFrameEvent(level, info, clippingHelper));
FlywheelEvents.BEGIN_FRAME.invoker().handleEvent(new BeginFrameEvent(level, info, clippingHelper));
}
/**
@ -60,7 +58,7 @@ public class RenderHooksMixin {
RenderBuffers renderBuffers = this.renderBuffers;
MinecraftForge.EVENT_BUS.post(new RenderLayerEvent(level, type, stack, renderBuffers, camX, camY, camZ));
FlywheelEvents.RENDER_LAYER.invoker().handleEvent(new RenderLayerEvent(level, type, stack, renderBuffers, camX, camY, camZ));
if (!OptifineHandler.usingShaders()) GL20.glUseProgram(0);
@ -72,7 +70,7 @@ public class RenderHooksMixin {
Backend.getInstance()
.refresh();
MinecraftForge.EVENT_BUS.post(new ReloadRenderersEvent(level));
FlywheelEvents.RELOAD_RENDERERS.invoker().handleEvent(new ReloadRenderersEvent(level));
}
@ -85,7 +83,7 @@ public class RenderHooksMixin {
Matrix4f view = stack.last()
.pose();
Matrix4f viewProjection = view.copy();
viewProjection.multiplyBackward(RenderSystem.getProjectionMatrix());
Matrix4fHelper.multiplyBackward(viewProjection, RenderSystem.getProjectionMatrix());
Vec3 cameraPos = info.getPosition();
CrumblingRenderer.renderBreaking(level, viewProjection, cameraPos.x, cameraPos.y, cameraPos.z);

View file

@ -0,0 +1,13 @@
package com.jozufozu.flywheel.mixin.fabric;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import com.mojang.blaze3d.vertex.BufferBuilder;
import com.mojang.blaze3d.vertex.VertexFormat;
@Mixin(BufferBuilder.class)
public interface BufferBuilderAccessor {
@Accessor("format")
VertexFormat getFormat();
}

View file

@ -0,0 +1,18 @@
package com.jozufozu.flywheel.mixin.fabric;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import com.jozufozu.flywheel.event.ForgeEvents;
import net.minecraft.client.multiplayer.ClientLevel;
@Mixin(ClientLevel.class)
public class ClientLevelMixin {
@Inject(method = "<init>(Lnet/minecraft/client/multiplayer/ClientPacketListener;Lnet/minecraft/client/multiplayer/ClientLevel$ClientLevelData;Lnet/minecraft/resources/ResourceKey;Lnet/minecraft/world/level/dimension/DimensionType;ILjava/util/function/Supplier;Lnet/minecraft/client/renderer/LevelRenderer;ZJ)V", at = @At("TAIL"))
private void onTailInit(CallbackInfo ci) {
ForgeEvents.onLoadWorld((ClientLevel) (Object) this);
}
}

View file

@ -0,0 +1,21 @@
package com.jozufozu.flywheel.mixin.fabric;
import java.util.List;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import com.jozufozu.flywheel.event.ForgeEvents;
import net.minecraft.client.gui.GuiComponent;
import net.minecraft.client.gui.components.DebugScreenOverlay;
@Mixin(DebugScreenOverlay.class)
public abstract class DebugScreenOverlayMixin extends GuiComponent {
@Inject(method = "getSystemInformation", at = @At("RETURN"))
private void modifyRightText(CallbackInfoReturnable<List<String>> cir) {
ForgeEvents.addToDebugScreen(cir.getReturnValue());
}
}

View file

@ -0,0 +1,29 @@
package com.jozufozu.flywheel.mixin.fabric;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import com.jozufozu.flywheel.fabric.extension.Matrix4fExtension;
import com.mojang.math.Matrix4f;
@Mixin(Matrix4f.class)
public abstract class Matrix4fMixin implements Matrix4fExtension {
@Shadow protected float m00;
@Shadow protected float m03;
@Shadow protected float m11;
@Shadow protected float m13;
@Shadow protected float m22;
@Shadow protected float m23;
@Shadow protected float m33;
@Override
public void setTranslation(float x, float y, float z) {
m00 = 1.0f;
m11 = 1.0f;
m22 = 1.0f;
m33 = 1.0f;
m03 = x;
m13 = y;
m23 = z;
}
}

View file

@ -0,0 +1,31 @@
package com.jozufozu.flywheel.mixin.fabric;
import org.objectweb.asm.Opcodes;
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.event.ForgeEvents;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientLevel;
@Mixin(Minecraft.class)
public abstract class MinecraftMixin {
@Shadow
public ClientLevel level;
@Inject(method = "setLevel(Lnet/minecraft/client/multiplayer/ClientLevel;)V", at = @At("HEAD"))
private void onHeadSetLevel(CallbackInfo ci) {
if (level != null) {
ForgeEvents.unloadWorld(level);
}
}
@Inject(method = "clearLevel(Lnet/minecraft/client/gui/screens/Screen;)V", at = @At(value = "JUMP", opcode = Opcodes.IFNULL, ordinal = 2))
private void onClearLevel(CallbackInfo ci) {
ForgeEvents.unloadWorld(level);
}
}

View file

@ -0,0 +1,14 @@
package com.jozufozu.flywheel.mixin.fabric;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import com.mojang.blaze3d.vertex.VertexFormat;
import it.unimi.dsi.fastutil.ints.IntList;
@Mixin(VertexFormat.class)
public interface VertexFormatAccessor {
@Accessor("offsets")
IntList getOffsets();
}

View file

@ -12,10 +12,7 @@ import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.core.SectionPos;
import net.minecraft.world.level.LightLayer;
import net.minecraft.world.level.chunk.ChunkSource;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@OnlyIn(Dist.CLIENT)
@Mixin(ClientChunkCache.class)
public abstract class LightUpdateMixin extends ChunkSource {

View file

@ -8,10 +8,6 @@ import org.spongepowered.asm.mixin.Shadow;
import com.jozufozu.flywheel.util.Attribute;
import com.mojang.math.Matrix3f;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@OnlyIn(Dist.CLIENT)
@Mixin(Matrix3f.class)
public abstract class Matrix3fMixin implements Attribute {

View file

@ -8,10 +8,6 @@ import org.spongepowered.asm.mixin.Shadow;
import com.jozufozu.flywheel.util.Attribute;
import com.mojang.math.Matrix4f;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@OnlyIn(Dist.CLIENT)
@Mixin(Matrix4f.class)
public abstract class Matrix4fMixin implements Attribute {

View file

@ -1,12 +1,14 @@
package com.jozufozu.flywheel.util;
import net.minecraft.client.renderer.block.model.BakedQuad;
import com.jozufozu.flywheel.fabric.helper.VertexFormatHelper;
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import com.mojang.blaze3d.vertex.VertexFormat;
import com.mojang.blaze3d.vertex.VertexFormatElement;
import net.minecraft.world.phys.Vec2;
import com.mojang.math.Vector3f;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.world.phys.Vec2;
public class BakedQuadWrapper {
private final FormatCache formatCache = new FormatCache();
private BakedQuad quad;
@ -198,7 +200,7 @@ public class BakedQuadWrapper {
.size(); elementId++) {
VertexFormatElement element = FORMAT.getElements()
.get(elementId);
int intOffset = FORMAT.getOffset(elementId) / Integer.BYTES;
int intOffset = VertexFormatHelper.getOffset(FORMAT, elementId) / Integer.BYTES;
if (element.getUsage() == VertexFormatElement.Usage.POSITION) {
position = intOffset;
} else if (element.getUsage() == VertexFormatElement.Usage.COLOR) {

View file

@ -2,10 +2,10 @@ package com.jozufozu.flywheel.util;
import java.nio.ByteBuffer;
import com.mojang.datafixers.util.Pair;
import com.jozufozu.flywheel.fabric.helper.BufferBuilderHelper;
import com.mojang.blaze3d.vertex.BufferBuilder;
import com.mojang.blaze3d.vertex.VertexFormat;
import com.mojang.datafixers.util.Pair;
public class BufferBuilderReader {
@ -15,7 +15,7 @@ public class BufferBuilderReader {
private final int size;
public BufferBuilderReader(BufferBuilder builder) {
VertexFormat vertexFormat = builder.getVertexFormat();
VertexFormat vertexFormat = BufferBuilderHelper.getVertexFormat(builder);
Pair<BufferBuilder.DrawState, ByteBuffer> data = builder.popNextBuffer();
buffer = data.getSecond();

View file

@ -6,13 +6,10 @@ import java.util.function.Consumer;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
/**
* Helper class for iterating over all loaded chunks.
*/
@OnlyIn(Dist.CLIENT)
public class ChunkIter {
private static final WeakHashMap<BlockGetter, AtomicReferenceArray<LevelChunk>> storages = new WeakHashMap<>();

View file

@ -2,13 +2,13 @@ package com.jozufozu.flywheel.util;
import java.util.function.Supplier;
import com.jozufozu.flywheel.fabric.helper.Matrix4fHelper;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.core.Direction;
import com.mojang.math.Matrix3f;
import com.mojang.math.Matrix4f;
import com.mojang.math.Vector3f;
import net.minecraft.core.Direction;
public class RenderUtil {
private static final Matrix4f IDENTITY = new Matrix4f();
@ -50,9 +50,9 @@ public class RenderUtil {
// .rotateY(AngleHelper.horizontalAngle(facing))
// .rotateX(AngleHelper.verticalAngle(facing))
// .unCentre();
stack.last()
.pose()
.setTranslation(0.5f, 0.5f, 0.5f);
Matrix4fHelper.setTranslation(stack.last()
.pose(),
0.5f, 0.5f, 0.5f);
stack.mulPose(Vector3f.YP.rotationDegrees(AngleHelper.horizontalAngle(facing)));
stack.mulPose(Vector3f.XP.rotationDegrees(AngleHelper.verticalAngle(facing)));
stack.translate(-0.5f, -0.5f, -0.5f);

View file

@ -1,30 +0,0 @@
package com.jozufozu.flywheel.util;
import net.minecraftforge.client.model.data.IModelData;
import net.minecraftforge.client.model.data.ModelProperty;
/**
* This model data instance is passed whenever a model is rendered without
* available in-world context. IBakedModel#getModelData can react accordingly
* and avoid looking for model data itself
**/
public enum VirtualEmptyModelData implements IModelData {
INSTANCE;
@Override
public boolean hasProperty(ModelProperty<?> prop) {
return false;
}
@Override
public <T> T getData(ModelProperty<T> prop) {
return null;
}
@Override
public <T> T setData(ModelProperty<T> prop, T data) {
return null;
}
}

View file

@ -1,29 +0,0 @@
modLoader = "javafml"
loaderVersion = "[37,)"
issueTrackerURL = "https://github.com/Jozufozu/Flywheel/issues"
license = "MIT"
[[mods]]
modId = "flywheel"
version = "${file.jarVersion}"
displayName = "Flywheel"
logoFile="logo.png"
displayURL = "https://www.curseforge.com/minecraft/mc-mods/flywheel"
authors="Jozufozu"
description = '''
A modern engine for modded minecraft.
'''
[[dependencies.flywheel]]
modId = "forge"
mandatory = true
versionRange = "[37,)"
ordering = "NONE"
side = "BOTH"
[[dependencies.flywheel]]
modId = "minecraft"
mandatory = true
versionRange = "[1.17,1.18)"
ordering = "NONE"
side = "BOTH"

View file

@ -0,0 +1,37 @@
{
"schemaVersion": 1,
"id": "flywheel",
"version": "${version}",
"name": "Flywheel",
"description": "A modern engine for modded minecraft.",
"authors": [
"Jozufozu",
"Pepper_Bell"
],
"contact": {
"homepage": "https://www.curseforge.com/minecraft/mc-mods/flywheel",
"issues": "https://github.com/Jozufozu/Flywheel/issues",
"sources": "https://github.com/Jozufozu/Flywheel"
},
"license": "MIT",
"icon": "logo.png",
"environment": "client",
"entrypoints": {
"client": [
"com.jozufozu.flywheel.FlywheelClient"
]
},
"mixins": [
"flywheel.mixins.json"
],
"depends": {
"fabricloader": ">=0.11.3",
"fabric": "*",
"minecraft": "1.17.x",
"java": ">=16"
}
}

View file

@ -3,7 +3,6 @@
"minVersion": "0.8",
"package": "com.jozufozu.flywheel.mixin",
"compatibilityLevel": "JAVA_16",
"refmap": "flywheel.refmap.json",
"client": [
"CancelEntityRenderMixin",
"ChunkRebuildHooksMixin",
@ -19,6 +18,13 @@
"InstanceRemoveMixin",
"LeakChunkStorageArrayMixin",
"PausedPartialTickAccessor"
,
"fabric.BufferBuilderAccessor",
"fabric.ClientLevelMixin",
"fabric.DebugScreenOverlayMixin",
"fabric.Matrix4fMixin",
"fabric.MinecraftMixin",
"fabric.VertexFormatAccessor"
],
"mixins": [
"matrix.Matrix3fMixin",

View file

@ -1,7 +0,0 @@
{
"pack": {
"description": "flywheel resources",
"pack_format": 6,
"_comment": "A pack_format of 6 requires json lang files and some texture changes from 1.16.2. Note: we require v6 pack meta for all mods."
}
}