mirror of
https://github.com/GTNewHorizons/Angelica.git
synced 2026-11-15 01:34:48 +00:00
Compare commits
66
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
701f55b5a5 | ||
|
|
5afb5d8f5a | ||
|
|
c353c83cf3 | ||
|
|
6563c7c0ce | ||
|
|
78072236d2 | ||
|
|
52dae51121 | ||
|
|
b42eb9a6b2 | ||
|
|
5925c28d29 | ||
|
|
fedabd0fb6 | ||
|
|
350fdcd7e4 | ||
|
|
3d98e57178 | ||
|
|
55c1786811 | ||
|
|
356d826387 | ||
|
|
c34d8548a5 | ||
|
|
81a000af75 | ||
|
|
711c23c722 | ||
|
|
5aa1d504b0 | ||
|
|
60ab3b7900 | ||
|
|
912e0e83b8 | ||
|
|
104eda0b51 | ||
|
|
7fb8cde66d | ||
|
|
0e4421f2ce | ||
|
|
3cf3d096fd | ||
|
|
ffa1193dd2 | ||
|
|
d180023469 | ||
|
|
762275a6da | ||
|
|
0e66bcf42f | ||
|
|
979ad344a1 | ||
|
|
5f328e9b57 | ||
|
|
2dba62bf20 | ||
|
|
0fd4d457e2 | ||
|
|
b56e803622 | ||
|
|
3ab965ded7 | ||
|
|
538b38898c | ||
|
|
e43cd6f18e | ||
|
|
38285087c9 | ||
|
|
deb6c2b6e5 | ||
|
|
e11985a913 | ||
|
|
4bbf39eb4d | ||
|
|
8c90f79c17 | ||
|
|
e4e657846d | ||
|
|
2dace708b4 | ||
|
|
1df1ec3530 | ||
|
|
d96ac28043 | ||
|
|
72c13cff67 | ||
|
|
f233ba65e3 | ||
|
|
c0d636d4f7 | ||
|
|
bd5cd350c3 | ||
|
|
88936d3713 | ||
|
|
cf5bf2e2e7 | ||
|
|
cfd2388c85 | ||
|
|
fd78f63f12 | ||
|
|
6cf119dfee | ||
|
|
8c5f4d2543 | ||
|
|
9e1fa7b80f | ||
|
|
6c99872459 | ||
|
|
f0809410ee | ||
|
|
98299b69d2 | ||
|
|
fed0aa77c5 | ||
|
|
f7fb3186c8 | ||
|
|
ab243bb936 | ||
|
|
60cce7ea1d | ||
|
|
b837b0571d | ||
|
|
7abc6213f5 | ||
|
|
b46643ae8c | ||
|
|
e3d1fedd48 |
No files matched your search
@@ -18,6 +18,14 @@ body:
|
||||
placeholder: "Example: 1.0.0-alpha1"
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: report
|
||||
attributes:
|
||||
label: Bug Report
|
||||
description: "Relevant information, as well as relevant logs attached such as `logs/fml-client-latest.log."
|
||||
placeholder: "Example: https://mclo.gs/ OR submit the file to github by dragging it to this textbox."
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: java
|
||||
attributes:
|
||||
@@ -48,12 +56,25 @@ body:
|
||||
- Mesa/Software
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: report
|
||||
- type: dropdown
|
||||
id: shaders
|
||||
attributes:
|
||||
label: Bug Report
|
||||
description: "Relevant information, as well as relevant logs attached such as `logs/fml-client-latest.log."
|
||||
placeholder: "Example: https://mclo.gs/ OR submit the file to github by dragging it to this textbox."
|
||||
label: Shaders
|
||||
description: Do you have a shaderpack enabled?
|
||||
options:
|
||||
- "No"
|
||||
- "Yes: Please put relevant information about shaderpack in the report(what shaderpack, any special settings of note, etc)"
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: mcpf
|
||||
attributes:
|
||||
label: MCPF or other features disabled by default
|
||||
description: Do you have MCPF or any other features that are disabled by default enabled?
|
||||
options:
|
||||
- "No: Go ahead and create an issue"
|
||||
- "Yes: I will not create an issue"
|
||||
- "Yes: I don't read and shouldn't be creating an issue"
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
@@ -76,6 +97,5 @@ body:
|
||||
required: true
|
||||
- label: "I am running an officially released version. (Or, if I've compiled it myself I plan to fix the issue)"
|
||||
required: true
|
||||
- label: "This issue is not related to a feature that is disabed by default - Shaders, MCPF, etc. [They'll be enabled when they're ready for testing]"
|
||||
required: true
|
||||
|
||||
|
||||
|
||||
@@ -29,5 +29,5 @@ body:
|
||||
required: true
|
||||
- label: "I have read the known incompatibilities and this is not related to one of those."
|
||||
required: true
|
||||
- label: "This issue is not related to a feature that is disabed by default - Shaders, MCPF, etc. [They'll be enabled when they're ready for testing]"
|
||||
required: true
|
||||
- label: "This issue is not related to a feature that is disabed by default - MCPF, etc. [They'll be enabled when they're ready for testing]"
|
||||
required: true
|
||||
@@ -36,3 +36,5 @@ addon.local.gradle
|
||||
addon.local.gradle.kts
|
||||
addon.late.local.gradle
|
||||
addon.late.local.gradle.kts
|
||||
/*.csv
|
||||
!gl_functions.csv
|
||||
@@ -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)
|
||||
|
||||
@@ -66,7 +68,7 @@
|
||||
* HUDCaching
|
||||
* Created by [Moulberry](https://github.com/Moulberry/MCHUDCaching), backported from [Patcher](https://github.com/Sk1erLLC/Patcher) mod by Alexdoru under the CC-BY-SA-NC 4.0 license
|
||||
* Angelica
|
||||
* mitchej123, Omni, Makamys, Embeddedt, NanoLive, Caedis, Cardinalstar, Alexdoru, Eigenraven, mist475, Clepto for helping get Angelica up and running!
|
||||
* mitchej123, Omni, Makamys, Embeddedt, NanoLive, Caedis, Cardinalstar, Alexdoru, Eigenraven, mist475, Clepto, kurrycat for helping get Angelica up and running!
|
||||
* IMS, jss2a98aj, || dbp ||, roadhog360 for advice and moral support
|
||||
* Forge 1.12+
|
||||
* Some files have been taken from Minecraft Forge under the LGPL 2.1 license and are marked as such
|
||||
@@ -75,4 +77,8 @@
|
||||
license, see LICENSE in `com.gtnewhorizons.angelica.models`
|
||||
* Dynamic Lights
|
||||
* LambdAurora for [LambDynamicLights](https://github.com/LambdAurora/LambDynamicLights) under the MIT license, and the Forge port anthxnymc for [DynamicLightsReforged](https://github.com/anthxnymc/DynamicLightsReforged), also under the MIT license
|
||||
|
||||
* 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
|
||||
+18
-20
@@ -49,7 +49,7 @@ configurations {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly("com.github.GTNewHorizons:Hodgepodge:2.4.31")
|
||||
compileOnly("com.github.GTNewHorizons:Hodgepodge:2.5.78")
|
||||
|
||||
compileOnly("com.gtnewhorizons.retrofuturabootstrap:RetroFuturaBootstrap:0.4.0") { transitive = false }
|
||||
|
||||
@@ -57,36 +57,33 @@ 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.4.2:dev")
|
||||
api("com.github.GTNewHorizons:GTNHLib:0.5.20:dev")
|
||||
shadowImplementation("org.anarres:jcpp:1.4.14") // Apache 2.0
|
||||
implementation("io.github.douira:glsl-transformer:1.0.0")
|
||||
shadowImplementation("io.github.douira:glsl-transformer:1.0.0") { // glsl-transformer Noncommercial License 1.0.0
|
||||
shadowImplementation("org.taumc:glsl-transformation-lib:0.2.0-4.g6b42bca") {
|
||||
exclude module: "antlr4" // we only want to shadow the runtime module
|
||||
}
|
||||
shadowImplementation("org.antlr:antlr4-runtime:4.13.2")
|
||||
compileOnly "org.apache.ant:ant:1.8.2"
|
||||
|
||||
// Because who doesn't want NEI
|
||||
devOnlyNonPublishable('com.github.GTNewHorizons:NotEnoughItems:2.4.9-GTNH:dev')
|
||||
devOnlyNonPublishable('com.github.GTNewHorizons:CodeChickenCore:1.2.0: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.5.16: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.0-GTNH:dev") { transitive = false }
|
||||
compileOnly("com.github.GTNewHorizons:Natura:2.6.1: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.1:dev")
|
||||
compileOnly("com.github.GTNewHorizons:ThaumicHorizons:1.6.4:dev")
|
||||
|
||||
compileOnly("com.github.GTNewHorizons:Battlegear2:1.4.0:dev") { transitive = false }
|
||||
compileOnly(rfg.deobf('maven.modrinth:backhand:1.4.1')) { transitive = false }
|
||||
|
||||
compileOnly("com.github.GTNewHorizons:Battlegear2:1.4.0:dev") { transitive = false }
|
||||
compileOnly("com.github.GTNewHorizons:Battlegear2:1.4.1:dev") { transitive = false }
|
||||
compileOnly(rfg.deobf('maven.modrinth:backhand:1.4.1')) { transitive = false }
|
||||
|
||||
compileOnly("com.falsepattern:chunkapi-mc1.7.10:0.5.1:api") { transitive = false }
|
||||
@@ -97,15 +94,13 @@ dependencies {
|
||||
|
||||
compileOnly("curse.maven:minefactory-reloaded-66672:2277486")
|
||||
|
||||
compileOnly("com.github.GTNewHorizons:NotEnoughIds:2.0.3:dev") // Mixin Version
|
||||
compileOnly("com.github.GTNewHorizons:NotEnoughIds:2.1.6:dev") // Mixin Version
|
||||
compileOnly("com.github.GTNewHorizons:NotEnoughIds-Legacy:1.4.7:dev") // ASM Version
|
||||
|
||||
compileOnly(rfg.deobf("curse.maven:campfirebackport-387444:4611675"))
|
||||
// HMMMMM
|
||||
compileOnly(rfg.deobf("curse.maven:journeymap-32274:2367915"))
|
||||
compileOnly(rfg.deobf("curse.maven:xaeros-minimap-263420:5060684"))
|
||||
|
||||
compileOnly("com.github.GTNewHorizons:HoloInventory:2.4.4-GTNH:dev")
|
||||
compileOnly("com.github.GTNewHorizons:HoloInventory:2.4.13-GTNH:dev")
|
||||
|
||||
runtimeOnlyNonPublishable(rfg.deobf("CoreTweaks:CoreTweaks:0.3.3.2"))
|
||||
|
||||
@@ -115,10 +110,13 @@ dependencies {
|
||||
// Better Crashes
|
||||
compileOnly("com.github.GTNewHorizons:BetterCrashes:1.4.0-GTNH:dev")
|
||||
|
||||
|
||||
// Tests
|
||||
testImplementation(platform('org.junit:junit-bom:5.9.2'))
|
||||
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
File diff suppressed because it is too large.
Load diff
+7
-1
@@ -122,9 +122,15 @@ minimizeShadowedDependencies = true
|
||||
# If disabled, won't rename the shadowed classes.
|
||||
relocateShadowedDependencies = true
|
||||
|
||||
# Adds the GTNH maven, CurseMaven, Modrinth, and some more well-known 1.7.10 repositories.
|
||||
# Adds CurseMaven, Modrinth, and some more well-known 1.7.10 repositories.
|
||||
includeWellKnownRepositories = true
|
||||
|
||||
# A list of repositories to exclude from the includeWellKnownRepositories setting. Should be a space separated
|
||||
# list of strings, with the acceptable keys being(case does not matter):
|
||||
# cursemaven
|
||||
# modrinth
|
||||
excludeWellKnownRepositories =
|
||||
|
||||
# Change these to your Maven coordinates if you want to publish to a custom Maven repository instead of the default GTNH Maven.
|
||||
# Authenticate with the MAVEN_USER and MAVEN_PASSWORD environment variables.
|
||||
# If you need a more complex setup disable maven publishing here and add a publishing repository to addon.gradle.
|
||||
|
||||
Vendored
BIN
Binary file not shown.
+1
-1
@@ -1,6 +1,6 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
@@ -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
@@ -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 ##########################################################################
|
||||
|
||||
@@ -25,5 +25,12 @@ repositories {
|
||||
includeGroup('CoreTweaks')
|
||||
}
|
||||
}
|
||||
maven {
|
||||
name = 'taumc'
|
||||
url = 'https://maven.taumc.org/releases'
|
||||
content {
|
||||
includeGroup 'org.taumc'
|
||||
}
|
||||
}
|
||||
mavenLocal()
|
||||
}
|
||||
+1
-1
@@ -16,5 +16,5 @@ pluginManagement {
|
||||
}
|
||||
|
||||
plugins {
|
||||
id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.26'
|
||||
id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.29'
|
||||
}
|
||||
@@ -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, "");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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,5 +1,6 @@
|
||||
package com.gtnewhorizons.angelica;
|
||||
|
||||
import com.gtnewhorizons.angelica.common.BlockError;
|
||||
import com.gtnewhorizons.angelica.compat.ModStatus;
|
||||
import com.gtnewhorizons.angelica.proxy.CommonProxy;
|
||||
import com.gtnewhorizons.angelica.utils.AnimationMode;
|
||||
@@ -27,10 +28,13 @@ public class AngelicaMod {
|
||||
|
||||
public static final ManagedEnum<AnimationMode> animationsMode = new ManagedEnum<>(AnimationMode.VISIBLE_ONLY);
|
||||
|
||||
public static BlockError blockError;
|
||||
|
||||
@Mod.EventHandler
|
||||
public void preInit(FMLPreInitializationEvent event) {
|
||||
ModStatus.preInit();
|
||||
proxy.preInit(event);
|
||||
blockError = new BlockError();
|
||||
}
|
||||
|
||||
@Mod.EventHandler
|
||||
|
||||
@@ -357,7 +357,7 @@ public class BatchingFontRenderer {
|
||||
final float underlineY = anchorY + underlying.FONT_HEIGHT - 1.0f;
|
||||
float underlineStartX = 0.0f;
|
||||
float underlineEndX = 0.0f;
|
||||
final float strikethroughY = anchorY + (float) (underlying.FONT_HEIGHT / 2);
|
||||
final float strikethroughY = anchorY + (float) (underlying.FONT_HEIGHT / 2) - 1.0F;
|
||||
float strikethroughStartX = 0.0f;
|
||||
float strikethroughEndX = 0.0f;
|
||||
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.gtnewhorizons.angelica.common;
|
||||
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.util.IIcon;
|
||||
import net.minecraftforge.client.event.TextureStitchEvent;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
|
||||
|
||||
/**
|
||||
* This Block is not actually getting registered. A static instance is created in AngelicaMod.
|
||||
* Actually registering the block on the client but not the server can cause block IDs to
|
||||
* different between client/server, which is not good.
|
||||
|
||||
* We're essentially injecting the block's texture, so that we may use this block as if it were
|
||||
* any normal block for rendering purposes with RenderBlocks and such, but not have to actually
|
||||
* register it as a block.
|
||||
*/
|
||||
|
||||
public class BlockError extends Block {
|
||||
|
||||
public static final IIcon[] icons = new IIcon[2];
|
||||
|
||||
public BlockError() {
|
||||
super(Material.rock);
|
||||
|
||||
MinecraftForge.EVENT_BUS.register(this);
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
@SideOnly(Side.CLIENT)
|
||||
public void onTextureStitch(TextureStitchEvent.Pre event) {
|
||||
if (event.map.getTextureType() == 0) {
|
||||
for (int i = 0; i < icons.length; i++) {
|
||||
icons[i] = event.map.registerIcon("angelica:error_block_" + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SideOnly(Side.CLIENT)
|
||||
public IIcon getIcon(int side, int meta) {
|
||||
return meta >= 0 && meta < icons.length ? icons[meta] : null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import com.gtnewhorizons.angelica.helpers.LoadControllerHelper;
|
||||
import cpw.mods.fml.common.Loader;
|
||||
import cpw.mods.fml.common.versioning.ArtifactVersion;
|
||||
import cpw.mods.fml.common.versioning.DefaultArtifactVersion;
|
||||
import mods.battlegear2.Battlegear;
|
||||
import net.dries007.holoInventory.HoloInventory;
|
||||
import xonin.backhand.Backhand;
|
||||
|
||||
@@ -52,6 +53,14 @@ public class ModStatus {
|
||||
) <= 0;
|
||||
}
|
||||
|
||||
// remove compat with original release of BG2
|
||||
if (isBattlegearLoaded){
|
||||
isBattlegearLoaded = new DefaultArtifactVersion("1.2.0")
|
||||
.compareTo(
|
||||
LoadControllerHelper.getOwningMod(Battlegear.class).getProcessedVersion()
|
||||
) <= 0;
|
||||
}
|
||||
|
||||
if (isBackhandLoaded){
|
||||
isBackhandLoaded = new DefaultArtifactVersion("1.4.1")
|
||||
.compareTo(
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -33,7 +33,7 @@ public class AngelicaConfig {
|
||||
public static boolean enableTestBlocks;
|
||||
|
||||
@Config.Comment("Enable Iris Shaders [Requires Sodium]")
|
||||
@Config.DefaultBoolean(false)
|
||||
@Config.DefaultBoolean(true)
|
||||
@Config.RequiresMcRestart
|
||||
public static boolean enableIris;
|
||||
|
||||
@@ -107,28 +107,45 @@ public class AngelicaConfig {
|
||||
@Config.RequiresMcRestart
|
||||
public static boolean optimizeTextureLoading;
|
||||
|
||||
@Config.Comment("Fix thread-safety in lotrs rendering")
|
||||
@Config.DefaultBoolean(true)
|
||||
@Config.RequiresMcRestart
|
||||
public static boolean fixLotrSodiumCompat;
|
||||
|
||||
@Config.Comment("Fix thread-safety in Extra Utilities rendering")
|
||||
@Config.DefaultBoolean(true)
|
||||
@Config.RequiresMcRestart
|
||||
public static boolean fixExtraUtilsSodiumCompat;
|
||||
|
||||
@Config.Comment("Fix thread-safety issues in MineFactory Reloaded")
|
||||
@Config.DefaultBoolean(true)
|
||||
@Config.RequiresMcRestart
|
||||
public static boolean fixMineFactoryReloadedSodiumCompat;
|
||||
|
||||
@Config.Comment("Fix RenderBlockFluid reading the block type from the world access multiple times")
|
||||
@Config.DefaultBoolean(true)
|
||||
@Config.RequiresMcRestart
|
||||
public static boolean fixFluidRendererCheckingBlockAgain;
|
||||
|
||||
@Config.Comment("Dynamically modifies the render distance of dropped items entities to preserve performance."
|
||||
+ " It starts reducing the render distance when exceeding the threshold set below.")
|
||||
@Config.DefaultBoolean(true)
|
||||
@Config.RequiresMcRestart
|
||||
public static boolean dynamicItemRenderDistance;
|
||||
|
||||
@Config.Comment("Max amount of dropped item rendered")
|
||||
@Config.DefaultInt(256)
|
||||
@Config.RangeInt(min = 32, max = 2048)
|
||||
public static int droppedItemLimit;
|
||||
|
||||
@Config.Comment("Use total world time instead of normal world time. Allows most shader animations to play when "
|
||||
+ "doDaylightCycle is off, but causes shader animations to desync from time of day.")
|
||||
@Config.DefaultBoolean(false)
|
||||
public static boolean useTotalWorldTime;
|
||||
|
||||
@Config.Comment("Enable Debug Logging")
|
||||
@Config.DefaultBoolean(false)
|
||||
@Config.RequiresMcRestart
|
||||
public static boolean enableDebugLogging;
|
||||
|
||||
@Config.Comment("Enable Zoom")
|
||||
@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,42 @@
|
||||
package com.gtnewhorizons.angelica.config;
|
||||
|
||||
import com.gtnewhorizon.gtnhlib.config.Config;
|
||||
|
||||
@Config(modid = "angelica", filename = "angelica-compat")
|
||||
public class CompatConfig {
|
||||
|
||||
@Config.Comment("Apply fixes to the LOTR mod")
|
||||
@Config.DefaultBoolean(true)
|
||||
@Config.RequiresMcRestart
|
||||
public static boolean fixLotr;
|
||||
|
||||
@Config.Comment("Apply fixes to Extra Utilities")
|
||||
@Config.DefaultBoolean(true)
|
||||
@Config.RequiresMcRestart
|
||||
public static boolean fixExtraUtils;
|
||||
|
||||
@Config.Comment("Apply fixes to Stacks on Stacks")
|
||||
@Config.DefaultBoolean(true)
|
||||
@Config.RequiresMcRestart
|
||||
public static boolean fixStacksOnStacks;
|
||||
|
||||
@Config.Comment("Apply fixes to Minefactory Reloaded")
|
||||
@Config.DefaultBoolean(true)
|
||||
@Config.RequiresMcRestart
|
||||
public static boolean fixMinefactoryReloaded;
|
||||
|
||||
@Config.Comment("Apply fixes to Thaumcraft")
|
||||
@Config.DefaultBoolean(true)
|
||||
@Config.RequiresMcRestart
|
||||
public static boolean fixThaumcraft;
|
||||
|
||||
@Config.Comment("Apply fixes to ThaumicHorizons")
|
||||
@Config.DefaultBoolean(true)
|
||||
@Config.RequiresMcRestart
|
||||
public static boolean fixThaumicHorizons;
|
||||
|
||||
@Config.Comment("Apply fixes to Immersive Engineering")
|
||||
@Config.DefaultBoolean(true)
|
||||
@Config.RequiresMcRestart
|
||||
public static boolean fixImmersiveEngineering;
|
||||
}
|
||||
@@ -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
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -37,6 +37,7 @@ import java.util.function.Predicate;
|
||||
public class DynamicLights {
|
||||
private static DynamicLights instance;
|
||||
public static DynamicLightsMode Mode = DynamicLightsMode.OFF;
|
||||
public static boolean ShaderForce = false;
|
||||
|
||||
private static final double MAX_RADIUS = 7.75;
|
||||
private static final double MAX_RADIUS_SQUARED = MAX_RADIUS * MAX_RADIUS;
|
||||
@@ -52,7 +53,11 @@ public class DynamicLights {
|
||||
}
|
||||
|
||||
public static boolean isEnabled() {
|
||||
return AngelicaConfig.enableDynamicLights && Mode.isEnabled() && !IrisApi.getInstance().isShaderPackInUse();
|
||||
return AngelicaConfig.enableDynamicLights &&
|
||||
Mode.isEnabled() &&
|
||||
// if shader force is enabled then true
|
||||
// if not, then true when shaders are not in use
|
||||
(ShaderForce || !IrisApi.getInstance().isShaderPackInUse());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -65,7 +70,7 @@ public class DynamicLights {
|
||||
return;
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
if (now >= this.lastUpdate + 50) {
|
||||
if (now >= this.lastUpdate + Mode.getDelay()) {
|
||||
this.lastUpdate = now;
|
||||
this.lastUpdateCount = 0;
|
||||
|
||||
|
||||
@@ -7,7 +7,8 @@ public enum DynamicLightsMode
|
||||
OFF("Off", 0),
|
||||
FASTEST("Fastest", 500),
|
||||
FAST("Fast", 250),
|
||||
FANCY("Fancy", 0);
|
||||
FANCY("Fancy", 50),
|
||||
REALTIME("Realtime", 0);
|
||||
|
||||
private final String name;
|
||||
private final int delay;
|
||||
|
||||
@@ -73,13 +73,6 @@ public interface IDynamicLightSource {
|
||||
*/
|
||||
void angelica$dynamicLightTick();
|
||||
|
||||
/**
|
||||
* Returns whether this dynamic light source should update.
|
||||
*
|
||||
* @return {@code true} if this dynamic light source should update, else {@code false}
|
||||
*/
|
||||
boolean angelica$shouldUpdateDynamicLight();
|
||||
|
||||
boolean angelica$updateDynamicLight(@NotNull SodiumWorldRenderer renderer);
|
||||
|
||||
void angelica$scheduleTrackedChunksRebuild(@NotNull SodiumWorldRenderer renderer);
|
||||
|
||||
@@ -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<>();
|
||||
@@ -971,6 +972,20 @@ public class GLStateManager {
|
||||
GL11.glDrawBuffer(mode);
|
||||
}
|
||||
|
||||
public static void glDrawElements(int mode, IntBuffer indices) {
|
||||
if(AngelicaConfig.enableIris) {
|
||||
Iris.getPipelineManager().getPipeline().ifPresent(WorldRenderingPipeline::syncProgram);
|
||||
}
|
||||
GL11.glDrawElements(mode, indices);
|
||||
}
|
||||
|
||||
public static void glBegin(int mode) {
|
||||
if (AngelicaConfig.enableIris) {
|
||||
Iris.getPipelineManager().getPipeline().ifPresent(WorldRenderingPipeline::syncProgram);
|
||||
}
|
||||
GL11.glBegin(mode);
|
||||
}
|
||||
|
||||
public static void glLogicOp(int opcode) {
|
||||
GL11.glLogicOp(opcode);
|
||||
}
|
||||
@@ -1173,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;
|
||||
@@ -1188,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();
|
||||
|
||||
@@ -19,9 +19,7 @@ import org.lwjgl.opengl.GL30;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
|
||||
import cpw.mods.fml.client.registry.ClientRegistry;
|
||||
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
|
||||
import cpw.mods.fml.common.gameevent.InputEvent;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.Gui;
|
||||
import net.minecraft.client.gui.GuiIngame;
|
||||
@@ -29,9 +27,7 @@ import net.minecraft.client.gui.ScaledResolution;
|
||||
import net.minecraft.client.renderer.EntityRenderer;
|
||||
import net.minecraft.client.renderer.OpenGlHelper;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.client.settings.KeyBinding;
|
||||
import net.minecraft.client.shader.Framebuffer;
|
||||
import net.minecraft.util.ChatComponentText;
|
||||
import net.minecraftforge.client.GuiIngameForge;
|
||||
import thaumcraft.common.Thaumcraft;
|
||||
import xaero.common.core.XaeroMinimapCore;
|
||||
@@ -70,31 +66,6 @@ public class HUDCaching {
|
||||
|
||||
private HUDCaching() {}
|
||||
|
||||
/* TODO START REMOVE DEBUG STUFF */
|
||||
|
||||
private final List<Long> updateTimeList = new ArrayList<>(21);
|
||||
private static boolean isEnabled = true;
|
||||
|
||||
// moved initialization to when its registered to avoid an empty Debug category, which can cause crashes when
|
||||
// opening the controls menu and hudcaching is disabled in the config
|
||||
private static KeyBinding toggle;
|
||||
|
||||
public static void registerKeyBindings() {
|
||||
toggle = new KeyBinding("Toggle HUDCaching", 0, "Debug");
|
||||
ClientRegistry.registerKeyBinding(toggle);
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void onKeypress(InputEvent.KeyInputEvent event) {
|
||||
if (toggle != null && toggle.isPressed()) {
|
||||
isEnabled = !isEnabled;
|
||||
final String msg = isEnabled ? "Enabled HUDCaching" : "Disabled HUDCaching";
|
||||
if (mc.thePlayer != null) mc.thePlayer.addChatMessage(new ChatComponentText(msg));
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO END REMOVE DEBUG STUFF */
|
||||
|
||||
// highest so it runs before the GLSM load event
|
||||
@SubscribeEvent(priority = EventPriority.HIGH)
|
||||
public void onJoinWorld(WorldEvent.Load event) {
|
||||
@@ -112,7 +83,7 @@ public class HUDCaching {
|
||||
XaeroMinimapCore.beforeIngameGuiRender(partialTicks);
|
||||
}
|
||||
|
||||
if (!OpenGlHelper.isFramebufferEnabled() || !isEnabled || framebuffer == null) {
|
||||
if (!OpenGlHelper.isFramebufferEnabled() || framebuffer == null) {
|
||||
ingame.renderGameOverlay(partialTicks, hasScreen, mouseX, mouseY);
|
||||
return;
|
||||
}
|
||||
@@ -244,13 +215,14 @@ public class HUDCaching {
|
||||
|
||||
// moved to here due to the method being called from a mixin
|
||||
public static void disableHoloInventory() {
|
||||
if (ModStatus.isHoloInventoryLoaded){
|
||||
Renderer.INSTANCE.angelicaOverride = isEnabled;
|
||||
if (ModStatus.isHoloInventoryLoaded) {
|
||||
Renderer.INSTANCE.angelicaOverride = true;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused") // called via ASM
|
||||
public static class HUDCachingHooks {
|
||||
public static boolean shouldReturnEarly(){
|
||||
public static boolean shouldReturnEarly() {
|
||||
return renderingCacheOverride;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,21 @@
|
||||
package com.gtnewhorizons.angelica.loading;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.gtnewhorizon.gtnhlib.asm.ASMUtil;
|
||||
import com.gtnewhorizon.gtnhlib.config.ConfigException;
|
||||
import com.gtnewhorizon.gtnhlib.config.ConfigurationManager;
|
||||
import com.gtnewhorizon.gtnhmixins.IEarlyMixinLoader;
|
||||
import com.gtnewhorizons.angelica.config.AngelicaConfig;
|
||||
import com.gtnewhorizons.angelica.config.CompatConfig;
|
||||
import com.gtnewhorizons.angelica.mixins.Mixins;
|
||||
import com.gtnewhorizons.angelica.mixins.TargetedMod;
|
||||
import com.gtnewhorizons.angelica.transform.compat.CompatASMTransformers;
|
||||
import com.gtnewhorizons.angelica.transform.compat.GenericCompatTransformer;
|
||||
import com.gtnewhorizons.angelica.transform.compat.handlers.CompatHandler;
|
||||
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;
|
||||
@@ -21,22 +26,28 @@ import org.spongepowered.asm.launch.GlobalProperties;
|
||||
import org.spongepowered.asm.service.mojang.MixinServiceLaunchWrapper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
// ================== Important ==================
|
||||
// Due to a bug caused by this class both implementing
|
||||
// IFMLLoadingPlugin and IEarlyMixinLoader,
|
||||
// the IClassTransformer registered in this class
|
||||
// will not respect the sorting index defined.
|
||||
// They will instead use default index 0 which means they will see
|
||||
// obfuscated mappings and not SRG mappings when running outside of dev env.
|
||||
// ===============================================
|
||||
//@IFMLLoadingPlugin.SortingIndex(Integer.MAX_VALUE - 5)
|
||||
@IFMLLoadingPlugin.MCVersion("1.7.10")
|
||||
@IFMLLoadingPlugin.TransformerExclusions(
|
||||
{
|
||||
@IFMLLoadingPlugin.TransformerExclusions({
|
||||
"com.gtnewhorizons.angelica.transform.RedirectorTransformer",
|
||||
"com.gtnewhorizons.angelica.glsm.GLStateManager"
|
||||
}
|
||||
)
|
||||
@IFMLLoadingPlugin.SortingIndex(Integer.MAX_VALUE - 5)
|
||||
"com.gtnewhorizons.angelica.glsm.GLStateManager"})
|
||||
public class AngelicaTweaker implements IFMLLoadingPlugin, IEarlyMixinLoader {
|
||||
|
||||
private static final boolean DUMP_CLASSES = Boolean.parseBoolean(System.getProperty("angelica.dumpClass", "false"));
|
||||
private static boolean OBF_ENV;
|
||||
public static final Logger LOGGER = LogManager.getLogger("Angelica");
|
||||
|
||||
private String[] transformerClasses;
|
||||
@@ -45,6 +56,8 @@ public class AngelicaTweaker implements IFMLLoadingPlugin, IEarlyMixinLoader {
|
||||
try {
|
||||
// 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);
|
||||
@@ -68,17 +81,24 @@ public class AngelicaTweaker implements IFMLLoadingPlugin, IEarlyMixinLoader {
|
||||
if (mixinTweakClasses != null) {
|
||||
mixinTweakClasses.add(MixinCompatHackTweaker.class.getName());
|
||||
}
|
||||
|
||||
// Return any others here
|
||||
if (transformerClasses == null) {
|
||||
|
||||
//Mod Compat transformers
|
||||
final List<String> transformers = new ArrayList<>();
|
||||
transformers.addAll(CompatASMTransformers.getTransformers());
|
||||
|
||||
//NotFine transformers
|
||||
Namer.initNames();
|
||||
transformers.addAll(Arrays.asList(AsmTransformers.getTransformers()));
|
||||
// Regsiter compat handlers, and add extra specific transformers, then build and register the generic transformer
|
||||
for (CompatHandler handler : CompatHandlers.getHandlers()) {
|
||||
GenericCompatTransformer.register(handler);
|
||||
if (handler.extraTransformers() != null) {
|
||||
transformers.addAll(handler.extraTransformers());
|
||||
}
|
||||
}
|
||||
|
||||
GenericCompatTransformer.build();
|
||||
transformers.add(GenericCompatTransformer.class.getName());
|
||||
|
||||
// Add NotFine transformers
|
||||
final List<String> notFineTransformers = AsmTransformers.getTransformers();
|
||||
if (!notFineTransformers.isEmpty()) Namer.initNames();
|
||||
transformers.addAll(notFineTransformers);
|
||||
|
||||
transformerClasses = transformers.toArray(new String[0]);
|
||||
}
|
||||
@@ -97,7 +117,7 @@ public class AngelicaTweaker implements IFMLLoadingPlugin, IEarlyMixinLoader {
|
||||
|
||||
@Override
|
||||
public void injectData(Map<String, Object> data) {
|
||||
// no-op
|
||||
OBF_ENV = (boolean) data.get("runtimeDeobfuscationEnabled");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -115,6 +135,24 @@ public class AngelicaTweaker implements IFMLLoadingPlugin, IEarlyMixinLoader {
|
||||
return Mixins.getEarlyMixins(loadedCoreMods);
|
||||
}
|
||||
|
||||
public static boolean DUMP_CLASSES() {
|
||||
return DUMP_CLASSES || !OBF_ENV;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if we are in an obfuscated environment, returns false in dev environment.
|
||||
*/
|
||||
public static boolean isObfEnv() {
|
||||
return OBF_ENV;
|
||||
}
|
||||
|
||||
public static void dumpClass(String className, byte[] originalBytes, byte[] transformedBytes, Object transformer) {
|
||||
if (AngelicaTweaker.DUMP_CLASSES()) {
|
||||
ASMUtil.saveAsRawClassFile(originalBytes, className + "_PRE", transformer);
|
||||
ASMUtil.saveAsRawClassFile(transformedBytes, className + "_POST", transformer);
|
||||
}
|
||||
}
|
||||
|
||||
private static final ImmutableMap<String, TargetedMod> MODS_BY_CLASS = ImmutableMap.<String, TargetedMod>builder()
|
||||
.put("optifine.OptiFineForgeTweaker", TargetedMod.OPTIFINE)
|
||||
.put("fastcraft.Tweaker", TargetedMod.FASTCRAFT)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.gtnewhorizons.angelica.mixins;
|
||||
|
||||
import com.gtnewhorizons.angelica.AngelicaMod;
|
||||
import com.gtnewhorizons.angelica.config.AngelicaConfig;
|
||||
import com.gtnewhorizons.angelica.config.CompatConfig;
|
||||
import com.gtnewhorizons.angelica.loading.AngelicaTweaker;
|
||||
import cpw.mods.fml.relauncher.FMLLaunchHandler;
|
||||
import jss.notfine.config.MCPatcherForgeConfig;
|
||||
@@ -26,9 +27,12 @@ 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"
|
||||
)
|
||||
),
|
||||
ANGELICA_VBO(
|
||||
@@ -69,6 +73,16 @@ public enum Mixins {
|
||||
.setApplyIf(() -> AngelicaConfig.fixFluidRendererCheckingBlockAgain)
|
||||
.addTargetedMod(TargetedMod.VANILLA)),
|
||||
|
||||
ANGELICA_LIMIT_DROPPED_ITEM_ENTITIES(new Builder("Dynamically modifies the render distance of dropped items entities to preserve performance")
|
||||
.setPhase(Phase.EARLY).addMixinClasses("angelica.optimizations.MixinRenderGlobal_ItemRenderDist").setSide(Side.CLIENT)
|
||||
.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(
|
||||
@@ -100,15 +114,15 @@ public enum Mixins {
|
||||
|
||||
SODIUM(new Builder("Sodium").addTargetedMod(TargetedMod.VANILLA).setSide(Side.CLIENT)
|
||||
.setPhase(Phase.EARLY).setApplyIf(() -> AngelicaConfig.enableSodium).addMixinClasses(
|
||||
"sodium.MixinChunkProviderClient"
|
||||
,"sodium.MixinBlock"
|
||||
"sodium.MixinBlock"
|
||||
,"sodium.MixinBlockFluidBase"
|
||||
,"sodium.AccessorBiomeColorEvent"
|
||||
,"sodium.MixinBiomeGenBase"
|
||||
,"sodium.MixinChunk"
|
||||
,"sodium.MixinChunkProviderServer"
|
||||
,"sodium.MixinClientRegistry"
|
||||
,"sodium.MixinEntity"
|
||||
,"sodium.MixinEntity_RenderDist"
|
||||
,"sodium.MixinEntityItem_RenderDist"
|
||||
,"sodium.MixinRenderManager"
|
||||
,"sodium.MixinExtendedBlockStorage"
|
||||
,"sodium.MixinEntityRenderer"
|
||||
@@ -131,25 +145,18 @@ public enum Mixins {
|
||||
)
|
||||
),
|
||||
|
||||
// Required for Sodium's FluidRenderer, so it treats vanilla liquids as IFluidBlocks
|
||||
SODIUM_WISHLIST(new Builder("Sodiumer").addTargetedMod(TargetedMod.VANILLA).setSide(Side.BOTH)
|
||||
.setPhase(Phase.EARLY).setApplyIf(() -> AngelicaConfig.enableSodiumFluidRendering).addMixinClasses(
|
||||
"sodium.MixinBlockLiquid")),
|
||||
|
||||
IRIS_RENDERING(new Builder("Iris Shaders").addTargetedMod(TargetedMod.VANILLA).setSide(Side.CLIENT)
|
||||
.setPhase(Phase.EARLY).setApplyIf(() -> AngelicaConfig.enableIris).addMixinClasses(
|
||||
"shaders.MixinEntityRenderer"
|
||||
,"shaders.MixinGuiIngameForge"
|
||||
,"shaders.MixinFramebuffer"
|
||||
,"shaders.MixinItem"
|
||||
,"shaders.MixinItemRenderer"
|
||||
,"shaders.MixinLocale"
|
||||
,"shaders.MixinOpenGlHelper"
|
||||
,"shaders.MixinRender"
|
||||
,"shaders.MixinRenderDragon"
|
||||
,"shaders.MixinRenderEnderman"
|
||||
,"shaders.MixinRendererLivingEntity"
|
||||
,"shaders.MixinRenderGlobal"
|
||||
,"shaders.MixinRenderSpider"
|
||||
,"shaders.MixinTileEntityBeaconRenderer"
|
||||
)
|
||||
),
|
||||
@@ -171,6 +178,14 @@ public enum Mixins {
|
||||
,"angelica.textures.MixinTextureUtil"
|
||||
)),
|
||||
|
||||
ANGELICA_ZOOM(new Builder("Zoom").addTargetedMod(TargetedMod.VANILLA).setSide(Side.CLIENT)
|
||||
.setPhase(Phase.EARLY).setApplyIf(() -> AngelicaConfig.enableZoom)
|
||||
.addMixinClasses(
|
||||
"angelica.zoom.MixinEntityRenderer_Zoom",
|
||||
"angelica.zoom.MixinMinecraft_Zoom",
|
||||
"angelica.zoom.MixinMouseFilter"
|
||||
)),
|
||||
|
||||
HUD_CACHING(new Builder("Renders the HUD elements 20 times per second maximum to improve performance")
|
||||
.addTargetedMod(TargetedMod.VANILLA).setSide(Side.CLIENT).setPhase(Phase.EARLY)
|
||||
.setApplyIf(() -> AngelicaConfig.enableHudCaching).addMixinClasses(
|
||||
@@ -205,7 +220,7 @@ public enum Mixins {
|
||||
|
||||
EXTRA_UTILITIES_THREAD_SAFETY(new Builder("Enable thread safety fixes in Extra Utilities").setPhase(Phase.LATE)
|
||||
.addTargetedMod(TargetedMod.EXTRAUTILS).setSide(Side.CLIENT)
|
||||
.setApplyIf(() -> AngelicaConfig.fixExtraUtilsSodiumCompat)
|
||||
.setApplyIf(() -> CompatConfig.fixExtraUtils)
|
||||
.addMixinClasses(
|
||||
"client.extrautils.MixinRenderBlockConnectedTextures",
|
||||
"client.extrautils.MixinRenderBlockConnectedTexturesEthereal",
|
||||
@@ -213,7 +228,7 @@ public enum Mixins {
|
||||
|
||||
MFR_THREAD_SAFETY(new Builder("Enable thread safety fixes for MineFactory Reloaded").setPhase(Phase.LATE)
|
||||
.addTargetedMod(TargetedMod.MINEFACTORY_RELOADED).setSide(Side.CLIENT)
|
||||
.setApplyIf(() -> AngelicaConfig.fixMineFactoryReloadedSodiumCompat)
|
||||
.setApplyIf(() -> CompatConfig.fixMinefactoryReloaded)
|
||||
.addMixinClasses("client.minefactoryreloaded.MixinRedNetCableRenderer")),
|
||||
|
||||
SPEEDUP_CAMPFIRE_BACKPORT_ANIMATIONS(new Builder("Add animation speedup support to Campfire Backport").setPhase(Phase.LATE)
|
||||
@@ -292,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",
|
||||
@@ -376,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",
|
||||
@@ -432,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",
|
||||
@@ -451,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",
|
||||
@@ -467,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",
|
||||
@@ -491,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",
|
||||
@@ -501,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")
|
||||
),
|
||||
@@ -569,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,11 +1,18 @@
|
||||
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;
|
||||
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;
|
||||
@@ -14,6 +21,7 @@ import com.gtnewhorizons.angelica.models.VanillaModels;
|
||||
import com.gtnewhorizons.angelica.render.CloudRenderer;
|
||||
import com.gtnewhorizons.angelica.rendering.AngelicaBlockSafetyRegistry;
|
||||
import com.gtnewhorizons.angelica.utils.AssetLoader;
|
||||
import com.gtnewhorizons.angelica.zoom.Zoom;
|
||||
import cpw.mods.fml.client.registry.ClientRegistry;
|
||||
import cpw.mods.fml.common.FMLCommonHandler;
|
||||
import cpw.mods.fml.common.event.FMLInitializationEvent;
|
||||
@@ -24,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;
|
||||
@@ -51,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) {
|
||||
@@ -95,8 +102,7 @@ public class ClientProxy extends CommonProxy {
|
||||
|
||||
if (AngelicaConfig.enableHudCaching) {
|
||||
FMLCommonHandler.instance().bus().register(HUDCaching.INSTANCE);
|
||||
MinecraftForge.EVENT_BUS.register(HUDCaching.INSTANCE); // TODO remove debug stuff, unused registration}
|
||||
HUDCaching.registerKeyBindings();
|
||||
MinecraftForge.EVENT_BUS.register(HUDCaching.INSTANCE);
|
||||
}
|
||||
if (AngelicaConfig.enableSodium) {
|
||||
MinecraftForge.EVENT_BUS.register(SodiumDebugScreenHandler.INSTANCE);
|
||||
@@ -129,7 +135,7 @@ public class ClientProxy extends CommonProxy {
|
||||
FMLCommonHandler.instance().bus().register(this);
|
||||
MinecraftForge.EVENT_BUS.register(this);
|
||||
|
||||
glsmKeyBinding = new KeyBinding("Print GLSM Debug", Keyboard.KEY_NONE, "Angelica Keybinds");
|
||||
glsmKeyBinding = new KeyBinding("Print GLSM Debug", Keyboard.KEY_NONE, "Angelica");
|
||||
ClientRegistry.registerKeyBinding(glsmKeyBinding);
|
||||
|
||||
VanillaModels.init();
|
||||
@@ -137,6 +143,9 @@ public class ClientProxy extends CommonProxy {
|
||||
if (ModStatus.isBetterCrashesLoaded) {
|
||||
BetterCrashesCompat.init();
|
||||
}
|
||||
if (AngelicaConfig.enableZoom) {
|
||||
Zoom.init();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean wasGLSMKeyPressed;
|
||||
@@ -154,7 +163,7 @@ public class ClientProxy extends CommonProxy {
|
||||
public void postInit(FMLPostInitializationEvent event) {
|
||||
super.postInit(event);
|
||||
|
||||
if (ModStatus.isLotrLoaded && AngelicaConfig.enableSodium && AngelicaConfig.fixLotrSodiumCompat) {
|
||||
if (ModStatus.isLotrLoaded && AngelicaConfig.enableSodium && CompatConfig.fixLotr) {
|
||||
try {
|
||||
Class<?> lotrRendering = Class.forName("lotr.common.coremod.LOTRReplacedMethods$BlockRendering");
|
||||
ReflectionHelper.setPrivateValue(lotrRendering, null, new ConcurrentHashMap<>(), "naturalBlockClassTable");
|
||||
@@ -179,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);
|
||||
@@ -199,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();
|
||||
@@ -206,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++) {
|
||||
@@ -246,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;
|
||||
@@ -268,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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -303,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.gtnewhorizons.angelica.transform;
|
||||
|
||||
import com.gtnewhorizons.angelica.loading.AngelicaTweaker;
|
||||
|
||||
public class AsmUtil {
|
||||
|
||||
public static String obf(String deobf, String obf) {
|
||||
if (AngelicaTweaker.isObfEnv()) {
|
||||
return obf;
|
||||
}
|
||||
return deobf;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.gtnewhorizons.angelica.transform;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.gtnewhorizons.angelica.loading.AngelicaTweaker;
|
||||
import net.minecraft.launchwrapper.IClassTransformer;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.objectweb.asm.ClassReader;
|
||||
@@ -10,9 +11,8 @@ import org.objectweb.asm.tree.ClassNode;
|
||||
import java.util.List;
|
||||
|
||||
public class BlockTransformer implements IClassTransformer {
|
||||
public static final String BlockClass = "net/minecraft/block/Block";
|
||||
public static final String BlockPackage = BlockClass.substring(0, BlockClass.lastIndexOf('/') + 1);
|
||||
private static final String BlockClassFriendly = BlockClass.replace('/', '.');
|
||||
|
||||
private static final String BlockClassFriendly = "net.minecraft.block.Block";
|
||||
public static final List<Pair<String, String>> BlockBoundsFields = ImmutableList.of(
|
||||
Pair.of("minX", "field_149759_B"),
|
||||
Pair.of("minY", "field_149760_C"),
|
||||
@@ -28,18 +28,18 @@ public class BlockTransformer implements IClassTransformer {
|
||||
*/
|
||||
@Override
|
||||
public byte[] transform(String name, String transformedName, byte[] basicClass) {
|
||||
if(basicClass != null && transformedName.equals(BlockClassFriendly)) {
|
||||
if (basicClass != null && BlockClassFriendly.equals(transformedName)) {
|
||||
final ClassReader cr = new ClassReader(basicClass);
|
||||
final ClassNode cn = new ClassNode();
|
||||
cr.accept(cn, 0);
|
||||
|
||||
cn.fields.removeIf(node -> BlockBoundsFields.stream().anyMatch(pair -> node.name.equals(pair.getLeft()) || node.name.equals(pair.getRight())));
|
||||
|
||||
cn.fields.removeIf(field -> BlockBoundsFields.stream().anyMatch(pair -> field.name.equals(pair.getLeft()) || field.name.equals(pair.getRight())));
|
||||
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
|
||||
cn.accept(cw);
|
||||
basicClass = cw.toByteArray();
|
||||
final byte[] bytes = cw.toByteArray();
|
||||
AngelicaTweaker.dumpClass(transformedName, basicClass, bytes, this);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
return basicClass;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,112 +0,0 @@
|
||||
package com.gtnewhorizons.angelica.transform;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.gtnewhorizons.angelica.loading.AngelicaTweaker;
|
||||
import net.minecraft.launchwrapper.IClassTransformer;
|
||||
import net.minecraft.launchwrapper.Launch;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.spongepowered.asm.lib.ClassReader;
|
||||
import org.spongepowered.asm.lib.ClassWriter;
|
||||
import org.spongepowered.asm.lib.Opcodes;
|
||||
import org.spongepowered.asm.lib.tree.ClassNode;
|
||||
import org.spongepowered.asm.lib.tree.InsnList;
|
||||
import org.spongepowered.asm.lib.tree.InsnNode;
|
||||
import org.spongepowered.asm.lib.tree.JumpInsnNode;
|
||||
import org.spongepowered.asm.lib.tree.LabelNode;
|
||||
import org.spongepowered.asm.lib.tree.MethodInsnNode;
|
||||
import org.spongepowered.asm.lib.tree.MethodNode;
|
||||
import org.spongepowered.asm.transformers.MixinClassWriter;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
public class HUDCachingTransformer implements IClassTransformer, Opcodes {
|
||||
static final String HUDCaching = "com/gtnewhorizons/angelica/hudcaching/HUDCaching$HUDCachingHooks";
|
||||
private static final boolean DUMP_CLASSES = Boolean.parseBoolean(System.getProperty("angelica.dumpClass", "false"));
|
||||
|
||||
static final Map<String, List<String>> ReturnEarlyMethods = ImmutableMap.of(
|
||||
"thaumcraft.client.lib.RenderEventHandler", ImmutableList.of("renderOverlay"),
|
||||
"com.kentington.thaumichorizons.client.lib.RenderEventHandler", ImmutableList.of("renderOverlay")
|
||||
);
|
||||
|
||||
@Override
|
||||
public byte[] transform(String name, String transformedName, byte[] basicClass) {
|
||||
if (basicClass == null) return null;
|
||||
|
||||
if (ReturnEarlyMethods.containsKey(transformedName)) {
|
||||
ClassReader cr = new ClassReader(basicClass);
|
||||
ClassNode cn = new ClassNode();
|
||||
cr.accept(cn, 0);
|
||||
|
||||
for (String targetMethod : ReturnEarlyMethods.get(transformedName)) {
|
||||
for (MethodNode method : cn.methods) {
|
||||
if (!method.name.equals(targetMethod)) continue;
|
||||
|
||||
InsnList list = new InsnList();
|
||||
LabelNode exitLabel = new LabelNode();
|
||||
AngelicaTweaker.LOGGER.info("Injecting HUDCaching Conditional Return: " + transformedName + "#" + method.name);
|
||||
list.add(new MethodInsnNode(INVOKESTATIC, HUDCaching, "shouldReturnEarly", "()Z", false));
|
||||
list.add(new JumpInsnNode(IFEQ, exitLabel));
|
||||
if (method.desc.endsWith("Z") || method.desc.endsWith("I")) {
|
||||
list.add(new InsnNode(ICONST_0));
|
||||
list.add(new InsnNode(IRETURN));
|
||||
} else if (method.desc.endsWith("V")) {
|
||||
list.add(new InsnNode(RETURN));
|
||||
} else {
|
||||
AngelicaTweaker.LOGGER.warn("HUDCaching Conditional Return - Unknown return type: " + transformedName + "#" + method.name + ":" + method.desc);
|
||||
return basicClass;
|
||||
}
|
||||
list.add(exitLabel);
|
||||
method.instructions.insert(list);
|
||||
}
|
||||
}
|
||||
|
||||
MixinClassWriter cw = new MixinClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
|
||||
cn.accept(cw);
|
||||
final byte[] bytes = cw.toByteArray();
|
||||
saveTransformedClass(bytes, transformedName);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
return basicClass;
|
||||
}
|
||||
|
||||
private File outputDir = null;
|
||||
private void saveTransformedClass(final byte[] data, final String transformedName) {
|
||||
if (!DUMP_CLASSES) {
|
||||
return;
|
||||
}
|
||||
if (outputDir == null) {
|
||||
outputDir = new File(Launch.minecraftHome, "ASM_HUD_CACHING");
|
||||
try {
|
||||
FileUtils.deleteDirectory(outputDir);
|
||||
} catch (IOException ignored) {}
|
||||
if (!outputDir.exists()) {
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
outputDir.mkdirs();
|
||||
}
|
||||
}
|
||||
final String fileName = transformedName.replace('.', File.separatorChar);
|
||||
final File classFile = new File(outputDir, fileName + ".class");
|
||||
final File outDir = classFile.getParentFile();
|
||||
if (!outDir.exists()) {
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
outDir.mkdirs();
|
||||
}
|
||||
if (classFile.exists()) {
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
classFile.delete();
|
||||
}
|
||||
try (final OutputStream output = Files.newOutputStream(classFile.toPath())) {
|
||||
output.write(data);
|
||||
} catch (IOException e) {
|
||||
AngelicaTweaker.LOGGER.error("Could not save transformed class (byte[]) " + transformedName, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,13 +2,10 @@ package com.gtnewhorizons.angelica.transform;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.gtnewhorizon.gtnhlib.asm.ClassConstantPoolParser;
|
||||
import com.gtnewhorizons.angelica.config.AngelicaConfig;
|
||||
import com.gtnewhorizons.angelica.loading.AngelicaTweaker;
|
||||
import net.coderbot.iris.IrisLogging;
|
||||
import net.minecraft.launchwrapper.IClassTransformer;
|
||||
import net.minecraft.launchwrapper.Launch;
|
||||
import net.minecraft.launchwrapper.LaunchClassLoader;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
@@ -23,12 +20,8 @@ import org.objectweb.asm.tree.LdcInsnNode;
|
||||
import org.objectweb.asm.tree.MethodInsnNode;
|
||||
import org.objectweb.asm.tree.MethodNode;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.nio.file.Files;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
@@ -38,17 +31,12 @@ import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.gtnewhorizons.angelica.transform.BlockTransformer.BlockBoundsFields;
|
||||
import static com.gtnewhorizons.angelica.transform.BlockTransformer.BlockClass;
|
||||
import static com.gtnewhorizons.angelica.transform.BlockTransformer.BlockPackage;
|
||||
|
||||
/**
|
||||
* This transformer redirects many GL calls to our custom GLStateManager
|
||||
*/
|
||||
public class RedirectorTransformer implements IClassTransformer {
|
||||
|
||||
private static final boolean ASSERT_MAIN_THREAD = Boolean.parseBoolean(System.getProperty("angelica.assertMainThread", "false"));
|
||||
private static final boolean DUMP_CLASSES = Boolean.parseBoolean(System.getProperty("angelica.dumpClass", "false"));
|
||||
private static final String Drawable = "org/lwjgl/opengl/Drawable";
|
||||
private static final String GLStateManager = "com/gtnewhorizons/angelica/glsm/GLStateManager";
|
||||
private static final String GL11 = "org/lwjgl/opengl/GL11";
|
||||
@@ -57,6 +45,9 @@ public class RedirectorTransformer implements IClassTransformer {
|
||||
private static final String GL20 = "org/lwjgl/opengl/GL20";
|
||||
private static final String Project = "org/lwjgl/util/glu/Project";
|
||||
|
||||
private static final String BlockClass = "net/minecraft/block/Block";
|
||||
private static final String BlockPackage = "net/minecraft/block/Block";
|
||||
|
||||
private static final String OpenGlHelper = "net/minecraft/client/renderer/OpenGlHelper";
|
||||
private static final String EXTBlendFunc = "org/lwjgl/opengl/EXTBlendFuncSeparate";
|
||||
private static final String ARBMultiTexture = "org/lwjgl/opengl/ARBMultitexture";
|
||||
@@ -106,6 +97,7 @@ public class RedirectorTransformer implements IClassTransformer {
|
||||
glCapRedirects.put(org.lwjgl.opengl.GL11.GL_SCISSOR_TEST, "ScissorTest");
|
||||
methodRedirects.put(GL11, RedirectMap.newMap()
|
||||
.add("glAlphaFunc")
|
||||
.add("glBegin")
|
||||
.add("glBindTexture")
|
||||
.add("glBlendFunc")
|
||||
.add("glCallList")
|
||||
@@ -128,6 +120,7 @@ public class RedirectorTransformer implements IClassTransformer {
|
||||
.add("glDepthRange")
|
||||
.add("glDrawArrays")
|
||||
.add("glDrawBuffer")
|
||||
.add("glDrawElements")
|
||||
.add("glEdgeFlag")
|
||||
.add("glEndList")
|
||||
.add("glFog")
|
||||
@@ -233,9 +226,9 @@ public class RedirectorTransformer implements IClassTransformer {
|
||||
}
|
||||
|
||||
private boolean isVanillaBlockSubclass(String className) {
|
||||
if(className.startsWith(BlockTransformer.BlockPackage)) {
|
||||
for(String exclusion : VanillaBlockExclusions) {
|
||||
if(className.startsWith(exclusion)) {
|
||||
if (className.startsWith(BlockPackage)) {
|
||||
for (String exclusion : VanillaBlockExclusions) {
|
||||
if (className.startsWith(exclusion)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -281,7 +274,7 @@ public class RedirectorTransformer implements IClassTransformer {
|
||||
final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
|
||||
cn.accept(cw);
|
||||
final byte[] bytes = cw.toByteArray();
|
||||
saveTransformedClass(bytes, transformedName);
|
||||
AngelicaTweaker.dumpClass(transformedName, basicClass, bytes, this);
|
||||
return bytes;
|
||||
}
|
||||
return basicClass;
|
||||
@@ -309,9 +302,9 @@ public class RedirectorTransformer implements IClassTransformer {
|
||||
} else {
|
||||
// Check if we declare any known field names
|
||||
Set<String> fieldsDeclaredByClass = cn.fields.stream().map(f -> f.name).collect(Collectors.toSet());
|
||||
doWeShadow = BlockBoundsFields.stream().anyMatch(pair -> fieldsDeclaredByClass.contains(pair.getLeft()) || fieldsDeclaredByClass.contains(pair.getRight()));
|
||||
doWeShadow = BlockTransformer.BlockBoundsFields.stream().anyMatch(pair -> fieldsDeclaredByClass.contains(pair.getLeft()) || fieldsDeclaredByClass.contains(pair.getRight()));
|
||||
}
|
||||
if(doWeShadow) {
|
||||
if (doWeShadow) {
|
||||
AngelicaTweaker.LOGGER.info("Class '{}' shadows one or more block bounds fields, these accesses won't be redirected!", cn.name);
|
||||
blockOwnerExclusions.add(cn.name);
|
||||
}
|
||||
@@ -383,13 +376,13 @@ public class RedirectorTransformer implements IClassTransformer {
|
||||
else if ((node.getOpcode() == Opcodes.GETFIELD || node.getOpcode() == Opcodes.PUTFIELD) && node instanceof FieldInsnNode fNode) {
|
||||
if(!blockOwnerExclusions.contains(fNode.owner) && isBlockSubclass(fNode.owner) && isSodiumEnabled()) {
|
||||
Pair<String, String> fieldToRedirect = null;
|
||||
for(Pair<String, String> blockPairs : BlockBoundsFields) {
|
||||
for(Pair<String, String> blockPairs : BlockTransformer.BlockBoundsFields) {
|
||||
if(fNode.name.equals(blockPairs.getLeft()) || fNode.name.equals(blockPairs.getRight())) {
|
||||
fieldToRedirect = blockPairs;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(fieldToRedirect != null) {
|
||||
if (fieldToRedirect != null) {
|
||||
if (IrisLogging.ENABLE_SPAM) {
|
||||
AngelicaTweaker.LOGGER.info("Redirecting Block.{} in {} to thread-safe wrapper", fNode.name, transformedName);
|
||||
}
|
||||
@@ -398,9 +391,9 @@ public class RedirectorTransformer implements IClassTransformer {
|
||||
fNode.owner = ThreadedBlockData;
|
||||
// Inject getter before the field access, to turn Block -> ThreadedBlockData
|
||||
final MethodInsnNode getter = new MethodInsnNode(Opcodes.INVOKESTATIC, ThreadedBlockData, "get", "(L" + BlockClass + ";)L" + ThreadedBlockData + ";", false);
|
||||
if(node.getOpcode() == Opcodes.GETFIELD) {
|
||||
if (node.getOpcode() == Opcodes.GETFIELD) {
|
||||
mn.instructions.insertBefore(fNode, getter);
|
||||
} else if(node.getOpcode() == Opcodes.PUTFIELD) {
|
||||
} else if (node.getOpcode() == Opcodes.PUTFIELD) {
|
||||
// FIXME: this code assumes doubles
|
||||
// Stack: Block, double
|
||||
final InsnList beforePut = new InsnList();
|
||||
@@ -418,7 +411,6 @@ public class RedirectorTransformer implements IClassTransformer {
|
||||
}
|
||||
changed = true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -430,40 +422,6 @@ public class RedirectorTransformer implements IClassTransformer {
|
||||
return changed;
|
||||
}
|
||||
|
||||
private File outputDir = null;
|
||||
|
||||
private void saveTransformedClass(final byte[] data, final String transformedName) {
|
||||
if (!DUMP_CLASSES) {
|
||||
return;
|
||||
}
|
||||
if (outputDir == null) {
|
||||
outputDir = new File(Launch.minecraftHome, "ASM_REDIRECTOR");
|
||||
try {
|
||||
FileUtils.deleteDirectory(outputDir);
|
||||
} catch (IOException ignored) {}
|
||||
if (!outputDir.exists()) {
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
outputDir.mkdirs();
|
||||
}
|
||||
}
|
||||
final String fileName = transformedName.replace('.', File.separatorChar);
|
||||
final File classFile = new File(outputDir, fileName + ".class");
|
||||
final File outDir = classFile.getParentFile();
|
||||
if (!outDir.exists()) {
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
outDir.mkdirs();
|
||||
}
|
||||
if (classFile.exists()) {
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
classFile.delete();
|
||||
}
|
||||
try (final OutputStream output = Files.newOutputStream(classFile.toPath())) {
|
||||
output.write(data);
|
||||
} catch (IOException e) {
|
||||
AngelicaTweaker.LOGGER.error("Could not save transformed class (byte[]) " + transformedName, e);
|
||||
}
|
||||
}
|
||||
|
||||
private static class RedirectMap<K> extends HashMap<K, K> {
|
||||
public static RedirectMap<String> newMap() {
|
||||
return new RedirectMap<>();
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
package com.gtnewhorizons.angelica.transform.compat;
|
||||
|
||||
import com.gtnewhorizons.angelica.config.AngelicaConfig;
|
||||
import com.gtnewhorizons.angelica.loading.AngelicaTweaker;
|
||||
import cpw.mods.fml.relauncher.FMLLaunchHandler;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public enum CompatASMTransformers {
|
||||
|
||||
EXTRA_UTILITIES_ISBRH("RenderBlockColor Transformer", () -> AngelicaConfig.fixExtraUtilsSodiumCompat, Side.CLIENT,
|
||||
"com.gtnewhorizons.angelica.transform.compat.ExtraUtilsTransformer"
|
||||
),
|
||||
HUD_CACHING("HUDCaching Early Return Transformer", () -> AngelicaConfig.enableHudCaching && AngelicaConfig.enableHudCachingEventTransformer, Side.CLIENT,
|
||||
"com.gtnewhorizons.angelica.transform.HUDCachingTransformer")
|
||||
;
|
||||
|
||||
private final Supplier<Boolean> applyIf;
|
||||
private final Side side;
|
||||
private final String[] transformerClasses;
|
||||
|
||||
CompatASMTransformers(String description, Supplier<Boolean> applyIf, Side side, String... transformers) {
|
||||
this.applyIf = applyIf;
|
||||
this.side = side;
|
||||
this.transformerClasses = transformers;
|
||||
}
|
||||
|
||||
private boolean shouldBeLoaded() { return applyIf.get() && shouldLoadSide(); }
|
||||
|
||||
private boolean shouldLoadSide() {
|
||||
return side == Side.BOTH || (side == Side.SERVER && FMLLaunchHandler.side()
|
||||
.isServer())
|
||||
|| (side == Side.CLIENT && FMLLaunchHandler.side()
|
||||
.isClient());
|
||||
}
|
||||
|
||||
public static List<String> getTransformers() {
|
||||
final List<String> list = new ArrayList<>();
|
||||
for (CompatASMTransformers transformer : values()) {
|
||||
if (transformer.shouldBeLoaded()) {
|
||||
AngelicaTweaker.LOGGER.info("Loading transformer {}", (Object[]) transformer.transformerClasses);
|
||||
list.addAll(Arrays.asList(transformer.transformerClasses));
|
||||
} else {
|
||||
AngelicaTweaker.LOGGER.info("Not loading transformer {}", (Object[]) transformer.transformerClasses);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private enum Side {
|
||||
BOTH,
|
||||
CLIENT,
|
||||
SERVER
|
||||
}
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
package com.gtnewhorizons.angelica.transform.compat;
|
||||
|
||||
import com.gtnewhorizons.angelica.loading.AngelicaTweaker;
|
||||
import net.minecraft.launchwrapper.IClassTransformer;
|
||||
import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.tree.AnnotationNode;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class ExtraUtilsTransformer implements IClassTransformer {
|
||||
|
||||
private static final String RenderBlockColor = "com.rwtema.extrautils.block.render.RenderBlockColor";
|
||||
private static final String RenderBlockConnectedTextures = "com.rwtema.extrautils.block.render.RenderBlockConnectedTextures";
|
||||
private static final String RenderBlockConnectedTexturesEthereal = "com.rwtema.extrautils.block.render.RenderBlockConnectedTexturesEthereal";
|
||||
private static final String RenderBlockFullBright = "com.rwtema.extrautils.block.render.RenderBlockFullBright";
|
||||
private static final String RenderBlockSpike = "com.rwtema.extrautils.block.render.RenderBlockSpike";
|
||||
|
||||
private static final List<String> transformedClasses = Arrays.asList(RenderBlockColor, RenderBlockConnectedTextures, RenderBlockConnectedTexturesEthereal, RenderBlockFullBright, RenderBlockSpike);
|
||||
|
||||
private static final Map<String, Boolean> perThreadMap = new HashMap<>();
|
||||
|
||||
static {
|
||||
perThreadMap.put(RenderBlockColor, false);
|
||||
perThreadMap.put(RenderBlockConnectedTextures, true);
|
||||
perThreadMap.put(RenderBlockConnectedTexturesEthereal, true);
|
||||
perThreadMap.put(RenderBlockFullBright, false);
|
||||
perThreadMap.put(RenderBlockSpike, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] transform(final String className, String transformedName, byte[] basicClass) {
|
||||
if (basicClass == null) return null;
|
||||
|
||||
if (!transformedClasses.contains(transformedName)) {
|
||||
return basicClass;
|
||||
}
|
||||
|
||||
AngelicaTweaker.LOGGER.info("Adding ThreadSafeISBRH for Extra Utilities to: {}", transformedName);
|
||||
|
||||
final ClassReader cr = new ClassReader(basicClass);
|
||||
final ClassNode cn = new ClassNode();
|
||||
cr.accept(cn, 0);
|
||||
|
||||
addThreadSafeISBRHAnnotation(transformedName, cn);
|
||||
|
||||
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
|
||||
cn.accept(cw);
|
||||
return cw.toByteArray();
|
||||
}
|
||||
|
||||
public void addThreadSafeISBRHAnnotation(String transformedName, ClassNode cn) {
|
||||
|
||||
AnnotationNode isbrhAnnotation = new AnnotationNode("Lcom/gtnewhorizons/angelica/api/ThreadSafeISBRH;");
|
||||
|
||||
Boolean perThread = perThreadMap.get(transformedName);
|
||||
if (perThread == null) {
|
||||
perThread = false;
|
||||
AngelicaTweaker.LOGGER.info("Tried to add ThreadSafeISBRH annotation to {} which is missing from perThreadMap. Using false for perThread.", transformedName);
|
||||
}
|
||||
isbrhAnnotation.values = Arrays.asList("perThread", perThread);
|
||||
|
||||
if (cn.visibleAnnotations == null) {
|
||||
cn.visibleAnnotations = new ArrayList<>();
|
||||
}
|
||||
cn.visibleAnnotations.add(isbrhAnnotation);
|
||||
}
|
||||
}
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
package com.gtnewhorizons.angelica.transform.compat;
|
||||
|
||||
import com.gtnewhorizons.angelica.loading.AngelicaTweaker;
|
||||
import com.gtnewhorizons.angelica.transform.compat.handlers.CompatHandler;
|
||||
import com.gtnewhorizons.angelica.transform.compat.transformers.generic.FieldLevelTessellatorTransformer;
|
||||
import com.gtnewhorizons.angelica.transform.compat.transformers.generic.HUDCachingEarlyReturnTransformer;
|
||||
import com.gtnewhorizons.angelica.transform.compat.transformers.generic.ThreadSafeISBRHAnnotationTransformer;
|
||||
import com.gtnewhorizons.angelica.transform.compat.transformers.generic.TileEntityNullGuardTransformer;
|
||||
import it.unimi.dsi.fastutil.objects.Object2BooleanOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
|
||||
import net.minecraft.launchwrapper.IClassTransformer;
|
||||
import org.spongepowered.asm.lib.ClassReader;
|
||||
import org.spongepowered.asm.lib.tree.ClassNode;
|
||||
import org.spongepowered.asm.transformers.MixinClassWriter;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class GenericCompatTransformer implements IClassTransformer {
|
||||
|
||||
private static final Map<String, List<String>> fieldLevelTessellator = new Object2ObjectOpenHashMap<>();
|
||||
private static final Map<String, List<String>> tileEntityNullGuard = new Object2ObjectOpenHashMap<>();
|
||||
private static final Map<String, Boolean> threadSafeIBSRH = new Object2BooleanOpenHashMap<>();
|
||||
private static final Map<String, List<String>> hudCachingEarlyReturn = new Object2ObjectOpenHashMap<>();
|
||||
|
||||
private static final Set<String> transformedClasses = new ObjectOpenHashSet<>();
|
||||
|
||||
@Override
|
||||
public byte[] transform(String name, String transformedName, byte[] basicClass) {
|
||||
if (basicClass == null) return null;
|
||||
|
||||
if (!transformedClasses.contains(transformedName)) return basicClass;
|
||||
|
||||
ClassReader cr = new ClassReader(basicClass);
|
||||
ClassNode cn = new ClassNode();
|
||||
cr.accept(cn, 0);
|
||||
|
||||
if (fieldLevelTessellator.containsKey(transformedName)) {
|
||||
FieldLevelTessellatorTransformer.transform(cn, fieldLevelTessellator.get(transformedName));
|
||||
}
|
||||
|
||||
if (tileEntityNullGuard.containsKey(transformedName)) {
|
||||
TileEntityNullGuardTransformer.transform(cn, tileEntityNullGuard.get(transformedName));
|
||||
}
|
||||
|
||||
if (threadSafeIBSRH.containsKey(transformedName)) {
|
||||
ThreadSafeISBRHAnnotationTransformer.transform(cn, threadSafeIBSRH.get(transformedName));
|
||||
}
|
||||
|
||||
if (hudCachingEarlyReturn.containsKey(transformedName)) {
|
||||
HUDCachingEarlyReturnTransformer.transform(cn, hudCachingEarlyReturn.get(transformedName));
|
||||
}
|
||||
|
||||
MixinClassWriter cw = new MixinClassWriter(MixinClassWriter.COMPUTE_MAXS | MixinClassWriter.COMPUTE_FRAMES);
|
||||
cn.accept(cw);
|
||||
final byte[] bytes = cw.toByteArray();
|
||||
AngelicaTweaker.dumpClass(transformedName, basicClass, bytes, this);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
public static void register(CompatHandler handler) {
|
||||
if (handler.getFieldLevelTessellator() != null)
|
||||
fieldLevelTessellator.putAll(handler.getFieldLevelTessellator());
|
||||
if (handler.getTileEntityNullGuard() != null)
|
||||
tileEntityNullGuard.putAll(handler.getTileEntityNullGuard());
|
||||
if (handler.getThreadSafeISBRHAnnotations() != null)
|
||||
threadSafeIBSRH.putAll(handler.getThreadSafeISBRHAnnotations());
|
||||
if (handler.getHUDCachingEarlyReturn() != null)
|
||||
hudCachingEarlyReturn.putAll(handler.getHUDCachingEarlyReturn());
|
||||
}
|
||||
|
||||
public static void build() {
|
||||
transformedClasses.addAll(fieldLevelTessellator.keySet());
|
||||
transformedClasses.addAll(tileEntityNullGuard.keySet());
|
||||
transformedClasses.addAll(threadSafeIBSRH.keySet());
|
||||
transformedClasses.addAll(hudCachingEarlyReturn.keySet());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.gtnewhorizons.angelica.transform.compat.handlers;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public interface CompatHandler {
|
||||
|
||||
default Map<String, List<String>> getFieldLevelTessellator() {
|
||||
return null;
|
||||
}
|
||||
|
||||
default Map<String, List<String>> getTileEntityNullGuard() {
|
||||
return null;
|
||||
}
|
||||
|
||||
default Map<String, Boolean> getThreadSafeISBRHAnnotations() {
|
||||
return null;
|
||||
}
|
||||
|
||||
default Map<String, List<String>> getHUDCachingEarlyReturn() {
|
||||
return null;
|
||||
}
|
||||
|
||||
default List<String> extraTransformers() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
package com.gtnewhorizons.angelica.transform.compat.handlers;
|
||||
|
||||
import com.gtnewhorizons.angelica.config.CompatConfig;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public enum CompatHandlers {
|
||||
|
||||
STACKS_ON_STACKS(() -> CompatConfig.fixStacksOnStacks, new StacksOnStacksCompatHandler()),
|
||||
EXTRA_UTILS(() -> CompatConfig.fixExtraUtils, new ExtraUtilsCompatHandler()),
|
||||
IMMERSIVE_ENGINEERING(() -> CompatConfig.fixImmersiveEngineering, new ImmersiveEngineeringCompatHandler()),
|
||||
THAUMCRAFT(() -> CompatConfig.fixThaumcraft, new ThaumcraftCompatHandler()),
|
||||
THAUMIC_HORIZONS(() -> CompatConfig.fixThaumicHorizons, new ThaumicHorizonsCompatHandler());
|
||||
|
||||
private final Supplier<Boolean> applyIf;
|
||||
private final CompatHandler handler;
|
||||
|
||||
CompatHandlers(Supplier<Boolean> applyIf, CompatHandler handler) {
|
||||
this.applyIf = applyIf;
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
private static List<CompatHandler> compatHandlers = null;
|
||||
|
||||
public static List<CompatHandler> getHandlers() {
|
||||
if (compatHandlers != null) {
|
||||
return compatHandlers;
|
||||
}
|
||||
compatHandlers = new ArrayList<>();
|
||||
for (CompatHandlers value : values()) {
|
||||
if (value.applyIf.get()) {
|
||||
compatHandlers.add(value.handler);
|
||||
}
|
||||
}
|
||||
return compatHandlers;
|
||||
}
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
package com.gtnewhorizons.angelica.transform.compat.handlers;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class ExtraUtilsCompatHandler implements CompatHandler {
|
||||
|
||||
@Override
|
||||
public Map<String, Boolean> getThreadSafeISBRHAnnotations() {
|
||||
return ImmutableMap.of(
|
||||
"com.rwtema.extrautils.block.render.RenderBlockColor",
|
||||
false,
|
||||
"com.rwtema.extrautils.block.render.RenderBlockConnectedTextures",
|
||||
true,
|
||||
"com.rwtema.extrautils.block.render.RenderBlockConnectedTexturesEthereal",
|
||||
true,
|
||||
"com.rwtema.extrautils.block.render.RenderBlockFullBright",
|
||||
false,
|
||||
"com.rwtema.extrautils.block.render.RenderBlockSpike",
|
||||
false);
|
||||
}
|
||||
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
package com.gtnewhorizons.angelica.transform.compat.handlers;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.gtnewhorizons.angelica.transform.compat.transformers.specific.ImmersiveEngineeringTransformer;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class ImmersiveEngineeringCompatHandler implements CompatHandler {
|
||||
|
||||
@Override
|
||||
public Map<String, List<String>> getTileEntityNullGuard() {
|
||||
final List<String> renderWorldBlockExclusive = ImmutableList.of("renderWorldBlock");
|
||||
return ImmutableMap.<String, List<String>>builder()
|
||||
.put("blusunrize.immersiveengineering.client.render.BlockRenderClothDevices", renderWorldBlockExclusive)
|
||||
.put("blusunrize.immersiveengineering.client.render.BlockRenderMetalDecoration", renderWorldBlockExclusive)
|
||||
.put("blusunrize.immersiveengineering.client.render.BlockRenderMetalDevices", renderWorldBlockExclusive)
|
||||
.put("blusunrize.immersiveengineering.client.render.BlockRenderMetalDevices2", renderWorldBlockExclusive)
|
||||
.put("blusunrize.immersiveengineering.client.render.BlockRenderWoodenDecoration", renderWorldBlockExclusive)
|
||||
.put("blusunrize.immersiveengineering.client.render.BlockRenderWoodenDevices", renderWorldBlockExclusive)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Boolean> getThreadSafeISBRHAnnotations() {
|
||||
return ImmutableMap.<String, Boolean>builder()
|
||||
.put("blusunrize.immersiveengineering.client.render.BlockRenderClothDevices", false)
|
||||
.put("blusunrize.immersiveengineering.client.render.BlockRenderMetalDecoration", false)
|
||||
.put("blusunrize.immersiveengineering.client.render.BlockRenderMetalDevices", false)
|
||||
.put("blusunrize.immersiveengineering.client.render.BlockRenderMetalDevices2", false)
|
||||
.put("blusunrize.immersiveengineering.client.render.BlockRenderMetalMultiblocks", false)
|
||||
.put("blusunrize.immersiveengineering.client.render.BlockRenderStoneDevices", false)
|
||||
.put("blusunrize.immersiveengineering.client.render.BlockRenderWoodenDecoration", false)
|
||||
.put("blusunrize.immersiveengineering.client.render.BlockRenderWoodenDevices", false)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> extraTransformers() {
|
||||
return ImmutableList.of(ImmersiveEngineeringTransformer.class.getName());
|
||||
}
|
||||
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
package com.gtnewhorizons.angelica.transform.compat.handlers;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.gtnewhorizons.angelica.transform.compat.transformers.specific.StacksOnStacksTransformer;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class StacksOnStacksCompatHandler implements CompatHandler {
|
||||
|
||||
@Override
|
||||
public Map<String, List<String>> getFieldLevelTessellator() {
|
||||
return ImmutableMap
|
||||
.of("com.tierzero.stacksonstacks.util.ClientUtils", ImmutableList.of("drawQuad", "drawRectangularPrism"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, List<String>> getTileEntityNullGuard() {
|
||||
return ImmutableMap
|
||||
.of("com.tierzero.stacksonstacks.client.render.RenderTilePile", ImmutableList.of("renderWorldBlock"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Boolean> getThreadSafeISBRHAnnotations() {
|
||||
return ImmutableMap.of("com.tierzero.stacksonstacks.client.render.RenderTilePile", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> extraTransformers() {
|
||||
return ImmutableList.of(StacksOnStacksTransformer.class.getName());
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
package com.gtnewhorizons.angelica.transform.compat.handlers;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class ThaumcraftCompatHandler implements CompatHandler {
|
||||
|
||||
@Override
|
||||
public Map<String, List<String>> getHUDCachingEarlyReturn() {
|
||||
return ImmutableMap.of("thaumcraft.client.lib.RenderEventHandler", ImmutableList.of("renderOverlay"));
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
package com.gtnewhorizons.angelica.transform.compat.handlers;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class ThaumicHorizonsCompatHandler implements CompatHandler {
|
||||
|
||||
@Override
|
||||
public Map<String, List<String>> getHUDCachingEarlyReturn() {
|
||||
return ImmutableMap
|
||||
.of("com.kentington.thaumichorizons.client.lib.RenderEventHandler", ImmutableList.of("renderOverlay"));
|
||||
}
|
||||
}
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
package com.gtnewhorizons.angelica.transform.compat.transformers.generic;
|
||||
|
||||
import com.gtnewhorizons.angelica.transform.AsmUtil;
|
||||
import org.spongepowered.asm.lib.Opcodes;
|
||||
import org.spongepowered.asm.lib.tree.AbstractInsnNode;
|
||||
import org.spongepowered.asm.lib.tree.ClassNode;
|
||||
import org.spongepowered.asm.lib.tree.FieldInsnNode;
|
||||
import org.spongepowered.asm.lib.tree.InsnList;
|
||||
import org.spongepowered.asm.lib.tree.LabelNode;
|
||||
import org.spongepowered.asm.lib.tree.LocalVariableNode;
|
||||
import org.spongepowered.asm.lib.tree.MethodNode;
|
||||
import org.spongepowered.asm.lib.tree.VarInsnNode;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class FieldLevelTessellatorTransformer {
|
||||
|
||||
public static void transform(ClassNode cn, List<String> patchMethods) {
|
||||
for (MethodNode method : cn.methods) {
|
||||
if (patchMethods.contains(method.name)) {
|
||||
injectLocalTessellatorAndReplaceFieldUsage(method);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void injectLocalTessellatorAndReplaceFieldUsage(MethodNode mn) {
|
||||
// This part searches the instructions to see if there is any usage of a Tessellator field
|
||||
// which is NOT owned by Minecraft itself. This means anyone that caches it into a field will get caught
|
||||
// but not direct usage of Tessellator.instance.whatever()
|
||||
List<String> fields = new ArrayList<>();
|
||||
for (int i = 0; i < mn.instructions.size(); i++) {
|
||||
AbstractInsnNode in = mn.instructions.get(i);
|
||||
if (in instanceof FieldInsnNode fin) {
|
||||
if ((fin.getOpcode() == Opcodes.GETSTATIC || fin.getOpcode() == Opcodes.GETFIELD)
|
||||
&& fin.desc.equals("Lnet/minecraft/client/renderer/Tessellator;")
|
||||
&& !fin.owner.equals("net/minecraft/client/renderer/Tessellator")) {
|
||||
fields.add(fin.owner + ";" + fin.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fields.isEmpty()) return;
|
||||
|
||||
// Injects a new local to store our new local Tessellator in
|
||||
int localIndex = mn.maxLocals;
|
||||
LabelNode startLabel = new LabelNode();
|
||||
LabelNode endLabel = new LabelNode();
|
||||
LocalVariableNode tesNode = new LocalVariableNode(
|
||||
"tes",
|
||||
"Lnet/minecraft/client/renderer/Tessellator;",
|
||||
null,
|
||||
startLabel,
|
||||
endLabel,
|
||||
localIndex);
|
||||
mn.localVariables.add(tesNode);
|
||||
|
||||
// Actually initialize the new local Tessellator
|
||||
InsnList list = new InsnList();
|
||||
list.add(startLabel);
|
||||
list.add(
|
||||
new FieldInsnNode(
|
||||
Opcodes.GETSTATIC,
|
||||
"net/minecraft/client/renderer/Tessellator",
|
||||
AsmUtil.obf("instance", "field_78398_a"),
|
||||
"Lnet/minecraft/client/renderer/Tessellator;"));
|
||||
list.add(new VarInsnNode(Opcodes.ASTORE, localIndex));
|
||||
mn.instructions.insert(list);
|
||||
|
||||
// This searches through all the instructions and finds usage of the previously discovered fields, then it
|
||||
// replaces them
|
||||
// with an ALOAD for our new local instead of the GETSTATIC/GETFIELD
|
||||
for (int i = 0; i < mn.instructions.size(); i++) {
|
||||
AbstractInsnNode in = mn.instructions.get(i);
|
||||
if (in instanceof FieldInsnNode fin) {
|
||||
String hash = fin.owner + ";" + fin.name;
|
||||
if ((fin.getOpcode() == Opcodes.GETSTATIC || fin.getOpcode() == Opcodes.GETFIELD)
|
||||
&& fin.desc.equals("Lnet/minecraft/client/renderer/Tessellator;")
|
||||
&& fields.contains(hash)) {
|
||||
mn.instructions.insertBefore(in, new VarInsnNode(Opcodes.ALOAD, localIndex));
|
||||
mn.instructions.remove(in);
|
||||
}
|
||||
}
|
||||
}
|
||||
mn.instructions.add(endLabel);
|
||||
}
|
||||
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
package com.gtnewhorizons.angelica.transform.compat.transformers.generic;
|
||||
|
||||
import com.gtnewhorizons.angelica.loading.AngelicaTweaker;
|
||||
import org.spongepowered.asm.lib.Opcodes;
|
||||
import org.spongepowered.asm.lib.tree.ClassNode;
|
||||
import org.spongepowered.asm.lib.tree.InsnList;
|
||||
import org.spongepowered.asm.lib.tree.InsnNode;
|
||||
import org.spongepowered.asm.lib.tree.JumpInsnNode;
|
||||
import org.spongepowered.asm.lib.tree.LabelNode;
|
||||
import org.spongepowered.asm.lib.tree.MethodInsnNode;
|
||||
import org.spongepowered.asm.lib.tree.MethodNode;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class HUDCachingEarlyReturnTransformer {
|
||||
|
||||
private static final String HUDCaching = "com/gtnewhorizons/angelica/hudcaching/HUDCaching$HUDCachingHooks";
|
||||
|
||||
public static void transform(ClassNode cn, List<String> patchMethods) {
|
||||
for (MethodNode method : cn.methods) {
|
||||
if (patchMethods.contains(method.name)) {
|
||||
InsnList list = new InsnList();
|
||||
LabelNode exitLabel = new LabelNode();
|
||||
list.add(new MethodInsnNode(Opcodes.INVOKESTATIC, HUDCaching, "shouldReturnEarly", "()Z", false));
|
||||
list.add(new JumpInsnNode(Opcodes.IFEQ, exitLabel));
|
||||
if (method.desc.endsWith("Z") || method.desc.endsWith("I")) {
|
||||
list.add(new InsnNode(Opcodes.ICONST_0));
|
||||
list.add(new InsnNode(Opcodes.IRETURN));
|
||||
} else if (method.desc.endsWith("V")) {
|
||||
list.add(new InsnNode(Opcodes.RETURN));
|
||||
} else {
|
||||
AngelicaTweaker.LOGGER.warn(
|
||||
"HUDCaching Conditional Return - Unknown return type: {}#{}:{}", cn.name, method.name, method.desc
|
||||
);
|
||||
return;
|
||||
}
|
||||
list.add(exitLabel);
|
||||
method.instructions.insert(list);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package com.gtnewhorizons.angelica.transform.compat.transformers.generic;
|
||||
|
||||
import org.spongepowered.asm.lib.tree.AnnotationNode;
|
||||
import org.spongepowered.asm.lib.tree.ClassNode;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class ThreadSafeISBRHAnnotationTransformer {
|
||||
|
||||
public static void transform(ClassNode cn, boolean perThread) {
|
||||
if (cn.visibleAnnotations == null) {
|
||||
cn.visibleAnnotations = new ArrayList<>();
|
||||
}
|
||||
|
||||
AnnotationNode isbrhAnnotation = new AnnotationNode("Lcom/gtnewhorizons/angelica/api/ThreadSafeISBRH;");
|
||||
isbrhAnnotation.values = Arrays.asList("perThread", perThread);
|
||||
cn.visibleAnnotations.add(isbrhAnnotation);
|
||||
}
|
||||
}
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
package com.gtnewhorizons.angelica.transform.compat.transformers.generic;
|
||||
|
||||
import com.gtnewhorizons.angelica.loading.AngelicaTweaker;
|
||||
import com.gtnewhorizons.angelica.transform.AsmUtil;
|
||||
import org.spongepowered.asm.lib.Opcodes;
|
||||
import org.spongepowered.asm.lib.tree.AbstractInsnNode;
|
||||
import org.spongepowered.asm.lib.tree.ClassNode;
|
||||
import org.spongepowered.asm.lib.tree.InsnList;
|
||||
import org.spongepowered.asm.lib.tree.InsnNode;
|
||||
import org.spongepowered.asm.lib.tree.JumpInsnNode;
|
||||
import org.spongepowered.asm.lib.tree.LabelNode;
|
||||
import org.spongepowered.asm.lib.tree.MethodInsnNode;
|
||||
import org.spongepowered.asm.lib.tree.MethodNode;
|
||||
import org.spongepowered.asm.lib.tree.TypeInsnNode;
|
||||
import org.spongepowered.asm.lib.tree.VarInsnNode;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class TileEntityNullGuardTransformer {
|
||||
|
||||
public static void transform(ClassNode cn, List<String> patchMethods) {
|
||||
for (MethodNode method : cn.methods) {
|
||||
if (patchMethods.contains(method.name)) {
|
||||
injectGetTileEntityNullGuard(method);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void injectGetTileEntityNullGuard(MethodNode mn) {
|
||||
/*
|
||||
* Searching for the following pattern:
|
||||
* L0 {
|
||||
* ...
|
||||
* INVOKEINTERFACE net/minecraft/world/IBlockAccess.getTileEntity(III)Lnet/minecraft/tileentity/TileEntity;
|
||||
* CHECKCAST *
|
||||
* ASTORE x
|
||||
* }
|
||||
* L1 {...
|
||||
* Then injecting the following after the ASTORE such that we get
|
||||
* L0 {
|
||||
* ASTORE x
|
||||
* ALOAD x
|
||||
* IFNONNULL L1
|
||||
* ICONST_0
|
||||
* IRETURN
|
||||
* }
|
||||
* L1 {...
|
||||
* Ultimately this converts:
|
||||
* MyTileEntity tile = (MyTileEntity) world.getTileEntity(x, y, z);
|
||||
* doSomethingWithTileEntity(tile);
|
||||
* into:
|
||||
* MyTileEntity tile = (MyTileEntity) world.getTileEntity(x, y, z);
|
||||
* if (tile == null) {
|
||||
* return false;
|
||||
* } else {
|
||||
* doSomethingWithTileEntity(tile);
|
||||
* }
|
||||
*/
|
||||
for (int i = 0; i < mn.instructions.size(); i++) {
|
||||
AbstractInsnNode in = mn.instructions.get(i);
|
||||
if (in instanceof MethodInsnNode min) {
|
||||
if (min.getOpcode() == Opcodes.INVOKEINTERFACE
|
||||
&& min.name.equals(AsmUtil.obf("getTileEntity", "func_147438_o"))
|
||||
&& min.owner.equals("net/minecraft/world/IBlockAccess")) {
|
||||
AbstractInsnNode castNodeAbstract = min.getNext();
|
||||
if (castNodeAbstract instanceof TypeInsnNode castNodeType) {
|
||||
if (castNodeType.getOpcode() == Opcodes.CHECKCAST) {
|
||||
AbstractInsnNode astoreNodeAbstract = castNodeType.getNext();
|
||||
if (astoreNodeAbstract instanceof VarInsnNode astoreNodeVar) {
|
||||
if (astoreNodeVar.getOpcode() == Opcodes.ASTORE) {
|
||||
InsnList list = new InsnList();
|
||||
LabelNode exit = new LabelNode();
|
||||
list.add(new VarInsnNode(Opcodes.ALOAD, astoreNodeVar.var));
|
||||
list.add(new JumpInsnNode(Opcodes.IFNONNULL, exit));
|
||||
if (mn.desc.endsWith("Z") || mn.desc.endsWith("I")) {
|
||||
list.add(new InsnNode(Opcodes.ICONST_0));
|
||||
list.add(new InsnNode(Opcodes.IRETURN));
|
||||
} else if (mn.desc.endsWith("V")) {
|
||||
list.add(new InsnNode(Opcodes.RETURN));
|
||||
} else {
|
||||
AngelicaTweaker.LOGGER.warn("TileEntityNullGuard - Unknown Return Type: {}:{}", mn.name, mn.desc);
|
||||
return;
|
||||
}
|
||||
list.add(exit);
|
||||
mn.instructions.insert(astoreNodeVar, list);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
package com.gtnewhorizons.angelica.transform.compat.transformers.specific;
|
||||
|
||||
import com.gtnewhorizons.angelica.loading.AngelicaTweaker;
|
||||
import net.minecraft.launchwrapper.IClassTransformer;
|
||||
import org.spongepowered.asm.lib.ClassReader;
|
||||
import org.spongepowered.asm.lib.Opcodes;
|
||||
import org.spongepowered.asm.lib.tree.AbstractInsnNode;
|
||||
import org.spongepowered.asm.lib.tree.ClassNode;
|
||||
import org.spongepowered.asm.lib.tree.FieldInsnNode;
|
||||
import org.spongepowered.asm.lib.tree.InsnNode;
|
||||
import org.spongepowered.asm.lib.tree.JumpInsnNode;
|
||||
import org.spongepowered.asm.lib.tree.MethodInsnNode;
|
||||
import org.spongepowered.asm.lib.tree.MethodNode;
|
||||
import org.spongepowered.asm.transformers.MixinClassWriter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ImmersiveEngineeringTransformer implements IClassTransformer {
|
||||
|
||||
private static final String BlockRenderClothDevices = "blusunrize.immersiveengineering.client.render.BlockRenderClothDevices";
|
||||
private static final String BlockRenderMetalDevices2 = "blusunrize.immersiveengineering.client.render.BlockRenderMetalDevices2";
|
||||
private static final String BlockRenderStoneDevices = "blusunrize.immersiveengineering.client.render.BlockRenderStoneDevices";
|
||||
private static final String ClientUtils = "blusunrize.immersiveengineering.client.ClientUtils";
|
||||
|
||||
private static final List<String> transformedClasses = new ArrayList<>();
|
||||
|
||||
private static final List<String> staticRenderPassPatches = new ArrayList<>();
|
||||
|
||||
static {
|
||||
transformedClasses.add(BlockRenderClothDevices);
|
||||
transformedClasses.add(BlockRenderMetalDevices2);
|
||||
transformedClasses.add(BlockRenderStoneDevices);
|
||||
transformedClasses.add(ClientUtils);
|
||||
|
||||
staticRenderPassPatches.add(BlockRenderClothDevices);
|
||||
staticRenderPassPatches.add(BlockRenderMetalDevices2);
|
||||
staticRenderPassPatches.add(BlockRenderStoneDevices);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] transform(String name, String transformedName, byte[] basicClass) {
|
||||
if (basicClass == null) return null;
|
||||
|
||||
if (!transformedClasses.contains(transformedName)) return basicClass;
|
||||
|
||||
final ClassReader cr = new ClassReader(basicClass);
|
||||
final ClassNode cn = new ClassNode();
|
||||
cr.accept(cn, 0);
|
||||
|
||||
if (transformedName.equals(ClientUtils)) {
|
||||
transformClientUtils(cn);
|
||||
}
|
||||
|
||||
if (staticRenderPassPatches.contains(transformedName)) {
|
||||
staticRenderPassPatcher(cn);
|
||||
}
|
||||
|
||||
MixinClassWriter cw = new MixinClassWriter(MixinClassWriter.COMPUTE_FRAMES);
|
||||
cn.accept(cw);
|
||||
final byte[] bytes = cw.toByteArray();
|
||||
AngelicaTweaker.LOGGER.info("[AngelicaCompat]Extra Transformers: Applied ImmersiveEngineeringTransformer");
|
||||
AngelicaTweaker.dumpClass(transformedName, basicClass, bytes, this);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
private void staticRenderPassPatcher(ClassNode cn) {
|
||||
for (MethodNode mn : cn.methods) {
|
||||
if (mn.name.equals("renderWorldBlock")) {
|
||||
for (int i = 0; i < mn.instructions.size(); i++) {
|
||||
AbstractInsnNode ain = mn.instructions.get(i);
|
||||
// So far every one of these has been named renderPass, eventually might need to make the name dynamic and possibly care about owner?
|
||||
// Maybe this is common in other mods, possibly could generalize this transformation further if it comes up more.
|
||||
if (ain instanceof FieldInsnNode fin && fin.getOpcode() == Opcodes.GETSTATIC && fin.name.equals("renderPass")) {
|
||||
MethodInsnNode getRenderPass = new MethodInsnNode(Opcodes.INVOKESTATIC, "net/minecraftforge/client/ForgeHooksClient", "getWorldRenderPass", "()I");
|
||||
mn.instructions.insert(fin, getRenderPass);
|
||||
mn.instructions.remove(fin);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void transformClientUtils(ClassNode cn) {
|
||||
for (MethodNode mn : cn.methods) {
|
||||
// This patches an if (world != null) check to just be if (false) in order to make the block of code not run
|
||||
// The block of code in question calls OpenGL to update the lightmap texture coordinates, which is illegal from an ISBRH
|
||||
// in Angelica. It doesn't seem to make anything not work by causing this to not happen.
|
||||
if (mn.name.equals("renderStaticWavefrontModelWithIcon") || mn.name.equals("renderStaticWavefrontModel")) {
|
||||
if (
|
||||
mn.desc.equals("(Lnet/minecraft/world/IBlockAccess;IIILnet/minecraftforge/client/model/obj/WavefrontObject;Lnet/minecraft/util/IIcon;Lnet/minecraft/client/renderer/Tessellator;Lblusunrize/immersiveengineering/common/util/chickenbones/Matrix4;Lblusunrize/immersiveengineering/common/util/chickenbones/Matrix4;IZFFF[Ljava/lang/String;)V")
|
||||
|| mn.desc.equals("(Lnet/minecraft/world/IBlockAccess;IIILnet/minecraftforge/client/model/obj/WavefrontObject;Lnet/minecraft/client/renderer/Tessellator;Lblusunrize/immersiveengineering/common/util/chickenbones/Matrix4;Lblusunrize/immersiveengineering/common/util/chickenbones/Matrix4;IZFFF[Ljava/lang/String;)V")
|
||||
) {
|
||||
for (int i = 0; i < mn.instructions.size(); i++) {
|
||||
AbstractInsnNode ain = mn.instructions.get(i);
|
||||
if (ain instanceof JumpInsnNode jump && jump.getOpcode() == Opcodes.IFNULL) {
|
||||
InsnNode iconst = new InsnNode(Opcodes.ICONST_0);
|
||||
jump.setOpcode(Opcodes.IFEQ);
|
||||
mn.instructions.insertBefore(jump, iconst);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+165
@@ -0,0 +1,165 @@
|
||||
package com.gtnewhorizons.angelica.transform.compat.transformers.specific;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.gtnewhorizons.angelica.loading.AngelicaTweaker;
|
||||
import net.minecraft.launchwrapper.IClassTransformer;
|
||||
import org.spongepowered.asm.lib.ClassReader;
|
||||
import org.spongepowered.asm.lib.ClassWriter;
|
||||
import org.spongepowered.asm.lib.Opcodes;
|
||||
import org.spongepowered.asm.lib.tree.AbstractInsnNode;
|
||||
import org.spongepowered.asm.lib.tree.ClassNode;
|
||||
import org.spongepowered.asm.lib.tree.FieldInsnNode;
|
||||
import org.spongepowered.asm.lib.tree.FieldNode;
|
||||
import org.spongepowered.asm.lib.tree.InsnList;
|
||||
import org.spongepowered.asm.lib.tree.InsnNode;
|
||||
import org.spongepowered.asm.lib.tree.LabelNode;
|
||||
import org.spongepowered.asm.lib.tree.MethodInsnNode;
|
||||
import org.spongepowered.asm.lib.tree.MethodNode;
|
||||
import org.spongepowered.asm.lib.tree.TypeInsnNode;
|
||||
import org.spongepowered.asm.lib.tree.VarInsnNode;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class StacksOnStacksTransformer implements IClassTransformer {
|
||||
|
||||
private static final String RenderTilePile = "com.tierzero.stacksonstacks.client.render.RenderTilePile";
|
||||
private static final List<String> staticRemovers = ImmutableList.of("ingotRender", "gemRender", "dustRender");
|
||||
|
||||
private static final String ClientUtils = "com.tierzero.stacksonstacks.util.ClientUtils";
|
||||
|
||||
@Override
|
||||
public byte[] transform(String name, String transformedName, byte[] basicClass) {
|
||||
if (basicClass == null) return null;
|
||||
|
||||
if (!transformedName.equals(RenderTilePile) && !transformedName.equals(ClientUtils)) return basicClass;
|
||||
|
||||
final ClassReader cr = new ClassReader(basicClass);
|
||||
final ClassNode cn = new ClassNode();
|
||||
cr.accept(cn, 0);
|
||||
|
||||
if (transformedName.equals(RenderTilePile)) {
|
||||
transformRenderTilePile(cn);
|
||||
} else {
|
||||
transformClientUtils(cn);
|
||||
}
|
||||
|
||||
ClassWriter cw = new ClassWriter(0);
|
||||
cn.accept(cw);
|
||||
final byte[] bytes = cw.toByteArray();
|
||||
AngelicaTweaker.LOGGER.info("[AngelicaCompat]Extra Transformers: Applied StacksOnStacksTransformer");
|
||||
AngelicaTweaker.dumpClass(transformedName, basicClass, bytes, this);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Injects initializers for the field level PileRender objects which used to be static into the <init>
|
||||
*/
|
||||
private static InsnList buildPilerRenderInitializer(String type) {
|
||||
LabelNode start = new LabelNode();
|
||||
LabelNode end = new LabelNode();
|
||||
InsnList list = new InsnList();
|
||||
list.add(start);
|
||||
list.add(new VarInsnNode(Opcodes.ALOAD, 0));
|
||||
list.add(new TypeInsnNode(Opcodes.NEW, "com/tierzero/stacksonstacks/client/render/PileRender" + type));
|
||||
list.add(new InsnNode(Opcodes.DUP));
|
||||
list.add(
|
||||
new MethodInsnNode(
|
||||
Opcodes.INVOKESPECIAL,
|
||||
"com/tierzero/stacksonstacks/client/render/PileRender" + type,
|
||||
"<init>",
|
||||
"()V"));
|
||||
list.add(
|
||||
new FieldInsnNode(
|
||||
Opcodes.PUTFIELD,
|
||||
"com/tierzero/stacksonstacks/client/render/RenderTilePile",
|
||||
type.toLowerCase() + "Render",
|
||||
"Lcom/tierzero/stacksonstacks/client/render/PileRender;"));
|
||||
list.add(end);
|
||||
return list;
|
||||
}
|
||||
|
||||
private static void transformRenderTilePile(ClassNode cn) {
|
||||
MethodNode clinit = null;
|
||||
for (MethodNode mn : cn.methods) {
|
||||
// Handles injecting field initializers for the various PileRender fields which used to be static
|
||||
// but we're removing <clinit> entirely and doing the initialization in <init>
|
||||
if (mn.name.equals("<init>")) {
|
||||
AbstractInsnNode objectInsn = null;
|
||||
// This removes the early return, and gets a reference to the self initialization so we can insert after
|
||||
for (int i = 0; i < mn.instructions.size(); i++) {
|
||||
AbstractInsnNode ain = mn.instructions.get(i);
|
||||
if (ain.getOpcode() == Opcodes.RETURN) mn.instructions.remove(ain);
|
||||
if (ain.getOpcode() == Opcodes.INVOKESPECIAL) objectInsn = mn.instructions.get(i);
|
||||
}
|
||||
// Build the initializer InsnLists and then insert them in reverse order, such that the dustRender comes
|
||||
// last
|
||||
// because we are adding the return opcode back in as part of that one's InsnList
|
||||
InsnList ingotRender = buildPilerRenderInitializer("Ingot");
|
||||
InsnList gemRender = buildPilerRenderInitializer("Gem");
|
||||
InsnList dustRender = buildPilerRenderInitializer("Dust");
|
||||
dustRender.add(new InsnNode(Opcodes.RETURN));
|
||||
mn.instructions.insert(objectInsn, dustRender);
|
||||
mn.instructions.insert(objectInsn, gemRender);
|
||||
mn.instructions.insert(objectInsn, ingotRender);
|
||||
}
|
||||
// Just catching the MethodNode for <clinit> so we can remove it later after we're done iterating
|
||||
if (mn.name.equals("<clinit>")) {
|
||||
clinit = mn;
|
||||
}
|
||||
if (mn.name.equals("renderWorldBlock")) {
|
||||
for (int i = 0; i < mn.instructions.size(); i++) {
|
||||
AbstractInsnNode in = mn.instructions.get(i);
|
||||
// This part removes the GETSTATIC for the field level PileRender objects which used to be static,
|
||||
// and replaces them with
|
||||
// a non-static GETFIELD
|
||||
if (in instanceof FieldInsnNode fin) {
|
||||
if (fin.getOpcode() == Opcodes.GETSTATIC && staticRemovers.contains(fin.name)) {
|
||||
FieldInsnNode nonStatic = new FieldInsnNode(
|
||||
Opcodes.GETFIELD,
|
||||
"com/tierzero/stacksonstacks/client/render/RenderTilePile",
|
||||
fin.name,
|
||||
"Lcom/tierzero/stacksonstacks/client/render/PileRender;");
|
||||
mn.instructions.insertBefore(fin, new VarInsnNode(Opcodes.ALOAD, 0));
|
||||
mn.instructions.insertBefore(fin, nonStatic);
|
||||
mn.instructions.remove(fin);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Remove clinit after iterating. Nothing else happens in here besides the field initialization, so no reason to
|
||||
// drill down
|
||||
// into the instructions
|
||||
if (clinit != null) cn.methods.remove(clinit);
|
||||
|
||||
// Remove the static access bits from the desired field names
|
||||
for (FieldNode fn : cn.fields) {
|
||||
if (staticRemovers.contains(fn.name)) {
|
||||
fn.access = fn.access & (~Opcodes.ACC_STATIC);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void transformClientUtils(ClassNode cn) {
|
||||
// Various things throughout the ISBRH call these functions which in turn call GL11.glPush/PopMatrix
|
||||
// Upon checking, these aren't called anywhere but in the ISBRH, and they're entirely unnecessary in there.
|
||||
// This just makes the methods no-op, since they aren't required by any other part of the mod to be working.
|
||||
for (MethodNode mn : cn.methods) {
|
||||
if (mn.name.equals("pushMatrix")) {
|
||||
for (int i = 0; i < mn.instructions.size(); i++) {
|
||||
AbstractInsnNode in = mn.instructions.get(i);
|
||||
if (in.getOpcode() == Opcodes.INVOKESTATIC) {
|
||||
mn.instructions.remove(in);
|
||||
}
|
||||
}
|
||||
} else if (mn.name.equals("popMatrix")) {
|
||||
for (int i = 0; i < mn.instructions.size(); i++) {
|
||||
AbstractInsnNode in = mn.instructions.get(i);
|
||||
if (in.getOpcode() == Opcodes.INVOKESTATIC) {
|
||||
mn.instructions.remove(in);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.gtnewhorizons.angelica.zoom;
|
||||
|
||||
public interface IMouseFilterExt {
|
||||
void angelica$reset();
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.gtnewhorizons.angelica.zoom;
|
||||
|
||||
import cpw.mods.fml.client.registry.ClientRegistry;
|
||||
import cpw.mods.fml.common.FMLCommonHandler;
|
||||
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
|
||||
import cpw.mods.fml.common.gameevent.InputEvent;
|
||||
import lombok.Getter;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.settings.KeyBinding;
|
||||
import net.minecraft.util.MathHelper;
|
||||
import org.lwjgl.input.Keyboard;
|
||||
|
||||
public class Zoom {
|
||||
|
||||
@Getter
|
||||
private static float zoom = 4.0F;
|
||||
@Getter
|
||||
private static final KeyBinding zoomKey = new KeyBinding("Zoom", 0, "key.categories.misc");
|
||||
|
||||
public static final float ZOOM_MIN = 1.0F;
|
||||
public static final float ZOOM_MAX = 64.0F;
|
||||
public static final float ZOOM_STEP = 1.2F;
|
||||
|
||||
private static boolean lastSmoothCameraState = false;
|
||||
|
||||
public static void init() {
|
||||
ClientRegistry.registerKeyBinding(zoomKey);
|
||||
FMLCommonHandler.instance().bus().register(new Zoom());
|
||||
}
|
||||
|
||||
public static void modifyZoom(int eventDWheel) {
|
||||
if (eventDWheel == 0) return;
|
||||
zoom = MathHelper.clamp_float((float) (zoom * Math.pow(ZOOM_STEP, Integer.signum(eventDWheel))), ZOOM_MIN, ZOOM_MAX);
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void onKeyPress(InputEvent.KeyInputEvent e) {
|
||||
final int keyCode = zoomKey.getKeyCode();
|
||||
if (keyCode == 0 || Keyboard.getEventKey() != keyCode || Keyboard.isRepeatEvent()) return;
|
||||
final Minecraft mc = Minecraft.getMinecraft();
|
||||
if (Keyboard.getEventKeyState()) {
|
||||
lastSmoothCameraState = mc.gameSettings.smoothCamera;
|
||||
mc.gameSettings.smoothCamera = true;
|
||||
} else {
|
||||
zoom = 4.0F;
|
||||
if (mc.gameSettings.smoothCamera != lastSmoothCameraState) {
|
||||
((IMouseFilterExt) mc.entityRenderer.mouseFilterXAxis).angelica$reset();
|
||||
((IMouseFilterExt) mc.entityRenderer.mouseFilterYAxis).angelica$reset();
|
||||
}
|
||||
mc.gameSettings.smoothCamera = lastSmoothCameraState;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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");
|
||||
@@ -45,7 +45,7 @@ public enum AsmTransformers {
|
||||
.isClient());
|
||||
}
|
||||
|
||||
public static String[] getTransformers() {
|
||||
public static List<String> getTransformers() {
|
||||
final List<String> list = new ArrayList<>();
|
||||
for (AsmTransformers transformer : values()) {
|
||||
if (transformer.shouldBeLoaded()) {
|
||||
@@ -55,7 +55,7 @@ public enum AsmTransformers {
|
||||
AngelicaTweaker.LOGGER.info("Not loading transformer {}", (Object[]) transformer.transformerClasses);
|
||||
}
|
||||
}
|
||||
return list.toArray(new String[0]);
|
||||
return list;
|
||||
}
|
||||
|
||||
private enum Side {
|
||||
|
||||
@@ -2,6 +2,7 @@ package jss.notfine.asm;
|
||||
|
||||
import static jss.notfine.asm.ASMUtils.matchesNodeSequence;
|
||||
|
||||
import com.gtnewhorizons.angelica.loading.AngelicaTweaker;
|
||||
import net.minecraft.launchwrapper.IClassTransformer;
|
||||
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
@@ -32,9 +33,10 @@ public class RenderBlocksTransformer implements IClassTransformer {
|
||||
|
||||
public byte[] transform(String name, String transformedName, byte[] basicClass) {
|
||||
if ("net.minecraft.client.renderer.RenderBlocks".equals(transformedName)) {
|
||||
return patchRenderBlocks(basicClass);
|
||||
final byte[] bytes = patchRenderBlocks(basicClass);
|
||||
AngelicaTweaker.dumpClass(transformedName, basicClass, bytes, this);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
return basicClass;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package jss.notfine.asm;
|
||||
|
||||
import static jss.notfine.asm.ASMUtils.matchesNodeSequence;
|
||||
|
||||
import com.gtnewhorizons.angelica.loading.AngelicaTweaker;
|
||||
import net.minecraft.launchwrapper.IClassTransformer;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
@@ -26,9 +27,10 @@ public class WorldRendererTransformer implements IClassTransformer {
|
||||
|
||||
public byte[] transform(String name, String transformedName, byte[] basicClass) {
|
||||
if ("net.minecraft.client.renderer.WorldRenderer".equals(transformedName)) {
|
||||
return patchWorldRenderer(basicClass);
|
||||
final byte[] bytes = patchWorldRenderer(basicClass);
|
||||
AngelicaTweaker.dumpClass(transformedName, basicClass, bytes, this);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
return basicClass;
|
||||
}
|
||||
|
||||
|
||||
@@ -50,9 +50,6 @@ public class Namer {
|
||||
final boolean obfuscated = !(Boolean) Launch.blackboard.get("fml.deobfuscatedEnvironment");
|
||||
AngelicaTweaker.LOGGER.info("Environment obfuscated: {}", obfuscated);
|
||||
if (obfuscated) {
|
||||
// due to mixin bug we can't use sortingIndex meaning we will run too early to use srg
|
||||
// new NamerSrg().setNames();
|
||||
//TODO: check if this is still the case in Angelica
|
||||
new NamerObf().setNames();
|
||||
} else {
|
||||
new NamerMcp().setNames();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -51,7 +51,13 @@ public enum Settings {
|
||||
DYNAMIC_LIGHTS(new NotFineOptionCycling(DynamicLightsMode.FANCY, OptionImpact.VARIES)){
|
||||
@Override
|
||||
public void applyChanges() {
|
||||
DynamicLights.Mode = (DynamicLightsMode) DYNAMIC_LIGHTS.option.getStore();
|
||||
DynamicLights.Mode = (DynamicLightsMode) this.option.getStore();
|
||||
}
|
||||
},
|
||||
DYNAMIC_LIGHTS_SHADER_FORCE(new NotFineOptionTickBox(false, OptionImpact.VARIES)){
|
||||
@Override
|
||||
public void applyChanges() {
|
||||
DynamicLights.ShaderForce = (boolean) this.option.getStore();
|
||||
}
|
||||
},
|
||||
FOG_NEAR_DISTANCE(new NotFineOptionSliderPercentage(75, 1, 100, 1, OptionImpact.LOW)),
|
||||
|
||||
@@ -191,6 +191,7 @@ public class NotFineGameOptionPages {
|
||||
.add(Settings.DOWNFALL_DISTANCE.option)
|
||||
.add(Settings.MODE_VIGNETTE.option)
|
||||
.add(Settings.DYNAMIC_LIGHTS.option, AngelicaConfig.enableDynamicLights)
|
||||
.add(Settings.DYNAMIC_LIGHTS_SHADER_FORCE.option, AngelicaConfig.enableDynamicLights)
|
||||
.add(Settings.MODE_SHADOWS.option)
|
||||
.add(Settings.VOID_FOG.option)
|
||||
.add(Settings.MODE_DROPPED_ITEMS.option)
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -19,6 +19,7 @@ import me.jellysquid.mods.sodium.client.gui.options.named.GraphicsMode;
|
||||
import me.jellysquid.mods.sodium.client.gui.options.named.GraphicsQuality;
|
||||
import me.jellysquid.mods.sodium.client.gui.options.named.LightingQuality;
|
||||
import me.jellysquid.mods.sodium.client.gui.options.named.ParticleMode;
|
||||
import me.jellysquid.mods.sodium.client.gui.options.storage.AngelicaOptionsStorage;
|
||||
import me.jellysquid.mods.sodium.client.gui.options.storage.MinecraftOptionsStorage;
|
||||
import me.jellysquid.mods.sodium.client.gui.options.storage.SodiumOptionsStorage;
|
||||
import me.jellysquid.mods.sodium.client.render.chunk.backends.multidraw.MultidrawChunkRenderBackend;
|
||||
@@ -36,6 +37,7 @@ import java.util.List;
|
||||
public class SodiumGameOptionPages {
|
||||
private static final SodiumOptionsStorage sodiumOpts = new SodiumOptionsStorage();
|
||||
private static final MinecraftOptionsStorage vanillaOpts = new MinecraftOptionsStorage();
|
||||
private static final AngelicaOptionsStorage angelicaOpts = new AngelicaOptionsStorage();
|
||||
|
||||
public static OptionPage general() {
|
||||
final List<OptionGroup> groups = new ArrayList<>();
|
||||
@@ -153,6 +155,15 @@ public class SodiumGameOptionPages {
|
||||
.add(Settings.DYNAMIC_FOV.option)
|
||||
.add(Settings.MODE_WATER.option)
|
||||
.add(Settings.MODE_DROPPED_ITEMS.option)
|
||||
.add(
|
||||
OptionImpl.createBuilder(int.class, angelicaOpts)
|
||||
.setName(I18n.format("options.angelica.droppedItemLimit"))
|
||||
.setTooltip(I18n.format("options.angelica.droppedItemLimit.tooltip"))
|
||||
.setControl(option -> new SliderControl(option, 32, 2048, 32, ControlValueFormatter.droppedItemLimitLimit()))
|
||||
.setBinding((options, value) -> AngelicaConfig.droppedItemLimit = value, options -> AngelicaConfig.droppedItemLimit)
|
||||
.setImpact(OptionImpact.MEDIUM)
|
||||
.build()
|
||||
)
|
||||
.build());
|
||||
|
||||
return new OptionPage(I18n.format("stat.generalButton"), ImmutableList.copyOf(groups));
|
||||
@@ -232,6 +243,7 @@ public class SodiumGameOptionPages {
|
||||
.add(Settings.MODE_SHADOWS.option)
|
||||
.add(Settings.MODE_VIGNETTE.option)
|
||||
.add(Settings.DYNAMIC_LIGHTS.option, AngelicaConfig.enableDynamicLights)
|
||||
.add(Settings.DYNAMIC_LIGHTS_SHADER_FORCE.option, AngelicaConfig.enableDynamicLights)
|
||||
.build());
|
||||
|
||||
|
||||
@@ -246,7 +258,7 @@ public class SodiumGameOptionPages {
|
||||
.build())
|
||||
.build());
|
||||
groups.add(OptionGroup.createBuilder()
|
||||
.add(Settings.MODE_GLINT_INV.option)
|
||||
.add(Settings.MODE_GLINT_INV.option)
|
||||
.add(Settings.MODE_GLINT_WORLD.option)
|
||||
.build());
|
||||
|
||||
@@ -360,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)
|
||||
|
||||
+3
@@ -10,6 +10,9 @@ public interface ControlValueFormatter {
|
||||
static ControlValueFormatter fpsLimit() {
|
||||
return (v) -> (v == 260) ? I18n.format("options.framerateLimit.max") : I18n.format("options.framerate", v);
|
||||
}
|
||||
static ControlValueFormatter droppedItemLimitLimit() {
|
||||
return (v) -> (v == 2048) ? I18n.format("options.droppedItems.max") : I18n.format("options.droppedItems", v);
|
||||
}
|
||||
|
||||
static ControlValueFormatter brightness() {
|
||||
return (v) -> {
|
||||
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
package me.jellysquid.mods.sodium.client.gui.options.storage;
|
||||
|
||||
import com.gtnewhorizon.gtnhlib.config.ConfigurationManager;
|
||||
import com.gtnewhorizons.angelica.config.AngelicaConfig;
|
||||
import me.jellysquid.mods.sodium.client.SodiumClientMod;
|
||||
|
||||
public class AngelicaOptionsStorage implements OptionStorage<AngelicaConfig> {
|
||||
|
||||
public AngelicaOptionsStorage() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public AngelicaConfig getData() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save() {
|
||||
ConfigurationManager.save(AngelicaConfig.class);
|
||||
SodiumClientMod.logger().info("Flushed changes to Angelica configuration");
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -25,6 +25,6 @@ public class SodiumOptionsStorage implements OptionStorage<SodiumGameOptions> {
|
||||
throw new RuntimeException("Couldn't save configuration changes", e);
|
||||
}
|
||||
|
||||
SodiumClientMod.logger().info("Flushed changes to Rubidium configuration");
|
||||
SodiumClientMod.logger().info("Flushed changes to Angelica configuration");
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
|
||||
@@ -24,6 +24,8 @@ import me.jellysquid.mods.sodium.client.render.chunk.backends.multidraw.Multidra
|
||||
import me.jellysquid.mods.sodium.client.render.chunk.backends.oneshot.ChunkRenderBackendOneshot;
|
||||
import me.jellysquid.mods.sodium.client.render.chunk.data.ChunkRenderData;
|
||||
import me.jellysquid.mods.sodium.client.render.chunk.format.DefaultModelVertexFormats;
|
||||
import me.jellysquid.mods.sodium.client.render.chunk.map.ChunkTracker;
|
||||
import me.jellysquid.mods.sodium.client.render.chunk.map.ChunkTrackerHolder;
|
||||
import me.jellysquid.mods.sodium.client.render.chunk.passes.BlockRenderPass;
|
||||
import me.jellysquid.mods.sodium.client.render.pipeline.context.ChunkRenderCacheShared;
|
||||
import me.jellysquid.mods.sodium.client.util.math.FrustumExtended;
|
||||
@@ -59,7 +61,7 @@ import java.util.Set;
|
||||
/**
|
||||
* Provides an extension to vanilla's {@link WorldRenderer}.
|
||||
*/
|
||||
public class SodiumWorldRenderer implements ChunkStatusListener {
|
||||
public class SodiumWorldRenderer {
|
||||
private static SodiumWorldRenderer instance;
|
||||
|
||||
private final Minecraft client;
|
||||
@@ -155,7 +157,6 @@ public class SodiumWorldRenderer implements ChunkStatusListener {
|
||||
this.chunkRenderBackend = null;
|
||||
}
|
||||
|
||||
this.loadedChunkPositions.clear();
|
||||
this.globalTileEntities.clear();
|
||||
|
||||
this.world = null;
|
||||
@@ -194,6 +195,8 @@ public class SodiumWorldRenderer implements ChunkStatusListener {
|
||||
public void updateChunks(Camera camera, Frustrum frustum, boolean hasForcedFrustum, int frame, boolean spectator) {
|
||||
this.frustum = frustum;
|
||||
|
||||
this.processChunkEvents();
|
||||
|
||||
this.useEntityCulling = SodiumClientMod.options().advanced.useEntityCulling;
|
||||
|
||||
if (this.client.gameSettings.renderDistanceChunks != this.renderDistance) {
|
||||
@@ -265,6 +268,11 @@ public class SodiumWorldRenderer implements ChunkStatusListener {
|
||||
}
|
||||
}
|
||||
|
||||
private void processChunkEvents() {
|
||||
var tracker = ChunkTrackerHolder.get(this.world);
|
||||
tracker.forEachEvent(this.chunkRenderManager::onChunkAdded, this.chunkRenderManager::onChunkRemoved);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a render pass for the given {@link RenderLayer} and draws all visible chunks for it.
|
||||
*/
|
||||
@@ -324,7 +332,9 @@ public class SodiumWorldRenderer implements ChunkStatusListener {
|
||||
this.chunkRenderBackend.createShaders(device);
|
||||
|
||||
this.chunkRenderManager = new ChunkRenderManager<>(this, this.chunkRenderBackend, this.world, this.renderDistance);
|
||||
this.chunkRenderManager.restoreChunks(this.loadedChunkPositions);
|
||||
|
||||
var tracker = ChunkTrackerHolder.get(this.world);
|
||||
ChunkTracker.forEachChunk(tracker.getReadyChunks(), this.chunkRenderManager::onChunkAdded);
|
||||
}
|
||||
|
||||
private static ChunkRenderBackend<?> createChunkRenderBackend(RenderDevice device, SodiumGameOptions options, ChunkVertexType vertexFormat) {
|
||||
@@ -379,18 +389,6 @@ public class SodiumWorldRenderer implements ChunkStatusListener {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChunkAdded(int x, int z) {
|
||||
this.loadedChunkPositions.add(ChunkPos.toLong(x, z));
|
||||
this.chunkRenderManager.onChunkAdded(x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChunkRemoved(int x, int z) {
|
||||
this.loadedChunkPositions.remove(ChunkPos.toLong(x, z));
|
||||
this.chunkRenderManager.onChunkRemoved(x, z);
|
||||
}
|
||||
|
||||
public void onChunkRenderUpdated(int x, int y, int z, ChunkRenderData meshBefore, ChunkRenderData meshAfter) {
|
||||
ListUtil.updateList(this.globalTileEntities, meshBefore.getGlobalTileEntities(), meshAfter.getGlobalTileEntities());
|
||||
|
||||
|
||||
Loaded 100 of 172 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user