Pre-port tasks I

- Rename Client to FlywheelClient
 - Remove Shadow plugin
 - Remove generated source set
 - Remove unused properties in gradle.properties
 - Organize all imports
 - Thanks for the list pepper!
This commit is contained in:
Jozsef 2021-06-30 12:43:54 -07:00
parent f89673a79e
commit f615825846
85 changed files with 555 additions and 651 deletions

View file

@ -19,4 +19,4 @@ indent_style = tab
ij_continuation_indent_size = 8 ij_continuation_indent_size = 8
ij_java_class_count_to_use_import_on_demand = 99 ij_java_class_count_to_use_import_on_demand = 99
ij_java_names_count_to_use_import_on_demand = 99 ij_java_names_count_to_use_import_on_demand = 99
ij_java_imports_layout = $*,|,java.**,|,javax.**,|,org.**,|,com.**,|,* ij_java_imports_layout = $*, |, java.**, |, javax.**, |, org.**, |, com.**, |, *

View file

@ -2,99 +2,75 @@
Version 3, 29 June 2007 Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/> Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU
This version of the GNU Lesser General Public License incorporates General Public License, supplemented by the additional permissions listed below.
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions. 0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to
General Public License, and the "GNU GPL" refers to version 3 of the GNU version 3 of the GNU General Public License.
General Public License.
"The Library" refers to a covered work governed by this License, "The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined
other than an Application or a Combined Work as defined below. below.
An "Application" is any work that makes use of an interface provided An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on
by the Library, but which is not otherwise based on the Library. the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by
Defining a subclass of a class defined by the Library is deemed a mode the Library.
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of
Application with the Library. The particular version of the Library the Library with which the Combined Work was made is also called the "Linked Version".
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding
Corresponding Source for the Combined Work, excluding any source code any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not
for portions of the Combined Work that, considered in isolation, are on the Linked Version.
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application,
object code and/or source code for the Application, including any data including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the
and utility programs needed for reproducing the Combined Work from the System Libraries of the Combined Work.
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL. 1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL.
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions. 2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied
facility refers to a function or data to be supplied by an Application by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may
that uses the facility (other than as an argument passed when the convey a copy of the modified version:
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not
ensure that, in the event an Application does not supply the supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful,
function or data, the facility still operates, and performs or
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy.
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files. 3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from The object code form of an Application may incorporate material from a header file that is part of the Library. You may
a header file that is part of the Library. You may convey such object convey such object code under terms of your choice, provided that, if the incorporated material is not limited to
code under terms of your choice, provided that, if the incorporated numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following: (ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its
Library is used in it and that the Library and its use are use are covered by this License.
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license b) Accompany the object code with a copy of the GNU GPL and this license document.
document.
4. Combined Works. 4. Combined Works.
You may convey a Combined Work under terms of your choice that, You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification
taken together, effectively do not restrict modification of the of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications,
portions of the Library contained in the Combined Work and reverse if you also do each of the following:
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its
the Library is used in it and that the Library and its use are use are covered by this License.
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license b) Accompany the Combined Work with a copy of the GNU GPL and this license document.
document.
c) For a Combined Work that displays copyright notices during c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library
execution, include the copyright notice for the Library among among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document.
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following: d) Do one of the following:
@ -113,53 +89,38 @@ d) Do one of the following:
of the Library that is interface-compatible with the Linked of the Library that is interface-compatible with the Linked
Version. Version.
e) Provide Installation Information, but only if you would otherwise e) Provide Installation Information, but only if you would otherwise be required to provide such information under
be required to provide such information under section 6 of the section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified
GNU GPL, and only to the extent that such information is version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked
necessary to install and execute a modified version of the Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and
Combined Work produced by recombining or relinking the Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner
Application with a modified version of the Linked Version. (If specified by section 6 of the GNU GPL for conveying Corresponding Source.)
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries. 5. Combined Libraries.
You may place library facilities that are a work based on the You may place library facilities that are a work based on the Library side by side in a single library together with
Library side by side in a single library together with other library other library facilities that are not Applications and are not covered by this License, and convey such a combined
facilities that are not Applications and are not covered by this library under terms of your choice, if you do both of the following:
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library
on the Library, uncombined with any other library facilities, facilities, conveyed under the terms of this License.
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where
is a work based on the Library, and explaining where to find the to find the accompanying uncombined form of the same work.
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License. 6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time
of the GNU Lesser General Public License from time to time. Such new to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new
versions will be similar in spirit to the present version, but may problems or concerns.
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Each version is given a distinguishing version number. If the Library as you received it specifies that a certain
Library as you received it specifies that a certain numbered version numbered version of the GNU Lesser General Public License "or any later version"
of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any
applies to it, you have the option of following the terms and later version published by the Free Software Foundation. If the Library as you received it does not specify a version
conditions either of that published version or of any later version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License
published by the Free Software Foundation. If the Library as you ever published by the Free Software Foundation.
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General
whether future versions of the GNU Lesser General Public License shall Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for
apply, that proxy's public statement of acceptance of any version is you to choose that version for the Library.
permanent authorization for you to choose that version for the
Library.

View file

