Compare commits

...
Author SHA1 Message Date
boubou19 701f55b5a5 Merge branch 'master' into glparser-util 2024-11-26 12:37:26 +01:00
kurrycat 5afb5d8f5a properly integrate mcpatcherforge connected textures + better grass (#745) 2024-11-25 21:38:01 +00:00
ah-OOG-ah c353c83cf3 Backport MemoryStack to reduce direct buffer allocations (#751)
* Initial MemoryStack backport

* Remove stubs, for now

Will re-add as needed

* Implement mallocInt

* Replace some buffer allocation

* Add mallocFloat

* Replace more uses of direct buffer allocation

* Reorder methods

Fixes a clinit crash and makes it easier to compare to upstream

* Remove another direct buffer creation
2024-11-25 16:26:07 -05:00
Martin Robertz 6563c7c0ce Merge branch 'master' into glparser-util 2024-11-25 22:03:00 +01:00
Darren Eberly 78072236d2 GLSL 120 Tweaks to Iris Shader Transformation (#743) 2024-11-24 01:04:30 -05:00
Darren Eberly 52dae51121 star imports 2024-11-23 02:16:55 -05:00
Darren Eberly b42eb9a6b2 Switch to static gl_functions csv 2024-11-23 02:16:24 -05:00
Darren Eberly 5925c28d29 star import 2024-11-23 01:33:57 -05:00
Darren Eberly fedabd0fb6 Add a GLParser utility for comparing GLSM to OpenGL Spec 2024-11-23 01:24:36 -05:00
Darren Eberly 350fdcd7e4 Fix for Extra Utilities ethereal blocks with connected textures (#746) 2024-11-22 03:22:14 +00:00
Darren Eberly 3d98e57178 Gracefully handle nested display list compilations in GLSM (#744) 2024-11-21 14:26:40 -08:00
Jason Mitchell 55c1786811 Update README.MD 2024-11-21 11:13:55 -08:00
Robert 356d826387 non silly pr title [ci skip] (#728) 2024-11-21 10:56:13 -08:00
Darren Eberly c34d8548a5 Item Renderer Optimization (#741) 2024-11-20 17:22:07 -05:00
Kotmatross 81a000af75 Backport F3 crosshair directions (#740)
* Backport F3 crosshair directions

* Remove render duplicate
2024-11-20 11:02:54 -05:00
ah-OOG-ahandkurrycat 711c23c722 Add frametime and TPS graphs (#739)
* Track frametimes

* impl rest of frametime graph, missing resize to not go over middle of screen when small

* only show fps graph with alt+f3 like in modern

* Add integrated server TPS reporting

---------

Co-authored-by: kurrycat <[email protected]>
2024-11-20 05:53:24 +00:00
Jason Mitchell 5aa1d504b0 Update README.MD 2024-11-18 00:12:04 -08:00
Jason Mitchell 60ab3b7900 Null check 2024-11-17 08:21:34 -08:00
Alexdoru 912e0e83b8 fix ArrayOutOfBounds in F3 debug text handler (#736) 2024-11-16 20:25:31 -08:00
Jason Mitchell 104eda0b51 Handle more incompatible mods (#735) 2024-11-16 19:23:39 +00:00
75 changed files with 4479 additions and 401 deletions

No files matched your search

+2
View File
@@ -36,3 +36,5 @@ addon.local.gradle
addon.local.gradle.kts
addon.late.local.gradle
addon.late.local.gradle.kts
/*.csv
!gl_functions.csv
+6 -2
View File
@@ -5,8 +5,9 @@
* The little Angle [sic] that supports shaders while saving your fps from a certain death -boubou
* Is it obtuse, or accute? -Caedis
* It's a cute angle -mitchej123
* It's the angel that pulls you out of OptiFine's hell -Roadhog360
## **Beta Quality - Here there be Dragons**
## **Beta Quality - Here there be Dragons**
* Shaders sneak preview - Please don't report issues yet, but please do submit fixes
* Complementary & BSL mostly function, but have some bugs
* Sildurs, Seus, and any other shader probably doesn't work
@@ -33,10 +34,11 @@
* OptiFine [Disabled, won't fix]
* FastCraft [Disabled, won't fix]
* BetterFPS [Disabled, won't fix]
* OptimizationsAndTweaks [Disabled, won't fix]
* [Amazing Trophies 1.2.1 and below](https://github.com/GTNewHorizons/Amazing-Trophies/releases) - use 1.2.2+
* [LWJGL3ify 1.5.4 and below](https://github.com/GTNewHorizons/lwjgl3ify/releases/) - Use the latest version available, 1.5.7+
* [ArchaicFix 0.6.2 and below](https://www.curseforge.com/minecraft/mc-mods/archaicfix/files/all?page=1&pageSize=20) - Use 0.7.0 or above
* [Hodgepodge 2.4.3 and below](https://github.com/GTNewHorizons/Hodgepodge/releases) - Use 2.4.4 or above
* [Hodgepodge 2.4.3 and below](https://github.com/GTNewHorizons/Hodgepodge/releases) - Use 0.4.5 or above
* CodeChicken[Core](https://github.com/GTNewHorizons/CodeChickenCore/releases)/[Lib](https://github.com/GTNewHorizons/CodeChickenLib/releases) <1.2.0 - Threading issues, use 1.3.0+
* Neodymium - Untested, but unlikely to be compatible. (Chunk Meshing is definitely incompatible, other features might work depending on config)
@@ -78,3 +80,5 @@
* Embeddedt and Ferri_Arnus for [glsl-transformation-lib](https://github.com/TauMC/glsl-transformation-lib)
* Also for work on [Monocle](https://github.com/ferriarnus/Monocle) which was used as a reference for implementing glsl-transformation-lib
* Code from both glsl-transformation-lib and Monocle taken under their respective LGPL 3.0 licenses
* FalseTweaks
* FalsePattern for [FalseTweaks](https://github.com/falsepattern/falsetweaks) - Item Rendering Optimizations taken from FalseTweaks under the LGPL 3.0 license
+14 -10
View File
@@ -49,7 +49,7 @@ configurations {
}
dependencies {
compileOnly("com.github.GTNewHorizons:Hodgepodge:2.5.71")
compileOnly("com.github.GTNewHorizons:Hodgepodge:2.5.78")
compileOnly("com.gtnewhorizons.retrofuturabootstrap:RetroFuturaBootstrap:0.4.0") { transitive = false }
@@ -57,11 +57,11 @@ dependencies {
annotationProcessor("org.projectlombok:lombok:1.18.22")
// Use modern models+textures to inject QuadProviders
devOnlyNonPublishable('com.github.GTNewHorizons:TX-Loader:1.7.1:dev')
devOnlyNonPublishable('com.github.GTNewHorizons:TX-Loader:1.7.2:dev')
// Iris Shaders
compileOnly('org.jetbrains:annotations:24.0.1')
api("com.github.GTNewHorizons:GTNHLib:0.5.12:dev")
api("com.github.GTNewHorizons:GTNHLib:0.5.20:dev")
shadowImplementation("org.anarres:jcpp:1.4.14") // Apache 2.0
shadowImplementation("org.taumc:glsl-transformation-lib:0.2.0-4.g6b42bca") {
exclude module: "antlr4" // we only want to shadow the runtime module
@@ -70,18 +70,18 @@ dependencies {
compileOnly "org.apache.ant:ant:1.8.2"
// Because who doesn't want NEI
devOnlyNonPublishable('com.github.GTNewHorizons:NotEnoughItems:2.6.39-GTNH:dev')
devOnlyNonPublishable('com.github.GTNewHorizons:CodeChickenCore:1.3.7:dev')
devOnlyNonPublishable('com.github.GTNewHorizons:NotEnoughItems:2.6.45-GTNH:dev')
devOnlyNonPublishable('com.github.GTNewHorizons:CodeChickenCore:1.3.10:dev')
// Notfine Deps
compileOnly("thaumcraft:Thaumcraft:1.7.10-4.2.3.5:dev")
devOnlyNonPublishable("com.github.GTNewHorizons:Baubles:1.0.4:dev")
compileOnly("com.github.GTNewHorizons:twilightforest:2.6.34:dev") { transitive = false }
compileOnly("com.github.GTNewHorizons:twilightforest:2.6.35:dev") { transitive = false }
compileOnly(rfg.deobf('curse.maven:witchery-69673:2234410'))
compileOnly("com.github.GTNewHorizons:TinkersConstruct:1.12.10-GTNH:dev") { transitive = false }
compileOnly("com.github.GTNewHorizons:Natura:2.7.3:dev")
compileOnly("com.github.GTNewHorizons:TinkersConstruct:1.12.14-GTNH:dev") { transitive = false }
compileOnly("com.github.GTNewHorizons:Natura:2.7.5:dev")
compileOnly("com.github.GTNewHorizons:ThaumicHorizons:1.6.3:dev")
compileOnly("com.github.GTNewHorizons:ThaumicHorizons:1.6.4:dev")
compileOnly("com.github.GTNewHorizons:Battlegear2:1.4.1:dev") { transitive = false }
compileOnly(rfg.deobf('maven.modrinth:backhand:1.4.1')) { transitive = false }
@@ -100,7 +100,7 @@ dependencies {
compileOnly(rfg.deobf("curse.maven:campfirebackport-387444:4611675"))
compileOnly(rfg.deobf("curse.maven:xaeros-minimap-263420:5060684"))
compileOnly("com.github.GTNewHorizons:HoloInventory:2.4.12-GTNH:dev")
compileOnly("com.github.GTNewHorizons:HoloInventory:2.4.13-GTNH:dev")
runtimeOnlyNonPublishable(rfg.deobf("CoreTweaks:CoreTweaks:0.3.3.2"))
@@ -115,4 +115,8 @@ dependencies {
testImplementation('org.junit.jupiter:junit-jupiter')
testImplementation("org.mockito:mockito-core:3.+")
testImplementation("org.lwjgl.lwjgl:lwjgl:2.9.4-nightly-20150209")
devOnlyNonPublishable("com.github.javaparser:javaparser-symbol-solver-core:3.26.2") {
exclude module: "guava"
}
}
+2084
View File
File diff suppressed because it is too large. Load diff
Binary file not shown.
Vendored
+5 -2
View File
@@ -15,6 +15,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
#
##############################################################################
#
@@ -55,7 +57,7 @@
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
@@ -84,7 +86,8 @@ done
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
' "$PWD" ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
Vendored
+2
View File
@@ -13,6 +13,8 @@
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@rem SPDX-License-Identifier: Apache-2.0
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
+1 -1
View File
@@ -16,5 +16,5 @@ pluginManagement {
}
plugins {
id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.27'
id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.29'
}
+120
View File
@@ -0,0 +1,120 @@
import com.github.javaparser.StaticJavaParser;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.Node;
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
import com.github.javaparser.ast.body.MethodDeclaration;
import com.github.javaparser.ast.body.Parameter;
import com.github.javaparser.ast.visitor.VoidVisitorWithDefaults;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* Used to generate gl_functions.csv. Which contains a mapping of OpenGL functions provided by LWJGL
* corresponding to the earliest GL version they appear in.
*/
public class GLFunctionParser {
final static String glPath = "util/gl"; // Path to LWJGL OpenGL bindings source code
public static void main(String[] args) throws FileNotFoundException {
HashMap<String, Set<String>> byFunction = new HashMap<>();
File dir = new File(glPath);
for (File file : dir.listFiles()) {
final String filename = file.getName();
if (filename.endsWith(".java") && filename.startsWith("GL") && Character.isDigit(filename.charAt(2))) {
Path p = Paths.get(filename);
String parsedFile = removeFileExtension(p.getFileName().toString());
CompilationUnit cu = StaticJavaParser.parse(file);
cu.accept(new VoidVisitorWithDefaults<>() {
@Override
public void defaultAction(Node n, Object arg) {
for( Node child : n.getChildNodes()) {
if(child instanceof ClassOrInterfaceDeclaration cd) {
for (MethodDeclaration md : cd.getMethods()) {
String methodName = md.getNameAsString() + "(";
for (Parameter p : md.getParameters()) {
methodName = methodName + p.getTypeAsString();
}
methodName = methodName + ")";
if(methodName.startsWith("n")) continue;
Set<String> functionSet = byFunction.computeIfAbsent(methodName, k -> new HashSet<>());
functionSet.add(parsedFile);
}
}
}
}
}, null);
}
}
Map<String, String> functionVersionMap = new HashMap<>();
for(String function : byFunction.keySet()) {
Set<String> versionsForFunction = byFunction.get(function);
int lowestInt = 46;
String lowestString = "GL46";
for(String version : versionsForFunction) {
int i = Integer.parseInt(version.substring(2, 4));
if (i < lowestInt) {
lowestInt = i;
lowestString = version;
}
}
functionVersionMap.put(function, lowestString);
}
List<String[]> outputLines = new ArrayList<>();
for (Map.Entry<String, String> entry : functionVersionMap.entrySet()) {
outputLines.add(new String[] {entry.getKey(), entry.getValue()});
}
File output = new File("output.csv");
try (PrintWriter writer = new PrintWriter(output)) {
outputLines.stream().map(GLSMFunctionComparison::convertToCSV).forEach(writer::println);
}
}
public static String convertToCSV(String[] data) {
return Stream.of(data).map(GLSMFunctionComparison::escapeSpecialCharacters).collect(Collectors.joining(","));
}
public static String escapeSpecialCharacters(String data) {
if (data == null) {
throw new IllegalArgumentException("Input data cannot be null");
}
String escapedData = data.replaceAll("\\R", " ");
if (data.contains(",") || data.contains("\"") || data.contains("'")) {
data = data.replace("\"", "\"\"");
escapedData = "\"" + data + "\"";
}
return escapedData;
}
public static String removeFileExtension(String filename) {
if (filename == null || filename.isEmpty()) {
return filename;
}
String extPattern = "(?<!^)[.]" + "[^.]*$";
return filename.replaceAll(extPattern, "");
}
}
+135
View File
@@ -0,0 +1,135 @@
import com.github.javaparser.ParserConfiguration;
import com.github.javaparser.StaticJavaParser;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.Node;
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
import com.github.javaparser.ast.body.MethodDeclaration;
import com.github.javaparser.ast.body.Parameter;
import com.github.javaparser.ast.visitor.VoidVisitorWithDefaults;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* Used to compare OpenGL functions from gl_functions.csv to current GLStateManager
* source code to determine what functions have an implementation in GLSM, and what ones don't.
* Only considers functions which appear in GL 2.1 and lower
*/
public class GLSMFunctionComparison {
/**
* If set to true, then the outputted CSV will show functions which do have an implementation in GLSM
*/
final static boolean INCLUDE_TRUE = false;
final static String glFunctionsCsvPath = "gl_functions.csv";
final static String glsmPath = "src/main/java/com/gtnewhorizons/angelica/glsm/GLStateManager.java";
public static Map<String, String> parseGLFunctions() {
Map<String, String> map = new HashMap<>();
try (BufferedReader br = new BufferedReader(new FileReader(glFunctionsCsvPath))) {
String line;
while ((line = br.readLine()) != null) {
String[] values = line.split(",");
if (values.length == 2) {
String key = values[0].trim();
String value = values[1].trim();
int versionInt = Integer.parseInt(value.substring(2, 4));
if (versionInt < 30) map.put(key, value);
}
}
} catch (IOException e) {
e.printStackTrace();
}
return map;
}
public static void main(String[] args) throws FileNotFoundException {
//GLSM will fail to parse without increasing language level
StaticJavaParser.getParserConfiguration().setLanguageLevel(ParserConfiguration.LanguageLevel.JAVA_17);
Map<String, String> functionMap = parseGLFunctions();
Set<String> glsmFunctions = new HashSet<>();
File glsmFile = new File(glsmPath);
CompilationUnit cu = StaticJavaParser.parse(glsmFile);
cu.accept(new VoidVisitorWithDefaults<>() {
@Override
public void defaultAction(Node n, Object arg) {
for (Node child : n.getChildNodes()) {
if (child instanceof ClassOrInterfaceDeclaration cd) {
for (MethodDeclaration md : cd.getMethods()) {
String methodName = md.getNameAsString() + "(";
for (Parameter p : md.getParameters()) {
methodName = methodName + p.getTypeAsString();
}
methodName = methodName + ")";
glsmFunctions.add(methodName);
}
}
}
}
}, null);
Map<String, String> functionGLSMMap = new HashMap<>();
for(String function : functionMap.keySet()) {
if (!glsmFunctions.contains(function)) {
functionGLSMMap.put(function, "false");
} else if (INCLUDE_TRUE) {
functionGLSMMap.put(function, "true");
}
}
List<String[]> outputLines = new ArrayList<>();
for (Map.Entry<String, String> entry : functionGLSMMap.entrySet()) {
outputLines.add(new String[] {entry.getKey(), functionMap.get(entry.getKey()), entry.getValue()});
}
File output = new File("glsm_function_comparison.csv");
try (PrintWriter writer = new PrintWriter(output)) {
outputLines.stream().map(GLSMFunctionComparison::convertToCSV).forEach(writer::println);
}
}
public static String convertToCSV(String[] data) {
return Stream.of(data).map(GLSMFunctionComparison::escapeSpecialCharacters).collect(Collectors.joining(","));
}
public static String escapeSpecialCharacters(String data) {
if (data == null) {
throw new IllegalArgumentException("Input data cannot be null");
}
String escapedData = data.replaceAll("\\R", " ");
if (data.contains(",") || data.contains("\"") || data.contains("'")) {
data = data.replace("\"", "\"\"");
escapedData = "\"" + data + "\"";
}
return escapedData;
}
public static String removeFileExtension(String filename) {
if (filename == null || filename.isEmpty()) {
return filename;
}
String extPattern = "(?<!^)[.]" + "[^.]*$";
return filename.replaceAll(extPattern, "");
}
}
@@ -1,12 +1,58 @@
package com.gtnewhorizons.angelica.compat.lwjgl;
import org.lwjgl.BufferUtils;
import static com.gtnewhorizons.angelica.compat.lwjgl.Pointer.BITS64;
import it.unimi.dsi.fastutil.longs.LongPredicate;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import org.lwjgl.BufferUtils;
/**
* Backported from LWJGL3 under the BSD 3-Clause "New" or "Revised" License license
*
* <p>This class provides functionality for managing native memory.
*
* <p>All methods in this class will make use of {@link sun.misc.Unsafe} if it's available, for performance. If Unsafe is not available, the fallback
* implementations make use of reflection and, in the worst-case, JNI.</p>
*
* <p>Method names in this class are prefixed with {@code mem} to avoid ambiguities when used with static imports.</p>
*/
public class CompatMemoryUtil {
public static final long NULL = 0;
static final sun.misc.Unsafe UNSAFE;
private static final Class<? extends ByteBuffer> BUFFER_BYTE;
private static final Class<? extends IntBuffer> BUFFER_INT;
private static final Class<? extends FloatBuffer> BUFFER_FLOAT;
private static final long MARK;
private static final long POSITION;
private static final long LIMIT;
private static final long CAPACITY;
private static final long ADDRESS;
static {
ByteBuffer bb = ByteBuffer.allocateDirect(0).order(ByteOrder.nativeOrder());
BUFFER_BYTE = bb.getClass();
BUFFER_INT = bb.asIntBuffer().getClass();
BUFFER_FLOAT = bb.asFloatBuffer().getClass();
UNSAFE = getUnsafeInstance();
MARK = getMarkOffset();
POSITION = getPositionOffset();
LIMIT = getLimitOffset();
CAPACITY = getCapacityOffset();
ADDRESS = getAddressOffset();
}
public static ByteBuffer memReallocDirect(ByteBuffer old, int capacity) {
ByteBuffer newBuf = BufferUtils.createByteBuffer(capacity);
int oldPos = old.position();
@@ -34,22 +80,100 @@ public class CompatMemoryUtil {
return newBuf;
}
/* -------------------------------------
-------------------------------------
UNSAFE MEMORY ACCESS API
-------------------------------------
------------------------------------- */
private static final int FILL_PATTERN_32 = Integer.divideUnsigned(-1, 255);
private static final long FILL_PATTERN_64 = Long.divideUnsigned(-1L, 255L);
/**
* Backported from LWJGL3 under the BSD 3-Clause "New" or "Revised" License license
* Sets all bytes in a specified block of memory to a fixed value (usually zero).
*
* <p>This class provides functionality for managing native memory.
*
* <p>All methods in this class will make use of {@link sun.misc.Unsafe} if it's available, for performance. If Unsafe is not available, the fallback
* implementations make use of reflection and, in the worst-case, JNI.</p>
*
* <p>Method names in this class are prefixed with {@code mem} to avoid ambiguities when used with static imports.</p>
* @param ptr the starting memory address
* @param value the value to set (memSet will convert it to unsigned byte)
* @param bytes the number of bytes to set
*/
public static void memSet(long ptr, int value, long bytes) {
if (/*DEBUG*/ false && (ptr == NULL || bytes < 0)) {
throw new IllegalArgumentException();
}
static final sun.misc.Unsafe UNSAFE;
/*
- Unsafe.setMemory is very slow.
- A custom Java loop is fastest at small sizes, approximately up to 256 bytes.
- The native memset becomes fastest at bigger sizes, when the JNI overhead becomes negligible.
TODO: verify this
*/
static {
UNSAFE = getUnsafeInstance();
//UNSAFE.setMemory(ptr, bytes, (byte)(value & 0xFF));
//if (bytes < 256L) {
int p = (int)ptr;
if (BITS64) {
if ((p & 7) == 0) {
memSet64(ptr, value, (int)bytes & 0xFF);
return;
}
} else {
if ((p & 3) == 0) {
memSet32(p, value, (int)bytes & 0xFF);
return;
}
}
//}
//nmemset(ptr, value, bytes);
}
private static void memSet64(long ptr, int value, int bytes) {
int aligned = bytes & ~7;
// Aligned body
long valuel = (value & 0xFF) * FILL_PATTERN_64;
for (int i = 0; i < aligned; i += 8) {
UNSAFE.putLong(null, ptr + i, valuel);
}
// Unaligned tail
byte valueb = (byte)(value & 0xFF);
for (int i = aligned; i < bytes; i++) {
UNSAFE.putByte(null, ptr + i, valueb);
}
}
private static void memSet32(int ptr, int value, int bytes) {
int aligned = bytes & ~3;
// Aligned body
int vi = (value & 0xFF) * FILL_PATTERN_32;
for (int i = 0; i < aligned; i += 4) {
UNSAFE.putInt(null, (ptr + i) & 0xFFFF_FFFFL, vi);
}
// Unaligned tail
byte vb = (byte)(value & 0xFF);
for (int i = aligned; i < bytes; i++) {
UNSAFE.putByte(null, (ptr + i) & 0xFFFF_FFFFL, vb);
}
}
public static boolean memGetBoolean(long ptr) { return UNSAFE.getByte(null, ptr) != 0; }
public static byte memGetByte(long ptr) { return UNSAFE.getByte(null, ptr); }
public static short memGetShort(long ptr) { return UNSAFE.getShort(null, ptr); }
public static int memGetInt(long ptr) { return UNSAFE.getInt(null, ptr); }
public static long memGetLong(long ptr) { return UNSAFE.getLong(null, ptr); }
public static float memGetFloat(long ptr) { return UNSAFE.getFloat(null, ptr); }
public static double memGetDouble(long ptr) { return UNSAFE.getDouble(null, ptr); }
public static void memPutByte(long ptr, byte value) { UNSAFE.putByte(null, ptr, value); }
public static void memPutShort(long ptr, short value) { UNSAFE.putShort(null, ptr, value); }
public static void memPutInt(long ptr, int value) { UNSAFE.putInt(null, ptr, value); }
public static void memPutLong(long ptr, long value) { UNSAFE.putLong(null, ptr, value); }
public static void memPutFloat(long ptr, float value) { UNSAFE.putFloat(null, ptr, value); }
public static void memPutDouble(long ptr, double value) { UNSAFE.putDouble(null, ptr, value); }
// -------------------------------------------------
// -------------------------------------------------
// -------------------------------------------------
private static sun.misc.Unsafe getUnsafeInstance() {
java.lang.reflect.Field[] fields = sun.misc.Unsafe.class.getDeclaredFields();
@@ -83,20 +207,121 @@ public class CompatMemoryUtil {
throw new UnsupportedOperationException("LWJGL requires sun.misc.Unsafe to be available.");
}
/**
* Recursively searches an object and its superclasses for a field with the same name and type. If the field isn't
* public, it may not be stable across library/JVM versions, and these calls are likely not portable. You have been
* warned!
*/
private static long getFieldOffset(Class<?> containerType, Class<?> fieldType, String name) {
Class<?> c = containerType;
while (c != Object.class) {
Field[] fields = c.getDeclaredFields();
for (Field field : fields) {
if (!field.getType().isAssignableFrom(fieldType) || Modifier.isStatic(field.getModifiers()) || field.isSynthetic()) {
continue;
}
public static void memPutByte(long ptr, byte value) { UNSAFE.putByte(null, ptr, value); }
public static void memPutShort(long ptr, short value) { UNSAFE.putShort(null, ptr, value); }
public static void memPutInt(long ptr, int value) { UNSAFE.putInt(null, ptr, value); }
public static void memPutLong(long ptr, long value) { UNSAFE.putLong(null, ptr, value); }
public static void memPutFloat(long ptr, float value) { UNSAFE.putFloat(null, ptr, value); }
public static void memPutDouble(long ptr, double value) { UNSAFE.putDouble(null, ptr, value); }
long offset = UNSAFE.objectFieldOffset(field);
if (field.getName().equals(name)) {
return offset;
}
}
c = c.getSuperclass();
}
throw new UnsupportedOperationException("Failed to find field offset in class.");
}
public static boolean memGetBoolean(long ptr) { return UNSAFE.getByte(null, ptr) != 0; }
public static byte memGetByte(long ptr) { return UNSAFE.getByte(null, ptr); }
public static short memGetShort(long ptr) { return UNSAFE.getShort(null, ptr); }
public static int memGetInt(long ptr) { return UNSAFE.getInt(null, ptr); }
public static long memGetLong(long ptr) { return UNSAFE.getLong(null, ptr); }
public static float memGetFloat(long ptr) { return UNSAFE.getFloat(null, ptr); }
public static double memGetDouble(long ptr) { return UNSAFE.getDouble(null, ptr); }
private static long getFieldOffset(Class<?> containerType, Class<?> fieldType, LongPredicate predicate) {
Class<?> c = containerType;
while (c != Object.class) {
Field[] fields = c.getDeclaredFields();
for (Field field : fields) {
if (!field.getType().isAssignableFrom(fieldType) || Modifier.isStatic(field.getModifiers()) || field.isSynthetic()) {
continue;
}
long offset = UNSAFE.objectFieldOffset(field);
if (predicate.test(offset)) {
return offset;
}
}
c = c.getSuperclass();
}
throw new UnsupportedOperationException("Failed to find field offset in class.");
}
private static long getFieldOffsetInt(Object container, int value) {
return getFieldOffset(container.getClass(), int.class, offset -> UNSAFE.getInt(container, offset) == value);
}
private static long getAddressOffset() {
final ByteBuffer bb = ByteBuffer.allocateDirect(0);
return getFieldOffset(bb.getClass(), long.class, "address");
// TODO: do this portably
// long MAGIC_ADDRESS = 0xDEADBEEF8BADF00DL & (BITS32 ? 0xFFFF_FFFFL : 0xFFFF_FFFF_FFFF_FFFFL);
// ByteBuffer bb = Objects.requireNonNull(NewDirectByteBuffer(MAGIC_ADDRESS, 0));
//return getFieldOffset(bb.getClass(), long.class, offset -> UNSAFE.getLong(bb, offset) == MAGIC_ADDRESS);
}
private static final int MAGIC_CAPACITY = 0x0D15EA5E;
private static final int MAGIC_POSITION = 0x00FACADE;
private static long getMarkOffset() {
// TODO: is this actually reliable without NewDirectByteBuffer?
ByteBuffer bb = ByteBuffer.allocateDirect(0);
return getFieldOffsetInt(bb, -1);
// ByteBuffer bb = Objects.requireNonNull(NewDirectByteBuffer(1L, 0));
// return getFieldOffsetInt(bb, -1);
}
private static long getPositionOffset() {
ByteBuffer bb = ByteBuffer.allocateDirect(MAGIC_CAPACITY);
bb.position(MAGIC_POSITION);
return getFieldOffsetInt(bb, MAGIC_POSITION);
}
private static long getLimitOffset() {
ByteBuffer bb = ByteBuffer.allocateDirect(MAGIC_CAPACITY);
bb.limit(MAGIC_POSITION);
return getFieldOffsetInt(bb, MAGIC_POSITION);
}
private static long getCapacityOffset() {
ByteBuffer bb = ByteBuffer.allocateDirect(MAGIC_CAPACITY);
bb.limit(0);
return getFieldOffsetInt(bb, MAGIC_CAPACITY);
}
static IntBuffer wrapBufferInt(long address, int capacity) {
IntBuffer buffer;
try {
buffer = (IntBuffer)UNSAFE.allocateInstance(BUFFER_INT);
} catch (InstantiationException e) {
throw new UnsupportedOperationException(e);
}
UNSAFE.putLong(buffer, ADDRESS, address);
UNSAFE.putInt(buffer, MARK, -1);
UNSAFE.putInt(buffer, LIMIT, capacity);
UNSAFE.putInt(buffer, CAPACITY, capacity);
return buffer;
}
static FloatBuffer wrapBufferFloat(long address, int capacity) {
FloatBuffer buffer;
try {
buffer = (FloatBuffer)UNSAFE.allocateInstance(BUFFER_FLOAT);
} catch (InstantiationException e) {
throw new UnsupportedOperationException(e);
}
UNSAFE.putLong(buffer, ADDRESS, address);
UNSAFE.putInt(buffer, MARK, -1);
UNSAFE.putInt(buffer, LIMIT, capacity);
UNSAFE.putInt(buffer, CAPACITY, capacity);
return buffer;
}
}
@@ -0,0 +1,382 @@
/*
* This class is backported from LWJGL3 under the BSD 3-clause "New" or "Revised" License
*/
package com.gtnewhorizons.angelica.compat.lwjgl;
import static com.gtnewhorizons.angelica.compat.lwjgl.CompatMemoryUtil.memPutDouble;
import static com.gtnewhorizons.angelica.compat.lwjgl.CompatMemoryUtil.memPutFloat;
import static com.gtnewhorizons.angelica.compat.lwjgl.CompatMemoryUtil.memPutInt;
import static com.gtnewhorizons.angelica.compat.lwjgl.CompatMemoryUtil.memPutLong;
import static com.gtnewhorizons.angelica.compat.lwjgl.CompatMemoryUtil.memPutShort;
import static com.gtnewhorizons.angelica.compat.lwjgl.CompatMemoryUtil.memSet;
import static com.gtnewhorizons.angelica.compat.lwjgl.CompatMemoryUtil.wrapBufferFloat;
import static com.gtnewhorizons.angelica.compat.lwjgl.CompatMemoryUtil.wrapBufferInt;
import com.gtnewhorizons.angelica.loading.AngelicaTweaker;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.Arrays;
import org.jetbrains.annotations.Nullable;
import org.lwjgl.BufferUtils;
import org.lwjgl.MemoryUtil;
/**
* An off-heap memory stack.
*
* <p>This class should be used in a thread-local manner for stack allocations.</p>
*
* @ see Configuration#STACK_SIZE
* @ see Configuration#DEBUG_STACK
*/
@SuppressWarnings("LombokGetterMayBeUsed")
public class MemoryStack extends Pointer.Default implements AutoCloseable {
private static final int DEFAULT_STACK_SIZE = /*Configuration.STACK_SIZE.get(64)*/ 64 * 1024;
private static final int DEFAULT_STACK_FRAMES = 8;
private static final ThreadLocal<MemoryStack> TLS = ThreadLocal.withInitial(MemoryStack::create);
static {
if (DEFAULT_STACK_SIZE < 0) {
throw new IllegalStateException("Invalid stack size.");
}
}
@SuppressWarnings({"FieldCanBeLocal", "unused"})
private final @Nullable ByteBuffer container;
private final int size;
private int pointer;
private int[] frames;
protected int frameIndex;
/**
* Creates a new {@code MemoryStack} backed by the specified memory region.
*
* <p>In the initial state, there is no active stack frame. The {@link #push} method must be used before any allocations.</p>
*
* @param container the backing memory buffer, may be null
* @param address the backing memory address
* @param size the backing memory size
*/
protected MemoryStack(@Nullable ByteBuffer container, long address, int size) {
super(address);
this.container = container;
this.size = size;
this.pointer = size;
this.frames = new int[DEFAULT_STACK_FRAMES];
}
/**
* Creates a new {@code MemoryStack} with the default size.
*
* <p>In the initial state, there is no active stack frame. The {@link #push} method must be used before any allocations.</p>
*/
public static MemoryStack create() {
return create(DEFAULT_STACK_SIZE);
}
/**
* Creates a new {@code MemoryStack} with the specified size.
*
* <p>In the initial state, there is no active stack frame. The {@link #push} method must be used before any allocations.</p>
*
* @param capacity the maximum number of bytes that may be allocated on the stack
*/
public static MemoryStack create(int capacity) {
return create(BufferUtils.createByteBuffer(capacity));
}
/**
* Creates a new {@code MemoryStack} backed by the specified memory buffer.
*
* <p>In the initial state, there is no active stack frame. The {@link #push} method must be used before any allocations.</p>
*
* @param buffer the backing memory buffer
*/
public static MemoryStack create(ByteBuffer buffer) {
long address = MemoryUtil.getAddress(buffer);
int size = buffer.remaining();
return new MemoryStack(buffer, address, size);
}
/**
* Creates a new {@code MemoryStack} backed by the specified memory region.
*
* <p>In the initial state, there is no active stack frame. The {@link #push} method must be used before any allocations.</p>
*
* @param address the backing memory address
* @param size the backing memory size
*/
public static MemoryStack ncreate(long address, int size) {
return new MemoryStack(null, address, size);
}
/**
* Stores the current stack pointer and pushes a new frame to the stack.
*
* <p>This method should be called when entering a method, before doing any stack allocations. When exiting a method, call the {@link #pop} method to
* restore the previous stack frame.</p>
*
* <p>Pairs of push/pop calls may be nested. Care must be taken to:</p>
* <ul>
* <li>match every push with a pop</li>
* <li>not call pop before push has been called at least once</li>
* <li>not nest push calls to more than the maximum supported depth</li>
* </ul>
*
* @return this stack
*/
public MemoryStack push() {
if (frameIndex == frames.length) {
frameOverflow();
}
frames[frameIndex++] = pointer;
return this;
}
private void frameOverflow() {
if (/*DEBUG*/ false) {
AngelicaTweaker.LOGGER.warn("[WARNING] Out of frame stack space (" + frames.length + ") in thread: " + Thread.currentThread());
}
frames = Arrays.copyOf(frames, frames.length * 3 / 2);
}
/**
* Pops the current stack frame and moves the stack pointer to the end of the previous stack frame.
*
* @return this stack
*/
public MemoryStack pop() {
pointer = frames[--frameIndex];
return this;
}
/**
* Calls {@link #pop} on this {@code MemoryStack}.
*
* <p>This method should not be used directly. It is called automatically when the {@code MemoryStack} is used as a resource in a try-with-resources
* statement.</p>
*/
@Override
public void close() {
//noinspection resource
pop();
}
/**
* Returns the address of the backing off-heap memory.
*
* <p>The stack grows "downwards", so the bottom of the stack is at {@code address + size}, while the top is at {@code address}.</p>
*/
public long getAddress() {
return address;
}
/**
* Returns the size of the backing off-heap memory.
*
* <p>This is the maximum number of bytes that may be allocated on the stack.</p>
*/
public int getSize() {
return size;
}
/**
* Returns the current frame index.
*
* <p>This is the current number of nested {@link #push} calls.</p>
*/
public int getFrameIndex() {
return frameIndex;
}
/** Returns the memory address at the current stack pointer. */
public long getPointerAddress() {
return address + (pointer & 0xFFFF_FFFFL);
}
/**
* Returns the current stack pointer.
*
* <p>The stack grows "downwards", so when the stack is empty {@code pointer} is equal to {@code size}. On every allocation {@code pointer} is reduced by
* the allocated size (after alignment) and {@code address + pointer} points to the first byte of the last allocation.</p>
*
* <p>Effectively, this methods returns how many more bytes may be allocated on the stack.</p>
*/
public int getPointer() {
return pointer;
}
/**
* Sets the current stack pointer.
*
* <p>This method directly manipulates the stack pointer. Using it irresponsibly may break the internal state of the stack. It should only be used in rare
* cases or in auto-generated code.</p>
*/
public void setPointer(int pointer) {
if (/*CHECKS*/ false) {
checkPointer(pointer);
}
this.pointer = pointer;
}
private void checkPointer(int pointer) {
if (pointer < 0 || size < pointer) {
throw new IndexOutOfBoundsException("Invalid stack pointer");
}
}
private static void checkAlignment(int alignment) {
if (Integer.bitCount(alignment) != 1) {
throw new IllegalArgumentException("Alignment must be a power-of-two value.");
}
}
/**
* Calls {@link #nmalloc(int, int)} with {@code alignment} equal to {@link Pointer#POINTER_SIZE POINTER_SIZE}.
*
* @param size the allocation size
*
* @return the memory address on the stack for the requested allocation
*/
public long nmalloc(int size) {
return nmalloc(POINTER_SIZE, size);
}
/**
* Allocates a block of {@code size} bytes of memory on the stack. The content of the newly allocated block of memory is not initialized, remaining with
* indeterminate values.
*
* @param alignment the required alignment
* @param size the allocation size
*
* @return the memory address on the stack for the requested allocation
*/
public long nmalloc(int alignment, int size) {
// Align address to the specified alignment
long address = (this.address + pointer - size) & ~Integer.toUnsignedLong(alignment - 1);
pointer = (int)(address - this.address);
if (/*CHECKS*/ false && pointer < 0) {
throw new OutOfMemoryError("Out of stack space.");
}
return address;
}
/**
* Allocates a block of memory on the stack for an array of {@code num} elements, each of them {@code size} bytes long, and initializes all its bits to
* zero.
*
* @param alignment the required element alignment
* @param num num the number of elements to allocate
* @param size the size of each element
*
* @return the memory address on the stack for the requested allocation
*/
public long ncalloc(int alignment, int num, int size) {
int bytes = num * size;
long address = nmalloc(alignment, bytes);
memSet(address, 0, bytes);
return address;
}
// -------------------------------------------------
/** Unsafe version of {@link #shorts(short)}. */
public long nshort(short value) {
long a = nmalloc(2, 2);
memPutShort(a, value);
return a;
}
// -------------------------------------------------
/** Int version of {@link #malloc(int)}. */
public IntBuffer mallocInt(int size) { return wrapBufferInt(nmalloc(4, size << 2), size); }
/** Unsafe version of {@link #ints(int)}. */
public long nint(int value) {
long a = nmalloc(4, 4);
memPutInt(a, value);
return a;
}
// -------------------------------------------------
/** Unsafe version of {@link #longs(long)}. */
public long nlong(long value) {
long a = nmalloc(8, 8);
memPutLong(a, value);
return a;
}
// -------------------------------------------------
/** Float version of {@link #malloc(int)}. */
public FloatBuffer mallocFloat(int size) { return wrapBufferFloat(nmalloc(4, size << 2), size); }
/** Unsafe version of {@link #floats(float)}. */
public long nfloat(float value) {
long a = nmalloc(4, 4);
memPutFloat(a, value);
return a;
}
// -------------------------------------------------
/** Unsafe version of {@link #doubles(double)}. */
public long ndouble(double value) {
long a = nmalloc(8, 8);
memPutDouble(a, value);
return a;
}
// -------------------------------------------------
// -------------------------------------------------
// -------------------------------------------------
/** Returns the stack of the current thread. */
public static MemoryStack stackGet() {
return TLS.get();
}
/**
* Calls {@link #push} on the stack of the current thread.
*
* @return the stack of the current thread.
*/
public static MemoryStack stackPush() {
return stackGet().push();
}
/**
* Calls {@link #pop} on the stack of the current thread.
*
* @return the stack of the current thread.
*/
public static MemoryStack stackPop() {
return stackGet().pop();
}
/** Thread-local version of {@link #nmalloc(int)}. */
public static long nstackMalloc(int size) { return stackGet().nmalloc(size); }
/** Thread-local version of {@link #nmalloc(int, int)}. */
public static long nstackMalloc(int alignment, int size) { return stackGet().nmalloc(alignment, size); }
/** Thread-local version of {@link #ncalloc}. */
public static long nstackCalloc(int alignment, int num, int size) { return stackGet().ncalloc(alignment, num, size); }
// -------------------------------------------------
}
@@ -0,0 +1,93 @@
/*
* This class is backported from LWJGL3 under the BSD 3-clause "New" or "Revised" License
*/
package com.gtnewhorizons.angelica.compat.lwjgl;
import static com.gtnewhorizons.angelica.compat.lwjgl.CompatMemoryUtil.NULL;
import static com.gtnewhorizons.angelica.compat.lwjgl.CompatMemoryUtil.UNSAFE;
import static org.lwjgl.LWJGLUtil.CHECKS;
import net.minecraft.util.Util;
import org.jetbrains.annotations.Nullable;
/**
* Pointer interface.
*
* <p>LWJGL can run on both 32bit and 64bit architectures. Since LWJGL applications deal with native memory directly, this interface provides necessary
* information about the underlying architecture of the running JVM process.</p>
*
* <p>When interacting with native functions, pointer values are mapped to Java {@code long}. LWJGL automatically converts long values to the correct pointer
* addresses when used in native code. Native functions sometimes require arrays of pointer values; the {@link PointerBuffer} class may be used for that
* purpose. It has an API similar to a {@link java.nio.LongBuffer} but handles pointer casts automatically.</p>
*/
public interface Pointer {
/** The pointer size in bytes. Will be 4 on a 32bit JVM and 8 on a 64bit one. */
int POINTER_SIZE = UNSAFE.addressSize();
/** The pointer size power-of-two. Will be 2 on a 32bit JVM and 3 on a 64bit one. */
int POINTER_SHIFT = POINTER_SIZE == 8 ? 3 : 2;
/** The value of {@code sizeof(long)} for the current platform. */
int CLONG_SIZE = POINTER_SIZE == 8 && Util.getOSType() == Util.EnumOS.WINDOWS ? 4 : POINTER_SIZE;
/** The value of {@code sizeof(long)} as a power-of-two. */
int CLONG_SHIFT = CLONG_SIZE == 8 ? 3 : 2;
/** Will be true on a 32bit JVM. */
boolean BITS32 = POINTER_SIZE * 8 == 32;
/** Will be true on a 64bit JVM. */
boolean BITS64 = POINTER_SIZE * 8 == 64;
/**
* Returns the raw pointer address as a {@code long} value.
*
* @return the pointer address
*/
long address();
/** Default {@link Pointer} implementation. */
abstract class Default implements Pointer {
// Removed final due to JDK-8139758. TODO: Restore if the fix is backported to JDK 8.
protected long address;
protected Default(long address) {
if (CHECKS && address == NULL) {
throw new NullPointerException();
}
this.address = address;
}
@Override
public long address() {
return address;
}
public boolean equals(@Nullable Object o) {
if (this == o) {
return true;
}
if (!(o instanceof Pointer)) {
return false;
}
Pointer that = (Pointer)o;
return address == that.address();
}
public int hashCode() {
return (int)(address ^ (address >>> 32));
}
@Override
public String toString() {
return String.format("%s pointer [0x%X]", getClass().getSimpleName(), address);
}
}
}
@@ -1,18 +1,17 @@
package com.gtnewhorizons.angelica.compat.mojang;
import lombok.Getter;
import net.coderbot.iris.Iris;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL12;
import javax.imageio.ImageIO;
import com.gtnewhorizons.angelica.compat.lwjgl.MemoryStack;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import javax.imageio.ImageIO;
import lombok.Getter;
import net.coderbot.iris.Iris;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL12;
// TBD
public class NativeImage extends BufferedImage {
@@ -59,12 +58,14 @@ public class NativeImage extends BufferedImage {
// final int width = GL11.glGetTexLevelParameteri(GL11.GL_TEXTURE_2D, level, GL11.GL_TEXTURE_WIDTH);
// final int height = GL11.glGetTexLevelParameteri(GL11.GL_TEXTURE_2D, level, GL11.GL_TEXTURE_HEIGHT);
IntBuffer buffer = BufferUtils.createIntBuffer(size);
int[] data = new int[size];
try (final MemoryStack stack = MemoryStack.stackPush()) {
final IntBuffer buffer = stack.mallocInt(size);
GL11.glGetTexImage(GL11.GL_TEXTURE_2D, level, format.glFormat, GL12.GL_UNSIGNED_INT_8_8_8_8_REV, buffer);
GL11.glGetTexImage(GL11.GL_TEXTURE_2D, level, format.glFormat, GL12.GL_UNSIGNED_INT_8_8_8_8_REV, buffer);
buffer.get(data);
setRGB(0, 0, width, height, data, 0, width);
int[] data = new int[size];
buffer.get(data);
setRGB(0, 0, width, height, data, 0, width);
}
}
public void writeToFile(File file) throws IOException{
try {
@@ -137,4 +137,15 @@ public class AngelicaConfig {
@Config.DefaultBoolean(true)
@Config.RequiresMcRestart
public static boolean enableZoom;
@Config.Comment("Optimizes in-world item rendering")
@Config.DefaultBoolean(true)
@Config.RequiresMcRestart
public static boolean optimizeInWorldItemRendering;
@Config.Comment("Max amount of display lists to cache for optimized item rendering. Higher number will use more VRAM")
@Config.DefaultInt(256)
@Config.RangeInt(min = 64, max = 1024)
public static int itemRendererDisplayListCacheSize;
}
@@ -0,0 +1,61 @@
package com.gtnewhorizons.angelica.debug;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.ScaledResolution;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.entity.Entity;
import net.minecraftforge.client.event.RenderGameOverlayEvent;
import org.lwjgl.opengl.GL11;
public class F3Direction {
public static void renderWorldDirectionsEvent(Minecraft mc, RenderGameOverlayEvent.Pre event) {
if (mc.gameSettings.showDebugInfo && mc.gameSettings.thirdPersonView == 0) {
ScaledResolution scaledresolution = new ScaledResolution(mc, mc.displayWidth, mc.displayHeight);
int width = scaledresolution.getScaledWidth();
int height = scaledresolution.getScaledHeight();
GL11.glPushMatrix();
GL11.glTranslatef((float) (width / 2), (float) (height / 2), -90);
Entity entity = mc.renderViewEntity;
GL11.glRotatef(entity.prevRotationPitch + (entity.rotationPitch - entity.prevRotationPitch) * event.partialTicks, -1.0F, 0.0F, 0.0F);
GL11.glRotatef(entity.prevRotationYaw + (entity.rotationYaw - entity.prevRotationYaw) * event.partialTicks, 0.0F, 1.0F, 0.0F);
GL11.glScalef(-1.0F, -1.0F, -1.0F);
renderWorldDirections();
GL11.glPopMatrix();
}
}
public static void renderWorldDirections() {
GL11.glDisable(GL11.GL_TEXTURE_2D);
GL11.glDepthMask(false);
Tessellator tessellator = Tessellator.instance;
GL11.glLineWidth(2.0F);
tessellator.startDrawing(GL11.GL_LINES);
//X
tessellator.setColorRGBA_F(255, 0, 0, 1);
tessellator.addVertex(0.0D, 0.0D, 0.0D);
tessellator.addVertex(10, 0.0D, 0.0D);
//Z
tessellator.setColorRGBA_F(0, 0, 255, 1);
tessellator.addVertex(0.0D, 0.0D, 0.0D);
tessellator.addVertex(0.0D, 0.0D, 10);
//Y
tessellator.setColorRGBA_F(0, 255, 0, 1);
tessellator.addVertex(0.0D, 0.0D, 0.0D);
tessellator.addVertex(0.0D, 10, 0.0D);
tessellator.draw();
GL11.glLineWidth(1.0F);
GL11.glDepthMask(true);
GL11.glEnable(GL11.GL_TEXTURE_2D);
}
}
@@ -0,0 +1,273 @@
package com.gtnewhorizons.angelica.debug;
import static org.lwjgl.opengl.GL11.GL_ALPHA_TEST;
import static org.lwjgl.opengl.GL11.GL_BLEND;
import static org.lwjgl.opengl.GL11.GL_CULL_FACE;
import static org.lwjgl.opengl.GL11.GL_DEPTH_TEST;
import static org.lwjgl.opengl.GL11.GL_FLOAT;
import static org.lwjgl.opengl.GL11.GL_ONE_MINUS_SRC_ALPHA;
import static org.lwjgl.opengl.GL11.GL_SRC_ALPHA;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D;
import static org.lwjgl.opengl.GL11.GL_TRIANGLE_STRIP;
import static org.lwjgl.opengl.GL11.GL_VERTEX_ARRAY;
import static org.lwjgl.opengl.GL11.glBlendFunc;
import static org.lwjgl.opengl.GL11.glColor4f;
import static org.lwjgl.opengl.GL11.glDisable;
import static org.lwjgl.opengl.GL11.glDisableClientState;
import static org.lwjgl.opengl.GL11.glDrawArrays;
import static org.lwjgl.opengl.GL11.glEnable;
import static org.lwjgl.opengl.GL11.glEnableClientState;
import static org.lwjgl.opengl.GL15.GL_ARRAY_BUFFER;
import static org.lwjgl.opengl.GL15.GL_STATIC_DRAW;
import static org.lwjgl.opengl.GL15.glBindBuffer;
import static org.lwjgl.opengl.GL15.glBufferData;
import static org.lwjgl.opengl.GL15.glGenBuffers;
import static org.lwjgl.opengl.GL20.glDisableVertexAttribArray;
import static org.lwjgl.opengl.GL20.glEnableVertexAttribArray;
import static org.lwjgl.opengl.GL20.glUniform1;
import static org.lwjgl.opengl.GL20.glUniform1f;
import static org.lwjgl.opengl.GL20.glUniform1i;
import static org.lwjgl.opengl.GL20.glVertexAttribPointer;
import com.gtnewhorizon.gtnhlib.client.renderer.shader.ShaderProgram;
import com.gtnewhorizons.angelica.compat.lwjgl.MemoryStack;
import java.nio.FloatBuffer;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.ScaledResolution;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.util.ResourceLocation;
import org.lwjgl.BufferUtils;
public abstract class F3Graph {
private static final int NUM_SAMPLES = 240;
// Two floats (x,y)
private static final int VERT_FLOATS = 2;
private static final int VERT_COUNT = 4;
private static final int BORDER = 1;
private static final int HEIGHT = 60;
private static final int WIDTH = NUM_SAMPLES;
private static final int FONT_COLOR = 0xFFE0E0E0;
// Due to GLSL 120 limitations, it's just easier to use floats
private final FloatBuffer sampleBuf = BufferUtils.createFloatBuffer(NUM_SAMPLES);
private final long[] samples = new long[NUM_SAMPLES]; // long version for calculations
// Circular buffer holding the last 240 samples, in nanoseconds
private int samplesHead = 0; // one ahead of the position of the last sample
private boolean initialized = false;
private ShaderProgram shader;
private int aPos;
private int uFBWidth;
private int uFBHeight;
private int uScaleFactor;
private int uHeadIdx;
private int uSamples;
private int vertBuf;
private final ResourceLocation texture;
private final float pxPerNs;
private final boolean left;
private long sum;
protected F3Graph(ResourceLocation texture, float pxPerNs, boolean left) {
this.texture = texture;
this.pxPerNs = pxPerNs;
this.left = left;
}
public void putSample(long time) {
// Manage running trackers
sum -= samples[samplesHead];
sum += time;
samples[samplesHead] = time;
sampleBuf.put(samplesHead, (float) time);
samplesHead = (samplesHead + 1) % NUM_SAMPLES;
}
private int getVertX(ScaledResolution sres, int idx) {
if (left) {
return switch (idx) {
case 0, 3 -> WIDTH + BORDER * 2;
case 1, 2 -> 0;
default -> throw new RuntimeException("Tried to get out-of-bounds vertex for graph!");
};
}
final int displayWidth = sres.getScaledWidth();
return switch (idx) {
case 0, 3 -> displayWidth;
case 1, 2 -> displayWidth - WIDTH - BORDER * 2;
default -> throw new RuntimeException("Tried to get out-of-bounds vertex for graph!");
};
}
private int getVertY(ScaledResolution sres, int idx) {
final int displayHeight = sres.getScaledHeight();
return switch (idx) {
case 0, 1 -> displayHeight - HEIGHT - BORDER * 2;
case 2, 3 -> displayHeight;
default -> throw new RuntimeException("Tried to get out-of-bounds vertex for graph!");
};
}
private void init() {
shader = new ShaderProgram(
"angelica",
"shaders/debug_graph.vert.glsl",
"shaders/debug_graph.frag.glsl");
shader.use();
// Register attributes
aPos = shader.getAttribLocation("pos");
// Register uniforms
uFBWidth = shader.getUniformLocation("fbWidth");
uFBHeight = shader.getUniformLocation("fbHeight");
uScaleFactor = shader.getUniformLocation("scaleFactor");
uSamples = shader.getUniformLocation("samples");
uHeadIdx = shader.getUniformLocation("headIdx");
final int uPxPerNs = shader.getUniformLocation("pxPerNs");
final int uLeft = shader.getUniformLocation("left");
// Load vertex buffer
vertBuf = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vertBuf);
try (final MemoryStack stack = MemoryStack.stackPush()) {
final FloatBuffer vertices = stack.mallocFloat(VERT_COUNT * VERT_FLOATS);
// Since we use a triangle strip, we only need 4 vertices. The quad extends to the top of the screen so spikes
// don't get truncated. The max height is replaced in the vert shader, no need to be precise.
vertices.put(new float[]{
BORDER, BORDER,
WIDTH + BORDER, BORDER,
BORDER, Float.MAX_VALUE,
WIDTH + BORDER, Float.MAX_VALUE
});
vertices.rewind();
glBufferData(GL_ARRAY_BUFFER, vertices, GL_STATIC_DRAW);
}
glBindBuffer(GL_ARRAY_BUFFER, 0);
final Minecraft mc = Minecraft.getMinecraft();
final ScaledResolution sr = new ScaledResolution(mc, mc.displayWidth, mc.displayHeight);
// Load initial value for uniforms
glUniform1f(uFBWidth, mc.displayWidth);
glUniform1f(uFBHeight, mc.displayHeight);
glUniform1f(uScaleFactor, sr.getScaleFactor());
glUniform1i(uHeadIdx, samplesHead);
glUniform1(uSamples, sampleBuf);
glUniform1f(uPxPerNs, pxPerNs);
glUniform1i(uLeft, left ? 1 : 0); // this is how you load bool uniforms
ShaderProgram.clear();
}
public void render() {
if (!initialized) {
init();
initialized = true;
}
/*
* We try to copy modern vanilla's tracker.
* It is 240 (FRAME_TIMES) wide by 60 tall, including the 1px borders.
* We instead make it 242x62 including borders to prevent the borders from overlapping the samples.
* The background is ARGB 90505050, the borders FFFFFFFF, and the text FFE0E0E0.
* First the background is rendered, then the samples, then the foreground texture and the text.
* The background is drawn via a 242x62 translucent rect.
* Next, the samples are rendered by a shader on a transparent 240x60 rect.
* Finally, the foreground texture and the text is rendered on top.
* The shader pipeline is only needed for the sample draw.
*/
final Minecraft mc = Minecraft.getMinecraft();
final ScaledResolution sr = new ScaledResolution(mc, mc.displayWidth, mc.displayHeight);
// Setup GL state
final Tessellator tess = Tessellator.instance;
glDisable(GL_DEPTH_TEST);
glEnable(GL_ALPHA_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// Draw background
glDisable(GL_TEXTURE_2D);
glColor4f(0x50 / 255.0F, 0x50 / 255.0F, 0x50 / 255.0F, 0x90 / 255.0F);
tess.startDrawingQuads();
for (int i = 0; i < 4; ++i) {
tess.addVertex(getVertX(sr, i), getVertY(sr, i), 0);
}
tess.draw();
glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
glEnable(GL_TEXTURE_2D);
// Draw samples
shader.use();
// Load uniforms
glUniform1f(uFBWidth, mc.displayWidth);
glUniform1f(uFBHeight, mc.displayHeight);
glUniform1f(uScaleFactor, sr.getScaleFactor());
glUniform1i(uHeadIdx, samplesHead);
glUniform1(uSamples, sampleBuf);
glBindBuffer(GL_ARRAY_BUFFER, vertBuf);
glEnableVertexAttribArray(aPos);
glVertexAttribPointer(aPos, VERT_FLOATS, GL_FLOAT, false, VERT_FLOATS * 4, 0);
glEnableClientState(GL_VERTEX_ARRAY);
// Left side graphs are inverted, so temporarily disable culling
if (!left) glDisable(GL_CULL_FACE);
glDrawArrays(GL_TRIANGLE_STRIP, 0, VERT_COUNT);
if (!left) glEnable(GL_CULL_FACE);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableVertexAttribArray(aPos);
glBindBuffer(GL_ARRAY_BUFFER, 0);
ShaderProgram.clear();
// Draw foreground
mc.getTextureManager().bindTexture(texture);
tess.startDrawingQuads();
tess.addVertexWithUV(getVertX(sr, 0), getVertY(sr, 0), 0.0D, 1, 0);
tess.addVertexWithUV(getVertX(sr, 1), getVertY(sr, 1), 0.0D, 0, 0);
tess.addVertexWithUV(getVertX(sr, 2), getVertY(sr, 2), 0.0D, 0, 1);
tess.addVertexWithUV(getVertX(sr, 3), getVertY(sr, 3), 0.0D, 1, 1);
tess.draw();
// Reset GL state
glEnable(GL_DEPTH_TEST);
glDisable(GL_ALPHA_TEST);
glDisable(GL_BLEND);
// Draw text
// Ensure running counters are reset on first sample
long min = Long.MAX_VALUE;
long max = Long.MIN_VALUE;
for (int i = 0; i < NUM_SAMPLES; ++i) {
min = Math.min(min, samples[i]);
max = Math.max(max, samples[i]);
}
String minStr = String.format("%.1f ms min", min / 1_000_000D);
String avgStr = String.format("%.1f ms avg", sum / 1_000_000 / (double) NUM_SAMPLES);
String maxStr = String.format("%.1f ms max", max / 1_000_000D);
final FontRenderer fr = mc.fontRenderer;
final int top = sr.getScaledHeight() - HEIGHT - BORDER * 2 - fr.FONT_HEIGHT;
final int scaledWidth = sr.getScaledWidth();
if (left) {
fr.drawString(minStr, BORDER * 2, top, FONT_COLOR, true);
fr.drawString(avgStr, BORDER + WIDTH / 2 - fr.getStringWidth(avgStr) / 2, top, FONT_COLOR, true);
fr.drawString(maxStr, BORDER * 2 + WIDTH - fr.getStringWidth(maxStr), top, FONT_COLOR, true);
} else {
fr.drawString(minStr, scaledWidth - (BORDER * 2 + WIDTH), top, FONT_COLOR, true);
fr.drawString(avgStr, scaledWidth - (BORDER + WIDTH / 2 + fr.getStringWidth(avgStr) / 2), top, FONT_COLOR, true);
fr.drawString(maxStr, scaledWidth - (BORDER * 2 + fr.getStringWidth(maxStr)), top, FONT_COLOR, true);
}
}
}
@@ -0,0 +1,14 @@
package com.gtnewhorizons.angelica.debug;
import net.minecraft.util.ResourceLocation;
public class FrametimeGraph extends F3Graph {
public FrametimeGraph() {
// At 1x scale, 30 FPS should be 60 px. 30 FPS = 33_333_333ns per frame, 60px/33_333_333ns = 0.0000018f px/ns
super(
new ResourceLocation("angelica:textures/frametimes_fg.png"),
0.0000018f,
true
);
}
}
@@ -0,0 +1,14 @@
package com.gtnewhorizons.angelica.debug;
import net.minecraft.util.ResourceLocation;
public class TPSGraph extends F3Graph {
public TPSGraph() {
// At 1x scale, 20 TPS should be 60 px. 20 FPS = 50_000_000ns per frame, 60px/50_000_000ns = 0.0000012 px/ns
super(
new ResourceLocation("angelica:textures/tps_fg.png"),
0.0000012f,
false
);
}
}
@@ -172,6 +172,7 @@ public class GLStateManager {
@Setter @Getter private static boolean runningSplash = true;
private static int glListMode = 0;
private static int glListNesting = 0;
private static int glListId = -1;
private static final Map<IStateStack<?>, ISettableState<?>> glListStates = new Object2ObjectArrayMap<>();
private static final Int2ObjectMap<Set<Map.Entry<IStateStack<?>, ISettableState<?>>>> glListChanges = new Int2ObjectOpenHashMap<>();
@@ -1187,7 +1188,8 @@ public class GLStateManager {
public static void glNewList(int list, int mode) {
if(glListMode > 0) {
throw new RuntimeException("glNewList called inside of a display list!");
glListNesting += 1;
return;
}
glListId = list;
glListMode = mode;
@@ -1202,6 +1204,11 @@ public class GLStateManager {
}
public static void glEndList() {
if (glListNesting > 0) {
glListNesting -= 1;
return;
}
if(glListMode == 0) {
throw new RuntimeException("glEndList called outside of a display list!");
}
@@ -239,7 +239,7 @@ public class RenderSystem {
dsaState.bindTextureToUnit(unit, texture);
}
public static FloatBuffer PROJECTION_MATRIX_BUFFER = BufferUtils.createFloatBuffer(16);
public static final FloatBuffer PROJECTION_MATRIX_BUFFER = BufferUtils.createFloatBuffer(16);
public static void setupProjectionMatrix(Matrix4f matrix) {
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glPushMatrix();
@@ -15,6 +15,7 @@ import com.gtnewhorizons.angelica.transform.compat.handlers.CompatHandlers;
import cpw.mods.fml.relauncher.IFMLLoadingPlugin;
import jss.notfine.asm.AsmTransformers;
import jss.notfine.asm.mappings.Namer;
import jss.notfine.config.MCPatcherForgeConfig;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -56,6 +57,7 @@ public class AngelicaTweaker implements IFMLLoadingPlugin, IEarlyMixinLoader {
// Angelica Config
ConfigurationManager.registerConfig(AngelicaConfig.class);
ConfigurationManager.registerConfig(CompatConfig.class);
MCPatcherForgeConfig.registerConfig();
final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
final Configuration config = ctx.getConfiguration();
final LoggerConfig loggerConfig = config.getLoggerConfig(LogManager.ROOT_LOGGER_NAME);
@@ -4,15 +4,24 @@ import com.gtnewhorizons.angelica.config.AngelicaConfig;
import com.gtnewhorizons.angelica.transform.BlockTransformer;
import com.gtnewhorizons.angelica.transform.RedirectorTransformer;
import cpw.mods.fml.common.Loader;
import cpw.mods.fml.relauncher.CoreModManager;
import cpw.mods.fml.relauncher.FMLLaunchHandler;
import net.minecraft.launchwrapper.IClassTransformer;
import net.minecraft.launchwrapper.ITweaker;
import net.minecraft.launchwrapper.Launch;
import net.minecraft.launchwrapper.LaunchClassLoader;
import org.spongepowered.asm.launch.platform.MixinContainer;
import org.spongepowered.asm.launch.platform.MixinPlatformManager;
import org.spongepowered.asm.launch.platform.container.IContainerHandle;
import org.spongepowered.asm.mixin.transformer.Config;
import java.io.File;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static com.gtnewhorizons.angelica.loading.AngelicaTweaker.LOGGER;
@@ -23,8 +32,8 @@ public class MixinCompatHackTweaker implements ITweaker {
verifyDependencies();
if(DISABLE_OPTIFINE_FASTCRAFT_BETTERFPS) {
LOGGER.info("Disabling Optifine, Fastcraft, and BetterFPS (if present)");
disableOptifineFastcraftAndBetterFPS();
LOGGER.info("Disabling Optifine, Fastcraft, BetterFPS, and other incompatible mods (if present)");
disableIncompatibleMods();
}
if (AngelicaConfig.enableHudCaching){
@@ -40,8 +49,8 @@ public class MixinCompatHackTweaker implements ITweaker {
private void disableXaerosMinimapWaypointTransformer(){
try {
LaunchClassLoader lcl = Launch.classLoader;
Field xformersField = lcl.getClass().getDeclaredField("transformers");
final LaunchClassLoader lcl = Launch.classLoader;
final Field xformersField = lcl.getClass().getDeclaredField("transformers");
xformersField.setAccessible(true);
@SuppressWarnings("unchecked")
List<IClassTransformer> xformers = (List<IClassTransformer>) xformersField.get(lcl);
@@ -57,14 +66,14 @@ public class MixinCompatHackTweaker implements ITweaker {
}
}
private void disableOptifineFastcraftAndBetterFPS() {
// Remove Optifine, Fastcraft, and BetterFPS transformers & Mod Containers
@SuppressWarnings("unchecked")
private void disableIncompatibleMods() {
// Remove transformers, Mod Containers, and mixins for Optifine, Fastcraft, BetterFPS and other incompatible mods
try {
LaunchClassLoader lcl = Launch.classLoader;
Field xformersField = lcl.getClass().getDeclaredField("transformers");
final LaunchClassLoader lcl = Launch.classLoader;
final Field xformersField = lcl.getClass().getDeclaredField("transformers");
xformersField.setAccessible(true);
@SuppressWarnings("unchecked")
List<IClassTransformer> xformers = (List<IClassTransformer>) xformersField.get(lcl);
final List<IClassTransformer> xformers = (List<IClassTransformer>) xformersField.get(lcl);
for (int idx = xformers.size() - 1; idx >= 0; idx--) {
final String name = xformers.get(idx).getClass().getName();
if (name.startsWith("optifine") || name.startsWith("fastcraft") || name.startsWith("me.guichaguri.betterfps")) {
@@ -76,17 +85,72 @@ public class MixinCompatHackTweaker implements ITweaker {
throw new RuntimeException(e);
}
try {
Field injectedContainersField = Loader.class.getDeclaredField("injectedContainers");
final Field injectedContainersField = Loader.class.getDeclaredField("injectedContainers");
injectedContainersField.setAccessible(true);
@SuppressWarnings("unchecked")
List<String> containers = (List<String> ) injectedContainersField.get(Loader.class);
final List<String> containers = (List<String> ) injectedContainersField.get(Loader.class);
for (int idx = containers.size() - 1; idx >= 0; idx--) {
final String name = containers.get(idx);
final String name = containers.get(idx);
if (name.startsWith("optifine") || name.startsWith("fastcraft")) {
LOGGER.info("Removing mod container " + name);
containers.remove(idx);
}
}
final Field reparsedCoremodsField = CoreModManager.class.getDeclaredField("reparsedCoremods");
final Field loadedCoremodsField = CoreModManager.class.getDeclaredField("loadedCoremods");
reparsedCoremodsField.setAccessible(true);
loadedCoremodsField.setAccessible(true);
final ArrayList<String> reparsedCoremods = (ArrayList<String>) reparsedCoremodsField.get(CoreModManager.class);
final ArrayList<String> loadedCoremods = (ArrayList<String>) loadedCoremodsField.get(CoreModManager.class);
for (int idx = reparsedCoremods.size() - 1; idx >= 0; idx--) {
final String coreMod = reparsedCoremods.get(idx);
if (coreMod.startsWith("optimizationsandtweaks")) {
LOGGER.info("Removing reparsed coremod " + coreMod);
// Fool the CoreModManager into not checking for a mod container again later
loadedCoremods.add(reparsedCoremods.remove(idx));
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}
try {
final ArrayList<String> mixinConfigsDefault = (ArrayList<String>) Launch.blackboard.get("mixin.configs.default");
if (mixinConfigsDefault != null) {
for (int idx = mixinConfigsDefault.size() - 1; idx >= 0; idx--) {
final String name = mixinConfigsDefault.get(idx);
if (name != null && name.contains("optimizationsandtweaks")) {
LOGGER.info("Removing mixin config " + name);
mixinConfigsDefault.remove(idx);
}
}
}
final Set<Config> mixinConfigs = (Set<Config>) Launch.blackboard.get("mixin.configs.queue");
final Set<Config> toRemove = new HashSet<>();
if (mixinConfigs != null) {
for (Config config : mixinConfigs) {
final String name = config.getName();
if (name != null && name.contains("optimizationsandtweaks")) {
LOGGER.info("Removing queued mixin config " + config.getName());
toRemove.add(config);
}
}
mixinConfigs.removeAll(toRemove);
}
final MixinPlatformManager platformManager = (MixinPlatformManager) Launch.blackboard.get("mixin.platform");
if (platformManager != null) {
final Field containersField = platformManager.getClass().getDeclaredField("containers");
containersField.setAccessible(true);
final Map<IContainerHandle, MixinContainer> containers = (Map<IContainerHandle, MixinContainer>) containersField.get(platformManager);
for (Map.Entry<IContainerHandle, MixinContainer> entry : containers.entrySet()) {
final String attribute = entry.getKey().getAttribute("MixinConfigs");
if(attribute != null && attribute.contains("optimizationsandtweaks")) {
LOGGER.info("Removing mixin container " + entry.getKey().toString());
containers.remove(entry.getKey());
}
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}
@@ -27,7 +27,9 @@ public enum Mixins {
.setPhase(Phase.EARLY).addMixinClasses(
"angelica.MixinActiveRenderInfo"
,"angelica.MixinEntityRenderer"
,"angelica.MixinGameSettings"
,"angelica.MixinMinecraft"
,"angelica.MixinMinecraftServer"
,"angelica.optimizations.MixinRendererLivingEntity"
,"angelica.MixinFMLClientHandler"
,"angelica.bugfixes.MixinRenderGlobal_DestroyBlock"
@@ -76,6 +78,11 @@ public enum Mixins {
.setApplyIf(() -> AngelicaConfig.dynamicItemRenderDistance)
.addTargetedMod(TargetedMod.VANILLA)),
ANGELICA_ITEM_DISPLAY_LIST_OPTIMIZATION(new Builder("Optimized item rendering by wrapping them with display lists")
.setPhase(Phase.EARLY).addMixinClasses("angelica.itemrenderer.MixinItemRenderer").setSide(Side.CLIENT)
.setApplyIf(() -> AngelicaConfig.optimizeInWorldItemRendering)
.addTargetedMod(TargetedMod.VANILLA)),
// Not compatible with the lwjgl debug callbacks, so disable if that's enabled
ARCHAIC_SPLASH(new Builder("ArchaicFix Splash").addTargetedMod(TargetedMod.VANILLA).setSide(Side.CLIENT)
.setPhase(Phase.EARLY).setApplyIf(() -> AngelicaConfig.showSplashMemoryBar && !AngelicaMod.lwjglDebug).addMixinClasses(
@@ -300,7 +307,7 @@ public enum Mixins {
),
NOTFINE_NO_CUSTOM_ITEM_TEXTURES(new Builder("NotFine no Custom Item Textures")
.setSide(Side.CLIENT).setPhase(Phase.EARLY)
.setApplyIf(() -> !AngelicaConfig.enableMCPatcherForgeFeatures || !MCPatcherForgeConfig.instance().customItemTexturesEnabled)
.setApplyIf(() -> !AngelicaConfig.enableMCPatcherForgeFeatures || !MCPatcherForgeConfig.CustomItemTextures.enabled)
.addTargetedMod(TargetedMod.VANILLA)
.addMixinClasses(addPrefix("notfine.glint.",
"MixinItemRenderer",
@@ -384,7 +391,7 @@ public enum Mixins {
),
MCPATCHER_FORGE_CUSTOM_COLORS(new Builder("MCP:F Custom Colors")
.setSide(Mixins.Side.CLIENT).setPhase(Phase.EARLY)
.setApplyIf(() -> AngelicaConfig.enableMCPatcherForgeFeatures && MCPatcherForgeConfig.instance().customColorsEnabled)
.setApplyIf(() -> AngelicaConfig.enableMCPatcherForgeFeatures && MCPatcherForgeConfig.CustomColors.enabled)
.addTargetedMod(TargetedMod.VANILLA)
.addMixinClasses(addPrefix("mcpatcherforge.cc.",
"block.material.MixinMapColor",
@@ -440,7 +447,7 @@ public enum Mixins {
),
MCPATCHER_FORGE_CUSTOM_ITEM_TEXTURES(new Builder("MCP:F Custom Item Textures")
.setSide(Side.CLIENT).setPhase(Phase.EARLY)
.setApplyIf(() -> AngelicaConfig.enableMCPatcherForgeFeatures && MCPatcherForgeConfig.instance().customItemTexturesEnabled)
.setApplyIf(() -> AngelicaConfig.enableMCPatcherForgeFeatures && MCPatcherForgeConfig.CustomItemTextures.enabled)
.addTargetedMod(TargetedMod.VANILLA)
.addMixinClasses(addPrefix("mcpatcherforge.cit.",
"client.renderer.entity.MixinRenderBiped",
@@ -459,13 +466,13 @@ public enum Mixins {
),
MCPATCHER_FORGE_CONNECTED_TEXTURES(new Builder("MCP:F Connected Textures")
.setSide(Side.CLIENT).setPhase(Phase.EARLY)
.setApplyIf(() -> AngelicaConfig.enableMCPatcherForgeFeatures && MCPatcherForgeConfig.instance().connectedTexturesEnabled)
.setApplyIf(() -> AngelicaConfig.enableMCPatcherForgeFeatures && MCPatcherForgeConfig.ConnectedTextures.enabled)
.addTargetedMod(TargetedMod.VANILLA)
.addMixinClasses("mcpatcherforge.ctm.MixinRenderBlocks")
),
MCPATCHER_FORGE_EXTENDED_HD(new Builder("MCP:F Extended hd")
.setSide(Side.CLIENT).setPhase(Phase.EARLY)
.setApplyIf(() -> AngelicaConfig.enableMCPatcherForgeFeatures && MCPatcherForgeConfig.instance().extendedHDEnabled)
.setApplyIf(() -> AngelicaConfig.enableMCPatcherForgeFeatures && MCPatcherForgeConfig.ExtendedHD.enabled)
.addTargetedMod(TargetedMod.VANILLA)
.addMixinClasses(addPrefix("mcpatcherforge.hd.",
"MixinTextureClock",
@@ -475,14 +482,14 @@ public enum Mixins {
),
MCPATCHER_FORGE_EXTENDED_HD_FONT(new Builder("MCP:F Extended HD Font")
.setSide(Side.CLIENT).setPhase(Phase.EARLY)
.setApplyIf(() -> (AngelicaConfig.enableMCPatcherForgeFeatures && MCPatcherForgeConfig.instance().extendedHDEnabled && MCPatcherForgeConfig.instance().hdFont))
.setApplyIf(() -> (AngelicaConfig.enableMCPatcherForgeFeatures && MCPatcherForgeConfig.ExtendedHD.enabled && MCPatcherForgeConfig.ExtendedHD.hdFont))
.addTargetedMod(TargetedMod.VANILLA)
.addExcludedMod(TargetedMod.COFHCORE)
.addMixinClasses("mcpatcherforge.hd.MixinFontRenderer")
),
MCPATCHER_FORGE_RANDOM_MOBS(new Builder("MCP:F Random Mobs")
.setSide(Side.CLIENT).setPhase(Phase.EARLY)
.setApplyIf(() -> AngelicaConfig.enableMCPatcherForgeFeatures && MCPatcherForgeConfig.instance().randomMobsEnabled)
.setApplyIf(() -> AngelicaConfig.enableMCPatcherForgeFeatures && MCPatcherForgeConfig.RandomMobs.enabled)
.addTargetedMod(TargetedMod.VANILLA)
.addMixinClasses(addPrefix("mcpatcherforge.mob.",
"MixinRender",
@@ -499,7 +506,7 @@ public enum Mixins {
),
MCPATCHER_FORGE_SKY(new Builder("MCP:F Sky")
.setSide(Side.CLIENT).setPhase(Phase.EARLY)
.setApplyIf(() -> AngelicaConfig.enableMCPatcherForgeFeatures && MCPatcherForgeConfig.instance().betterSkiesEnabled)
.setApplyIf(() -> AngelicaConfig.enableMCPatcherForgeFeatures && MCPatcherForgeConfig.BetterSkies.enabled)
.addTargetedMod(TargetedMod.VANILLA)
.addMixinClasses(addPrefix("mcpatcherforge.sky.",
"MixinEffectRenderer",
@@ -509,32 +516,32 @@ public enum Mixins {
MCPATCHER_FORGE_CC_NO_CTM(new Builder("MCP:F Custom Colors, no Connected Textures")
.setSide(Side.CLIENT).setPhase(Phase.EARLY)
.setApplyIf(() -> AngelicaConfig.enableMCPatcherForgeFeatures
&& !MCPatcherForgeConfig.instance().connectedTexturesEnabled
&& MCPatcherForgeConfig.instance().customColorsEnabled)
&& !MCPatcherForgeConfig.ConnectedTextures.enabled
&& MCPatcherForgeConfig.CustomColors.enabled)
.addTargetedMod(TargetedMod.VANILLA)
.addMixinClasses("mcpatcherforge.cc_ctm.MixinRenderBlocksNoCTM")
),
MCPATCHER_FORGE_CTM_NO_CC(new Builder("MCP:F Connected Textures, no Custom Colours")
.setSide(Side.CLIENT).setPhase(Phase.EARLY)
.setApplyIf(() -> AngelicaConfig.enableMCPatcherForgeFeatures
&& MCPatcherForgeConfig.instance().connectedTexturesEnabled
&& !MCPatcherForgeConfig.instance().customColorsEnabled)
&& MCPatcherForgeConfig.ConnectedTextures.enabled
&& !MCPatcherForgeConfig.CustomColors.enabled)
.addTargetedMod(TargetedMod.VANILLA)
.addMixinClasses("mcpatcherforge.ctm_cc.MixinRenderBlocksNoCC")
),
MCPATCHER_FORGE_CTM_AND_CC(new Builder("MCP:F Connected Textures and Custom Colors")
.setSide(Side.CLIENT).setPhase(Phase.EARLY)
.setApplyIf(() -> AngelicaConfig.enableMCPatcherForgeFeatures
&& MCPatcherForgeConfig.instance().connectedTexturesEnabled
&& MCPatcherForgeConfig.instance().customColorsEnabled)
&& MCPatcherForgeConfig.ConnectedTextures.enabled
&& MCPatcherForgeConfig.CustomColors.enabled)
.addTargetedMod(TargetedMod.VANILLA)
.addMixinClasses("mcpatcherforge.ctm_cc.MixinRenderBlocks")
),
MCPATCHER_FORGE_CTM_OR_CC(new Builder("MCP:F Connected Textures or Custom Colors")
.setSide(Side.CLIENT).setPhase(Phase.EARLY)
.setApplyIf(() -> AngelicaConfig.enableMCPatcherForgeFeatures
&& MCPatcherForgeConfig.instance().connectedTexturesEnabled
|| MCPatcherForgeConfig.instance().customColorsEnabled)
&& MCPatcherForgeConfig.ConnectedTextures.enabled
|| MCPatcherForgeConfig.CustomColors.enabled)
.addTargetedMod(TargetedMod.VANILLA)
.addMixinClasses("mcpatcherforge.ctm_cc.MixinTextureMap")
),
@@ -577,7 +584,7 @@ public enum Mixins {
NotFineConfig.loadSettings();
//This may be possible to handle differently or fix.
if(loadedCoreMods.contains("cofh.asm.LoadingPlugin")) {
MCPatcherForgeConfig.instance().hdFont = false;
MCPatcherForgeConfig.ExtendedHD.hdFont = false;
}
final List<String> mixins = new ArrayList<>();
final List<String> notLoading = new ArrayList<>();
@@ -0,0 +1,6 @@
package com.gtnewhorizons.angelica.mixins.interfaces;
public interface IGameSettingsExt {
boolean angelica$showFpsGraph();
void angelica$setShowFpsGraph(boolean renderFpsGraph);
}
@@ -1,5 +1,7 @@
package com.gtnewhorizons.angelica.proxy;
import static com.gtnewhorizons.angelica.loading.AngelicaTweaker.LOGGER;
import com.google.common.base.Objects;
import com.gtnewhorizon.gtnhlib.client.renderer.vertex.DefaultVertexFormat;
import com.gtnewhorizon.gtnhlib.client.renderer.vertex.VertexFormat;
@@ -7,6 +9,10 @@ import com.gtnewhorizons.angelica.compat.ModStatus;
import com.gtnewhorizons.angelica.compat.bettercrashes.BetterCrashesCompat;
import com.gtnewhorizons.angelica.config.AngelicaConfig;
import com.gtnewhorizons.angelica.config.CompatConfig;
import com.gtnewhorizons.angelica.debug.F3Direction;
import com.gtnewhorizons.angelica.debug.FrametimeGraph;
import com.gtnewhorizons.angelica.debug.TPSGraph;
import com.gtnewhorizons.angelica.mixins.interfaces.IGameSettingsExt;
import com.gtnewhorizons.angelica.dynamiclights.DynamicLights;
import com.gtnewhorizons.angelica.glsm.GLStateManager;
import com.gtnewhorizons.angelica.glsm.debug.OpenGLDebugging;
@@ -26,6 +32,9 @@ import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import cpw.mods.fml.common.gameevent.TickEvent;
import cpw.mods.fml.common.registry.GameData;
import cpw.mods.fml.relauncher.ReflectionHelper;
import java.lang.management.ManagementFactory;
import java.util.Locale;
import java.util.concurrent.ConcurrentHashMap;
import jss.notfine.core.Settings;
import me.jellysquid.mods.sodium.client.SodiumDebugScreenHandler;
import net.coderbot.iris.Iris;
@@ -53,15 +62,11 @@ import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.world.WorldEvent;
import org.lwjgl.input.Keyboard;
import java.lang.management.ManagementFactory;
import java.util.Locale;
import java.util.concurrent.ConcurrentHashMap;
import static com.gtnewhorizons.angelica.loading.AngelicaTweaker.LOGGER;
public class ClientProxy extends CommonProxy {
final Minecraft mc = Minecraft.getMinecraft();
final FrametimeGraph frametimeGraph = new FrametimeGraph();
final TPSGraph tpsGraph = new TPSGraph();
@Override
public void preInit(FMLPreInitializationEvent event) {
@@ -183,19 +188,30 @@ public class ClientProxy extends CommonProxy {
}
}
@SubscribeEvent(priority = EventPriority.LOWEST)
public void onRenderOverlay(RenderGameOverlayEvent.Pre event) {
if (event.isCanceled() || !mc.gameSettings.showDebugInfo) return;
if (AngelicaConfig.modernizeF3Screen && event.type == RenderGameOverlayEvent.ElementType.CROSSHAIRS) {
F3Direction.renderWorldDirectionsEvent(mc, event);
event.setCanceled(true);
}
}
@SubscribeEvent(priority = EventPriority.LOWEST)
public void onRenderOverlay(RenderGameOverlayEvent.Text event) {
Minecraft mc = Minecraft.getMinecraft();
if (event.isCanceled() || !mc.gameSettings.showDebugInfo || event.left.isEmpty()) return;
NetHandlerPlayClient cl = mc.getNetHandler();
if (cl != null) {
IntegratedServer srv = mc.getIntegratedServer();
if (srv != null) {
String s = String.format("Integrated server @ %.0f ms ticks", lastIntegratedTickTime);
event.left.add(1, s);
event.left.add(Math.min(event.left.size(), 1), s);
}
}
if (AngelicaConfig.showBlockDebugInfo && mc.objectMouseOver != null && mc.objectMouseOver.typeOfHit == MovingObjectPosition.MovingObjectType.BLOCK) {
if (!event.right.isEmpty() && !Objects.firstNonNull(event.right.get(event.right.size() - 1), "").isEmpty()) event.right.add("");
Block block = mc.theWorld.getBlock(mc.objectMouseOver.blockX, mc.objectMouseOver.blockY, mc.objectMouseOver.blockZ);
@@ -203,6 +219,7 @@ public class ClientProxy extends CommonProxy {
event.right.add(Block.blockRegistry.getNameForObject(block));
event.right.add("meta: " + meta);
}
if (DynamicLights.isEnabled()) {
var builder = new StringBuilder("Dynamic Light Sources: ");
DynamicLights dl = DynamicLights.get();
@@ -210,6 +227,7 @@ public class ClientProxy extends CommonProxy {
event.right.add(builder.toString());
}
if (AngelicaConfig.modernizeF3Screen) {
boolean hasReplacedXYZ = false;
for (int i = 0; i < event.left.size() - 3; i++) {
@@ -250,6 +268,8 @@ public class ClientProxy extends CommonProxy {
}
}
event.setCanceled(true);
// TODO don't cancel the event and render here,
// instead mixin into the vanilla code and add a background to it
/* render ourselves for modern background */
FontRenderer fontrenderer = mc.fontRenderer;
int fontColor = 0xe0e0e0;
@@ -272,6 +292,14 @@ public class ClientProxy extends CommonProxy {
Gui.drawRect(strX - 1, strY - 1, strX + w + 1, strY + fontrenderer.FONT_HEIGHT - 1, rectColor);
fontrenderer.drawString(msg, strX, strY, fontColor);
}
// Draw a frametime graph
if (((IGameSettingsExt)mc.gameSettings).angelica$showFpsGraph()) {
frametimeGraph.render();
if (Minecraft.getMinecraft().isSingleplayer()) {
tpsGraph.render();
}
}
}
}
@@ -307,4 +335,14 @@ public class ClientProxy extends CommonProxy {
event.newfov = 1.0F;
}
}
@Override
public void putFrametime(long time) {
frametimeGraph.putSample(time);
}
@Override
public void putTicktime(long time) {
tpsGraph.putSample(time);
}
}
@@ -2,7 +2,6 @@ package com.gtnewhorizons.angelica.proxy;
import com.gtnewhorizons.angelica.common.BlockTest;
import com.gtnewhorizons.angelica.config.AngelicaConfig;
import com.gtnewhorizons.angelica.utils.AssetLoader;
import cpw.mods.fml.common.event.FMLInitializationEvent;
import cpw.mods.fml.common.event.FMLPostInitializationEvent;
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
@@ -20,4 +19,9 @@ public class CommonProxy {
public void init(FMLInitializationEvent event) {}
public void postInit(FMLPostInitializationEvent event) {}
// Only present on the client!
public void putFrametime(long time) { throw new UnsupportedOperationException(); }
public void putTicktime(long time) { throw new UnsupportedOperationException(); }
}
@@ -0,0 +1,111 @@
/*
* This file is part of FalseTweaks.
*
* Copyright (C) 2022-2024 FalsePattern
* All Rights Reserved
*
* Modifications by Angelica in accordance with LGPL v3.0
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* FalseTweaks is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FalseTweaks is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with FalseTweaks. If not, see <https://www.gnu.org/licenses/>.
*/
package com.gtnewhorizons.angelica.rendering;
import com.gtnewhorizons.angelica.config.AngelicaConfig;
import lombok.AccessLevel;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.val;
import org.lwjgl.opengl.GL11;
import net.minecraft.client.renderer.GLAllocation;
import net.minecraft.client.resources.IResourceManager;
import net.minecraft.client.resources.IResourceManagerReloadListener;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class ItemRenderListManager implements IResourceManagerReloadListener {
public static final ItemRenderListManager INSTANCE = new ItemRenderListManager();
private final Map<ItemProp, Integer> theMap = new HashMap<>();
private final List<ItemProp> propList = new ArrayList<>();
private final ItemProp prop = new ItemProp();
private int list = 0;
public boolean pre(float a, float b, float c, float d, int e, int f, float g) {
prop.set(a, b, c, d, e, f, g);
if (theMap.containsKey(prop)) {
val list = theMap.get(prop);
propList.add(propList.remove(propList.indexOf(prop)));
GL11.glCallList(list);
return true;
} else {
if (propList.size() >= AngelicaConfig.itemRendererDisplayListCacheSize) {
val oldProp = propList.remove(0);
GLAllocation.deleteDisplayLists(theMap.remove(oldProp));
}
list = GLAllocation.generateDisplayLists(1);
val newProp = new ItemProp(prop);
theMap.put(newProp, list);
propList.add(newProp);
GL11.glNewList(list, GL11.GL_COMPILE);
return false;
}
}
public void post() {
GL11.glEndList();
GL11.glCallList(list);
}
@Override
public void onResourceManagerReload(IResourceManager p_110549_1_) {
propList.clear();
theMap.forEach((key, value) -> GLAllocation.deleteDisplayLists(value));
theMap.clear();
}
@NoArgsConstructor
@Data
public class ItemProp {
private float a;
private float b;
private float c;
private float d;
private int e;
private int f;
private float g;
public ItemProp(ItemProp old) {
set(old.a, old.b, old.c, old.d, old.e, old.f, old.g);
}
public void set(float a, float b, float c, float d, int e, int f, float g) {
this.a = a;
this.b = b;
this.c = c;
this.d = d;
this.e = e;
this.f = f;
this.g = g;
}
}
}
+15 -14
View File
@@ -1,5 +1,7 @@
package com.prupe.mcpatcher;
import jss.notfine.config.MCPatcherForgeConfig;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Formatter;
@@ -8,10 +10,10 @@ import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import jss.notfine.config.MCPatcherForgeConfig;
public class MCLogger {
private static final org.apache.logging.log4j.Logger MAIN_LOGGER = org.apache.logging.log4j.LogManager.getLogger("MCPatcherForge");
private static final Map<String, MCLogger> allLoggers = new HashMap<>();
public static final Level ERROR = new ErrorLevel();
@@ -44,16 +46,15 @@ public class MCLogger {
private MCLogger(Category category, String logPrefix) {
this.logPrefix = logPrefix;
logger = Logger.getLogger(category.name);
MCPatcherForgeConfig config = MCPatcherForgeConfig.instance();
logger.setLevel(Level.parse(switch (category) {
case CUSTOM_COLORS -> config.customColorsLoggingLevel;
case CUSTOM_ITEM_TEXTURES -> config.customItemTexturesLoggingLevel;
case CONNECTED_TEXTURES -> config.connectedTexturesLoggingLevel;
case EXTENDED_HD -> config.extendedHDLoggingLevel;
case RANDOM_MOBS -> config.randomMobsLoggingLevel;
case BETTER_SKIES -> config.betterSkiesLoggingLevel;
default -> Level.INFO.getName();
}));
logger.setLevel(switch (category) {
case CUSTOM_COLORS -> MCPatcherForgeConfig.CustomColors.logging.level;
case CUSTOM_ITEM_TEXTURES -> MCPatcherForgeConfig.CustomItemTextures.logging.level;
case CONNECTED_TEXTURES -> MCPatcherForgeConfig.ConnectedTextures.logging.level;
case EXTENDED_HD -> MCPatcherForgeConfig.ExtendedHD.logging.level;
case RANDOM_MOBS -> MCPatcherForgeConfig.RandomMobs.logging.level;
case BETTER_SKIES -> MCPatcherForgeConfig.BetterSkies.logging.level;
default -> Level.INFO;
});
logger.setUseParentHandlers(false);
logger.addHandler(new Handler() {
@@ -72,14 +73,14 @@ public class MCLogger {
prefix.append("\n");
message = message.substring(1);
}
return prefix + "[" + MCLogger.this.logPrefix + "] " + level.toString() + ": " + message;
return prefix + "[" + MCLogger.this.logPrefix + "/" + level.toString() + "]: " + message;
}
}
};
@Override
public void publish(LogRecord record) {
System.out.println(formatter.format(record));
MAIN_LOGGER.info(formatter.format(record));
}
@Override
@@ -34,14 +34,14 @@ public class ColorizeBlock {
private static final MCLogger logger = MCLogger.getLogger(MCLogger.Category.CUSTOM_COLORS);
private static final boolean useWaterColors = MCPatcherForgeConfig.instance().ccWater;
private static final boolean useTreeColors = MCPatcherForgeConfig.instance().ccTree;
private static final boolean useRedstoneColors = MCPatcherForgeConfig.instance().ccRedstone;
private static final boolean useStemColors = MCPatcherForgeConfig.instance().ccStem;
private static final boolean useBlockColors = MCPatcherForgeConfig.instance().ccOtherBlocks;
private static final boolean useWaterColors = MCPatcherForgeConfig.CustomColors.water;
private static final boolean useTreeColors = MCPatcherForgeConfig.CustomColors.tree;
private static final boolean useRedstoneColors = MCPatcherForgeConfig.CustomColors.redstone;
private static final boolean useStemColors = MCPatcherForgeConfig.CustomColors.stem;
private static final boolean useBlockColors = MCPatcherForgeConfig.CustomColors.otherBlocks;
private static final boolean enableSmoothBiomes = MCPatcherForgeConfig.instance().smoothBiomes;
private static final boolean enableTestColorSmoothing = MCPatcherForgeConfig.instance().testColorSmoothing;
private static final boolean enableSmoothBiomes = MCPatcherForgeConfig.CustomColors.smoothBiomes;
private static final boolean enableTestColorSmoothing = MCPatcherForgeConfig.CustomColors.testColorSmoothing;
private static final ResourceLocation REDSTONE_COLORS = TexturePackAPI
.newMCPatcherResourceLocation("colormap/redstone.png");
@@ -73,7 +73,7 @@ public class ColorizeBlock {
private static IColorMap waterColorMap;
private static float[][] redstoneColor; // colormap/redstone.png
private static final int blockBlendRadius = MCPatcherForgeConfig.instance().blockBlendRadius;
private static final int blockBlendRadius = MCPatcherForgeConfig.CustomColors.blockBlendRadius;
public static int blockColor;
public static boolean isSmooth;
@@ -26,7 +26,7 @@ import jss.notfine.config.MCPatcherForgeConfig;
public class ColorizeWorld {
private static final int fogBlendRadius = MCPatcherForgeConfig.instance().fogBlendRadius;
private static final int fogBlendRadius = MCPatcherForgeConfig.CustomColors.fogBlendRadius;
private static final ResourceLocation UNDERWATERCOLOR = TexturePackAPI
.newMCPatcherResourceLocation("colormap/underwater.png");
@@ -20,15 +20,15 @@ public class Colorizer {
static final ResourceLocation COLOR_PROPERTIES = TexturePackAPI.newMCPatcherResourceLocation("color.properties");
private static PropertiesFile properties;
static final boolean usePotionColors = MCPatcherForgeConfig.instance().ccPotion;
static final boolean useParticleColors = MCPatcherForgeConfig.instance().ccParticle;
static final boolean useFogColors = MCPatcherForgeConfig.instance().ccFog;
static final boolean useCloudType = MCPatcherForgeConfig.instance().ccClouds;
static final boolean useMapColors = MCPatcherForgeConfig.instance().ccMap;
static final boolean useDyeColors = MCPatcherForgeConfig.instance().ccDye;
static final boolean useTextColors = MCPatcherForgeConfig.instance().ccText;
static final boolean useXPOrbColors = MCPatcherForgeConfig.instance().ccXPOrb;
static final boolean useEggColors = MCPatcherForgeConfig.instance().ccEgg;
static final boolean usePotionColors = MCPatcherForgeConfig.CustomColors.potion;
static final boolean useParticleColors = MCPatcherForgeConfig.CustomColors.particle;
static final boolean useFogColors = MCPatcherForgeConfig.CustomColors.fog;
static final boolean useCloudType = MCPatcherForgeConfig.CustomColors.clouds;
static final boolean useMapColors = MCPatcherForgeConfig.CustomColors.map;
static final boolean useDyeColors = MCPatcherForgeConfig.CustomColors.dye;
static final boolean useTextColors = MCPatcherForgeConfig.CustomColors.text;
static final boolean useXPOrbColors = MCPatcherForgeConfig.CustomColors.xporb;
static final boolean useEggColors = MCPatcherForgeConfig.CustomColors.egg;
public static final float[] setColor = new float[3];
@@ -24,7 +24,7 @@ public final class Lightmap {
private static final int HEIGHT_WITHOUT_NIGHTVISION = 2 * LIGHTMAP_SIZE;
private static final int HEIGHT_WITH_NIGHTVISION = 4 * LIGHTMAP_SIZE;
private static final boolean useLightmaps = MCPatcherForgeConfig.instance().ccLightmaps;
private static final boolean useLightmaps = MCPatcherForgeConfig.CustomColors.lightmaps;
private static final Map<Integer, Lightmap> lightmaps = new HashMap<>();
@@ -46,9 +46,9 @@ public class CITUtils {
static Item itemCompass;
static Item itemClock;
static final boolean enableItems = MCPatcherForgeConfig.instance().citItems;
static final boolean enableEnchantments = MCPatcherForgeConfig.instance().citEnchantments;
static final boolean enableArmor = MCPatcherForgeConfig.instance().citArmor;
static final boolean enableItems = MCPatcherForgeConfig.CustomItemTextures.items;
static final boolean enableEnchantments = MCPatcherForgeConfig.CustomItemTextures.enchantments;
static final boolean enableArmor = MCPatcherForgeConfig.CustomItemTextures.armor;
private static TileLoader tileLoader;
private static final Map<Item, List<ItemOverride>> items = new IdentityHashMap<>();
@@ -9,7 +9,6 @@ import java.util.Map;
import java.util.Set;
import net.minecraft.block.Block;
import net.minecraft.client.renderer.RenderBlocks;
import net.minecraft.util.IIcon;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.IBlockAccess;
@@ -32,9 +31,6 @@ public class CTMUtils {
private static final MCLogger logger = MCLogger.getLogger(MCLogger.Category.CONNECTED_TEXTURES, "CTM");
private static final boolean enableStandard = MCPatcherForgeConfig.instance().ctmStandard;
private static final boolean enableNonStandard = MCPatcherForgeConfig.instance().ctmNonStandard;
private static final List<TileOverride> allOverrides = new ArrayList<>();
private static final Map<Block, List<BlockStateMatcher>> blockOverrides = new IdentityHashMap<>();
private static final Map<String, List<TileOverride>> tileOverrides = new HashMap<>();
@@ -81,7 +77,7 @@ public class CTMUtils {
tileLoader = new TileLoader("textures/blocks", logger);
RenderPassAPI.instance.refreshBlendingOptions();
if (enableStandard || enableNonStandard) {
if (MCPatcherForgeConfig.ConnectedTextures.standard || MCPatcherForgeConfig.ConnectedTextures.nonStandard) {
for (ResourceLocation resource : ResourceList.getInstance()
.listResources(TexturePackAPI.MCPATCHER_SUBDIR + "ctm", ".properties", true)) {
registerOverride(TileOverride.create(resource, tileLoader));
@@ -160,7 +156,7 @@ public class CTMUtils {
public static void reset() {}
private static boolean checkFace(int face) {
return face < 0 ? enableNonStandard : enableStandard;
return face < 0 ? MCPatcherForgeConfig.ConnectedTextures.nonStandard : MCPatcherForgeConfig.ConnectedTextures.standard;
}
private static boolean checkRenderType(Block block) {
@@ -12,8 +12,6 @@ import jss.notfine.config.MCPatcherForgeConfig;
public class GlassPaneRenderer {
private static final boolean enable = MCPatcherForgeConfig.instance().ctmGlassPane;
public static boolean skipPaneRendering;
public static boolean skipTopEdgeRendering;
public static boolean skipBottomEdgeRendering;
@@ -47,7 +45,7 @@ public class GlassPaneRenderer {
private static boolean setupIcons(RenderBlocks renderBlocks, Block blockPane, IIcon origIcon, int x, int y, int z) {
skipPaneRendering = skipBottomEdgeRendering = skipTopEdgeRendering = false;
if (!enable) {
if (!MCPatcherForgeConfig.ConnectedTextures.glassPane) {
return false;
}
for (int face = BlockOrientation.NORTH_FACE; face <= BlockOrientation.EAST_FACE; face++) {
@@ -15,8 +15,6 @@ import jss.notfine.config.MCPatcherForgeConfig;
abstract public class TileOverrideIterator implements Iterator<TileOverride> {
private static final int MAX_RECURSION = MCPatcherForgeConfig.instance().maxRecursion;
private final Map<Block, List<BlockStateMatcher>> allBlockOverrides;
private final Map<String, List<TileOverride>> allTileOverrides;
@@ -118,7 +116,7 @@ abstract public class TileOverrideIterator implements Iterator<TileOverride> {
lastMatchedOverride = null;
skipOverrides.clear();
pass: for (int pass = 0; pass < MAX_RECURSION; pass++) {
pass: for (int pass = 0; pass < MCPatcherForgeConfig.ConnectedTextures.maxRecursion; pass++) {
while (hasNext()) {
TileOverride override = next();
IIcon newIcon = getTile(override, renderBlockState, origIcon);
@@ -28,7 +28,7 @@ public class CustomAnimation implements Comparable<CustomAnimation> {
private static final MCLogger logger = MCLogger.getLogger(MCLogger.Category.EXTENDED_HD, "Animation");
private static final boolean enable = MCPatcherForgeConfig.instance().animations;
private static final boolean enable = MCPatcherForgeConfig.ExtendedHD.animations;
private static final Set<PropertiesFile> pending = new HashSet<>();
private static final List<CustomAnimation> animations = new ArrayList<>();
@@ -48,10 +48,10 @@ public class FancyDial {
private static final boolean fboSupported = GLContext.getCapabilities().GL_EXT_framebuffer_object;
private static final boolean gl13Supported = GLContext.getCapabilities().OpenGL13;
private static final boolean enableCompass = MCPatcherForgeConfig.instance().fancyCompass;
private static final boolean enableClock = MCPatcherForgeConfig.instance().fancyClock;
private static final boolean useGL13 = gl13Supported && MCPatcherForgeConfig.instance().useGL13;
private static final boolean useScratchTexture = MCPatcherForgeConfig.instance().useScratchTexture;
private static final boolean enableCompass = MCPatcherForgeConfig.ExtendedHD.fancyCompass;
private static final boolean enableClock = MCPatcherForgeConfig.ExtendedHD.fancyClock;
private static final boolean useGL13 = gl13Supported && MCPatcherForgeConfig.ExtendedHD.useGL13;
private static final boolean useScratchTexture = MCPatcherForgeConfig.ExtendedHD.useScratchTexture;
private static final int glAttributes;
private static boolean initialized;
private static boolean active;
@@ -21,8 +21,8 @@ public class FontUtils {
private static final MCLogger logger = MCLogger.getLogger(MCLogger.Category.EXTENDED_HD);
private static final boolean enable = MCPatcherForgeConfig.instance().hdFont;
private static final boolean enableNonHD = MCPatcherForgeConfig.instance().nonHDFontWidth;
private static final boolean enable = MCPatcherForgeConfig.ExtendedHD.hdFont;
private static final boolean enableNonHD = MCPatcherForgeConfig.ExtendedHD.nonHDFontWidth;
private static final int ROWS = 16;
private static final int COLS = 16;
@@ -32,8 +32,8 @@ public class MipmapHelper {
static final int TEX_DATA_TYPE = GL12.GL_UNSIGNED_INT_8_8_8_8_REV;
private static final boolean mipmapSupported;
static final boolean mipmapEnabled = MCPatcherForgeConfig.instance().mipmap;
static final int maxMipmapLevel = MCPatcherForgeConfig.instance().maxMipMapLevel;
static final boolean mipmapEnabled = MCPatcherForgeConfig.ExtendedHD.mipmap;
static final int maxMipmapLevel = MCPatcherForgeConfig.ExtendedHD.maxMipMapLevel;
private static final boolean useMipmap;
private static final boolean anisoSupported;
@@ -53,14 +53,14 @@ public class MipmapHelper {
if (anisoSupported) {
anisoMax = (int) GL11.glGetFloat(EXTTextureFilterAnisotropic.GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT);
checkGLError("glGetFloat(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT)");
anisoLevel = Math.max(Math.min(MCPatcherForgeConfig.instance().anisotropicFiltering, anisoMax), 1);
anisoLevel = Math.max(Math.min(MCPatcherForgeConfig.ExtendedHD.anisotropicFiltering, anisoMax), 1);
} else {
anisoMax = anisoLevel = 1;
}
lodSupported = GLContext.getCapabilities().GL_EXT_texture_lod_bias;
if (lodSupported) {
lodBias = MCPatcherForgeConfig.instance().lodBias;
lodBias = MCPatcherForgeConfig.ExtendedHD.lodBias;
} else {
lodBias = 0;
}
@@ -25,7 +25,7 @@ abstract public class ColorMap implements IColorMap {
private static final MCLogger logger = MCLogger.getLogger(MCLogger.Category.CUSTOM_COLORS);
public static final boolean useSwampColors = MCPatcherForgeConfig.instance().swampColors;
public static final boolean useSwampColors = MCPatcherForgeConfig.CustomColors.swampColors;
private static final int FIXED = 0;
private static final int TEMPERATURE_HUMIDITY = 1;
@@ -165,7 +165,7 @@ abstract public class ColorMap implements IColorMap {
unusedPNGs.clear();
defaultColorMapFormat = TEMPERATURE_HUMIDITY;
defaultFlipY = false;
defaultYVariance = MCPatcherForgeConfig.instance().yVariance;
defaultYVariance = MCPatcherForgeConfig.CustomColors.yVariance;
}
public static void reloadColorMapSettings(PropertiesFile properties) {
@@ -11,8 +11,6 @@ import jss.notfine.config.MCPatcherForgeConfig;
// Shared by both CTM and Custom Colors.
public class RenderBlocksUtils {
public static final boolean enableBetterGrass = MCPatcherForgeConfig.instance().betterGrass;
private static final int COLOR = 0;
private static final int NONCOLOR = 1;
private static final int COLOR_AND_NONCOLOR = 2;
@@ -35,7 +33,7 @@ public class RenderBlocksUtils {
colorMultiplierType[5] = COLOR;
} else if (block == Blocks.grass) {
colorMultiplierType[0] = NONCOLOR;
if (enableBetterGrass) {
if (MCPatcherForgeConfig.ConnectedTextures.betterGrass) {
if (isSnowCovered(blockAccess, x, y, z)) {
colorMultiplierType[2] = NONCOLOR;
colorMultiplierType[3] = NONCOLOR;
@@ -135,7 +133,7 @@ public class RenderBlocksUtils {
public static IIcon getGrassTexture(Block block, IBlockAccess blockAccess, int x, int y, int z, int face,
IIcon topIcon) {
if (!enableBetterGrass || face < 2) {
if (!MCPatcherForgeConfig.ConnectedTextures.betterGrass || face < 2) {
return null;
}
boolean isSnow = isSnowCovered(blockAccess, x, y, z);
@@ -31,7 +31,6 @@ public class TileLoader {
private static final List<TileLoader> loaders = new ArrayList<>();
private static final boolean debugTextures = MCPatcherForgeConfig.instance().debugTextures;
private static final Map<String, String> specialTextures = new HashMap<>();
private static final TexturePackChangeHandler changeHandler;
@@ -220,7 +219,7 @@ public class TileLoader {
return true;
}
BufferedImage image = null;
if (!debugTextures) {
if (!MCPatcherForgeConfig.ConnectedTextures.debugTextures) {
image = TexturePackAPI.getImage(resource);
if (image == null) {
subLogger.warning("missing %s", resource);
@@ -20,7 +20,7 @@ public class LineRenderer {
private static final double D_WIDTH = 1.0 / 1024.0;
private static final double D_POS = 1.0 / 256.0;
private static final boolean enable = MCPatcherForgeConfig.instance().leashLine;
private static final boolean enable = MCPatcherForgeConfig.RandomMobs.leashLine;
private static final LineRenderer[] renderers = new LineRenderer[2];
private final ResourceLocation texture;
@@ -23,7 +23,7 @@ public class FireworksHelper {
.newMCPatcherResourceLocation("particle.properties");
private static final MCLogger logger = MCLogger.getLogger(MCLogger.Category.BETTER_SKIES);
private static final boolean enable = MCPatcherForgeConfig.instance().brightenFireworks;
private static final boolean enable = MCPatcherForgeConfig.BetterSkies.brightenFireworks;
private static BlendMethod blendMethod;
public static int getFXLayer(EntityFX entity) {
@@ -28,9 +28,9 @@ public class SkyRenderer {
private static final MCLogger logger = MCLogger.getLogger(MCLogger.Category.BETTER_SKIES);
private static final boolean enable = MCPatcherForgeConfig.instance().skybox;
private static final boolean unloadTextures = MCPatcherForgeConfig.instance().unloadTextures;
public static final double horizonHeight = MCPatcherForgeConfig.instance().horizon;
private static final boolean enable = MCPatcherForgeConfig.BetterSkies.skybox;
private static final boolean unloadTextures = MCPatcherForgeConfig.BetterSkies.unloadTextures;
public static final double horizonHeight = MCPatcherForgeConfig.BetterSkies.horizon;
private static double worldTime;
private static float celestialAngle;
@@ -7,6 +7,7 @@ import cpw.mods.fml.common.Mod;
version = "1.0.0-alpha",
name = "MCPatcherForge",
acceptedMinecraftVersions = "[1.7.10]",
acceptableRemoteVersions = "*")
acceptableRemoteVersions = "*",
guiFactory = "jss.notfine.config.MCPatcherForgeGuiConfigFactory")
public class McPatcherForge {
}
@@ -18,7 +18,7 @@ import jss.notfine.config.NotFineConfig;
public enum AsmTransformers {
RENDERBLOCKS("RenderBlocks transformer", () -> AngelicaConfig.enableMCPatcherForgeFeatures
&& MCPatcherForgeConfig.instance().customColorsEnabled,
&& MCPatcherForgeConfig.CustomColors.enabled,
Side.CLIENT, "jss.notfine.asm.RenderBlocksTransformer"),
WORLDRENDERER("WorldRenderer transformer", () -> NotFineConfig.renderPass, Side.CLIENT,
"jss.notfine.asm.WorldRendererTransformer");
@@ -1,179 +1,296 @@
package jss.notfine.config;
import java.io.File;
import com.gtnewhorizon.gtnhlib.config.Config;
import com.gtnewhorizon.gtnhlib.config.ConfigException;
import com.gtnewhorizon.gtnhlib.config.ConfigurationManager;
import java.util.logging.Level;
import net.minecraft.launchwrapper.Launch;
import net.minecraftforge.common.config.Configuration;
// Adapted from hodgepodge
public class MCPatcherForgeConfig {
private static MCPatcherForgeConfig config;
@Config(modid = "mcpatcherforge", category = "custom_colors")
public static class CustomColors {
@Config.Comment("Enable the custom colors module")
@Config.DefaultBoolean(true)
@Config.RequiresMcRestart
public static boolean enabled;
// CUSTOM_COLORS
public boolean customColorsEnabled;
public String customColorsLoggingLevel;
public int yVariance;
public int blockBlendRadius;
public int fogBlendRadius;
public boolean swampColors;
public boolean ccWater;
public boolean ccTree;
public boolean ccRedstone;
public boolean ccStem;
public boolean ccOtherBlocks;
public boolean smoothBiomes;
public boolean testColorSmoothing;
public boolean ccPotion;
public boolean ccParticle;
public boolean ccFog;
public boolean ccClouds;
public boolean ccMap;
public boolean ccDye;
public boolean ccText;
public boolean ccXPOrb;
public boolean ccEgg;
public boolean ccLightmaps;
@Config.Comment("logging level")
@Config.DefaultEnum("INFO")
@Config.RequiresMcRestart
public static LogLevel logging;
// CUSTOM_ITEM_TEXTURES
public boolean customItemTexturesEnabled;
public String customItemTexturesLoggingLevel;
public boolean citItems;
public boolean citEnchantments;
public boolean citArmor;
@Config.DefaultInt(0)
@Config.RequiresMcRestart
public static int yVariance;
// CONNECTED_TEXTURES
public boolean connectedTexturesEnabled;
public String connectedTexturesLoggingLevel;
public int maxRecursion;
public boolean debugTextures;
public boolean betterGrass;
public boolean ctmStandard;
public boolean ctmNonStandard;
public boolean ctmGlassPane;
@Config.DefaultInt(4)
@Config.RequiresMcRestart
public static int blockBlendRadius;
// EXTENDED_HD
public boolean extendedHDEnabled;
public String extendedHDLoggingLevel;
public int maxMipMapLevel;
public int anisotropicFiltering;
public int lodBias;
public boolean animations;
public boolean fancyCompass;
public boolean fancyClock;
public boolean useGL13;
public boolean useScratchTexture;
public boolean hdFont;
public boolean nonHDFontWidth;
public boolean mipmap;
@Config.DefaultInt(7)
@Config.RequiresMcRestart
public static int fogBlendRadius;
// RANDOM_MOBS
public boolean randomMobsEnabled;
public String randomMobsLoggingLevel;
public boolean leashLine;
@Config.DefaultBoolean(true)
@Config.RequiresMcRestart
public static boolean swampColors;
// BETTER_SKIES
public boolean betterSkiesEnabled;
public String betterSkiesLoggingLevel;
public int horizon;
public boolean brightenFireworks;
public boolean skybox;
public boolean unloadTextures;
@Config.DefaultBoolean(true)
@Config.RequiresMcRestart
public static boolean water;
public enum Category {
@Config.DefaultBoolean(true)
@Config.RequiresMcRestart
public static boolean tree;
CUSTOM_COLORS,
CUSTOM_ITEM_TEXTURES,
CONNECTED_TEXTURES,
EXTENDED_HD,
RANDOM_MOBS,
BETTER_SKIES;
@Config.DefaultBoolean(true)
@Config.RequiresMcRestart
public static boolean redstone;
@Override
public String toString() {
return name().toLowerCase();
}
@Config.DefaultBoolean(true)
@Config.RequiresMcRestart
public static boolean stem;
@Config.DefaultBoolean(true)
@Config.RequiresMcRestart
public static boolean otherBlocks;
@Config.DefaultBoolean(true)
@Config.RequiresMcRestart
public static boolean smoothBiomes;
@Config.DefaultBoolean(false)
@Config.RequiresMcRestart
public static boolean testColorSmoothing;
@Config.DefaultBoolean(true)
@Config.RequiresMcRestart
public static boolean potion;
@Config.DefaultBoolean(true)
@Config.RequiresMcRestart
public static boolean particle;
@Config.DefaultBoolean(true)
@Config.RequiresMcRestart
public static boolean fog;
@Config.DefaultBoolean(true)
@Config.RequiresMcRestart
public static boolean clouds;
@Config.DefaultBoolean(true)
@Config.RequiresMcRestart
public static boolean map;
@Config.DefaultBoolean(true)
@Config.RequiresMcRestart
public static boolean dye;
@Config.DefaultBoolean(true)
@Config.RequiresMcRestart
public static boolean text;
@Config.DefaultBoolean(true)
@Config.RequiresMcRestart
public static boolean xporb;
@Config.DefaultBoolean(true)
@Config.RequiresMcRestart
public static boolean egg;
@Config.DefaultBoolean(true)
@Config.RequiresMcRestart
public static boolean lightmaps;
}
public static MCPatcherForgeConfig instance() {
if (config == null) {
config = new MCPatcherForgeConfig(new File(Launch.minecraftHome, "config/mcpatcherforge.cfg"));
}
return config;
@Config(modid = "mcpatcherforge", category = "custom_item_textures")
public static class CustomItemTextures {
@Config.Comment("Enable the custom item textures module")
@Config.DefaultBoolean(true)
@Config.RequiresMcRestart
public static boolean enabled;
@Config.Comment("logging level")
@Config.DefaultEnum("INFO")
@Config.RequiresMcRestart
public static LogLevel logging;
@Config.DefaultBoolean(true)
@Config.RequiresMcRestart
public static boolean items;
@Config.DefaultBoolean(true)
@Config.RequiresMcRestart
public static boolean enchantments;
@Config.DefaultBoolean(true)
@Config.RequiresMcRestart
public static boolean armor;
}
public MCPatcherForgeConfig(File file) {
Configuration config = new Configuration(file);
@Config(modid = "mcpatcherforge", category = "connected_textures")
public static class ConnectedTextures {
@Config.Comment("Enable the connected textures module")
@Config.DefaultBoolean(true)
@Config.RequiresMcRestart
public static boolean enabled;
// spotless:off
@Config.Comment("logging level")
@Config.DefaultEnum("INFO")
@Config.RequiresMcRestart
public static LogLevel logging;
customColorsEnabled = config.get(Category.CUSTOM_COLORS.toString(),"enabled",true,"Enable the custom colors module").getBoolean();
customColorsLoggingLevel = config.get(Category.CUSTOM_COLORS.toString(),"logging",Level.INFO.getName(),"logging level").getString();
yVariance = config.get(Category.CUSTOM_COLORS.toString(),"yVariance",0).getInt();
blockBlendRadius = config.get(Category.CUSTOM_COLORS.toString(),"blockBlendRadius",4).getInt();
fogBlendRadius = config.get(Category.CUSTOM_COLORS.toString(),"fogBlendRadius",7).getInt();
swampColors = config.get(Category.CUSTOM_COLORS.toString(),"swampColors",true).getBoolean();
ccWater = config.get(Category.CUSTOM_COLORS.toString(),"water",true).getBoolean();
ccTree = config.get(Category.CUSTOM_COLORS.toString(),"tree",true).getBoolean();
ccRedstone = config.get(Category.CUSTOM_COLORS.toString(),"redstone",true).getBoolean();
ccStem = config.get(Category.CUSTOM_COLORS.toString(),"stem",true).getBoolean();
ccOtherBlocks = config.get(Category.CUSTOM_COLORS.toString(),"otherBlocks",true).getBoolean();
smoothBiomes = config.get(Category.CUSTOM_COLORS.toString(),"smoothBiomes",true).getBoolean();
testColorSmoothing = config.get(Category.CUSTOM_COLORS.toString(),"testColorSmoothing",false).getBoolean();
ccPotion = config.get(Category.CUSTOM_COLORS.toString(),"potion",true).getBoolean();
ccParticle = config.get(Category.CUSTOM_COLORS.toString(),"particle",true).getBoolean();
ccFog = config.get(Category.CUSTOM_COLORS.toString(),"fog",true).getBoolean();
ccClouds = config.get(Category.CUSTOM_COLORS.toString(),"clouds",true).getBoolean();
ccMap = config.get(Category.CUSTOM_COLORS.toString(),"map",true).getBoolean();
ccDye = config.get(Category.CUSTOM_COLORS.toString(),"dye",true).getBoolean();
ccText = config.get(Category.CUSTOM_COLORS.toString(),"text",true).getBoolean();
ccXPOrb = config.get(Category.CUSTOM_COLORS.toString(),"xporb",true).getBoolean();
ccEgg = config.get(Category.CUSTOM_COLORS.toString(),"egg",true).getBoolean();
ccLightmaps = config.get(Category.CUSTOM_COLORS.toString(),"lightmaps",true).getBoolean();
@Config.DefaultInt(4)
public static int maxRecursion;
customItemTexturesEnabled = config.get(Category.CUSTOM_ITEM_TEXTURES.toString(),"enabled",true,"Enable the custom item textures module").getBoolean();
customItemTexturesLoggingLevel = config.get(Category.CUSTOM_ITEM_TEXTURES.toString(),"logging",Level.INFO.getName(),"logging level").getString();
citItems = config.get(Category.CUSTOM_ITEM_TEXTURES.toString(),"items",true).getBoolean();
citEnchantments = config.get(Category.CUSTOM_ITEM_TEXTURES.toString(),"enchantments",true).getBoolean();
citArmor = config.get(Category.CUSTOM_ITEM_TEXTURES.toString(),"armor",true).getBoolean();
@Config.DefaultBoolean(false)
public static boolean debugTextures;
connectedTexturesEnabled = config.get(Category.CONNECTED_TEXTURES.toString(),"enabled",true,"Enable the connected textures module").getBoolean();
connectedTexturesLoggingLevel = config.get(Category.CONNECTED_TEXTURES.toString(),"logging",Level.INFO.getName(),"logging level").getString();
maxRecursion = config.get(Category.CONNECTED_TEXTURES.toString(),"maxRecursion",4).getInt();
debugTextures = config.get(Category.CONNECTED_TEXTURES.toString(),"debugTextures",false).getBoolean();
betterGrass = config.get(Category.CONNECTED_TEXTURES.toString(),"betterGrass",false).getBoolean();
ctmStandard = config.get(Category.CONNECTED_TEXTURES.toString(),"standard",true).getBoolean();
ctmNonStandard = config.get(Category.CONNECTED_TEXTURES.toString(),"nonStandard",true).getBoolean();
ctmGlassPane = config.get(Category.CONNECTED_TEXTURES.toString(),"glassPane",false).getBoolean();
@Config.DefaultBoolean(false)
public static boolean betterGrass;
extendedHDEnabled = config.get(Category.EXTENDED_HD.toString(),"enabled",true,"Enable the extended hd module").getBoolean();
extendedHDLoggingLevel = config.get(Category.EXTENDED_HD.toString(),"logging",Level.INFO.getName(),"logging level").getString();
maxMipMapLevel = config.get(Category.EXTENDED_HD.toString(),"maxMipMapLevel",3).getInt();
anisotropicFiltering = config.get(Category.EXTENDED_HD.toString(),"anisotropicFiltering",1).getInt();
lodBias = config.get(Category.EXTENDED_HD.toString(),"lod bias",0).getInt();
@Config.DefaultBoolean(true)
public static boolean standard;
animations = config.get(Category.EXTENDED_HD.toString(),"animations",true).getBoolean();
fancyCompass = config.get(Category.EXTENDED_HD.toString(),"fancyCompass",true).getBoolean();
fancyClock = config.get(Category.EXTENDED_HD.toString(),"fancyClock",true).getBoolean();
useGL13 = config.get(Category.EXTENDED_HD.toString(),"useGL13",true).getBoolean();
useScratchTexture = config.get(Category.EXTENDED_HD.toString(),"useScratchTexture",true).getBoolean();
hdFont = config.get(Category.EXTENDED_HD.toString(),"HDFont",true).getBoolean();
nonHDFontWidth = config.get(Category.EXTENDED_HD.toString(),"nonHDFontWidth",false).getBoolean();
mipmap = config.get(Category.EXTENDED_HD.toString(),"mipmap",false).getBoolean();
@Config.DefaultBoolean(true)
public static boolean nonStandard;
randomMobsEnabled = config.get(Category.RANDOM_MOBS.toString(),"enabled",true,"Enable the random mobs module").getBoolean();
randomMobsLoggingLevel = config.get(Category.RANDOM_MOBS.toString(),"logging",Level.INFO.getName(),"logging level").getString();
leashLine = config.get(Category.RANDOM_MOBS.toString(),"leashLine",true).getBoolean();
@Config.DefaultBoolean(false)
public static boolean glassPane;
}
betterSkiesEnabled = config.get(Category.BETTER_SKIES.toString(),"enabled",true,"Enable the better skies module").getBoolean();
betterSkiesLoggingLevel = config.get(Category.BETTER_SKIES.toString(),"logging",Level.INFO.getName(),"logging level").getString();
horizon = config.get(Category.BETTER_SKIES.toString(),"horizon",16).getInt();
brightenFireworks = config.get(Category.BETTER_SKIES.toString(),"brightenFireworks",true).getBoolean();
skybox = config.get(Category.BETTER_SKIES.toString(),"skybox",true).getBoolean();
unloadTextures = config.get(Category.BETTER_SKIES.toString(),"unloadTextures",true).getBoolean();
@Config(modid = "mcpatcherforge", category = "extended_hd")
public static class ExtendedHD {
@Config.Comment("Enable the extended hd module")
@Config.DefaultBoolean(true)
@Config.RequiresMcRestart
public static boolean enabled;
// spotless:on
if (config.hasChanged()) config.save();
@Config.Comment("logging level")
@Config.DefaultEnum("INFO")
@Config.RequiresMcRestart
public static LogLevel logging;
@Config.DefaultInt(3)
@Config.RequiresMcRestart
public static int maxMipMapLevel;
@Config.DefaultInt(1)
@Config.RequiresMcRestart
public static int anisotropicFiltering;
@Config.DefaultInt(0)
@Config.RequiresMcRestart
@Config.Name("lod bias")
public static int lodBias;
@Config.DefaultBoolean(true)
@Config.RequiresMcRestart
public static boolean animations;
@Config.DefaultBoolean(true)
@Config.RequiresMcRestart
public static boolean fancyCompass;
@Config.DefaultBoolean(true)
@Config.RequiresMcRestart
public static boolean fancyClock;
@Config.DefaultBoolean(true)
@Config.RequiresMcRestart
public static boolean useGL13;
@Config.DefaultBoolean(true)
@Config.RequiresMcRestart
public static boolean useScratchTexture;
@Config.DefaultBoolean(true)
@Config.RequiresMcRestart
@Config.Name("HDFont")
public static boolean hdFont;
@Config.DefaultBoolean(false)
@Config.RequiresMcRestart
public static boolean nonHDFontWidth;
@Config.DefaultBoolean(false)
@Config.RequiresMcRestart
public static boolean mipmap;
}
@Config(modid = "mcpatcherforge", category = "random_mobs")
public static class RandomMobs {
@Config.Comment("Enable the random mobs module")
@Config.DefaultBoolean(true)
@Config.RequiresMcRestart
public static boolean enabled;
@Config.Comment("logging level")
@Config.DefaultEnum("INFO")
@Config.RequiresMcRestart
public static LogLevel logging;
@Config.DefaultBoolean(true)
@Config.RequiresMcRestart
public static boolean leashLine;
}
@Config(modid = "mcpatcherforge", category = "better_skies")
public static class BetterSkies {
@Config.Comment("Enable the better skies module")
@Config.DefaultBoolean(true)
@Config.RequiresMcRestart
public static boolean enabled;
@Config.Comment("logging level")
@Config.DefaultEnum("INFO")
@Config.RequiresMcRestart
public static LogLevel logging;
@Config.DefaultInt(16)
@Config.RequiresMcRestart
public static int horizon;
@Config.DefaultBoolean(true)
@Config.RequiresMcRestart
public static boolean brightenFireworks;
@Config.DefaultBoolean(true)
@Config.RequiresMcRestart
public static boolean skybox;
@Config.DefaultBoolean(true)
@Config.RequiresMcRestart
public static boolean unloadTextures;
}
public static void registerConfig() throws ConfigException {
ConfigurationManager.registerConfig(CustomColors.class);
ConfigurationManager.registerConfig(CustomItemTextures.class);
ConfigurationManager.registerConfig(ConnectedTextures.class);
ConfigurationManager.registerConfig(ExtendedHD.class);
ConfigurationManager.registerConfig(RandomMobs.class);
ConfigurationManager.registerConfig(BetterSkies.class);
}
public enum LogLevel {
OFF(Level.OFF),
SEVERE(Level.SEVERE),
WARNING(Level.WARNING),
INFO(Level.INFO),
CONFIG(Level.CONFIG),
FINE(Level.FINE),
FINER(Level.FINER),
FINEST(Level.FINEST),
ALL(Level.ALL);
@Config.Ignore
public final Level level;
LogLevel(Level level) {
this.level = level;
}
}
}
@@ -0,0 +1,18 @@
package jss.notfine.config;
import com.gtnewhorizon.gtnhlib.config.ConfigException;
import com.gtnewhorizon.gtnhlib.config.SimpleGuiConfig;
import net.minecraft.client.gui.GuiScreen;
public class MCPatcherForgeGuiConfig extends SimpleGuiConfig {
public MCPatcherForgeGuiConfig(GuiScreen parent) throws ConfigException {
super(parent, "mcpatcherforge", "MCPatcherForge", true,
MCPatcherForgeConfig.CustomColors.class,
MCPatcherForgeConfig.CustomItemTextures.class,
MCPatcherForgeConfig.ConnectedTextures.class,
MCPatcherForgeConfig.ExtendedHD.class,
MCPatcherForgeConfig.RandomMobs.class,
MCPatcherForgeConfig.BetterSkies.class
);
}
}
@@ -0,0 +1,11 @@
package jss.notfine.config;
import com.gtnewhorizon.gtnhlib.config.SimpleGuiFactory;
import net.minecraft.client.gui.GuiScreen;
public class MCPatcherForgeGuiConfigFactory implements SimpleGuiFactory {
@Override
public Class<? extends GuiScreen> mainConfigGuiClass() {
return MCPatcherForgeGuiConfig.class;
}
}
@@ -17,7 +17,7 @@ public class SodiumDebugScreenHandler {
public void onRenderGameOverlayTextEvent(RenderGameOverlayEvent.Text event) {
final Minecraft mc = Minecraft.getMinecraft();
if (mc.gameSettings.showDebugInfo) {
event.right.add(2, "Off-Heap: +" + ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage().getUsed() / 1024L / 1024L + "MB");
event.right.add(Math.min(event.right.size(), 2), "Off-Heap: +" + ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage().getUsed() / 1024L / 1024L + "MB");
event.right.add("");
event.right.add("Sodium (Embeddium) Renderer");
@@ -372,6 +372,17 @@ public class SodiumGameOptionPages {
)
.build());
groups.add(OptionGroup.createBuilder()
.add(OptionImpl.createBuilder(int.class, angelicaOpts)
.setName(I18n.format("options.angelica.itemdisplaylistcount"))
.setTooltip(I18n.format("options.angelica.itemdisplaylistcount.tooltip"))
.setControl(o -> new SliderControl(o, 0, 1024, 1, ControlValueFormatter.number()))
.setImpact(OptionImpact.MEDIUM)
.setBinding((opts, value) -> AngelicaConfig.itemRendererDisplayListCacheSize = value, options -> AngelicaConfig.itemRendererDisplayListCacheSize)
.build()
)
.build());
groups.add(OptionGroup.createBuilder()
.add(Settings.MODE_GUI_BACKGROUND.option)
.add(Settings.GUI_BACKGROUND.option)
@@ -1,13 +1,12 @@
package me.jellysquid.mods.sodium.client.render;
import com.gtnewhorizons.angelica.compat.lwjgl.MemoryStack;
import com.gtnewhorizons.angelica.compat.toremove.MatrixStack;
import com.gtnewhorizons.angelica.config.AngelicaConfig;
import com.gtnewhorizons.angelica.rendering.RenderingState;
import java.nio.FloatBuffer;
import net.coderbot.iris.shadows.ShadowRenderingState;
import org.joml.Matrix4f;
import org.lwjgl.BufferUtils;
import java.nio.FloatBuffer;
public class GameRendererContext {
/**
@@ -17,8 +16,8 @@ public class GameRendererContext {
* @return A float-buffer on the stack containing the model-view-projection matrix in a format suitable for
* uploading as uniform state
*/
public static FloatBuffer getModelViewProjectionMatrix(MatrixStack.Entry matrices) {
final FloatBuffer bufModelViewProjection = BufferUtils.createFloatBuffer(16);
public static FloatBuffer getModelViewProjectionMatrix(MatrixStack.Entry matrices, MemoryStack stack) {
final FloatBuffer bufModelViewProjection = stack.mallocFloat(16);
final Matrix4f projectionMatrix = (AngelicaConfig.enableIris && ShadowRenderingState.areShadowsCurrentlyBeingRendered()) ? ShadowRenderingState.getShadowOrthoMatrix() : RenderingState.INSTANCE.getProjectionMatrix();
final Matrix4f matrix = new Matrix4f(projectionMatrix);
matrix.mul(matrices.getModel());
@@ -1,5 +1,6 @@
package me.jellysquid.mods.sodium.client.render.chunk.shader;
import com.gtnewhorizons.angelica.compat.lwjgl.MemoryStack;
import com.gtnewhorizons.angelica.compat.toremove.MatrixStack;
import me.jellysquid.mods.sodium.client.gl.device.RenderDevice;
import me.jellysquid.mods.sodium.client.gl.shader.GlProgram;
@@ -47,6 +48,12 @@ public class ChunkProgram extends GlProgram {
this.fogShader.setup();
if(this.uModelViewProjectionMatrix != -1) GL20.glUniformMatrix4(this.uModelViewProjectionMatrix, false, GameRendererContext.getModelViewProjectionMatrix(matrixStack.peek()));
if (this.uModelViewProjectionMatrix == -1) return;
try (MemoryStack stack = MemoryStack.stackPush()) {
GL20.glUniformMatrix4(
this.uModelViewProjectionMatrix,
false,
GameRendererContext.getModelViewProjectionMatrix(matrixStack.peek(), stack));
}
}
}
@@ -2,7 +2,6 @@ package net.coderbot.iris.client;
import com.gtnewhorizons.angelica.AngelicaMod;
import com.gtnewhorizons.angelica.config.AngelicaConfig;
import com.mitchej123.hodgepodge.client.HodgepodgeClient;
import cpw.mods.fml.common.eventhandler.EventPriority;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import net.coderbot.iris.Iris;
@@ -39,7 +38,7 @@ public class IrisDebugScreenHandler {
public void onRenderGameOverlayTextEvent(RenderGameOverlayEvent.Text event) {
final Minecraft mc = Minecraft.getMinecraft();
if (mc.gameSettings.showDebugInfo) {
event.right.add(2, "Direct Buffers: +" + iris$humanReadableByteCountBin(iris$directPool.getMemoryUsed()));
event.right.add(Math.min(event.right.size(), 2), "Direct Buffers: +" + iris$humanReadableByteCountBin(iris$directPool.getMemoryUsed()));
event.right.add("");
@@ -49,8 +48,8 @@ public class IrisDebugScreenHandler {
} else {
event.right.add("[" + Iris.MODNAME + "] Shaders are disabled");
}
if(AngelicaConfig.speedupAnimations) {
event.right.add(9, "animationsMode: " + AngelicaMod.animationsMode);
if (AngelicaConfig.speedupAnimations) {
event.right.add(Math.min(event.right.size(), 9), "animationsMode: " + AngelicaMod.animationsMode);
}
Iris.getPipelineManager().getPipeline().ifPresent(pipeline -> pipeline.addDebugText(event.left));
@@ -1,19 +1,18 @@
package net.coderbot.iris.gl.framebuffer;
import com.gtnewhorizons.angelica.compat.lwjgl.MemoryStack;
import com.gtnewhorizons.angelica.glsm.RenderSystem;
import com.gtnewhorizons.angelica.glsm.texture.TextureInfoCache;
import it.unimi.dsi.fastutil.ints.Int2IntArrayMap;
import it.unimi.dsi.fastutil.ints.Int2IntMap;
import java.nio.IntBuffer;
import net.coderbot.iris.gl.GlResource;
import net.coderbot.iris.gl.texture.DepthBufferFormat;
import net.minecraft.client.renderer.OpenGlHelper;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL30;
import java.nio.IntBuffer;
public class GlFramebuffer extends GlResource {
private final Int2IntMap attachments;
private final int maxDrawBuffers;
@@ -52,25 +51,29 @@ public class GlFramebuffer extends GlResource {
}
public void noDrawBuffers() {
final IntBuffer buffer = BufferUtils.createIntBuffer(1);
buffer.put(GL11.GL_NONE);
RenderSystem.drawBuffers(getGlId(), buffer);
try (MemoryStack stack = MemoryStack.stackPush()) {
final IntBuffer buffer = stack.mallocInt(1);
buffer.put(GL11.GL_NONE);
RenderSystem.drawBuffers(getGlId(), buffer);
}
}
public void drawBuffers(int[] buffers) {
final IntBuffer glBuffers = BufferUtils.createIntBuffer(buffers.length);
int index = 0;
try (MemoryStack stack = MemoryStack.stackPush()) {
final IntBuffer glBuffers = stack.mallocInt(buffers.length);
int index = 0;
if (buffers.length > maxDrawBuffers) {
throw new IllegalArgumentException("Cannot write to more than " + maxDrawBuffers + " draw buffers on this GPU");
}
for (int buffer : buffers) {
if (buffer >= maxColorAttachments) {
throw new IllegalArgumentException("Only " + maxColorAttachments + " color attachments are supported on this GPU, but an attempt was made to write to a color attachment with index " + buffer);
}
glBuffers.put(index++, GL30.GL_COLOR_ATTACHMENT0 + buffer);
}
RenderSystem.drawBuffers(getGlId(), glBuffers);
if (buffers.length > maxDrawBuffers) {
throw new IllegalArgumentException("Cannot write to more than " + maxDrawBuffers + " draw buffers on this GPU");
}
for (int buffer : buffers) {
if (buffer >= maxColorAttachments) {
throw new IllegalArgumentException("Only " + maxColorAttachments + " color attachments are supported on this GPU, but an attempt was made to write to a color attachment with index " + buffer);
}
glBuffers.put(index++, GL30.GL_COLOR_ATTACHMENT0 + buffer);
}
RenderSystem.drawBuffers(getGlId(), glBuffers);
}
}
public void readBuffer(int buffer) {
@@ -19,7 +19,7 @@ public final class ComputeProgram extends GlResource {
private Vector3i absoluteWorkGroups;
private Vector2f relativeWorkGroups;
// private int[] localSize;
private IntBuffer localSizeBuffer;
private final IntBuffer localSizeBuffer;
private float cachedWidth;
private float cachedHeight;
private Vector3i cachedWorkGroups;
@@ -5,12 +5,14 @@ import com.gtnewhorizons.angelica.compat.mojang.Camera;
import com.gtnewhorizons.angelica.compat.toremove.MatrixStack;
import com.gtnewhorizons.angelica.glsm.GLStateManager;
import com.gtnewhorizons.angelica.glsm.RenderSystem;
import com.gtnewhorizons.angelica.mixins.interfaces.IRenderGlobalExt;
import com.gtnewhorizons.angelica.rendering.RenderingState;
import cpw.mods.fml.relauncher.ReflectionHelper;
import me.jellysquid.mods.sodium.client.gl.device.RenderDevice;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import me.jellysquid.mods.sodium.client.render.SodiumWorldRenderer;
import me.jellysquid.mods.sodium.client.render.chunk.passes.BlockRenderPass;
import net.coderbot.iris.Iris;
import net.coderbot.iris.shaderpack.OptionalBoolean;
import net.coderbot.iris.shaderpack.PackDirectives;
@@ -33,7 +35,6 @@ import net.minecraft.client.multiplayer.WorldClient;
import net.minecraft.client.renderer.EntityRenderer;
import net.minecraft.client.renderer.OpenGlHelper;
import net.minecraft.client.renderer.RenderGlobal;
import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.client.renderer.culling.Frustrum;
import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraft.client.renderer.texture.TextureMap;
@@ -52,16 +53,9 @@ import org.lwjgl.opengl.GL13;
import org.lwjgl.opengl.GL14;
import org.lwjgl.opengl.GL30;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
public class ShadowRenderer {
public static final Matrix4f MODELVIEW = new Matrix4f();
public static FloatBuffer MODELVIEW_BUFFER = BufferUtils.createFloatBuffer(16);
public static final FloatBuffer MODELVIEW_BUFFER = BufferUtils.createFloatBuffer(16);
public static final Matrix4f PROJECTION = new Matrix4f();
public static List<TileEntity> visibleTileEntities;
public static boolean ACTIVE = false;
@@ -33,6 +33,7 @@ public class ShaderTransformer {
static String tab = "";
private static final Pattern versionPattern = Pattern.compile("#version\\s+(\\d+)(?:\\s+(\\w+))?");
private static final Pattern inOutVaryingPattern = Pattern.compile("(?m)^\\s*(in|out)(\\s+)");
private static final int CACHE_SIZE = 100;
private static final Object2ObjectLinkedOpenHashMap<TransformKey, Map<PatchShaderType, String>> shaderTransformationCache = new Object2ObjectLinkedOpenHashMap<>();
@@ -152,6 +153,7 @@ public class ShaderTransformer {
EnumMap<PatchShaderType, GLSLParser.Translation_unitContext> types = new EnumMap<>(PatchShaderType.class);
EnumMap<PatchShaderType, String> prepatched = new EnumMap<>(PatchShaderType.class);
List<GLSLParser.Translation_unitContext> textureLodExtensionPatches = new ArrayList<>();
List<GLSLParser.Translation_unitContext> hacky120Patches = new ArrayList<>();
Stopwatch watch = Stopwatch.createStarted();
@@ -216,24 +218,45 @@ public class ShaderTransformer {
}
// Check if we need to patch in texture LOD extension enabling
if (versionInt <= 120 && (Util.containsCall(translationUnit, "texture2DLod") || Util.containsCall(translationUnit, "texture3DLod"))) {
if (versionInt <= 120 && (Util.containsCall(translationUnit, "texture2DLod") || Util.containsCall(translationUnit, "texture3DLod") || Util.containsCall(translationUnit, "texture2DGradARB"))) {
textureLodExtensionPatches.add(translationUnit);
}
// Check if we need to patch in some hacky GLSL 120 compat
if (versionInt <= 120) {
hacky120Patches.add(translationUnit);
}
types.put(type, translationUnit);
prepatched.put(type, profileString);
}
CompatibilityTransformer.transformGrouped(types, parameters);
for (var entry : types.entrySet()) {
// This is a hack to inject an extension declaration when the GLSL version is less than 120
// Doing this as a string manipulation on the final shader output since it needs to put this
// before variables, didn't see an easy way to do that with glsl-transformation-lib
// Eventually this can probably be moved to use glsl-transformation-lib
String formattedShader = getFormattedShader(entry.getValue(), prepatched.get(entry.getKey()));
// Please don't mind the entire rest of this loop basically, we're doing awful fragile regex on the transformed
// shader output to do things that I can't figure out with AST because I'm bad at it
if (textureLodExtensionPatches.contains(entry.getValue())) {
String[] parts = formattedShader.split("\n", 2);
parts[1] = "#extension GL_ARB_shader_texture_lod : require\n" + parts[1];
formattedShader = parts[0] + "\n" + parts[1];
}
if (hacky120Patches.contains(entry.getValue())) {
// Forcibly enable GL_EXT_gpu_shader4, it has a lot of compatibility backports with GLSL 130+
// and seems more or less universally supported by hardware/drivers
String[] parts = formattedShader.split("\n", 2);
parts[1] = "#extension GL_EXT_gpu_shader4 : require\n" + parts[1];
formattedShader = parts[0] + "\n" + parts[1];
// Kind of GLSL 120 supports in/out specifiers, but also kind of not, and is driver dependent
// and also depends on the types of the variables, doesn't work with integers for example(at least on Nvidia)
// So we are replacing all in/out usage with varying.
Matcher inOutVaryingMatcher = inOutVaryingPattern.matcher(formattedShader);
formattedShader = inOutVaryingMatcher.replaceAll("varying$2");
}
result.put(entry.getKey(), formattedShader);
}
watch.stop();
@@ -1,5 +1,6 @@
package net.coderbot.iris.rendertarget;
import com.gtnewhorizons.angelica.compat.lwjgl.MemoryStack;
import com.gtnewhorizons.angelica.glsm.GLStateManager;
import com.gtnewhorizons.angelica.glsm.RenderSystem;
import lombok.Getter;
@@ -40,11 +41,13 @@ public class RenderTarget {
this.width = builder.width;
this.height = builder.height;
IntBuffer textures = BufferUtils.createIntBuffer(2);
GL11.glGenTextures(textures);
try (MemoryStack stack = MemoryStack.stackPush()) {
IntBuffer textures = stack.mallocInt(2);
GL11.glGenTextures(textures);
this.mainTexture = textures.get(0);
this.altTexture = textures.get(1);
this.mainTexture = textures.get(0);
this.altTexture = textures.get(1);
}
boolean isPixelFormatInteger = builder.internalFormat.getPixelFormat().isInteger();
setupTexture(mainTexture, builder.width, builder.height, !isPixelFormatInteger);
@@ -1,7 +1,9 @@
package net.coderbot.iris.sodium.shader_overrides;
import com.gtnewhorizons.angelica.compat.lwjgl.MemoryStack;
import com.gtnewhorizons.angelica.compat.toremove.MatrixStack;
import com.gtnewhorizons.angelica.glsm.RenderSystem;
import java.nio.FloatBuffer;
import me.jellysquid.mods.sodium.client.gl.device.RenderDevice;
import me.jellysquid.mods.sodium.client.render.chunk.shader.ChunkProgram;
import me.jellysquid.mods.sodium.client.render.chunk.shader.ChunkShaderFogComponent;
@@ -11,9 +13,6 @@ import net.coderbot.iris.gl.program.ProgramUniforms;
import net.minecraft.util.ResourceLocation;
import org.jetbrains.annotations.Nullable;
import org.joml.Matrix4f;
import org.lwjgl.BufferUtils;
import java.nio.FloatBuffer;
public class IrisChunkProgram extends ChunkProgram {
// Uniform variable binding indexes
@@ -87,10 +86,12 @@ public class IrisChunkProgram extends ChunkProgram {
return;
}
FloatBuffer buffer = BufferUtils.createFloatBuffer(16);
try (MemoryStack stack = MemoryStack.stackPush()) {
FloatBuffer buffer = stack.mallocFloat(16);
matrix.get(buffer);
matrix.get(buffer);
RenderSystem.uniformMatrix4fv(location, false, buffer);
RenderSystem.uniformMatrix4fv(location, false, buffer);
}
}
}
@@ -137,6 +137,8 @@ options.dynamic_lights_shader_force=Dynamic Lights - Forced With Shaders
options.dynamic_lights_shader_force.tooltip=Enabled - Dynamic Lights are shown even when a shader is active, Disabled - Dynamic Lights are disabled when a shader is active.
options.angelica.droppedItemLimit=Dropped Item Render Limit
options.angelica.droppedItemLimit.tooltip=The maximum number of dropped items that will be rendered. Lower values can improve performance.
options.angelica.itemdisplaylistcount=Item Renderer Display List Cache Size
options.angelica.itemdisplaylistcount.tooltip=The maximum number of display lists to cache in the optimized item renderer. Higher values will increase performance but increase VRAM usage.
pack.iris.select.title=Select
pack.iris.configure.title=Configure
label.iris.true=On
@@ -0,0 +1,35 @@
#version 120
uniform int headIdx;
uniform float scaleFactor;
uniform float samples[240];
uniform float pxPerNs;
uniform bool left;
uniform float fbWidth;
void main() {
// Get position - gl_FragCoord starts from the lower left and returns the position of the center of the pixel
// i.e. the lower-left-most pixel is (0.5, 0.5). Shift if we're on the right side of the screen.
int dx = int((left ? gl_FragCoord.x : gl_FragCoord.x - fbWidth) / scaleFactor) - 1;
int dy = int(gl_FragCoord.y / scaleFactor);
// Get the time for this frag. Last at the left edge, first at the right, shifting as needed when the head moves.
int idx = int(mod(dx + headIdx, 240));
float time = samples[idx];
// Time is in nanoseconds. Height is calculated from the given pixels/ns factor.
// If it's higher or as high as we are, recolor accordingly.
// Also, apparently GLSL 120 doesn't have rounding.
float height = floor(time * pxPerNs + 0.5);
// Calculate the nanoseconds at the midpoint, 30px. The bar can exceed twice that, but it's used for coloring
float midNs = 30.0 / pxPerNs;
// Increase red from 0-midpoint, and decrease green from midpoint-"max"
vec4 color = vec4(0.0, 0.0, 0.0, 0.0);
float r = clamp(time / midNs, 0.0, 1.0);
float g = 1.0 - clamp((time - midNs) / midNs, 0.0, 1.0);
if (dy <= height)
color = vec4(r, g, 0.0, 1.0);
gl_FragColor = color;
}
@@ -0,0 +1,18 @@
#version 120
attribute vec2 pos;
uniform float fbWidth;
uniform float fbHeight;
uniform float scaleFactor;
uniform bool left;
void main() {
// Shift the bounds (originally in pixel coords) to clip space. Flip horizontally if on the right, and ensure the
// top vertices are pinned to the top of the screen.
float x = pos.x / fbWidth * scaleFactor * 2.0 - 1.0;
float y = pos.y / fbHeight * scaleFactor * 2.0 - 1.0;
x = left ? x : -x;
y = y < -0.9 ? y : 1.0; // -0.9 arbitrariy chosen as "probably between bottom and top verts"
gl_Position = vec4(x, y, 0.0, 1.0);
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 481 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

@@ -0,0 +1,22 @@
package com.gtnewhorizons.angelica.mixins.early.angelica;
import com.gtnewhorizons.angelica.mixins.interfaces.IGameSettingsExt;
import net.minecraft.client.settings.GameSettings;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
@Mixin(GameSettings.class)
public class MixinGameSettings implements IGameSettingsExt {
@Unique
private boolean angelica$showFpsGraph = false;
@Override
public boolean angelica$showFpsGraph() {
return this.angelica$showFpsGraph;
}
@Override
public void angelica$setShowFpsGraph(boolean renderFpsGraph) {
this.angelica$showFpsGraph = renderFpsGraph;
}
}
@@ -1,14 +1,25 @@
package com.gtnewhorizons.angelica.mixins.early.angelica;
import com.gtnewhorizons.angelica.AngelicaMod;
import com.gtnewhorizons.angelica.mixins.interfaces.IGameSettingsExt;
import net.minecraft.client.Minecraft;
import net.minecraft.client.settings.GameSettings;
import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.GL11;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(Minecraft.class)
public class MixinMinecraft {
@Shadow
public GameSettings gameSettings;
@Unique
private long angelica$lastFrameTime = 0;
@Inject(
method = "runGameLoop",
@@ -17,4 +28,19 @@ public class MixinMinecraft {
private void angelica$injectLightingFixPostRenderTick(CallbackInfo ci) {
GL11.glEnable(GL11.GL_LIGHTING);
}
@Inject(
method = "func_147120_f",
at = @At(value = "INVOKE", target = "Lorg/lwjgl/opengl/Display;update()V", shift = At.Shift.AFTER, remap = false)
)
private void angelica$trackFrametimes(CallbackInfo ci) {
long time = System.nanoTime();
AngelicaMod.proxy.putFrametime(time - angelica$lastFrameTime);
angelica$lastFrameTime = time;
}
@Inject(method = "runTick", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/GuiScreen;isShiftKeyDown()Z", shift = At.Shift.AFTER))
private void angelica$setShowFpsGraph(CallbackInfo ci) {
((IGameSettingsExt) gameSettings).angelica$setShowFpsGraph(Keyboard.isKeyDown(Keyboard.KEY_LMENU) || Keyboard.isKeyDown(Keyboard.KEY_RMENU));
}
}
@@ -0,0 +1,17 @@
package com.gtnewhorizons.angelica.mixins.early.angelica;
import com.gtnewhorizons.angelica.AngelicaMod;
import com.llamalad7.mixinextras.sugar.Local;
import net.minecraft.server.MinecraftServer;
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;
@Mixin(MinecraftServer.class)
public class MixinMinecraftServer {
@Inject(method = "tick", at = @At(value = "TAIL"))
private void angelica$trackTicktimes(CallbackInfo ci, @Local(ordinal = 0) long preTime) {
AngelicaMod.proxy.putTicktime(System.nanoTime() - preTime);
}
}
@@ -0,0 +1,87 @@
/*
* This file is part of FalseTweaks.
*
* Copyright (C) 2022-2024 FalsePattern
* All Rights Reserved
*
* Modifications by Angelica in accordance with LGPL v3.0
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* FalseTweaks is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FalseTweaks is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with FalseTweaks. If not, see <https://www.gnu.org/licenses/>.
*/
package com.gtnewhorizons.angelica.mixins.early.angelica.itemrenderer;
import com.gtnewhorizons.angelica.rendering.ItemRenderListManager;
import lombok.SneakyThrows;
import net.minecraft.client.renderer.ItemRenderer;
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.Redirect;
import org.spongepowered.asm.mixin.injection.Slice;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import net.minecraft.client.renderer.Tessellator;
@Mixin(ItemRenderer.class)
public abstract class MixinItemRenderer {
@SneakyThrows
@Inject(method = "renderItemIn2D",
at = @At("HEAD"),
cancellable = true,
require = 1)
private static void leFunnyRenderListStart(Tessellator tess, float a, float b, float c, float d, int e, int f, float g, CallbackInfo ci) {
if (ItemRenderListManager.INSTANCE.pre(a, b, c, d, e, f, g)) {
ci.cancel();
}
}
@Inject(method = "renderItemIn2D",
at = @At("RETURN"),
require = 1)
private static void leFunnyRenderListEnd(Tessellator tess, float a, float b, float c, float d, int e, int f, float g, CallbackInfo ci) {
ItemRenderListManager.INSTANCE.post();
}
@Redirect(method = "renderItemIn2D",
slice = @Slice(from = @At(value = "INVOKE",
target = "Lnet/minecraft/client/renderer/Tessellator;draw()I",
ordinal = 0),
to = @At(value = "INVOKE",
target = "Lnet/minecraft/client/renderer/Tessellator;startDrawingQuads()V",
ordinal = 5)),
at = @At(value = "INVOKE",
target = "Lnet/minecraft/client/renderer/Tessellator;draw()I"),
require = 5)
private static int batchDrawCalls1(Tessellator instance) {
return 0;
}
@Redirect(method = "renderItemIn2D",
slice = @Slice(from = @At(value = "INVOKE",
target = "Lnet/minecraft/client/renderer/Tessellator;draw()I",
ordinal = 0),
to = @At(value = "INVOKE",
target = "Lnet/minecraft/client/renderer/Tessellator;startDrawingQuads()V",
ordinal = 5)),
at = @At(value = "INVOKE",
target = "Lnet/minecraft/client/renderer/Tessellator;startDrawingQuads()V"),
require = 5)
private static void batchDrawCalls2(Tessellator instance) {
}
}
@@ -61,17 +61,16 @@ public abstract class MixinMinecraft {
private void modifyStartGame1(CallbackInfo ci) {
TileLoader.init();
CTMUtils.reset();
MCPatcherForgeConfig config = MCPatcherForgeConfig.instance();
if (config.customItemTexturesEnabled) {
if (MCPatcherForgeConfig.CustomItemTextures.enabled) {
CITUtils.init();
}
if (config.extendedHDEnabled) {
if (MCPatcherForgeConfig.ExtendedHD.enabled) {
FontUtils.init();
}
if (config.randomMobsEnabled) {
if (MCPatcherForgeConfig.RandomMobs.enabled) {
MobRandomizer.init();
}
if (config.customColorsEnabled) {
if (MCPatcherForgeConfig.CustomColors.enabled) {
Colorizer.init();
}
}
@@ -1,10 +1,5 @@
package com.gtnewhorizons.angelica.mixins.early.mcpatcherforge.ctm;
import static net.minecraftforge.common.util.ForgeDirection.EAST;
import static net.minecraftforge.common.util.ForgeDirection.NORTH;
import static net.minecraftforge.common.util.ForgeDirection.SOUTH;
import static net.minecraftforge.common.util.ForgeDirection.WEST;
import com.llamalad7.mixinextras.sugar.Local;
import net.minecraft.block.Block;
import net.minecraft.block.BlockAnvil;
@@ -16,15 +11,12 @@ import net.minecraft.block.BlockHopper;
import net.minecraft.block.BlockPane;
import net.minecraft.block.BlockRailBase;
import net.minecraft.block.BlockRedstoneDiode;
import net.minecraft.block.BlockStainedGlassPane;
import net.minecraft.client.renderer.EntityRenderer;
import net.minecraft.client.renderer.RenderBlocks;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.util.IIcon;
import net.minecraft.world.IBlockAccess;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
@@ -65,7 +57,7 @@ public abstract class MixinRenderBlocks {
target = "Lnet/minecraft/client/renderer/RenderBlocks;getBlockIconFromSideAndMetadata(Lnet/minecraft/block/Block;II)Lnet/minecraft/util/IIcon;"))
private IIcon modifyRenderBlockMinecartTrack(RenderBlocks instance, Block block, int side, int meta,
BlockRailBase specializedBlock, int x, int y, int z) {
return getBlockIcon(block, blockAccess, x, y, z, side);
return CTMUtils.getBlockIcon(getIconSafe(block.getIcon(side, meta)), block, side, meta);
}
@Redirect(
@@ -92,7 +84,7 @@ public abstract class MixinRenderBlocks {
target = "Lnet/minecraft/client/renderer/RenderBlocks;getBlockIconFromSideAndMetadata(Lnet/minecraft/block/Block;II)Lnet/minecraft/util/IIcon;"))
private IIcon modifyRenderBlockBrewingStand(RenderBlocks instance, Block block, int side, int meta,
BlockBrewingStand specializedBlock, int x, int y, int z) {
return getBlockIcon(block, blockAccess, x, y, z, side);
return CTMUtils.getBlockIcon(getIconSafe(block.getIcon(side, meta)), block, side, meta);
}
@Redirect(
@@ -112,7 +104,7 @@ public abstract class MixinRenderBlocks {
target = "Lnet/minecraft/client/renderer/RenderBlocks;getBlockIconFromSideAndMetadata(Lnet/minecraft/block/Block;II)Lnet/minecraft/util/IIcon;"))
private IIcon modifyRenderBlockAnvilRotate(RenderBlocks instance, Block block, int side, int meta,
BlockAnvil specializedBlock, int x, int y, int z) {
return getBlockIcon(block, blockAccess, x, y, z, side);
return CTMUtils.getBlockIcon(getIconSafe(block.getIcon(side, meta)), block, side, meta);
}
@Redirect(
@@ -122,14 +114,13 @@ public abstract class MixinRenderBlocks {
target = "Lnet/minecraft/client/renderer/RenderBlocks;getBlockIconFromSideAndMetadata(Lnet/minecraft/block/Block;II)Lnet/minecraft/util/IIcon;"))
private IIcon modifyRenderRedstoneDiodeMetadata(RenderBlocks instance, Block block, int side, int meta,
BlockRedstoneDiode specializedBlock, int x, int y, int z) {
return getBlockIcon(block, blockAccess, x, y, z, side);
return CTMUtils.getBlockIcon(getIconSafe(block.getIcon(side, meta)), block, side, meta);
}
@Redirect(method = "renderBlockPane", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/RenderBlocks;getBlockIconFromSideAndMetadata(Lnet/minecraft/block/Block;II)Lnet/minecraft/util/IIcon;"))
private IIcon tweakPaneIcons(RenderBlocks instance, Block block, int side, int meta_unused,
@Local(name = "p_147767_2_") int x, @Local(name = "p_147767_3_") int y, @Local(name = "p_147767_4_") int z) {
return this.getBlockIcon(block, this.blockAccess, x, y, z, side);
private IIcon tweakPaneIcons(RenderBlocks instance, Block block, int side, int meta) {
return CTMUtils.getBlockIcon(getIconSafe(block.getIcon(side, meta)), block, side, meta);
}
/**
@@ -497,9 +488,8 @@ public abstract class MixinRenderBlocks {
}
@Redirect(method = "renderBlockStainedGlassPane", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/RenderBlocks;getBlockIconFromSideAndMetadata(Lnet/minecraft/block/Block;II)Lnet/minecraft/util/IIcon;"))
private IIcon tweakStainedPaneIcons(RenderBlocks instance, Block block, int side, int meta_unused,
@Local(name = "p_147733_2_") int x, @Local(name = "p_147733_3_") int y, @Local(name = "p_147733_4_") int z) {
return this.getBlockIcon(block, this.blockAccess, x, y, z, side);
private IIcon tweakStainedPaneIcons(RenderBlocks instance, Block block, int side, int meta) {
return CTMUtils.getBlockIcon(getIconSafe(block.getIcon(side, meta)), block, side, meta);
}
/**
@@ -845,7 +835,7 @@ public abstract class MixinRenderBlocks {
target = "Lnet/minecraft/client/renderer/RenderBlocks;getBlockIconFromSideAndMetadata(Lnet/minecraft/block/Block;II)Lnet/minecraft/util/IIcon;"))
private IIcon redirectGetBlockIconFromSideAndMetadata(RenderBlocks instance, Block block, int side, int meta,
Block specializedBlock, int x, int y, int z) {
return getBlockIcon(block, blockAccess, x, y, z, side);
return CTMUtils.getBlockIcon(getIconSafe(block.getIcon(side, meta)), block, side, meta);
}
@Redirect(
@@ -865,6 +855,44 @@ public abstract class MixinRenderBlocks {
-1);
}
@Inject(
method = "renderStandardBlockWithColorMultiplier",
at = {
@At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/RenderBlocks;renderFaceZNeg(Lnet/minecraft/block/Block;DDDLnet/minecraft/util/IIcon;)V", ordinal = 0),
@At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/RenderBlocks;renderFaceZPos(Lnet/minecraft/block/Block;DDDLnet/minecraft/util/IIcon;)V", ordinal = 0),
}
)
private void fixBetterGrassColorMultiplierZ(Block block, int x, int y, int z, float red, float green, float blue,
CallbackInfoReturnable<Boolean> cir,
@Local(name = "tessellator") Tessellator tessellator,
@Local(name = "iicon") IIcon iicon,
@Local(name = "f11") float r,
@Local(name = "f14") float g,
@Local(name = "f17") float b) {
if (iicon.getIconName().equals("grass_top")) {
tessellator.setColorOpaque_F(r * red, g * green, b * blue);
}
}
@Inject(
method = "renderStandardBlockWithColorMultiplier",
at = {
@At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/RenderBlocks;renderFaceXNeg(Lnet/minecraft/block/Block;DDDLnet/minecraft/util/IIcon;)V", ordinal = 0),
@At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/RenderBlocks;renderFaceXPos(Lnet/minecraft/block/Block;DDDLnet/minecraft/util/IIcon;)V", ordinal = 0),
}
)
private void fixBetterGrassColorMultiplierX(Block block, int x, int y, int z, float red, float green, float blue,
CallbackInfoReturnable<Boolean> cir,
@Local(name = "tessellator") Tessellator tessellator,
@Local(name = "iicon") IIcon iicon,
@Local(name = "f12") float r,
@Local(name = "f15") float g,
@Local(name = "f18") float b) {
if (iicon.getIconName().equals("grass_top")) {
tessellator.setColorOpaque_F(r * red, g * green, b * blue);
}
}
@Redirect(
method = { "renderStandardBlockWithColorMultiplier(Lnet/minecraft/block/Block;IIIFFF)Z",
"renderStandardBlockWithAmbientOcclusionPartial(Lnet/minecraft/block/Block;IIIFFF)Z",
@@ -948,7 +976,7 @@ public abstract class MixinRenderBlocks {
target = "Lnet/minecraft/client/renderer/RenderBlocks;getBlockIconFromSideAndMetadata(Lnet/minecraft/block/Block;II)Lnet/minecraft/util/IIcon;"))
private IIcon modifyRenderBlockHopperMetadata(RenderBlocks instance, Block block, int side, int meta,
BlockHopper specializedBlock, int x, int y, int z) {
return getBlockIcon(block, blockAccess, x, y, z, side);
return CTMUtils.getBlockIcon(getIconSafe(block.getIcon(side, meta)), block, side, meta);
}
@Redirect(
@@ -999,7 +1027,7 @@ public abstract class MixinRenderBlocks {
ordinal = 1))
private IIcon mcpatcherforge$redirectToGetBlockIcon(RenderBlocks instance, Block block, int side, int meta,
Block specializedBlock, int x, int y, int z) {
return getBlockIcon(block, blockAccess, x, y, z, side);
return CTMUtils.getBlockIcon(getIconSafe(block.getIcon(side, meta)), block, side, meta);
}
@Redirect(
@@ -34,8 +34,8 @@ public abstract class MixinRenderBlockConnectedTexturesEthereal extends RenderBl
getFakeRender().setRenderBoundsFromBlock(block);
boolean render = getFakeRender().renderStandardBlock(block, x, y, z);
newFakeRenderEthereal.setWorld(renderer.blockAccess);
newFakeRenderEthereal.curBlock = fakeRender.curBlock;
newFakeRenderEthereal.curMeta = fakeRender.curMeta;
newFakeRenderEthereal.curBlock = getFakeRender().curBlock;
newFakeRenderEthereal.curMeta = getFakeRender().curMeta;
double h = 0.05D;
newFakeRenderEthereal.setRenderBounds(h, h, h, 1.0D - h, 1.0D - h, 1.0D - h);
render &= newFakeRenderEthereal.renderStandardBlock(block, x, y, z);