@ -9,28 +9,34 @@
</div> </div>
### About ### About
The goal of this project is to provide tools for mod developers so they no longer have to worry about performance, or limitations of Minecraft's archaic rendering engine.
That said, this is primarily an outlet for me to have fun with graphics programming.
The goal of this project is to provide tools for mod developers so they no longer have to worry about performance, or
limitations of Minecraft's archaic rendering engine. That said, this is primarily an outlet for me to have fun with
graphics programming.
### Instancing ### Instancing
Flywheel provides an alternate, unified path for entity and tile entity rendering that takes advantage of GPU instancing. In doing so, Flywheel gives the developer the flexibility to define their own vertex and instance formats, and write custom shaders to ingest that data.
Flywheel provides an alternate, unified path for entity and tile entity rendering that takes advantage of GPU
instancing. In doing so, Flywheel gives the developer the flexibility to define their own vertex and instance formats,
and write custom shaders to ingest that data.
### Shaders ### Shaders
To accomodate the developer and leave more in the hands of the engine, Flywheel provides a custom shader loading and templating system to hide the details of the CPU/GPU interface. This system is a work in progress. There will be breaking changes, and I make no guarantees of backwards compatibility.
To accomodate the developer and leave more in the hands of the engine, Flywheel provides a custom shader loading and
templating system to hide the details of the CPU/GPU interface. This system is a work in progress. There will be
breaking changes, and I make no guarantees of backwards compatibility.
### Plans ### Plans
- Vanilla performance improvements
- Compute shader particles
- Deferred rendering
- Different renderers for differently aged hardware
- Vanilla performance improvements
- Compute shader particles
- Deferred rendering
- Different renderers for differently aged hardware
### Getting Started (For Developers) ### Getting Started (For Developers)
Add the following repo to your `build.gradle`: Add the following repo to your `build.gradle`:
```groovy ```groovy
repositories { repositories {
maven { maven {
@ -41,6 +47,7 @@ repositories {
``` ```
Then add Flywheel as a dependency: Then add Flywheel as a dependency:
```groovy ```groovy
dependencies { dependencies {
implementation fg.deobf("com.jozufozu.flywheel:Flywheel:1.16-0.0.2.9") implementation fg.deobf("com.jozufozu.flywheel:Flywheel:1.16-0.0.2.9")

View file

@ -3,7 +3,7 @@ buildscript {
maven { url = 'https://files.minecraftforge.net/maven' } maven { url = 'https://files.minecraftforge.net/maven' }
jcenter() jcenter()
mavenCentral() mavenCentral()
maven { url='https://repo.spongepowered.org/repository/maven-public/' } maven { url = 'https://repo.spongepowered.org/repository/maven-public/' }
} }
dependencies { dependencies {
classpath group: 'net.minecraftforge.gradle', name: 'ForgeGradle', version: '3.+', changing: true classpath group: 'net.minecraftforge.gradle', name: 'ForgeGradle', version: '3.+', changing: true
@ -11,7 +11,6 @@ buildscript {
} }
} }
plugins { plugins {
id 'com.github.johnrengelman.shadow' version '5.2.0'
id 'com.matthewprenger.cursegradle' version '1.4.0' id 'com.matthewprenger.cursegradle' version '1.4.0'
} }
@ -89,9 +88,6 @@ mixin {
add sourceSets.main, "flywheel.refmap.json" add sourceSets.main, "flywheel.refmap.json"
} }
// Include resources generated by data generators.
sourceSets.main.resources { srcDir 'src/generated/resources' }
repositories { repositories {
maven { maven {
name "tterrag maven" name "tterrag maven"

View file

@ -5,18 +5,10 @@ org.gradle.daemon=false
mod_version=0.0.3 mod_version=0.0.3
mc_update_version=1.16 mc_update_version=1.16
minecraft_version=1.16.5 minecraft_version=1.16.5
forge_version=36.0.42 forge_version=36.0.42
mcp_mappings=20200920-mixed-1.16.3 mcp_mappings=20200920-mixed-1.16.3
# dependency versions
registrate_version=1.0.4
jei_version=7.6.1.71
# curseforge information
# projectId=486392
# curse_type=beta
# github information
projectId=486392 projectId=486392
curse_type=beta curse_type=beta
github_project=Jozufozu/Flywheel github_project=Jozufozu/Flywheel

View file

@ -1,34 +1,35 @@
package com.jozufozu.flywheel; package com.jozufozu.flywheel;
import com.jozufozu.flywheel.config.FlwConfig; import org.apache.logging.log4j.LogManager;
import com.jozufozu.flywheel.config.FlwCommands; import org.apache.logging.log4j.Logger;
import com.jozufozu.flywheel.config.FlwCommands;
import com.jozufozu.flywheel.config.FlwConfig;
import com.jozufozu.flywheel.config.FlwPackets; import com.jozufozu.flywheel.config.FlwPackets;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.fml.DistExecutor; import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@Mod("flywheel") @Mod("flywheel")
public class Flywheel { public class Flywheel {
public static final String ID = "flywheel"; public static final String ID = "flywheel";
private static final Logger LOGGER = LogManager.getLogger(); private static final Logger LOGGER = LogManager.getLogger();
public Flywheel() { public Flywheel() {
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::setup); FMLJavaModLoadingContext.get()
.getModEventBus()
.addListener(this::setup);
MinecraftForge.EVENT_BUS.addListener(FlwCommands::onServerStarting); MinecraftForge.EVENT_BUS.addListener(FlwCommands::onServerStarting);
FlwConfig.init(); FlwConfig.init();
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> Client::clientInit); DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> FlywheelClient::clientInit);
} }
private void setup(final FMLCommonSetupEvent event) { private void setup(final FMLCommonSetupEvent event) {

View file

@ -2,20 +2,19 @@ package com.jozufozu.flywheel;
import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.core.AtlasStitcher; import com.jozufozu.flywheel.core.AtlasStitcher;
import com.jozufozu.flywheel.core.Contexts; import com.jozufozu.flywheel.core.Contexts;
import com.jozufozu.flywheel.core.Materials; import com.jozufozu.flywheel.core.Materials;
import net.minecraftforge.eventbus.api.IEventBus; import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
public class Client { public class FlywheelClient {
public static void clientInit() { public static void clientInit() {
Backend.init(); Backend.init();
IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus(); IEventBus modEventBus = FMLJavaModLoadingContext.get()
.getModEventBus();
modEventBus.addListener(AtlasStitcher.getInstance()::onTextureStitch); modEventBus.addListener(AtlasStitcher.getInstance()::onTextureStitch);

View file

@ -6,7 +6,7 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import com.jozufozu.flywheel.config.FlwConfig; import javax.annotation.Nullable;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
@ -16,6 +16,7 @@ import org.lwjgl.opengl.GLCapabilities;
import com.jozufozu.flywheel.backend.gl.versioned.GlCompat; import com.jozufozu.flywheel.backend.gl.versioned.GlCompat;
import com.jozufozu.flywheel.backend.instancing.InstanceData; import com.jozufozu.flywheel.backend.instancing.InstanceData;
import com.jozufozu.flywheel.backend.instancing.MaterialSpec; import com.jozufozu.flywheel.backend.instancing.MaterialSpec;
import com.jozufozu.flywheel.config.FlwConfig;
import com.jozufozu.flywheel.core.shader.spec.ProgramSpec; import com.jozufozu.flywheel.core.shader.spec.ProgramSpec;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
@ -24,8 +25,6 @@ import net.minecraft.util.math.vector.Matrix4f;
import net.minecraft.world.IWorld; import net.minecraft.world.IWorld;
import net.minecraft.world.World; import net.minecraft.world.World;
import javax.annotation.Nullable;
public class Backend { public class Backend {
public static final Logger log = LogManager.getLogger(Backend.class); public static final Logger log = LogManager.getLogger(Backend.class);
@ -111,7 +110,9 @@ public class Backend {
} }
materialRegistry.put(name, spec); materialRegistry.put(name, spec);
log.debug("registered material '" + name + "' with vertex size " + spec.getModelFormat().getStride() + " and instance size " + spec.getInstanceFormat().getStride()); log.debug("registered material '" + name + "' with vertex size " + spec.getModelFormat()
.getStride() + " and instance size " + spec.getInstanceFormat()
.getStride());
return spec; return spec;
} }
@ -146,11 +147,10 @@ public class Backend {
compat = new GlCompat(capabilities); compat = new GlCompat(capabilities);
instancedArrays = compat.vertexArrayObjectsSupported() && instancedArrays = compat.vertexArrayObjectsSupported() && compat.drawInstancedSupported() && compat.instancedArraysSupported();
compat.drawInstancedSupported() &&
compat.instancedArraysSupported();
enabled = FlwConfig.get().enabled() && !OptifineHandler.usingShaders(); enabled = FlwConfig.get()
.enabled() && !OptifineHandler.usingShaders();
} }
public boolean canUseInstancing(World world) { public boolean canUseInstancing(World world) {
@ -181,11 +181,9 @@ public class Backend {
* Used to avoid calling Flywheel functions on (fake) worlds that don't specifically support it. * Used to avoid calling Flywheel functions on (fake) worlds that don't specifically support it.
*/ */
public static boolean isFlywheelWorld(@Nullable IWorld world) { public static boolean isFlywheelWorld(@Nullable IWorld world) {
if (world == null) if (world == null) return false;
return false;
if (world instanceof IFlywheelWorld && ((IFlywheelWorld) world).supportsFlywheel()) if (world instanceof IFlywheelWorld && ((IFlywheelWorld) world).supportsFlywheel()) return true;
return true;
return world == Minecraft.getInstance().world; return world == Minecraft.getInstance().world;
} }
@ -198,5 +196,6 @@ public class Backend {
RenderWork.enqueue(Minecraft.getInstance().worldRenderer::loadRenderers); RenderWork.enqueue(Minecraft.getInstance().worldRenderer::loadRenderers);
} }
public static void init() { } public static void init() {
}
} }

View file

@ -9,7 +9,8 @@ import net.minecraft.util.ResourceLocation;
public interface IShaderContext<P extends GlProgram> { public interface IShaderContext<P extends GlProgram> {
default P getProgram(ResourceLocation loc) { default P getProgram(ResourceLocation loc) {
return this.getProgramSupplier(loc).get(); return this.getProgramSupplier(loc)
.get();
} }
Supplier<P> getProgramSupplier(ResourceLocation loc); Supplier<P> getProgramSupplier(ResourceLocation loc);

View file

@ -45,7 +45,8 @@ public class OptifineHandler {
if (optifine == null) { if (optifine == null) {
Backend.log.info("Optifine not detected."); Backend.log.info("Optifine not detected.");
} else { }
else {
Backend.log.info("Optifine detected."); Backend.log.info("Optifine detected.");
refresh(); refresh();

View file

@ -17,7 +17,8 @@ public class RenderWork {
@SubscribeEvent(priority = EventPriority.LOWEST) @SubscribeEvent(priority = EventPriority.LOWEST)
public static void onRenderWorldLast(RenderWorldLastEvent event) { public static void onRenderWorldLast(RenderWorldLastEvent event) {
while (!runs.isEmpty()) { while (!runs.isEmpty()) {
runs.remove().run(); runs.remove()
.run();
} }
} }

View file

@ -9,7 +9,8 @@ public class ResourceUtil {
} }
public static ResourceLocation removePrefixUnchecked(ResourceLocation full, String root) { public static ResourceLocation removePrefixUnchecked(ResourceLocation full, String root) {
return new ResourceLocation(full.getNamespace(), full.getPath().substring(root.length())); return new ResourceLocation(full.getNamespace(), full.getPath()
.substring(root.length()));
} }
public static ResourceLocation trim(ResourceLocation loc, String prefix, String suffix) { public static ResourceLocation trim(ResourceLocation loc, String prefix, String suffix) {

View file

@ -57,7 +57,8 @@ public abstract class ShaderContext<P extends GlProgram> implements IShaderConte
@Override @Override
public void delete() { public void delete() {
programs.values().forEach(IMultiProgram::delete); programs.values()
.forEach(IMultiProgram::delete);
programs.clear(); programs.clear();
} }

View file

@ -19,15 +19,6 @@ import java.util.stream.Stream;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault; import javax.annotation.ParametersAreNonnullByDefault;
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
import com.jozufozu.flywheel.event.ForgeEvents;
import net.minecraft.client.Minecraft;
import net.minecraft.client.world.ClientWorld;
import net.minecraftforge.event.world.WorldEvent;
import org.lwjgl.system.MemoryUtil; import org.lwjgl.system.MemoryUtil;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
@ -35,6 +26,7 @@ import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.jozufozu.flywheel.backend.gl.shader.ShaderType; import com.jozufozu.flywheel.backend.gl.shader.ShaderType;
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
import com.jozufozu.flywheel.backend.loading.Shader; import com.jozufozu.flywheel.backend.loading.Shader;
import com.jozufozu.flywheel.backend.loading.ShaderLoadingException; import com.jozufozu.flywheel.backend.loading.ShaderLoadingException;
import com.jozufozu.flywheel.core.shader.spec.ProgramSpec; import com.jozufozu.flywheel.core.shader.spec.ProgramSpec;
@ -44,6 +36,8 @@ import com.mojang.datafixers.util.Pair;
import com.mojang.serialization.DataResult; import com.mojang.serialization.DataResult;
import com.mojang.serialization.JsonOps; import com.mojang.serialization.JsonOps;
import net.minecraft.client.Minecraft;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.resources.IReloadableResourceManager; import net.minecraft.resources.IReloadableResourceManager;
import net.minecraft.resources.IResource; import net.minecraft.resources.IResource;
import net.minecraft.resources.IResourceManager; import net.minecraft.resources.IResourceManager;
@ -84,7 +78,8 @@ public class ShaderSources implements ISelectiveResourceReloadListener {
shouldCrash = false; shouldCrash = false;
backend.clearContexts(); backend.clearContexts();
ModLoader.get().postEvent(new GatherContextEvent(backend)); ModLoader.get()
.postEvent(new GatherContextEvent(backend));
loadProgramSpecs(manager); loadProgramSpecs(manager);
loadShaderSources(manager); loadShaderSources(manager);
@ -123,7 +118,9 @@ public class ShaderSources implements ISelectiveResourceReloadListener {
DataResult<Pair<ProgramSpec, JsonElement>> result = ProgramSpec.CODEC.decode(JsonOps.INSTANCE, GSON.fromJson(s, JsonElement.class)); DataResult<Pair<ProgramSpec, JsonElement>> result = ProgramSpec.CODEC.decode(JsonOps.INSTANCE, GSON.fromJson(s, JsonElement.class));
ProgramSpec spec = result.get().orThrow().getFirst(); ProgramSpec spec = result.get()
.orThrow()
.getFirst();
spec.setName(specName); spec.setName(specName);
@ -210,7 +207,8 @@ public class ShaderSources implements ISelectiveResourceReloadListener {
while (filechannel.read(bytebuffer) != -1) { while (filechannel.read(bytebuffer) != -1) {
} }
} else { }
else {
bytebuffer = MemoryUtil.memAlloc(8192); bytebuffer = MemoryUtil.memAlloc(8192);
ReadableByteChannel readablebytechannel = Channels.newChannel(is); ReadableByteChannel readablebytechannel = Channels.newChannel(is);

View file

@ -53,9 +53,11 @@ public enum GlNumericType {
public void castAndBuffer(ByteBuffer buf, int val) { public void castAndBuffer(ByteBuffer buf, int val) {
if (this == UBYTE || this == BYTE) { if (this == UBYTE || this == BYTE) {
buf.put((byte) val); buf.put((byte) val);
} else if (this == USHORT || this == SHORT) { }
else if (this == USHORT || this == SHORT) {
buf.putShort((short) val); buf.putShort((short) val);
} else if (this == UINT || this == INT) { }
else if (this == UINT || this == INT) {
buf.putInt(val); buf.putInt(val);
} }
} }

View file

@ -56,7 +56,8 @@ public class GlBuffer extends GlObject {
public MappedBuffer getBuffer(int offset, int length) { public MappedBuffer getBuffer(int offset, int length) {
if (Backend.getInstance().compat.mapBufferRange != MapBufferRange.UNSUPPORTED) { if (Backend.getInstance().compat.mapBufferRange != MapBufferRange.UNSUPPORTED) {
return new MappedBufferRange(this, offset, length, GL30.GL_MAP_WRITE_BIT); return new MappedBufferRange(this, offset, length, GL30.GL_MAP_WRITE_BIT);
} else { }
else {
MappedFullBuffer fullBuffer = new MappedFullBuffer(this, MappedBufferUsage.WRITE_ONLY); MappedFullBuffer fullBuffer = new MappedFullBuffer(this, MappedBufferUsage.WRITE_ONLY);
fullBuffer.position(offset); fullBuffer.position(offset);
return fullBuffer; return fullBuffer;

View file

@ -39,8 +39,8 @@ public class VecBuffer {
for (float f : floats) { for (float f : floats) {
internal.putFloat(f); internal.putFloat(f);
} }
// internal.asFloatBuffer().put(floats); // internal.asFloatBuffer().put(floats);
// internal.position(internal.position() + floats.length * 4); // internal.position(internal.position() + floats.length * 4);
return this; return this;
} }

View file

@ -79,7 +79,10 @@ public class GlCompat {
throw new IllegalStateException(""); throw new IllegalStateException("");
} }
return Arrays.stream(constants).filter(it -> it.supported(caps)).findFirst().get(); return Arrays.stream(constants)
.filter(it -> it.supported(caps))
.findFirst()
.get();
} }
/** /**

View file

@ -61,8 +61,7 @@ public abstract class InstanceManager<T> implements MaterialManager.OriginShiftL
int dY = pos.getY() - cY; int dY = pos.getY() - cY;
int dZ = pos.getZ() - cZ; int dZ = pos.getZ() - cZ;
if ((tick % getUpdateDivisor(dX, dY, dZ)) == 0) if ((tick % getUpdateDivisor(dX, dY, dZ)) == 0) instance.tick();
instance.tick();
} }
} }
@ -88,16 +87,18 @@ public abstract class InstanceManager<T> implements MaterialManager.OriginShiftL
int cZ = (int) info.getProjectedView().z; int cZ = (int) info.getProjectedView().z;
if (dynamicInstances.size() > 0) { if (dynamicInstances.size() > 0) {
dynamicInstances.object2ObjectEntrySet().fastForEach(e -> { dynamicInstances.object2ObjectEntrySet()
IDynamicInstance dyn = e.getValue(); .fastForEach(e -> {
if (!dyn.decreaseFramerateWithDistance() || shouldFrameUpdate(dyn.getWorldPosition(), lookX, lookY, lookZ, cX, cY, cZ)) IDynamicInstance dyn = e.getValue();
dyn.beginFrame(); if (!dyn.decreaseFramerateWithDistance() || shouldFrameUpdate(dyn.getWorldPosition(), lookX, lookY, lookZ, cX, cY, cZ))
}); dyn.beginFrame();
});
} }
} }
public void add(T obj) { public void add(T obj) {
if (!Backend.getInstance().canUseInstancing()) return; if (!Backend.getInstance()
.canUseInstancing()) return;
if (obj instanceof IInstanceRendered) { if (obj instanceof IInstanceRendered) {
addInternal(obj); addInternal(obj);
@ -105,13 +106,15 @@ public abstract class InstanceManager<T> implements MaterialManager.OriginShiftL
} }
public synchronized void queueAdd(T obj) { public synchronized void queueAdd(T obj) {
if (!Backend.getInstance().canUseInstancing()) return; if (!Backend.getInstance()
.canUseInstancing()) return;
queuedAdditions.add(obj); queuedAdditions.add(obj);
} }
public void update(T obj) { public void update(T obj) {
if (!Backend.getInstance().canUseInstancing()) return; if (!Backend.getInstance()
.canUseInstancing()) return;
if (obj instanceof IInstanceRendered) { if (obj instanceof IInstanceRendered) {
IInstance instance = getInstance(obj, false); IInstance instance = getInstance(obj, false);
@ -122,7 +125,8 @@ public abstract class InstanceManager<T> implements MaterialManager.OriginShiftL
removeInternal(obj, instance); removeInternal(obj, instance);
createInternal(obj); createInternal(obj);
} else { }
else {
instance.update(); instance.update();
} }
} }
@ -130,29 +134,30 @@ public abstract class InstanceManager<T> implements MaterialManager.OriginShiftL
} }
public synchronized void queueUpdate(T obj) { public synchronized void queueUpdate(T obj) {
if (!Backend.getInstance().canUseInstancing()) return; if (!Backend.getInstance()
.canUseInstancing()) return;
queuedUpdates.add(obj); queuedUpdates.add(obj);
} }
public void onLightUpdate(T obj) { public void onLightUpdate(T obj) {
if (!Backend.getInstance().canUseInstancing()) return; if (!Backend.getInstance()
.canUseInstancing()) return;
if (obj instanceof IInstanceRendered) { if (obj instanceof IInstanceRendered) {
IInstance instance = getInstance(obj, false); IInstance instance = getInstance(obj, false);
if (instance != null) if (instance != null) instance.updateLight();
instance.updateLight();
} }
} }
public void remove(T obj) { public void remove(T obj) {
if (!Backend.getInstance().canUseInstancing()) return; if (!Backend.getInstance()
.canUseInstancing()) return;
if (obj instanceof IInstanceRendered) { if (obj instanceof IInstanceRendered) {
IInstance instance = getInstance(obj, false); IInstance instance = getInstance(obj, false);
if (instance != null) if (instance != null) removeInternal(obj, instance);
removeInternal(obj, instance);
} }
} }
@ -165,15 +170,18 @@ public abstract class InstanceManager<T> implements MaterialManager.OriginShiftL
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Nullable @Nullable
protected <I extends T> IInstance getInstance(I obj, boolean create) { protected <I extends T> IInstance getInstance(I obj, boolean create) {
if (!Backend.getInstance().canUseInstancing()) return null; if (!Backend.getInstance()
.canUseInstancing()) return null;
IInstance instance = instances.get(obj); IInstance instance = instances.get(obj);
if (instance != null) { if (instance != null) {
return instance; return instance;
} else if (create && canCreateInstance(obj)) { }
else if (create && canCreateInstance(obj)) {
return createInternal(obj); return createInternal(obj);
} else { }
else {
return null; return null;
} }
} }
@ -222,11 +230,9 @@ public abstract class InstanceManager<T> implements MaterialManager.OriginShiftL
renderer.updateLight(); renderer.updateLight();
instances.put(obj, renderer); instances.put(obj, renderer);
if (renderer instanceof IDynamicInstance) if (renderer instanceof IDynamicInstance) dynamicInstances.put(obj, (IDynamicInstance) renderer);
dynamicInstances.put(obj, (IDynamicInstance) renderer);
if (renderer instanceof ITickableInstance) if (renderer instanceof ITickableInstance) tickableInstances.put(obj, ((ITickableInstance) renderer));
tickableInstances.put(obj, ((ITickableInstance) renderer));
} }
return renderer; return renderer;

View file

@ -55,7 +55,10 @@ public class InstanceMaterial<D extends InstanceData> {
} }
public boolean nothingToRender() { public boolean nothingToRender() {
return models.size() > 0 && models.asMap().values().stream().allMatch(Instancer::empty); return models.size() > 0 && models.asMap()
.values()
.stream()
.allMatch(Instancer::empty);
} }
public void delete() { public void delete() {
@ -66,11 +69,14 @@ public class InstanceMaterial<D extends InstanceData> {
* Clear all instance data without freeing resources. * Clear all instance data without freeing resources.
*/ */
public void clear() { public void clear() {
models.asMap().values().forEach(Instancer::clear); models.asMap()
.values()
.forEach(Instancer::clear);
} }
public void forEachInstancer(Consumer<Instancer<D>> f) { public void forEachInstancer(Consumer<Instancer<D>> f) {
for (Instancer<D> model : models.asMap().values()) { for (Instancer<D> model : models.asMap()
.values()) {
f.accept(model); f.accept(model);
} }
} }
@ -84,8 +90,7 @@ public class InstanceMaterial<D extends InstanceData> {
} }
public Instancer<D> getModel(PartialModel partial, BlockState referenceState, Direction dir, Supplier<MatrixStack> modelTransform) { public Instancer<D> getModel(PartialModel partial, BlockState referenceState, Direction dir, Supplier<MatrixStack> modelTransform) {
return get(Pair.of(dir, partial), return get(Pair.of(dir, partial), () -> buildModel(partial.get(), referenceState, modelTransform.get()));
() -> buildModel(partial.get(), referenceState, modelTransform.get()));
} }
public Instancer<D> getModel(BlockState toRender) { public Instancer<D> getModel(BlockState toRender) {
@ -102,7 +107,8 @@ public class InstanceMaterial<D extends InstanceData> {
} }
private BufferedModel buildModel(BlockState renderedState) { private BufferedModel buildModel(BlockState renderedState) {
BlockRendererDispatcher dispatcher = Minecraft.getInstance().getBlockRendererDispatcher(); BlockRendererDispatcher dispatcher = Minecraft.getInstance()
.getBlockRendererDispatcher();
return buildModel(dispatcher.getModelForState(renderedState), renderedState); return buildModel(dispatcher.getModelForState(renderedState), renderedState);
} }
@ -153,16 +159,15 @@ public class InstanceMaterial<D extends InstanceData> {
BlockModelRenderer blockRenderer = dispatcher.getBlockModelRenderer(); BlockModelRenderer blockRenderer = dispatcher.getBlockModelRenderer();
BufferBuilder builder = new BufferBuilder(512); BufferBuilder builder = new BufferBuilder(512);
// BakedQuadWrapper quadReader = new BakedQuadWrapper(); // BakedQuadWrapper quadReader = new BakedQuadWrapper();
// //
// IModelData modelData = model.getModelData(mc.world, BlockPos.ZERO.up(255), referenceState, VirtualEmptyModelData.INSTANCE); // IModelData modelData = model.getModelData(mc.world, BlockPos.ZERO.up(255), referenceState, VirtualEmptyModelData.INSTANCE);
// List<BakedQuad> quads = Arrays.stream(dirs) // List<BakedQuad> quads = Arrays.stream(dirs)
// .flatMap(dir -> model.getQuads(referenceState, dir, mc.world.rand, modelData).stream()) // .flatMap(dir -> model.getQuads(referenceState, dir, mc.world.rand, modelData).stream())
// .collect(Collectors.toList()); // .collect(Collectors.toList());
builder.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK); builder.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK);
blockRenderer.renderModel(mc.world, model, referenceState, BlockPos.ZERO.up(255), ms, builder, true, blockRenderer.renderModel(mc.world, model, referenceState, BlockPos.ZERO.up(255), ms, builder, true, mc.world.rand, 42, OverlayTexture.DEFAULT_UV, VirtualEmptyModelData.INSTANCE);
mc.world.rand, 42, OverlayTexture.DEFAULT_UV, VirtualEmptyModelData.INSTANCE);
builder.finishDrawing(); builder.finishDrawing();
return builder; return builder;
} }

View file

@ -109,7 +109,8 @@ public class InstancedRenderDispatcher {
@SubscribeEvent @SubscribeEvent
public static void renderLayer(RenderLayerEvent event) { public static void renderLayer(RenderLayerEvent event) {
ClientWorld world = event.getWorld(); ClientWorld world = event.getWorld();
if (!Backend.getInstance().canUseInstancing(world)) return; if (!Backend.getInstance()
.canUseInstancing(world)) return;
event.type.startDrawing(); event.type.startDrawing();
@ -122,7 +123,8 @@ public class InstancedRenderDispatcher {
@SubscribeEvent @SubscribeEvent
public static void onReloadRenderers(ReloadRenderersEvent event) { public static void onReloadRenderers(ReloadRenderersEvent event) {
ClientWorld world = event.getWorld(); ClientWorld world = event.getWorld();
if (Backend.getInstance().canUseInstancing() && world != null) { if (Backend.getInstance()
.canUseInstancing() && world != null) {
loadAllInWorld(world); loadAllInWorld(world);
} }
} }
@ -130,7 +132,8 @@ public class InstancedRenderDispatcher {
private static final RenderType crumblingLayer = ModelBakery.BLOCK_DESTRUCTION_RENDER_LAYERS.get(0); private static final RenderType crumblingLayer = ModelBakery.BLOCK_DESTRUCTION_RENDER_LAYERS.get(0);
public static void renderBreaking(ClientWorld world, Matrix4f viewProjection, double cameraX, double cameraY, double cameraZ) { public static void renderBreaking(ClientWorld world, Matrix4f viewProjection, double cameraX, double cameraY, double cameraZ) {
if (!Backend.getInstance().canUseInstancing(world)) return; if (!Backend.getInstance()
.canUseInstancing(world)) return;
WorldRenderer worldRenderer = Minecraft.getInstance().worldRenderer; WorldRenderer worldRenderer = Minecraft.getInstance().worldRenderer;
Long2ObjectMap<SortedSet<DestroyBlockProgress>> breakingProgressions = worldRenderer.blockBreakingProgressions; Long2ObjectMap<SortedSet<DestroyBlockProgress>> breakingProgressions = worldRenderer.blockBreakingProgressions;
@ -145,9 +148,11 @@ public class InstancedRenderDispatcher {
SortedSet<DestroyBlockProgress> progresses = entry.getValue(); SortedSet<DestroyBlockProgress> progresses = entry.getValue();
if (progresses != null && !progresses.isEmpty()) { if (progresses != null && !progresses.isEmpty()) {
int blockDamage = progresses.last().getPartialBlockDamage(); int blockDamage = progresses.last()
.getPartialBlockDamage();
bitSet.set(blockDamage); bitSet.set(blockDamage);
renderers.get(blockDamage).add(world.getTileEntity(breakingPos)); renderers.get(blockDamage)
.add(world.getTileEntity(breakingPos));
} }
} }
@ -155,38 +160,41 @@ public class InstancedRenderDispatcher {
ActiveRenderInfo info = Minecraft.getInstance().gameRenderer.getActiveRenderInfo(); ActiveRenderInfo info = Minecraft.getInstance().gameRenderer.getActiveRenderInfo();
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textureManager.getTexture(PlayerContainer.BLOCK_ATLAS_TEXTURE).getGlTextureId()); glBindTexture(GL_TEXTURE_2D, textureManager.getTexture(PlayerContainer.BLOCK_ATLAS_TEXTURE)
.getGlTextureId());
glActiveTexture(GL_TEXTURE4); glActiveTexture(GL_TEXTURE4);
crumblingLayer.startDrawing(); crumblingLayer.startDrawing();
bitSet.stream().forEach(i -> { bitSet.stream()
Texture breaking = textureManager.getTexture(ModelBakery.BLOCK_DESTRUCTION_STAGE_TEXTURES.get(i)); .forEach(i -> {
CrumblingInstanceManager renderer = renderers.get(i); Texture breaking = textureManager.getTexture(ModelBakery.BLOCK_DESTRUCTION_STAGE_TEXTURES.get(i));
renderer.beginFrame(info); CrumblingInstanceManager renderer = renderers.get(i);
renderer.beginFrame(info);
if (breaking != null) { if (breaking != null) {
glBindTexture(GL_TEXTURE_2D, breaking.getGlTextureId()); glBindTexture(GL_TEXTURE_2D, breaking.getGlTextureId());
renderer.materialManager.render(RenderType.getCutoutMipped(), viewProjection, cameraX, cameraY, cameraZ); renderer.materialManager.render(RenderType.getCutoutMipped(), viewProjection, cameraX, cameraY, cameraZ);
} }
renderer.invalidate(); renderer.invalidate();
}); });
crumblingLayer.endDrawing(); crumblingLayer.endDrawing();
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
Texture breaking = textureManager.getTexture(ModelBakery.BLOCK_DESTRUCTION_STAGE_TEXTURES.get(0)); Texture breaking = textureManager.getTexture(ModelBakery.BLOCK_DESTRUCTION_STAGE_TEXTURES.get(0));
if (breaking != null) if (breaking != null) glBindTexture(GL_TEXTURE_2D, breaking.getGlTextureId());
glBindTexture(GL_TEXTURE_2D, breaking.getGlTextureId());
} }
public static void loadAllInWorld(ClientWorld world) { public static void loadAllInWorld(ClientWorld world) {
Contexts.WORLD.getMaterialManager(world).delete(); Contexts.WORLD.getMaterialManager(world)
.delete();
TileInstanceManager tiles = tileInstanceManager.replace(world); TileInstanceManager tiles = tileInstanceManager.replace(world);
world.loadedTileEntityList.forEach(tiles::add); world.loadedTileEntityList.forEach(tiles::add);
EntityInstanceManager entities = entityInstanceManager.replace(world); EntityInstanceManager entities = entityInstanceManager.replace(world);
world.getAllEntities().forEach(entities::add); world.getAllEntities()
.forEach(entities::add);
} }
} }

View file

@ -65,8 +65,7 @@ public class Instancer<D extends InstanceData> {
vao.bind(); vao.bind();
renderSetup(); renderSetup();
if (glInstanceCount > 0) if (glInstanceCount > 0) model.drawInstances(glInstanceCount);
model.drawInstances(glInstanceCount);
vao.unbind(); vao.unbind();
} }
@ -160,12 +159,13 @@ public class Instancer<D extends InstanceData> {
if (length > 0) { if (length > 0) {
MappedBuffer mapped = instanceVBO.getBuffer(offset, length); MappedBuffer mapped = instanceVBO.getBuffer(offset, length);
dirtySet.stream().forEach(i -> { dirtySet.stream()
final D d = data.get(i); .forEach(i -> {
final D d = data.get(i);
mapped.position(i * stride); mapped.position(i * stride);
d.write(mapped); d.write(mapped);
}); });
mapped.flush(); mapped.flush();
} }
} }
@ -236,7 +236,8 @@ public class Instancer<D extends InstanceData> {
anyToUpdate = true; anyToUpdate = true;
data.subList(newSize, oldSize).clear(); data.subList(newSize, oldSize)
.clear();
} }

View file

@ -42,7 +42,9 @@ public class MaterialManager<P extends WorldProgram> {
this.context = context; this.context = context;
this.atlasMaterials = new HashMap<>(); this.atlasMaterials = new HashMap<>();
this.atlasRenderers = new ArrayList<>(Backend.getInstance().allMaterials().size()); this.atlasRenderers = new ArrayList<>(Backend.getInstance()
.allMaterials()
.size());
this.materials = new HashMap<>(); this.materials = new HashMap<>();
this.renderers = new HashMap<>(); this.renderers = new HashMap<>();
@ -90,8 +92,13 @@ public class MaterialManager<P extends WorldProgram> {
} }
public void delete() { public void delete() {
atlasMaterials.values().forEach(InstanceMaterial::delete); atlasMaterials.values()
materials.values().stream().flatMap(m -> m.values().stream()).forEach(InstanceMaterial::delete); .forEach(InstanceMaterial::delete);
materials.values()
.stream()
.flatMap(m -> m.values()
.stream())
.forEach(InstanceMaterial::delete);
atlasMaterials.clear(); atlasMaterials.clear();
atlasRenderers.clear(); atlasRenderers.clear();
@ -151,8 +158,13 @@ public class MaterialManager<P extends WorldProgram> {
originCoordinate = new BlockPos(cX, cY, cZ); originCoordinate = new BlockPos(cX, cY, cZ);
materials.values().stream().flatMap(m -> m.values().stream()).forEach(InstanceMaterial::clear); materials.values()
atlasMaterials.values().forEach(InstanceMaterial::clear); .stream()
.flatMap(m -> m.values()
.stream())
.forEach(InstanceMaterial::clear);
atlasMaterials.values()
.forEach(InstanceMaterial::clear);
listeners.forEach(OriginShiftListener::onOriginShift); listeners.forEach(OriginShiftListener::onOriginShift);
} }
} }

View file

@ -24,7 +24,7 @@ import net.minecraft.world.World;
/** /**
* The layer between a {@link TileEntity} and the Flywheel backend. * The layer between a {@link TileEntity} and the Flywheel backend.
** * *
* <br><br> There are a few additional features that overriding classes can opt in to: * <br><br> There are a few additional features that overriding classes can opt in to:
* <ul> * <ul>
* <li>{@link IDynamicInstance}</li> * <li>{@link IDynamicInstance}</li>
@ -94,11 +94,7 @@ public abstract class EntityInstance<E extends Entity> implements IInstance {
public Vector3f getInstancePosition() { public Vector3f getInstancePosition() {
Vector3d pos = entity.getPositionVec(); Vector3d pos = entity.getPositionVec();
Vector3i origin = materialManager.getOriginCoordinate(); Vector3i origin = materialManager.getOriginCoordinate();
return new Vector3f( return new Vector3f((float) (pos.x - origin.getX()), (float) (pos.y - origin.getY()), (float) (pos.z - origin.getZ()));
(float) (pos.x - origin.getX()),
(float) (pos.y - origin.getY()),
(float) (pos.z - origin.getZ())
);
} }
@Override @Override
@ -119,7 +115,8 @@ public abstract class EntityInstance<E extends Entity> implements IInstance {
} }
protected <L extends IFlatLight<?>> void relight(int block, int sky, Stream<L> models) { protected <L extends IFlatLight<?>> void relight(int block, int sky, Stream<L> models) {
models.forEach(model -> model.setBlockLight(block).setSkyLight(sky)); models.forEach(model -> model.setBlockLight(block)
.setSkyLight(sky));
} }
protected InstanceMaterial<ModelData> getTransformMaterial() { protected InstanceMaterial<ModelData> getTransformMaterial() {

View file

@ -19,7 +19,8 @@ public class EntityInstanceManager extends InstanceManager<Entity> {
@Override @Override
protected IInstance createRaw(Entity obj) { protected IInstance createRaw(Entity obj) {
return InstancedRenderRegistry.getInstance().create(materialManager, obj); return InstancedRenderRegistry.getInstance()
.create(materialManager, obj);
} }
@Override @Override

View file

@ -117,7 +117,8 @@ public abstract class TileEntityInstance<T extends TileEntity> implements IInsta
} }
protected <L extends IFlatLight<?>> void relight(int block, int sky, Stream<L> models) { protected <L extends IFlatLight<?>> void relight(int block, int sky, Stream<L> models) {
models.forEach(model -> model.setBlockLight(block).setSkyLight(sky)); models.forEach(model -> model.setBlockLight(block)
.setSkyLight(sky));
} }
protected InstanceMaterial<ModelData> getTransformMaterial() { protected InstanceMaterial<ModelData> getTransformMaterial() {

View file

@ -19,7 +19,8 @@ public class TileInstanceManager extends InstanceManager<TileEntity> {
@Override @Override
protected IInstance createRaw(TileEntity obj) { protected IInstance createRaw(TileEntity obj) {
return InstancedRenderRegistry.getInstance().create(materialManager, obj); return InstancedRenderRegistry.getInstance()
.create(materialManager, obj);
} }
@Override @Override

View file

@ -33,7 +33,9 @@ public class InstancedArraysTemplate extends ProgramTemplate {
public void attachAttributes(Program builder) { public void attachAttributes(Program builder) {
Shader shader = builder.attached.get(ShaderType.VERTEX); Shader shader = builder.attached.get(ShaderType.VERTEX);
shader.getTag(vertexData).addPrefixedAttributes(builder, vertexPrefix); shader.getTag(vertexData)
shader.getTag(instanceData).addPrefixedAttributes(builder, instancePrefix); .addPrefixedAttributes(builder, vertexPrefix);
shader.getTag(instanceData)
.addPrefixedAttributes(builder, instancePrefix);
} }
} }

View file

@ -30,6 +30,7 @@ public class ModelTemplate extends ProgramTemplate {
public void attachAttributes(Program builder) { public void attachAttributes(Program builder) {
Shader shader = builder.attached.get(ShaderType.VERTEX); Shader shader = builder.attached.get(ShaderType.VERTEX);
shader.getTag(vertexData).addPrefixedAttributes(builder, vertexPrefix); shader.getTag(vertexData)
.addPrefixedAttributes(builder, vertexPrefix);
} }
} }

View file

@ -72,7 +72,9 @@ public class Shader {
if (matcher.find()) { if (matcher.find()) {
StringBuffer sourceWithDefines = new StringBuffer(); StringBuffer sourceWithDefines = new StringBuffer();
String lines = defines.stream().map(it -> "#define " + it).collect(Collectors.joining("\n")); String lines = defines.stream()
.map(it -> "#define " + it)
.collect(Collectors.joining("\n"));
matcher.appendReplacement(sourceWithDefines, matcher.group() + '\n' + lines); matcher.appendReplacement(sourceWithDefines, matcher.group() + '\n' + lines);
@ -92,7 +94,8 @@ public class Shader {
structs.add(struct); structs.add(struct);
String replacement = decorator.matcher(struct.source).replaceFirst(""); String replacement = decorator.matcher(struct.source)
.replaceFirst("");
structMatcher.appendReplacement(strippedSrc, replacement); structMatcher.appendReplacement(strippedSrc, replacement);
tag2Struct.put(struct.tag, struct); tag2Struct.put(struct.tag, struct);
@ -138,12 +141,14 @@ public class Shader {
public String printSource() { public String printSource() {
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
builder.append("Source for shader '").append(name).append("':\n"); builder.append("Source for shader '")
.append(name)
.append("':\n");
int i = 1; int i = 1;
for (String s : source.split("\n")) { for (String s : source.split("\n")) {
builder.append(String.format("%1$4s: ", i++)) builder.append(String.format("%1$4s: ", i++))
.append(s) .append(s)
.append('\n'); .append('\n');
} }
return builder.toString(); return builder.toString();

View file

@ -47,7 +47,8 @@ public class ShaderTemplate {
if (struct != null) { if (struct != null) {
s = s.replace(name, struct.name); s = s.replace(name, struct.name);
} else { }
else {
missing.add(name); missing.add(name);
} }
} }

View file

@ -40,9 +40,6 @@ public class TaggedField {
@Override @Override
public String toString() { public String toString() {
return "TaggedField{" + return "TaggedField{" + "name='" + name + '\'' + ", type='" + type + '\'' + '}';
"name='" + name + '\'' +
", type='" + type + '\'' +
'}';
} }
} }

View file

@ -25,7 +25,8 @@ public class IndexedModel extends BufferedModel {
} }
public static IndexedModel fromSequentialQuads(VertexFormat modelFormat, ByteBuffer quads, int vertices) { public static IndexedModel fromSequentialQuads(VertexFormat modelFormat, ByteBuffer quads, int vertices) {
return new IndexedModel(modelFormat, quads, vertices, QuadConverter.getInstance().quads2Tris(vertices / 4)); return new IndexedModel(modelFormat, quads, vertices, QuadConverter.getInstance()
.quads2Tris(vertices / 4));
} }
@Override @Override

View file

@ -1,7 +1,6 @@
@ParametersAreNonnullByDefault @ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault
@MethodsReturnNonnullByDefault
package com.jozufozu.flywheel.backend; package com.jozufozu.flywheel.backend;
import mcp.MethodsReturnNonnullByDefault;
import javax.annotation.ParametersAreNonnullByDefault; import javax.annotation.ParametersAreNonnullByDefault;
import mcp.MethodsReturnNonnullByDefault;

View file

@ -1,5 +1,8 @@
package com.jozufozu.flywheel.config; 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.Backend;
import com.jozufozu.flywheel.backend.OptifineHandler; import com.jozufozu.flywheel.backend.OptifineHandler;
@ -12,9 +15,6 @@ import net.minecraft.util.text.TextFormatting;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
import java.util.function.Consumer;
import java.util.function.Supplier;
public enum BooleanConfig { public enum BooleanConfig {
ENGINE(() -> BooleanConfig::enabled), ENGINE(() -> BooleanConfig::enabled),
NORMAL_OVERLAY(() -> BooleanConfig::normalOverlay), NORMAL_OVERLAY(() -> BooleanConfig::normalOverlay),

View file

@ -22,28 +22,24 @@ public class BooleanConfigCommand {
public ArgumentBuilder<CommandSource, ?> register() { public ArgumentBuilder<CommandSource, ?> register() {
return Commands.literal(name) return Commands.literal(name)
.executes(context -> { .executes(context -> {
ServerPlayerEntity player = context.getSource().asPlayer(); ServerPlayerEntity player = context.getSource()
FlwPackets.channel.send( .asPlayer();
PacketDistributor.PLAYER.with(() -> player), FlwPackets.channel.send(PacketDistributor.PLAYER.with(() -> player), new SConfigureBooleanPacket(value, BooleanDirective.DISPLAY));
new SConfigureBooleanPacket(value, BooleanDirective.DISPLAY)
);
return Command.SINGLE_SUCCESS; return Command.SINGLE_SUCCESS;
}) })
.then(Commands.literal("on").executes(context -> { .then(Commands.literal("on")
ServerPlayerEntity player = context.getSource().asPlayer(); .executes(context -> {
FlwPackets.channel.send( ServerPlayerEntity player = context.getSource()
PacketDistributor.PLAYER.with(() -> player), .asPlayer();
new SConfigureBooleanPacket(value, BooleanDirective.TRUE) FlwPackets.channel.send(PacketDistributor.PLAYER.with(() -> player), new SConfigureBooleanPacket(value, BooleanDirective.TRUE));
); return Command.SINGLE_SUCCESS;
return Command.SINGLE_SUCCESS; }))
})) .then(Commands.literal("off")
.then(Commands.literal("off").executes(context -> { .executes(context -> {
ServerPlayerEntity player = context.getSource().asPlayer(); ServerPlayerEntity player = context.getSource()
FlwPackets.channel.send( .asPlayer();
PacketDistributor.PLAYER.with(() -> player), FlwPackets.channel.send(PacketDistributor.PLAYER.with(() -> player), new SConfigureBooleanPacket(value, BooleanDirective.FALSE));
new SConfigureBooleanPacket(value, BooleanDirective.FALSE) return Command.SINGLE_SUCCESS;
); }));
return Command.SINGLE_SUCCESS;
}));
} }
} }

View file

@ -1,19 +1,18 @@
package com.jozufozu.flywheel.config; package com.jozufozu.flywheel.config;
import com.mojang.brigadier.Command;
import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.CommandDispatcher;
import net.minecraft.command.CommandSource; import net.minecraft.command.CommandSource;
import net.minecraft.command.Commands; import net.minecraft.command.Commands;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.event.server.FMLServerStartingEvent; import net.minecraftforge.fml.event.server.FMLServerStartingEvent;
import net.minecraftforge.fml.network.PacketDistributor;
public class FlwCommands { public class FlwCommands {
@SubscribeEvent @SubscribeEvent
public static void onServerStarting(FMLServerStartingEvent event) { public static void onServerStarting(FMLServerStartingEvent event) {
CommandDispatcher<CommandSource> dispatcher = event.getServer().getCommandManager().getDispatcher(); CommandDispatcher<CommandSource> dispatcher = event.getServer()
.getCommandManager()
.getDispatcher();
dispatcher.register(Commands.literal("flywheel") dispatcher.register(Commands.literal("flywheel")
.then(new BooleanConfigCommand("backend", BooleanConfig.ENGINE).register()) .then(new BooleanConfigCommand("backend", BooleanConfig.ENGINE).register())

View file

@ -1,13 +1,12 @@
package com.jozufozu.flywheel.config; package com.jozufozu.flywheel.config;
import org.apache.commons.lang3.tuple.Pair;
import net.minecraftforge.common.ForgeConfigSpec; import net.minecraftforge.common.ForgeConfigSpec;
import net.minecraftforge.common.ForgeConfigSpec.BooleanValue; import net.minecraftforge.common.ForgeConfigSpec.BooleanValue;
import net.minecraftforge.fml.ModLoadingContext; import net.minecraftforge.fml.ModLoadingContext;
import net.minecraftforge.fml.config.ModConfig; import net.minecraftforge.fml.config.ModConfig;
import org.apache.commons.lang3.tuple.Pair;
public class FlwConfig { public class FlwConfig {
private static final FlwConfig INSTANCE = new FlwConfig(); private static final FlwConfig INSTANCE = new FlwConfig();
@ -19,7 +18,8 @@ public class FlwConfig {
this.client = client.getLeft(); this.client = client.getLeft();
ModLoadingContext.get().registerConfig(ModConfig.Type.CLIENT, client.getRight()); ModLoadingContext.get()
.registerConfig(ModConfig.Type.CLIENT, client.getRight());
} }
public static FlwConfig get() { public static FlwConfig get() {
@ -34,7 +34,8 @@ public class FlwConfig {
return client.normalDebug.get(); return client.normalDebug.get();
} }
public static void init() { } public static void init() {
}
public static class ClientConfig { public static class ClientConfig {
public final BooleanValue enabled; public final BooleanValue enabled;
@ -43,10 +44,10 @@ public class FlwConfig {
public ClientConfig(ForgeConfigSpec.Builder builder) { public ClientConfig(ForgeConfigSpec.Builder builder) {
enabled = builder.comment("Enable or disable the entire engine") enabled = builder.comment("Enable or disable the entire engine")
.define("enabled", true); .define("enabled", true);
normalDebug = builder.comment("Enable or disable a debug overlay that colors pixels by their normal") normalDebug = builder.comment("Enable or disable a debug overlay that colors pixels by their normal")
.define("normalDebug", false); .define("normalDebug", false);
} }
} }
} }

View file

@ -14,15 +14,15 @@ public class FlwPackets {
public static void registerPackets() { public static void registerPackets() {
channel = NetworkRegistry.ChannelBuilder.named(CHANNEL_NAME) channel = NetworkRegistry.ChannelBuilder.named(CHANNEL_NAME)
.serverAcceptedVersions(NETWORK_VERSION::equals) .serverAcceptedVersions(NETWORK_VERSION::equals)
.clientAcceptedVersions(NETWORK_VERSION::equals) .clientAcceptedVersions(NETWORK_VERSION::equals)
.networkProtocolVersion(() -> NETWORK_VERSION) .networkProtocolVersion(() -> NETWORK_VERSION)
.simpleChannel(); .simpleChannel();
channel.messageBuilder(SConfigureBooleanPacket.class, 0, NetworkDirection.PLAY_TO_CLIENT) channel.messageBuilder(SConfigureBooleanPacket.class, 0, NetworkDirection.PLAY_TO_CLIENT)
.decoder(SConfigureBooleanPacket::new) .decoder(SConfigureBooleanPacket::new)
.encoder(SConfigureBooleanPacket::encode) .encoder(SConfigureBooleanPacket::encode)
.consumer(SConfigureBooleanPacket::execute) .consumer(SConfigureBooleanPacket::execute)
.add(); .add();
} }
} }

View file

@ -1,10 +1,10 @@
package com.jozufozu.flywheel.config; package com.jozufozu.flywheel.config;
import java.util.function.Supplier;
import net.minecraft.network.PacketBuffer; import net.minecraft.network.PacketBuffer;
import net.minecraftforge.fml.network.NetworkEvent; import net.minecraftforge.fml.network.NetworkEvent;
import java.util.function.Supplier;
/** /**
* Thanks, @zelophed * Thanks, @zelophed
*/ */
@ -29,8 +29,10 @@ public class SConfigureBooleanPacket {
} }
public void execute(Supplier<NetworkEvent.Context> ctx) { public void execute(Supplier<NetworkEvent.Context> ctx) {
target.receiver.get().accept(directive); target.receiver.get()
ctx.get().setPacketHandled(true); .accept(directive);
ctx.get()
.setPacketHandled(true);
} }
} }

View file

@ -30,8 +30,7 @@ public class AtlasStitcher {
public void onTextureStitch(TextureStitchEvent.Pre event) { public void onTextureStitch(TextureStitchEvent.Pre event) {
if (!event.getMap() if (!event.getMap()
.getId() .getId()
.equals(PlayerContainer.BLOCK_ATLAS_TEXTURE)) .equals(PlayerContainer.BLOCK_ATLAS_TEXTURE)) return;
return;
sprites.forEach(StitchedSprite::reset); sprites.forEach(StitchedSprite::reset);
sprites.stream() sprites.stream()

View file

@ -13,8 +13,6 @@ import com.jozufozu.flywheel.event.GatherContextEvent;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public class Contexts { public class Contexts {
@ -31,15 +29,13 @@ public class Contexts {
SpecMetaRegistry.register(WorldFog.LINEAR); SpecMetaRegistry.register(WorldFog.LINEAR);
SpecMetaRegistry.register(WorldFog.EXP2); SpecMetaRegistry.register(WorldFog.EXP2);
CRUMBLING = backend.register(new WorldContext<>(backend, CrumblingProgram::new) CRUMBLING = backend.register(new WorldContext<>(backend, CrumblingProgram::new).withName(Names.CRUMBLING)
.withName(Names.CRUMBLING) .withBuiltin(ShaderType.FRAGMENT, Names.CRUMBLING, "/builtin.frag")
.withBuiltin(ShaderType.FRAGMENT, Names.CRUMBLING, "/builtin.frag") .withBuiltin(ShaderType.VERTEX, Names.CRUMBLING, "/builtin.vert"));
.withBuiltin(ShaderType.VERTEX, Names.CRUMBLING, "/builtin.vert"));
WORLD = backend.register(new WorldContext<>(backend, WorldProgram::new) WORLD = backend.register(new WorldContext<>(backend, WorldProgram::new).withName(Names.WORLD)
.withName(Names.WORLD) .withBuiltin(ShaderType.FRAGMENT, Names.WORLD, "/builtin.frag")
.withBuiltin(ShaderType.FRAGMENT, Names.WORLD, "/builtin.frag") .withBuiltin(ShaderType.VERTEX, Names.WORLD, "/builtin.vert"));
.withBuiltin(ShaderType.VERTEX, Names.WORLD, "/builtin.vert"));
} }
public static class Names { public static class Names {

View file

@ -9,12 +9,9 @@ public class Formats {
.addAttributes(CommonAttributes.VEC3, CommonAttributes.NORMAL, CommonAttributes.UV) .addAttributes(CommonAttributes.VEC3, CommonAttributes.NORMAL, CommonAttributes.UV)
.build(); .build();
public static final VertexFormat TRANSFORMED = litInstance() public static final VertexFormat TRANSFORMED = litInstance().addAttributes(MatrixAttributes.MAT4, MatrixAttributes.MAT3)
.addAttributes(MatrixAttributes.MAT4,
MatrixAttributes.MAT3)
.build(); .build();
public static final VertexFormat ORIENTED = litInstance() public static final VertexFormat ORIENTED = litInstance().addAttributes(CommonAttributes.VEC3, CommonAttributes.VEC3, CommonAttributes.QUATERNION)
.addAttributes(CommonAttributes.VEC3, CommonAttributes.VEC3, CommonAttributes.QUATERNION)
.build(); .build();
public static VertexFormat.Builder litInstance() { public static VertexFormat.Builder litInstance() {

View file

@ -15,14 +15,9 @@ public class FullscreenQuad {
private static final float[] vertices = { private static final float[] vertices = {
// pos // tex // pos // tex
-1.0f, -1.0f, 0.0f, 0.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, 0.0f, 1.0f,
-1.0f, -1.0f, 0.0f, 0.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f};
1.0f, -1.0f, 1.0f, 0.0f,
1.0f, 1.0f, 1.0f, 1.0f
};
private static final int bufferSize = vertices.length * 4; private static final int bufferSize = vertices.length * 4;

View file

@ -1,6 +1,5 @@
package com.jozufozu.flywheel.core; package com.jozufozu.flywheel.core;
import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.instancing.MaterialSpec; import com.jozufozu.flywheel.backend.instancing.MaterialSpec;
import com.jozufozu.flywheel.core.materials.ModelData; import com.jozufozu.flywheel.core.materials.ModelData;
import com.jozufozu.flywheel.core.materials.OrientedData; import com.jozufozu.flywheel.core.materials.OrientedData;
@ -16,8 +15,10 @@ public class Materials {
public static final MaterialSpec<ModelData> TRANSFORMED = new MaterialSpec<>(Locations.MODEL, Programs.TRANSFORMED, Formats.UNLIT_MODEL, Formats.TRANSFORMED, ModelData::new); public static final MaterialSpec<ModelData> TRANSFORMED = new MaterialSpec<>(Locations.MODEL, Programs.TRANSFORMED, Formats.UNLIT_MODEL, Formats.TRANSFORMED, ModelData::new);
public static void flwInit(GatherContextEvent event) { public static void flwInit(GatherContextEvent event) {
event.getBackend().register(ORIENTED); event.getBackend()
event.getBackend().register(TRANSFORMED); .register(ORIENTED);
event.getBackend()
.register(TRANSFORMED);
} }
public static class Locations { public static class Locations {

View file

@ -82,7 +82,8 @@ public class QuadConverter {
} }
public void free() { public void free() {
ebos.values().forEach(GlBuffer::delete); ebos.values()
.forEach(GlBuffer::delete);
ebos.clear(); ebos.clear();
initCapacities(); initCapacities();
} }
@ -100,7 +101,8 @@ public class QuadConverter {
ByteBuffer indices; ByteBuffer indices;
if (bytes > stack.getSize()) { if (bytes > stack.getSize()) {
indices = MemoryUtil.memAlloc(bytes); // not enough space on the preallocated stack indices = MemoryUtil.memAlloc(bytes); // not enough space on the preallocated stack
} else { }
else {
stack.push(); stack.push();
indices = stack.malloc(bytes); indices = stack.malloc(bytes);
} }
@ -117,7 +119,8 @@ public class QuadConverter {
if (bytes > stack.getSize()) { if (bytes > stack.getSize()) {
MemoryUtil.memFree(indices); MemoryUtil.memFree(indices);
} else { }
else {
stack.pop(); stack.pop();
} }

View file

@ -102,8 +102,7 @@ public class WorldContext<P extends WorldProgram> extends ShaderContext<P> {
} }
template = templateFactory.create(backend.sources); template = templateFactory.create(backend.sources);
transformer = new ShaderTransformer() transformer = new ShaderTransformer().pushStage(this::injectBuiltins)
.pushStage(this::injectBuiltins)
.pushStage(Shader::processIncludes) .pushStage(Shader::processIncludes)
.pushStage(template) .pushStage(template)
.pushStage(Shader::processIncludes); .pushStage(Shader::processIncludes);
@ -150,8 +149,7 @@ public class WorldContext<P extends WorldProgram> extends ShaderContext<P> {
public void injectBuiltins(Shader shader) { public void injectBuiltins(Shader shader) {
Matcher matcher = builtinPattern.matcher(shader.getSource()); Matcher matcher = builtinPattern.matcher(shader.getSource());
if (matcher.find()) if (matcher.find()) shader.setSource(matcher.replaceFirst(builtinSources.get(shader.type)));
shader.setSource(matcher.replaceFirst(builtinSources.get(shader.type)));
else else
throw new ShaderLoadingException(String.format("%s is missing %s, cannot use in World Context", shader.type.name, declaration)); throw new ShaderLoadingException(String.format("%s is missing %s, cannot use in World Context", shader.type.name, declaration));
} }

View file

@ -38,7 +38,8 @@ public class ConditionalInstance<D extends InstanceData> {
if (shouldShow && instance == null) { if (shouldShow && instance == null) {
instance = model.createInstance(); instance = model.createInstance();
if (setupFunc != null) setupFunc.accept(instance); if (setupFunc != null) setupFunc.accept(instance);
} else if (!shouldShow && instance != null) { }
else if (!shouldShow && instance != null) {
instance.delete(); instance.delete();
instance = null; instance = null;
} }

View file

@ -46,7 +46,8 @@ public class GroupInstance<D extends InstanceData> extends AbstractCollection<D>
for (int i = size; i < count; i++) { for (int i = size; i < count; i++) {
addInstance(); addInstance();
} }
} else { }
else {
List<D> unnecessary = backing.subList(count, size); List<D> unnecessary = backing.subList(count, size);
unnecessary.forEach(InstanceData::delete); unnecessary.forEach(InstanceData::delete);
unnecessary.clear(); unnecessary.clear();

View file

@ -37,10 +37,12 @@ public class SelectInstance<D extends InstanceData> {
current.delete(); current.delete();
current = null; current = null;
} }
} else if (i != last) { }
else if (i != last) {
if (current != null) current.delete(); if (current != null) current.delete();
current = models.get(i).createInstance(); current = models.get(i)
.createInstance();
} }
last = i; last = i;

View file

@ -44,7 +44,8 @@ public abstract class BasicData extends InstanceData implements IFlatLight<Basic
if (alpha) { if (alpha) {
byte a = (byte) ((color >> 24) & 0xFF); byte a = (byte) ((color >> 24) & 0xFF);
return setColor(r, g, b, a); return setColor(r, g, b, a);
} else { }
else {
return setColor(r, g, b); return setColor(r, g, b);
} }
} }

View file

@ -82,18 +82,7 @@ public class OrientedData extends BasicData {
public void write(MappedBuffer buf) { public void write(MappedBuffer buf) {
super.write(buf); super.write(buf);
buf.putFloatArray(new float[]{ buf.putFloatArray(new float[]{posX, posY, posZ, pivotX, pivotY, pivotZ, qX, qY, qZ, qW});
posX,
posY,
posZ,
pivotX,
pivotY,
pivotZ,
qX,
qY,
qZ,
qW
});
} }
} }

View file

@ -35,7 +35,8 @@ public class ExtensibleGlProgram extends GlProgram {
list.add(extension); list.add(extension);
} }
this.extensions = list; this.extensions = list;
} else { }
else {
this.extensions = Collections.emptyList(); this.extensions = Collections.emptyList();
} }
} }
@ -51,12 +52,12 @@ public class ExtensibleGlProgram extends GlProgram {
public String toString() { public String toString() {
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
builder.append("program ") builder.append("program ")
.append(name) .append(name)
.append('['); .append('[');
for (IExtensionInstance extension : extensions) { for (IExtensionInstance extension : extensions) {
builder.append(extension) builder.append(extension)
.append('+'); .append('+');
} }
builder.append(']'); builder.append(']');

View file

@ -35,13 +35,13 @@ public class GlFog {
int mode = getFogModeGlEnum(); int mode = getFogModeGlEnum();
switch (mode) { switch (mode) {
case GL11.GL_EXP2: case GL11.GL_EXP2:
case GL11.GL_EXP: case GL11.GL_EXP:
return WorldFog.EXP2; return WorldFog.EXP2;
case GL11.GL_LINEAR: case GL11.GL_LINEAR:
return WorldFog.LINEAR; return WorldFog.LINEAR;
default: default:
throw new UnsupportedOperationException("Unknown fog mode: " + mode); throw new UnsupportedOperationException("Unknown fog mode: " + mode);
} }
} }
} }

View file

@ -34,8 +34,8 @@ public class StateSensitiveMultiProgram<P extends GlProgram> implements IMultiPr
@Override @Override
public P get() { public P get() {
for (Pair<IContextCondition, P> variant : variants) { for (Pair<IContextCondition, P> variant : variants) {
if (variant.getFirst().get()) if (variant.getFirst()
return variant.getSecond(); .get()) return variant.getSecond();
} }
return fallback; return fallback;
@ -44,7 +44,8 @@ public class StateSensitiveMultiProgram<P extends GlProgram> implements IMultiPr
@Override @Override
public void delete() { public void delete() {
for (Pair<IContextCondition, P> variant : variants) { for (Pair<IContextCondition, P> variant : variants) {
variant.getSecond().delete(); variant.getSecond()
.delete();
} }
fallback.delete(); fallback.delete();

View file

@ -7,8 +7,8 @@ import java.util.List;
import com.jozufozu.flywheel.backend.loading.Program; import com.jozufozu.flywheel.backend.loading.Program;
import com.jozufozu.flywheel.core.shader.extension.IProgramExtension; import com.jozufozu.flywheel.core.shader.extension.IProgramExtension;
import com.jozufozu.flywheel.util.AnimationTickHolder; import com.jozufozu.flywheel.util.AnimationTickHolder;
import net.minecraft.util.math.vector.Matrix4f; import net.minecraft.util.math.vector.Matrix4f;
public class WorldProgram extends ExtensibleGlProgram { public class WorldProgram extends ExtensibleGlProgram {

View file

@ -9,7 +9,8 @@ public class UnitExtensionInstance implements IExtensionInstance {
public static final ResourceLocation NAME = new ResourceLocation(Flywheel.ID, "unit"); public static final ResourceLocation NAME = new ResourceLocation(Flywheel.ID, "unit");
public UnitExtensionInstance(GlProgram program) { } public UnitExtensionInstance(GlProgram program) {
}
@Override @Override
public void bind() { public void bind() {

View file

@ -17,7 +17,8 @@ public class NormalDebugStateProvider implements IBooleanStateProvider {
@Override @Override
public boolean isTrue() { public boolean isTrue() {
return FlwConfig.get().normalOverlayEnabled(); return FlwConfig.get()
.normalOverlayEnabled();
} }
@Override @Override

View file

@ -12,16 +12,12 @@ import net.minecraft.util.ResourceLocation;
public class ProgramSpec { public class ProgramSpec {
// TODO: Block model style inheritance? // TODO: Block model style inheritance?
public static final Codec<ProgramSpec> CODEC = RecordCodecBuilder.create(instance -> public static final Codec<ProgramSpec> CODEC = RecordCodecBuilder.create(instance -> instance.group(ResourceLocation.CODEC.fieldOf("vert")
instance.group( .forGetter(ProgramSpec::getVert), ResourceLocation.CODEC.fieldOf("frag")
ResourceLocation.CODEC.fieldOf("vert") .forGetter(ProgramSpec::getFrag), ProgramState.CODEC.listOf()
.forGetter(ProgramSpec::getVert), .optionalFieldOf("states", Collections.emptyList())
ResourceLocation.CODEC.fieldOf("frag") .forGetter(ProgramSpec::getStates))
.forGetter(ProgramSpec::getFrag), .apply(instance, ProgramSpec::new));
ProgramState.CODEC.listOf()
.optionalFieldOf("states", Collections.emptyList())
.forGetter(ProgramSpec::getStates)
).apply(instance, ProgramSpec::new));
public ResourceLocation name; public ResourceLocation name;
public final ResourceLocation vert; public final ResourceLocation vert;

View file

@ -13,35 +13,26 @@ import com.mojang.serialization.codecs.RecordCodecBuilder;
public class ProgramState { public class ProgramState {
// TODO: Use Codec.dispatch // TODO: Use Codec.dispatch
private static final Codec<IContextCondition> WHEN = Codec.either( private static final Codec<IContextCondition> WHEN = Codec.either(BooleanContextCondition.BOOLEAN_SUGAR, SpecificValueCondition.CODEC)
BooleanContextCondition.BOOLEAN_SUGAR, .flatXmap(either -> either.map(DataResult::success, DataResult::success), any -> {
SpecificValueCondition.CODEC if (any instanceof BooleanContextCondition) {
).flatXmap( return DataResult.success(Either.left((BooleanContextCondition) any));
either -> either.map(DataResult::success, DataResult::success), }
any -> {
if (any instanceof BooleanContextCondition) {
return DataResult.success(Either.left((BooleanContextCondition) any));
}
if (any instanceof SpecificValueCondition) { if (any instanceof SpecificValueCondition) {
return DataResult.success(Either.right((SpecificValueCondition) any)); return DataResult.success(Either.right((SpecificValueCondition) any));
} }
return DataResult.error("unknown context condition"); return DataResult.error("unknown context condition");
} });
);
public static final Codec<ProgramState> CODEC = RecordCodecBuilder.create(state -> public static final Codec<ProgramState> CODEC = RecordCodecBuilder.create(state -> state.group(WHEN.fieldOf("when")
state.group( .forGetter(ProgramState::getContext), CodecUtil.oneOrMore(Codec.STRING)
WHEN.fieldOf("when") .optionalFieldOf("define", Collections.emptyList())
.forGetter(ProgramState::getContext), .forGetter(ProgramState::getDefines), CodecUtil.oneOrMore(IProgramExtension.CODEC)
CodecUtil.oneOrMore(Codec.STRING) .optionalFieldOf("extend", Collections.emptyList())
.optionalFieldOf("define", Collections.emptyList()) .forGetter(ProgramState::getExtensions))
.forGetter(ProgramState::getDefines), .apply(state, ProgramState::new));
CodecUtil.oneOrMore(IProgramExtension.CODEC)
.optionalFieldOf("extend", Collections.emptyList())
.forGetter(ProgramState::getExtensions)
).apply(state, ProgramState::new));
private final IContextCondition context; private final IContextCondition context;
private final List<String> defines; private final List<String> defines;

View file

@ -8,10 +8,10 @@ import net.minecraft.util.ResourceLocation;
public class SpecificValueCondition implements IContextCondition { public class SpecificValueCondition implements IContextCondition {
public static final Codec<SpecificValueCondition> CODEC = RecordCodecBuilder.create(condition -> condition.group( public static final Codec<SpecificValueCondition> CODEC = RecordCodecBuilder.create(condition -> condition.group(IGameStateProvider.CODEC.fieldOf("provider")
IGameStateProvider.CODEC.fieldOf("provider").forGetter(SpecificValueCondition::contextProvider), .forGetter(SpecificValueCondition::contextProvider), Codec.STRING.fieldOf("value")
Codec.STRING.fieldOf("value").forGetter(SpecificValueCondition::getValue) .forGetter(SpecificValueCondition::getValue))
).apply(condition, SpecificValueCondition::new)); .apply(condition, SpecificValueCondition::new));
private final String required; private final String required;
private final IGameStateProvider context; private final IGameStateProvider context;
@ -37,6 +37,7 @@ public class SpecificValueCondition implements IContextCondition {
@Override @Override
public boolean get() { public boolean get() {
return required.equals(context.getValue().toString()); return required.equals(context.getValue()
.toString());
} }
} }

View file

@ -13,15 +13,13 @@ public class EntityWorldHandler {
@SubscribeEvent @SubscribeEvent
public static void onEntityJoinWorld(EntityJoinWorldEvent event) { public static void onEntityJoinWorld(EntityJoinWorldEvent event) {
if (event.getWorld().isRemote) if (event.getWorld().isRemote) InstancedRenderDispatcher.getEntities(event.getWorld())
InstancedRenderDispatcher.getEntities(event.getWorld()) .queueAdd(event.getEntity());
.queueAdd(event.getEntity());
} }
@SubscribeEvent @SubscribeEvent
public static void onEntityLeaveWorld(EntityLeaveWorldEvent event) { public static void onEntityLeaveWorld(EntityLeaveWorldEvent event) {
if (event.getWorld().isRemote) if (event.getWorld().isRemote) InstancedRenderDispatcher.getEntities(event.getWorld())
InstancedRenderDispatcher.getEntities(event.getWorld()) .remove(event.getEntity());
.remove(event.getEntity());
} }
} }

View file

@ -24,11 +24,13 @@ public class ForgeEvents {
ArrayList<String> right = event.getRight(); ArrayList<String> right = event.getRight();
String text = "Flywheel: " + Backend.getInstance().getBackendDescriptor(); String text = "Flywheel: " + Backend.getInstance()
.getBackendDescriptor();
if (right.size() < 10) { if (right.size() < 10) {
right.add(""); right.add("");
right.add(text); right.add(text);
} else { }
else {
right.add(9, ""); right.add(9, "");
right.add(10, text); right.add(10, text);
} }

View file

@ -46,32 +46,17 @@ public class GridAlignedBB {
} }
public static GridAlignedBB from(SectionPos pos) { public static GridAlignedBB from(SectionPos pos) {
return new GridAlignedBB(pos.getWorldStartX(), return new GridAlignedBB(pos.getWorldStartX(), pos.getWorldStartY(), pos.getWorldStartZ(), pos.getWorldEndX() + 1, pos.getWorldEndY() + 1, pos.getWorldEndZ() + 1);
pos.getWorldStartY(),
pos.getWorldStartZ(),
pos.getWorldEndX() + 1,
pos.getWorldEndY() + 1,
pos.getWorldEndZ() + 1);
} }
public static GridAlignedBB from(BlockPos start, BlockPos end) { public static GridAlignedBB from(BlockPos start, BlockPos end) {
return new GridAlignedBB(start.getX(), return new GridAlignedBB(start.getX(), start.getY(), start.getZ(), end.getX() + 1, end.getY() + 1, end.getZ() + 1);
start.getY(),
start.getZ(),
end.getX() + 1,
end.getY() + 1,
end.getZ() + 1);
} }
public static GridAlignedBB from(int sectionX, int sectionZ) { public static GridAlignedBB from(int sectionX, int sectionZ) {
int startX = sectionX << 4; int startX = sectionX << 4;
int startZ = sectionZ << 4; int startZ = sectionZ << 4;
return new GridAlignedBB(startX, return new GridAlignedBB(startX, 0, startZ, startX + 16, 256, startZ + 16);
0,
startZ,
startX + 16,
256,
startZ + 16);
} }
public static AxisAlignedBB toAABB(GridAlignedBB bb) { public static AxisAlignedBB toAABB(GridAlignedBB bb) {
@ -83,12 +68,7 @@ public class GridAlignedBB {
} }
public boolean sameAs(GridAlignedBB other) { public boolean sameAs(GridAlignedBB other) {
return minX == other.minX && return minX == other.minX && minY == other.minY && minZ == other.minZ && maxX == other.maxX && maxY == other.maxY && maxZ == other.maxZ;
minY == other.minY &&
minZ == other.minZ &&
maxX == other.maxX &&
maxY == other.maxY &&
maxZ == other.maxZ;
} }
public void fixMinMax() { public void fixMinMax() {
@ -125,9 +105,7 @@ public class GridAlignedBB {
public boolean empty() { public boolean empty() {
// if any dimension has side length 0 this box contains no volume // if any dimension has side length 0 this box contains no volume
return minX == maxX || return minX == maxX || minY == maxY || minZ == maxZ;
minY == maxY ||
minZ == maxZ;
} }
public void translate(Vector3i by) { public void translate(Vector3i by) {
@ -144,7 +122,8 @@ public class GridAlignedBB {
} }
public void mirrorAbout(Direction.Axis axis) { public void mirrorAbout(Direction.Axis axis) {
Vector3i axisVec = Direction.getFacingFromAxis(Direction.AxisDirection.POSITIVE, axis).getDirectionVec(); Vector3i axisVec = Direction.getFacingFromAxis(Direction.AxisDirection.POSITIVE, axis)
.getDirectionVec();
int flipX = axisVec.getX() - 1; int flipX = axisVec.getX() - 1;
int flipY = axisVec.getY() - 1; int flipY = axisVec.getY() - 1;
int flipZ = axisVec.getZ() - 1; int flipZ = axisVec.getZ() - 1;
@ -267,12 +246,7 @@ public class GridAlignedBB {
} }
public boolean contains(GridAlignedBB other) { public boolean contains(GridAlignedBB other) {
return other.minX >= this.minX && return other.minX >= this.minX && other.maxX <= this.maxX && other.minY >= this.minY && other.maxY <= this.maxY && other.minZ >= this.minZ && other.maxZ <= this.maxZ;
other.maxX <= this.maxX &&
other.minY >= this.minY &&
other.maxY <= this.maxY &&
other.minZ >= this.minZ &&
other.maxZ <= this.maxZ;
} }
public boolean isContainedBy(GridAlignedBB other) { public boolean isContainedBy(GridAlignedBB other) {

View file

@ -24,8 +24,7 @@ public interface ILightUpdateListener {
default boolean onLightPacket(IBlockDisplayReader world, int chunkX, int chunkZ) { default boolean onLightPacket(IBlockDisplayReader world, int chunkX, int chunkZ) {
GridAlignedBB changedVolume = GridAlignedBB.from(chunkX, chunkZ); GridAlignedBB changedVolume = GridAlignedBB.from(chunkX, chunkZ);
if (onLightUpdate(world, LightType.BLOCK, changedVolume)) if (onLightUpdate(world, LightType.BLOCK, changedVolume)) return true;
return true;
return onLightUpdate(world, LightType.SKY, changedVolume); return onLightUpdate(world, LightType.SKY, changedVolume);
} }

View file

@ -27,8 +27,7 @@ public class LightUpdater {
private static LightUpdater instance; private static LightUpdater instance;
public static LightUpdater getInstance() { public static LightUpdater getInstance() {
if (instance == null) if (instance == null) instance = new LightUpdater();
instance = new LightUpdater();
return instance; return instance;
} }
@ -151,7 +150,8 @@ public class LightUpdater {
if (set == null) { if (set == null) {
set = new LongRBTreeSet(); set = new LongRBTreeSet();
listeners.put(listener, set); listeners.put(listener, set);
} else { }
else {
set.forEach((LongConsumer) l -> { set.forEach((LongConsumer) l -> {
WeakHashSet<ILightUpdateListener> listeningSections = lookup.get(l); WeakHashSet<ILightUpdateListener> listeningSections = lookup.get(l);

View file

@ -126,11 +126,13 @@ public class LightVolume {
sampleVolume = newSampleVolume; sampleVolume = newSampleVolume;
copyLight(world, newArea); copyLight(world, newArea);
} else { }
else {
sampleVolume = newSampleVolume; sampleVolume = newSampleVolume;
initialize(world); initialize(world);
} }
} else { }
else {
setSampleVolume(newSampleVolume); setSampleVolume(newSampleVolume);
int volume = textureVolume.volume(); int volume = textureVolume.volume();
if (volume * 2 > lightData.capacity()) { if (volume * 2 > lightData.capacity()) {
@ -141,11 +143,9 @@ public class LightVolume {
} }
public void notifyLightUpdate(IBlockDisplayReader world, LightType type, GridAlignedBB changedVolume) { public void notifyLightUpdate(IBlockDisplayReader world, LightType type, GridAlignedBB changedVolume) {
if (removed) if (removed) return;
return;
if (!changedVolume.intersects(sampleVolume)) if (!changedVolume.intersects(sampleVolume)) return;
return;
changedVolume = changedVolume.intersect(sampleVolume); // compute the region contained by us that has dirty lighting data. changedVolume = changedVolume.intersect(sampleVolume); // compute the region contained by us that has dirty lighting data.
if (type == LightType.BLOCK) copyBlock(world, changedVolume); if (type == LightType.BLOCK) copyBlock(world, changedVolume);
@ -156,8 +156,7 @@ public class LightVolume {
if (removed) return; if (removed) return;
GridAlignedBB changedVolume = GridAlignedBB.from(chunkX, chunkZ); GridAlignedBB changedVolume = GridAlignedBB.from(chunkX, chunkZ);
if (!changedVolume.intersects(sampleVolume)) if (!changedVolume.intersects(sampleVolume)) return;
return;
changedVolume.intersectAssign(sampleVolume); // compute the region contained by us that has dirty lighting data. changedVolume.intersectAssign(sampleVolume); // compute the region contained by us that has dirty lighting data.
copyLight(world, changedVolume); copyLight(world, changedVolume);

View file

@ -24,7 +24,8 @@ public class CancelEntityRenderMixin {
@Redirect(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/world/ClientWorld;getAllEntities()Ljava/lang/Iterable;")) @Redirect(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/world/ClientWorld;getAllEntities()Ljava/lang/Iterable;"))
private Iterable<Entity> filterEntities(ClientWorld world) { private Iterable<Entity> filterEntities(ClientWorld world) {
Iterable<Entity> entities = world.getAllEntities(); Iterable<Entity> entities = world.getAllEntities();
if (Backend.getInstance().canUseInstancing()) { if (Backend.getInstance()
.canUseInstancing()) {
ArrayList<Entity> filtered = Lists.newArrayList(entities); ArrayList<Entity> filtered = Lists.newArrayList(entities);
filtered.removeIf(entity -> entity instanceof IInstanceRendered && !((IInstanceRendered) entity).shouldRenderNormally()); filtered.removeIf(entity -> entity instanceof IInstanceRendered && !((IInstanceRendered) entity).shouldRenderNormally());
@ -37,7 +38,8 @@ public class CancelEntityRenderMixin {
@Group(name = "entityFilter") @Group(name = "entityFilter")
@Redirect(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/ClassInheritanceMultiMap;iterator()Ljava/util/Iterator;")) @Redirect(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/ClassInheritanceMultiMap;iterator()Ljava/util/Iterator;"))
private Iterator<Entity> filterEntitiesOF(ClassInheritanceMultiMap<Entity> classInheritanceMultiMap) { private Iterator<Entity> filterEntitiesOF(ClassInheritanceMultiMap<Entity> classInheritanceMultiMap) {
if (Backend.getInstance().canUseInstancing()) { if (Backend.getInstance()
.canUseInstancing()) {
ArrayList<Entity> filtered = Lists.newArrayList(classInheritanceMultiMap); ArrayList<Entity> filtered = Lists.newArrayList(classInheritanceMultiMap);
filtered.removeIf(entity -> entity instanceof IInstanceRendered && !((IInstanceRendered) entity).shouldRenderNormally()); filtered.removeIf(entity -> entity instanceof IInstanceRendered && !((IInstanceRendered) entity).shouldRenderNormally());

View file

@ -27,7 +27,8 @@ public class CancelTileEntityRenderMixin {
*/ */
@Inject(at = @At("RETURN"), method = "getTileEntities", cancellable = true) @Inject(at = @At("RETURN"), method = "getTileEntities", cancellable = true)
private void noRenderInstancedTiles(CallbackInfoReturnable<List<TileEntity>> cir) { private void noRenderInstancedTiles(CallbackInfoReturnable<List<TileEntity>> cir) {
if (Backend.getInstance().canUseInstancing()) { if (Backend.getInstance()
.canUseInstancing()) {
List<TileEntity> tiles = cir.getReturnValue(); List<TileEntity> tiles = cir.getReturnValue();
tiles.removeIf(tile -> tile instanceof IInstanceRendered && !((IInstanceRendered) tile).shouldRenderNormally()); tiles.removeIf(tile -> tile instanceof IInstanceRendered && !((IInstanceRendered) tile).shouldRenderNormally());

View file

@ -1,5 +1,10 @@
package com.jozufozu.flywheel.mixin; package com.jozufozu.flywheel.mixin;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.platform.GlStateManager;
@ -11,11 +16,6 @@ import net.minecraft.util.math.vector.Matrix4f;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
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;
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
@Mixin(WorldRenderer.class) @Mixin(WorldRenderer.class)
public class FixFabulousDepthMixin { public class FixFabulousDepthMixin {

View file

@ -1,5 +1,7 @@
package com.jozufozu.flywheel.mixin; package com.jozufozu.flywheel.mixin;
import com.jozufozu.flywheel.backend.OptifineHandler;
import org.lwjgl.opengl.GL20; import org.lwjgl.opengl.GL20;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
@ -36,9 +38,7 @@ public class RenderHooksMixin {
private ClientWorld world; private ClientWorld world;
@Inject(at = @At(value = "INVOKE", target = "net.minecraft.client.renderer.WorldRenderer.updateChunks(J)V"), method = "render") @Inject(at = @At(value = "INVOKE", target = "net.minecraft.client.renderer.WorldRenderer.updateChunks(J)V"), method = "render")
private void setupFrame(MatrixStack stack, float p_228426_2_, long p_228426_3_, boolean p_228426_5_, private void setupFrame(MatrixStack stack, float p_228426_2_, long p_228426_3_, boolean p_228426_5_, ActiveRenderInfo info, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f p_228426_9_, CallbackInfo ci) {
ActiveRenderInfo info, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f p_228426_9_,
CallbackInfo ci) {
MinecraftForge.EVENT_BUS.post(new BeginFrameEvent(world, stack, info, gameRenderer, lightTexture)); MinecraftForge.EVENT_BUS.post(new BeginFrameEvent(world, stack, info, gameRenderer, lightTexture));
} }
@ -48,12 +48,12 @@ public class RenderHooksMixin {
* This should probably be a forge event. * This should probably be a forge event.
*/ */
@Inject(at = @At("TAIL"), method = "renderLayer") @Inject(at = @At("TAIL"), method = "renderLayer")
private void renderLayer(RenderType type, MatrixStack stack, double camX, double camY, double camZ, private void renderLayer(RenderType type, MatrixStack stack, double camX, double camY, double camZ, CallbackInfo ci) {
CallbackInfo ci) {
Matrix4f view = stack.peek() Matrix4f view = stack.peek()
.getModel(); .getModel();
Matrix4f viewProjection = view.copy(); Matrix4f viewProjection = view.copy();
viewProjection.multiplyBackward(Backend.getInstance().getProjectionMatrix()); viewProjection.multiplyBackward(Backend.getInstance()
.getProjectionMatrix());
MinecraftForge.EVENT_BUS.post(new RenderLayerEvent(world, type, viewProjection, camX, camY, camZ)); MinecraftForge.EVENT_BUS.post(new RenderLayerEvent(world, type, viewProjection, camX, camY, camZ));
GL20.glUseProgram(0); GL20.glUseProgram(0);
@ -61,33 +61,30 @@ public class RenderHooksMixin {
@Inject(at = @At("TAIL"), method = "loadRenderers") @Inject(at = @At("TAIL"), method = "loadRenderers")
private void refresh(CallbackInfo ci) { private void refresh(CallbackInfo ci) {
Backend.getInstance().refresh(); Backend.getInstance()
.refresh();
MinecraftForge.EVENT_BUS.post(new ReloadRenderersEvent(world)); MinecraftForge.EVENT_BUS.post(new ReloadRenderersEvent(world));
} }
@Inject(at = @Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/WorldRenderer;checkEmpty(Lcom/mojang/blaze3d/matrix/MatrixStack;)V", ordinal = 2 // after the game renders the breaking overlay normally
@At( ), method = "render")
value = "INVOKE", private void renderBlockBreaking(MatrixStack stack, float p_228426_2_, long p_228426_3_, boolean p_228426_5_, ActiveRenderInfo info, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f p_228426_9_, CallbackInfo ci) {
target = "Lnet/minecraft/client/renderer/WorldRenderer;checkEmpty(Lcom/mojang/blaze3d/matrix/MatrixStack;)V", if (!Backend.getInstance()
ordinal = 2 // after the game renders the breaking overlay normally .available()) return;
),
method = "render")
private void renderBlockBreaking(MatrixStack stack, float p_228426_2_, long p_228426_3_, boolean p_228426_5_,
ActiveRenderInfo info, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f p_228426_9_,
CallbackInfo ci) {
if (!Backend.getInstance().available())
return;
Matrix4f view = stack.peek() Matrix4f view = stack.peek()
.getModel(); .getModel();
Matrix4f viewProjection = view.copy(); Matrix4f viewProjection = view.copy();
viewProjection.multiplyBackward(Backend.getInstance().getProjectionMatrix()); viewProjection.multiplyBackward(Backend.getInstance()
.getProjectionMatrix());
Vector3d cameraPos = info.getProjectedView(); Vector3d cameraPos = info.getProjectedView();
InstancedRenderDispatcher.renderBreaking(world, viewProjection, cameraPos.x, cameraPos.y, cameraPos.z); InstancedRenderDispatcher.renderBreaking(world, viewProjection, cameraPos.x, cameraPos.y, cameraPos.z);
GL20.glUseProgram(0);
if (!OptifineHandler.usingShaders())
GL20.glUseProgram(0);
} }
// Instancing // Instancing

View file

@ -26,8 +26,8 @@ public class ShaderCloseMixin {
if (OptifineHandler.optifineInstalled() && screen instanceof VideoSettingsScreen) { if (OptifineHandler.optifineInstalled() && screen instanceof VideoSettingsScreen) {
Screen old = this.currentScreen; Screen old = this.currentScreen;
if (old != null && old.getClass() if (old != null && old.getClass()
.getName() .getName()
.startsWith(OptifineHandler.SHADER_PACKAGE)) { .startsWith(OptifineHandler.SHADER_PACKAGE)) {
OptifineHandler.refresh(); OptifineHandler.refresh();
} }
} }

View file

@ -30,7 +30,8 @@ public abstract class StoreProjectionMatrixMixin {
@Inject(method = "loadProjectionMatrix", at = @At("TAIL")) @Inject(method = "loadProjectionMatrix", at = @At("TAIL"))
private void onProjectionMatrixLoad(Matrix4f projection, CallbackInfo ci) { private void onProjectionMatrixLoad(Matrix4f projection, CallbackInfo ci) {
if (shouldCopy) { if (shouldCopy) {
Backend.getInstance().setProjectionMatrix(projection.copy()); Backend.getInstance()
.setProjectionMatrix(projection.copy());
shouldCopy = false; shouldCopy = false;
} }
} }

View file

@ -23,8 +23,7 @@ public class TileRemoveMixin {
@Inject(at = @At("TAIL"), method = "remove") @Inject(at = @At("TAIL"), method = "remove")
private void onRemove(CallbackInfo ci) { private void onRemove(CallbackInfo ci) {
if (world instanceof ClientWorld) if (world instanceof ClientWorld) InstancedRenderDispatcher.getTiles(this.world)
InstancedRenderDispatcher.getTiles(this.world) .remove((TileEntity) (Object) this);
.remove((TileEntity) (Object) this);
} }
} }

View file

@ -43,16 +43,15 @@ public abstract class LightUpdateMixin extends AbstractChunkProvider {
.entrySet() .entrySet()
.stream() .stream()
.filter(entry -> SectionPos.toChunk(entry.getKey() .filter(entry -> SectionPos.toChunk(entry.getKey()
.getY()) == sectionY) .getY()) == sectionY)
.map(Map.Entry::getValue) .map(Map.Entry::getValue)
.forEach(InstancedRenderDispatcher.getTiles(world)::onLightUpdate); .forEach(InstancedRenderDispatcher.getTiles(world)::onLightUpdate);
if (sectionY >= 0) // TODO: 1.17 if (sectionY >= 0) // TODO: 1.17
chunk.getEntityLists()[sectionY] chunk.getEntityLists()[sectionY].forEach(InstancedRenderDispatcher.getEntities(world)::onLightUpdate);
.forEach(InstancedRenderDispatcher.getEntities(world)::onLightUpdate);
} }
LightUpdater.getInstance() LightUpdater.getInstance()
.onLightUpdate(world, type, pos.asLong()); .onLightUpdate(world, type, pos.asLong());
} }
} }

View file

@ -26,14 +26,13 @@ public class NetworkLightUpdateMixin {
RenderWork.enqueue(() -> { RenderWork.enqueue(() -> {
ClientWorld world = Minecraft.getInstance().world; ClientWorld world = Minecraft.getInstance().world;
if (world == null) if (world == null) return;
return;
int chunkX = packet.getChunkX(); int chunkX = packet.getChunkX();
int chunkZ = packet.getChunkZ(); int chunkZ = packet.getChunkZ();
Chunk chunk = world.getChunkProvider() Chunk chunk = world.getChunkProvider()
.getChunk(chunkX, chunkZ, false); .getChunk(chunkX, chunkZ, false);
if (chunk != null) { if (chunk != null) {
chunk.getTileEntityMap() chunk.getTileEntityMap()
@ -46,7 +45,7 @@ public class NetworkLightUpdateMixin {
} }
LightUpdater.getInstance() LightUpdater.getInstance()
.onLightPacket(world, chunkX, chunkZ); .onLightPacket(world, chunkX, chunkZ);
}); });
} }
} }

View file

@ -10,8 +10,7 @@ public class AngleHelper {
*/ */
public static float horizontalAngle(Direction facing) { public static float horizontalAngle(Direction facing) {
float angle = facing.getHorizontalAngle(); float angle = facing.getHorizontalAngle();
if (facing.getAxis() == Axis.X) if (facing.getAxis() == Axis.X) angle = -angle;
angle = -angle;
return angle; return angle;
} }
@ -19,12 +18,12 @@ public class AngleHelper {
* Same as {@link #horizontalAngle(Direction)}, but returns 0 instead of -90 for vertical directions. * Same as {@link #horizontalAngle(Direction)}, but returns 0 instead of -90 for vertical directions.
*/ */
public static float horizontalAngleNew(Direction facing) { public static float horizontalAngleNew(Direction facing) {
if (facing.getAxis().isVertical()) { if (facing.getAxis()
.isVertical()) {
return 0; return 0;
} }
float angle = facing.getHorizontalAngle(); float angle = facing.getHorizontalAngle();
if (facing.getAxis() == Axis.X) if (facing.getAxis() == Axis.X) angle = -angle;
angle = -angle;
return angle; return angle;
} }
@ -33,14 +32,12 @@ public class AngleHelper {
} }
public static float rad(double angle) { public static float rad(double angle) {
if (angle == 0) if (angle == 0) return 0;
return 0;
return (float) (angle / 180 * Math.PI); return (float) (angle / 180 * Math.PI);
} }
public static float deg(double angle) { public static float deg(double angle) {
if (angle == 0) if (angle == 0) return 0;
return 0;
return (float) (angle * 180 / Math.PI); return (float) (angle * 180 / Math.PI);
} }

View file

@ -1,41 +1,41 @@
package com.jozufozu.flywheel.util; package com.jozufozu.flywheel.util;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.world.IWorld;
public class AnimationTickHolder { public class AnimationTickHolder {
private static int ticks; private static int ticks;
private static int paused_ticks; private static int paused_ticks;
public static void reset() { public static void reset() {
ticks = 0; ticks = 0;
paused_ticks = 0; paused_ticks = 0;
} }
public static void tick() { public static void tick() {
if (!Minecraft.getInstance() if (!Minecraft.getInstance()
.isGamePaused()) { .isGamePaused()) {
ticks = (ticks + 1) % 1_728_000; // wrap around every 24 hours so we maintain enough floating point precision ticks = (ticks + 1) % 1_728_000; // wrap around every 24 hours so we maintain enough floating point precision
} else { }
paused_ticks = (paused_ticks + 1) % 1_728_000; else {
} paused_ticks = (paused_ticks + 1) % 1_728_000;
} }
}
public static int getTicks() { public static int getTicks() {
return getTicks(false); return getTicks(false);
} }
public static int getTicks(boolean includePaused) { public static int getTicks(boolean includePaused) {
return includePaused ? ticks + paused_ticks : ticks; return includePaused ? ticks + paused_ticks : ticks;
} }
public static float getRenderTime() { public static float getRenderTime() {
return getTicks() + getPartialTicks(); return getTicks() + getPartialTicks();
} }
public static float getPartialTicks() { public static float getPartialTicks() {
Minecraft mc = Minecraft.getInstance(); Minecraft mc = Minecraft.getInstance();
return (mc.isGamePaused() ? mc.renderPartialTicksPaused : mc.getRenderPartialTicks()); return (mc.isGamePaused() ? mc.renderPartialTicksPaused : mc.getRenderPartialTicks());
} }
} }

View file

@ -194,20 +194,26 @@ public class BakedQuadWrapper {
public void refresh() { public void refresh() {
vertexSize = FORMAT.getIntegerSize(); vertexSize = FORMAT.getIntegerSize();
for (int elementId = 0; elementId < FORMAT.getElements().size(); elementId++) { for (int elementId = 0; elementId < FORMAT.getElements()
VertexFormatElement element = FORMAT.getElements().get(elementId); .size(); elementId++) {
VertexFormatElement element = FORMAT.getElements()
.get(elementId);
int intOffset = FORMAT.getOffset(elementId) / Integer.BYTES; int intOffset = FORMAT.getOffset(elementId) / Integer.BYTES;
if (element.getUsage() == VertexFormatElement.Usage.POSITION) { if (element.getUsage() == VertexFormatElement.Usage.POSITION) {
position = intOffset; position = intOffset;
} else if (element.getUsage() == VertexFormatElement.Usage.COLOR) { }
else if (element.getUsage() == VertexFormatElement.Usage.COLOR) {
color = intOffset; color = intOffset;
} else if (element.getUsage() == VertexFormatElement.Usage.UV) { }
else if (element.getUsage() == VertexFormatElement.Usage.UV) {
if (element.getIndex() == 0) { if (element.getIndex() == 0) {
texture = intOffset; texture = intOffset;
} else if (element.getIndex() == 2) { }
else if (element.getIndex() == 2) {
light = intOffset; light = intOffset;
} }
} else if (element.getUsage() == VertexFormatElement.Usage.NORMAL) { }
else if (element.getUsage() == VertexFormatElement.Usage.NORMAL) {
normal = intOffset; normal = intOffset;
} }
} }

View file

@ -27,13 +27,13 @@ public class BufferBuilderReader {
size = vertexCount * formatSize; size = vertexCount * formatSize;
// TODO: adjust the getters based on the input format // TODO: adjust the getters based on the input format
// ImmutableList<VertexFormatElement> elements = vertexFormat.getElements(); // ImmutableList<VertexFormatElement> elements = vertexFormat.getElements();
// for (int i = 0, size = elements.size(); i < size; i++) { // for (int i = 0, size = elements.size(); i < size; i++) {
// VertexFormatElement element = elements.get(i); // VertexFormatElement element = elements.get(i);
// int offset = vertexFormat.getOffset(i); // int offset = vertexFormat.getOffset(i);
// //
// element.getUsage() // element.getUsage()
// } // }
} }
public boolean isEmpty() { public boolean isEmpty() {

View file

@ -13,14 +13,13 @@ public class CodecUtil {
*/ */
public static <T> Codec<List<T>> oneOrMore(Codec<T> codec) { public static <T> Codec<List<T>> oneOrMore(Codec<T> codec) {
return Codec.either(codec.listOf(), codec) return Codec.either(codec.listOf(), codec)
.xmap( .xmap(either -> either.map(l -> l, Collections::singletonList), list -> {
either -> either.map(l -> l, Collections::singletonList), if (list.size() == 1) {
list -> { return Either.right(list.get(0));
if (list.size() == 1) { }
return Either.right(list.get(0)); else {
} else { return Either.left(list);
return Either.left(list); }
} });
});
} }
} }

View file

@ -38,8 +38,7 @@ public class Pair<F, S> {
@Override @Override
public boolean equals(final Object obj) { public boolean equals(final Object obj) {
if (obj == this) if (obj == this) return true;
return true;
if (obj instanceof Pair) { if (obj instanceof Pair) {
final Pair<?, ?> other = (Pair<?, ?>) obj; final Pair<?, ?> other = (Pair<?, ?>) obj;
return Objects.equals(first, other.first) && Objects.equals(second, other.second); return Objects.equals(first, other.first) && Objects.equals(second, other.second);

View file

@ -29,70 +29,31 @@ public class RenderUtil {
} }
public static float[] writeMatrixStack(MatrixStack stack) { public static float[] writeMatrixStack(MatrixStack stack) {
return writeMatrixStack(stack.peek().getModel(), stack.peek().getNormal()); return writeMatrixStack(stack.peek()
.getModel(), stack.peek()
.getNormal());
} }
// GPUs want matrices in column major order. // GPUs want matrices in column major order.
public static float[] writeMatrixStack(Matrix4f model, Matrix3f normal) { public static float[] writeMatrixStack(Matrix4f model, Matrix3f normal) {
return new float[]{ return new float[]{model.a00, model.a10, model.a20, model.a30, model.a01, model.a11, model.a21, model.a31, model.a02, model.a12, model.a22, model.a32, model.a03, model.a13, model.a23, model.a33, normal.a00, normal.a10, normal.a20, normal.a01, normal.a11, normal.a21, normal.a02, normal.a12, normal.a22,};
model.a00,
model.a10,
model.a20,
model.a30,
model.a01,
model.a11,
model.a21,
model.a31,
model.a02,
model.a12,
model.a22,
model.a32,
model.a03,
model.a13,
model.a23,
model.a33,
normal.a00,
normal.a10,
normal.a20,
normal.a01,
normal.a11,
normal.a21,
normal.a02,
normal.a12,
normal.a22,
};
} }
public static float[] writeMatrix(Matrix4f model) { public static float[] writeMatrix(Matrix4f model) {
return new float[]{ return new float[]{model.a00, model.a10, model.a20, model.a30, model.a01, model.a11, model.a21, model.a31, model.a02, model.a12, model.a22, model.a32, model.a03, model.a13, model.a23, model.a33,};
model.a00,
model.a10,
model.a20,
model.a30,
model.a01,
model.a11,
model.a21,
model.a31,
model.a02,
model.a12,
model.a22,
model.a32,
model.a03,
model.a13,
model.a23,
model.a33,
};
} }
public static Supplier<MatrixStack> rotateToFace(Direction facing) { public static Supplier<MatrixStack> rotateToFace(Direction facing) {
return () -> { return () -> {
MatrixStack stack = new MatrixStack(); MatrixStack stack = new MatrixStack();
// MatrixStacker.of(stack) // MatrixStacker.of(stack)
// .centre() // .centre()
// .rotateY(AngleHelper.horizontalAngle(facing)) // .rotateY(AngleHelper.horizontalAngle(facing))
// .rotateX(AngleHelper.verticalAngle(facing)) // .rotateX(AngleHelper.verticalAngle(facing))
// .unCentre(); // .unCentre();
stack.peek().getModel().setTranslation(0.5f, 0.5f, 0.5f); stack.peek()
.getModel()
.setTranslation(0.5f, 0.5f, 0.5f);
stack.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(AngleHelper.horizontalAngle(facing))); stack.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(AngleHelper.horizontalAngle(facing)));
stack.multiply(Vector3f.POSITIVE_X.getDegreesQuaternion(AngleHelper.verticalAngle(facing))); stack.multiply(Vector3f.POSITIVE_X.getDegreesQuaternion(AngleHelper.verticalAngle(facing)));
stack.translate(-0.5f, -0.5f, -0.5f); stack.translate(-0.5f, -0.5f, -0.5f);

View file

@ -57,7 +57,7 @@ public class WeakHashSet<T> extends AbstractSet<T> {
@Override @Override
public Iterator<T> iterator() { public Iterator<T> iterator() {
return map.keySet() return map.keySet()
.iterator(); .iterator();
} }
@Override @Override
@ -88,13 +88,12 @@ public class WeakHashSet<T> extends AbstractSet<T> {
@Override @Override
public Object[] toArray() { public Object[] toArray() {
return map.keySet() return map.keySet()
.toArray(); .toArray();
} }
@Override @Override
public boolean containsAll(Collection<?> c) { public boolean containsAll(Collection<?> c) {
return stream() return stream().allMatch(map::containsKey);
.allMatch(map::containsKey);
} }
@Override @Override

View file

@ -7,7 +7,6 @@ import java.util.function.Consumer;
import java.util.function.Function; import java.util.function.Function;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import net.minecraft.world.IWorld; import net.minecraft.world.IWorld;
@ -24,8 +23,7 @@ public class WorldAttached<T> {
@Nonnull @Nonnull
public T get(IWorld world) { public T get(IWorld world) {
T t = attached.get(world); T t = attached.get(world);
if (t != null) if (t != null) return t;
return t;
T entry = factory.apply(world); T entry = factory.apply(world);
put(world, entry); put(world, entry);
return entry; return entry;