Compare commits
222 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 42ab9eebe5 | |||
| 49e3e11250 | |||
| 10925d7c57 | |||
| 7d918fe8dc | |||
| 938631a379 | |||
| 48966bf32a | |||
| 2dc38622e2 | |||
| 36f1c49f49 | |||
| 271f4e8b21 | |||
| b164e4646d | |||
| 14fd5729e2 | |||
| 7c3e279237 | |||
| 536389af0b | |||
| 2884094dee | |||
| 817c268491 | |||
| 071a306f14 | |||
| 7ad0599beb | |||
| c97fea6d0a | |||
| d94faf828d | |||
| 0d6d4b133e | |||
| 8234ac60b8 | |||
| 5ab6bfb663 | |||
| e087dbc878 | |||
| 391e96ad3d | |||
| fbf812091d | |||
| 31ab738392 | |||
| 7448483f84 | |||
| e3d6e1bcc6 | |||
| fbbcd1b95b | |||
| d8e7325044 | |||
| f17aeca79c | |||
| ac3a223114 | |||
| e4312c2f8b | |||
| 17bde631ac | |||
| 578efbf15f | |||
| 8b6bb228e3 | |||
| 611c4606d7 | |||
| 05bdaf0390 | |||
| eb8fcaee36 | |||
| 32a71933d6 | |||
| a4baf9ca0a | |||
| 72bfd0a2bb | |||
| 7ae4a9f460 | |||
| 9bd6fb0105 | |||
| 1f1024251b | |||
| fc516a20d5 | |||
| 791c2c3426 | |||
| b00079897a | |||
| 37b73e1d5c | |||
| 4bd1136713 | |||
| 42344e9c31 | |||
| 904cc4760f | |||
| 297a8dc980 | |||
| ef98dbd5fd | |||
| 5df0a60b06 | |||
| 9feb20eff8 | |||
| c9267d61a8 | |||
| a29e225a80 | |||
| ae0f3c2b3b | |||
| 852ea75449 | |||
| ab6a5dad2b | |||
| 1a1eaca280 | |||
| 0272f8c57f | |||
| cf09358710 | |||
| b5d833fa3d | |||
| 329dbe9585 | |||
| c7ae7f155e | |||
| 30eb02f3b7 | |||
| 86cda56381 | |||
| 35c1bae156 | |||
| e1ce3ae200 | |||
| ed16c83271 | |||
| 5f7dbb8662 | |||
| ee21548151 | |||
| ca00125960 | |||
| 4067264e72 | |||
| 9c2d243ad4 | |||
| de9d8b0d2e | |||
| 67f4615b34 | |||
| cd7a130ee4 | |||
| 4d17f7aecf | |||
| a59e7500ab | |||
| 9d9fdd8ddd | |||
| 2711d8dccc | |||
| c8535f13a6 | |||
| b5ba7862a9 | |||
| 33e61b7ef0 | |||
| 1617ebda9e | |||
| 29042e2ced | |||
| 390dda94c6 | |||
| 6600703d52 | |||
| 3a065d1784 | |||
| 0e340e4558 | |||
| ca550a0a57 | |||
| 30143cbbcb | |||
| 81abcbdb86 | |||
| 3080102f06 | |||
| 6316587ebe | |||
| 2e1a2367bd | |||
| e65b1e2dfc | |||
| 40040294e7 | |||
| 783e61ec3d | |||
| e09db5d7df | |||
| 91f9ef3f4b | |||
| d52a3abb14 | |||
| 16370b0b6e | |||
| bfa60b48cf | |||
| 50518bfe21 | |||
| 80e4467829 | |||
| 396315bd05 | |||
| 7a0fec2c2f | |||
| 4afaaa7b12 | |||
| b057041467 | |||
| 33e6ce6376 | |||
| 118ef39c30 | |||
| 1013e1c824 | |||
| b0e924c7fe | |||
| 1777acd1d4 | |||
| 8276a862f8 | |||
| 4329acf91d | |||
| 72f83b40f7 | |||
| a33eb30a53 | |||
| d3e96f50a8 | |||
| 3aefeb98b4 | |||
| 3553ff8e60 | |||
| 945a2c0c5a | |||
| 8c7974e216 | |||
| 37756cd759 | |||
| c60cc4f013 | |||
| 87cce2e33c | |||
| 40ada9c186 | |||
| 55fb458266 | |||
| 79d2466fa2 | |||
| d750e489df | |||
| a206e49b2b | |||
| 0b691ebcd5 | |||
| 3c35c52803 | |||
| 0ed4964ee5 | |||
| b7cf7b61c8 | |||
| 54b0ccfce6 | |||
| 050d00b628 | |||
| 2733201ac3 | |||
| 26bf03205c | |||
| 628d57d216 | |||
| 58ed8259f2 | |||
| 062ed5bcc8 | |||
| 539d152caa | |||
| a1af4335e0 | |||
| e68b112020 | |||
| fab6d187ca | |||
| 0daa00cec2 | |||
| f3036850ce | |||
| 51c8b47bba | |||
| 89efd53d61 | |||
| 7667f51cf3 | |||
| 61eaa5a734 | |||
| 1d589d1a62 | |||
| 03b1eeb77e | |||
| 8446df72f7 | |||
| c07397e9c0 | |||
| 29a92aeb93 | |||
| 8467782b80 | |||
| c8dbb21ea4 | |||
| 63e1c12564 | |||
| 52f58150da | |||
| d1d642a7bb | |||
| 8e45358aad | |||
| a959c7220b | |||
| e06425c5eb | |||
| 66ce258fe1 | |||
| 181881a661 | |||
| af0d8d1d2f | |||
| 6c68e94b96 | |||
| 93313a5c50 | |||
| 0527baa708 | |||
| ce1fbde937 | |||
| 764abdac45 | |||
| b42d3d8f74 | |||
| cd67a773c5 | |||
| 6d7bade7ca | |||
| dea8d4498a | |||
| 2969916f34 | |||
| 8785224c51 | |||
| 605f02a655 | |||
| 8099d37c14 | |||
| dd4dbefe9a | |||
| 52a15fd349 | |||
| 3b3be6aed4 | |||
| aeb7d6d0f9 | |||
| 5336dbafec | |||
| 6079cb4830 | |||
| 50ff174104 | |||
| b77ef89df6 | |||
| a701dd29a9 | |||
| ab36fdd545 | |||
| f87afb34f4 | |||
| 053917d3d7 | |||
| 063ba01970 | |||
| 72a888f3ff | |||
| 0bd36bff1d | |||
| 2bf125b7ac | |||
| ba3cf8fd56 | |||
| 951f2a4ee7 | |||
| d55b1bb3c2 | |||
| 275ecb78c3 | |||
| 64ac0d6017 | |||
| 29381bce7b | |||
| 9fea29cbb6 | |||
| 7e1e5a56e2 | |||
| 059293ebe0 | |||
| 4f9d4e2a14 | |||
| 6bd3c825c3 | |||
| c75595a5e2 | |||
| 266d463873 | |||
| 73c718c676 | |||
| 3df5c04759 | |||
| d72c34a926 | |||
| 8991338be1 | |||
| 6b32ab02d3 | |||
| c5adc3f72a | |||
| 1d0d67d215 | |||
| e5536de44f |
@@ -1,19 +0,0 @@
|
||||
**/.git
|
||||
**/.gitlab
|
||||
**/.cache
|
||||
|
||||
buildAllJars
|
||||
|
||||
**/_Misc Files
|
||||
*.bat
|
||||
*.md
|
||||
*.sh
|
||||
*.txt
|
||||
|
||||
coreSubProjects/*.md
|
||||
coreSubProjects/*.txt
|
||||
|
||||
**/.gitignore
|
||||
**/.gitattributes
|
||||
**/.gitlab-cy.yml
|
||||
**/.gitmodules
|
||||
@@ -25,6 +25,8 @@ hs_err_pid*
|
||||
Merged/
|
||||
# Folder created by the buildAll scripts
|
||||
buildAllJars/
|
||||
_buildAllJars/
|
||||
_buildWorkers/
|
||||
|
||||
relocate_natives/.venv/
|
||||
relocate_natives/__pycache__/
|
||||
|
||||
+3
-2
@@ -35,13 +35,14 @@ build:
|
||||
parallel:
|
||||
matrix:
|
||||
- MC_VER: [
|
||||
"1.26.1",
|
||||
"26.1.2",
|
||||
"1.21.11", "1.21.10", "1.21.9", "1.21.8", "1.21.6", "1.21.5", "1.21.4", "1.21.3", "1.21.1",
|
||||
"1.20.6", "1.20.4", "1.20.2", "1.20.1",
|
||||
"1.19.4", "1.19.2",
|
||||
"1.18.2",
|
||||
"1.17.1",
|
||||
"1.16.5"
|
||||
"1.16.5",
|
||||
"1.12.2"
|
||||
]
|
||||
script:
|
||||
# this both runs the unit tests and assembles the code
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="distant-horizons [cleanroom:runClient]" type="GradleRunConfiguration" factoryName="Gradle">
|
||||
<ExternalSystemSettings>
|
||||
<option name="executionName" />
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="externalSystemIdString" value="GRADLE" />
|
||||
<option name="scriptParameters" value="" />
|
||||
<option name="taskDescriptions">
|
||||
<list />
|
||||
</option>
|
||||
<option name="taskNames">
|
||||
<list>
|
||||
<option value="cleanroom:runClient" />
|
||||
</list>
|
||||
</option>
|
||||
<option name="vmOptions" />
|
||||
</ExternalSystemSettings>
|
||||
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
|
||||
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
|
||||
<ExternalSystemDebugDisabled>false</ExternalSystemDebugDisabled>
|
||||
<DebugAllEnabled>false</DebugAllEnabled>
|
||||
<RunAsTest>false</RunAsTest>
|
||||
<GradleProfilingDisabled>false</GradleProfilingDisabled>
|
||||
<GradleCoverageDisabled>false</GradleCoverageDisabled>
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
</component>
|
||||
-12
@@ -1,12 +0,0 @@
|
||||
FROM eclipse-temurin:25-jdk
|
||||
|
||||
WORKDIR /home/build/
|
||||
COPY ./gradlew .
|
||||
RUN chmod +x ./gradlew
|
||||
CMD echo "\r========== [CLEAN: $MC_VER] ==========" && \
|
||||
./gradlew clean -PmcVer="$MC_VER" --gradle-user-home .gradle-cache/ && \
|
||||
echo "\r========== [BUILD: $MC_VER] ==========" && \
|
||||
./gradlew build -PmcVer="$MC_VER" --gradle-user-home .gradle-cache/ && \
|
||||
echo "\r========== [MERGE: $MC_VER] ==========" && \
|
||||
./gradlew mergeJars -PmcVer="$MC_VER" --gradle-user-home .gradle-cache/ && \
|
||||
echo "\r========== [DONE: $MC_VER] =========="
|
||||
@@ -14,89 +14,11 @@ Below is a video demonstrating the system:
|
||||
|
||||
<br>
|
||||
|
||||
## Minecraft and Library Versions
|
||||
|
||||
### This branch supports the following versions of Minecraft:
|
||||
|
||||
#### 1.20.4, 1.20.3 (Default)
|
||||
Fabric: 0.15.1\
|
||||
Fabric API: 0.91.2+1.20.4\
|
||||
Forge: 49.0.30\
|
||||
NeoForge: 118-beta\
|
||||
Parchment: 1.20.2:2023.12.10\
|
||||
Modmenu: 9.0.0-pre.1
|
||||
|
||||
#### 1.20.2
|
||||
Fabric: 0.14.24\
|
||||
Fabric API: 0.90.4+1.20.2\
|
||||
Forge: 48.0.13\
|
||||
Parchment: 1.20.1:2023.09.03\
|
||||
Modmenu: 8.0.0
|
||||
|
||||
#### 1.20.1, 1.20
|
||||
Fabric: 0.14.24\
|
||||
Fabric API: 0.90.4+1.20.1\
|
||||
Forge: 47.2.1\
|
||||
Parchment: 1.20.1:2023.09.03\
|
||||
Modmenu: 7.2.2
|
||||
|
||||
#### 1.19.4
|
||||
Fabric: 0.14.24\
|
||||
Fabric API: 0.87.1+1.19.4\
|
||||
Forge: 45.2.4\
|
||||
Parchment: 1.19.4:2023.06.26\
|
||||
Modmenu: 6.3.1
|
||||
|
||||
#### 1.19.2
|
||||
Fabric: 0.14.24\
|
||||
Fabric API: 0.76.1+1.19.2\
|
||||
Forge: 43.3.2\
|
||||
Parchment: 1.19.2:2022.11.27\
|
||||
Modmenu: 4.2.0-beta.2
|
||||
|
||||
#### 1.18.2
|
||||
Fabric: 0.14.24\
|
||||
Fabric API: 0.76.0+1.18.2\
|
||||
Forge: 40.2.10\
|
||||
Parchment: 1.18.2:2022.11.06\
|
||||
Modmenu: 3.2.5
|
||||
|
||||
#### 1.17.1, 1.17
|
||||
Fabric: 0.14.24\
|
||||
Fabric API: 0.46.1+1.17\
|
||||
Forge: 37.1.1\
|
||||
Parchment: 1.17.1:2021.12.12\
|
||||
Modmenu: 2.0.14
|
||||
|
||||
#### 1.16.5, 1.16.4
|
||||
Fabric: 0.14.24\
|
||||
Fabric API: 0.42.0+1.16\
|
||||
Forge: 36.2.39\
|
||||
Parchment: 1.16.5:2022.03.06\
|
||||
Modmenu: 1.16.22
|
||||
|
||||
### Versions no longer supported
|
||||
- 1.18.1, 1.18
|
||||
- 1.19.1, 1.19
|
||||
- 1.19.3
|
||||
|
||||
<br>
|
||||
|
||||
### Plugin and Library versions
|
||||
|
||||
Gradle: 8.5\
|
||||
Fabric loom: 1.4-SNAPSHOT\
|
||||
Architectury loom (Forge gradle replacement): 1.4-SNAPSHOT\
|
||||
Sponge vanilla gradle: 0.2.1-SNAPSHOT\
|
||||
Java Preprocessor plugin: Manifold Preprocessor
|
||||
|
||||
<br>
|
||||
|
||||
## Source Code Installation
|
||||
|
||||
### Prerequisites
|
||||
|
||||
* A Java Development Kit (JDK) for Java 17 (recommended) or newer. <br>
|
||||
* A Java Development Kit (JDK) for Java 25 (recommended) or newer. <br>
|
||||
Visit https://www.oracle.com/java/technologies/downloads/ for installers.
|
||||
* Git or someway to clone git projects. <br>
|
||||
Visit https://git-scm.com/ for installers.
|
||||
@@ -104,15 +26,10 @@ Java Preprocessor plugin: Manifold Preprocessor
|
||||
|
||||
**If using IntelliJ:**
|
||||
1. Install the Manifold plugin
|
||||
- https://plugins.jetbrains.com/plugin/10057-manifold-ij
|
||||
2. Open IDEA and import the build.gradle
|
||||
3. Refresh the Gradle project in IDEA if required
|
||||
|
||||
**If using Eclipse: (Note that Eclipse doesn't support Manifold's preprocessor!)**
|
||||
1. Run the command: `./gradlew geneclipseruns`
|
||||
2. Run the command: `./gradlew eclipse`
|
||||
3. Make sure eclipse has the JDK 17 installed. (This is needed so that eclipse can run minecraft)
|
||||
4. Import the project into eclipse
|
||||
|
||||
<br>
|
||||
|
||||
## Switching Versions
|
||||
@@ -127,72 +44,42 @@ In IntelliJ, you will also need to do a gradle sync if it didn't happen automati
|
||||
## Compiling
|
||||
|
||||
Prerequisites:
|
||||
- JDK 17 or newer
|
||||
|
||||
From the File Explorer:
|
||||
1. Download and extract the project zip
|
||||
2. Download the core from https://gitlab.com/distant-horizons-team/distant-horizons-core and extract into a folder called `coreSubProjects`
|
||||
3. Open a terminal emulator in the project folder (On Windows you can type `cmd` in the title bar)
|
||||
4. Run the commands: `./gradlew assemble` (You may need to use a `.\` on Windows)
|
||||
5. Merge the jars with `./gradlew mergeJars`
|
||||
6. The compiled jar file will be in the folder `Merged`
|
||||
- JDK 25 or newer
|
||||
|
||||
From the command line:
|
||||
1. `git clone --recurse-submodules https://gitlab.com/distant-horizons-team/distant-horizons.git`
|
||||
2. `cd distant-horizons`
|
||||
3. `./gradlew assemble`
|
||||
4. `./gradlew mergeJars`
|
||||
5. The compiled jar file will be in the folder `Merged`
|
||||
5. The compiled jar file will be in the folder `\build\libs`
|
||||
|
||||
Run tests with: `./gradlew test`
|
||||
From the File Explorer:
|
||||
1. Download and extract the project zip
|
||||
2. Download the core from https://gitlab.com/distant-horizons-team/distant-horizons-core and extract into a folder called `coreSubProjects`
|
||||
3. Open command prompt/terminal in the project folder
|
||||
4. Run the commands: `./gradlew assemble`
|
||||
6. The compiled jar file will be in the folder `\build\libs`
|
||||
|
||||
>Note: You can add the argument `-PmcVer=?` to tell gradle to build a selected MC version instead of having to modify the `gradle.properties` file.\
|
||||
> For example: `./gradlew assemble -PmcVer=1.18.2`
|
||||
|
||||
<br>
|
||||
|
||||
## Compiling with Docker
|
||||
|
||||
`./compile <version>`
|
||||
|
||||
You can also locally compile the DH jars without a Java environment by using Docker. Where `<version>` is the version of Minecraft to compile for (ie `1.20.1`), or the keyword `all`. See [Versions](#minecraft-and-library-versions) for a list of all supported values.
|
||||
|
||||
<br>
|
||||
|
||||
## Other commands
|
||||
|
||||
`./gradlew --refresh-dependencies` to refresh local dependencies.
|
||||
|
||||
`./gradlew clean` to delete any compiled code.
|
||||
|
||||
<br>
|
||||
|
||||
## Note to self
|
||||
|
||||
The Minecraft source code is NOT added to your workspace in an editable way. Minecraft is treated like a normal Library. Sources are there for documentation and research purposes only.
|
||||
|
||||
Source code uses Mojang mappings & [Parchment](https://parchmentmc.org/) mappings.
|
||||
|
||||
To generate the source code run `./gradlew genSources` <br>
|
||||
If your IDE fails to auto-detect the source jars when browsing Minecraft classes; manually select the JAR file ending with -sources.jar when prompted by your IDE. <br>
|
||||
(In IntelliJ it's at the top where it says "choose sources" when browsing a Minecraft class)
|
||||
|
||||
<br>
|
||||
|
||||
## Other Useful commands
|
||||
|
||||
Run the standalone jar: `./gradlew run` <br>
|
||||
Build the standalone jar: `./gradlew core:build` <br>
|
||||
Only build Fabric: `./gradlew fabric:assemble` or `./gradlew fabric:build` <br>
|
||||
Only build Forge: `./gradlew forge:assemble` or `./gradlew forge:build` <br>
|
||||
Run the Fabric client (for debugging): `./gradlew fabric:runClient` <br>
|
||||
Run the Forge client (for debugging): `./gradlew forge:runClient` <br>
|
||||
Delete all compiled code: `./gradlew clean` <br>
|
||||
Refresh local dependencies: `./gradlew --refresh-dependencies`
|
||||
|
||||
To build all versions: `./buildAll` (all builds will end up in the `Merged` folder)
|
||||
To build all versions: `./buildAll`
|
||||
|
||||
<br>
|
||||
|
||||
## Open Source Acknowledgements
|
||||
## Open Source Libraries
|
||||
|
||||
Forgix (To merge multiple mod versions into one jar) [_Formerly_ [_DHJarMerger_](https://github.com/Ran-helo/DHJarMerger)]\
|
||||
https://github.com/PacifistMC/Forgix
|
||||
@@ -208,3 +95,18 @@ https://github.com/blackears/svgSalamander
|
||||
|
||||
sqlite-jdbc\
|
||||
https://github.com/xerial/sqlite-jdbc
|
||||
|
||||
|
||||
## Acknowledgements
|
||||
|
||||
Distant Horizons has been graciously provided an open source license for <a href="https://www.yourkit.com/java/profiler/">YourKit Java Profiler</a>.
|
||||
|
||||
> <img src="https://www.yourkit.com/images/yklogo.png">
|
||||
>
|
||||
> YourKit supports open source projects with innovative and intelligent tools
|
||||
for monitoring and profiling Java and .NET applications.
|
||||
YourKit is the creator of <a href="https://www.yourkit.com/java/profiler/">YourKit Java Profiler</a>,
|
||||
<a href="https://www.yourkit.com/dotnet-profiler/">YourKit .NET Profiler</a>,
|
||||
and <a href="https://www.yourkit.com/youmonitor/">YourKit YouMonitor</a>.
|
||||
|
||||
|
||||
|
||||
+27
-1
@@ -4,5 +4,31 @@ plugins {
|
||||
}
|
||||
|
||||
forgix {
|
||||
autoRun = true
|
||||
|
||||
// add the mod loaders to the end of the jar
|
||||
// put together in the format: "a", "a-b", "a-b-c"
|
||||
int loaderCount = 0;
|
||||
String modLoaders = "";
|
||||
((String) gradle.builds_for)
|
||||
.split(",")
|
||||
.each
|
||||
{ loader ->
|
||||
def loaderName = loader.trim()
|
||||
if (modLoaders != "")
|
||||
{
|
||||
modLoaders += "-";
|
||||
}
|
||||
|
||||
modLoaders += loaderName;
|
||||
|
||||
loaderCount++;
|
||||
}
|
||||
|
||||
// run if there are multiple launchers that need merging
|
||||
autoRun = (loaderCount > 1);
|
||||
|
||||
// merged jars are named in the format:
|
||||
// "DistantHorizons-3.0.1-b-dev-26.1-fabric-neoforge.jar"
|
||||
archiveClassifier = modLoaders
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
echo "==================== Note: All build jars will be in the folder called 'buildAllJars' ===================="
|
||||
mkdir -p buildAllJars
|
||||
rm -rf buildAllJars/*
|
||||
rm -rf build/forgix/*
|
||||
|
||||
# Loop trough everything in the version properties folder
|
||||
for d in versionProperties/*; do
|
||||
@@ -19,10 +20,6 @@ for d in versionProperties/*; do
|
||||
sh gradlew build -PmcVer=$version
|
||||
if [ $? != 0 ]; then continue; fi
|
||||
|
||||
echo "==================== Merging $version ===================="
|
||||
sh gradlew mergeJars -PmcVer=$version
|
||||
if [ $? != 0 ]; then continue; fi
|
||||
|
||||
echo "==================== Moving jar ===================="
|
||||
mv build/merged/*.jar buildAllJars/
|
||||
mv build/forgix/*.jar buildAllJars/
|
||||
done
|
||||
|
||||
+2
-4
@@ -6,6 +6,7 @@
|
||||
echo ==================== Note: All build jars will be in the folder called 'buildAllJars' ====================
|
||||
mkdir buildAllJars
|
||||
del buildAllJars/*
|
||||
del build/forgix/*
|
||||
|
||||
@rem Loop trough everything in the version properties folder
|
||||
for %%f in (versionProperties\*) do (
|
||||
@@ -19,11 +20,8 @@ for %%f in (versionProperties\*) do (
|
||||
echo ==================== Building !version! ====================
|
||||
call .\gradlew.bat build -PmcVer="!version!"
|
||||
|
||||
echo ==================== Merging !version! ====================
|
||||
call .\gradlew.bat mergeJars -PmcVer="!version!"
|
||||
|
||||
echo ==================== Moving jar ====================
|
||||
move build\merged\*.jar buildAllJars\
|
||||
move build\forgix\*.jar buildAllJars\
|
||||
)
|
||||
|
||||
endlocal
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
@echo off & setlocal enabledelayedexpansion
|
||||
|
||||
|
||||
echo ==================== Getting versions to build... ====================
|
||||
mkdir _buildAllJars 2>nul
|
||||
del _buildAllJars\* /Q 2>nul
|
||||
|
||||
set "ROOT=%~dp0"
|
||||
set "WORK_DIR=%ROOT%_buildWorkers"
|
||||
mkdir "%WORK_DIR%" 2>nul
|
||||
|
||||
|
||||
REM get the number of versions to compile
|
||||
set count=0
|
||||
for %%f in (versionProperties\*) do set /a count+=1
|
||||
echo ==================== Found %count% versions to build in parallel ====================
|
||||
|
||||
REM Launch a parallel job for each version
|
||||
for %%f in (%ROOT%versionProperties\*) do (
|
||||
set version=%%~nf
|
||||
|
||||
echo starting [!version!]...
|
||||
start "Build !version!" cmd /c ""%ROOT%build_worker.bat" "!version!" "%ROOT%" "%WORK_DIR%" ""..\..\_buildAllJars"""
|
||||
|
||||
REM Minor timeout between launches so we can stop the build early if we only want
|
||||
REM to test part of the script and to reduce startup load
|
||||
timeout /t 3 /nobreak
|
||||
|
||||
REM 2>nul to supress a harmless warning that the for loop
|
||||
REM "cannot find the drive specified"
|
||||
) 2>nul
|
||||
|
||||
|
||||
echo ==================== All builds started... Completed Jars will be in _buildAllJars ====================
|
||||
endlocal
|
||||
@@ -18,7 +18,7 @@ repositories {
|
||||
|
||||
dependencies {
|
||||
implementation 'com.gradleup.shadow:shadow-gradle-plugin:9.0.0'
|
||||
implementation 'xyz.wagyourtail.unimined:xyz.wagyourtail.unimined.gradle.plugin:1.4.17-kappa'
|
||||
implementation 'xyz.wagyourtail.unimined:xyz.wagyourtail.unimined.gradle.plugin:1.4.18-kappa'
|
||||
implementation 'xyz.wagyourtail:manifold-gradle:1.0.0-SNAPSHOT'
|
||||
implementation 'xyz.wagyourtail.jvmdowngrader:xyz.wagyourtail.jvmdowngrader.gradle.plugin:1.3.4'
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import org.apache.tools.zip.ZipOutputStream
|
||||
import javax.annotation.Nonnull
|
||||
import java.util.function.Function
|
||||
import java.util.function.Predicate
|
||||
import groovy.json.JsonSlurper
|
||||
|
||||
// Convention plugin for all MC-facing subprojects (common + loaders).
|
||||
// Common uses this directly; loaders use it via unimined-fabric/forge/neoforge.
|
||||
@@ -23,6 +24,9 @@ plugins {
|
||||
|
||||
def isNotCommonProject = project.name != "common"
|
||||
|
||||
if (isNotCommonProject) {
|
||||
evaluationDependsOn(":common")
|
||||
}
|
||||
|
||||
// ==================== Version Properties ====================
|
||||
|
||||
@@ -54,7 +58,12 @@ repositories {
|
||||
url "https://www.cursemaven.com"
|
||||
content { includeGroup "curse.maven" }
|
||||
}
|
||||
maven { url "https://repo.spongepowered.org/maven/" }
|
||||
maven {
|
||||
url "https://repo.spongepowered.org/maven/"
|
||||
// exclusion is needed since sponge has a deprecated version of fabric
|
||||
// that gradle would prefer to get over the up-to-date version modrinth provides
|
||||
content { excludeGroupByRegex "net\\.fabricmc(\\..*)?" }
|
||||
}
|
||||
maven { url "https://maven.terraformersmc.com/" }
|
||||
maven { url "https://maven.neoforged.net/releases/" }
|
||||
flatDir {
|
||||
@@ -116,6 +125,15 @@ if (isNotCommonProject) {
|
||||
'Multi-Release': true,
|
||||
'Main-Class': 'com.seibel.distanthorizons.core.jar.JarMain',
|
||||
)
|
||||
if (project.name == "cleanroom") {
|
||||
attributes(
|
||||
'ModType': 'CRL',
|
||||
'MixinConfigs': "${mod_id}.default.mixin.json,${mod_id}.mod.mixin.json",
|
||||
'FMLCorePlugin': 'com.seibel.distanthorizons.cleanroom.DistantHorizonsLoadingPlugin',
|
||||
'FMLCorePluginContainsFMLMod': true,
|
||||
'FMLAT': "src/main/resources/${gradle.ext.accessWidenerVersion}.distanthorizons_at.cfg"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -128,8 +146,14 @@ unimined.minecraft(sourceSets.main, true) {
|
||||
|
||||
if (gradle.ext.minecraft_version.startsWith("1.")) { // 26.1+ doesn't use obfuscation
|
||||
mappings {
|
||||
mojmap()
|
||||
devNamespace "mojmap"
|
||||
if(gradle.ext.minecraft_version.startsWith("1.12.2")){
|
||||
mcp("stable", "39-1.12")
|
||||
}
|
||||
else{
|
||||
mojmap()
|
||||
devNamespace "mojmap"
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -160,18 +184,22 @@ if (isNotCommonProject) {
|
||||
source(project(":common").sourceSets.main.allSource)
|
||||
}
|
||||
} else {
|
||||
// Common: fabric for compilation + access widener, no jar remapping or runs
|
||||
unimined.minecraft {
|
||||
fabric {
|
||||
loader gradle.ext.fabric_loader_version
|
||||
accessWidener project.file("src/main/resources/${gradle.ext.accessWidenerVersion}.distanthorizons.accesswidener")
|
||||
if (gradle.ext.minecraft_version.equals("1.12.2")) {
|
||||
cleanroom {
|
||||
loader gradle.ext.cleanroom_loader_version
|
||||
}
|
||||
} else {
|
||||
fabric {
|
||||
loader gradle.ext.fabric_loader_version
|
||||
accessWidener project.file("src/main/resources/${gradle.ext.accessWidenerVersion}.distanthorizons.accesswidener")
|
||||
}
|
||||
}
|
||||
defaultRemapJar = false
|
||||
runs.off = true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ==================== Configurations ====================
|
||||
|
||||
evaluationDependsOn(":core")
|
||||
@@ -286,7 +314,6 @@ class NativeTransformer implements ResourceTransformer {
|
||||
if (isNotCommonProject) {
|
||||
shadowJar {
|
||||
configurations = [project.configurations.shadowMe]
|
||||
relocate "com.seibel.distanthorizons.common", "loaderCommon.${project.name}.com.seibel.distanthorizons.common"
|
||||
def librariesLocation = "DistantHorizons.libraries"
|
||||
|
||||
// LZ4
|
||||
@@ -342,34 +369,103 @@ if (isNotCommonProject) {
|
||||
def loaderPaths = configurations.minecraftLibraries.resolve().collect { it.path }.toSet()
|
||||
tasks.withType(JavaExec).configureEach { runTask ->
|
||||
dependsOn(shadowJar)
|
||||
classpath = files(shadowJar.archiveFile) + classpath.filter { file ->
|
||||
!file.path.contains(project.buildDir.path) &&
|
||||
!file.path.contains("core${File.separator}build") &&
|
||||
!file.path.contains("api${File.separator}build") &&
|
||||
!file.path.contains("common${File.separator}build") &&
|
||||
!(shadowedPaths.contains(file.path) && !loaderPaths.contains(file.path))
|
||||
if (project.name != "cleanroom") {
|
||||
classpath = files(shadowJar.archiveFile) + classpath.filter { file ->
|
||||
file != shadowJar.archiveFile.get().asFile &&
|
||||
!file.path.contains(project.buildDir.path) &&
|
||||
!file.path.contains("core${File.separator}build") &&
|
||||
!file.path.contains("api${File.separator}build") &&
|
||||
!file.path.contains("common${File.separator}build") &&
|
||||
!(shadowedPaths.contains(file.path) && !loaderPaths.contains(file.path))
|
||||
}
|
||||
} else {
|
||||
// For cleanroom, don't put shadow jar on app classpath.
|
||||
// crl.dev.extrapath loads it via LaunchClassLoader instead.
|
||||
classpath = classpath.filter { file ->
|
||||
!file.path.contains(project.buildDir.path) &&
|
||||
!file.path.contains("core${File.separator}build") &&
|
||||
!file.path.contains("api${File.separator}build") &&
|
||||
!file.path.contains("common${File.separator}build") &&
|
||||
!(shadowedPaths.contains(file.path) && !loaderPaths.contains(file.path))
|
||||
}
|
||||
}
|
||||
|
||||
// Shared run directory so all loaders use the same worlds
|
||||
def isClient = runTask.name.toLowerCase().contains("client")
|
||||
runTask.workingDir = rootProject.file("run/${isClient ? 'client' : 'server'}")
|
||||
|
||||
// Minecraft automatically has G1GC args present,
|
||||
// remove them so we can use ZGC instead
|
||||
def filteredArgs = runTask.jvmArgs.findAll { arg ->
|
||||
!arg.startsWith("-XX:+UseG1GC") &&
|
||||
!arg.startsWith("-XX:G1") &&
|
||||
!arg.startsWith("-XX:MaxGCPauseMillis")
|
||||
}
|
||||
runTask.jvmArgs = filteredArgs
|
||||
|
||||
if(project.name == "forge"
|
||||
|| project.name == "neoforge"
|
||||
|| project.name == "cleanroom")
|
||||
{
|
||||
// fix (Neo)forge, Cleanroom debug running
|
||||
doFirst {
|
||||
def modsDir = rootProject.file("run/${isClient ? 'client' : 'server'}/mods")
|
||||
modsDir.mkdirs()
|
||||
|
||||
// Remove any stale DH jars before copying the fresh one
|
||||
modsDir.listFiles()?.each({ file ->
|
||||
if (file.name.startsWith(rootProject.mod_name))
|
||||
{
|
||||
file.delete()
|
||||
}
|
||||
});
|
||||
|
||||
// Copy shadow jar into mods folder so (Neo)Forge discovers it properly
|
||||
copy {
|
||||
from shadowJar.archiveFile
|
||||
into modsDir
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// JVM args
|
||||
runTask.jvmArgs(
|
||||
"-Dio.netty.leakDetection.level=advanced",
|
||||
//"-XX:+UseZGC",
|
||||
// TODO only use for modern java versions
|
||||
"-XX:+UseZGC",
|
||||
// TODO don't use for even more modern-er java versions
|
||||
//"-XX:+ZGenerational",
|
||||
rootProject.minecraftMemoryJavaArg,
|
||||
)
|
||||
if (isClient) {
|
||||
if (isClient)
|
||||
{
|
||||
runTask.jvmArgs(
|
||||
"-Dminecraft.api.auth.host=https://nope.invalid",
|
||||
"-Dminecraft.api.account.host=https://nope.invalid",
|
||||
"-Dminecraft.api.session.host=https://nope.invalid",
|
||||
"-Dminecraft.api.services.host=https://nope.invalid",
|
||||
)
|
||||
runTask.args("--username", "Dev", "--renderDebugLabels", "--tracy")
|
||||
runTask.args(
|
||||
// use a consistent username for easier debugging in a given world (vs randomly teleporting to a new user each time the game boots)
|
||||
"--username", "Dev",
|
||||
// "--renderDebugLabels" is a Mojang command to show render names in RenderDoc
|
||||
"--renderDebugLabels"
|
||||
)
|
||||
|
||||
// enabling tracy causes constant memory growth so it isn't always desired
|
||||
if (rootProject.minecraftEnableTracy == "true")
|
||||
{
|
||||
// "--tracy" is a Mojang command to allow individual frames to be debugged using Tracy https://github.com/wolfpld/tracy/releases/tag/v0.13.1
|
||||
runTask.args("--tracy")
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
tasks.downgradeJar.inputFile.set(tasks.named("remapJar").flatMap { it.archiveFile })
|
||||
tasks.jar.finalizedBy(tasks.named("remapJar"))
|
||||
tasks.named("remapJar").configure { finalizedBy(tasks.shadeDowngradedApi) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -381,6 +477,7 @@ if (isNotCommonProject) {
|
||||
def resourceTargets = [
|
||||
"build_info.json",
|
||||
"fabric.mod.json",
|
||||
"mcmod.info",
|
||||
"quilt.mod.json",
|
||||
"META-INF/mods.toml",
|
||||
"META-INF/neoforge.mods.toml",
|
||||
@@ -391,6 +488,7 @@ if (isNotCommonProject) {
|
||||
// Quilt contributors
|
||||
def quilt_contributors = []
|
||||
def mod_author_list = rootProject.mod_authors.replaceAll("\"", "").replace("[", "").replace("]", "").split(",")
|
||||
def cleanroom_author_list = rootProject.mod_authors.replace('[', '').replace(']', '').split(',').collect({ it.trim().replace('"', '') }).join('", "')
|
||||
for (dev in mod_author_list) {
|
||||
quilt_contributors.push("\"${dev.strip()}\": \"Developer\"")
|
||||
}
|
||||
@@ -408,15 +506,18 @@ if (isNotCommonProject) {
|
||||
|
||||
def replaceProperties = [
|
||||
version : rootProject.mod_version,
|
||||
mod_id : rootProject.mod_id,
|
||||
mod_name : rootProject.mod_readable_name,
|
||||
group : rootProject.maven_group,
|
||||
authors : rootProject.mod_authors,
|
||||
cleanroom_authors : cleanroom_author_list,
|
||||
description : rootProject.mod_description,
|
||||
homepage : rootProject.mod_homepage,
|
||||
source : rootProject.mod_source,
|
||||
issues : rootProject.mod_issues,
|
||||
discord : rootProject.mod_discord,
|
||||
minecraft_version : rootProject.minecraft_version,
|
||||
accessWidenerVersion : rootProject.accessWidenerVersion,
|
||||
compatible_minecraft_versions: rootProject.compatible_minecraft_versions,
|
||||
compatible_forgemc_versions : compatible_forgemc_versions,
|
||||
java_version : rootProject.java_version,
|
||||
@@ -427,6 +528,7 @@ if (isNotCommonProject) {
|
||||
fabric_incompatibility_list : rootProject.fabric_incompatibility_list,
|
||||
fabric_recommend_list : rootProject.fabric_recommend_list,
|
||||
neoforge_version_range : rootProject.neoforge_version_range,
|
||||
logo_path : "assets/distanthorizons/icon.png"
|
||||
]
|
||||
|
||||
inputs.properties replaceProperties
|
||||
@@ -437,7 +539,7 @@ if (isNotCommonProject) {
|
||||
|
||||
// Remove unused access wideners
|
||||
exclude { file ->
|
||||
if (file.name.contains(".distanthorizons.accesswidener") && file.name != "${rootProject.accessWidenerVersion}.distanthorizons.accesswidener") {
|
||||
if ((file.name.contains(".distanthorizons.accesswidener") && file.name != "${rootProject.accessWidenerVersion}.distanthorizons.accesswidener")) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
@@ -447,16 +549,35 @@ if (isNotCommonProject) {
|
||||
|
||||
// ==================== Resource Copy Tasks ====================
|
||||
|
||||
task copyCommonLoaderResources(type: Copy) {
|
||||
from project(":common").file("src/main/resources/${rootProject.accessWidenerVersion}.distanthorizons.accesswidener")
|
||||
into(file(project.file("build/resources/main")))
|
||||
rename "${rootProject.accessWidenerVersion}.distanthorizons.accesswidener", "distanthorizons.accesswidener"
|
||||
}
|
||||
// task copyCommonLoaderResources(type: Copy) {
|
||||
// from project(":common").file("src/main/resources/${rootProject.accessWidenerVersion}.distanthorizons.accesswidener")
|
||||
// into(file(project.file("build/resources/main")))
|
||||
// rename "${rootProject.accessWidenerVersion}.distanthorizons.accesswidener", "distanthorizons.accesswidener"
|
||||
// }
|
||||
|
||||
task copyCoreResources(type: Copy) {
|
||||
from fileTree(project(":core").file("src/main/resources"))
|
||||
into project.file("build/resources/main")
|
||||
}
|
||||
|
||||
tasks.register("convertJsonToLang") {
|
||||
dependsOn(copyCoreResources)
|
||||
|
||||
File input = project.file("build/resources/main/assets/distanthorizons/lang/en_us.json")
|
||||
File output = project.file("build/resources/main/assets/distanthorizons/lang/en_us.lang")
|
||||
inputs.file(input)
|
||||
outputs.file(output)
|
||||
doLast {
|
||||
output.withWriter("UTF-8") { writer ->
|
||||
writer.writeLine("#PARSE_ESCAPES")
|
||||
new JsonSlurper()
|
||||
.parse(input)
|
||||
.each { key, value ->
|
||||
writer.writeLine("${key}=${value.toString().replace("%", "%%").replace("\n", "\\n")}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ==================== JVMDowngrader ====================
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
plugins {
|
||||
id 'dh-loader'
|
||||
}
|
||||
|
||||
unimined.minecraft {
|
||||
cleanroom {
|
||||
loader gradle.ext.cleanroom_loader_version
|
||||
useToolchains = false
|
||||
accessTransformer project(":common").file("src/main/resources/${gradle.ext.accessWidenerVersion}.distanthorizons_at.cfg")
|
||||
runs.all {
|
||||
systemProperty("crl.dev.mixin", "${mod_id}.default.mixin.json,${mod_id}.mod.mixin.json")
|
||||
systemProperty("fml.coreMods.load", "com.seibel.distanthorizons.cleanroom.DistantHorizonsLoadingPlugin")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
@echo off & setlocal enabledelayedexpansion
|
||||
|
||||
set "VERSION=%~1"
|
||||
set "ROOT=%~2"
|
||||
set "WORK_DIR=%~3"
|
||||
set "WORKER=%WORK_DIR%\%VERSION%"
|
||||
set "JAR_OUTPUT_DIR=%~4"
|
||||
|
||||
REM remove the ending "\" from the root folder, otherwise the final quote
|
||||
REM in the robocopy command will be escaped and it won't run
|
||||
if "%ROOT:~-1%"=="\" set "ROOT=%ROOT:~0,-1%"
|
||||
set "WORKER=%~3\%~1"
|
||||
|
||||
set "BUILT_JAR_DIR=%WORKER%\build\forgix"
|
||||
|
||||
|
||||
|
||||
echo ==================== [%VERSION%] Copying workspace ====================
|
||||
mkdir "%WORKER%"
|
||||
robocopy "%ROOT%" "%WORKER%" /E /XD "%WORKER%" "_buildWorkers" "buildAllJars" ".gradle" "build" ".git" ".idea" ".gitlab" "run" "testScripts" /NFL /NDL
|
||||
|
||||
echo ==================== [%VERSION%] Cleaning ====================
|
||||
cd /d "%WORKER%"
|
||||
call .\gradlew.bat clean
|
||||
REM optional arg that can be added if we want to log the result to a file
|
||||
REM >"%WORK_DIR%\build_%VERSION%.log" 2>&1
|
||||
|
||||
echo ==================== [%VERSION%] Assembling ====================
|
||||
call .\gradlew.bat assemble -PmcVer="%VERSION%"
|
||||
REM optional arg that can be added if we want to log the result to a file
|
||||
REM >>"%WORK_DIR%\build_%VERSION%.log" 2>&1
|
||||
|
||||
echo ==================== [%VERSION%] Exporting ====================
|
||||
mkdir "%JAR_OUTPUT_DIR%"
|
||||
robocopy "%BUILT_JAR_DIR%" "%JAR_OUTPUT_DIR%" /NFL /NDL
|
||||
|
||||
echo ==================== [%VERSION%] Done ====================
|
||||
endlocal
|
||||
|
||||
REM can be uncommented for debugging
|
||||
REM pause
|
||||
@@ -0,0 +1,48 @@
|
||||
plugins {
|
||||
id 'unimined-cleanroom'
|
||||
}
|
||||
|
||||
|
||||
// ==================== Mod Dependency Helper ====================
|
||||
|
||||
def addMod(path, enabled) {
|
||||
if (enabled == "2")
|
||||
dependencies { modImplementation(path) }
|
||||
else if (enabled == "1")
|
||||
dependencies { compileOnly(path) }
|
||||
}
|
||||
|
||||
|
||||
// ==================== Dependencies ====================
|
||||
|
||||
dependencies {
|
||||
|
||||
}
|
||||
|
||||
|
||||
// ==================== Tasks ====================
|
||||
|
||||
task deleteResources(type: Delete) {
|
||||
delete file("build/resources/main")
|
||||
}
|
||||
|
||||
processResources {
|
||||
rename '(.+_at.cfg)', 'META-INF/$1'
|
||||
dependsOn(copyCoreResources)
|
||||
dependsOn(convertJsonToLang)
|
||||
// dependsOn(copyCommonLoaderResources)
|
||||
}
|
||||
|
||||
tasks.named('runClient') {
|
||||
dependsOn(copyCoreResources)
|
||||
// dependsOn(copyCommonLoaderResources)
|
||||
finalizedBy(deleteResources)
|
||||
}
|
||||
|
||||
sourcesJar {
|
||||
def commonSources = project(":common").sourcesJar
|
||||
dependsOn commonSources
|
||||
from commonSources.archiveFile.map { zipTree(it) }
|
||||
}
|
||||
|
||||
|
||||
+214
@@ -0,0 +1,214 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizons mod
|
||||
* licensed under the GNU LGPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020 James Seibel
|
||||
*
|
||||
* This program 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, version 3.
|
||||
*
|
||||
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.distanthorizons.cleanroom;
|
||||
|
||||
import com.seibel.distanthorizons.common.AbstractModInitializer;
|
||||
import com.seibel.distanthorizons.common.util.ProxyUtil;
|
||||
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
|
||||
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftRenderWrapper;
|
||||
import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper;
|
||||
import com.seibel.distanthorizons.core.api.internal.ClientApi;
|
||||
import com.seibel.distanthorizons.core.api.internal.ServerApi;
|
||||
import com.seibel.distanthorizons.core.api.internal.SharedApi;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.logging.f3.F3Screen;
|
||||
import com.seibel.distanthorizons.core.network.messages.AbstractNetworkMessage;
|
||||
import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IPluginPacketSender;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IServerPlayerWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.WorldClient;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import net.minecraftforge.client.event.RenderGameOverlayEvent;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.event.entity.player.PlayerInteractEvent;
|
||||
import net.minecraftforge.event.world.ChunkEvent;
|
||||
import net.minecraftforge.event.world.WorldEvent;
|
||||
import net.minecraftforge.fml.common.FMLCommonHandler;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.gameevent.InputEvent;
|
||||
import net.minecraftforge.fml.common.gameevent.TickEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
|
||||
import java.util.concurrent.AbstractExecutorService;
|
||||
|
||||
public class CleanroomClientProxy implements AbstractModInitializer.IEventProxy
|
||||
{
|
||||
private static final IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
|
||||
private static final CleanroomPluginPacketSender PACKET_SENDER = (CleanroomPluginPacketSender) SingletonInjector.INSTANCE.get(IPluginPacketSender.class);
|
||||
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||
|
||||
private static World GetEventLevel(WorldEvent e) { return e.getWorld(); }
|
||||
|
||||
|
||||
@Override
|
||||
public void registerEvents()
|
||||
{
|
||||
MinecraftForge.EVENT_BUS.register(this);
|
||||
MinecraftForge.EVENT_BUS.register(FMLCommonHandler.instance());
|
||||
CleanroomPluginPacketSender.setPacketHandler(ClientApi.INSTANCE::pluginMessageReceived);
|
||||
}
|
||||
|
||||
|
||||
//==============//
|
||||
// chunk events //
|
||||
//==============//
|
||||
//region
|
||||
|
||||
@SubscribeEvent
|
||||
public void rightClickBlockEvent(PlayerInteractEvent.RightClickBlock event)
|
||||
{
|
||||
if (MC.clientConnectedToDedicatedServer())
|
||||
{
|
||||
World level = event.getWorld();
|
||||
|
||||
ILevelWrapper wrappedLevel = ProxyUtil.getLevelWrapper(level);
|
||||
if (SharedApi.isChunkAtBlockPosAlreadyUpdating(wrappedLevel, event.getPos().getX(), event.getPos().getZ()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AbstractExecutorService executor = ThreadPoolUtil.getFileHandlerExecutor();
|
||||
if (executor != null)
|
||||
{
|
||||
executor.execute(() ->
|
||||
{
|
||||
Chunk chunk = level.getChunk(event.getPos());
|
||||
SharedApi.INSTANCE.applyChunkUpdate(new ChunkWrapper(chunk, wrappedLevel), wrappedLevel);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@SubscribeEvent
|
||||
public void leftClickBlockEvent(PlayerInteractEvent.LeftClickBlock event)
|
||||
{
|
||||
if (MC.clientConnectedToDedicatedServer())
|
||||
{
|
||||
World level = event.getWorld();
|
||||
|
||||
ILevelWrapper wrappedLevel = ProxyUtil.getLevelWrapper(level);
|
||||
if (SharedApi.isChunkAtBlockPosAlreadyUpdating(wrappedLevel, event.getPos().getX(), event.getPos().getZ()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AbstractExecutorService executor = ThreadPoolUtil.getFileHandlerExecutor();
|
||||
if (executor != null)
|
||||
{
|
||||
executor.execute(() ->
|
||||
{
|
||||
Chunk chunk = level.getChunk(event.getPos());
|
||||
SharedApi.INSTANCE.applyChunkUpdate(new ChunkWrapper(chunk, wrappedLevel), wrappedLevel);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void clientChunkLoadEvent(ChunkEvent.Load event)
|
||||
{
|
||||
if (MC.clientConnectedToDedicatedServer())
|
||||
{
|
||||
ILevelWrapper wrappedLevel = ProxyUtil.getLevelWrapper(GetEventLevel(event));
|
||||
IChunkWrapper chunkWrapper = new ChunkWrapper(event.getChunk(), wrappedLevel);
|
||||
SharedApi.INSTANCE.applyChunkUpdate(chunkWrapper, wrappedLevel);
|
||||
}
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//==============//
|
||||
// key bindings //
|
||||
//==============//
|
||||
//region
|
||||
|
||||
@SubscribeEvent
|
||||
public void registerKeyBindings(InputEvent.KeyInputEvent event)
|
||||
{
|
||||
/* if (Minecraft.getMinecraft().player == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (event.getAction() != GLFW.GLFW_PRESS)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ClientApi.INSTANCE.keyPressedEvent(event.getKey());*/
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//===========//
|
||||
// rendering //
|
||||
//===========//
|
||||
//region
|
||||
|
||||
@SubscribeEvent
|
||||
public void afterLevelRenderEvent(TickEvent.RenderTickEvent event)
|
||||
{
|
||||
if (event.type.equals(TickEvent.RenderTickEvent.Type.RENDER))
|
||||
{
|
||||
try
|
||||
{
|
||||
// should generally only need to be set once per game session
|
||||
// allows DH to render directly to Optifine's level frame buffer,
|
||||
// allowing better shader support
|
||||
MinecraftRenderWrapper.INSTANCE.finalLevelFrameBufferId = GL32.glGetInteger(GL32.GL_FRAMEBUFFER_BINDING);
|
||||
}
|
||||
catch (Exception | Error e)
|
||||
{
|
||||
LOGGER.error("Unexpected error in afterLevelRenderEvent: "+e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void onRenderOverlay(RenderGameOverlayEvent.Text event)
|
||||
{
|
||||
Minecraft mc = Minecraft.getMinecraft();
|
||||
if (event.isCanceled()
|
||||
|| !mc.gameSettings.showDebugInfo)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
F3Screen.addStringToDisplay(event.getRight());
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizons mod
|
||||
* licensed under the GNU LGPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020 James Seibel
|
||||
*
|
||||
* This program 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, version 3.
|
||||
*
|
||||
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.distanthorizons.cleanroom;
|
||||
|
||||
import com.seibel.distanthorizons.cleanroom.modAccessor.ModChecker;
|
||||
import com.seibel.distanthorizons.common.AbstractModInitializer;
|
||||
import com.seibel.distanthorizons.common.commands.CommandInitializer;
|
||||
import com.seibel.distanthorizons.common.wrappers.worldGeneration.InternalServerGenerator;
|
||||
import com.seibel.distanthorizons.core.api.internal.ServerApi;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IPluginPacketSender;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IModChecker;
|
||||
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.ForgeChunkManager;
|
||||
import net.minecraftforge.fml.common.FMLCommonHandler;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.common.event.*;
|
||||
import org.apache.logging.log4j.Level;
|
||||
import org.apache.logging.log4j.core.config.Configurator;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* Initialize and setup the Mod. <br>
|
||||
* If you are looking for the real start of the mod
|
||||
* check out the ClientProxy.
|
||||
*/
|
||||
@Mod(modid = ModInfo.ID, name = ModInfo.NAME, version = ModInfo.VERSION)
|
||||
public class CleanroomMain extends AbstractModInitializer
|
||||
{
|
||||
@Mod.Instance
|
||||
public static CleanroomMain instance;
|
||||
|
||||
@Mod.EventHandler
|
||||
public void preinit(FMLPreInitializationEvent event)
|
||||
{
|
||||
Configurator.setLevel("org.sqlite", Level.INFO);
|
||||
ForgeChunkManager.setForcedChunkLoadingCallback(CleanroomMain.instance, (tickets, world) -> { });
|
||||
}
|
||||
|
||||
@Mod.EventHandler
|
||||
public void init(FMLInitializationEvent event)
|
||||
{
|
||||
if (FMLCommonHandler.instance().getEffectiveSide().isClient())
|
||||
{
|
||||
this.onInitializeClient();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.onInitializeServer();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createInitialSharedBindings()
|
||||
{
|
||||
SingletonInjector.INSTANCE.bind(IModChecker.class, ModChecker.INSTANCE);
|
||||
SingletonInjector.INSTANCE.bind(IPluginPacketSender.class, new CleanroomPluginPacketSender());
|
||||
}
|
||||
@Override
|
||||
protected void createInitialClientBindings() { /* no additional setup needed currently */ }
|
||||
|
||||
@Override
|
||||
protected IEventProxy createClientProxy() { return new CleanroomClientProxy(); }
|
||||
|
||||
@Override
|
||||
protected IEventProxy createServerProxy(boolean isDedicated) { return new CleanroomServerProxy(isDedicated); }
|
||||
|
||||
@Override
|
||||
protected void initializeModCompat()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/* @Override
|
||||
protected void subscribeRegisterCommandsEvent(Consumer<CommandDispatcher<CommandSourceStack>> eventHandler)
|
||||
{ MinecraftForge.EVENT_BUS.addListener((RegisterCommandsEvent e) -> { eventHandler.accept(e.getDispatcher()); }); }*/
|
||||
|
||||
@Override
|
||||
protected void subscribeClientStartedEvent(Runnable eventHandler)
|
||||
{
|
||||
// Just run the event handler, since there are no proper ClientLifecycleEvent for the client
|
||||
// to signify readiness other than FmlClientSetupEvent
|
||||
eventHandler.run();
|
||||
}
|
||||
|
||||
@Mod.EventHandler
|
||||
public void onServerStarting(FMLServerStartingEvent event)
|
||||
{
|
||||
event.registerServerCommand(CommandInitializer.initCommands());
|
||||
}
|
||||
|
||||
@Mod.EventHandler
|
||||
public void onServerAboutToStart(FMLServerAboutToStartEvent event)
|
||||
{
|
||||
if (eventHandlerStartServer != null)
|
||||
{
|
||||
eventHandlerStartServer.accept(event.getServer());
|
||||
}
|
||||
}
|
||||
|
||||
Consumer<MinecraftServer> eventHandlerStartServer;
|
||||
|
||||
@Override
|
||||
protected void subscribeServerStartingEvent(Consumer<MinecraftServer> eventHandler)
|
||||
{
|
||||
eventHandlerStartServer = eventHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void runDelayedSetup() { SingletonInjector.INSTANCE.runDelayedSetup(); }
|
||||
|
||||
// ServerWorldLoadEvent
|
||||
@Mod.EventHandler
|
||||
public void dedicatedWorldLoadEvent(FMLServerAboutToStartEvent event)
|
||||
{
|
||||
ServerApi.INSTANCE.serverLoadEvent(event.getServer().isDedicatedServer());
|
||||
}
|
||||
|
||||
// ServerWorldUnloadEvent
|
||||
@Mod.EventHandler
|
||||
public void serverWorldUnloadEvent(FMLServerStoppingEvent event)
|
||||
{
|
||||
ServerApi.INSTANCE.serverUnloadEvent();
|
||||
}
|
||||
}
|
||||
+136
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizons mod
|
||||
* licensed under the GNU LGPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020 James Seibel
|
||||
*
|
||||
* This program 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, version 3.
|
||||
*
|
||||
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.distanthorizons.cleanroom;
|
||||
|
||||
import com.seibel.distanthorizons.common.AbstractPluginPacketSender;
|
||||
import com.seibel.distanthorizons.common.wrappers.misc.ServerPlayerWrapper;
|
||||
import com.seibel.distanthorizons.core.network.messages.AbstractNetworkMessage;
|
||||
import com.seibel.distanthorizons.core.network.messages.MessageRegistry;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IServerPlayerWrapper;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraftforge.fml.common.network.NetworkRegistry;
|
||||
import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
|
||||
import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler;
|
||||
import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
|
||||
import net.minecraftforge.fml.common.network.simpleimpl.SimpleNetworkWrapper;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class CleanroomPluginPacketSender extends AbstractPluginPacketSender
|
||||
{
|
||||
public static final SimpleNetworkWrapper PLUGIN_CHANNEL =
|
||||
NetworkRegistry.INSTANCE.newSimpleChannel(
|
||||
AbstractPluginPacketSender.WRAPPER_PACKET_RESOURCE
|
||||
);
|
||||
|
||||
|
||||
|
||||
public static void setPacketHandler(Consumer<AbstractNetworkMessage> consumer)
|
||||
{ setPacketHandler((player, message) -> consumer.accept(message)); }
|
||||
static BiConsumer<IServerPlayerWrapper, AbstractNetworkMessage> consumerPacket;
|
||||
public static void setPacketHandler(BiConsumer<IServerPlayerWrapper, AbstractNetworkMessage> consumer)
|
||||
{
|
||||
PLUGIN_CHANNEL.registerMessage(MessageWrapper.Handler.class, MessageWrapper.class, 0, Side.CLIENT);
|
||||
PLUGIN_CHANNEL.registerMessage(MessageWrapper.Handler.class, MessageWrapper.class, 0, Side.SERVER);
|
||||
consumerPacket = consumer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendToServer(AbstractNetworkMessage message)
|
||||
{ PLUGIN_CHANNEL.sendToServer(new MessageWrapper(message)); }
|
||||
|
||||
@Override
|
||||
public void sendToClient(EntityPlayerMP serverPlayer, AbstractNetworkMessage message)
|
||||
{ PLUGIN_CHANNEL.sendTo(new MessageWrapper(message), serverPlayer); }
|
||||
|
||||
|
||||
|
||||
//================//
|
||||
// helper classes //
|
||||
//================//
|
||||
//region
|
||||
|
||||
// Forge doesn't support using abstract classes
|
||||
@SuppressWarnings({"ClassCanBeRecord", "RedundantSuppression"})
|
||||
public static class MessageWrapper implements IMessage
|
||||
{
|
||||
public AbstractNetworkMessage message;
|
||||
|
||||
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
//region
|
||||
|
||||
public MessageWrapper(AbstractNetworkMessage message) { this.message = message; }
|
||||
|
||||
public MessageWrapper()
|
||||
{
|
||||
// For reflection
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
@Override
|
||||
public void fromBytes(ByteBuf buf)
|
||||
{
|
||||
int messageId = buf.readByte();
|
||||
message = MessageRegistry.INSTANCE.createMessage(messageId);
|
||||
message.decode(buf);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toBytes(ByteBuf buf)
|
||||
{
|
||||
buf.writeByte(MessageRegistry.INSTANCE.getMessageId(message));
|
||||
message.encode(buf);
|
||||
}
|
||||
|
||||
public static class Handler implements IMessageHandler<MessageWrapper, IMessage>
|
||||
{
|
||||
@Override
|
||||
public IMessage onMessage(MessageWrapper wrapper, MessageContext context)
|
||||
{
|
||||
if (wrapper.message != null)
|
||||
{
|
||||
if (context.side == Side.SERVER)
|
||||
{
|
||||
consumerPacket.accept(ServerPlayerWrapper.getWrapper(context.getServerHandler().player), wrapper.message);
|
||||
}
|
||||
else
|
||||
{
|
||||
consumerPacket.accept(null, wrapper.message);
|
||||
}
|
||||
}
|
||||
|
||||
return null; // No response needed
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
}
|
||||
+181
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizons mod
|
||||
* licensed under the GNU LGPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020 James Seibel
|
||||
*
|
||||
* This program 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, version 3.
|
||||
*
|
||||
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.distanthorizons.cleanroom;
|
||||
|
||||
import com.seibel.distanthorizons.common.AbstractModInitializer;
|
||||
import com.seibel.distanthorizons.common.commands.CommandInitializer;
|
||||
import com.seibel.distanthorizons.common.commonMixins.MixinChunkMapCommon;
|
||||
import com.seibel.distanthorizons.common.util.ProxyUtil;
|
||||
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
|
||||
import com.seibel.distanthorizons.common.wrappers.misc.ServerPlayerWrapper;
|
||||
import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper;
|
||||
import com.seibel.distanthorizons.common.wrappers.worldGeneration.InternalServerGenerator;
|
||||
import com.seibel.distanthorizons.core.api.internal.ServerApi;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IPluginPacketSender;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.WorldServer;
|
||||
import net.minecraftforge.common.ForgeChunkManager;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.event.world.ChunkDataEvent;
|
||||
import net.minecraftforge.event.world.ChunkEvent;
|
||||
import net.minecraftforge.event.world.WorldEvent;
|
||||
import net.minecraftforge.fml.common.FMLCommonHandler;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.common.event.FMLServerAboutToStartEvent;
|
||||
import net.minecraftforge.fml.common.event.FMLServerStartingEvent;
|
||||
import net.minecraftforge.fml.common.event.FMLServerStoppingEvent;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.gameevent.PlayerEvent;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import static com.seibel.distanthorizons.cleanroom.CleanroomMain.instance;
|
||||
|
||||
public class CleanroomServerProxy implements AbstractModInitializer.IEventProxy
|
||||
{
|
||||
private static final CleanroomPluginPacketSender PACKET_SENDER = (CleanroomPluginPacketSender) SingletonInjector.INSTANCE.get(IPluginPacketSender.class);
|
||||
private static World GetEventLevel(WorldEvent e) { return e.getWorld(); }
|
||||
|
||||
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||
private final ServerApi serverApi = ServerApi.INSTANCE;
|
||||
private final boolean isDedicated;
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void registerEvents()
|
||||
{
|
||||
MinecraftForge.EVENT_BUS.register(this);
|
||||
FMLCommonHandler.instance().bus().register(this);
|
||||
if (this.isDedicated)
|
||||
{
|
||||
PACKET_SENDER.setPacketHandler(ServerApi.INSTANCE::pluginMessageReceived);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
//region
|
||||
|
||||
public CleanroomServerProxy(boolean isDedicated) { this.isDedicated = isDedicated; }
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//========//
|
||||
// events //
|
||||
//========//
|
||||
//region
|
||||
|
||||
// ServerLevelLoadEvent
|
||||
@SubscribeEvent
|
||||
public void serverLevelLoadEvent(WorldEvent.Load event)
|
||||
{
|
||||
if (GetEventLevel(event) instanceof WorldServer)
|
||||
{
|
||||
this.serverApi.serverLevelLoadEvent(getServerLevelWrapper((WorldServer) GetEventLevel(event)));
|
||||
}
|
||||
}
|
||||
|
||||
// ServerLevelUnloadEvent
|
||||
@SubscribeEvent
|
||||
public void serverLevelUnloadEvent(WorldEvent.Unload event)
|
||||
{
|
||||
if (GetEventLevel(event) instanceof WorldServer)
|
||||
{
|
||||
this.serverApi.serverLevelUnloadEvent(getServerLevelWrapper((WorldServer) GetEventLevel(event)));
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void serverChunkLoadEvent(ChunkEvent.Load event)
|
||||
{
|
||||
ILevelWrapper levelWrapper = ProxyUtil.getLevelWrapper(GetEventLevel(event));
|
||||
IChunkWrapper chunk = new ChunkWrapper(event.getChunk(), levelWrapper);
|
||||
this.serverApi.serverChunkLoadEvent(chunk, levelWrapper);
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void serverChunkSaveEvent(ChunkDataEvent.Save event)
|
||||
{
|
||||
if (event.getWorld() instanceof WorldServer worldServer)
|
||||
{
|
||||
MixinChunkMapCommon.onChunkSave(worldServer, event.getChunk());
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void playerLoggedInEvent(PlayerEvent.PlayerLoggedInEvent event)
|
||||
{ this.serverApi.serverPlayerJoinEvent(getServerPlayerWrapper(event)); }
|
||||
|
||||
@SubscribeEvent
|
||||
public void playerLoggedOutEvent(PlayerEvent.PlayerLoggedOutEvent event)
|
||||
{ this.serverApi.serverPlayerDisconnectEvent(getServerPlayerWrapper(event)); }
|
||||
|
||||
@SubscribeEvent
|
||||
public void playerChangedDimensionEvent(PlayerEvent.PlayerChangedDimensionEvent event)
|
||||
{
|
||||
this.serverApi.serverPlayerLevelChangeEvent(
|
||||
getServerPlayerWrapper(event),
|
||||
getServerLevelWrapper(event.fromDim, event),
|
||||
getServerLevelWrapper(event.toDim, event)
|
||||
);
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//================//
|
||||
// helper methods //
|
||||
//================//
|
||||
//region
|
||||
|
||||
private static ServerLevelWrapper getServerLevelWrapper(WorldServer level) { return ServerLevelWrapper.getWrapper(level); }
|
||||
|
||||
private static ServerLevelWrapper getServerLevelWrapper(int dimensionId, PlayerEvent event)
|
||||
{
|
||||
MinecraftServer server = event.player.getServer();
|
||||
if (server == null)
|
||||
{
|
||||
LOGGER.error("getServerLevelWrapper: server is null for player {}", event.player.getName());
|
||||
return null;
|
||||
}
|
||||
return getServerLevelWrapper(server.getWorld(dimensionId));
|
||||
}
|
||||
|
||||
private static ServerPlayerWrapper getServerPlayerWrapper(PlayerEvent event)
|
||||
{ return ServerPlayerWrapper.getWrapper((EntityPlayerMP) event.player); }
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizons mod
|
||||
* licensed under the GNU LGPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020 James Seibel
|
||||
*
|
||||
* This program 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, version 3.
|
||||
*
|
||||
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.distanthorizons.cleanroom;
|
||||
|
||||
import net.minecraftforge.fml.common.Loader;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
|
||||
import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class DistantHorizonsConfigPlugin implements IMixinConfigPlugin
|
||||
{
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
|
||||
@Override
|
||||
public void onLoad(String mixinPackage)
|
||||
{ }
|
||||
|
||||
@Override
|
||||
public boolean shouldApplyMixin(String targetClassName, String mixinClassName)
|
||||
{
|
||||
/* return switch (mixinClassName.split("\\.")[5]) {
|
||||
case "mist" -> Loader.isModLoaded("mist");
|
||||
default -> true;
|
||||
};*/
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override public String getRefMapperConfig() { return null; }
|
||||
@Override public void acceptTargets(Set<String> myTargets, Set<String> otherTargets) { }
|
||||
@Override public List<String> getMixins() { return null; }
|
||||
@Override public void preApply(String targetClassName, ClassNode classNode, String mixinClassName, IMixinInfo mixinInfo) { }
|
||||
@Override public void postApply(String targetClassName, ClassNode classNode, String mixinClassName, IMixinInfo mixinInfo) { }
|
||||
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizons mod
|
||||
* licensed under the GNU LGPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020 James Seibel
|
||||
*
|
||||
* This program 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, version 3.
|
||||
*
|
||||
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.distanthorizons.cleanroom;
|
||||
|
||||
import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class DistantHorizonsLoadingPlugin implements IFMLLoadingPlugin
|
||||
{
|
||||
@Override
|
||||
public @Nullable String[] getASMTransformerClass()
|
||||
{
|
||||
return new String[0];
|
||||
}
|
||||
@Override
|
||||
public @Nullable String getModContainerClass()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@Override
|
||||
public @Nullable String getSetupClass()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@Override
|
||||
public void injectData(Map<String, Object> data) { }
|
||||
@Override
|
||||
public @Nullable String getAccessTransformerClass()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizons mod
|
||||
* licensed under the GNU LGPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020 James Seibel
|
||||
*
|
||||
* This program 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, version 3.
|
||||
*
|
||||
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.distanthorizons.cleanroom.mixins.client;
|
||||
|
||||
import com.seibel.distanthorizons.common.commonMixins.MixinVanillaFogCommon;
|
||||
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftRenderWrapper;
|
||||
import com.seibel.distanthorizons.core.api.internal.ClientApi;
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.EntityRenderer;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
import net.minecraft.client.renderer.texture.DynamicTexture;
|
||||
import net.minecraft.init.MobEffects;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(EntityRenderer.class)
|
||||
public class MixinEntityRenderer
|
||||
{
|
||||
@Shadow
|
||||
@Final
|
||||
private DynamicTexture lightmapTexture;
|
||||
|
||||
@Shadow @Final private Minecraft mc;
|
||||
@Shadow @Final private static Logger LOGGER;
|
||||
private static final float A_REALLY_REALLY_BIG_VALUE = 420694206942069.F;
|
||||
private static final float A_EVEN_LARGER_VALUE = 42069420694206942069.F;
|
||||
|
||||
@Inject(at = @At("TAIL"), method = "updateLightmap")
|
||||
public void onUpdateLightmap(float patrialTicks, CallbackInfo ci)
|
||||
{
|
||||
IMinecraftClientWrapper mc = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
|
||||
if (mc == null || mc.getWrappedClientLevel() == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
MinecraftRenderWrapper renderWrapper = (MinecraftRenderWrapper)SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
|
||||
renderWrapper.setLightmapId(lightmapTexture.getGlTextureId());
|
||||
}
|
||||
|
||||
@Inject(at = @At("RETURN"), method = "setupFog")
|
||||
private void disableSetupFog(int startCoords, float partialTicks, CallbackInfo ci)
|
||||
{
|
||||
boolean cancelFog = MixinVanillaFogCommon.cancelFog(startCoords, mc);
|
||||
if (cancelFog)
|
||||
{
|
||||
GlStateManager.setFogStart(A_REALLY_REALLY_BIG_VALUE);
|
||||
GlStateManager.setFogEnd(A_EVEN_LARGER_VALUE);
|
||||
ClientApi.RENDER_STATE.vanillaFogEnabled = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
ClientApi.RENDER_STATE.vanillaFogEnabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizons mod
|
||||
* licensed under the GNU LGPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020 James Seibel
|
||||
*
|
||||
* This program 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, version 3.
|
||||
*
|
||||
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.distanthorizons.cleanroom.mixins.client;
|
||||
|
||||
import com.seibel.distanthorizons.core.api.internal.ClientApi;
|
||||
import net.minecraft.client.network.NetHandlerPlayClient;
|
||||
import net.minecraft.network.play.server.SPacketJoinGame;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(NetHandlerPlayClient.class)
|
||||
public class MixinNetHandlerPlayClient
|
||||
{
|
||||
@Inject(method = "handleJoinGame", at = @At("RETURN"))
|
||||
private void onHandleJoinGameEnd(SPacketJoinGame packet, CallbackInfo ci)
|
||||
{
|
||||
ClientApi.INSTANCE.onClientOnlyConnected();
|
||||
}
|
||||
|
||||
@Inject(method = "onDisconnect", at = @At("RETURN"))
|
||||
private void onDisconnect(ITextComponent reason, CallbackInfo ci)
|
||||
{
|
||||
ClientApi.INSTANCE.onClientOnlyDisconnected();
|
||||
}
|
||||
|
||||
}
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizons mod
|
||||
* licensed under the GNU LGPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020 James Seibel
|
||||
*
|
||||
* This program 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, version 3.
|
||||
*
|
||||
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.distanthorizons.cleanroom.mixins.client;
|
||||
|
||||
import com.seibel.distanthorizons.common.wrappers.gui.GetConfigScreen;
|
||||
import com.seibel.distanthorizons.common.wrappers.gui.TexturedButtonWidget;
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.GuiOptions;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
/**
|
||||
* Adds a button to the menu to goto the config
|
||||
*
|
||||
* @author coolGi
|
||||
* @version 12-02-2021
|
||||
*/
|
||||
@Mixin(GuiOptions.class)
|
||||
public class MixinOptionsScreen extends GuiScreen
|
||||
{
|
||||
// Get the texture for the button
|
||||
@Unique private static final ResourceLocation ICON_TEXTURE = new ResourceLocation(ModInfo.ID, "textures/gui/button.png");
|
||||
|
||||
@Unique private static final int button_id = 99;
|
||||
|
||||
@Inject(at = @At("HEAD"), method = "initGui")
|
||||
private void lodconfig$init(CallbackInfo ci)
|
||||
{
|
||||
if (Config.Client.showDhOptionsButtonInMinecraftUi.get())
|
||||
this.buttonList.add(
|
||||
(new TexturedButtonWidget(
|
||||
button_id,
|
||||
// Where the button is on the screen
|
||||
this.width / 2 - 180, this.height / 6 - 12,
|
||||
// Width and height of the button
|
||||
20, 20,
|
||||
// Offset
|
||||
0, 0,
|
||||
// Some textuary stuff
|
||||
20, ICON_TEXTURE, 20, 40,
|
||||
// Create the button and tell it where to go
|
||||
// For now it goes to the client option by default
|
||||
// Add a title to the button
|
||||
ModInfo.ID + ".title")));
|
||||
|
||||
}
|
||||
|
||||
@Inject(at = @At("HEAD"), method = "actionPerformed", cancellable = true)
|
||||
private void lodconfig$actionPerformed(GuiButton button, CallbackInfo ci)
|
||||
{
|
||||
if (button.id == button_id)
|
||||
{
|
||||
Minecraft.getMinecraft().displayGuiScreen(GetConfigScreen.getScreen(this));
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizons mod
|
||||
* licensed under the GNU LGPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020 James Seibel
|
||||
*
|
||||
* This program 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, version 3.
|
||||
*
|
||||
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.distanthorizons.cleanroom.mixins.client;
|
||||
|
||||
import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper;
|
||||
import com.seibel.distanthorizons.core.api.internal.ClientApi;
|
||||
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
||||
import net.minecraft.client.multiplayer.WorldClient;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
import net.minecraft.client.renderer.RenderGlobal;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.util.BlockRenderLayer;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL15;
|
||||
import org.lwjgl.opengl.GL20;
|
||||
import org.lwjgl.opengl.GL30;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
@Mixin(RenderGlobal.class)
|
||||
public class MixinRenderGlobal
|
||||
{
|
||||
@Shadow private WorldClient world;
|
||||
|
||||
@Inject(method = "renderBlockLayer(Lnet/minecraft/util/BlockRenderLayer;DILnet/minecraft/entity/Entity;)I", at = @At("HEAD"))
|
||||
private void renderChunkLayer(BlockRenderLayer blockLayerIn, double partialTicks, int pass, Entity entityIn, CallbackInfoReturnable<Integer> cir)
|
||||
{
|
||||
if (blockLayerIn == BlockRenderLayer.SOLID)
|
||||
{
|
||||
float[] mcProjMatrixRaw = new float[16];
|
||||
GL11.glGetFloatv(GL11.GL_PROJECTION_MATRIX, mcProjMatrixRaw);
|
||||
ClientApi.RENDER_STATE.mcProjectionMatrix = new Mat4f(mcProjMatrixRaw);
|
||||
ClientApi.RENDER_STATE.mcProjectionMatrix.transpose();
|
||||
|
||||
float[] mcModelViewRaw = new float[16];
|
||||
GL11.glGetFloatv(GL11.GL_MODELVIEW_MATRIX, mcModelViewRaw);
|
||||
ClientApi.RENDER_STATE.mcModelViewMatrix = new Mat4f(mcModelViewRaw);
|
||||
ClientApi.RENDER_STATE.mcModelViewMatrix.transpose();
|
||||
|
||||
ClientApi.RENDER_STATE.partialTickTime = (float) partialTicks;
|
||||
ClientApi.RENDER_STATE.clientLevelWrapper = ClientLevelWrapper.getWrapperIfDifferent(ClientApi.RENDER_STATE.clientLevelWrapper, this.world);
|
||||
|
||||
int blendSrc = GL11.glGetInteger(GL11.GL_BLEND_SRC);
|
||||
int blendDst = GL11.glGetInteger(GL11.GL_BLEND_DST);
|
||||
int boundTexture = GL11.glGetInteger(GL11.GL_TEXTURE_BINDING_2D);
|
||||
|
||||
ClientApi.INSTANCE.renderLods();
|
||||
|
||||
GL30.glBindVertexArray(0);
|
||||
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
GL20.glUseProgram(0);
|
||||
|
||||
//Restore vanilla states
|
||||
GlStateManager.depthFunc(GL11.GL_LEQUAL);
|
||||
GlStateManager.bindTexture(boundTexture);
|
||||
GlStateManager.tryBlendFuncSeparate(blendSrc, blendDst, GL11.GL_ONE, GL11.GL_ZERO);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizons mod
|
||||
* licensed under the GNU LGPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020 James Seibel
|
||||
*
|
||||
* This program 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, version 3.
|
||||
*
|
||||
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.distanthorizons.cleanroom.mixins.server;
|
||||
|
||||
import com.seibel.distanthorizons.common.wrappers.misc.IMixinServerPlayer;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.world.WorldServer;
|
||||
import net.minecraftforge.common.util.ITeleporter;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
@Mixin(EntityPlayerMP.class)
|
||||
public abstract class MixinEntityPlayerMP implements IMixinServerPlayer
|
||||
{
|
||||
@Shadow
|
||||
@Final
|
||||
public MinecraftServer server;
|
||||
|
||||
@Unique
|
||||
@Nullable
|
||||
private volatile WorldServer distantHorizons$dimensionChangeDestination;
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public WorldServer distantHorizons$getDimensionChangeDestination()
|
||||
{ return this.distantHorizons$dimensionChangeDestination; }
|
||||
|
||||
@Inject(at = @At("HEAD"), method = "changeDimension(ILnet/minecraftforge/common/util/ITeleporter;)Lnet/minecraft/entity/Entity;")
|
||||
public void setDimensionChangeDestination(int destinationDimensionID, ITeleporter teleporter, CallbackInfoReturnable<Entity> cir)
|
||||
{ this.distantHorizons$dimensionChangeDestination = this.server.getWorld(destinationDimensionID); }
|
||||
|
||||
@Inject(at = @At("RETURN"), method = "clearInvulnerableDimensionChange")
|
||||
public void clearDimensionChangeDestination(CallbackInfo ci)
|
||||
{ this.distantHorizons$dimensionChangeDestination = null; }
|
||||
|
||||
|
||||
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizons mod
|
||||
* licensed under the GNU LGPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020 James Seibel
|
||||
*
|
||||
* This program 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, version 3.
|
||||
*
|
||||
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.distanthorizons.cleanroom.modAccessor;
|
||||
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IModChecker;
|
||||
import net.minecraftforge.fml.common.Loader;
|
||||
import net.minecraftforge.fml.common.ModContainer;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class ModChecker implements IModChecker
|
||||
{
|
||||
public static final ModChecker INSTANCE = new ModChecker();
|
||||
|
||||
@Override
|
||||
public boolean isModLoaded(String modid)
|
||||
{
|
||||
return Loader.isModLoaded(modid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public File modLocation(String modid)
|
||||
{
|
||||
Stream<ModContainer> foundStream = Loader.instance().getModList().stream().filter(x -> x.getModId().equals(modid));
|
||||
Optional<ModContainer> container = foundStream.findFirst();
|
||||
if (!container.isPresent())
|
||||
{
|
||||
throw new RuntimeException("Mod not found: " + modid);
|
||||
}
|
||||
return container.get().getSource();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"required": true,
|
||||
"package": "com.seibel.distanthorizons.cleanroom.mixins",
|
||||
"compatibilityLevel": "JAVA_8",
|
||||
"target": "@env(DEFAULT)",
|
||||
"mixins": [],
|
||||
"minVersion": "0.8.7",
|
||||
"server": [
|
||||
"server.MixinEntityPlayerMP"
|
||||
],
|
||||
"client": [
|
||||
"client.MixinEntityRenderer",
|
||||
"client.MixinNetHandlerPlayClient",
|
||||
"client.MixinOptionsScreen",
|
||||
"client.MixinRenderGlobal"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"required": false,
|
||||
"package": "com.seibel.distanthorizons.cleanroom.mixins.mod",
|
||||
"compatibilityLevel": "JAVA_8",
|
||||
"target": "@env(MOD)",
|
||||
"mixins": [],
|
||||
"minVersion": "0.8.7",
|
||||
"plugin": "com.seibel.distanthorizons.cleanroom.DistantHorizonsConfigPlugin",
|
||||
"client": [
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
[{
|
||||
"modid": "${mod_id}",
|
||||
"name": "${mod_name}",
|
||||
"version": "${version}",
|
||||
"mcversion": "1.12.2",
|
||||
"description": "${description}",
|
||||
"authorList": ["${cleanroom_authors}"],
|
||||
"credits": "",
|
||||
"url": "",
|
||||
"updateJSON": "",
|
||||
"logoFile": "${logo_path}"
|
||||
}]
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"pack": {
|
||||
"description": "${mod_name} Resources",
|
||||
"pack_format": 3
|
||||
}
|
||||
}
|
||||
+52
-15
@@ -1,15 +1,16 @@
|
||||
package com.seibel.distanthorizons.common;
|
||||
|
||||
import com.mojang.brigadier.CommandDispatcher;
|
||||
import com.seibel.distanthorizons.api.enums.config.EDhApiMcRenderingFadeMode;
|
||||
import com.seibel.distanthorizons.api.enums.config.EDhApiRenderApi;
|
||||
import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiDistantGeneratorMode;
|
||||
import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiAfterDhInitEvent;
|
||||
import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiBeforeDhInitEvent;
|
||||
import com.seibel.distanthorizons.common.commands.CommandInitializer;
|
||||
import com.seibel.distanthorizons.common.wrappers.DependencySetup;
|
||||
import com.seibel.distanthorizons.common.wrappers.gui.DhDebugScreenEntry;
|
||||
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftServerWrapper;
|
||||
import com.seibel.distanthorizons.core.Initializer;
|
||||
import com.seibel.distanthorizons.core.api.internal.ClientApi;
|
||||
import com.seibel.distanthorizons.core.api.internal.SharedApi;
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.config.ConfigHandler;
|
||||
import com.seibel.distanthorizons.core.config.eventHandlers.presets.ThreadPresetConfigEventHandler;
|
||||
@@ -21,10 +22,8 @@ import com.seibel.distanthorizons.core.jar.updater.SelfUpdater;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.render.renderer.AbstractDebugWireframeRenderer;
|
||||
import com.seibel.distanthorizons.core.render.renderer.StubDebugWireframeRenderer;
|
||||
import com.seibel.distanthorizons.core.util.NativeDialogUtil;
|
||||
import com.seibel.distanthorizons.common.wrappers.gui.NativeDialogUtil;
|
||||
import com.seibel.distanthorizons.core.util.ThreadUtil;
|
||||
import com.seibel.distanthorizons.core.util.threading.DhThreadFactory;
|
||||
import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.IVersionConstants;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IIrisAccessor;
|
||||
@@ -32,7 +31,6 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IModAccesso
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IModChecker;
|
||||
import com.seibel.distanthorizons.coreapi.DependencyInjection.ApiEventInjector;
|
||||
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.dedicated.DedicatedServer;
|
||||
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||
@@ -41,6 +39,11 @@ import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
#if MC_VER > MC_1_12_2
|
||||
import com.mojang.brigadier.CommandDispatcher;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Base for all mod loader initializers
|
||||
* and handles most setup.
|
||||
@@ -64,7 +67,9 @@ public abstract class AbstractModInitializer
|
||||
protected abstract IEventProxy createServerProxy(boolean isDedicated);
|
||||
protected abstract void initializeModCompat();
|
||||
|
||||
#if MC_VER > MC_1_12_2
|
||||
protected abstract void subscribeRegisterCommandsEvent(Consumer<CommandDispatcher<CommandSourceStack>> eventHandler);
|
||||
#endif
|
||||
|
||||
protected abstract void subscribeClientStartedEvent(Runnable eventHandler);
|
||||
protected abstract void subscribeServerStartingEvent(Consumer<MinecraftServer> eventHandler);
|
||||
@@ -97,7 +102,9 @@ public abstract class AbstractModInitializer
|
||||
|
||||
// Client uses config for auto-updater, so it's initialized here instead of post-init stage
|
||||
this.initConfig();
|
||||
logModIncompatibilityWarnings(); // needs to be called after config loading
|
||||
logIncompatibilityWarnings(); // needs to be called after config loading
|
||||
setUnsupportedConfigsBasedOnMcVersion();
|
||||
Initializer.postConfigInit();
|
||||
|
||||
LOGGER.info(ModInfo.READABLE_NAME + " client Initialized.");
|
||||
|
||||
@@ -131,21 +138,33 @@ public abstract class AbstractModInitializer
|
||||
this.initializeModCompat();
|
||||
|
||||
LOGGER.info(ModInfo.READABLE_NAME + " server Initialized, adding event subscribers...");
|
||||
#if MC_VER > MC_1_12_2
|
||||
this.commandInitializer = new CommandInitializer();
|
||||
this.subscribeRegisterCommandsEvent(dispatcher -> { this.commandInitializer.initCommands(dispatcher); });
|
||||
#endif
|
||||
|
||||
this.subscribeServerStartingEvent(server ->
|
||||
{
|
||||
MinecraftServerWrapper.INSTANCE.dedicatedServer = (DedicatedServer)server;
|
||||
|
||||
this.initConfig();
|
||||
Initializer.postConfigInit();
|
||||
this.postInit();
|
||||
this.postServerInit();
|
||||
#if MC_VER > MC_1_12_2
|
||||
this.commandInitializer.onServerReady();
|
||||
#endif
|
||||
|
||||
this.checkForUpdates();
|
||||
|
||||
LOGGER.info(ModInfo.READABLE_NAME + " server Initialized at " + server.getServerDirectory());
|
||||
String serverFolderPath;
|
||||
#if MC_VER <= MC_1_12_2
|
||||
serverFolderPath = server.getDataDirectory() + "";
|
||||
#else
|
||||
serverFolderPath = server.getServerDirectory() + "";
|
||||
#endif
|
||||
|
||||
LOGGER.info(ModInfo.READABLE_NAME + " server Initialized at " + serverFolderPath);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -161,7 +180,7 @@ public abstract class AbstractModInitializer
|
||||
private void startup()
|
||||
{
|
||||
DependencySetup.createSharedBindings();
|
||||
SharedApi.init();
|
||||
Initializer.preConfigInit();
|
||||
this.createInitialSharedBindings();
|
||||
}
|
||||
|
||||
@@ -263,9 +282,9 @@ public abstract class AbstractModInitializer
|
||||
|
||||
|
||||
|
||||
//==================================//
|
||||
// mod partial compatibility checks //
|
||||
//==================================//
|
||||
//======================//
|
||||
// compatibility checks //
|
||||
//======================//
|
||||
//region
|
||||
|
||||
/**
|
||||
@@ -274,7 +293,7 @@ public abstract class AbstractModInitializer
|
||||
* This method will log (and display to chat if enabled)
|
||||
* these warnings and potential fixes.
|
||||
*/
|
||||
private static void logModIncompatibilityWarnings()
|
||||
private static void logIncompatibilityWarnings()
|
||||
{
|
||||
boolean showChatWarnings = Config.Common.Logging.Warning.showModCompatibilityWarningsOnStartup.get();
|
||||
IModChecker modChecker = SingletonInjector.INSTANCE.get(IModChecker.class);
|
||||
@@ -375,10 +394,10 @@ public abstract class AbstractModInitializer
|
||||
renderApi = versionConstants.getDefaultRenderingApi();
|
||||
}
|
||||
|
||||
// Iris only supports nataive OpenGL
|
||||
// Iris only supports native OpenGL
|
||||
if (renderApi != EDhApiRenderApi.OPEN_GL)
|
||||
{
|
||||
String irisUnsupportedMessage = "Iris doesn't support DH when using the ["+EDhApiRenderApi.BLAZE_3D+"] rendering API, this will need to be fixed on Iris' end. As a temporary fix please change the rendering API to ["+EDhApiRenderApi.OPEN_GL+"] in DH's config file.";
|
||||
String irisUnsupportedMessage = "Iris doesn't support DH when using the ["+EDhApiRenderApi.BLAZE_3D+"] rendering API, this will need to be fixed on Iris end. As a temporary fix please change the rendering API to ["+EDhApiRenderApi.OPEN_GL+"] in the DH config file.";
|
||||
LOGGER.fatal(irisUnsupportedMessage);
|
||||
NativeDialogUtil.showDialog(ModInfo.READABLE_NAME, irisUnsupportedMessage, "ok", "error");
|
||||
|
||||
@@ -393,6 +412,24 @@ public abstract class AbstractModInitializer
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Some Minecraft versions don't support all
|
||||
* DH options.
|
||||
* In that case we need to override what options are available.
|
||||
*/
|
||||
private static void setUnsupportedConfigsBasedOnMcVersion()
|
||||
{
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
Config.Client.Advanced.Graphics.Experimental.renderingApi.setMcVersionOverrideValue(EDhApiRenderApi.OPEN_GL);
|
||||
Config.Client.Advanced.Graphics.Quality.vanillaFadeMode.setMcVersionOverrideValue(EDhApiMcRenderingFadeMode.NONE);
|
||||
Config.Common.WorldGenerator.distantGeneratorMode.setMcVersionOverrideValue(EDhApiDistantGeneratorMode.INTERNAL_SERVER);
|
||||
#elif MC_VER <= MC_1_21_10
|
||||
Config.Client.Advanced.Graphics.Experimental.renderingApi.setMcVersionOverrideValue(EDhApiRenderApi.OPEN_GL);
|
||||
#else
|
||||
#endif
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
+29
-2
@@ -12,10 +12,17 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IPluginPacketSende
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IServerPlayerWrapper;
|
||||
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||
import io.netty.buffer.ByteBufUtil;
|
||||
#if MC_VER <= MC_1_12_2
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.network.PacketBuffer;
|
||||
#else
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
#endif
|
||||
|
||||
#if MC_VER <= MC_1_21_10
|
||||
#if MC_VER <= MC_1_12_2
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
#elif MC_VER <= MC_1_21_10
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
#else
|
||||
import net.minecraft.resources.Identifier;
|
||||
@@ -30,7 +37,9 @@ public abstract class AbstractPluginPacketSender implements IPluginPacketSender
|
||||
.fileLevelConfig(Config.Common.Logging.logNetworkEventToFile)
|
||||
.build();
|
||||
|
||||
#if MC_VER <= MC_1_20_6
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public static final String WRAPPER_PACKET_RESOURCE = ModInfo.RESOURCE_NAMESPACE + ModInfo.WRAPPER_PACKET_PATH;
|
||||
#elif MC_VER <= MC_1_20_6
|
||||
public static final ResourceLocation WRAPPER_PACKET_RESOURCE = new ResourceLocation(ModInfo.RESOURCE_NAMESPACE, ModInfo.WRAPPER_PACKET_PATH);
|
||||
#elif MC_VER <= MC_1_21_10
|
||||
public static final ResourceLocation WRAPPER_PACKET_RESOURCE = ResourceLocation.fromNamespaceAndPath(ModInfo.RESOURCE_NAMESPACE, ModInfo.WRAPPER_PACKET_PATH);
|
||||
@@ -52,14 +61,28 @@ public abstract class AbstractPluginPacketSender implements IPluginPacketSender
|
||||
@Override
|
||||
public final void sendToClient(IServerPlayerWrapper serverPlayer, AbstractNetworkMessage message)
|
||||
{
|
||||
#if MC_VER <= MC_1_12_2
|
||||
this.sendToClient((EntityPlayerMP) serverPlayer.getWrappedMcObject(), message);
|
||||
#else
|
||||
this.sendToClient((ServerPlayer) serverPlayer.getWrappedMcObject(), message);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public abstract void sendToClient(EntityPlayerMP serverPlayer, AbstractNetworkMessage message);
|
||||
#else
|
||||
public abstract void sendToClient(ServerPlayer serverPlayer, AbstractNetworkMessage message);
|
||||
#endif
|
||||
|
||||
|
||||
@Override
|
||||
public abstract void sendToServer(AbstractNetworkMessage message);
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public AbstractNetworkMessage decodeMessage(PacketBuffer in)
|
||||
#else
|
||||
public AbstractNetworkMessage decodeMessage(FriendlyByteBuf in)
|
||||
#endif
|
||||
{
|
||||
AbstractNetworkMessage message = null;
|
||||
|
||||
@@ -100,7 +123,11 @@ public abstract class AbstractPluginPacketSender implements IPluginPacketSender
|
||||
}
|
||||
}
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public void encodeMessage(PacketBuffer out, AbstractNetworkMessage message)
|
||||
#else
|
||||
public void encodeMessage(FriendlyByteBuf out, AbstractNetworkMessage message)
|
||||
#endif
|
||||
{
|
||||
// This is intentionally unhandled, because errors related to this are unlikely to appear in wild
|
||||
Objects.requireNonNull(message);
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
package com.seibel.distanthorizons.common.commands;
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public abstract class AbstractCommand {}
|
||||
|
||||
#else
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import com.seibel.distanthorizons.common.wrappers.misc.ServerPlayerWrapper;
|
||||
@@ -100,3 +104,4 @@ public abstract class AbstractCommand
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
+81
-3
@@ -1,12 +1,26 @@
|
||||
package com.seibel.distanthorizons.common.commands;
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
import com.seibel.distanthorizons.core.config.ConfigHandler;
|
||||
import com.seibel.distanthorizons.core.config.types.AbstractConfigBase;
|
||||
import com.seibel.distanthorizons.core.config.types.ConfigEntry;
|
||||
import com.seibel.distanthorizons.core.logging.f3.F3Screen;
|
||||
import net.minecraft.command.CommandBase;
|
||||
import net.minecraft.command.ICommand;
|
||||
import net.minecraft.command.ICommandSender;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.util.text.TextComponentString;
|
||||
#else
|
||||
import com.mojang.brigadier.CommandDispatcher;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import static net.minecraft.commands.Commands.literal;
|
||||
#endif
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static com.seibel.distanthorizons.core.network.messages.MessageRegistry.DEBUG_CODEC_CRASH_MESSAGE;
|
||||
import static net.minecraft.commands.Commands.literal;
|
||||
|
||||
#if MC_VER <= MC_1_21_10
|
||||
#else
|
||||
@@ -25,6 +39,70 @@ public class CommandInitializer
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public static ICommand initCommands()
|
||||
{
|
||||
return new CommandBase()
|
||||
{
|
||||
@Override
|
||||
public String getName() { return "dh"; }
|
||||
|
||||
@Override
|
||||
public String getUsage(ICommandSender sender) { return "/dh <debug|config|pregen>"; }
|
||||
|
||||
@Override
|
||||
public void execute(MinecraftServer server, ICommandSender sender, String[] args)
|
||||
{
|
||||
if (args.length == 0)
|
||||
{
|
||||
if (DEBUG_CODEC_CRASH_MESSAGE)
|
||||
{
|
||||
sender.sendMessage(new TextComponentString("Usage: /dh <debug|config|crash|pregen>"));
|
||||
}
|
||||
else
|
||||
{
|
||||
sender.sendMessage(new TextComponentString("Usage: /dh <debug|config|pregen"));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
switch (args[0])
|
||||
{
|
||||
case "debug":
|
||||
DebugCommand debugCommand = new DebugCommand();
|
||||
debugCommand.execute(sender);
|
||||
break;
|
||||
case "config":
|
||||
ConfigCommand configCommand = new ConfigCommand();
|
||||
configCommand.execute(sender, args);
|
||||
break;
|
||||
case "crash":
|
||||
if (DEBUG_CODEC_CRASH_MESSAGE)
|
||||
{
|
||||
CrashCommand crashCommand = new CrashCommand();
|
||||
crashCommand.execute(sender, args);
|
||||
}
|
||||
break;
|
||||
case "pregen":
|
||||
if (!server.isDedicatedServer())
|
||||
{
|
||||
sender.sendMessage(new TextComponentString("Pregen command is only available on dedicated servers"));
|
||||
break;
|
||||
}
|
||||
PregenCommand pregenCommand = new PregenCommand();
|
||||
pregenCommand.execute(server, sender, args);
|
||||
break;
|
||||
default:
|
||||
sender.sendMessage(new TextComponentString("Unknown subcommand: " + args[0]));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/**
|
||||
* A received command dispatcher, which is held until the server is ready to initialize the commands.
|
||||
*/
|
||||
@@ -80,5 +158,5 @@ public class CommandInitializer
|
||||
|
||||
commandDispatcher.register(builder);
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1,13 +1,25 @@
|
||||
package com.seibel.distanthorizons.common.commands;
|
||||
|
||||
import com.mojang.brigadier.arguments.*;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import com.seibel.distanthorizons.core.config.ConfigHandler;
|
||||
import com.seibel.distanthorizons.core.config.types.AbstractConfigBase;
|
||||
import com.seibel.distanthorizons.core.config.types.ConfigEntry;
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
import net.minecraft.command.ICommandSender;
|
||||
import net.minecraft.util.text.TextComponentString;
|
||||
#else
|
||||
import com.mojang.brigadier.arguments.*;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
|
||||
import static com.mojang.brigadier.arguments.DoubleArgumentType.doubleArg;
|
||||
import static com.mojang.brigadier.arguments.IntegerArgumentType.integer;
|
||||
import static net.minecraft.commands.Commands.argument;
|
||||
import static net.minecraft.commands.Commands.literal;
|
||||
#endif
|
||||
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
@@ -16,16 +28,75 @@ import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.function.ToIntBiFunction;
|
||||
|
||||
import static com.mojang.brigadier.arguments.DoubleArgumentType.doubleArg;
|
||||
import static com.mojang.brigadier.arguments.IntegerArgumentType.integer;
|
||||
import static net.minecraft.commands.Commands.argument;
|
||||
import static net.minecraft.commands.Commands.literal;
|
||||
|
||||
|
||||
/**
|
||||
* Command for managing config.
|
||||
*/
|
||||
public class ConfigCommand extends AbstractCommand
|
||||
{
|
||||
#if MC_VER <= MC_1_12_2
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
private static void setConfigValue(ConfigEntry<?> configEntry, String value)
|
||||
{
|
||||
Class<?> type = configEntry.getType();
|
||||
|
||||
if (type == Boolean.class) ((ConfigEntry) configEntry).set(Boolean.parseBoolean(value));
|
||||
else if (type == Integer.class) ((ConfigEntry) configEntry).set(Integer.parseInt(value));
|
||||
else if (type == Double.class) ((ConfigEntry) configEntry).set(Double.parseDouble(value));
|
||||
else if (type == Float.class) ((ConfigEntry) configEntry).set(Float.parseFloat(value));
|
||||
else if (type == Long.class) ((ConfigEntry) configEntry).set(Long.parseLong(value));
|
||||
else if (type == String.class) ((ConfigEntry) configEntry).set(value);
|
||||
else if (type.isEnum()) ((ConfigEntry) configEntry).set(Enum.valueOf((Class<Enum>) type, value));
|
||||
else throw new RuntimeException("Unsupported config type: " + type.getSimpleName());
|
||||
}
|
||||
public void execute(ICommandSender sender, String[] args)
|
||||
{
|
||||
if (args.length < 2)
|
||||
{
|
||||
sender.sendMessage(new TextComponentString("Usage: /dh config <name> [value]"));
|
||||
return;
|
||||
}
|
||||
|
||||
String configName = args[1];
|
||||
AbstractConfigBase<?> found = null;
|
||||
for (AbstractConfigBase<?> entry : ConfigHandler.INSTANCE.configBaseList)
|
||||
{
|
||||
if (entry instanceof ConfigEntry && configName.equals(((ConfigEntry<?>) entry).getChatCommandName()))
|
||||
{
|
||||
found = entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found == null)
|
||||
{
|
||||
sender.sendMessage(new TextComponentString("Unknown config: " + configName));
|
||||
return;
|
||||
}
|
||||
|
||||
ConfigEntry<?> configEntry = (ConfigEntry<?>) found;
|
||||
if (args.length == 2)
|
||||
{
|
||||
sender.sendMessage(new TextComponentString("Current value of " + configName + " is " + configEntry.get()));
|
||||
}
|
||||
else
|
||||
{
|
||||
String value = args[2];
|
||||
try
|
||||
{
|
||||
setConfigValue(configEntry, value);
|
||||
sender.sendMessage(new TextComponentString("Changed " + configName + " to " + value));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
sender.sendMessage(new TextComponentString("Invalid value: " + value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
private static final List<CommandArgumentData<?>> commandArguments = Arrays.asList(
|
||||
new CommandArgumentData<>(Integer.class, configEntry -> integer(configEntry.getMin(), configEntry.getMax()), IntegerArgumentType::getInteger),
|
||||
new CommandArgumentData<>(Double.class, configEntry -> doubleArg(configEntry.getMin(), configEntry.getMax()), DoubleArgumentType::getDouble),
|
||||
@@ -150,5 +221,6 @@ public class ConfigCommand extends AbstractCommand
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,60 @@
|
||||
package com.seibel.distanthorizons.common.commands;
|
||||
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.seibel.distanthorizons.core.api.internal.SharedApi;
|
||||
import com.seibel.distanthorizons.core.multiplayer.server.ServerPlayerState;
|
||||
import com.seibel.distanthorizons.core.network.messages.base.CodecCrashMessage;
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
import com.seibel.distanthorizons.common.wrappers.misc.ServerPlayerWrapper;
|
||||
import net.minecraft.command.ICommandSender;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.util.text.TextComponentString;
|
||||
#else
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
|
||||
import static net.minecraft.commands.Commands.literal;
|
||||
#endif
|
||||
|
||||
|
||||
public class CrashCommand extends AbstractCommand
|
||||
{
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public void execute(ICommandSender sender, String[] args)
|
||||
{
|
||||
if (!(sender instanceof EntityPlayerMP))
|
||||
{
|
||||
sender.sendMessage(new TextComponentString("This command can only be run by a player"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.length < 2)
|
||||
{
|
||||
sender.sendMessage(new TextComponentString("Usage: /dh crash <encode|decode>"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (SharedApi.tryGetDhServerWorld() == null) return;
|
||||
|
||||
ServerPlayerState serverPlayerState = SharedApi.tryGetDhServerWorld()
|
||||
.getServerPlayerStateManager()
|
||||
.getConnectedPlayer(ServerPlayerWrapper.getWrapper((EntityPlayerMP) sender));
|
||||
|
||||
if (serverPlayerState == null) return;
|
||||
|
||||
switch (args[1])
|
||||
{
|
||||
case "encode":
|
||||
serverPlayerState.networkSession.sendMessage(new CodecCrashMessage(CodecCrashMessage.ECrashPhase.ENCODE));
|
||||
break;
|
||||
case "decode":
|
||||
serverPlayerState.networkSession.sendMessage(new CodecCrashMessage(CodecCrashMessage.ECrashPhase.DECODE));
|
||||
break;
|
||||
default:
|
||||
sender.sendMessage(new TextComponentString("Usage: /dh crash <encode|decode>"));
|
||||
}
|
||||
}
|
||||
#else
|
||||
@Override
|
||||
public LiteralArgumentBuilder<CommandSourceStack> buildCommand()
|
||||
{
|
||||
@@ -40,5 +85,6 @@ public class CrashCommand extends AbstractCommand
|
||||
return 1;
|
||||
}));
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
@@ -1,25 +1,44 @@
|
||||
package com.seibel.distanthorizons.common.commands;
|
||||
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.seibel.distanthorizons.core.logging.f3.F3Screen;
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
import net.minecraft.command.ICommandSender;
|
||||
import net.minecraft.util.text.TextComponentString;
|
||||
#else
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
|
||||
import static net.minecraft.commands.Commands.literal;
|
||||
#endif
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static net.minecraft.commands.Commands.literal;
|
||||
|
||||
public class DebugCommand extends AbstractCommand
|
||||
{
|
||||
private static String getDebugString()
|
||||
{
|
||||
List<String> lines = new ArrayList<>();
|
||||
F3Screen.addStringToDisplay(lines);
|
||||
return String.join("\n", lines);
|
||||
}
|
||||
|
||||
#if MC_VER > MC_1_12_2
|
||||
@Override
|
||||
public LiteralArgumentBuilder<CommandSourceStack> buildCommand()
|
||||
{
|
||||
return literal("debug")
|
||||
.executes(c -> {
|
||||
List<String> lines = new ArrayList<>();
|
||||
F3Screen.addStringToDisplay(lines);
|
||||
return this.sendSuccessResponse(c, String.join("\n", lines), false);
|
||||
});
|
||||
return literal("debug")
|
||||
.executes(c -> {
|
||||
return this.sendSuccessResponse(c, getDebugString(), false);
|
||||
});
|
||||
}
|
||||
#else
|
||||
public void execute(ICommandSender sender)
|
||||
{
|
||||
sender.sendMessage(new TextComponentString(getDebugString()));
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
+112
-8
@@ -1,27 +1,36 @@
|
||||
package com.seibel.distanthorizons.common.commands;
|
||||
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper;
|
||||
import com.seibel.distanthorizons.core.api.internal.SharedApi;
|
||||
import com.seibel.distanthorizons.core.generation.PregenManager;
|
||||
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos2D;
|
||||
import com.seibel.distanthorizons.core.world.DhServerWorld;
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
import net.minecraft.command.ICommandSender;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.util.text.TextComponentString;
|
||||
import net.minecraft.world.WorldServer;
|
||||
#else
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.commands.arguments.DimensionArgument;
|
||||
import net.minecraft.commands.arguments.coordinates.ColumnPosArgument;
|
||||
import net.minecraft.server.level.ColumnPos;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.CancellationException;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import static com.mojang.brigadier.arguments.IntegerArgumentType.getInteger;
|
||||
import static com.mojang.brigadier.arguments.IntegerArgumentType.integer;
|
||||
import static net.minecraft.commands.Commands.argument;
|
||||
import static net.minecraft.commands.Commands.literal;
|
||||
#endif
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.CancellationException;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
|
||||
public class PregenCommand extends AbstractCommand
|
||||
{
|
||||
@@ -31,6 +40,101 @@ public class PregenCommand extends AbstractCommand
|
||||
return world.getPregenManager();
|
||||
}
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public void execute(MinecraftServer server, ICommandSender sender, String[] args)
|
||||
{
|
||||
if (args.length < 2)
|
||||
{
|
||||
sender.sendMessage(new TextComponentString("Usage: /dh pregen <status|start|stop>"));
|
||||
return;
|
||||
}
|
||||
|
||||
switch (args[1])
|
||||
{
|
||||
case "status":
|
||||
{
|
||||
String statusString = this.getPregenManager().getStatusString();
|
||||
sender.sendMessage(new TextComponentString(
|
||||
statusString != null ? statusString : "Pregen is not running"));
|
||||
break;
|
||||
}
|
||||
case "start":
|
||||
{
|
||||
if (args.length < 5)
|
||||
{
|
||||
sender.sendMessage(new TextComponentString("Usage: /dh pregen start <dimension> <x> <z> <chunkRadius>"));
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
String dimensionName = args[2];
|
||||
int x = Integer.parseInt(args[3]);
|
||||
int z = Integer.parseInt(args[4]);
|
||||
int chunkRadius = args.length >= 6 ? Integer.parseInt(args[5]) : 32;
|
||||
|
||||
// find the world by dimension name
|
||||
WorldServer world = null;
|
||||
for (WorldServer w : server.worlds)
|
||||
{
|
||||
if (w.provider.getDimensionType().getName().equals(dimensionName))
|
||||
{
|
||||
world = w;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (world == null)
|
||||
{
|
||||
sender.sendMessage(new TextComponentString("Unknown dimension: " + dimensionName));
|
||||
return;
|
||||
}
|
||||
|
||||
sender.sendMessage(new TextComponentString("Starting pregen. Progress will be in the server console."));
|
||||
|
||||
final ICommandSender finalSender = sender;
|
||||
CompletableFuture<Void> future = this.getPregenManager().startPregen(
|
||||
ServerLevelWrapper.getWrapper(world),
|
||||
new DhBlockPos2D(x, z),
|
||||
chunkRadius
|
||||
);
|
||||
|
||||
future.whenComplete((result, throwable) -> {
|
||||
if (throwable instanceof CancellationException)
|
||||
{
|
||||
finalSender.sendMessage(new TextComponentString("Pregen is cancelled"));
|
||||
return;
|
||||
}
|
||||
else if (throwable != null)
|
||||
{
|
||||
finalSender.sendMessage(new TextComponentString("Pregen failed: " + throwable.getMessage()));
|
||||
return;
|
||||
}
|
||||
finalSender.sendMessage(new TextComponentString("Pregen is complete"));
|
||||
});
|
||||
}
|
||||
catch (NumberFormatException e)
|
||||
{
|
||||
sender.sendMessage(new TextComponentString("Invalid number format"));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "stop":
|
||||
{
|
||||
CompletableFuture<Void> runningPregen = this.getPregenManager().getRunningPregen();
|
||||
if (runningPregen == null)
|
||||
{
|
||||
sender.sendMessage(new TextComponentString("Pregen is not running"));
|
||||
return;
|
||||
}
|
||||
runningPregen.cancel(true);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
sender.sendMessage(new TextComponentString("Unknown subcommand: " + args[1]));
|
||||
}
|
||||
}
|
||||
#else
|
||||
@Override
|
||||
public LiteralArgumentBuilder<CommandSourceStack> buildCommand()
|
||||
{
|
||||
@@ -110,5 +214,5 @@ public class PregenCommand extends AbstractCommand
|
||||
runningPregen.cancel(true);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
+7
-3
@@ -1,5 +1,6 @@
|
||||
package com.seibel.distanthorizons.common.commonMixins;
|
||||
|
||||
#if MC_VER > MC_1_12_2
|
||||
import com.seibel.distanthorizons.api.enums.config.EDhApiUpdateBranch;
|
||||
import com.seibel.distanthorizons.common.wrappers.gui.updater.UpdateModScreen;
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
@@ -11,16 +12,18 @@ import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.IVersionConstants;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.screens.TitleScreen;
|
||||
#if MC_VER <= MC_1_12_2
|
||||
|
||||
#else
|
||||
import net.minecraft.client.gui.screens.TitleScreen;
|
||||
#endif
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class DhUpdateScreenBase
|
||||
{
|
||||
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||
|
||||
private static final Minecraft MC = Minecraft.getInstance();
|
||||
|
||||
private static final Minecraft MC = Minecraft #if MC_VER <= MC_1_12_2 .getMinecraft() #else .getInstance() #endif;
|
||||
|
||||
|
||||
public static void tryShowUpdateScreenAndRunAutoUpdateStartup(Runnable runnable)
|
||||
@@ -86,3 +89,4 @@ public class DhUpdateScreenBase
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
+22
-4
@@ -6,15 +6,23 @@ import com.seibel.distanthorizons.core.api.internal.ServerApi;
|
||||
import com.seibel.distanthorizons.core.api.internal.SharedApi;
|
||||
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper;
|
||||
#if MC_VER <= MC_1_12_2
|
||||
import net.minecraft.world.WorldServer;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
#else
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
import net.minecraft.world.level.chunk.ProtoChunk;
|
||||
#endif
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
public class MixinChunkMapCommon
|
||||
{
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public static void onChunkSave(WorldServer level, Chunk chunk)
|
||||
#else
|
||||
public static void onChunkSave(ServerLevel level, ChunkAccess chunk, CallbackInfoReturnable<Boolean> ci)
|
||||
#endif
|
||||
{
|
||||
IServerLevelWrapper levelWrapper = ServerLevelWrapper.getWrapper(level);
|
||||
|
||||
@@ -37,7 +45,7 @@ public class MixinChunkMapCommon
|
||||
|
||||
|
||||
// is this chunk being saved to disk?
|
||||
boolean savingChunkToDisk = ci.getReturnValue();
|
||||
boolean savingChunkToDisk = #if MC_VER <= MC_1_12_2 true #else ci.getReturnValue() #endif;
|
||||
// true means a chunk was saved to disk
|
||||
if (!savingChunkToDisk)
|
||||
{
|
||||
@@ -50,7 +58,12 @@ public class MixinChunkMapCommon
|
||||
|
||||
// MC has a tendency to try saving incomplete or corrupted chunks (which show up as empty or black chunks)
|
||||
// this logic should prevent that from happening
|
||||
#if MC_VER <= MC_1_17_1
|
||||
#if MC_VER <= MC_1_12_2
|
||||
if (!chunk.isTerrainPopulated() || !chunk.isLightPopulated())
|
||||
{
|
||||
return;
|
||||
}
|
||||
#elif MC_VER <= MC_1_17_1
|
||||
if (chunk.isUnsaved() || chunk.getUpgradeData() != null || !chunk.isLightCorrect())
|
||||
{
|
||||
return;
|
||||
@@ -67,7 +80,12 @@ public class MixinChunkMapCommon
|
||||
// biome validation //
|
||||
|
||||
// some chunks may be missing their biomes, which cause issues when attempting to save them
|
||||
#if MC_VER <= MC_1_17_1
|
||||
#if MC_VER <= MC_1_12_2
|
||||
if (chunk. getBiomeArray() == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
#elif MC_VER <= MC_1_17_1
|
||||
if (chunk.getBiomes() == null)
|
||||
{
|
||||
return;
|
||||
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
package com.seibel.distanthorizons.common.commonMixins;
|
||||
|
||||
#if MC_VER > MC_1_12_2
|
||||
import com.seibel.distanthorizons.common.wrappers.modAccessor.ImmersivePortalsAccessorCommon;
|
||||
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
||||
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos;
|
||||
import com.seibel.distanthorizons.core.util.math.Vec3d;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public class MixinImmersivePortalsRenderStatesCommon
|
||||
{
|
||||
|
||||
public static void saveVolatileOriginals()
|
||||
{
|
||||
Minecraft mc = Minecraft.getInstance();
|
||||
ImmersivePortalsAccessorCommon.originalLevel = mc.level;
|
||||
|
||||
if (mc.player == null) {
|
||||
ImmersivePortalsAccessorCommon.originalBlockPos = null;
|
||||
ImmersivePortalsAccessorCommon.originalChunkPos = null;
|
||||
ImmersivePortalsAccessorCommon.originalCameraPos = null;
|
||||
return;
|
||||
}
|
||||
|
||||
BlockPos pos = mc.player.blockPosition();
|
||||
ImmersivePortalsAccessorCommon.originalBlockPos = new DhBlockPos(pos.getX(), pos.getY(), pos.getZ());
|
||||
#if MC_VER < MC_1_17_1
|
||||
ChunkPos cPos = new ChunkPos(mc.player.blockPosition());
|
||||
#else
|
||||
ChunkPos cPos = mc.player.chunkPosition();
|
||||
#endif
|
||||
|
||||
#if MC_VER <= MC_1_21_11
|
||||
ImmersivePortalsAccessorCommon.originalChunkPos = new DhChunkPos(cPos.x, cPos.z);
|
||||
#else
|
||||
ImmersivePortalsAccessorCommon.originalChunkPos = new DhChunkPos(cPos.x(), cPos.z());
|
||||
#endif
|
||||
|
||||
|
||||
#if MC_VER <= MC_1_21_10
|
||||
Vec3 cameraPos = mc.gameRenderer.getMainCamera().getPosition();
|
||||
#else
|
||||
Vec3 cameraPos = mc.gameRenderer.getMainCamera().position();
|
||||
#endif
|
||||
ImmersivePortalsAccessorCommon.originalCameraPos = new Vec3d(cameraPos.x(), cameraPos.y(), cameraPos.z());
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
+141
@@ -0,0 +1,141 @@
|
||||
package com.seibel.distanthorizons.common.commonMixins;
|
||||
|
||||
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftClientWrapper;
|
||||
import com.seibel.distanthorizons.core.api.internal.ClientApi;
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IImmersivePortalsAccessor;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
#if MC_VER <= MC_1_12_2
|
||||
#else
|
||||
import net.minecraft.client.Camera;
|
||||
import net.minecraft.world.effect.MobEffects;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
#endif
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
import net.minecraft.client.entity.EntityPlayerSP;
|
||||
import net.minecraft.init.MobEffects;
|
||||
#elif MC_VER < MC_1_17_1
|
||||
import net.minecraft.world.level.material.FluidState;
|
||||
import net.minecraft.client.renderer.FogRenderer;
|
||||
import net.minecraft.client.renderer.FogRenderer.FogMode;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
#elif MC_VER < MC_1_21_3
|
||||
import net.minecraft.world.level.material.FogType;
|
||||
import net.minecraft.client.renderer.FogRenderer;
|
||||
import net.minecraft.client.renderer.FogRenderer.FogMode;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
#elif MC_VER < MC_1_21_6
|
||||
import net.minecraft.world.level.material.FogType;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
import com.mojang.blaze3d.shaders.FogShape;
|
||||
import net.minecraft.client.renderer.FogRenderer;
|
||||
import net.minecraft.client.renderer.FogRenderer.FogMode;
|
||||
import net.minecraft.client.renderer.FogParameters;
|
||||
import org.joml.Vector4f;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
#else
|
||||
import net.minecraft.world.level.material.FogType;
|
||||
import net.minecraft.client.renderer.fog.FogRenderer;
|
||||
import net.minecraft.client.renderer.fog.FogData;
|
||||
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
||||
#endif
|
||||
|
||||
|
||||
public class MixinVanillaFogCommon
|
||||
{
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public static boolean cancelFog(int startCoords, Minecraft mc)
|
||||
#elif MC_VER < MC_1_21_6
|
||||
public static boolean cancelFog(Camera camera, FogRenderer.FogMode fogMode)
|
||||
#else
|
||||
public static boolean cancelFog()
|
||||
#endif
|
||||
{
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
EntityPlayerSP entity = mc.player;
|
||||
#elif MC_VER < MC_1_21_6
|
||||
Entity entity = camera.getEntity();
|
||||
#elif MC_VER <= MC_1_21_10
|
||||
Camera camera = Minecraft.getInstance().gameRenderer.getMainCamera();
|
||||
Entity entity = camera.getEntity();
|
||||
#else
|
||||
Camera camera = Minecraft.getInstance().gameRenderer.getMainCamera();
|
||||
Entity entity = camera.entity();
|
||||
#endif
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
boolean cameraNotInFluid = cameraNotInFluid(mc);
|
||||
#else
|
||||
boolean cameraNotInFluid = cameraNotInFluid(camera);
|
||||
#endif
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
boolean isSpecialFog = entity.isPotionActive(MobEffects.BLINDNESS);
|
||||
#else
|
||||
boolean isSpecialFog = (entity instanceof LivingEntity) && ((LivingEntity) entity).hasEffect(MobEffects.BLINDNESS);
|
||||
#endif
|
||||
|
||||
boolean cancelFog = !isSpecialFog;
|
||||
cancelFog = cancelFog && cameraNotInFluid;
|
||||
#if MC_VER <= MC_1_12_2
|
||||
cancelFog = cancelFog && startCoords == 0; // 0 = terrain fog
|
||||
#elif MC_VER < MC_1_21_6
|
||||
cancelFog = cancelFog && (fogMode == FogRenderer.FogMode.FOG_TERRAIN);
|
||||
#endif
|
||||
|
||||
cancelFog = cancelFog && !SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class).isFogStateSpecial();
|
||||
cancelFog = cancelFog && !Config.Client.Advanced.Graphics.Fog.enableVanillaFog.get();
|
||||
|
||||
|
||||
|
||||
IImmersivePortalsAccessor immersivePortals = ModAccessorInjector.INSTANCE.get(IImmersivePortalsAccessor.class);
|
||||
if (immersivePortals != null
|
||||
&& immersivePortals.isRenderingPortal())
|
||||
{
|
||||
cancelFog = false;
|
||||
}
|
||||
|
||||
return cancelFog;
|
||||
}
|
||||
#if MC_VER <= MC_1_12_2
|
||||
private static boolean cameraNotInFluid(Minecraft mc)
|
||||
#else
|
||||
private static boolean cameraNotInFluid(Camera camera)
|
||||
#endif
|
||||
{
|
||||
#if MC_VER <= MC_1_12_2
|
||||
boolean cameraNotInFluid = mc.getRenderViewEntity() != null && !mc.world.getBlockState(mc.getRenderViewEntity().getPosition()).getMaterial().isLiquid();
|
||||
#elif MC_VER < MC_1_17_1
|
||||
FluidState fluidState = camera.getFluidInCamera();
|
||||
boolean cameraNotInFluid = fluidState.isEmpty();
|
||||
#else
|
||||
FogType fogTypes = camera.getFluidInCamera();
|
||||
boolean cameraNotInFluid = fogTypes == FogType.NONE;
|
||||
#endif
|
||||
|
||||
return cameraNotInFluid;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+21
-21
@@ -299,27 +299,27 @@ public class BlazeDebugWireframeRenderer extends AbstractDebugWireframeRenderer
|
||||
|
||||
// render //
|
||||
|
||||
//try (RenderPass renderPass = commandEncoder.createRenderPass(
|
||||
// this::getRenderPassName,
|
||||
// BlazeDhMetaRenderer.INSTANCE.dhColorTextureWrapper.textureView,
|
||||
// /*optionalClearColorAsInt*/ OptionalInt.empty(),
|
||||
// BlazeDhMetaRenderer.INSTANCE.dhDepthTextureWrapper.textureView,
|
||||
// /*optionalDepthValueAsDouble*/ OptionalDouble.empty()))
|
||||
//{
|
||||
// // Bind instance data //
|
||||
// renderPass.setUniform("uniformBlock", this.uniformBuffer);
|
||||
//
|
||||
// renderPass.setPipeline(this.pipeline);
|
||||
// renderPass.setIndexBuffer(this.boxIndexBuffer, VertexFormat.IndexType.INT);
|
||||
//
|
||||
// renderPass.setVertexBuffer(0, this.boxVertexBuffer);
|
||||
//
|
||||
// renderPass.drawIndexed(
|
||||
// /*indexStart*/ 0,
|
||||
// /*firstIndex*/0,
|
||||
// /*indexCount*/BOX_OUTLINE_INDICES.length,
|
||||
// /*instanceCount*/1);
|
||||
//}
|
||||
try (RenderPass renderPass = commandEncoder.createRenderPass(
|
||||
this::getRenderPassName,
|
||||
BlazeDhMetaRenderer.INSTANCE.dhColorTextureWrapper.textureView,
|
||||
/*optionalClearColorAsInt*/ OptionalInt.empty(),
|
||||
BlazeDhMetaRenderer.INSTANCE.dhDepthTextureWrapper.textureView,
|
||||
/*optionalDepthValueAsDouble*/ OptionalDouble.empty()))
|
||||
{
|
||||
// Bind instance data //
|
||||
renderPass.setUniform("uniformBlock", this.uniformBuffer);
|
||||
|
||||
renderPass.setPipeline(this.pipeline);
|
||||
renderPass.setIndexBuffer(this.boxIndexBuffer, VertexFormat.IndexType.INT);
|
||||
|
||||
renderPass.setVertexBuffer(0, this.boxVertexBuffer);
|
||||
|
||||
renderPass.drawIndexed(
|
||||
/*indexStart*/ 0,
|
||||
/*firstIndex*/0,
|
||||
/*indexCount*/BOX_OUTLINE_INDICES.length,
|
||||
/*instanceCount*/1);
|
||||
}
|
||||
}
|
||||
private String getRenderPassName() { return "distantHorizons:McDebugRenderer"; }
|
||||
|
||||
|
||||
+188
-170
@@ -57,6 +57,7 @@ import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.logging.f3.F3Screen;
|
||||
import com.seibel.distanthorizons.core.render.RenderParams;
|
||||
import com.seibel.distanthorizons.core.render.RenderThreadTaskHandler;
|
||||
import com.seibel.distanthorizons.core.render.renderer.GenericRenderObjectFactory;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.render.objects.IDhGenericObjectVertexBufferContainer;
|
||||
import com.seibel.distanthorizons.core.render.renderer.RenderableBoxGroup;
|
||||
@@ -330,194 +331,194 @@ public class BlazeDhGenericObjectRenderer implements IDhGenericRenderer
|
||||
@Override
|
||||
public void render(RenderParams renderEventParam, IProfilerWrapper profiler, boolean renderingWithSsao)
|
||||
{
|
||||
//==============//
|
||||
// render setup //
|
||||
//==============//
|
||||
//#region
|
||||
|
||||
profiler.push("setup");
|
||||
|
||||
this.init();
|
||||
|
||||
ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeGenericRenderSetupEvent.class, renderEventParam);
|
||||
|
||||
Vec3d camPos = MC_RENDER.getCameraExactPosition();
|
||||
|
||||
//#endregion
|
||||
|
||||
if (BlazeDhMetaRenderer.INSTANCE.dhColorTextureWrapper.isEmpty()
|
||||
|| BlazeDhMetaRenderer.INSTANCE.dhDepthTextureWrapper.isEmpty())
|
||||
try (IProfilerWrapper.IProfileBlock generic_profile = profiler.push("setup"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//===========//
|
||||
// rendering //
|
||||
//===========//
|
||||
//#region
|
||||
|
||||
Collection<RenderableBoxGroup> boxList = this.boxGroupById.values();
|
||||
for (RenderableBoxGroup boxGroup : boxList)
|
||||
{
|
||||
// validation //
|
||||
|
||||
// shouldn't happen, but just in case
|
||||
if (boxGroup == null)
|
||||
|
||||
//==============//
|
||||
// render setup //
|
||||
//==============//
|
||||
//#region
|
||||
|
||||
this.init();
|
||||
|
||||
ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeGenericRenderSetupEvent.class, renderEventParam);
|
||||
|
||||
Vec3d camPos = MC_RENDER.getCameraExactPosition();
|
||||
|
||||
//#endregion
|
||||
|
||||
if (BlazeDhMetaRenderer.INSTANCE.dhColorTextureWrapper.isEmpty()
|
||||
|| BlazeDhMetaRenderer.INSTANCE.dhDepthTextureWrapper.isEmpty())
|
||||
{
|
||||
continue;
|
||||
return;
|
||||
}
|
||||
|
||||
// skip boxes that shouldn't render this pass
|
||||
if (boxGroup.ssaoEnabled != renderingWithSsao)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
profiler.popPush("render prep");
|
||||
boxGroup.preRender(renderEventParam); // called even if the group is inactive, so the group can be activate if desired
|
||||
|
||||
// ignore inactive groups
|
||||
if (!boxGroup.active)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
//===========//
|
||||
// rendering //
|
||||
//===========//
|
||||
//#region
|
||||
|
||||
// allow API users to cancel this object's rendering
|
||||
boolean cancelRendering = ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeGenericObjectRenderEvent.class, new DhApiBeforeGenericObjectRenderEvent.EventParam(renderEventParam, boxGroup));
|
||||
if (cancelRendering)
|
||||
Collection<RenderableBoxGroup> boxList = this.boxGroupById.values();
|
||||
for (RenderableBoxGroup boxGroup : boxList)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// update instanced data if needed
|
||||
{
|
||||
boxGroup.tryUpdateInstancedDataAsync();
|
||||
// validation //
|
||||
|
||||
// skip groups that haven't been uploaded yet
|
||||
if (boxGroup.vertexBufferContainer.getState() != IDhGenericObjectVertexBufferContainer.EState.RENDER)
|
||||
// shouldn't happen, but just in case
|
||||
if (boxGroup == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// skip boxes that shouldn't render this pass
|
||||
if (boxGroup.ssaoEnabled != renderingWithSsao)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
profiler.popPush("render prep");
|
||||
boxGroup.preRender(renderEventParam); // called even if the group is inactive, so the group can be activate if desired
|
||||
|
||||
// ignore inactive groups
|
||||
if (!boxGroup.active)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// allow API users to cancel this object's rendering
|
||||
boolean cancelRendering = ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeGenericObjectRenderEvent.class, new DhApiBeforeGenericObjectRenderEvent.EventParam(renderEventParam, boxGroup));
|
||||
if (cancelRendering)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// update instanced data if needed
|
||||
{
|
||||
boxGroup.tryUpdateInstancedDataAsync();
|
||||
|
||||
// skip groups that haven't been uploaded yet
|
||||
if (boxGroup.vertexBufferContainer.getState() != IDhGenericObjectVertexBufferContainer.EState.RENDER)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DhApiRenderableBoxGroupShading shading = boxGroup.shading;
|
||||
if (shading == null)
|
||||
{
|
||||
shading = DEFAULT_SHADING;
|
||||
}
|
||||
|
||||
// uniforms
|
||||
{
|
||||
int uniformBufferSize = new Std140SizeCalculator()
|
||||
.putIVec3() // uOffsetChunk
|
||||
.putVec3() // uOffsetSubChunk
|
||||
.putIVec3() // uCameraPosChunk
|
||||
.putVec3() // uCameraPosSubChunk
|
||||
|
||||
.putVec3() // aTranslateChunk
|
||||
.putVec3() // aTranslateSubChunk
|
||||
|
||||
.putMat4f() // uProjectionMvm
|
||||
.putInt() // uSkyLight
|
||||
.putInt() // uBlockLight
|
||||
|
||||
.putFloat() // uNorthShading
|
||||
.putFloat() // uSouthShading
|
||||
.putFloat() // uEastShading
|
||||
.putFloat() // uWestShading
|
||||
.putFloat() // uTopShading
|
||||
.putFloat() // uBottomShading
|
||||
.get();
|
||||
|
||||
|
||||
// create data //
|
||||
|
||||
Mat4f projectionMvmMatrix = new Mat4f(renderEventParam.dhProjectionMatrix);
|
||||
projectionMvmMatrix.multiply(renderEventParam.dhModelViewMatrix);
|
||||
|
||||
|
||||
// upload data //
|
||||
|
||||
ByteBuffer buffer = ByteBuffer.allocateDirect(uniformBufferSize);
|
||||
buffer.order(ByteOrder.nativeOrder());
|
||||
buffer = Std140Builder.intoBuffer(buffer)
|
||||
.putIVec3(
|
||||
LodUtil.getChunkPosFromDouble(boxGroup.getOriginBlockPos().x),
|
||||
LodUtil.getChunkPosFromDouble(boxGroup.getOriginBlockPos().y),
|
||||
LodUtil.getChunkPosFromDouble(boxGroup.getOriginBlockPos().z)
|
||||
) // uOffsetChunk
|
||||
.putVec3(
|
||||
LodUtil.getSubChunkPosFromDouble(boxGroup.getOriginBlockPos().x),
|
||||
LodUtil.getSubChunkPosFromDouble(boxGroup.getOriginBlockPos().y),
|
||||
LodUtil.getSubChunkPosFromDouble(boxGroup.getOriginBlockPos().z)
|
||||
) // uOffsetSubChunk
|
||||
.putIVec3(
|
||||
LodUtil.getChunkPosFromDouble(camPos.x),
|
||||
LodUtil.getChunkPosFromDouble(camPos.y),
|
||||
LodUtil.getChunkPosFromDouble(camPos.z)
|
||||
) // uCameraPosChunk
|
||||
.putVec3(
|
||||
LodUtil.getSubChunkPosFromDouble(camPos.x),
|
||||
LodUtil.getSubChunkPosFromDouble(camPos.y),
|
||||
LodUtil.getSubChunkPosFromDouble(camPos.z)
|
||||
) // uCameraPosSubChunk
|
||||
|
||||
.putMat4f(projectionMvmMatrix.createJomlMatrix()) // uProjectionMvm
|
||||
.putInt(boxGroup.getSkyLight()) // uSkyLight
|
||||
.putInt(boxGroup.getBlockLight()) // uBlockLight
|
||||
|
||||
.putFloat(shading.north)
|
||||
.putFloat(shading.south)
|
||||
.putFloat(shading.east)
|
||||
.putFloat(shading.west)
|
||||
.putFloat(shading.top)
|
||||
.putFloat(shading.bottom)
|
||||
|
||||
.get()
|
||||
;
|
||||
|
||||
this.vertUniformBuffer = BlazeUniformUtil.createBuffer("vertUniformBlock", uniformBufferSize, this.vertUniformBuffer);
|
||||
GpuBufferSlice bufferSlice = new GpuBufferSlice(this.vertUniformBuffer, 0, uniformBufferSize);
|
||||
|
||||
COMMAND_ENCODER.writeToBuffer(bufferSlice, buffer);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// render //
|
||||
|
||||
profiler.popPush("rendering");
|
||||
try (IProfilerWrapper.IProfileBlock namespace_profile = profiler.push(boxGroup.getResourceLocationNamespace());
|
||||
IProfilerWrapper.IProfileBlock location_profile = profiler.push(boxGroup.getResourceLocationPath()))
|
||||
{
|
||||
this.renderBoxGroupInstanced(renderEventParam, boxGroup, profiler);
|
||||
}
|
||||
|
||||
boxGroup.postRender(renderEventParam);
|
||||
}
|
||||
|
||||
|
||||
DhApiRenderableBoxGroupShading shading = boxGroup.shading;
|
||||
if (shading == null)
|
||||
{
|
||||
shading = DEFAULT_SHADING;
|
||||
}
|
||||
|
||||
// uniforms
|
||||
{
|
||||
int uniformBufferSize = new Std140SizeCalculator()
|
||||
.putIVec3() // uOffsetChunk
|
||||
.putVec3() // uOffsetSubChunk
|
||||
.putIVec3() // uCameraPosChunk
|
||||
.putVec3() // uCameraPosSubChunk
|
||||
|
||||
.putVec3() // aTranslateChunk
|
||||
.putVec3() // aTranslateSubChunk
|
||||
|
||||
.putMat4f() // uProjectionMvm
|
||||
.putInt() // uSkyLight
|
||||
.putInt() // uBlockLight
|
||||
|
||||
.putFloat() // uNorthShading
|
||||
.putFloat() // uSouthShading
|
||||
.putFloat() // uEastShading
|
||||
.putFloat() // uWestShading
|
||||
.putFloat() // uTopShading
|
||||
.putFloat() // uBottomShading
|
||||
.get();
|
||||
|
||||
|
||||
// create data //
|
||||
|
||||
Mat4f projectionMvmMatrix = new Mat4f(renderEventParam.dhProjectionMatrix);
|
||||
projectionMvmMatrix.multiply(renderEventParam.dhModelViewMatrix);
|
||||
|
||||
|
||||
// upload data //
|
||||
|
||||
ByteBuffer buffer = ByteBuffer.allocateDirect(uniformBufferSize);
|
||||
buffer.order(ByteOrder.nativeOrder());
|
||||
buffer = Std140Builder.intoBuffer(buffer)
|
||||
.putIVec3(
|
||||
LodUtil.getChunkPosFromDouble(boxGroup.getOriginBlockPos().x),
|
||||
LodUtil.getChunkPosFromDouble(boxGroup.getOriginBlockPos().y),
|
||||
LodUtil.getChunkPosFromDouble(boxGroup.getOriginBlockPos().z)
|
||||
) // uOffsetChunk
|
||||
.putVec3(
|
||||
LodUtil.getSubChunkPosFromDouble(boxGroup.getOriginBlockPos().x),
|
||||
LodUtil.getSubChunkPosFromDouble(boxGroup.getOriginBlockPos().y),
|
||||
LodUtil.getSubChunkPosFromDouble(boxGroup.getOriginBlockPos().z)
|
||||
) // uOffsetSubChunk
|
||||
.putIVec3(
|
||||
LodUtil.getChunkPosFromDouble(camPos.x),
|
||||
LodUtil.getChunkPosFromDouble(camPos.y),
|
||||
LodUtil.getChunkPosFromDouble(camPos.z)
|
||||
) // uCameraPosChunk
|
||||
.putVec3(
|
||||
LodUtil.getSubChunkPosFromDouble(camPos.x),
|
||||
LodUtil.getSubChunkPosFromDouble(camPos.y),
|
||||
LodUtil.getSubChunkPosFromDouble(camPos.z)
|
||||
) // uCameraPosSubChunk
|
||||
|
||||
.putMat4f(projectionMvmMatrix.createJomlMatrix()) // uProjectionMvm
|
||||
.putInt(boxGroup.getSkyLight()) // uSkyLight
|
||||
.putInt(boxGroup.getBlockLight()) // uBlockLight
|
||||
|
||||
.putFloat(shading.north)
|
||||
.putFloat(shading.south)
|
||||
.putFloat(shading.east)
|
||||
.putFloat(shading.west)
|
||||
.putFloat(shading.top)
|
||||
.putFloat(shading.bottom)
|
||||
|
||||
.get()
|
||||
;
|
||||
|
||||
this.vertUniformBuffer = BlazeUniformUtil.createBuffer("vertUniformBlock", uniformBufferSize, this.vertUniformBuffer);
|
||||
GpuBufferSlice bufferSlice = new GpuBufferSlice(this.vertUniformBuffer, 0, uniformBufferSize);
|
||||
|
||||
COMMAND_ENCODER.writeToBuffer(bufferSlice, buffer);
|
||||
}
|
||||
//#endregion
|
||||
|
||||
|
||||
|
||||
//==========//
|
||||
// clean up //
|
||||
//==========//
|
||||
//region
|
||||
|
||||
// render //
|
||||
profiler.popPush("cleanup");
|
||||
|
||||
profiler.popPush("rendering");
|
||||
profiler.push(boxGroup.getResourceLocationNamespace());
|
||||
profiler.push(boxGroup.getResourceLocationPath());
|
||||
ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeGenericRenderCleanupEvent.class, renderEventParam);
|
||||
|
||||
this.renderBoxGroupInstanced(renderEventParam, boxGroup, profiler);
|
||||
|
||||
profiler.pop(); // resource path
|
||||
profiler.pop(); // resource namespace
|
||||
|
||||
boxGroup.postRender(renderEventParam);
|
||||
//endregion
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
|
||||
|
||||
//==========//
|
||||
// clean up //
|
||||
//==========//
|
||||
//region
|
||||
|
||||
profiler.popPush("cleanup");
|
||||
|
||||
ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeGenericRenderCleanupEvent.class, renderEventParam);
|
||||
|
||||
profiler.pop();
|
||||
|
||||
//endregion
|
||||
}
|
||||
private String getRenderPassName() { return "distantHorizons:McGenericObjectRenderer"; }
|
||||
|
||||
@@ -545,8 +546,6 @@ public class BlazeDhGenericObjectRenderer implements IDhGenericRenderer
|
||||
|
||||
// update instance data //
|
||||
|
||||
profiler.push("vertex setup");
|
||||
|
||||
BlazeGenericObjectVertexContainer container = (BlazeGenericObjectVertexContainer) boxGroup.vertexBufferContainer;
|
||||
|
||||
LightMapWrapper lightMapWrapper = (LightMapWrapper) renderEventParam.lightmap;
|
||||
@@ -556,7 +555,6 @@ public class BlazeDhGenericObjectRenderer implements IDhGenericRenderer
|
||||
|
||||
|
||||
// Bind instance data //
|
||||
profiler.popPush("binding");
|
||||
|
||||
|
||||
renderPass.setUniform("vertUniformBlock", this.vertUniformBuffer);
|
||||
@@ -568,7 +566,6 @@ public class BlazeDhGenericObjectRenderer implements IDhGenericRenderer
|
||||
renderPass.setVertexBuffer(0, container.vboGpuBuffer);
|
||||
|
||||
// Draw instanced
|
||||
profiler.popPush("render");
|
||||
if (container.uploadedBoxCount > 0)
|
||||
{
|
||||
renderPass.drawIndexed(
|
||||
@@ -579,7 +576,6 @@ public class BlazeDhGenericObjectRenderer implements IDhGenericRenderer
|
||||
|
||||
}
|
||||
}
|
||||
profiler.pop();
|
||||
}
|
||||
|
||||
//endregion
|
||||
@@ -620,5 +616,27 @@ public class BlazeDhGenericObjectRenderer implements IDhGenericRenderer
|
||||
|
||||
|
||||
|
||||
//================//
|
||||
// base overrides //
|
||||
//================//
|
||||
//region
|
||||
|
||||
@Override
|
||||
public void close()
|
||||
{
|
||||
// close is called outside the render thread and buffer closing must be done on the render thread
|
||||
RenderThreadTaskHandler.INSTANCE.queueRunningOnRenderThread("Generic Obj Cleanup", () ->
|
||||
{
|
||||
if (this.vertUniformBuffer != null)
|
||||
{
|
||||
this.vertUniformBuffer.close();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
}
|
||||
#endif
|
||||
+22
-4
@@ -6,13 +6,16 @@ public class BlazeDhMetaRenderer {}
|
||||
#else
|
||||
|
||||
import com.mojang.blaze3d.textures.GpuTexture;
|
||||
import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiAfterColorDepthTextureCreatedEvent;
|
||||
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiTextureCreatedParam;
|
||||
import com.seibel.distanthorizons.common.render.blaze.apply.BlazeDhApplyRenderer;
|
||||
import com.seibel.distanthorizons.common.render.blaze.wrappers.texture.BlazeTextureWrapper;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.render.RenderParams;
|
||||
import com.seibel.distanthorizons.core.util.ColorUtil;
|
||||
import com.seibel.distanthorizons.coreapi.util.ColorUtil;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.render.renderPass.IDhMetaRenderer;
|
||||
import com.seibel.distanthorizons.coreapi.DependencyInjection.ApiEventInjector;
|
||||
import net.minecraft.client.Minecraft;
|
||||
|
||||
import java.awt.*;
|
||||
@@ -57,9 +60,24 @@ public class BlazeDhMetaRenderer implements IDhMetaRenderer
|
||||
@Override
|
||||
public void runRenderPassSetup(RenderParams renderParams)
|
||||
{
|
||||
// textures
|
||||
this.dhDepthTextureWrapper.tryCreateOrResize();
|
||||
this.dhColorTextureWrapper.tryCreateOrResize();
|
||||
int oldWidth = this.dhDepthTextureWrapper.getWidth();
|
||||
int oldHeight = this.dhDepthTextureWrapper.getHeight();
|
||||
|
||||
boolean texturesChanged = false;
|
||||
texturesChanged = this.dhDepthTextureWrapper.tryCreateOrResize() | texturesChanged;
|
||||
texturesChanged = this.dhColorTextureWrapper.tryCreateOrResize() | texturesChanged;
|
||||
|
||||
if (texturesChanged)
|
||||
{
|
||||
int newTextureWidth = MC_RENDER.getTargetFramebufferViewportWidth();
|
||||
int newTextureHeight = MC_RENDER.getTargetFramebufferViewportHeight();
|
||||
|
||||
DhApiTextureCreatedParam textureCreatedParam = new DhApiTextureCreatedParam(
|
||||
oldWidth, oldHeight,
|
||||
newTextureWidth, newTextureHeight
|
||||
);
|
||||
ApiEventInjector.INSTANCE.fireAllEvents(DhApiAfterColorDepthTextureCreatedEvent.class, textureCreatedParam);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+193
-194
@@ -19,6 +19,7 @@ import com.mojang.blaze3d.systems.RenderPass;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.VertexFormat;
|
||||
import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiBeforeBufferRenderEvent;
|
||||
import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiBeforeRenderPassEvent;
|
||||
import com.seibel.distanthorizons.common.render.blaze.util.BlazeDhVertexFormatUtil;
|
||||
import com.seibel.distanthorizons.common.render.blaze.util.BlazeUniformUtil;
|
||||
import com.seibel.distanthorizons.common.render.blaze.wrappers.RenderPipelineBuilderWrapper;
|
||||
@@ -151,210 +152,208 @@ public class BlazeDhTerrainRenderer implements IDhTerrainRenderer
|
||||
{
|
||||
this.tryInit();
|
||||
|
||||
|
||||
profiler.push("vert unique uniforms");
|
||||
try(IProfilerWrapper.IProfileBlock terrain_profile = profiler.push("terrain render"))
|
||||
{
|
||||
// create data //
|
||||
|
||||
for (int lodIndex = 0; lodIndex < bufferContainers.size(); lodIndex++)
|
||||
profiler.popPush("vert unique uniforms");
|
||||
{
|
||||
LodBufferContainer bufferContainer = bufferContainers.get(lodIndex);
|
||||
bufferContainer.uniformContainer.tryUpload();
|
||||
}
|
||||
}
|
||||
|
||||
profiler.popPush("vert share uniforms");
|
||||
{
|
||||
Mat4f combinedMatrix = new Mat4f(renderEventParam.dhProjectionMatrix);
|
||||
combinedMatrix.multiply(renderEventParam.dhModelViewMatrix);
|
||||
|
||||
float earthCurveRatio = Config.Client.Advanced.Graphics.Experimental.earthCurveRatio.get();
|
||||
if (earthCurveRatio < -1.0f || earthCurveRatio > 1.0f)
|
||||
{
|
||||
earthCurveRatio = /*6371KM*/ 6371000.0f / earthCurveRatio;
|
||||
}
|
||||
else
|
||||
{
|
||||
// disable curvature if the config value is between -1 and 1
|
||||
earthCurveRatio = 0.0f;
|
||||
}
|
||||
|
||||
|
||||
// upload data //
|
||||
|
||||
int uniformBufferSize = new Std140SizeCalculator()
|
||||
.putInt() // uIsWhiteWorld
|
||||
|
||||
.putFloat() // uWorldYOffset
|
||||
.putFloat() // uMircoOffset
|
||||
.putFloat() // uEarthRadius
|
||||
|
||||
.putVec3() // uCameraPos
|
||||
.putMat4f() // uCombinedMatrix
|
||||
.get();
|
||||
|
||||
ByteBuffer buffer = MemoryUtil.memAlloc(uniformBufferSize);
|
||||
buffer.order(ByteOrder.nativeOrder());
|
||||
Std140Builder.intoBuffer(buffer)
|
||||
.putInt(0) // uIsWhiteWorld
|
||||
|
||||
.putFloat((float) renderEventParam.worldYOffset) // uWorldYOffset
|
||||
.putFloat(0.01f) // uMircoOffset // 0.01 block offset
|
||||
.putFloat(earthCurveRatio) // uEarthRadius
|
||||
|
||||
.putVec3(
|
||||
(float)renderEventParam.exactCameraPosition.x,
|
||||
(float)renderEventParam.exactCameraPosition.y,
|
||||
(float)renderEventParam.exactCameraPosition.z) // uCameraPos
|
||||
.putMat4f(combinedMatrix.createJomlMatrix()) // uCombinedMatrix
|
||||
.get();
|
||||
|
||||
this.vertSharedUniformBuffer = BlazeUniformUtil.createBuffer("vertSharedUniformBlock", uniformBufferSize, this.vertSharedUniformBuffer);
|
||||
GpuBufferSlice bufferSlice = new GpuBufferSlice(this.vertSharedUniformBuffer, 0, uniformBufferSize);
|
||||
|
||||
COMMAND_ENCODER.writeToBuffer(bufferSlice, buffer);
|
||||
|
||||
MemoryUtil.memFree(buffer);
|
||||
}
|
||||
|
||||
profiler.popPush("set frag uniforms");
|
||||
{
|
||||
int uniformBufferSize = new Std140SizeCalculator()
|
||||
.putFloat() // uClipDistance
|
||||
.putFloat() // uNoiseIntensity
|
||||
.putInt() // uNoiseSteps
|
||||
.putInt() // uNoiseDropoff
|
||||
.putInt() // uDitherDhRendering
|
||||
.putInt() // uNoiseEnabled
|
||||
.get();
|
||||
|
||||
|
||||
// create data //
|
||||
|
||||
float dhNearClipDistance = RenderUtil.getNearClipPlaneInBlocks();
|
||||
if (!Config.Client.Advanced.Debugging.lodOnlyMode.get())
|
||||
{
|
||||
// this added value prevents the near clip plane and discard circle from touching, which looks bad
|
||||
dhNearClipDistance += 16f;
|
||||
}
|
||||
|
||||
|
||||
// upload data //
|
||||
|
||||
ByteBuffer buffer = MemoryUtil.memAlloc(uniformBufferSize);
|
||||
buffer.order(ByteOrder.nativeOrder());
|
||||
buffer = Std140Builder.intoBuffer(buffer)
|
||||
.putFloat(dhNearClipDistance) // uClipDistance
|
||||
.putFloat(Config.Client.Advanced.Graphics.NoiseTexture.noiseIntensity.get()) // uNoiseIntensity
|
||||
.putInt(Config.Client.Advanced.Graphics.NoiseTexture.noiseSteps.get()) // uNoiseSteps
|
||||
.putInt(Config.Client.Advanced.Graphics.NoiseTexture.noiseDropoff.get()) // uNoiseDropoff
|
||||
.putInt(Config.Client.Advanced.Graphics.Quality.ditherDhFade.get() ? 1 : 0) // uDitherDhRendering
|
||||
.putInt(Config.Client.Advanced.Graphics.NoiseTexture.enableNoiseTexture.get() ? 1 : 0) // uNoiseEnabled
|
||||
.get()
|
||||
;
|
||||
|
||||
this.fragUniformBuffer = BlazeUniformUtil.createBuffer("fragUniformBlock", uniformBufferSize, this.fragUniformBuffer);
|
||||
GpuBufferSlice bufferSlice = new GpuBufferSlice(this.fragUniformBuffer, 0, uniformBufferSize);
|
||||
|
||||
COMMAND_ENCODER.writeToBuffer(bufferSlice, buffer);
|
||||
MemoryUtil.memFree(buffer);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// render pass setup
|
||||
{
|
||||
profiler.popPush("setup");
|
||||
|
||||
// create a render pass
|
||||
try(RenderPass renderPass = COMMAND_ENCODER.createRenderPass(
|
||||
this::getRenderPassName,
|
||||
BlazeDhMetaRenderer.INSTANCE.dhColorTextureWrapper.textureView,
|
||||
/*optionalClearColorAsInt*/ OptionalInt.empty(),
|
||||
BlazeDhMetaRenderer.INSTANCE.dhDepthTextureWrapper.textureView,
|
||||
/*optionalDepthValueAsDouble*/ OptionalDouble.empty())
|
||||
)
|
||||
{
|
||||
LightMapWrapper lightMapWrapper = (LightMapWrapper) renderEventParam.lightmap;
|
||||
BlazeTextureViewWrapper lightmapTextureViewWrapper = lightMapWrapper.getTextureViewWrapper();
|
||||
renderPass.bindTexture("uLightMap", lightmapTextureViewWrapper.textureView, lightmapTextureViewWrapper.textureSampler);
|
||||
|
||||
// set pipeline
|
||||
renderPass.setPipeline(opaquePass ? this.opaquePipeline : this.transparentPipeline);
|
||||
|
||||
// shared uniforms
|
||||
renderPass.setUniform("fragUniformBlock", this.fragUniformBuffer);
|
||||
renderPass.setUniform("vertSharedUniformBlock", this.vertSharedUniformBuffer);
|
||||
|
||||
|
||||
// create data //
|
||||
|
||||
for (int lodIndex = 0; lodIndex < bufferContainers.size(); lodIndex++)
|
||||
{
|
||||
profiler.popPush("binding");
|
||||
|
||||
LodBufferContainer bufferContainer = bufferContainers.get(lodIndex);
|
||||
BlazeLodUniformBufferWrapper uniformWrapper = (BlazeLodUniformBufferWrapper)bufferContainer.uniformContainer;
|
||||
|
||||
boolean columnBuilderDebugEnabled = Config.Client.Advanced.Debugging.ColumnBuilderDebugging.columnBuilderDebugEnable.get();
|
||||
if (columnBuilderDebugEnabled)
|
||||
{
|
||||
if (DhSectionPos.getDetailLevel(bufferContainer.pos) == Config.Client.Advanced.Debugging.ColumnBuilderDebugging.columnBuilderDebugDetailLevel.get()
|
||||
&& DhSectionPos.getX(bufferContainer.pos) == Config.Client.Advanced.Debugging.ColumnBuilderDebugging.columnBuilderDebugXPos.get()
|
||||
&& DhSectionPos.getZ(bufferContainer.pos) == Config.Client.Advanced.Debugging.ColumnBuilderDebugging.columnBuilderDebugZPos.get())
|
||||
{
|
||||
int breakpoint = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
renderPass.setUniform("vertUniqueUniformBlock", uniformWrapper.gpuBuffer);
|
||||
|
||||
|
||||
|
||||
profiler.popPush("rendering");
|
||||
|
||||
// render each buffer
|
||||
IVertexBufferWrapper[] bufferWrapperList = opaquePass ? bufferContainer.vboOpaqueWrappers : bufferContainer.vboTransparentWrappers;
|
||||
for (int i = 0; i < bufferWrapperList.length; i++)
|
||||
{
|
||||
BlazeVertexBufferWrapper bufferWrapper = (BlazeVertexBufferWrapper) bufferWrapperList[i];
|
||||
if (!bufferWrapper.uploaded
|
||||
|| bufferWrapper.vertexCount == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// fire render event
|
||||
{
|
||||
Vec3d camPos = renderEventParam.exactCameraPosition;
|
||||
Vec3f modelPos = new Vec3f(
|
||||
(float) (bufferContainer.minCornerBlockPos.getX() - camPos.x),
|
||||
(float) (bufferContainer.minCornerBlockPos.getY() - camPos.y),
|
||||
(float) (bufferContainer.minCornerBlockPos.getZ() - camPos.z));
|
||||
ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeBufferRenderEvent.class, new DhApiBeforeBufferRenderEvent.EventParam(renderEventParam, modelPos));
|
||||
}
|
||||
|
||||
renderPass.setIndexBuffer(bufferWrapper.getIndexGpuBuffer(), VertexFormat.IndexType.INT);
|
||||
renderPass.setVertexBuffer(0, bufferWrapper.vertexGpuBuffer); // vertex buffer can only be "0" lol
|
||||
|
||||
if (!bufferWrapper.vertexGpuBuffer.isClosed())
|
||||
{
|
||||
renderPass.drawIndexed(
|
||||
/*indexStart*/ 0,
|
||||
/*firstIndex*/0,
|
||||
/*indexCount*/bufferWrapper.indexCount,
|
||||
/*instanceCount*/1);
|
||||
}
|
||||
}
|
||||
bufferContainer.uniformContainer.tryUpload();
|
||||
}
|
||||
}
|
||||
|
||||
profiler.popPush("vert share uniforms");
|
||||
{
|
||||
Mat4f combinedMatrix = new Mat4f(renderEventParam.dhProjectionMatrix);
|
||||
combinedMatrix.multiply(renderEventParam.dhModelViewMatrix);
|
||||
|
||||
float earthCurveRatio = Config.Client.Advanced.Graphics.Experimental.earthCurveRatio.get();
|
||||
if (earthCurveRatio < -1.0f || earthCurveRatio > 1.0f)
|
||||
{
|
||||
earthCurveRatio = /*6371KM*/ 6371000.0f / earthCurveRatio;
|
||||
}
|
||||
else
|
||||
{
|
||||
// disable curvature if the config value is between -1 and 1
|
||||
earthCurveRatio = 0.0f;
|
||||
}
|
||||
|
||||
|
||||
// upload data //
|
||||
|
||||
int uniformBufferSize = new Std140SizeCalculator()
|
||||
.putInt() // uIsWhiteWorld
|
||||
|
||||
.putFloat() // uWorldYOffset
|
||||
.putFloat() // uMircoOffset
|
||||
.putFloat() // uEarthRadius
|
||||
|
||||
.putVec3() // uCameraPos
|
||||
.putMat4f() // uCombinedMatrix
|
||||
.get();
|
||||
|
||||
ByteBuffer buffer = MemoryUtil.memAlloc(uniformBufferSize);
|
||||
buffer.order(ByteOrder.nativeOrder());
|
||||
Std140Builder.intoBuffer(buffer)
|
||||
.putInt(0) // uIsWhiteWorld
|
||||
|
||||
.putFloat((float) renderEventParam.worldYOffset) // uWorldYOffset
|
||||
.putFloat(0.01f) // uMircoOffset // 0.01 block offset
|
||||
.putFloat(earthCurveRatio) // uEarthRadius
|
||||
|
||||
.putVec3(
|
||||
(float) renderEventParam.exactCameraPosition.x,
|
||||
(float) renderEventParam.exactCameraPosition.y,
|
||||
(float) renderEventParam.exactCameraPosition.z) // uCameraPos
|
||||
.putMat4f(combinedMatrix.createJomlMatrix()) // uCombinedMatrix
|
||||
.get();
|
||||
|
||||
this.vertSharedUniformBuffer = BlazeUniformUtil.createBuffer("vertSharedUniformBlock", uniformBufferSize, this.vertSharedUniformBuffer);
|
||||
GpuBufferSlice bufferSlice = new GpuBufferSlice(this.vertSharedUniformBuffer, 0, uniformBufferSize);
|
||||
|
||||
COMMAND_ENCODER.writeToBuffer(bufferSlice, buffer);
|
||||
|
||||
MemoryUtil.memFree(buffer);
|
||||
}
|
||||
|
||||
profiler.popPush("set frag uniforms");
|
||||
{
|
||||
int uniformBufferSize = new Std140SizeCalculator()
|
||||
.putFloat() // uClipDistance
|
||||
.putFloat() // uNoiseIntensity
|
||||
.putInt() // uNoiseSteps
|
||||
.putInt() // uNoiseDropoff
|
||||
.putInt() // uDitherDhRendering
|
||||
.putInt() // uNoiseEnabled
|
||||
.get();
|
||||
|
||||
|
||||
// create data //
|
||||
|
||||
float dhNearClipDistance = RenderUtil.getNearClipPlaneInBlocks();
|
||||
if (!Config.Client.Advanced.Debugging.lodOnlyMode.get())
|
||||
{
|
||||
// this added value prevents the near clip plane and discard circle from touching, which looks bad
|
||||
dhNearClipDistance += 16f;
|
||||
}
|
||||
|
||||
|
||||
// upload data //
|
||||
|
||||
ByteBuffer buffer = MemoryUtil.memAlloc(uniformBufferSize);
|
||||
buffer.order(ByteOrder.nativeOrder());
|
||||
buffer = Std140Builder.intoBuffer(buffer)
|
||||
.putFloat(dhNearClipDistance) // uClipDistance
|
||||
.putFloat(Config.Client.Advanced.Graphics.NoiseTexture.noiseIntensity.get()) // uNoiseIntensity
|
||||
.putInt(Config.Client.Advanced.Graphics.NoiseTexture.noiseSteps.get()) // uNoiseSteps
|
||||
.putInt(Config.Client.Advanced.Graphics.NoiseTexture.noiseDropoff.get()) // uNoiseDropoff
|
||||
.putInt(Config.Client.Advanced.Graphics.Quality.ditherDhFade.get() ? 1 : 0) // uDitherDhRendering
|
||||
.putInt(Config.Client.Advanced.Graphics.NoiseTexture.enableNoiseTexture.get() ? 1 : 0) // uNoiseEnabled
|
||||
.get()
|
||||
;
|
||||
|
||||
this.fragUniformBuffer = BlazeUniformUtil.createBuffer("fragUniformBlock", uniformBufferSize, this.fragUniformBuffer);
|
||||
GpuBufferSlice bufferSlice = new GpuBufferSlice(this.fragUniformBuffer, 0, uniformBufferSize);
|
||||
|
||||
COMMAND_ENCODER.writeToBuffer(bufferSlice, buffer);
|
||||
MemoryUtil.memFree(buffer);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// render pass setup
|
||||
{
|
||||
profiler.popPush("rendering");
|
||||
|
||||
ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeRenderPassEvent.class, renderEventParam);
|
||||
|
||||
// create a render pass
|
||||
try (RenderPass renderPass = COMMAND_ENCODER.createRenderPass(
|
||||
this::getRenderPassName,
|
||||
BlazeDhMetaRenderer.INSTANCE.dhColorTextureWrapper.textureView,
|
||||
/*optionalClearColorAsInt*/ OptionalInt.empty(),
|
||||
BlazeDhMetaRenderer.INSTANCE.dhDepthTextureWrapper.textureView,
|
||||
/*optionalDepthValueAsDouble*/ OptionalDouble.empty())
|
||||
)
|
||||
{
|
||||
LightMapWrapper lightMapWrapper = (LightMapWrapper) renderEventParam.lightmap;
|
||||
BlazeTextureViewWrapper lightmapTextureViewWrapper = lightMapWrapper.getTextureViewWrapper();
|
||||
renderPass.bindTexture("uLightMap", lightmapTextureViewWrapper.textureView, lightmapTextureViewWrapper.textureSampler);
|
||||
|
||||
// set pipeline
|
||||
renderPass.setPipeline(opaquePass ? this.opaquePipeline : this.transparentPipeline);
|
||||
|
||||
// shared uniforms
|
||||
renderPass.setUniform("fragUniformBlock", this.fragUniformBuffer);
|
||||
renderPass.setUniform("vertSharedUniformBlock", this.vertSharedUniformBuffer);
|
||||
|
||||
|
||||
|
||||
for (int lodIndex = 0; lodIndex < bufferContainers.size(); lodIndex++)
|
||||
{
|
||||
LodBufferContainer bufferContainer = bufferContainers.get(lodIndex);
|
||||
BlazeLodUniformBufferWrapper uniformWrapper = (BlazeLodUniformBufferWrapper) bufferContainer.uniformContainer;
|
||||
|
||||
boolean columnBuilderDebugEnabled = Config.Client.Advanced.Debugging.ColumnBuilderDebugging.columnBuilderDebugEnable.get();
|
||||
if (columnBuilderDebugEnabled)
|
||||
{
|
||||
if (DhSectionPos.getDetailLevel(bufferContainer.pos) == Config.Client.Advanced.Debugging.ColumnBuilderDebugging.columnBuilderDebugDetailLevel.get()
|
||||
&& DhSectionPos.getX(bufferContainer.pos) == Config.Client.Advanced.Debugging.ColumnBuilderDebugging.columnBuilderDebugXPos.get()
|
||||
&& DhSectionPos.getZ(bufferContainer.pos) == Config.Client.Advanced.Debugging.ColumnBuilderDebugging.columnBuilderDebugZPos.get())
|
||||
{
|
||||
int breakpoint = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
renderPass.setUniform("vertUniqueUniformBlock", uniformWrapper.gpuBuffer);
|
||||
|
||||
|
||||
|
||||
// render each buffer
|
||||
IVertexBufferWrapper[] bufferWrapperList = opaquePass ? bufferContainer.vboOpaqueWrappers : bufferContainer.vboTransparentWrappers;
|
||||
for (int i = 0; i < bufferWrapperList.length; i++)
|
||||
{
|
||||
BlazeVertexBufferWrapper bufferWrapper = (BlazeVertexBufferWrapper) bufferWrapperList[i];
|
||||
if (!bufferWrapper.uploaded
|
||||
|| bufferWrapper.vertexCount == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// fire render event
|
||||
{
|
||||
Vec3d camPos = renderEventParam.exactCameraPosition;
|
||||
Vec3f modelPos = new Vec3f(
|
||||
(float) (bufferContainer.minCornerBlockPos.getX() - camPos.x),
|
||||
(float) (bufferContainer.minCornerBlockPos.getY() - camPos.y),
|
||||
(float) (bufferContainer.minCornerBlockPos.getZ() - camPos.z));
|
||||
ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeBufferRenderEvent.class, new DhApiBeforeBufferRenderEvent.EventParam(renderEventParam, modelPos));
|
||||
}
|
||||
|
||||
renderPass.setIndexBuffer(bufferWrapper.getIndexGpuBuffer(), VertexFormat.IndexType.INT);
|
||||
renderPass.setVertexBuffer(0, bufferWrapper.vertexGpuBuffer); // vertex buffer can only be "0" lol
|
||||
|
||||
if (!bufferWrapper.vertexGpuBuffer.isClosed())
|
||||
{
|
||||
renderPass.drawIndexed(
|
||||
/*indexStart*/ 0,
|
||||
/*firstIndex*/0,
|
||||
/*indexCount*/bufferWrapper.indexCount,
|
||||
/*instanceCount*/1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
profiler.pop();
|
||||
}
|
||||
private String getIndexBufferName() { return "distantHorizons:LodIndexBuffer"; }
|
||||
private String getRenderPassName() { return "distantHorizons:McLodRenderer"; }
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ import com.seibel.distanthorizons.common.render.openGl.glObject.enums.GLEnums;
|
||||
import com.seibel.distanthorizons.core.render.RenderThreadTaskHandler;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.render.objects.IDhGenericObjectVertexBufferContainer;
|
||||
import com.seibel.distanthorizons.core.render.renderer.RenderableBoxGroup;
|
||||
import com.seibel.distanthorizons.core.util.ColorUtil;
|
||||
import com.seibel.distanthorizons.coreapi.util.ColorUtil;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
+22
-5
@@ -1,15 +1,26 @@
|
||||
package com.seibel.distanthorizons.common.render.blaze.wrappers;
|
||||
|
||||
|
||||
#if MC_VER <= MC_1_21_10
|
||||
public class RenderPipelineBuilderWrapper {}
|
||||
|
||||
#else
|
||||
|
||||
import com.mojang.blaze3d.pipeline.BlendFunction;
|
||||
import com.mojang.blaze3d.pipeline.ColorTargetState;
|
||||
import com.mojang.blaze3d.pipeline.DepthStencilState;
|
||||
import com.mojang.blaze3d.pipeline.RenderPipeline;
|
||||
import com.mojang.blaze3d.platform.CompareOp;
|
||||
import com.mojang.blaze3d.platform.PolygonMode;
|
||||
import com.mojang.blaze3d.shaders.UniformType;
|
||||
import com.mojang.blaze3d.vertex.VertexFormat;
|
||||
import net.minecraft.resources.Identifier;
|
||||
|
||||
#if MC_VER <= MC_1_21_11
|
||||
import com.mojang.blaze3d.platform.DepthTestFunction;
|
||||
#else
|
||||
import com.mojang.blaze3d.pipeline.ColorTargetState;
|
||||
import com.mojang.blaze3d.pipeline.DepthStencilState;
|
||||
import com.mojang.blaze3d.platform.CompareOp;
|
||||
#endif
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Optional;
|
||||
@@ -206,15 +217,20 @@ public class RenderPipelineBuilderWrapper
|
||||
this.blazePipelineBuilder.withoutBlend();
|
||||
}
|
||||
|
||||
DepthTestFunction depthTestFunction;
|
||||
switch (this.depthTest)
|
||||
{
|
||||
case NONE:
|
||||
|
||||
depthTestFunction = DepthTestFunction.NO_DEPTH_TEST;
|
||||
break;
|
||||
case LESS:
|
||||
depthTestFunction = DepthTestFunction.LESS_DEPTH_TEST;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new UnsupportedOperationException("No depth test defined for type ["+this.depthTest+"].");
|
||||
}
|
||||
this.blazepipelineBuilder.withDepthTest(RenderPipelineBuilderWrapper.EDhDepthTest.NONE);
|
||||
this.blazePipelineBuilder.withDepthTestFunction(depthTestFunction);
|
||||
|
||||
#else
|
||||
|
||||
@@ -349,3 +365,4 @@ public class RenderPipelineBuilderWrapper
|
||||
|
||||
|
||||
}
|
||||
#endif
|
||||
+1
-6
@@ -140,7 +140,7 @@ public class BlazeVertexBufferWrapper implements IVertexBufferWrapper
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uploadIndexBuffer(ByteBuffer buffer, int vertexCount)
|
||||
public void uploadIndexBuffer(ByteBuffer indexBuffer, int vertexCount)
|
||||
{
|
||||
int oldIndexCount = this.indexCount;
|
||||
// 4 vertices per face, but 6 indices (IE 2 triangles) per face, aka need to multiply by 1.5
|
||||
@@ -169,17 +169,12 @@ public class BlazeVertexBufferWrapper implements IVertexBufferWrapper
|
||||
this.indexGpuBuffer.close();
|
||||
}
|
||||
|
||||
ByteBuffer indexBuffer = IndexBufferBuilder.createBuffer(this.vertexCount);
|
||||
|
||||
int usage = GpuBuffer.USAGE_COPY_DST
|
||||
| GpuBuffer.USAGE_INDEX;
|
||||
this.indexGpuBuffer = GPU_DEVICE.createBuffer(BlazeVertexBufferWrapper::getIndexBufferName, usage, indexBuffer.capacity());
|
||||
|
||||
GpuBufferSlice bufferSlice = new GpuBufferSlice(this.indexGpuBuffer, /*offset*/ 0, indexBuffer.capacity());
|
||||
COMMAND_ENCODER.writeToBuffer(bufferSlice, indexBuffer);
|
||||
|
||||
MemoryUtil.memFree(indexBuffer);
|
||||
|
||||
}
|
||||
}
|
||||
private static String getIndexBufferName() { return "distantHorizons:LodIndexBuffer"; }
|
||||
|
||||
+38
-28
@@ -13,7 +13,7 @@ import com.mojang.blaze3d.textures.*;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.util.ColorUtil;
|
||||
import com.seibel.distanthorizons.coreapi.util.ColorUtil;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
|
||||
import java.util.OptionalDouble;
|
||||
@@ -79,42 +79,52 @@ public class BlazeTextureWrapper
|
||||
//=======//
|
||||
//region
|
||||
|
||||
/** does nothing if the texture is already created and the correct size */
|
||||
public void tryCreateOrResize()
|
||||
/**
|
||||
* does nothing if the texture is already created and the correct size
|
||||
* @return true if the texture was (re)created
|
||||
*/
|
||||
public boolean tryCreateOrResize()
|
||||
{
|
||||
this.tryCreateTexture();
|
||||
boolean textureChanged = this.tryCreateTexture();
|
||||
this.tryCreateSampler();
|
||||
return textureChanged;
|
||||
}
|
||||
private void tryCreateTexture()
|
||||
private boolean tryCreateTexture()
|
||||
{
|
||||
int viewWidth = MC_RENDER.getTargetFramebufferViewportWidth();
|
||||
int viewHeight = MC_RENDER.getTargetFramebufferViewportHeight();
|
||||
|
||||
if (this.texture == null
|
||||
|| this.width != viewWidth
|
||||
|| this.height != viewHeight)
|
||||
if (this.texture != null
|
||||
&& this.width == viewWidth
|
||||
&& this.height == viewHeight)
|
||||
{
|
||||
if (this.texture != null)
|
||||
{
|
||||
this.texture.close();
|
||||
this.textureView.close();
|
||||
}
|
||||
|
||||
this.width = viewWidth;
|
||||
this.height = viewHeight;
|
||||
|
||||
int usage = GpuTexture.USAGE_COPY_DST
|
||||
| GpuTexture.USAGE_TEXTURE_BINDING
|
||||
| GpuTexture.USAGE_COPY_SRC
|
||||
| GpuTexture.USAGE_RENDER_ATTACHMENT;
|
||||
this.texture = GPU_DEVICE.createTexture(this.name,
|
||||
usage,
|
||||
this.textureFormat,
|
||||
viewWidth, viewHeight,
|
||||
/*depthOrLayers*/ 1, /*mipLevels*/ 1
|
||||
);
|
||||
this.textureView = GPU_DEVICE.createTextureView(this.texture);
|
||||
// no changes needed
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (this.texture != null)
|
||||
{
|
||||
this.texture.close();
|
||||
this.textureView.close();
|
||||
}
|
||||
|
||||
this.width = viewWidth;
|
||||
this.height = viewHeight;
|
||||
|
||||
int usage = GpuTexture.USAGE_COPY_DST
|
||||
| GpuTexture.USAGE_TEXTURE_BINDING
|
||||
| GpuTexture.USAGE_COPY_SRC
|
||||
| GpuTexture.USAGE_RENDER_ATTACHMENT;
|
||||
this.texture = GPU_DEVICE.createTexture(this.name,
|
||||
usage,
|
||||
this.textureFormat,
|
||||
viewWidth, viewHeight,
|
||||
/*depthOrLayers*/ 1, /*mipLevels*/ 1
|
||||
);
|
||||
this.textureView = GPU_DEVICE.createTextureView(this.texture);
|
||||
|
||||
return true;
|
||||
}
|
||||
private void tryCreateSampler()
|
||||
{
|
||||
|
||||
+22
-25
@@ -10,10 +10,10 @@ import com.seibel.distanthorizons.common.render.openGl.glObject.GLProxy;
|
||||
import com.seibel.distanthorizons.common.render.openGl.glObject.GlDhFramebuffer;
|
||||
import com.seibel.distanthorizons.common.render.openGl.glObject.texture.*;
|
||||
import com.seibel.distanthorizons.common.render.openGl.postProcessing.apply.GlDhApplyShader;
|
||||
import com.seibel.distanthorizons.common.render.openGl.terrain.GlDhTerrainShaderProgram;
|
||||
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftGLWrapper;
|
||||
import com.seibel.distanthorizons.common.wrappers.misc.LightMapWrapper;
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
@@ -21,7 +21,7 @@ import com.seibel.distanthorizons.core.render.DhApiRenderProxy;
|
||||
import com.seibel.distanthorizons.core.render.RenderParams;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.ILightMapWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.AbstractOptifineAccessor;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IOptifineAccessor;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.render.renderPass.IDhMetaRenderer;
|
||||
import com.seibel.distanthorizons.coreapi.DependencyInjection.ApiEventInjector;
|
||||
import com.seibel.distanthorizons.coreapi.DependencyInjection.OverrideInjector;
|
||||
@@ -45,6 +45,8 @@ public class GlDhMetaRenderer implements IDhMetaRenderer
|
||||
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
|
||||
private static final MinecraftGLWrapper GLMC = MinecraftGLWrapper.INSTANCE;
|
||||
|
||||
private static final IOptifineAccessor OPTIFINE_ACCESSOR = ModAccessorInjector.INSTANCE.get(IOptifineAccessor.class);
|
||||
|
||||
|
||||
private int activeFramebufferId = -1;
|
||||
private int activeColorTextureId = -1;
|
||||
@@ -242,7 +244,7 @@ public class GlDhMetaRenderer implements IDhMetaRenderer
|
||||
|
||||
|
||||
// create or get the frame buffer
|
||||
if (AbstractOptifineAccessor.optifinePresent())
|
||||
if (OPTIFINE_ACCESSOR != null)
|
||||
{
|
||||
// use MC/Optifine's default Framebuffer so shaders won't remove the LODs
|
||||
int currentFramebufferId = MC_RENDER.getTargetFramebuffer();
|
||||
@@ -383,31 +385,26 @@ public class GlDhMetaRenderer implements IDhMetaRenderer
|
||||
|
||||
|
||||
|
||||
// needs to be fired after all the textures have been created/bound
|
||||
boolean clearTextures = !ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeTextureClearEvent.class, renderParams);
|
||||
if (clearTextures)
|
||||
GL32.glClearDepth(1.0);
|
||||
|
||||
float[] clearColorValues = new float[4];
|
||||
GL32.glGetFloatv(GL32.GL_COLOR_CLEAR_VALUE, clearColorValues);
|
||||
GL32.glClearColor(clearColorValues[0], clearColorValues[1], clearColorValues[2], 1.0f);
|
||||
|
||||
if (this.usingMcFramebuffer
|
||||
&& framebufferOverride == null)
|
||||
{
|
||||
GL32.glClearDepth(1.0);
|
||||
//// Due to using MC/Optifine's framebuffer we need to re-bind the depth texture,
|
||||
//// otherwise we'll be writing to MC/Optifine's depth texture which causes rendering issues
|
||||
//this.framebuffer.addDepthAttachment(this.depthTexture.getTextureId(), EDhDepthBufferFormat.DEPTH32F.isCombinedStencil());
|
||||
|
||||
float[] clearColorValues = new float[4];
|
||||
GL32.glGetFloatv(GL32.GL_COLOR_CLEAR_VALUE, clearColorValues);
|
||||
GL32.glClearColor(clearColorValues[0], clearColorValues[1], clearColorValues[2], 1.0f);
|
||||
|
||||
if (this.usingMcFramebuffer
|
||||
&& framebufferOverride == null)
|
||||
{
|
||||
//// Due to using MC/Optifine's framebuffer we need to re-bind the depth texture,
|
||||
//// otherwise we'll be writing to MC/Optifine's depth texture which causes rendering issues
|
||||
//this.framebuffer.addDepthAttachment(this.depthTexture.getTextureId(), EDhDepthBufferFormat.DEPTH32F.isCombinedStencil());
|
||||
|
||||
|
||||
// don't clear the color texture, that removes the sky
|
||||
GL32.glClear(GL32.GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
else if (firstPass)
|
||||
{
|
||||
GL32.glClear(GL32.GL_COLOR_BUFFER_BIT | GL32.GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
// don't clear the color texture, that removes the sky
|
||||
GL32.glClear(GL32.GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
else if (firstPass)
|
||||
{
|
||||
GL32.glClear(GL32.GL_COLOR_BUFFER_BIT | GL32.GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+201
-181
@@ -413,133 +413,133 @@ public class GlGenericObjectRenderer implements IDhGenericRenderer
|
||||
|
||||
|
||||
// render setup //
|
||||
profiler.push("setup");
|
||||
|
||||
this.init();
|
||||
|
||||
ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeGenericRenderSetupEvent.class, renderEventParam);
|
||||
|
||||
|
||||
boolean renderWireframe = Config.Client.Advanced.Debugging.renderWireframe.get();
|
||||
if (renderWireframe)
|
||||
try (IProfilerWrapper.IProfileBlock setup_profile = profiler.push("setup"))
|
||||
{
|
||||
GL32.glPolygonMode(GL32.GL_FRONT_AND_BACK, GL32.GL_LINE);
|
||||
GLMC.disableFaceCulling();
|
||||
}
|
||||
else
|
||||
{
|
||||
GL32.glPolygonMode(GL32.GL_FRONT_AND_BACK, GL32.GL_FILL);
|
||||
GLMC.enableFaceCulling();
|
||||
}
|
||||
|
||||
GLMC.enableBlend();
|
||||
GL32.glBlendEquation(GL32.GL_FUNC_ADD);
|
||||
GLMC.glBlendFuncSeparate(GL32.GL_SRC_ALPHA, GL32.GL_ONE_MINUS_SRC_ALPHA, GL32.GL_ONE, GL32.GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
IDhApiGenericObjectShaderProgram shaderProgram = this.instancedRenderingAvailable ? this.instancedShaderProgram : this.directShaderProgram;
|
||||
IDhApiGenericObjectShaderProgram shaderProgramOverride = OverrideInjector.INSTANCE.get(IDhApiGenericObjectShaderProgram.class);
|
||||
if (shaderProgramOverride != null && shaderProgram.overrideThisFrame())
|
||||
{
|
||||
shaderProgram = shaderProgramOverride;
|
||||
}
|
||||
|
||||
shaderProgram.bind(renderEventParam);
|
||||
shaderProgram.bindVertexBuffer(this.boxVertexBuffer.getId());
|
||||
|
||||
this.boxIndexBuffer.bind();
|
||||
|
||||
Vec3d camPos = MC_RENDER.getCameraExactPosition();
|
||||
|
||||
|
||||
|
||||
// rendering //
|
||||
|
||||
Collection<RenderableBoxGroup> boxList = this.boxGroupById.values();
|
||||
for (RenderableBoxGroup boxGroup : boxList)
|
||||
{
|
||||
// validation //
|
||||
|
||||
// shouldn't happen, but just in case
|
||||
if (boxGroup == null)
|
||||
this.init();
|
||||
|
||||
ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeGenericRenderSetupEvent.class, renderEventParam);
|
||||
|
||||
|
||||
boolean renderWireframe = Config.Client.Advanced.Debugging.renderWireframe.get();
|
||||
if (renderWireframe)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// skip boxes that shouldn't render this pass
|
||||
if (boxGroup.ssaoEnabled != renderingWithSsao)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
profiler.popPush("render prep");
|
||||
boxGroup.preRender(renderEventParam); // called even if the group is inactive, so the group can be activate if desired
|
||||
|
||||
// ignore inactive groups
|
||||
if (!boxGroup.active)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// allow API users to cancel this object's rendering
|
||||
boolean cancelRendering = ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeGenericObjectRenderEvent.class, new DhApiBeforeGenericObjectRenderEvent.EventParam(renderEventParam, boxGroup));
|
||||
if (cancelRendering)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// update instanced data if needed
|
||||
if (this.instancedRenderingAvailable)
|
||||
{
|
||||
boxGroup.tryUpdateInstancedDataAsync();
|
||||
|
||||
// skip groups that haven't been uploaded yet
|
||||
if (boxGroup.vertexBufferContainer.getState() != GlGenericObjectVertexContainer.EState.RENDER)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// render //
|
||||
|
||||
profiler.popPush("rendering");
|
||||
profiler.push(boxGroup.getResourceLocationNamespace());
|
||||
profiler.push(boxGroup.getResourceLocationPath());
|
||||
if (this.instancedRenderingAvailable)
|
||||
{
|
||||
this.renderBoxGroupInstanced(shaderProgram, renderEventParam, boxGroup, camPos, profiler);
|
||||
GL32.glPolygonMode(GL32.GL_FRONT_AND_BACK, GL32.GL_LINE);
|
||||
GLMC.disableFaceCulling();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.renderBoxGroupDirect(shaderProgram, renderEventParam, boxGroup, camPos, profiler);
|
||||
GL32.glPolygonMode(GL32.GL_FRONT_AND_BACK, GL32.GL_FILL);
|
||||
GLMC.enableFaceCulling();
|
||||
}
|
||||
profiler.pop(); // resource path
|
||||
profiler.pop(); // resource namespace
|
||||
|
||||
boxGroup.postRender(renderEventParam);
|
||||
GLMC.enableBlend();
|
||||
GL32.glBlendEquation(GL32.GL_FUNC_ADD);
|
||||
GLMC.glBlendFuncSeparate(GL32.GL_SRC_ALPHA, GL32.GL_ONE_MINUS_SRC_ALPHA, GL32.GL_ONE, GL32.GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
IDhApiGenericObjectShaderProgram shaderProgram = this.instancedRenderingAvailable ? this.instancedShaderProgram : this.directShaderProgram;
|
||||
IDhApiGenericObjectShaderProgram shaderProgramOverride = OverrideInjector.INSTANCE.get(IDhApiGenericObjectShaderProgram.class);
|
||||
if (shaderProgramOverride != null && shaderProgram.overrideThisFrame())
|
||||
{
|
||||
shaderProgram = shaderProgramOverride;
|
||||
}
|
||||
|
||||
shaderProgram.bind(renderEventParam);
|
||||
shaderProgram.bindVertexBuffer(this.boxVertexBuffer.getId());
|
||||
|
||||
this.boxIndexBuffer.bind();
|
||||
|
||||
Vec3d camPos = MC_RENDER.getCameraExactPosition();
|
||||
|
||||
|
||||
|
||||
// rendering //
|
||||
|
||||
Collection<RenderableBoxGroup> boxList = this.boxGroupById.values();
|
||||
for (RenderableBoxGroup boxGroup : boxList)
|
||||
{
|
||||
// validation //
|
||||
|
||||
// shouldn't happen, but just in case
|
||||
if (boxGroup == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// skip boxes that shouldn't render this pass
|
||||
if (boxGroup.ssaoEnabled != renderingWithSsao)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
profiler.popPush("render prep");
|
||||
boxGroup.preRender(renderEventParam); // called even if the group is inactive, so the group can be activate if desired
|
||||
|
||||
// ignore inactive groups
|
||||
if (!boxGroup.active)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// allow API users to cancel this object's rendering
|
||||
boolean cancelRendering = ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeGenericObjectRenderEvent.class, new DhApiBeforeGenericObjectRenderEvent.EventParam(renderEventParam, boxGroup));
|
||||
if (cancelRendering)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// update instanced data if needed
|
||||
if (this.instancedRenderingAvailable)
|
||||
{
|
||||
boxGroup.tryUpdateInstancedDataAsync();
|
||||
|
||||
// skip groups that haven't been uploaded yet
|
||||
if (boxGroup.vertexBufferContainer.getState() != GlGenericObjectVertexContainer.EState.RENDER)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// render //
|
||||
|
||||
profiler.popPush("rendering");
|
||||
try (IProfilerWrapper.IProfileBlock namespace_profile = profiler.push(boxGroup.getResourceLocationNamespace());
|
||||
IProfilerWrapper.IProfileBlock location_profile = profiler.push(boxGroup.getResourceLocationPath()))
|
||||
{
|
||||
if (this.instancedRenderingAvailable)
|
||||
{
|
||||
this.renderBoxGroupInstanced(shaderProgram, renderEventParam, boxGroup, camPos, profiler);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.renderBoxGroupDirect(shaderProgram, renderEventParam, boxGroup, camPos, profiler);
|
||||
}
|
||||
}
|
||||
|
||||
boxGroup.postRender(renderEventParam);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//==========//
|
||||
// clean up //
|
||||
//==========//
|
||||
|
||||
profiler.popPush("cleanup");
|
||||
|
||||
ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeGenericRenderCleanupEvent.class, renderEventParam);
|
||||
|
||||
if (renderWireframe)
|
||||
{
|
||||
// default back to GL_FILL since all other rendering uses it
|
||||
GL32.glPolygonMode(GL32.GL_FRONT_AND_BACK, GL32.GL_FILL);
|
||||
GLMC.enableFaceCulling();
|
||||
}
|
||||
|
||||
shaderProgram.unbind();
|
||||
}
|
||||
|
||||
|
||||
|
||||
//==========//
|
||||
// clean up //
|
||||
//==========//
|
||||
|
||||
profiler.popPush("cleanup");
|
||||
|
||||
ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeGenericRenderCleanupEvent.class, renderEventParam);
|
||||
|
||||
if (renderWireframe)
|
||||
{
|
||||
// default back to GL_FILL since all other rendering uses it
|
||||
GL32.glPolygonMode(GL32.GL_FRONT_AND_BACK, GL32.GL_FILL);
|
||||
GLMC.enableFaceCulling();
|
||||
}
|
||||
|
||||
shaderProgram.unbind();
|
||||
|
||||
profiler.pop();
|
||||
}
|
||||
|
||||
//endregion
|
||||
@@ -556,72 +556,71 @@ public class GlGenericObjectRenderer implements IDhGenericRenderer
|
||||
RenderableBoxGroup boxGroup, Vec3d camPos,
|
||||
IProfilerWrapper profiler)
|
||||
{
|
||||
// update instance data //
|
||||
|
||||
profiler.push("vertex setup");
|
||||
|
||||
DhApiRenderableBoxGroupShading shading = boxGroup.shading;
|
||||
if (shading == null)
|
||||
try (IProfilerWrapper.IProfileBlock render_profile = profiler.push("vertex setup"))
|
||||
{
|
||||
shading = DEFAULT_SHADING;
|
||||
}
|
||||
|
||||
shaderProgram.fillIndirectUniformData(
|
||||
|
||||
// update instance data //
|
||||
DhApiRenderableBoxGroupShading shading = boxGroup.shading;
|
||||
if (shading == null)
|
||||
{
|
||||
shading = DEFAULT_SHADING;
|
||||
}
|
||||
|
||||
shaderProgram.fillIndirectUniformData(
|
||||
renderEventParam,
|
||||
shading, boxGroup,
|
||||
camPos);
|
||||
|
||||
|
||||
|
||||
// Bind instance data //
|
||||
profiler.popPush("binding");
|
||||
|
||||
GlGenericObjectVertexContainer container = (GlGenericObjectVertexContainer)(boxGroup.vertexBufferContainer);
|
||||
|
||||
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, container.color);
|
||||
GL32.glEnableVertexAttribArray(1);
|
||||
GL32.glVertexAttribPointer(1, 4, GL32.GL_FLOAT, false, 4 * Float.BYTES, 0);
|
||||
this.vertexAttribDivisor(1, 1);
|
||||
|
||||
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, container.scale);
|
||||
GL32.glEnableVertexAttribArray(2);
|
||||
this.vertexAttribDivisor(2, 1);
|
||||
GL32.glVertexAttribPointer(2, 3, GL32.GL_FLOAT, false, 3 * Float.BYTES, 0);
|
||||
|
||||
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, container.chunkPos);
|
||||
GL32.glEnableVertexAttribArray(3);
|
||||
this.vertexAttribDivisor(3, 1);
|
||||
GL32.glVertexAttribIPointer(3, 3, GL32.GL_INT, 3 * Integer.BYTES, 0);
|
||||
|
||||
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, container.subChunkPos);
|
||||
GL32.glEnableVertexAttribArray(4);
|
||||
this.vertexAttribDivisor(4, 1);
|
||||
GL32.glVertexAttribPointer(4, 3, GL32.GL_FLOAT, false, 3 * Float.BYTES, 0);
|
||||
|
||||
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, container.material);
|
||||
GL32.glEnableVertexAttribArray(5);
|
||||
this.vertexAttribDivisor(5, 1);
|
||||
GL32.glVertexAttribIPointer(5, 1, GL32.GL_BYTE, Byte.BYTES, 0);
|
||||
|
||||
|
||||
// Draw instanced
|
||||
profiler.popPush("render");
|
||||
if (container.uploadedBoxCount > 0)
|
||||
{
|
||||
GL32.glDrawElementsInstanced(GL32.GL_TRIANGLES, BOX_INDICES.length, GL32.GL_UNSIGNED_INT, 0, container.uploadedBoxCount);
|
||||
|
||||
|
||||
|
||||
// Bind instance data //
|
||||
profiler.popPush("binding");
|
||||
|
||||
GlGenericObjectVertexContainer container = (GlGenericObjectVertexContainer) (boxGroup.vertexBufferContainer);
|
||||
|
||||
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, container.color);
|
||||
GL32.glEnableVertexAttribArray(1);
|
||||
GL32.glVertexAttribPointer(1, 4, GL32.GL_FLOAT, false, 4 * Float.BYTES, 0);
|
||||
this.vertexAttribDivisor(1, 1);
|
||||
|
||||
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, container.scale);
|
||||
GL32.glEnableVertexAttribArray(2);
|
||||
this.vertexAttribDivisor(2, 1);
|
||||
GL32.glVertexAttribPointer(2, 3, GL32.GL_FLOAT, false, 3 * Float.BYTES, 0);
|
||||
|
||||
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, container.chunkPos);
|
||||
GL32.glEnableVertexAttribArray(3);
|
||||
this.vertexAttribDivisor(3, 1);
|
||||
GL32.glVertexAttribIPointer(3, 3, GL32.GL_INT, 3 * Integer.BYTES, 0);
|
||||
|
||||
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, container.subChunkPos);
|
||||
GL32.glEnableVertexAttribArray(4);
|
||||
this.vertexAttribDivisor(4, 1);
|
||||
GL32.glVertexAttribPointer(4, 3, GL32.GL_FLOAT, false, 3 * Float.BYTES, 0);
|
||||
|
||||
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, container.material);
|
||||
GL32.glEnableVertexAttribArray(5);
|
||||
this.vertexAttribDivisor(5, 1);
|
||||
GL32.glVertexAttribIPointer(5, 1, GL32.GL_BYTE, Byte.BYTES, 0);
|
||||
|
||||
|
||||
// Draw instanced
|
||||
profiler.popPush("render");
|
||||
if (container.uploadedBoxCount > 0)
|
||||
{
|
||||
GL32.glDrawElementsInstanced(GL32.GL_TRIANGLES, BOX_INDICES.length, GL32.GL_UNSIGNED_INT, 0, container.uploadedBoxCount);
|
||||
}
|
||||
|
||||
|
||||
// Clean up
|
||||
profiler.popPush("cleanup");
|
||||
|
||||
GL32.glDisableVertexAttribArray(1);
|
||||
GL32.glDisableVertexAttribArray(2);
|
||||
GL32.glDisableVertexAttribArray(3);
|
||||
GL32.glDisableVertexAttribArray(4);
|
||||
GL32.glDisableVertexAttribArray(5);
|
||||
}
|
||||
|
||||
|
||||
// Clean up
|
||||
profiler.popPush("cleanup");
|
||||
|
||||
GL32.glDisableVertexAttribArray(1);
|
||||
GL32.glDisableVertexAttribArray(2);
|
||||
GL32.glDisableVertexAttribArray(3);
|
||||
GL32.glDisableVertexAttribArray(4);
|
||||
GL32.glDisableVertexAttribArray(5);
|
||||
|
||||
profiler.pop();
|
||||
}
|
||||
/**
|
||||
* Clean way to handle both {@link GL33#glVertexAttribDivisor} and {@link ARBInstancedArrays#glVertexAttribDivisorARB}
|
||||
@@ -689,8 +688,6 @@ public class GlGenericObjectRenderer implements IDhGenericRenderer
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
profiler.pop();
|
||||
}
|
||||
|
||||
//endregion
|
||||
@@ -751,4 +748,27 @@ public class GlGenericObjectRenderer implements IDhGenericRenderer
|
||||
|
||||
|
||||
|
||||
//================//
|
||||
// base overrides //
|
||||
//================//
|
||||
//region
|
||||
|
||||
@Override
|
||||
public void close()
|
||||
{
|
||||
if (this.boxVertexBuffer != null)
|
||||
{
|
||||
this.boxVertexBuffer.close();
|
||||
}
|
||||
|
||||
if (this.boxIndexBuffer != null)
|
||||
{
|
||||
this.boxIndexBuffer.close();
|
||||
}
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
+40
-9
@@ -21,13 +21,17 @@ package com.seibel.distanthorizons.common.render.openGl.glObject;
|
||||
|
||||
import com.seibel.distanthorizons.api.enums.config.EDhApiGLErrorHandlingMode;
|
||||
import com.seibel.distanthorizons.api.enums.config.EDhApiGpuUploadMethod;
|
||||
import com.seibel.distanthorizons.api.enums.config.EDhApiLoggerLevel;
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.config.types.ConfigEntry;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.jar.EPlatform;
|
||||
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.util.objects.GLMessages.*;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IIrisAccessor;
|
||||
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
import org.lwjgl.opengl.GL;
|
||||
@@ -46,10 +50,30 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
*/
|
||||
public class GLProxy
|
||||
{
|
||||
public static final DhLogger LOGGER = new DhLoggerBuilder()
|
||||
.fileLevelConfig(Config.Common.Logging.logRendererGLEventToFile)
|
||||
.chatLevelConfig(Config.Common.Logging.logRendererGLEventToChat)
|
||||
.build();
|
||||
private static final IIrisAccessor IRIS_ACCESSOR = ModAccessorInjector.INSTANCE.get(IIrisAccessor.class);
|
||||
|
||||
public static final DhLogger LOGGER;
|
||||
static
|
||||
{
|
||||
DhLoggerBuilder loggerBuilder = new DhLoggerBuilder();
|
||||
loggerBuilder.fileLevelConfig(Config.Common.Logging.logRendererGLEventToFile);
|
||||
|
||||
// don't send chat messages if Iris is present since
|
||||
// Iris is known to cause (harmless) GL errors
|
||||
// and this can confuse users
|
||||
boolean irisPresent = (IRIS_ACCESSOR != null);
|
||||
if (!irisPresent)
|
||||
{
|
||||
loggerBuilder.chatLevelConfig(Config.Common.Logging.logRendererGLEventToChat);
|
||||
}
|
||||
|
||||
LOGGER = loggerBuilder.build();
|
||||
|
||||
if (irisPresent)
|
||||
{
|
||||
LOGGER.info("Iris detected, Distant Horizons OpenGL error logging won't be sent in the chat due to Iris throwing known (harmless) OpenGL errors. This is a bug with Iris, not Distant Horizons.");
|
||||
}
|
||||
}
|
||||
|
||||
public static final Set<String> LOGGED_GL_MESSAGES = Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>());
|
||||
|
||||
@@ -238,7 +262,7 @@ public class GLProxy
|
||||
//region
|
||||
|
||||
/** this method is called on the render thread at the point of the GL Error */
|
||||
private static void logMessage(GLMessage msg)
|
||||
private static void logMessage(GLMessage glMessage)
|
||||
{
|
||||
EDhApiGLErrorHandlingMode errorHandlingMode = Config.Client.Advanced.Debugging.OpenGl.glErrorHandlingMode.get();
|
||||
if (errorHandlingMode == EDhApiGLErrorHandlingMode.IGNORE)
|
||||
@@ -249,19 +273,26 @@ public class GLProxy
|
||||
|
||||
|
||||
boolean onlyLogOnce = Config.Client.Advanced.Debugging.OpenGl.onlyLogGlErrorsOnce.get();
|
||||
String errorMessage = "GL ERROR [" + msg.id + "] from [" + msg.source + "]: [" + msg.message + "]"+(onlyLogOnce ? " this message will only be logged once" : "")+".";
|
||||
if (onlyLogOnce
|
||||
&& !LOGGED_GL_MESSAGES.add(errorMessage))
|
||||
&& !LOGGED_GL_MESSAGES.add(glMessage.message))
|
||||
{
|
||||
// this message has already been logged
|
||||
return;
|
||||
}
|
||||
|
||||
String errorMessage = "GL ERROR [" + glMessage.id + "] from [" + glMessage.source + "]: [" + glMessage.message + "].";
|
||||
if (onlyLogOnce)
|
||||
{
|
||||
errorMessage += " This message will only be logged once.";
|
||||
errorMessage += " Note: Distant Horizons will catch and log OpenGL errors from other mods, not just DH itself; if everything is rendering correctly these errors can probably be ignored.";
|
||||
}
|
||||
|
||||
|
||||
|
||||
// create an exception so we get a stacktrace of where the message was triggered from
|
||||
RuntimeException exception = new RuntimeException(errorMessage);
|
||||
|
||||
if (msg.type == EGLMessageType.ERROR || msg.type == EGLMessageType.UNDEFINED_BEHAVIOR)
|
||||
if (glMessage.type == EGLMessageType.ERROR || glMessage.type == EGLMessageType.UNDEFINED_BEHAVIOR)
|
||||
{
|
||||
// critical error
|
||||
|
||||
@@ -278,7 +309,7 @@ public class GLProxy
|
||||
{
|
||||
// non-critical log
|
||||
|
||||
EGLMessageSeverity severity = msg.severity;
|
||||
EGLMessageSeverity severity = glMessage.severity;
|
||||
if (severity == null)
|
||||
{
|
||||
// just in case the message was malformed
|
||||
|
||||
+18
-4
@@ -97,7 +97,9 @@ public class GLState implements AutoCloseable
|
||||
{
|
||||
this.frameBufferTexture0 = GL32.glGetFramebufferAttachmentParameteri(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT0, GL32.GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME);
|
||||
this.frameBufferTexture1 = GL32.glGetFramebufferAttachmentParameteri(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT1, GL32.GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME);
|
||||
this.frameBufferDepthTexture = GL32.glGetFramebufferAttachmentParameteri(GL32.GL_FRAMEBUFFER, GL32.GL_DEPTH_ATTACHMENT, GL32.GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME);
|
||||
|
||||
int depthType = GL32.glGetFramebufferAttachmentParameteri(GL32.GL_FRAMEBUFFER, GL32.GL_DEPTH_ATTACHMENT, GL32.GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE);
|
||||
this.frameBufferDepthTexture = (depthType == GL32.GL_TEXTURE) ? GL32.glGetFramebufferAttachmentParameteri(GL32.GL_FRAMEBUFFER, GL32.GL_DEPTH_ATTACHMENT, GL32.GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -179,9 +181,21 @@ public class GLState implements AutoCloseable
|
||||
// attempting to set textures on the default frame buffer (ID 0) will throw errors
|
||||
if (frameBufferSet)
|
||||
{
|
||||
GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT0, GL32.GL_TEXTURE_2D, this.frameBufferTexture0, 0);
|
||||
GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT1, GL32.GL_TEXTURE_2D, this.frameBufferTexture1, 0);
|
||||
GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, GL32.GL_DEPTH_ATTACHMENT, GL32.GL_TEXTURE_2D, this.frameBufferDepthTexture, 0);
|
||||
if (GL32.glIsTexture(this.frameBufferTexture0))
|
||||
{
|
||||
GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT0, GL32.GL_TEXTURE_2D, this.frameBufferTexture0, 0);
|
||||
}
|
||||
|
||||
if (this.frameBufferTexture1 != 0 && GL32.glIsTexture(this.frameBufferTexture1))
|
||||
{
|
||||
GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT1, GL32.GL_TEXTURE_2D, this.frameBufferTexture1, 0);
|
||||
}
|
||||
|
||||
if (GL32.glIsTexture(this.frameBufferDepthTexture))
|
||||
{
|
||||
GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, GL32.GL_DEPTH_ATTACHMENT, GL32.GL_TEXTURE_2D, this.frameBufferDepthTexture, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
GL32.glBindVertexArray(GL32.glIsVertexArray(this.vao) ? this.vao : 0);
|
||||
|
||||
+303
-57
@@ -21,14 +21,19 @@ package com.seibel.distanthorizons.common.render.openGl.glObject.buffer;
|
||||
|
||||
import com.seibel.distanthorizons.api.enums.config.EDhApiGpuUploadMethod;
|
||||
import com.seibel.distanthorizons.common.render.openGl.glObject.GLProxy;
|
||||
import com.seibel.distanthorizons.common.render.openGl.glObject.GLState;
|
||||
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftGLWrapper;
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.jar.EPlatform;
|
||||
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.logging.f3.F3Screen;
|
||||
import com.seibel.distanthorizons.core.render.RenderThreadTaskHandler;
|
||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||
import com.seibel.distanthorizons.core.util.ThreadUtil;
|
||||
import com.seibel.distanthorizons.core.util.objects.Pair;
|
||||
import com.seibel.distanthorizons.core.util.objects.pooling.PhantomLoggingHelper;
|
||||
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||
import com.seibel.distanthorizons.coreapi.util.StringUtil;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
import org.lwjgl.opengl.GL44;
|
||||
|
||||
@@ -36,9 +41,12 @@ import java.lang.ref.PhantomReference;
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.locks.StampedLock;
|
||||
|
||||
public class GLBuffer implements AutoCloseable
|
||||
{
|
||||
@@ -50,26 +58,57 @@ public class GLBuffer implements AutoCloseable
|
||||
private static final MinecraftGLWrapper GLMC = MinecraftGLWrapper.INSTANCE;
|
||||
|
||||
|
||||
// TODO move to a shared location that can be handled by both GL and Blaze3D buffers
|
||||
/** if enabled the number of GC'ed buffers will be logged */
|
||||
private static final boolean LOG_PHANTOM_RECOVERY = ModInfo.IS_DEV_BUILD;
|
||||
/** If enabled buffers allocation/upload stacks will be logged when GC'ed. */
|
||||
private static final boolean LOG_PHANTOM_ALLOCATION_STACKS = false; // disabled by default due to the increased GC load
|
||||
|
||||
public static final double BUFFER_EXPANSION_MULTIPLIER = 1.3;
|
||||
public static final double BUFFER_SHRINK_TRIGGER = BUFFER_EXPANSION_MULTIPLIER * BUFFER_EXPANSION_MULTIPLIER;
|
||||
|
||||
/**
|
||||
* On macOS the legacy OpenGL -> Metal bridge crashes with SIGBUS in
|
||||
* {@code _platform_memmove} when {@code glBufferData} or {@code glBufferSubData}
|
||||
* are called with a large ByteBuffer in one shot. To work around it, we split
|
||||
* the upload into smaller sub-data calls that each fit comfortably inside the
|
||||
* driver's internal staging path. <br>
|
||||
* 256 KiB tuned empirically against macOS 26.5 — a 1 MiB chunk still
|
||||
* tripped the same {@code _platform_memmove} crash inside
|
||||
* {@code glBufferSubData_Exec}, but 256 KiB consistently survives.
|
||||
*/
|
||||
public static final int MAC_UPLOAD_CHUNK_BYTES = 256 * 1024;
|
||||
/** Threshold above which the chunked path kicks in on macOS. */
|
||||
public static final int MAC_UPLOAD_CHUNK_THRESHOLD = MAC_UPLOAD_CHUNK_BYTES;
|
||||
/** the number of active buffers, can be used for debugging */
|
||||
public static AtomicInteger bufferCount = new AtomicInteger(0);
|
||||
|
||||
private static final int PHANTOM_REF_CHECK_TIME_IN_MS = 5 * 1000;
|
||||
private static final ConcurrentHashMap<PhantomReference<? extends GLBuffer>, Integer> PHANTOM_TO_BUFFER_ID = new ConcurrentHashMap<>();
|
||||
private static final ConcurrentHashMap<Integer, PhantomReference<? extends GLBuffer>> BUFFER_ID_TO_PHANTOM = new ConcurrentHashMap<>();
|
||||
private static final ConcurrentHashMap<Integer, String> BUFFER_ID_TO_ALLOCATION_STRING = new ConcurrentHashMap<>();
|
||||
private static final ReferenceQueue<GLBuffer> PHANTOM_REFERENCE_QUEUE = new ReferenceQueue<>();
|
||||
private static final ThreadPoolExecutor CLEANUP_THREAD = ThreadUtil.makeSingleDaemonThreadPool("GLBuffer Cleanup");
|
||||
|
||||
|
||||
protected int id;
|
||||
protected volatile int id = 0;
|
||||
public final int getId() { return this.id; }
|
||||
protected int size = 0;
|
||||
public int getSize() { return this.size; }
|
||||
protected boolean bufferStorage;
|
||||
public final boolean isBufferStorage() { return this.bufferStorage; }
|
||||
protected boolean isMapped = false;
|
||||
|
||||
/**
|
||||
* Locking on the render thread isn't great, but is needed due to an inconsistent
|
||||
* race condition where VBOs can be marked as deleted outside the render thread. <br><br>
|
||||
*
|
||||
* But, due to being a read-write lock the chance of freezing
|
||||
* the render thread is very low
|
||||
* and since this is a stamped lock, the optimistic read time is basically zero.
|
||||
* (The optimistic lock time doesn't even appear in the profiler).
|
||||
*/
|
||||
public final StampedLock renderStampLock = new StampedLock();
|
||||
|
||||
|
||||
|
||||
//==============//
|
||||
@@ -112,72 +151,119 @@ public class GLBuffer implements AutoCloseable
|
||||
LodUtil.assertNotReach("Thread ["+Thread.currentThread()+"] tried to create a GLBuffer outside the MC render thread.");
|
||||
}
|
||||
|
||||
// destroy the old buffer if one is present
|
||||
if (this.id != 0)
|
||||
|
||||
// lock to prevent the render thread from accessing the buffer's ID
|
||||
// while we are removing it
|
||||
long writeStamp = renderStampLock.writeLock();
|
||||
try
|
||||
{
|
||||
destroyBufferIdNow(this.id);
|
||||
final int oldId = this.id;
|
||||
this.id = GLMC.glGenBuffers();
|
||||
//LOGGER.info("created [" + newId + "].");
|
||||
|
||||
// destroy the old buffer
|
||||
// after the new one has been created
|
||||
// to hopefully prevent a rare race conditions where the old ID
|
||||
// is still used somewhere
|
||||
if (oldId != 0)
|
||||
{
|
||||
// this ID doesn't need to be tracked anymore
|
||||
tryRemoveBufferIdFromPhantom(oldId);
|
||||
destroyBufferIdNow(oldId, "destroyOldAndCreate");
|
||||
}
|
||||
|
||||
|
||||
this.bufferStorage = asBufferStorage;
|
||||
bufferCount.getAndIncrement();
|
||||
|
||||
PhantomReference<GLBuffer> phantom = new PhantomReference<>(this, PHANTOM_REFERENCE_QUEUE);
|
||||
PHANTOM_TO_BUFFER_ID.put(phantom, this.id);
|
||||
BUFFER_ID_TO_PHANTOM.put(this.id, phantom);
|
||||
|
||||
this.updateAllocationStackTrace();
|
||||
}
|
||||
finally
|
||||
{
|
||||
renderStampLock.unlock(writeStamp);
|
||||
}
|
||||
|
||||
this.id = GLMC.glGenBuffers();
|
||||
this.bufferStorage = asBufferStorage;
|
||||
bufferCount.getAndIncrement();
|
||||
|
||||
PhantomReference<GLBuffer> phantom = new PhantomReference<>(this, PHANTOM_REFERENCE_QUEUE);
|
||||
PHANTOM_TO_BUFFER_ID.put(phantom, this.id);
|
||||
BUFFER_ID_TO_PHANTOM.put(this.id, phantom);
|
||||
|
||||
}
|
||||
|
||||
protected void destroyAsync()
|
||||
{
|
||||
if (this.id == 0)
|
||||
// lock to prevent the render thread from accessing the buffer's ID
|
||||
// while we are removing it
|
||||
long writeStamp = renderStampLock.writeLock();
|
||||
try
|
||||
{
|
||||
// the buffer has already been closed
|
||||
return;
|
||||
if (this.id == 0)
|
||||
{
|
||||
// the buffer has already been closed
|
||||
return;
|
||||
}
|
||||
|
||||
final int idToDelete = this.id; // saving the ID to a separate variable is necessary so it can be captured by the lambda
|
||||
|
||||
// remove the phantom tracking now so the phantom doesn't have the chance to
|
||||
// get garbage collected before the render thread task runs
|
||||
// (this can happen if MC is running at extremely low framerates like 1 fps via mods)
|
||||
tryRemoveBufferIdFromPhantom(idToDelete);
|
||||
|
||||
// mark the old data is invalid before deleting to prevent a rare race condition
|
||||
// where the queued on render thread task runs before the ID is cleared
|
||||
this.id = 0;
|
||||
this.size = 0;
|
||||
|
||||
//LOGGER.info("async destroy [" + idToDelete + "].");
|
||||
RenderThreadTaskHandler.INSTANCE.queueRunningOnRenderThread("GLBuffer destroyAsync", () -> { destroyBufferIdNow(idToDelete, "destroyAsync"); });
|
||||
}
|
||||
finally
|
||||
{
|
||||
renderStampLock.unlock(writeStamp);
|
||||
}
|
||||
|
||||
final int idToDelete = this.id; // saving the ID to a separate variable is necessary so it can be captured by the lambda
|
||||
RenderThreadTaskHandler.INSTANCE.queueRunningOnRenderThread("GLBuffer destroyAsync", () -> { destroyBufferIdNow(idToDelete); });
|
||||
|
||||
this.id = 0;
|
||||
this.size = 0;
|
||||
}
|
||||
private static void destroyBufferIdNow(int id)
|
||||
|
||||
private static void destroyBufferIdNow(int id, String cause)
|
||||
{
|
||||
// only delete valid buffers
|
||||
if (id == 0)
|
||||
{
|
||||
LOGGER.warn("Attempted to destroy a buffer with ID 0, VRAM memory leaks may occur.");
|
||||
LOGGER.warn("Attempted to destroy a buffer with ID 0, VRAM memory leaks may occur, cause: ["+cause+"].");
|
||||
return;
|
||||
}
|
||||
|
||||
// remove and clear the phantom reference if present
|
||||
if (BUFFER_ID_TO_PHANTOM.containsKey(id))
|
||||
bufferCount.decrementAndGet();
|
||||
GLMC.glDeleteBuffers(id);
|
||||
|
||||
if (Config.Client.Advanced.Debugging.logBufferGarbageCollection.get())
|
||||
{
|
||||
LOGGER.info("destroyed buffer [" + id + "], remaining: [" + BUFFER_ID_TO_PHANTOM.size() + "], cause: ["+cause+"].");
|
||||
}
|
||||
}
|
||||
|
||||
/** should be called before {@link GLBuffer#destroyBufferIdNow} */
|
||||
private static void tryRemoveBufferIdFromPhantom(int id)
|
||||
{
|
||||
// will contain nothing if stack tracking isn't enabled
|
||||
BUFFER_ID_TO_ALLOCATION_STRING.remove(id);
|
||||
|
||||
PhantomReference<? extends GLBuffer> phantom = BUFFER_ID_TO_PHANTOM.remove(id);
|
||||
if (phantom != null)
|
||||
{
|
||||
Reference<? extends GLBuffer> phantom = BUFFER_ID_TO_PHANTOM.get(id);
|
||||
|
||||
// if we are manually closing this buffer, we don't want the phantom reference to accidentally close it again
|
||||
// this can cause a race condition were we accidentally delete an in-use buffer and cause NVIDIA
|
||||
// to throw an EXCEPTION_ACCESS_VIOLATION when we attempt to render it
|
||||
phantom.clear();
|
||||
|
||||
PHANTOM_TO_BUFFER_ID.remove(phantom);
|
||||
BUFFER_ID_TO_PHANTOM.remove(id);
|
||||
}
|
||||
|
||||
bufferCount.decrementAndGet();
|
||||
|
||||
// destroy the buffer if it exists,
|
||||
// the buffer may not exist if the destroy method is called twice
|
||||
if (GL32.glIsBuffer(id))
|
||||
{
|
||||
GLMC.glDeleteBuffers(id);
|
||||
|
||||
if (Config.Client.Advanced.Debugging.logBufferGarbageCollection.get())
|
||||
Integer phantomId = PHANTOM_TO_BUFFER_ID.remove(phantom);
|
||||
if (phantomId == null)
|
||||
{
|
||||
LOGGER.info("destroyed buffer [" + id + "], remaining: [" + BUFFER_ID_TO_PHANTOM.size() + "]");
|
||||
LOGGER.warn("No Phantom->ID binding stored for ID ["+id+"]");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGGER.warn("Unable to remove phantom GLBuffer with ID ["+id+"], buffer may have already been deleted.");
|
||||
}
|
||||
}
|
||||
|
||||
//endregion
|
||||
@@ -210,9 +296,12 @@ public class GLBuffer implements AutoCloseable
|
||||
|
||||
|
||||
|
||||
// re-binding the old VBO is necessary for old MC versions (IE 1.16.5 and older)
|
||||
// otherwise the screen may be black when on the home menu
|
||||
int previousBoundVbo = GL32.glGetInteger(GL32.GL_ARRAY_BUFFER_BINDING);
|
||||
// re-binding the old buffers is necessary for old MC versions for the following reasons:
|
||||
// for 16.5 and older the screen may be black when on the home menu
|
||||
// and for 1.19.2 - 1.21.4 the inventory/UI will render without a background
|
||||
int vao = GL32.glGetInteger(GL32.GL_VERTEX_ARRAY_BINDING);
|
||||
int vbo = GL32.glGetInteger(GL32.GL_ARRAY_BUFFER_BINDING);
|
||||
int ebo = GL32.glGetInteger(GL32.GL_ELEMENT_ARRAY_BUFFER_BINDING);
|
||||
|
||||
try
|
||||
{
|
||||
@@ -238,7 +327,9 @@ public class GLBuffer implements AutoCloseable
|
||||
}
|
||||
finally
|
||||
{
|
||||
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, GL32.glIsBuffer(previousBoundVbo) ? previousBoundVbo : 0);
|
||||
GL32.glBindVertexArray(GL32.glIsVertexArray(vao) ? vao : 0);
|
||||
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, GL32.glIsBuffer(vbo) ? vbo : 0);
|
||||
GL32.glBindBuffer(GL32.GL_ELEMENT_ARRAY_BUFFER, GL32.glIsBuffer(ebo) ? ebo: 0);
|
||||
}
|
||||
}
|
||||
/** Requires the buffer to be bound */
|
||||
@@ -258,8 +349,25 @@ public class GLBuffer implements AutoCloseable
|
||||
LodUtil.assertTrue(!this.bufferStorage, "Buffer is bufferStorage but its trying to use bufferData upload method!");
|
||||
|
||||
int bbSize = bb.limit() - bb.position();
|
||||
GL32.glBufferData(this.getBufferBindingTarget(), bb, bufferDataHint);
|
||||
int target = this.getBufferBindingTarget();
|
||||
|
||||
if (shouldUploadToGpuInChunks(bbSize))
|
||||
{
|
||||
// Two-step path used on macOS to dodge the Apple OpenGL -> Metal
|
||||
// memmove SIGBUS triggered by uploading a large ByteBuffer in one
|
||||
// glBufferData call:
|
||||
// 1) allocate-only with the size overload (no memcpy)
|
||||
// 2) fill the buffer through chunked glBufferSubData calls
|
||||
GL32.glBufferData(target, (long) bbSize, bufferDataHint);
|
||||
subDataUploadInChunks(target, 0, bb, MAC_UPLOAD_CHUNK_BYTES);
|
||||
}
|
||||
else
|
||||
{
|
||||
GL32.glBufferData(target, bb, bufferDataHint);
|
||||
}
|
||||
this.size = bbSize;
|
||||
|
||||
this.updateAllocationStackTrace();
|
||||
}
|
||||
/** Requires the buffer to be bound */
|
||||
protected void uploadSubData(ByteBuffer bb, int maxExpansionSize, int bufferDataHint)
|
||||
@@ -267,14 +375,30 @@ public class GLBuffer implements AutoCloseable
|
||||
LodUtil.assertTrue(!this.bufferStorage, "Buffer is bufferStorage but its trying to use subData upload method!");
|
||||
|
||||
int bbSize = bb.limit() - bb.position();
|
||||
int target = this.getBufferBindingTarget();
|
||||
if (this.size < bbSize || this.size > bbSize * BUFFER_SHRINK_TRIGGER)
|
||||
{
|
||||
int newSize = (int) (bbSize * BUFFER_EXPANSION_MULTIPLIER);
|
||||
if (newSize > maxExpansionSize) newSize = maxExpansionSize;
|
||||
GL32.glBufferData(this.getBufferBindingTarget(), newSize, bufferDataHint);
|
||||
if (newSize > maxExpansionSize)
|
||||
{
|
||||
newSize = maxExpansionSize;
|
||||
}
|
||||
|
||||
// allocate-only — no memcpy, safe on macOS regardless of size
|
||||
GL32.glBufferData(target, (long) newSize, bufferDataHint);
|
||||
this.size = newSize;
|
||||
}
|
||||
GL32.glBufferSubData(this.getBufferBindingTarget(), 0, bb);
|
||||
|
||||
if (shouldUploadToGpuInChunks(bbSize))
|
||||
{
|
||||
subDataUploadInChunks(target, 0, bb, MAC_UPLOAD_CHUNK_BYTES);
|
||||
}
|
||||
else
|
||||
{
|
||||
GL32.glBufferSubData(target, 0, bb);
|
||||
}
|
||||
|
||||
this.updateAllocationStackTrace();
|
||||
}
|
||||
|
||||
//endregion
|
||||
@@ -316,7 +440,6 @@ public class GLBuffer implements AutoCloseable
|
||||
{
|
||||
// recreate if the buffer storage type changed
|
||||
this.bind();
|
||||
destroyBufferIdNow(this.id);
|
||||
this.destroyOldAndCreate(uploadMethod.useBufferStorage);
|
||||
this.bind();
|
||||
}
|
||||
@@ -333,6 +456,91 @@ public class GLBuffer implements AutoCloseable
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* macOS-only mitigation for the SIGBUS in
|
||||
* {@code libsystem_platform.dylib _platform_memmove} that happens when the
|
||||
* Apple OpenGL -> Metal translation layer copies a single large ByteBuffer
|
||||
* out of LWJGL into driver memory. Splitting the copy into
|
||||
* {@link #MAC_UPLOAD_CHUNK_BYTES} slices keeps every memmove inside a size
|
||||
* the bridge handles reliably.
|
||||
*/
|
||||
private static boolean shouldUploadToGpuInChunks(int byteCount)
|
||||
{
|
||||
return EPlatform.get() == EPlatform.MACOS
|
||||
&& byteCount > MAC_UPLOAD_CHUNK_THRESHOLD;
|
||||
}
|
||||
|
||||
/**
|
||||
* Uploads {@code bb} into the currently bound buffer at {@code baseOffset}
|
||||
* using a sequence of {@link GL32#glBufferSubData(int, long, ByteBuffer)}
|
||||
* calls of at most {@code chunkBytes} each. The buffer's position/limit are
|
||||
* restored before returning.
|
||||
*/
|
||||
private static void subDataUploadInChunks(int target, int baseOffset, ByteBuffer bb, int chunkBytes)
|
||||
{
|
||||
final int origPos = bb.position();
|
||||
final int origLimit = bb.limit();
|
||||
try
|
||||
{
|
||||
final int total = origLimit - origPos;
|
||||
int uploaded = 0;
|
||||
while (uploaded < total)
|
||||
{
|
||||
int chunk = Math.min(chunkBytes, total - uploaded);
|
||||
bb.position(origPos + uploaded);
|
||||
bb.limit(origPos + uploaded + chunk);
|
||||
GL32.glBufferSubData(target, (long) (baseOffset + uploaded), bb);
|
||||
uploaded += chunk;
|
||||
// Force the driver to drain its command queue between chunks
|
||||
// so the OpenGL -> Metal bridge processes (and frees) each
|
||||
// staging copy before the next sub-data call piles another
|
||||
// memmove on top of it.
|
||||
if (uploaded < total)
|
||||
{
|
||||
GL32.glFlush();
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
bb.limit(origLimit);
|
||||
bb.position(origPos);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* used to help track down leaks where the buffer isn't properly closed
|
||||
* Note: this probably needs extending to accept a stack trace from outside where it's being called
|
||||
* since it's often called on the render thread in an un-helpful location.
|
||||
*/
|
||||
public void updateAllocationStackTrace()
|
||||
{
|
||||
if (LOG_PHANTOM_ALLOCATION_STACKS)
|
||||
{
|
||||
String stack;
|
||||
|
||||
RenderThreadTaskHandler.QueuedRunnable parentQueuedRunnable;
|
||||
// if this is running on the render thread, try getting the render task's stack trace instead
|
||||
// since it's a lot more helpful than wherever the render thread tasks themselves are being run from
|
||||
if (RenderThreadTaskHandler.INSTANCE.isCurrentThread()
|
||||
&& (parentQueuedRunnable = RenderThreadTaskHandler.INSTANCE.getCurrentlyRunningTask()) != null
|
||||
&& parentQueuedRunnable.stackTrace != null)
|
||||
{
|
||||
// trim off the getStacktrace() and queueRunningOnRenderThread() methods
|
||||
StackTraceElement[] trimmedElements = Arrays.copyOfRange(parentQueuedRunnable.stackTrace, 2, parentQueuedRunnable.stackTrace.length);
|
||||
stack = StringUtil.join("\n", trimmedElements).intern();
|
||||
}
|
||||
else
|
||||
{
|
||||
// not running on the render thread, use the normal stack trace
|
||||
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
|
||||
stack = StringUtil.join("\n", stackTraceElements).intern();
|
||||
}
|
||||
|
||||
BUFFER_ID_TO_ALLOCATION_STRING.put(this.id, stack);
|
||||
}
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
@@ -344,8 +552,13 @@ public class GLBuffer implements AutoCloseable
|
||||
|
||||
private static void runPhantomReferenceCleanupLoop()
|
||||
{
|
||||
// these arrays are stored here so they don't have to be re-allocated each loop
|
||||
ArrayList<Pair<String, AtomicInteger>> allocationStackTraceCountPairList = new ArrayList<>();
|
||||
|
||||
while (true)
|
||||
{
|
||||
allocationStackTraceCountPairList.clear();
|
||||
|
||||
try
|
||||
{
|
||||
try
|
||||
@@ -354,20 +567,53 @@ public class GLBuffer implements AutoCloseable
|
||||
}
|
||||
catch (InterruptedException ignore) { }
|
||||
|
||||
int collectedCount = 0;
|
||||
|
||||
Reference<? extends GLBuffer> phantomRef = PHANTOM_REFERENCE_QUEUE.poll();
|
||||
while (phantomRef != null)
|
||||
{
|
||||
// destroy the buffer if it hasn't been cleared yet
|
||||
if (PHANTOM_TO_BUFFER_ID.containsKey(phantomRef))
|
||||
Integer idRef = PHANTOM_TO_BUFFER_ID.remove((PhantomReference<? extends GLBuffer>)phantomRef); // cast to make IntelliJ happy
|
||||
if (idRef != null)
|
||||
{
|
||||
int id = PHANTOM_TO_BUFFER_ID.get(phantomRef);
|
||||
RenderThreadTaskHandler.INSTANCE.queueRunningOnRenderThread("GLBuffer phantom destroy", () -> { destroyBufferIdNow(id); });
|
||||
//LOGGER.warn("Buffer Phantom collected, ID: ["+id+"]");
|
||||
BUFFER_ID_TO_PHANTOM.remove(idRef);
|
||||
final int id = idRef;
|
||||
RenderThreadTaskHandler.INSTANCE.queueRunningOnRenderThread("GLBuffer phantom destroy", () -> { destroyBufferIdNow(id, "runPhantomReferenceCleanupLoop"); });
|
||||
//LOGGER.info("Buffer Phantom collected, ID: ["+id+"]");
|
||||
|
||||
if (LOG_PHANTOM_ALLOCATION_STACKS) // stack trace shouldn't be null, but just in case
|
||||
{
|
||||
String stack = BUFFER_ID_TO_ALLOCATION_STRING.get(idRef);
|
||||
PhantomLoggingHelper.putAndIncrementTrackingString(stack, allocationStackTraceCountPairList);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGGER.warn("Failed to find Buffer ID for phantom reference: ["+phantomRef+"]");
|
||||
}
|
||||
|
||||
|
||||
collectedCount++;
|
||||
phantomRef = PHANTOM_REFERENCE_QUEUE.poll();
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (LOG_PHANTOM_RECOVERY)
|
||||
{
|
||||
// we only want to log when something has been returned
|
||||
if (collectedCount != 0)
|
||||
{
|
||||
LOGGER.warn("GLBuffer phantom recovered: ["+ F3Screen.NUMBER_FORMAT.format(collectedCount)+"].");
|
||||
|
||||
// log stack traces if present
|
||||
if (LOG_PHANTOM_ALLOCATION_STACKS)
|
||||
{
|
||||
PhantomLoggingHelper.LogAllocationStackTracePairCounts(LOGGER, allocationStackTraceCountPairList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
||||
+5
-4
@@ -37,10 +37,11 @@ public class GLIndexBuffer extends GLBuffer
|
||||
protected int glType = GL32.GL_UNSIGNED_INT;
|
||||
public int getGlType() { return this.glType; }
|
||||
|
||||
public GLIndexBuffer(boolean isBufferStorage)
|
||||
{
|
||||
super(isBufferStorage);
|
||||
}
|
||||
|
||||
|
||||
public GLIndexBuffer(boolean isBufferStorage) { super(isBufferStorage); }
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void destroyAsync()
|
||||
|
||||
+7
-3
@@ -22,15 +22,16 @@ package com.seibel.distanthorizons.common.render.openGl.glObject.buffer;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import com.seibel.distanthorizons.common.render.openGl.glObject.GLProxy;
|
||||
import com.seibel.distanthorizons.core.dataObjects.render.bufferBuilding.IndexBufferBuilder;
|
||||
import com.seibel.distanthorizons.core.dataObjects.render.bufferBuilding.LodQuadBuilder;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.jar.EPlatform;
|
||||
import com.seibel.distanthorizons.core.render.RenderThreadTaskHandler;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.render.AbstractDhRenderApiDefinition;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.render.objects.IVertexBufferWrapper;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
|
||||
import com.seibel.distanthorizons.api.enums.config.EDhApiGpuUploadMethod;
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
/**
|
||||
* This is a container for a OpenGL
|
||||
@@ -83,7 +84,10 @@ public class GLVertexBuffer extends GLBuffer implements IVertexBufferWrapper
|
||||
int maxSize = LodQuadBuilder.getMaxBufferByteSize();
|
||||
int maxVertexCount = maxSize / LodQuadBuilder.BYTES_PER_VERTEX;
|
||||
int maxQuadCount = (maxVertexCount / 4);
|
||||
GLOBAL_QUAD_IBO.upload(maxQuadCount);
|
||||
|
||||
ByteBuffer buffer = IndexBufferBuilder.createBuffer(maxQuadCount);
|
||||
GLOBAL_QUAD_IBO.upload(buffer, maxQuadCount);
|
||||
MemoryUtil.memFree(buffer);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -158,7 +162,7 @@ public class GLVertexBuffer extends GLBuffer implements IVertexBufferWrapper
|
||||
this.quadIBO = new GlQuadIndexBuffer();
|
||||
|
||||
int quadCount = (vertexCount / 4);
|
||||
this.quadIBO.upload(quadCount);
|
||||
this.quadIBO.upload(buffer, quadCount);
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
+1
-5
@@ -43,7 +43,7 @@ public class GlQuadIndexBuffer extends GLIndexBuffer
|
||||
|
||||
public GlQuadIndexBuffer() { super(false); }
|
||||
|
||||
public void upload(int quadCount)
|
||||
public void upload(ByteBuffer buffer, int quadCount)
|
||||
{
|
||||
if (quadCount < 0)
|
||||
{
|
||||
@@ -63,12 +63,8 @@ public class GlQuadIndexBuffer extends GLIndexBuffer
|
||||
}
|
||||
|
||||
this.glType = GL32.GL_UNSIGNED_INT;
|
||||
ByteBuffer buffer = IndexBufferBuilder.createBuffer(quadCount);
|
||||
this.bind();
|
||||
super.uploadBuffer(buffer, EDhApiGpuUploadMethod.DATA,
|
||||
this.indicesCount * GLEnums.getTypeSize(this.glType), GL32.GL_STATIC_DRAW);
|
||||
|
||||
MemoryUtil.memFree(buffer);
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
-8
@@ -122,8 +122,6 @@ public class GlDhFarFadeRenderer implements IDhFarFadeRenderer
|
||||
{
|
||||
try
|
||||
{
|
||||
//profiler.push("Fade Generate");
|
||||
|
||||
this.init();
|
||||
|
||||
// resize the framebuffer if necessary
|
||||
@@ -141,8 +139,6 @@ public class GlDhFarFadeRenderer implements IDhFarFadeRenderer
|
||||
GlDhFarFadeShader.INSTANCE.setProjectionMatrix(renderParams.mcModelViewMatrix, renderParams.mcProjectionMatrix);
|
||||
GlDhFarFadeShader.INSTANCE.render(renderParams);
|
||||
|
||||
//profiler.popPush("Fade Apply");
|
||||
|
||||
GlDhFarFadeApplyShader.INSTANCE.fadeTexture = this.fadeTexture;
|
||||
GlDhFarFadeApplyShader.INSTANCE.readFramebuffer = GlDhFarFadeShader.INSTANCE.frameBuffer;
|
||||
GlDhFarFadeApplyShader.INSTANCE.drawFramebuffer = GlDhMetaRenderer.INSTANCE.getActiveFramebufferId();
|
||||
@@ -152,10 +148,6 @@ public class GlDhFarFadeRenderer implements IDhFarFadeRenderer
|
||||
{
|
||||
LOGGER.error("Unexpected error during fade render, error: ["+e.getMessage()+"].", e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
//profiler.pop();
|
||||
}
|
||||
}
|
||||
|
||||
//emdregion
|
||||
|
||||
+3
-12
@@ -135,14 +135,9 @@ public class GlVanillaFadeRenderer implements IDhVanillaFadeRenderer
|
||||
|
||||
|
||||
IProfilerWrapper profiler = MC_CLIENT.getProfiler();
|
||||
profiler.pop(); // get out of "terrain"
|
||||
profiler.push("DH-Vanilla Fade");
|
||||
|
||||
|
||||
try(GLState mcState = new GLState())
|
||||
try (IProfilerWrapper.IProfileBlock fade_profile = profiler.push("DH-Vanilla Fade");
|
||||
GLState mcState = new GLState())
|
||||
{
|
||||
profiler.push("Vanilla Fade Generate");
|
||||
|
||||
this.init();
|
||||
|
||||
// resize the framebuffer if necessary
|
||||
@@ -165,19 +160,15 @@ public class GlVanillaFadeRenderer implements IDhVanillaFadeRenderer
|
||||
// otherwise we can directly render to their texture
|
||||
if (MC_RENDER.mcRendersToFrameBuffer())
|
||||
{
|
||||
profiler.popPush("Vanilla Fade Apply");
|
||||
|
||||
GlDhFarFadeApplyShader.INSTANCE.fadeTexture = this.fadeTexture;
|
||||
GlDhFarFadeApplyShader.INSTANCE.readFramebuffer = GlDhVanillaFadeShader.INSTANCE.frameBuffer;
|
||||
GlDhFarFadeApplyShader.INSTANCE.drawFramebuffer = MC_RENDER.getTargetFramebuffer();
|
||||
GlDhFarFadeApplyShader.INSTANCE.render(renderParams);
|
||||
}
|
||||
|
||||
profiler.pop();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LOGGER.error("Unexpected error during fade render, error: ["+e.getMessage()+"].", e);
|
||||
LOGGER.error("Unexpected error during fade render, error: [" + e.getMessage() + "].", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+46
-19
@@ -289,6 +289,9 @@ public class GlDhTerrainShaderProgram extends GlShaderProgram implements IDhApiS
|
||||
GLMC.disableBlend();
|
||||
}
|
||||
|
||||
// needs to be triggered after DH attempts to set the GL state so that Iris
|
||||
// can override it as needed
|
||||
ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeRenderPassEvent.class, renderEventParam);
|
||||
|
||||
|
||||
|
||||
@@ -296,8 +299,6 @@ public class GlDhTerrainShaderProgram extends GlShaderProgram implements IDhApiS
|
||||
// rendering //
|
||||
//===========//
|
||||
|
||||
ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeRenderPassEvent.class, renderEventParam);
|
||||
|
||||
if (IRIS_ACCESSOR != null)
|
||||
{
|
||||
// done to fix a bug with Iris where face culling isn't properly set or reverted in the MC state manager
|
||||
@@ -313,6 +314,12 @@ public class GlDhTerrainShaderProgram extends GlShaderProgram implements IDhApiS
|
||||
for (int lodIndex = 0; lodIndex < bufferContainers.size(); lodIndex++)
|
||||
{
|
||||
LodBufferContainer bufferContainer = bufferContainers.get(lodIndex);
|
||||
if (!bufferContainer.buffersUploaded)
|
||||
{
|
||||
// make sure we don't accidentally try
|
||||
// rendering a buffer that is (or is going to be) freed
|
||||
continue;
|
||||
}
|
||||
|
||||
// set uniforms and fire events
|
||||
{
|
||||
@@ -337,25 +344,45 @@ public class GlDhTerrainShaderProgram extends GlShaderProgram implements IDhApiS
|
||||
continue;
|
||||
}
|
||||
|
||||
if (vbo.getVertexCount() == 0)
|
||||
|
||||
// for lock information please view the lock's javadocs
|
||||
long vboReadStamp = vbo.renderStampLock.readLock();
|
||||
long iboReadStamp = vbo.getQuadIBO().renderStampLock.readLock();
|
||||
try
|
||||
{
|
||||
continue;
|
||||
// don't render empty sections
|
||||
if (vbo.getVertexCount() == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// don't render deleted VBOs (this will crash the driver/game)
|
||||
if (vbo.getId() == 0
|
||||
|| vbo.getQuadIBO().getId() == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// 4 vertices per face, but 6 indices (IE 2 triangles) per face, aka need to multiply by 1.5
|
||||
int indexCount = (int) (vbo.getVertexCount() * 1.5);
|
||||
|
||||
vbo.bind();
|
||||
vbo.getQuadIBO().bind();
|
||||
|
||||
GlDhMetaRenderer.INSTANCE.shaderProgramForThisFrame.bindVertexBuffer(vbo.getId());
|
||||
GL32.glDrawElements(
|
||||
GL32.GL_TRIANGLES,
|
||||
indexCount,
|
||||
vbo.getQuadIBO().getGlType(), 0);
|
||||
|
||||
vbo.unbind();
|
||||
vbo.getQuadIBO().unbind();
|
||||
}
|
||||
finally
|
||||
{
|
||||
vbo.renderStampLock.unlock(vboReadStamp);
|
||||
vbo.getQuadIBO().renderStampLock.unlock(iboReadStamp);
|
||||
}
|
||||
|
||||
// 4 vertices per face, but 6 indices (IE 2 triangles) per face, aka need to multiply by 1.5
|
||||
int indexCount = (int)(vbo.getVertexCount() * 1.5);
|
||||
|
||||
vbo.bind();
|
||||
vbo.getQuadIBO().bind();
|
||||
|
||||
GlDhMetaRenderer.INSTANCE.shaderProgramForThisFrame.bindVertexBuffer(vbo.getId());
|
||||
GL32.glDrawElements(
|
||||
GL32.GL_TRIANGLES,
|
||||
indexCount,
|
||||
vbo.getQuadIBO().getGlType(), 0);
|
||||
|
||||
vbo.unbind();
|
||||
vbo.getQuadIBO().unbind();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,23 +22,34 @@ package com.seibel.distanthorizons.common.util;
|
||||
import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper;
|
||||
import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
||||
#if MC_VER <= MC_1_12_2
|
||||
import net.minecraft.client.multiplayer.WorldClient;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.WorldServer;
|
||||
#else
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
|
||||
#endif
|
||||
public class ProxyUtil
|
||||
{
|
||||
|
||||
public static ILevelWrapper getLevelWrapper(LevelAccessor level)
|
||||
public static ILevelWrapper getLevelWrapper(
|
||||
#if MC_VER <= MC_1_12_2 World #else LevelAccessor #endif level
|
||||
)
|
||||
{
|
||||
ILevelWrapper levelWrapper;
|
||||
if (level instanceof ServerLevel)
|
||||
if (level instanceof #if MC_VER <= MC_1_12_2 WorldServer #else ServerLevel #endif)
|
||||
{
|
||||
levelWrapper = ServerLevelWrapper.getWrapper((ServerLevel) level);
|
||||
levelWrapper = ServerLevelWrapper.getWrapper(
|
||||
#if MC_VER <= MC_1_12_2 (WorldServer) #else (ServerLevel) #endif level
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
levelWrapper = ClientLevelWrapper.getWrapper((ClientLevel) level);
|
||||
levelWrapper = ClientLevelWrapper.getWrapper(
|
||||
#if MC_VER <= MC_1_12_2 (WorldClient) #else (ClientLevel) #endif level
|
||||
);
|
||||
}
|
||||
|
||||
return levelWrapper;
|
||||
|
||||
+13
-2
@@ -25,7 +25,7 @@ import com.seibel.distanthorizons.common.render.blaze.BlazeDhRenderApiDefinition
|
||||
import com.seibel.distanthorizons.common.render.openGl.GlDhRenderApiDefinition;
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.render.renderer.GenericRenderObjectFactory;
|
||||
import com.seibel.distanthorizons.common.wrappers.gui.ClassicConfigGUI;
|
||||
import com.seibel.distanthorizons.common.wrappers.gui.classicConfig.ClassicConfigGUI;
|
||||
import com.seibel.distanthorizons.common.wrappers.gui.LangWrapper;
|
||||
import com.seibel.distanthorizons.common.wrappers.level.KeyedClientLevelManager;
|
||||
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftServerWrapper;
|
||||
@@ -80,9 +80,20 @@ public class DependencySetup
|
||||
SingletonInjector.INSTANCE.bind(IConfigGui.class, ClassicConfigGUI.CONFIG_CORE_INTERFACE);
|
||||
}
|
||||
|
||||
private static boolean renderingApiBindingsSet = false;
|
||||
/** will be called from a DH thread, not the render thread */
|
||||
public static void setRenderingApiBindings()
|
||||
public synchronized static void setRenderingApiBindings()
|
||||
{
|
||||
// shouldn't happen, but there was a single report that this method was triggered twice
|
||||
if (renderingApiBindingsSet)
|
||||
{
|
||||
LOGGER.warn("Rendering bindings already set, skipping. How did this happen?");
|
||||
return;
|
||||
}
|
||||
renderingApiBindingsSet = true;
|
||||
|
||||
|
||||
|
||||
EDhApiRenderApi renderingApiEnum = Config.Client.Advanced.Graphics.Experimental.renderingApi.get();
|
||||
if (renderingApiEnum == EDhApiRenderApi.AUTO)
|
||||
{
|
||||
|
||||
+102
-18
@@ -26,9 +26,15 @@ import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos;
|
||||
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
||||
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
#else
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This class converts to and from Minecraft objects (Ex: Matrix4f)
|
||||
@@ -39,15 +45,17 @@ import net.minecraft.world.level.ChunkPos;
|
||||
*/
|
||||
public class McObjectConverter
|
||||
{
|
||||
private static int bufferIndex(int x, int y)
|
||||
{
|
||||
return y * 4 + x;
|
||||
}
|
||||
|
||||
|
||||
//========//
|
||||
// matrix //
|
||||
//========//
|
||||
//region
|
||||
|
||||
/** 4x4 float matrix converter */
|
||||
public static Mat4f Convert(
|
||||
#if MC_VER < MC_1_19_4 com.mojang.math.Matrix4f
|
||||
#if MC_VER <= MC_1_12_2 org.joml.Matrix4f
|
||||
#elif MC_VER < MC_1_19_4 com.mojang.math.Matrix4f
|
||||
#elif MC_VER < MC_1_21_6 org.joml.Matrix4f
|
||||
#else org.joml.Matrix4fc
|
||||
#endif
|
||||
@@ -56,21 +64,24 @@ public class McObjectConverter
|
||||
FloatBuffer buffer = FloatBuffer.allocate(16);
|
||||
storeMatrix(mcMatrix, buffer);
|
||||
Mat4f matrix = new Mat4f(buffer);
|
||||
#if MC_VER < MC_1_19_4
|
||||
#if MC_VER > MC_1_12_2 && MC_VER < MC_1_19_4
|
||||
matrix.transpose(); // In 1.19.3 and later, we no longer need to transpose it
|
||||
#endif
|
||||
return matrix;
|
||||
}
|
||||
/** Taken from Minecraft's com.mojang.math.Matrix4f class from 1.18.2 */
|
||||
private static void storeMatrix(
|
||||
#if MC_VER < MC_1_19_4 com.mojang.math.Matrix4f
|
||||
#if MC_VER <= MC_1_12_2 org.joml.Matrix4f
|
||||
#elif MC_VER < MC_1_19_4 com.mojang.math.Matrix4f
|
||||
#elif MC_VER < MC_1_21_6 org.joml.Matrix4f
|
||||
#else org.joml.Matrix4fc
|
||||
#endif
|
||||
matrix,
|
||||
FloatBuffer buffer)
|
||||
{
|
||||
#if MC_VER < MC_1_19_4
|
||||
#if MC_VER <= MC_1_12_2
|
||||
matrix.get(buffer);
|
||||
#elif MC_VER < MC_1_19_4
|
||||
matrix.store(buffer);
|
||||
#else
|
||||
// Mojang starts to use joml's Matrix4f libary in 1.19.3 so we copy their store method and use it here if its newer than 1.19.3
|
||||
@@ -92,37 +103,85 @@ public class McObjectConverter
|
||||
buffer.put(bufferIndex(3, 3), matrix.m33());
|
||||
#endif
|
||||
}
|
||||
private static int bufferIndex(int x, int y) { return y * 4 + x; }
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
static final Direction[] directions;
|
||||
static final EDhDirection[] lodDirections;
|
||||
|
||||
//===========//
|
||||
// direction //
|
||||
//===========//
|
||||
//region
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
private static final EnumFacing[] mcDirections;
|
||||
#else
|
||||
private static final Direction[] mcDirections;
|
||||
#endif
|
||||
|
||||
private static final EDhDirection[] dhDirections;
|
||||
static
|
||||
{
|
||||
EDhDirection[] lodDirs = EDhDirection.values();
|
||||
directions = new Direction[lodDirs.length];
|
||||
lodDirections = new EDhDirection[lodDirs.length];
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
mcDirections = new EnumFacing[lodDirs.length];
|
||||
#else
|
||||
mcDirections = new Direction[lodDirs.length];
|
||||
#endif
|
||||
|
||||
dhDirections = new EDhDirection[lodDirs.length];
|
||||
for (EDhDirection lodDir : lodDirs)
|
||||
{
|
||||
Direction dir;
|
||||
#if MC_VER <= MC_1_12_2
|
||||
EnumFacing dir;
|
||||
#else
|
||||
Direction dir;
|
||||
#endif
|
||||
switch (lodDir.name().toUpperCase())
|
||||
{
|
||||
case "DOWN":
|
||||
#if MC_VER <= MC_1_12_2
|
||||
dir = EnumFacing.DOWN;
|
||||
#else
|
||||
dir = Direction.DOWN;
|
||||
#endif
|
||||
break;
|
||||
case "UP":
|
||||
#if MC_VER <= MC_1_12_2
|
||||
dir = EnumFacing.UP;
|
||||
#else
|
||||
dir = Direction.UP;
|
||||
#endif
|
||||
break;
|
||||
case "NORTH":
|
||||
#if MC_VER <= MC_1_12_2
|
||||
dir = EnumFacing.NORTH;
|
||||
#else
|
||||
dir = Direction.NORTH;
|
||||
#endif
|
||||
break;
|
||||
case "SOUTH":
|
||||
#if MC_VER <= MC_1_12_2
|
||||
dir = EnumFacing.SOUTH;
|
||||
#else
|
||||
dir = Direction.SOUTH;
|
||||
#endif
|
||||
break;
|
||||
case "WEST":
|
||||
#if MC_VER <= MC_1_12_2
|
||||
dir = EnumFacing.WEST;
|
||||
#else
|
||||
dir = Direction.WEST;
|
||||
#endif
|
||||
break;
|
||||
case "EAST":
|
||||
#if MC_VER <= MC_1_12_2
|
||||
dir = EnumFacing.EAST;
|
||||
#else
|
||||
dir = Direction.EAST;
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
dir = null;
|
||||
@@ -131,13 +190,37 @@ public class McObjectConverter
|
||||
|
||||
if (dir == null)
|
||||
{
|
||||
throw new IllegalArgumentException("Invalid direction on init mapping: " + lodDir);
|
||||
throw new IllegalArgumentException("Invalid direction on init mapping: [" + lodDir + "].");
|
||||
}
|
||||
directions[lodDir.ordinal()] = dir;
|
||||
lodDirections[dir.ordinal()] = lodDir;
|
||||
mcDirections[lodDir.ordinal()] = dir;
|
||||
dhDirections[dir.ordinal()] = lodDir;
|
||||
}
|
||||
}
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public static EnumFacing Convert(EDhDirection lodDirection)
|
||||
#else
|
||||
public static Direction Convert(EDhDirection lodDirection)
|
||||
#endif
|
||||
{ return mcDirections[lodDirection.ordinal()]; }
|
||||
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public static EDhDirection Convert(EnumFacing direction)
|
||||
#else
|
||||
public static EDhDirection Convert(Direction direction)
|
||||
#endif
|
||||
{ return dhDirections[direction.ordinal()]; }
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//==================//
|
||||
// position objects //
|
||||
//==================//
|
||||
//region
|
||||
|
||||
public static BlockPos Convert(DhBlockPos wrappedPos) { return new BlockPos(wrappedPos.getX(), wrappedPos.getY(), wrappedPos.getZ()); }
|
||||
|
||||
public static ChunkPos Convert(DhChunkPos wrappedPos) { return new ChunkPos(wrappedPos.getX(), wrappedPos.getZ()); }
|
||||
@@ -150,7 +233,8 @@ public class McObjectConverter
|
||||
#endif
|
||||
}
|
||||
|
||||
public static Direction Convert(EDhDirection lodDirection) { return directions[lodDirection.ordinal()]; }
|
||||
public static EDhDirection Convert(Direction direction) { return lodDirections[direction.ordinal()]; }
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
+8
-5
@@ -51,7 +51,10 @@ public class VersionConstants implements IVersionConstants
|
||||
// it can't load client classes when running as a dedicated server,
|
||||
// which was how we were dynamically accessing the MC version string
|
||||
|
||||
#if MC_VER == MC_1_16_5
|
||||
#if MC_VER == MC_1_12_2
|
||||
return "1.12.2";
|
||||
|
||||
#elif MC_VER == MC_1_16_5
|
||||
return "1.16.5";
|
||||
|
||||
#elif MC_VER == MC_1_17_1
|
||||
@@ -93,8 +96,8 @@ public class VersionConstants implements IVersionConstants
|
||||
return "1.21.10";
|
||||
#elif MC_VER == MC_1_21_11
|
||||
return "1.21.11";
|
||||
#elif MC_VER == MC_1_26_1
|
||||
return "21.6";
|
||||
#elif MC_VER == MC_26_1_2
|
||||
return "26.1.2";
|
||||
#else
|
||||
ERROR MC version constant missing
|
||||
#endif
|
||||
@@ -104,10 +107,10 @@ public class VersionConstants implements IVersionConstants
|
||||
@Override
|
||||
public EDhApiRenderApi getDefaultRenderingApi()
|
||||
{
|
||||
#if MC_VER <= MC_1_26_1
|
||||
#if MC_VER <= MC_1_21_11
|
||||
return EDhApiRenderApi.OPEN_GL;
|
||||
#else
|
||||
ERROR MC version constant missing
|
||||
return EDhApiRenderApi.BLAZE_3D;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
+145
-53
@@ -46,17 +46,30 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.world.IBiomeWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.worldGeneration.IBatchGeneratorEnvironmentWrapper;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
|
||||
#if MC_VER > MC_1_17_1
|
||||
import net.minecraft.core.Holder;
|
||||
#endif
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.client.multiplayer.WorldClient;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.WorldServer;
|
||||
import net.minecraft.world.biome.Biome;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
#else
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.LevelReader;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
#endif
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashSet;
|
||||
|
||||
/**
|
||||
* This handles creating abstract wrapper objects.
|
||||
@@ -115,7 +128,7 @@ public class WrapperFactory implements IWrapperFactory
|
||||
throw new ClassCastException("levelWrapper must be returned by DH and of type ["+ILevelWrapper.class.getName()+"].");
|
||||
}
|
||||
|
||||
return BiomeWrapper.deserialize(resourceLocationString, (ILevelWrapper)levelWrapper);
|
||||
return BiomeWrapper.deserialize(resourceLocationString, (ILevelWrapper)levelWrapper);
|
||||
}
|
||||
@Override
|
||||
public IDhApiBlockStateWrapper getDefaultBlockStateWrapper(String resourceLocationString, IDhApiLevelWrapper levelWrapper) throws IOException, ClassCastException
|
||||
@@ -125,19 +138,19 @@ public class WrapperFactory implements IWrapperFactory
|
||||
throw new ClassCastException("Invalid ["+IDhApiLevelWrapper.class.getSimpleName()+"] value given. Level wrapper object must be one given by the DH API (it can't be a custom implementation), specifically of type ["+ILevelWrapper.class.getName()+"].");
|
||||
}
|
||||
|
||||
return BlockStateWrapper.deserialize(resourceLocationString, (ILevelWrapper)levelWrapper);
|
||||
return BlockStateWrapper.deserialize(resourceLocationString, (ILevelWrapper)levelWrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBiomeWrapper deserializeBiomeWrapper(String str, ILevelWrapper levelWrapper) throws IOException { return BiomeWrapper.deserialize(str, levelWrapper); }
|
||||
@Override
|
||||
@Override
|
||||
public IBiomeWrapper getPlainsBiomeWrapper(ILevelWrapper levelWrapper)
|
||||
{
|
||||
try
|
||||
{
|
||||
return BiomeWrapper.deserialize(BiomeWrapper.PLAINS_RESOURCE_LOCATION_STRING, levelWrapper);
|
||||
}
|
||||
catch (IOException e)
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new LodUtil.AssertFailureException("Unable to parse plains resource string ["+BiomeWrapper.PLAINS_RESOURCE_LOCATION_STRING+"], error:\n " + e.getMessage());
|
||||
}
|
||||
@@ -172,7 +185,8 @@ public class WrapperFactory implements IWrapperFactory
|
||||
*/
|
||||
public IChunkWrapper createChunkWrapper(Object[] objectArray) throws ClassCastException
|
||||
{
|
||||
if (objectArray.length == 1 && objectArray[0] instanceof IChunkWrapper)
|
||||
if (objectArray.length == 1
|
||||
&& objectArray[0] instanceof IChunkWrapper)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -186,41 +200,102 @@ public class WrapperFactory implements IWrapperFactory
|
||||
}
|
||||
}
|
||||
|
||||
//#if MC_VER <= MC_1_XX_X
|
||||
else if (objectArray.length == 2)
|
||||
{
|
||||
// correct number of parameters from the API
|
||||
|
||||
// chunk
|
||||
if (!(objectArray[0] instanceof ChunkAccess))
|
||||
{
|
||||
throw new ClassCastException(createChunkWrapperErrorMessage(objectArray));
|
||||
}
|
||||
ChunkAccess chunk = (ChunkAccess) objectArray[0];
|
||||
|
||||
// level / light source
|
||||
if (!(objectArray[1] instanceof Level))
|
||||
{
|
||||
throw new ClassCastException(createChunkWrapperErrorMessage(objectArray));
|
||||
}
|
||||
// the level is needed for the DH level wrapper...
|
||||
Level level = (Level) objectArray[1];
|
||||
|
||||
|
||||
// level wrapper
|
||||
ILevelWrapper levelWrapper = level.isClientSide()
|
||||
? ClientLevelWrapper.getWrapper((ClientLevel)level)
|
||||
: ServerLevelWrapper.getWrapper((ServerLevel)level);
|
||||
|
||||
|
||||
return new ChunkWrapper(chunk, levelWrapper);
|
||||
}
|
||||
// incorrect number of parameters from the API
|
||||
else
|
||||
else if (objectArray.length != 2)
|
||||
{
|
||||
throw new ClassCastException(createChunkWrapperErrorMessage(objectArray));
|
||||
}
|
||||
//#endif
|
||||
|
||||
|
||||
// correct number of parameters from the API
|
||||
|
||||
//=======//
|
||||
// chunk //
|
||||
//=======//
|
||||
//region
|
||||
|
||||
boolean chunkClassCorrect;
|
||||
#if MC_VER <= MC_1_12_2
|
||||
chunkClassCorrect = (objectArray[0] instanceof Chunk);
|
||||
#else
|
||||
chunkClassCorrect = (objectArray[0] instanceof ChunkAccess);
|
||||
#endif
|
||||
if (!chunkClassCorrect)
|
||||
{
|
||||
throw new ClassCastException(createChunkWrapperErrorMessage(objectArray));
|
||||
}
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
Chunk chunk = (Chunk) objectArray[0];
|
||||
#else
|
||||
ChunkAccess chunk = (ChunkAccess) objectArray[0];
|
||||
#endif
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//=======//
|
||||
// level //
|
||||
//=======//
|
||||
//region
|
||||
|
||||
boolean levelClassCorrect;
|
||||
#if MC_VER <= MC_1_12_2
|
||||
levelClassCorrect = (objectArray[1] instanceof World);
|
||||
#else
|
||||
levelClassCorrect = (objectArray[1] instanceof Level);
|
||||
#endif
|
||||
|
||||
if (!levelClassCorrect)
|
||||
{
|
||||
throw new ClassCastException(createChunkWrapperErrorMessage(objectArray));
|
||||
}
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
World level = (World) objectArray[1];
|
||||
#else
|
||||
Level level = (Level) objectArray[1];
|
||||
#endif
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//===============//
|
||||
// level wrapper //
|
||||
//===============//
|
||||
//region
|
||||
|
||||
boolean isClientSide;
|
||||
#if MC_VER <= MC_1_12_2
|
||||
isClientSide = !level.isRemote;
|
||||
#else
|
||||
isClientSide = level.isClientSide();
|
||||
#endif
|
||||
|
||||
ILevelWrapper levelWrapper;
|
||||
if (isClientSide)
|
||||
{
|
||||
#if MC_VER <= MC_1_12_2
|
||||
levelWrapper = ClientLevelWrapper.getWrapper((WorldClient)level);
|
||||
#else
|
||||
levelWrapper = ClientLevelWrapper.getWrapper((ClientLevel)level);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#if MC_VER <= MC_1_12_2
|
||||
levelWrapper = ServerLevelWrapper.getWrapper((WorldServer)level);
|
||||
#else
|
||||
levelWrapper = ServerLevelWrapper.getWrapper((ServerLevel)level);
|
||||
#endif
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
return new ChunkWrapper(chunk, levelWrapper);
|
||||
}
|
||||
/**
|
||||
* Note: when this is updated for different MC versions,
|
||||
@@ -230,13 +305,19 @@ public class WrapperFactory implements IWrapperFactory
|
||||
{
|
||||
String[] expectedClassNames;
|
||||
|
||||
//#if MC_VER <= MC_1_XX_X
|
||||
expectedClassNames = new String[]
|
||||
{
|
||||
ChunkAccess.class.getName(),
|
||||
"[ServerLevel] or [ClientLevel]" // Classes are not referenced by names to avoid exception when one of them is missing
|
||||
};
|
||||
//#endif
|
||||
#if MC_VER <= MC_1_12_2
|
||||
expectedClassNames = new String[]
|
||||
{
|
||||
Chunk.class.getName(),
|
||||
"[WorldClient] or [WorldServer]" // Classes are not referenced by names to avoid exception when one of them is missing
|
||||
};
|
||||
#else
|
||||
expectedClassNames = new String[]
|
||||
{
|
||||
ChunkAccess.class.getName(),
|
||||
"[ServerLevel] or [ClientLevel]" // Classes are not referenced by names to avoid exception when one of them is missing
|
||||
};
|
||||
#endif
|
||||
|
||||
return createWrapperErrorMessage("Chunk wrapper", expectedClassNames, objectArray);
|
||||
}
|
||||
@@ -258,7 +339,7 @@ public class WrapperFactory implements IWrapperFactory
|
||||
|
||||
// documentation should be in the API interface
|
||||
|
||||
public IDhApiBiomeWrapper getBiomeWrapper(Object[] objectArray, IDhApiLevelWrapper levelWrapper)
|
||||
public IDhApiBiomeWrapper getBiomeWrapper(Object[] objectArray, IDhApiLevelWrapper levelWrapper)
|
||||
{
|
||||
// confirm the API level wrapper is also a Core wrapper
|
||||
if (!(levelWrapper instanceof ILevelWrapper))
|
||||
@@ -322,19 +403,29 @@ public class WrapperFactory implements IWrapperFactory
|
||||
|
||||
|
||||
|
||||
//#if MC_VER <= MC_1_XX_X
|
||||
if (objectArray.length != 1)
|
||||
{
|
||||
throw new ClassCastException(createBlockStateWrapperErrorMessage(objectArray));
|
||||
}
|
||||
if (!(objectArray[0] instanceof BlockState))
|
||||
|
||||
boolean blockClassCorrect;
|
||||
#if MC_VER <= MC_1_12_2
|
||||
blockClassCorrect = (objectArray[0] instanceof IBlockState);
|
||||
#else
|
||||
blockClassCorrect = (objectArray[0] instanceof BlockState);
|
||||
#endif
|
||||
if (!blockClassCorrect)
|
||||
{
|
||||
throw new ClassCastException(createBlockStateWrapperErrorMessage(objectArray));
|
||||
}
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
IBlockState blockState = (IBlockState) objectArray[0];
|
||||
return BlockStateWrapper.fromBlockState(blockState, coreLevelWrapper);
|
||||
#else
|
||||
BlockState blockState = (BlockState) objectArray[0];
|
||||
return BlockStateWrapper.fromBlockState(blockState, coreLevelWrapper);
|
||||
//#endif
|
||||
#endif
|
||||
}
|
||||
/**
|
||||
* Note: when this is updated for different MC versions,
|
||||
@@ -344,7 +435,9 @@ public class WrapperFactory implements IWrapperFactory
|
||||
{
|
||||
String[] expectedClassNames;
|
||||
|
||||
#if MC_VER == MC_1_16_5 || MC_VER == MC_1_17_1
|
||||
#if MC_VER <= MC_1_12_2
|
||||
expectedClassNames = new String[] { IBlockState.class.getName() };
|
||||
#elif MC_VER <= MC_1_17_1
|
||||
expectedClassNames = new String[] { Biome.class.getName() };
|
||||
#else
|
||||
expectedClassNames = new String[] { Holder.class.getName()+"<"+Biome.class.getName()+">" };
|
||||
@@ -357,7 +450,6 @@ public class WrapperFactory implements IWrapperFactory
|
||||
|
||||
|
||||
|
||||
|
||||
//================//
|
||||
// helper methods //
|
||||
//================//
|
||||
@@ -367,8 +459,8 @@ public class WrapperFactory implements IWrapperFactory
|
||||
{
|
||||
// error header
|
||||
StringBuilder message = new StringBuilder(
|
||||
wrapperName + " creation failed. \n" +
|
||||
"Expected object array parameters: \n");
|
||||
wrapperName + " creation failed. \n" +
|
||||
"Expected object array parameters: \n");
|
||||
|
||||
|
||||
// expected parameters
|
||||
|
||||
+40
-12
@@ -1,20 +1,24 @@
|
||||
package com.seibel.distanthorizons.common.wrappers.block;
|
||||
|
||||
#if MC_VER > MC_1_12_2
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.dataObjects.BlockBiomeWrapperPair;
|
||||
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
||||
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPosMutable;
|
||||
import com.seibel.distanthorizons.core.util.ColorUtil;
|
||||
import com.seibel.distanthorizons.coreapi.util.ColorUtil;
|
||||
import com.seibel.distanthorizons.core.util.FullDataPointUtil;
|
||||
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||
import net.minecraft.client.Minecraft;
|
||||
#if MC_VER <= MC_1_12_2
|
||||
import net.minecraft.world.biome.Biome;
|
||||
#else
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.level.ColorResolver;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
#endif
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
@@ -45,8 +49,6 @@ public abstract class AbstractDhTintGetter implements BlockAndTintGetter
|
||||
#endif
|
||||
|
||||
private static final ConcurrentHashMap<BlockBiomeWrapperPair, Integer> COLOR_BY_BLOCK_BIOME_PAIR = new ConcurrentHashMap<>();
|
||||
/** returned if the color cache is incomplete */
|
||||
public static final int INVALID_COLOR = Integer.MIN_VALUE;
|
||||
|
||||
|
||||
protected BiomeWrapper biomeWrapper;
|
||||
@@ -60,6 +62,7 @@ public abstract class AbstractDhTintGetter implements BlockAndTintGetter
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
//region
|
||||
|
||||
public AbstractDhTintGetter() { }
|
||||
|
||||
@@ -76,11 +79,14 @@ public abstract class AbstractDhTintGetter implements BlockAndTintGetter
|
||||
this.smoothingRadiusInBlocks = Config.Client.Advanced.Graphics.Quality.lodBiomeBlending.get();
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
//================//
|
||||
// shared methods //
|
||||
//================//
|
||||
|
||||
//===============//
|
||||
// color getters //
|
||||
//===============//
|
||||
//region
|
||||
|
||||
/** Called by MC's tint getter */
|
||||
@Override
|
||||
@@ -94,7 +100,7 @@ public abstract class AbstractDhTintGetter implements BlockAndTintGetter
|
||||
* Can be called by DH directly, skipping some of MC's logic
|
||||
* to speed up tint getting slightly.
|
||||
*
|
||||
* @return {@link AbstractDhTintGetter#INVALID_COLOR} if any of the biomes needed for this position
|
||||
* @return {@link ClientBlockStateColorCache#INVALID_COLOR} if any of the biomes needed for this position
|
||||
* were not cached. In that case calling {@link AbstractDhTintGetter#getBlockTint(BlockPos, ColorResolver)}
|
||||
* will need to be called by MC's ColorResolver so we can
|
||||
* populate the color cache.
|
||||
@@ -155,9 +161,9 @@ public abstract class AbstractDhTintGetter implements BlockAndTintGetter
|
||||
int id = FullDataPointUtil.getId(dataPoint);
|
||||
BiomeWrapper biomeWrapper = (BiomeWrapper) this.fullDataSource.mapping.getBiomeWrapper(id);
|
||||
int color = this.tryGetClientBiomeColor(colorResolver, biomeWrapper);
|
||||
if (color == INVALID_COLOR)
|
||||
if (color == ClientBlockStateColorCache.INVALID_COLOR)
|
||||
{
|
||||
return INVALID_COLOR;
|
||||
return ClientBlockStateColorCache.INVALID_COLOR;
|
||||
}
|
||||
|
||||
|
||||
@@ -195,7 +201,7 @@ public abstract class AbstractDhTintGetter implements BlockAndTintGetter
|
||||
BlockBiomeWrapperPair pair = BlockBiomeWrapperPair.get(this.blockStateWrapper, biomeWrapper);
|
||||
|
||||
// use the cached color if possible
|
||||
Integer cachedColor = COLOR_BY_BLOCK_BIOME_PAIR.get(pair); // explicit Integer return here reduces unnecessary allocations
|
||||
Integer cachedColor = COLOR_BY_BLOCK_BIOME_PAIR.get(pair);
|
||||
if (cachedColor != null)
|
||||
{
|
||||
return cachedColor;
|
||||
@@ -206,7 +212,7 @@ public abstract class AbstractDhTintGetter implements BlockAndTintGetter
|
||||
// no color resolver is present,
|
||||
// the cache needs to be populated before
|
||||
// we can use the fast path
|
||||
return INVALID_COLOR;
|
||||
return ClientBlockStateColorCache.INVALID_COLOR;
|
||||
}
|
||||
|
||||
|
||||
@@ -335,6 +341,28 @@ public abstract class AbstractDhTintGetter implements BlockAndTintGetter
|
||||
});
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//===========//
|
||||
// set color //
|
||||
//===========//
|
||||
//region
|
||||
|
||||
/**
|
||||
* can be used in newer MC versions
|
||||
* where the color getting logic is a bit more manual
|
||||
*/
|
||||
public static void setStaticColor(BlockStateWrapper blockStateWrapper, BiomeWrapper biomeWrapper, Integer colorInt)
|
||||
{
|
||||
BlockBiomeWrapperPair pair = BlockBiomeWrapperPair.get(blockStateWrapper, biomeWrapper);
|
||||
COLOR_BY_BLOCK_BIOME_PAIR.put(pair, colorInt);
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
}
|
||||
#endif
|
||||
+68
-14
@@ -28,12 +28,15 @@ import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
||||
import net.minecraft.world.level.Level;
|
||||
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IBiomeWrapper;
|
||||
|
||||
#if MC_VER == MC_1_16_5 || MC_VER == MC_1_17_1
|
||||
#if MC_VER > MC_1_12_2
|
||||
import net.minecraft.world.level.Level;
|
||||
#endif
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
#elif MC_VER == MC_1_16_5 || MC_VER == MC_1_17_1
|
||||
import net.minecraft.core.Registry;
|
||||
#elif MC_VER == MC_1_18_2 || MC_VER == MC_1_19_2
|
||||
import net.minecraft.core.Holder;
|
||||
@@ -45,14 +48,21 @@ import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
#endif
|
||||
|
||||
#if MC_VER <= MC_1_21_10
|
||||
#if MC_VER <= MC_1_12_2
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
#elif MC_VER <= MC_1_21_10
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
#else
|
||||
import net.minecraft.resources.Identifier;
|
||||
import net.minecraft.core.component.DataComponentMap;
|
||||
#endif
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
import net.minecraft.world.biome.Biome;
|
||||
#else
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
#endif
|
||||
|
||||
|
||||
#if MC_VER >= MC_1_18_2
|
||||
import net.minecraft.world.level.biome.Biomes;
|
||||
@@ -108,8 +118,13 @@ public class BiomeWrapper implements IBiomeWrapper
|
||||
//==============//
|
||||
// constructors //
|
||||
//==============//
|
||||
//region
|
||||
|
||||
public static BiomeWrapper getBiomeWrapper(#if MC_VER < MC_1_18_2 Biome #else Holder<Biome> #endif biome, ILevelWrapper levelWrapper)
|
||||
#if MC_VER < MC_1_18_2
|
||||
public static BiomeWrapper getBiomeWrapper(Biome biome, ILevelWrapper levelWrapper)
|
||||
#else
|
||||
public static BiomeWrapper getBiomeWrapper(Holder<Biome> biome, ILevelWrapper levelWrapper)
|
||||
#endif
|
||||
{
|
||||
if (biome == null)
|
||||
{
|
||||
@@ -129,7 +144,12 @@ public class BiomeWrapper implements IBiomeWrapper
|
||||
return newWrapper;
|
||||
}
|
||||
}
|
||||
private BiomeWrapper(#if MC_VER < MC_1_18_2 Biome #else Holder<Biome> #endif biome, ILevelWrapper levelWrapper)
|
||||
|
||||
#if MC_VER < MC_1_18_2
|
||||
private BiomeWrapper(Biome biome, ILevelWrapper levelWrapper)
|
||||
#else
|
||||
private BiomeWrapper(Holder<Biome> biome, ILevelWrapper levelWrapper)
|
||||
#endif
|
||||
{
|
||||
this.biome = biome;
|
||||
this.serialString = this.serialize(levelWrapper);
|
||||
@@ -138,11 +158,14 @@ public class BiomeWrapper implements IBiomeWrapper
|
||||
//LOGGER.trace("Created BiomeWrapper ["+this.serialString+"] for ["+biome+"]");
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//=========//
|
||||
// methods //
|
||||
//=========//
|
||||
//region
|
||||
|
||||
@Override
|
||||
public String getName()
|
||||
@@ -188,11 +211,14 @@ public class BiomeWrapper implements IBiomeWrapper
|
||||
@Override
|
||||
public String toString() { return this.getSerialString(); }
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//=======================//
|
||||
// serialization methods //
|
||||
//=======================//
|
||||
//region
|
||||
|
||||
public String serialize(ILevelWrapper levelWrapper)
|
||||
{
|
||||
@@ -219,8 +245,10 @@ public class BiomeWrapper implements IBiomeWrapper
|
||||
|
||||
// generate the serial string //
|
||||
|
||||
#if MC_VER > MC_1_12_2
|
||||
Level level = (Level)levelWrapper.getWrappedMcObject();
|
||||
net.minecraft.core.RegistryAccess registryAccess = level.registryAccess();
|
||||
#endif
|
||||
|
||||
#if MC_VER <= MC_1_21_10
|
||||
ResourceLocation resourceLocation;
|
||||
@@ -228,16 +256,19 @@ public class BiomeWrapper implements IBiomeWrapper
|
||||
Identifier resourceLocation;
|
||||
#endif
|
||||
|
||||
#if MC_VER <= MC_1_17_1
|
||||
#if MC_VER <= MC_1_12_2
|
||||
resourceLocation = biome.getRegistryName();
|
||||
#elif MC_VER <= MC_1_17_1
|
||||
resourceLocation = registryAccess.registryOrThrow(Registry.BIOME_REGISTRY).getKey(this.biome);
|
||||
#elif MC_VER <= MC_1_19_2
|
||||
resourceLocation = registryAccess.registryOrThrow(Registry.BIOME_REGISTRY).getKey(this.biome.value());
|
||||
#elif MC_VER <= MC_1_21_4
|
||||
#elif MC_VER <= MC_1_21_1
|
||||
resourceLocation = registryAccess.registryOrThrow(Registries.BIOME).getKey(this.biome.value());
|
||||
#else
|
||||
resourceLocation = registryAccess.lookupOrThrow(Registries.BIOME).getKey(this.biome.value());
|
||||
#endif
|
||||
|
||||
|
||||
if (resourceLocation == null)
|
||||
{
|
||||
String biomeName;
|
||||
@@ -292,11 +323,16 @@ public class BiomeWrapper implements IBiomeWrapper
|
||||
{
|
||||
try
|
||||
{
|
||||
#if MC_VER > MC_1_12_2
|
||||
Level level = (Level) levelWrapper.getWrappedMcObject();
|
||||
net.minecraft.core.RegistryAccess registryAccess = level.registryAccess();
|
||||
|
||||
#endif
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
BiomeDeserializeResult deserializeResult = deserializeBiome(resourceLocationString);
|
||||
#else
|
||||
BiomeDeserializeResult deserializeResult = deserializeBiome(resourceLocationString, registryAccess);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
if (!deserializeResult.success)
|
||||
@@ -324,7 +360,11 @@ public class BiomeWrapper implements IBiomeWrapper
|
||||
}
|
||||
}
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public static BiomeDeserializeResult deserializeBiome(String resourceLocationString) throws IOException
|
||||
#else
|
||||
public static BiomeDeserializeResult deserializeBiome(String resourceLocationString, net.minecraft.core.RegistryAccess registryAccess) throws IOException
|
||||
#endif
|
||||
{
|
||||
// parse the resource location
|
||||
int separatorIndex = resourceLocationString.indexOf(":");
|
||||
@@ -355,14 +395,17 @@ public class BiomeWrapper implements IBiomeWrapper
|
||||
|
||||
|
||||
boolean success;
|
||||
#if MC_VER <= MC_1_17_1
|
||||
#if MC_VER <= MC_1_12_2
|
||||
Biome biome = Biome.REGISTRY.getObject(resourceLocation);
|
||||
success = (biome != null);
|
||||
#elif MC_VER <= MC_1_17_1
|
||||
Biome biome = registryAccess.registryOrThrow(Registry.BIOME_REGISTRY).get(resourceLocation);
|
||||
success = (biome != null);
|
||||
#elif MC_VER <= MC_1_19_2
|
||||
Biome unwrappedBiome = registryAccess.registryOrThrow(Registry.BIOME_REGISTRY).get(resourceLocation);
|
||||
success = (unwrappedBiome != null);
|
||||
Holder<Biome> biome = new Holder.Direct<>(unwrappedBiome);
|
||||
#elif MC_VER <= MC_1_21_4
|
||||
#elif MC_VER <= MC_1_21_1
|
||||
Biome unwrappedBiome = registryAccess.registryOrThrow(Registries.BIOME).get(resourceLocation);
|
||||
success = (unwrappedBiome != null);
|
||||
Holder<Biome> biome = new Holder.Direct<>(unwrappedBiome);
|
||||
@@ -399,10 +442,14 @@ public class BiomeWrapper implements IBiomeWrapper
|
||||
return new BiomeDeserializeResult(success, biome);
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//================//
|
||||
// helper classes //
|
||||
//================//
|
||||
//region
|
||||
|
||||
public static class BiomeDeserializeResult
|
||||
{
|
||||
@@ -412,14 +459,21 @@ public class BiomeWrapper implements IBiomeWrapper
|
||||
public final Biome biome;
|
||||
#else
|
||||
public final Holder<Biome> biome;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
public BiomeDeserializeResult(boolean success, #if MC_VER < MC_1_18_2 Biome #else Holder<Biome> #endif biome)
|
||||
#if MC_VER < MC_1_18_2
|
||||
public BiomeDeserializeResult(boolean success, Biome biome)
|
||||
#else
|
||||
public BiomeDeserializeResult(boolean success, Holder<Biome> biome)
|
||||
#endif
|
||||
{
|
||||
this.success = success;
|
||||
this.biome = biome;
|
||||
}
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
+865
-431
File diff suppressed because it is too large
Load Diff
+417
-153
@@ -19,31 +19,45 @@
|
||||
|
||||
package com.seibel.distanthorizons.common.wrappers.block;
|
||||
|
||||
import com.seibel.distanthorizons.api.interfaces.block.IDhApiBlockStateWrapper;
|
||||
import com.seibel.distanthorizons.api.interfaces.world.IDhApiLevelWrapper;
|
||||
import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiBlockColorOverrideEvent;
|
||||
import com.seibel.distanthorizons.common.wrappers.McObjectConverter;
|
||||
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos;
|
||||
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPosMutable;
|
||||
import com.seibel.distanthorizons.core.util.ColorUtil;
|
||||
import com.seibel.distanthorizons.coreapi.util.ColorUtil;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||
import com.seibel.distanthorizons.coreapi.DependencyInjection.ApiEventInjector;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
#if MC_VER <= MC_1_12_2
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.util.EnumBlockRenderType;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.block.BlockRotatedPillar;
|
||||
import net.minecraft.block.*;
|
||||
import net.minecraft.client.multiplayer.WorldClient;
|
||||
import net.minecraft.client.renderer.color.BlockColors;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
#else
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.level.block.*;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.properties.SlabType;
|
||||
#endif
|
||||
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
#if MC_VER >= MC_1_19_2
|
||||
import net.minecraft.util.RandomSource;
|
||||
#else
|
||||
import java.util.Random;
|
||||
#endif
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||
import net.minecraft.world.level.block.state.properties.SlabType;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
#if MC_VER < MC_1_21_5
|
||||
import net.minecraft.client.renderer.block.model.BakedQuad;
|
||||
@@ -53,23 +67,38 @@ import net.minecraft.client.renderer.block.model.BakedQuad;
|
||||
#else
|
||||
import net.minecraft.client.renderer.block.dispatch.BlockStateModelPart;
|
||||
import net.minecraft.client.resources.model.geometry.BakedQuad;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.client.color.block.BlockTintSource;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This stores and calculates the colors
|
||||
* the given {@link BlockState} should have based
|
||||
* the given BlockState should have based
|
||||
* on the given {@link IClientLevelWrapper}.
|
||||
*
|
||||
*
|
||||
* @see ColorUtil
|
||||
*/
|
||||
public class ClientBlockStateColorCache
|
||||
{
|
||||
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
private static final Minecraft MC = Minecraft.getMinecraft();
|
||||
#else
|
||||
private static final Minecraft MC = Minecraft.getInstance();
|
||||
#endif
|
||||
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
#else
|
||||
private static final HashSet<BlockState> BLOCK_STATES_THAT_NEED_LEVEL = new HashSet<>();
|
||||
#endif
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
private static final HashSet<IBlockState> BROKEN_BLOCK_STATES = new HashSet<>();
|
||||
#else
|
||||
private static final HashSet<BlockState> BROKEN_BLOCK_STATES = new HashSet<>();
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Methods using MC's "RandomSource" object aren't thread safe <br>
|
||||
@@ -81,18 +110,33 @@ public class ClientBlockStateColorCache
|
||||
*/
|
||||
private static final ReentrantLock RESOLVE_LOCK = new ReentrantLock();
|
||||
|
||||
public static final int INVALID_COLOR = -1;
|
||||
|
||||
|
||||
/** This is the order each direction on a block is processed when attempting to get the texture/color */
|
||||
#if MC_VER <= MC_1_12_2
|
||||
private static final @Nullable EnumFacing[] COLOR_RESOLUTION_DIRECTION_ORDER =
|
||||
{
|
||||
EnumFacing.UP,
|
||||
null, // null represents "unculled" faces, IE the top of farmland
|
||||
EnumFacing.NORTH,
|
||||
EnumFacing.EAST,
|
||||
EnumFacing.WEST,
|
||||
EnumFacing.SOUTH,
|
||||
EnumFacing.DOWN
|
||||
};
|
||||
#else
|
||||
private static final @Nullable Direction[] COLOR_RESOLUTION_DIRECTION_ORDER =
|
||||
{
|
||||
{
|
||||
Direction.UP,
|
||||
null, // null represents "unculled" faces, IE the top of farmland
|
||||
Direction.NORTH,
|
||||
Direction.EAST,
|
||||
Direction.WEST,
|
||||
Direction.SOUTH,
|
||||
Direction.DOWN
|
||||
Direction.NORTH,
|
||||
Direction.EAST,
|
||||
Direction.WEST,
|
||||
Direction.SOUTH,
|
||||
Direction.DOWN
|
||||
};
|
||||
#endif
|
||||
|
||||
private static final int FLOWER_COLOR_SCALE = 5;
|
||||
|
||||
@@ -106,7 +150,11 @@ public class ClientBlockStateColorCache
|
||||
#endif
|
||||
|
||||
private final IClientLevelWrapper clientLevelWrapper;
|
||||
#if MC_VER <= MC_1_12_2
|
||||
private final IBlockState blockState;
|
||||
#else
|
||||
private final BlockState blockState;
|
||||
#endif
|
||||
private final BlockStateWrapper blockStateWrapper;
|
||||
|
||||
private boolean isColorResolved = false;
|
||||
@@ -119,6 +167,7 @@ public class ClientBlockStateColorCache
|
||||
//===========//
|
||||
// constants //
|
||||
//===========//
|
||||
//region
|
||||
|
||||
private static final int MIN_SRGB_BITS = 0x39000000; // 2^(-13)
|
||||
private static final int MAX_SRGB_BITS = 0x3f7fffff; // 1.0 - f32::EPSILON
|
||||
@@ -182,16 +231,27 @@ public class ClientBlockStateColorCache
|
||||
//endregion
|
||||
};
|
||||
|
||||
private static final ThreadLocal<TintWithoutLevelOverrider> TintWithoutLevelOverrideGetter = ThreadLocal.withInitial(() -> new TintWithoutLevelOverrider());
|
||||
private static final ThreadLocal<TintGetterOverride> TintOverrideGetter = ThreadLocal.withInitial(() -> new TintGetterOverride());
|
||||
// these are threadlocals since AbstractDhTintGetter use local variables to handle color queries
|
||||
#if MC_VER > MC_1_12_2
|
||||
private static final ThreadLocal<TintWithoutLevelOverrider> TintWithoutLevelOverrideGetter = ThreadLocal.withInitial(TintWithoutLevelOverrider::new);
|
||||
private static final ThreadLocal<TintGetterOverride> TintOverrideGetter = ThreadLocal.withInitial(TintGetterOverride::new);
|
||||
#endif
|
||||
private static final ThreadLocal<DhApiBlockColorOverrideEvent.EventParam> ColorOverrideEventParamGetter = ThreadLocal.withInitial(DhApiBlockColorOverrideEvent.EventParam::new);
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
//region
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public ClientBlockStateColorCache(IBlockState blockState, IClientLevelWrapper clientLevelWrapper)
|
||||
#else
|
||||
public ClientBlockStateColorCache(BlockState blockState, IClientLevelWrapper clientLevelWrapper)
|
||||
#endif
|
||||
{
|
||||
this.blockState = blockState;
|
||||
this.blockStateWrapper = BlockStateWrapper.fromBlockState(blockState, clientLevelWrapper);
|
||||
@@ -200,11 +260,14 @@ public class ClientBlockStateColorCache
|
||||
this.resolveColors();
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//===================//
|
||||
// color calculation //
|
||||
//===================//
|
||||
//region
|
||||
|
||||
private void resolveColors()
|
||||
{
|
||||
@@ -218,17 +281,44 @@ public class ClientBlockStateColorCache
|
||||
// getQuads() isn't thread safe so we need to put this logic in a lock
|
||||
RESOLVE_LOCK.lock();
|
||||
|
||||
if (this.blockState.getFluidState().isEmpty())
|
||||
#if MC_VER <= MC_1_12_2
|
||||
if (this.blockState.getRenderType() == EnumBlockRenderType.ENTITYBLOCK_ANIMATED)
|
||||
{
|
||||
this.needPostTinting = false;
|
||||
this.tintIndex = 0;
|
||||
this.baseColor = ColorUtil.argbToInt(255,
|
||||
this.blockStateWrapper.getMapColor().getRed(),
|
||||
this.blockStateWrapper.getMapColor().getGreen(),
|
||||
this.blockStateWrapper.getMapColor().getBlue());
|
||||
this.isColorResolved = true;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!this.blockStateWrapper.isLiquid())
|
||||
{
|
||||
// look for the first non-empty direction
|
||||
List<BakedQuad> quads = null;
|
||||
for (Direction direction : COLOR_RESOLUTION_DIRECTION_ORDER)
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
EnumFacing direction;
|
||||
#else
|
||||
Direction direction;
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < COLOR_RESOLUTION_DIRECTION_ORDER.length; i++)
|
||||
{
|
||||
direction = COLOR_RESOLUTION_DIRECTION_ORDER[i];
|
||||
quads = this.getQuadsForDirection(direction);
|
||||
if (quads != null && !quads.isEmpty()
|
||||
&& !(
|
||||
#if MC_VER <= MC_1_12_2
|
||||
this.blockState.getBlock() instanceof BlockRotatedPillar
|
||||
&& direction == EnumFacing.UP
|
||||
#else
|
||||
this.blockState.getBlock() instanceof RotatedPillarBlock
|
||||
&& direction == Direction.UP
|
||||
#endif
|
||||
)
|
||||
)
|
||||
{
|
||||
@@ -245,39 +335,57 @@ public class ClientBlockStateColorCache
|
||||
&& !quads.isEmpty()
|
||||
&& quads.get(0) != null)
|
||||
{
|
||||
BakedQuad firstQuad = quads.get(0);
|
||||
try
|
||||
{
|
||||
BakedQuad firstQuad = quads.get(0);
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
this.needPostTinting = firstQuad.hasTintIndex();
|
||||
#elif MC_VER <= MC_1_21_11
|
||||
this.needPostTinting = firstQuad.isTinted();
|
||||
#else
|
||||
this.needPostTinting = firstQuad.materialInfo().isTinted();
|
||||
#endif
|
||||
|
||||
#if MC_VER <= MC_1_21_11
|
||||
this.needPostTinting = firstQuad.isTinted();
|
||||
#else
|
||||
this.needPostTinting = firstQuad.materialInfo().isTinted();
|
||||
#endif
|
||||
|
||||
#if MC_VER <= MC_1_21_4
|
||||
this.tintIndex = firstQuad.getTintIndex();
|
||||
#elif MC_VER <= MC_1_21_11
|
||||
this.tintIndex = firstQuad.tintIndex();
|
||||
#else
|
||||
this.tintIndex = firstQuad.materialInfo().tintIndex();
|
||||
#endif
|
||||
|
||||
#if MC_VER < MC_1_17_1
|
||||
this.baseColor = calculateColorFromTexture(
|
||||
firstQuad.sprite,
|
||||
EColorMode.getColorMode(this.blockState.getBlock()));
|
||||
#elif MC_VER < MC_1_21_5
|
||||
this.baseColor = calculateColorFromTexture(
|
||||
firstQuad.getSprite(),
|
||||
EColorMode.getColorMode(this.blockState.getBlock()));
|
||||
#elif MC_VER <= MC_1_21_11
|
||||
this.baseColor = calculateColorFromTexture(
|
||||
firstQuad.sprite(),
|
||||
EColorMode.getColorMode(this.blockState.getBlock()));
|
||||
#else
|
||||
this.baseColor = calculateColorFromTexture(
|
||||
firstQuad.materialInfo().sprite(),
|
||||
EColorMode.getColorMode(this.blockState.getBlock()));
|
||||
#endif
|
||||
#if MC_VER <= MC_1_21_4
|
||||
this.tintIndex = firstQuad.getTintIndex();
|
||||
#elif MC_VER <= MC_1_21_11
|
||||
this.tintIndex = firstQuad.tintIndex();
|
||||
#else
|
||||
this.tintIndex = firstQuad.materialInfo().tintIndex();
|
||||
#endif
|
||||
|
||||
#if MC_VER < MC_1_17_1 && MC_VER > MC_1_12_2
|
||||
this.baseColor = calculateColorFromTexture(
|
||||
firstQuad.sprite,
|
||||
EColorMode.getColorMode(this.blockState.getBlock()));
|
||||
#elif MC_VER < MC_1_21_5
|
||||
this.baseColor = calculateColorFromTexture(
|
||||
firstQuad.getSprite(),
|
||||
EColorMode.getColorMode(this.blockState.getBlock()));
|
||||
#elif MC_VER <= MC_1_21_11
|
||||
this.baseColor = calculateColorFromTexture(
|
||||
firstQuad.sprite(),
|
||||
EColorMode.getColorMode(this.blockState.getBlock()));
|
||||
#else
|
||||
this.baseColor = calculateColorFromTexture(
|
||||
firstQuad.materialInfo().sprite(),
|
||||
EColorMode.getColorMode(this.blockState.getBlock()));
|
||||
#endif
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// Shouldn't normally happen, but there was at least
|
||||
// one report of MC's texture being un-loaded
|
||||
// which prevented us from getting the texture.
|
||||
// So we should have some basic backup logic.
|
||||
|
||||
LOGGER.warn("Failed to get texture color for block ["+this.blockStateWrapper.getSerialString()+"] due to: ["+e.getMessage()+"], falling back to particle color.");
|
||||
|
||||
this.needPostTinting = false;
|
||||
this.tintIndex = 0;
|
||||
this.baseColor = this.getParticleIconColor();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -307,20 +415,43 @@ public class ClientBlockStateColorCache
|
||||
@Nullable
|
||||
private List<BakedQuad> getUnculledQuads() { return this.getQuadsForDirection(null); }
|
||||
@Nullable
|
||||
#if MC_VER <= MC_1_12_2
|
||||
private List<BakedQuad> getQuadsForDirection(@Nullable EnumFacing direction)
|
||||
#else
|
||||
private List<BakedQuad> getQuadsForDirection(@Nullable Direction direction)
|
||||
#endif
|
||||
{
|
||||
#if MC_VER <= MC_1_12_2
|
||||
IBlockState effectiveBlockState = this.blockState;
|
||||
#else
|
||||
BlockState effectiveBlockState = this.blockState;
|
||||
#endif
|
||||
|
||||
// if this block is a slab, use it's double variant so we can get the top face,
|
||||
// otherwise the color will use the side, which isn't as accurate
|
||||
#if MC_VER <= MC_1_12_2
|
||||
if (this.blockState.getBlock() instanceof BlockSlab && !((BlockSlab) this.blockState.getBlock()).isDouble())
|
||||
{
|
||||
effectiveBlockState = this.blockState.withProperty(BlockSlab.HALF, BlockSlab.EnumBlockHalf.TOP);
|
||||
}
|
||||
#else
|
||||
if (this.blockState.getBlock() instanceof SlabBlock)
|
||||
{
|
||||
effectiveBlockState = this.blockState.setValue( SlabBlock.TYPE, SlabType.DOUBLE );
|
||||
}
|
||||
#endif
|
||||
|
||||
List<BakedQuad> quads;
|
||||
|
||||
#if MC_VER < MC_1_21_5
|
||||
#if MC_VER <= MC_1_12_2
|
||||
try {
|
||||
quads = MC.getBlockRendererDispatcher().getModelForState(effectiveBlockState).getQuads(effectiveBlockState, direction, RANDOM.nextLong());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
quads = Collections.emptyList();
|
||||
}
|
||||
#elif MC_VER < MC_1_21_5
|
||||
quads = MC.getModelManager().getBlockModelShaper().
|
||||
getBlockModel(effectiveBlockState).getQuads(effectiveBlockState, direction, RANDOM);
|
||||
#elif MC_VER <= MC_1_21_11
|
||||
@@ -377,29 +508,29 @@ public class ClientBlockStateColorCache
|
||||
//_ OpenGL RGBA format Java Order: 0xAA BB GG RR
|
||||
tempColor = TextureAtlasSpriteWrapper.getPixelRGBA(texture, 0, u, v);
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
int b = (tempColor & 0x000000FF);
|
||||
int g = (tempColor & 0x0000FF00) >>> 8;
|
||||
int r = (tempColor & 0x00FF0000) >>> 16;
|
||||
int a = (tempColor & 0xFF000000) >>> 24;
|
||||
#else
|
||||
int r = (tempColor & 0x000000FF);
|
||||
int g = (tempColor & 0x0000FF00) >>> 8;
|
||||
int b = (tempColor & 0x00FF0000) >>> 16;
|
||||
int a = (tempColor & 0xFF000000) >>> 24;
|
||||
#endif
|
||||
|
||||
int scale = 1;
|
||||
if (colorMode == EColorMode.Leaves)
|
||||
{
|
||||
//switch (//FIXME add config option)
|
||||
// case BLACK:
|
||||
// a = 255; //simulate black background of fast leaves
|
||||
// break;
|
||||
// case IGNORE:
|
||||
if (a == 0) {
|
||||
continue; //same long grass
|
||||
}
|
||||
else
|
||||
{
|
||||
a = 255; //just in case there are semi transparent pixels
|
||||
}
|
||||
// break;
|
||||
// case TRANSPARENT:
|
||||
// break; //do nothing, let it count towards transparency
|
||||
|
||||
if (a == 0)
|
||||
{
|
||||
continue; //same long grass
|
||||
}
|
||||
else
|
||||
{
|
||||
a = 255; //just in case there are semi transparent pixels
|
||||
}
|
||||
}
|
||||
else if (a == 0 && colorMode != EColorMode.Glass)
|
||||
{
|
||||
@@ -445,7 +576,9 @@ public class ClientBlockStateColorCache
|
||||
}
|
||||
private static int getTextureWidth(TextureAtlasSprite texture)
|
||||
{
|
||||
#if MC_VER < MC_1_19_4
|
||||
#if MC_VER <= MC_1_12_2
|
||||
return texture.getIconWidth();
|
||||
#elif MC_VER < MC_1_19_4
|
||||
return texture.getWidth();
|
||||
#else
|
||||
return texture.contents().width();
|
||||
@@ -453,7 +586,9 @@ public class ClientBlockStateColorCache
|
||||
}
|
||||
private static int getTextureHeight(TextureAtlasSprite texture)
|
||||
{
|
||||
#if MC_VER < MC_1_19_4
|
||||
#if MC_VER <= MC_1_12_2
|
||||
return texture.getIconHeight();
|
||||
#elif MC_VER < MC_1_19_4
|
||||
return texture.getHeight();
|
||||
#else
|
||||
return texture.contents().height();
|
||||
@@ -487,7 +622,9 @@ public class ClientBlockStateColorCache
|
||||
private int getParticleIconColor()
|
||||
{
|
||||
return calculateColorFromTexture(
|
||||
#if MC_VER <= MC_1_21_11
|
||||
#if MC_VER <= MC_1_12_2
|
||||
Minecraft.getMinecraft().getBlockRendererDispatcher().getBlockModelShapes().getTexture(this.blockState),
|
||||
#elif MC_VER <= MC_1_21_11
|
||||
Minecraft.getInstance().getModelManager().getBlockModelShaper().getParticleIcon(this.blockState),
|
||||
#else
|
||||
Minecraft.getInstance().getModelManager().getBlockStateModelSet().get(this.blockState).particleMaterial().sprite(),
|
||||
@@ -495,126 +632,206 @@ public class ClientBlockStateColorCache
|
||||
EColorMode.getColorMode(this.blockState.getBlock()));
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//===============//
|
||||
// public getter //
|
||||
//===============//
|
||||
//region
|
||||
|
||||
public int getColor(BiomeWrapper biomeWrapper, FullDataSourceV2 fullDataSource, DhBlockPos blockPos)
|
||||
{
|
||||
// only get the tint if the block needs to be tinted
|
||||
if (!this.needPostTinting)
|
||||
{
|
||||
return this.baseColor;
|
||||
}
|
||||
int tintColor = ClientBlockStateColorCache.INVALID_COLOR;
|
||||
|
||||
// don't try tinting blocks that don't support our method of tint getting
|
||||
if (BROKEN_BLOCK_STATES.contains(this.blockState))
|
||||
if (this.needPostTinting)
|
||||
{
|
||||
return this.baseColor;
|
||||
}
|
||||
|
||||
|
||||
// attempt to get the tint
|
||||
int tintColor = -1;
|
||||
try
|
||||
{
|
||||
// try to use the fast tint getter logic first
|
||||
if (!BLOCK_STATES_THAT_NEED_LEVEL.contains(this.blockState))
|
||||
// don't try tinting blocks that don't support our method of tint getting
|
||||
if (BROKEN_BLOCK_STATES.contains(this.blockState))
|
||||
{
|
||||
try
|
||||
return this.baseColor;
|
||||
}
|
||||
|
||||
|
||||
// attempt to get the tint
|
||||
try
|
||||
{
|
||||
#if MC_VER <= MC_1_12_2
|
||||
// 1.12.2 doesn't have BlockAndTintGetter -> get tintColor from biome
|
||||
WorldClient world = (WorldClient) this.clientLevelWrapper.getWrappedMcObject();
|
||||
BlockPos mcPos = new BlockPos(blockPos.getX(), blockPos.getY(), blockPos.getZ());
|
||||
|
||||
Block block = this.blockState.getBlock();
|
||||
if (block instanceof BlockGrass
|
||||
|| block instanceof BlockBush)
|
||||
{
|
||||
TintWithoutLevelOverrider tintOverride = TintWithoutLevelOverrideGetter.get();
|
||||
tintColor = biomeWrapper.biome.getGrassColorAtPos(mcPos);
|
||||
}
|
||||
else if (block instanceof BlockLeaves)
|
||||
{
|
||||
tintColor = biomeWrapper.biome.getFoliageColorAtPos(mcPos);
|
||||
}
|
||||
else if (block instanceof BlockLiquid) // We don't want lava to fall into the else block
|
||||
{
|
||||
if(block == Blocks.WATER
|
||||
|| block == Blocks.FLOWING_WATER)
|
||||
{
|
||||
tintColor = biomeWrapper.biome.getWaterColor();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BlockColors blockColors = Minecraft.getMinecraft().getBlockColors();
|
||||
tintColor = blockColors.colorMultiplier(blockState, world, mcPos, this.tintIndex);
|
||||
|
||||
if (tintColor == ClientBlockStateColorCache.INVALID_COLOR)
|
||||
{
|
||||
tintColor = blockColors.getColor(blockState, world, mcPos);
|
||||
}
|
||||
}
|
||||
#else
|
||||
// try to use the fast tint getter logic first
|
||||
if (!BLOCK_STATES_THAT_NEED_LEVEL.contains(this.blockState))
|
||||
{
|
||||
try
|
||||
{
|
||||
TintWithoutLevelOverrider tintOverride = TintWithoutLevelOverrideGetter.get();
|
||||
tintOverride.update(biomeWrapper, this.blockStateWrapper, fullDataSource, this.clientLevelWrapper);
|
||||
|
||||
// try using DH's cached tint values first if possible
|
||||
tintColor = tintOverride.tryGetBlockTint(new DhBlockPosMutable(blockPos));
|
||||
if (tintColor == ClientBlockStateColorCache.INVALID_COLOR)
|
||||
{
|
||||
// one or more tint values weren't calculated,
|
||||
// we need MC's color resolver
|
||||
#if MC_VER <= MC_1_21_11
|
||||
tintColor = Minecraft.getInstance()
|
||||
.getBlockColors()
|
||||
.getColor(this.blockState,
|
||||
tintOverride, // tintOverride will save the result of this query to speed up future queries
|
||||
McObjectConverter.Convert(blockPos),
|
||||
this.tintIndex);
|
||||
#else
|
||||
BlockTintSource tintSource = Minecraft.getInstance()
|
||||
.getBlockColors()
|
||||
.getTintSource(this.blockState, this.tintIndex);
|
||||
// a tint source may be null for blocks that don't actually need tinting
|
||||
// in that case the base color should be sufficient
|
||||
// Example: cherry blossom leaves
|
||||
if (tintSource != null)
|
||||
{
|
||||
BlockPos mcPos = McObjectConverter.Convert(blockPos);
|
||||
tintColor = tintSource.colorInWorld(this.blockState, tintOverride, mcPos);
|
||||
if (tintColor == ClientBlockStateColorCache.INVALID_COLOR)
|
||||
{
|
||||
tintColor = tintSource.colorAsTerrainParticle(this.blockState, tintOverride, mcPos);
|
||||
}
|
||||
}
|
||||
|
||||
// save this color to speed up future queries
|
||||
TintWithoutLevelOverrider.setStaticColor(this.blockStateWrapper, biomeWrapper, tintColor);
|
||||
// try to get the blended color with this new information
|
||||
tintColor = tintOverride.tryGetBlockTint(new DhBlockPosMutable(blockPos));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
#if MC_VER <= MC_1_21_11
|
||||
// this exception generally occurs if the tint requires other blocks besides itself
|
||||
LOGGER.debug("Unable to use ["+ TintWithoutLevelOverrider.class.getSimpleName()+"] to get the block tint for block: [" + this.blockState + "] and biome: [" + biomeWrapper + "] at pos: " + blockPos + ". Error: [" + e.getMessage() + "]. Attempting to use backup method...", e);
|
||||
BLOCK_STATES_THAT_NEED_LEVEL.add(this.blockState);
|
||||
#else
|
||||
// only display the error once per block/biome type to reduce log spam
|
||||
if (!BROKEN_BLOCK_STATES.contains(this.blockState))
|
||||
{
|
||||
LOGGER.warn("Failed to get block color for block: [" + this.blockState + "] and biome: [" + biomeWrapper + "] at pos: " + blockPos + ". Error: [" + e.getMessage() + "]. Note: future errors for this block/biome will be ignored.", e);
|
||||
BROKEN_BLOCK_STATES.add(this.blockState);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// level-specific logic is only needed for MC 1.21.11 and older
|
||||
#if MC_VER <= MC_1_21_11 && MC_VER > MC_1_12_2
|
||||
// use the level logic only if requested
|
||||
if (BLOCK_STATES_THAT_NEED_LEVEL.contains(this.blockState))
|
||||
{
|
||||
// the level shouldn't be used all the time due to it breaking some blocks tinting
|
||||
// specifically oceans don't render correctly
|
||||
|
||||
TintGetterOverride tintOverride = TintOverrideGetter.get();
|
||||
tintOverride.update(biomeWrapper, this.blockStateWrapper, fullDataSource, this.clientLevelWrapper);
|
||||
|
||||
// try using DH's cached tint values first if possible
|
||||
tintColor = tintOverride.tryGetBlockTint(new DhBlockPosMutable(blockPos));
|
||||
if (tintColor == AbstractDhTintGetter.INVALID_COLOR)
|
||||
if (tintColor == ClientBlockStateColorCache.INVALID_COLOR)
|
||||
{
|
||||
// one or more tint values weren't calculated,
|
||||
// we need MC's color resolver
|
||||
#if MC_VER <= MC_1_21_11
|
||||
tintColor = Minecraft.getInstance()
|
||||
.getBlockColors()
|
||||
.getColor(this.blockState,
|
||||
tintOverride,
|
||||
McObjectConverter.Convert(blockPos),
|
||||
this.tintIndex);
|
||||
#else
|
||||
tintColor = Minecraft.getInstance()
|
||||
.getBlockColors()
|
||||
.getTintSources(this.blockState)
|
||||
.get(this.tintIndex)
|
||||
.color(this.blockState);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
catch (UnsupportedOperationException e)
|
||||
{
|
||||
// this exception generally occurs if the tint requires other blocks besides itself
|
||||
LOGGER.debug("Unable to use ["+ TintWithoutLevelOverrider.class.getSimpleName()+"] to get the block tint for block: [" + this.blockState + "] and biome: [" + biomeWrapper + "] at pos: " + blockPos + ". Error: [" + e.getMessage() + "]. Attempting to use backup method...", e);
|
||||
BLOCK_STATES_THAT_NEED_LEVEL.add(this.blockState);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
// use the level logic only if requested
|
||||
if (BLOCK_STATES_THAT_NEED_LEVEL.contains(this.blockState))
|
||||
catch (Exception e)
|
||||
{
|
||||
// the level shouldn't be used all the time due to it breaking some blocks tinting
|
||||
// specifically oceans don't render correctly
|
||||
|
||||
TintGetterOverride tintOverride = TintOverrideGetter.get();
|
||||
tintOverride.update(biomeWrapper, this.blockStateWrapper, fullDataSource, this.clientLevelWrapper);
|
||||
|
||||
tintColor = tintOverride.tryGetBlockTint(new DhBlockPosMutable(blockPos));
|
||||
if (tintColor == AbstractDhTintGetter.INVALID_COLOR)
|
||||
// only display the error once per block/biome type to reduce log spam
|
||||
if (!BROKEN_BLOCK_STATES.contains(this.blockState))
|
||||
{
|
||||
#if MC_VER <= MC_1_21_11
|
||||
tintColor = Minecraft.getInstance()
|
||||
.getBlockColors()
|
||||
.getColor(this.blockState,
|
||||
tintOverride,
|
||||
McObjectConverter.Convert(blockPos),
|
||||
this.tintIndex);
|
||||
#else
|
||||
tintColor = Minecraft.getInstance()
|
||||
.getBlockColors()
|
||||
.getTintSources(this.blockState)
|
||||
.get(this.tintIndex)
|
||||
.color(this.blockState);
|
||||
#endif
|
||||
LOGGER.warn("Failed to get block color for block: [" + this.blockState + "] and biome: [" + biomeWrapper + "] at pos: " + blockPos + ". Error: [" + e.getMessage() + "]. Note: future errors for this block/biome will be ignored.", e);
|
||||
BROKEN_BLOCK_STATES.add(this.blockState);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
|
||||
|
||||
int returnColor;
|
||||
if (tintColor != ClientBlockStateColorCache.INVALID_COLOR)
|
||||
{
|
||||
// only display the error once per block/biome type to reduce log spam
|
||||
if (!BROKEN_BLOCK_STATES.contains(this.blockState))
|
||||
{
|
||||
LOGGER.warn("Failed to get block color for block: [" + this.blockState + "] and biome: [" + biomeWrapper + "] at pos: " + blockPos + ". Error: ["+e.getMessage() + "]. Note: future errors for this block/biome will be ignored.", e);
|
||||
BROKEN_BLOCK_STATES.add(this.blockState);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (tintColor != -1)
|
||||
{
|
||||
return ColorUtil.multiplyARGBwithRGB(this.baseColor, tintColor);
|
||||
returnColor = ColorUtil.multiplyARGBwithRGB(this.baseColor, tintColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
// unable to get the tinted color, use the base color instead
|
||||
return this.baseColor;
|
||||
returnColor = this.baseColor;
|
||||
}
|
||||
|
||||
|
||||
// only fire an API event if needed
|
||||
// (this is done to reduce GC pressure and speed up color getting)
|
||||
if (this.blockStateWrapper.allowApiColorOverride())
|
||||
{
|
||||
DhApiBlockColorOverrideEvent.EventParam eventParam = ColorOverrideEventParamGetter.get();
|
||||
eventParam.update(
|
||||
this.clientLevelWrapper,
|
||||
this.blockStateWrapper, returnColor,
|
||||
blockPos.getX(), blockPos.getY(), blockPos.getZ()
|
||||
);
|
||||
ApiEventInjector.INSTANCE.fireAllEvents(DhApiBlockColorOverrideEvent.class, eventParam);
|
||||
|
||||
// let the API user override this color
|
||||
returnColor = eventParam.getColorAsInt();
|
||||
}
|
||||
|
||||
return returnColor;
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//================//
|
||||
// helper classes //
|
||||
//================//
|
||||
//region
|
||||
|
||||
private enum EColorMode
|
||||
{
|
||||
@@ -626,14 +843,54 @@ public class ClientBlockStateColorCache
|
||||
|
||||
static EColorMode getColorMode(Block block)
|
||||
{
|
||||
if (block instanceof LeavesBlock)
|
||||
|
||||
|
||||
|
||||
//========//
|
||||
// leaves //
|
||||
//========//
|
||||
//region
|
||||
|
||||
boolean isLeavesBlock;
|
||||
#if MC_VER <= MC_1_12_2
|
||||
isLeavesBlock = block instanceof BlockLeaves;
|
||||
#else
|
||||
isLeavesBlock = block instanceof LeavesBlock;
|
||||
#endif
|
||||
if (isLeavesBlock)
|
||||
{
|
||||
return Leaves;
|
||||
}
|
||||
if (block instanceof FlowerBlock)
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//========//
|
||||
// flower //
|
||||
//========//
|
||||
//region
|
||||
|
||||
boolean isFlowerBlock;
|
||||
#if MC_VER <= MC_1_12_2
|
||||
isFlowerBlock = block instanceof BlockFlower;
|
||||
#else
|
||||
isFlowerBlock = block instanceof FlowerBlock;
|
||||
#endif
|
||||
if (isFlowerBlock)
|
||||
{
|
||||
return Flower;
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// misc/simple //
|
||||
//=============//
|
||||
//region
|
||||
|
||||
if (block.toString().contains("glass"))
|
||||
{
|
||||
return Glass;
|
||||
@@ -642,10 +899,17 @@ public class ClientBlockStateColorCache
|
||||
{
|
||||
return Chisel;
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
return Default;
|
||||
}
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
+5
-2
@@ -25,7 +25,7 @@ import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
#if MC_VER < MC_1_17_1
|
||||
#elif MC_VER < MC_1_21_3
|
||||
#else
|
||||
import com.seibel.distanthorizons.core.util.ColorUtil;
|
||||
import com.seibel.distanthorizons.coreapi.util.ColorUtil;
|
||||
import net.minecraft.client.renderer.texture.SpriteContents;
|
||||
#endif
|
||||
|
||||
@@ -38,7 +38,10 @@ public class TextureAtlasSpriteWrapper
|
||||
{
|
||||
public static int getPixelRGBA(TextureAtlasSprite sprite, int frameIndex, int x, int y)
|
||||
{
|
||||
#if MC_VER < MC_1_17_1
|
||||
#if MC_VER <= MC_1_12_2
|
||||
int[][] frameData = sprite.getFrameTextureData(frameIndex);
|
||||
return frameData[0][y * sprite.getIconWidth() + x];
|
||||
#elif MC_VER < MC_1_17_1
|
||||
return sprite.mainImage[0].getPixelRGBA(
|
||||
x + sprite.framesX[frameIndex] * sprite.getWidth(),
|
||||
y + sprite.framesY[frameIndex] * sprite.getHeight());
|
||||
|
||||
+2
-1
@@ -18,7 +18,7 @@
|
||||
*/
|
||||
|
||||
package com.seibel.distanthorizons.common.wrappers.block;
|
||||
|
||||
#if MC_VER > MC_1_12_2
|
||||
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||
import net.minecraft.core.BlockPos;
|
||||
@@ -189,3 +189,4 @@ public class TintGetterOverride extends AbstractDhTintGetter
|
||||
|
||||
|
||||
}
|
||||
#endif
|
||||
+2
-1
@@ -18,7 +18,7 @@
|
||||
*/
|
||||
|
||||
package com.seibel.distanthorizons.common.wrappers.block;
|
||||
|
||||
#if MC_VER > MC_1_12_2
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.level.LevelReader;
|
||||
@@ -109,3 +109,4 @@ public class TintWithoutLevelOverrider extends AbstractDhTintGetter
|
||||
|
||||
|
||||
}
|
||||
#endif
|
||||
+144
-22
@@ -31,12 +31,19 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.ChunkLightStorage
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IMutableBlockPosWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IBiomeWrapper;
|
||||
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
||||
#if MC_VER <= MC_1_12_2
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
|
||||
#else
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
import net.minecraft.world.level.chunk.ProtoChunk;
|
||||
import net.minecraft.world.level.levelgen.Heightmap;
|
||||
#endif
|
||||
|
||||
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||
|
||||
@@ -67,9 +74,10 @@ import net.minecraft.world.level.chunk.LevelChunkSection;
|
||||
import net.minecraft.world.level.chunk.LevelChunkSection;
|
||||
#endif
|
||||
|
||||
#if MC_VER <= MC_1_20_4
|
||||
#if MC_VER <= MC_1_12_2
|
||||
#elif MC_VER <= MC_1_20_4
|
||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||
#else
|
||||
#elif MC_VER > MC_1_12_2
|
||||
import net.minecraft.world.level.chunk.status.ChunkStatus;
|
||||
#endif
|
||||
|
||||
@@ -86,8 +94,12 @@ public class ChunkWrapper implements IChunkWrapper
|
||||
|
||||
private static boolean heightmapThreadWarningLogged = false;
|
||||
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
private final Chunk chunk;
|
||||
#else
|
||||
private final ChunkAccess chunk;
|
||||
#endif
|
||||
|
||||
private final DhChunkPos chunkPos;
|
||||
private final ILevelWrapper wrappedLevel;
|
||||
|
||||
@@ -112,13 +124,17 @@ public class ChunkWrapper implements IChunkWrapper
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
|
||||
//region
|
||||
/**
|
||||
* Note: this constructor should be very
|
||||
* fast since it will be called frequently on the MC
|
||||
* server thread and a slow method will cause server lag.
|
||||
*/
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public ChunkWrapper(Chunk chunk, ILevelWrapper wrappedLevel)
|
||||
#else
|
||||
public ChunkWrapper(ChunkAccess chunk, ILevelWrapper wrappedLevel)
|
||||
#endif
|
||||
{
|
||||
this.chunk = chunk;
|
||||
this.wrappedLevel = wrappedLevel;
|
||||
@@ -133,15 +149,22 @@ public class ChunkWrapper implements IChunkWrapper
|
||||
@Override
|
||||
public ChunkWrapper copy() { return new ChunkWrapper(this.chunk, this.wrappedLevel); }
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//=========//
|
||||
// getters //
|
||||
//=========//
|
||||
//region
|
||||
|
||||
@Override
|
||||
public int getHeight() { return getHeight(this.chunk); }
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public static int getHeight(Chunk chunk)
|
||||
#else
|
||||
public static int getHeight(ChunkAccess chunk)
|
||||
#endif
|
||||
{
|
||||
#if MC_VER < MC_1_17_1
|
||||
return 255;
|
||||
@@ -152,7 +175,11 @@ public class ChunkWrapper implements IChunkWrapper
|
||||
|
||||
@Override
|
||||
public int getInclusiveMinBuildHeight() { return getInclusiveMinBuildHeight(this.chunk); }
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public static int getInclusiveMinBuildHeight(Chunk chunk)
|
||||
#else
|
||||
public static int getInclusiveMinBuildHeight(ChunkAccess chunk)
|
||||
#endif
|
||||
{
|
||||
#if MC_VER < MC_1_17_1
|
||||
return 0;
|
||||
@@ -165,9 +192,15 @@ public class ChunkWrapper implements IChunkWrapper
|
||||
|
||||
@Override
|
||||
public int getExclusiveMaxBuildHeight() { return getExclusiveMaxBuildHeight(this.chunk); }
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public static int getExclusiveMaxBuildHeight(Chunk chunk)
|
||||
#else
|
||||
public static int getExclusiveMaxBuildHeight(ChunkAccess chunk)
|
||||
#endif
|
||||
{
|
||||
#if MC_VER < MC_1_21_3
|
||||
#if MC_VER <= MC_1_12_2
|
||||
return 256;
|
||||
#elif MC_VER < MC_1_21_3
|
||||
return chunk.getMaxBuildHeight();
|
||||
#else
|
||||
// +1 since Minecraft made the max value inclusive
|
||||
@@ -188,7 +221,11 @@ public class ChunkWrapper implements IChunkWrapper
|
||||
this.minNonEmptyHeight = this.getInclusiveMinBuildHeight();
|
||||
|
||||
// determine the lowest empty section (bottom up)
|
||||
#if MC_VER <= MC_1_12_2
|
||||
ExtendedBlockStorage[] sections = this.chunk.getBlockStorageArray();
|
||||
#else
|
||||
LevelChunkSection[] sections = this.chunk.getSections();
|
||||
#endif
|
||||
for (int index = 0; index < sections.length; index++)
|
||||
{
|
||||
if (sections[index] == null)
|
||||
@@ -220,7 +257,11 @@ public class ChunkWrapper implements IChunkWrapper
|
||||
this.maxNonEmptyHeight = this.getExclusiveMaxBuildHeight();
|
||||
|
||||
// determine the highest empty section (top down)
|
||||
#if MC_VER <= MC_1_12_2
|
||||
ExtendedBlockStorage[] sections = this.chunk.getBlockStorageArray();
|
||||
#else
|
||||
LevelChunkSection[] sections = this.chunk.getSections();
|
||||
#endif
|
||||
for (int index = sections.length-1; index >= 0; index--)
|
||||
{
|
||||
// update at each position to fix using the max height if the chunk is empty
|
||||
@@ -240,11 +281,13 @@ public class ChunkWrapper implements IChunkWrapper
|
||||
|
||||
return this.maxNonEmptyHeight;
|
||||
}
|
||||
#if MC_VER <= MC_1_12_2
|
||||
private static boolean isChunkSectionEmpty(ExtendedBlockStorage section)
|
||||
#else
|
||||
private static boolean isChunkSectionEmpty(LevelChunkSection section)
|
||||
#endif
|
||||
{
|
||||
#if MC_VER == MC_1_16_5
|
||||
return section.isEmpty();
|
||||
#elif MC_VER == MC_1_17_1
|
||||
#if MC_VER <= MC_1_17_1
|
||||
return section.isEmpty();
|
||||
#else
|
||||
return section.hasOnlyAir();
|
||||
@@ -322,7 +365,11 @@ public class ChunkWrapper implements IChunkWrapper
|
||||
// will be null if we want to use MC heightmaps
|
||||
if (this.solidHeightMap == null)
|
||||
{
|
||||
#if MC_VER <= MC_1_12_2
|
||||
return this.chunk.getHeightValue(xRel, zRel);
|
||||
#else
|
||||
return this.chunk.getOrCreateHeightmapUnprimed(Heightmap.Types.WORLD_SURFACE).getFirstAvailable(xRel, zRel);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -337,19 +384,30 @@ public class ChunkWrapper implements IChunkWrapper
|
||||
|
||||
if (this.lightBlockingHeightMap == null)
|
||||
{
|
||||
#if MC_VER <= MC_1_12_2
|
||||
return this.chunk.getHeightValue(xRel, zRel);
|
||||
#else
|
||||
return this.chunk.getOrCreateHeightmapUnprimed(Heightmap.Types.MOTION_BLOCKING).getFirstAvailable(xRel, zRel);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.lightBlockingHeightMap[xRel][zRel];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public IBiomeWrapper getBiome(int relX, int relY, int relZ)
|
||||
{
|
||||
#if MC_VER < MC_1_17_1
|
||||
#if MC_VER <= MC_1_12_2
|
||||
BlockPos.MutableBlockPos blockPos = MUTABLE_BLOCK_POS_REF.get();
|
||||
blockPos.setPos(relX, relY, relZ);
|
||||
|
||||
World world = (World) this.wrappedLevel.getWrappedMcObject();
|
||||
|
||||
return BiomeWrapper.getBiomeWrapper(this.chunk.getBiome(blockPos, world.getBiomeProvider()), wrappedLevel);
|
||||
#elif MC_VER < MC_1_17_1
|
||||
return BiomeWrapper.getBiomeWrapper(this.chunk.getBiomes().getNoiseBiome(
|
||||
relX >> 2, relY >> 2, relZ >> 2),
|
||||
this.wrappedLevel);
|
||||
@@ -357,10 +415,6 @@ public class ChunkWrapper implements IChunkWrapper
|
||||
return BiomeWrapper.getBiomeWrapper(this.chunk.getBiomes().getNoiseBiome(
|
||||
QuartPos.fromBlock(relX), QuartPos.fromBlock(relY), QuartPos.fromBlock(relZ)),
|
||||
this.wrappedLevel);
|
||||
#elif MC_VER < MC_1_18_2
|
||||
return BiomeWrapper.getBiomeWrapper(this.chunk.getNoiseBiome(
|
||||
QuartPos.fromBlock(relX), QuartPos.fromBlock(relY), QuartPos.fromBlock(relZ)),
|
||||
this.wrappedLevel);
|
||||
#else
|
||||
//Now returns a Holder<Biome> instead of Biome
|
||||
return BiomeWrapper.getBiomeWrapper(this.chunk.getNoiseBiome(
|
||||
@@ -376,9 +430,13 @@ public class ChunkWrapper implements IChunkWrapper
|
||||
|
||||
BlockPos.MutableBlockPos blockPos = MUTABLE_BLOCK_POS_REF.get();
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
blockPos.setPos(relX, relY, relZ);
|
||||
#else
|
||||
blockPos.setX(relX);
|
||||
blockPos.setY(relY);
|
||||
blockPos.setZ(relZ);
|
||||
#endif
|
||||
|
||||
try
|
||||
{
|
||||
@@ -401,9 +459,13 @@ public class ChunkWrapper implements IChunkWrapper
|
||||
this.throwIndexOutOfBoundsIfRelativePosOutsideChunkBounds(relX, relY, relZ);
|
||||
|
||||
BlockPos.MutableBlockPos pos = (BlockPos.MutableBlockPos)mcBlockPos.getWrappedMcObject();
|
||||
#if MC_VER <= MC_1_12_2
|
||||
pos.setPos(relX, relY, relZ);
|
||||
#else
|
||||
pos.setX(relX);
|
||||
pos.setY(relY);
|
||||
pos.setZ(relZ);
|
||||
#endif
|
||||
|
||||
try
|
||||
{
|
||||
@@ -513,8 +575,14 @@ public class ChunkWrapper implements IChunkWrapper
|
||||
@Override
|
||||
public DhChunkPos getChunkPos() { return this.chunkPos; }
|
||||
|
||||
public ChunkAccess getChunk() { return this.chunk; }
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public Chunk getChunk()
|
||||
#else
|
||||
public ChunkAccess getChunk()
|
||||
#endif
|
||||
{ return this.chunk; }
|
||||
|
||||
#if MC_VER > MC_1_12_2
|
||||
public void trySetStatus(ChunkStatus status) { trySetStatus(this.getChunk(), status); }
|
||||
/** does nothing if the chunk object doesn't support setting it's status */
|
||||
public static void trySetStatus(ChunkAccess chunk, ChunkStatus status)
|
||||
@@ -538,21 +606,53 @@ public class ChunkWrapper implements IChunkWrapper
|
||||
return chunk.getPersistedStatus();
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
@Override
|
||||
public int getMaxBlockX() { return this.chunk.getPos().getMaxBlockX(); }
|
||||
public int getMaxBlockX()
|
||||
{
|
||||
#if MC_VER <= MC_1_12_2
|
||||
return this.chunk.getPos().getXEnd();
|
||||
#else
|
||||
return this.chunk.getPos().getMaxBlockX();
|
||||
#endif
|
||||
}
|
||||
@Override
|
||||
public int getMaxBlockZ() { return this.chunk.getPos().getMaxBlockZ(); }
|
||||
public int getMaxBlockZ()
|
||||
{
|
||||
#if MC_VER <= MC_1_12_2
|
||||
return this.chunk.getPos().getZEnd();
|
||||
#else
|
||||
return this.chunk.getPos().getMaxBlockZ();
|
||||
#endif
|
||||
}
|
||||
@Override
|
||||
public int getMinBlockX() { return this.chunk.getPos().getMinBlockX(); }
|
||||
public int getMinBlockX()
|
||||
{
|
||||
#if MC_VER <= MC_1_12_2
|
||||
return this.chunk.getPos().getXStart();
|
||||
#else
|
||||
return this.chunk.getPos().getMinBlockX();
|
||||
#endif
|
||||
}
|
||||
@Override
|
||||
public int getMinBlockZ() { return this.chunk.getPos().getMinBlockZ(); }
|
||||
public int getMinBlockZ()
|
||||
{
|
||||
#if MC_VER <= MC_1_12_2
|
||||
return this.chunk.getPos().getZStart();
|
||||
#else
|
||||
return this.chunk.getPos().getMinBlockZ();
|
||||
#endif
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//==========//
|
||||
// lighting //
|
||||
//==========//
|
||||
//region
|
||||
|
||||
@Override
|
||||
public void setIsDhSkyLightCorrect(boolean isDhLightCorrect) { this.isDhSkyLightCorrect = isDhLightCorrect; }
|
||||
@@ -629,8 +729,23 @@ public class ChunkWrapper implements IChunkWrapper
|
||||
{
|
||||
this.blockLightPosList = new ArrayList<>();
|
||||
|
||||
|
||||
#if MC_VER < MC_1_20_1
|
||||
//1.12.2 doesn't store lights we must bruteforce it
|
||||
#if MC_VER <= MC_1_12_2
|
||||
for (int x = 0; x < 16; x++)
|
||||
{
|
||||
for (int z = 0; z < 16; z++)
|
||||
{
|
||||
for (int y = 0; y < 256; y++)
|
||||
{
|
||||
IBlockState blockState = this.chunk.getBlockState(x, y, z);
|
||||
if (blockState.getLightValue() > 0)
|
||||
{
|
||||
this.blockLightPosList.add(new DhBlockPos(this.chunk.getPos().getXStart() + x, y, this.chunk.getPos().getZStart() + z));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#elif MC_VER < MC_1_20_1
|
||||
this.chunk.getLights().forEach((blockPos) ->
|
||||
{
|
||||
this.blockLightPosList.add(new DhBlockPos(blockPos.getX(), blockPos.getY(), blockPos.getZ()));
|
||||
@@ -652,11 +767,14 @@ public class ChunkWrapper implements IChunkWrapper
|
||||
return this.blockLightPosList;
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//================//
|
||||
// base overrides //
|
||||
//================//
|
||||
//region
|
||||
|
||||
@Override
|
||||
public String toString() { return this.chunk.getClass().getSimpleName() + this.chunk.getPos(); }
|
||||
@@ -672,4 +790,8 @@ public class ChunkWrapper implements IChunkWrapper
|
||||
// return this.blockBiomeHashCode;
|
||||
//}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
-1121
File diff suppressed because it is too large
Load Diff
@@ -1,12 +1,19 @@
|
||||
package com.seibel.distanthorizons.common.wrappers.gui;
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
#else
|
||||
import net.minecraft.client.gui.Font;
|
||||
|
||||
import net.minecraft.client.gui.components.Button;
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
import net.minecraft.network.chat.Component;
|
||||
#endif
|
||||
|
||||
#if MC_VER < MC_1_20_1
|
||||
#if MC_VER <= MC_1_12_2
|
||||
#elif MC_VER < MC_1_20_1
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
#elif MC_VER <= MC_1_21_11
|
||||
import net.minecraft.client.gui.GuiGraphics;
|
||||
@@ -16,26 +23,73 @@ import net.minecraft.client.gui.GuiGraphicsExtractor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public class DhScreen extends GuiScreen
|
||||
#else
|
||||
public class DhScreen extends Screen
|
||||
#endif
|
||||
{
|
||||
#if MC_VER <= MC_1_12_2
|
||||
protected ITextComponent title;
|
||||
#endif
|
||||
|
||||
protected DhScreen(Component $$0)
|
||||
#if MC_VER <= MC_1_12_2
|
||||
protected DhScreen(ITextComponent title)
|
||||
{
|
||||
super($$0);
|
||||
this.title = title;
|
||||
}
|
||||
#else
|
||||
protected DhScreen(Component title)
|
||||
{
|
||||
super(title);
|
||||
}
|
||||
#endif
|
||||
|
||||
// addRenderableWidget in 1.17 and over
|
||||
// addButton in 1.16 and below
|
||||
#if MC_VER <= MC_1_12_2
|
||||
protected GuiButton addBtn(GuiButton button)
|
||||
#else
|
||||
protected Button addBtn(Button button)
|
||||
#endif
|
||||
{
|
||||
#if MC_VER < MC_1_17_1
|
||||
#if MC_VER <= MC_1_12_2
|
||||
this.buttonList.add(button);
|
||||
return button;
|
||||
#elif MC_VER < MC_1_17_1
|
||||
return this.addButton(button);
|
||||
#else
|
||||
return this.addRenderableWidget(button);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if MC_VER < MC_1_20_1
|
||||
#if MC_VER <= MC_1_12_2
|
||||
@Override
|
||||
protected void actionPerformed(GuiButton button)
|
||||
{
|
||||
OnPressed handler = GuiHelper.HANDLER_BY_BUTTON.get(button);
|
||||
if (handler != null)
|
||||
{
|
||||
handler.pressed(button);
|
||||
}
|
||||
}
|
||||
|
||||
protected void DhDrawCenteredString(ITextComponent text, int x, int y, int color) {
|
||||
drawCenteredString(fontRenderer, text.getFormattedText(), x, y, color);
|
||||
}
|
||||
|
||||
protected void DhDrawString(ITextComponent text, int x, int y, int color) {
|
||||
drawString(fontRenderer, text.getFormattedText(), x, y, color);
|
||||
}
|
||||
|
||||
protected void DhRenderComponentTooltip(List<ITextComponent> list, int x, int y) {
|
||||
drawHoveringText(list.stream().map(ITextComponent::getFormattedText).toList(), x, y, fontRenderer);
|
||||
}
|
||||
|
||||
protected void DhRenderTooltip(ITextComponent text, int x, int y) {
|
||||
drawHoveringText(List.of(text.getFormattedText()), x, y, fontRenderer);
|
||||
}
|
||||
#elif MC_VER < MC_1_20_1
|
||||
protected void DhDrawCenteredString(PoseStack guiStack, Font font, Component text, int x, int y, int color)
|
||||
{
|
||||
drawCenteredString(guiStack, font, text, x, y, color);
|
||||
@@ -112,7 +166,4 @@ public class DhScreen extends Screen
|
||||
guiStack.setTooltipForNextFrame(font, text, x, y);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
+9
@@ -1,16 +1,25 @@
|
||||
package com.seibel.distanthorizons.common.wrappers.gui;
|
||||
|
||||
import com.seibel.distanthorizons.common.wrappers.gui.classicConfig.ClassicConfigGUI;
|
||||
import com.seibel.distanthorizons.core.config.ConfigHandler;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||
#if MC_VER <= MC_1_12_2
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
#else
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
#endif
|
||||
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||
|
||||
public class GetConfigScreen
|
||||
{
|
||||
protected static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public static GuiScreen getScreen(GuiScreen parent)
|
||||
#else
|
||||
public static Screen getScreen(Screen parent)
|
||||
#endif
|
||||
{
|
||||
if (ModInfo.IS_DEV_BUILD)
|
||||
{
|
||||
|
||||
+63
-11
@@ -1,11 +1,21 @@
|
||||
package com.seibel.distanthorizons.common.wrappers.gui;
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.GuiTextField;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
import net.minecraft.util.text.TextComponentString;
|
||||
import net.minecraft.util.text.TextComponentTranslation;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
#else
|
||||
import net.minecraft.client.gui.components.AbstractWidget;
|
||||
import net.minecraft.client.gui.components.Button;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.MutableComponent;
|
||||
#endif
|
||||
|
||||
#if MC_VER < MC_1_19_2
|
||||
#if MC_VER < MC_1_19_2 && MC_VER > MC_1_12_2
|
||||
import net.minecraft.network.chat.TextComponent;
|
||||
import net.minecraft.network.chat.TranslatableComponent;
|
||||
#endif
|
||||
@@ -15,57 +25,99 @@ public class GuiHelper
|
||||
/**
|
||||
* Helper static methods for versional compat
|
||||
*/
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public static final Map<GuiButton, OnPressed> HANDLER_BY_BUTTON = new HashMap<>();
|
||||
#endif
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public static GuiButton MakeBtn(ITextComponent base, int posX, int posZ, int width, int height, OnPressed action)
|
||||
#else
|
||||
public static Button MakeBtn(Component base, int posX, int posZ, int width, int height, Button.OnPress action)
|
||||
#endif
|
||||
{
|
||||
#if MC_VER < MC_1_19_4
|
||||
#if MC_VER <= MC_1_12_2
|
||||
GuiButton button = new GuiButton(HANDLER_BY_BUTTON.size(), posX, posZ, width, height, base.getFormattedText());
|
||||
HANDLER_BY_BUTTON.put(button, action);
|
||||
return button;
|
||||
#elif MC_VER < MC_1_19_4
|
||||
return new Button(posX, posZ, width, height, base, action);
|
||||
#else
|
||||
return Button.builder(base, action).bounds(posX, posZ, width, height).build();
|
||||
#endif
|
||||
}
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public static ITextComponent TextOrLiteral(String text)
|
||||
#else
|
||||
public static MutableComponent TextOrLiteral(String text)
|
||||
#endif
|
||||
{
|
||||
#if MC_VER < MC_1_19_2
|
||||
#if MC_VER <= MC_1_12_2
|
||||
return new TextComponentString(text);
|
||||
#elif MC_VER < MC_1_19_2
|
||||
return new TextComponent(text);
|
||||
#else
|
||||
return Component.literal(text);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public static ITextComponent TextOrTranslatable(String text)
|
||||
#else
|
||||
public static MutableComponent TextOrTranslatable(String text)
|
||||
#endif
|
||||
{
|
||||
#if MC_VER < MC_1_19_2
|
||||
#if MC_VER <= MC_1_12_2
|
||||
return new TextComponentString(text);
|
||||
#elif MC_VER < MC_1_19_2
|
||||
return new TextComponent(text);
|
||||
#else
|
||||
return Component.translatable(text);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public static ITextComponent Translatable(String text, Object... args)
|
||||
#else
|
||||
public static MutableComponent Translatable(String text, Object... args)
|
||||
#endif
|
||||
{
|
||||
#if MC_VER < MC_1_19_2
|
||||
#if MC_VER <= MC_1_12_2
|
||||
return new TextComponentTranslation(text, args);
|
||||
#elif MC_VER < MC_1_19_2
|
||||
return new TranslatableComponent(text, args);
|
||||
#else
|
||||
return Component.translatable(text, args);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void SetX(AbstractWidget w, int x)
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public static void SetX(GuiButton widget, int x)
|
||||
#else
|
||||
public static void SetX(AbstractWidget widget, int x)
|
||||
#endif
|
||||
{
|
||||
#if MC_VER < MC_1_19_4
|
||||
w.x = x;
|
||||
widget.x = x;
|
||||
#else
|
||||
w.setX(x);
|
||||
widget.setX(x);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void SetY(AbstractWidget w, int y)
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public static void SetY(GuiTextField textField, int y) { textField.y = y; }
|
||||
#endif
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public static void SetY(GuiButton widget, int y)
|
||||
#else
|
||||
public static void SetY(AbstractWidget widget, int y)
|
||||
#endif
|
||||
{
|
||||
#if MC_VER < MC_1_19_4
|
||||
w.y = y;
|
||||
widget.y = y;
|
||||
#else
|
||||
w.setY(y);
|
||||
widget.setY(y);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -1,21 +1,34 @@
|
||||
package com.seibel.distanthorizons.common.wrappers.gui;
|
||||
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.config.ILangWrapper;
|
||||
#if MC_VER <= MC_1_12_2
|
||||
import net.minecraft.client.resources.I18n;
|
||||
#else
|
||||
import net.minecraft.client.resources.language.I18n;
|
||||
#endif
|
||||
|
||||
public class LangWrapper implements ILangWrapper
|
||||
{
|
||||
public static final LangWrapper INSTANCE = new LangWrapper();
|
||||
|
||||
@Override
|
||||
public boolean langExists(String str)
|
||||
{
|
||||
#if MC_VER <= MC_1_12_2
|
||||
return I18n.hasKey(str);
|
||||
#else
|
||||
return I18n.exists(str);
|
||||
#endif
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLang(String str)
|
||||
{
|
||||
#if MC_VER <= MC_1_12_2
|
||||
return I18n.format(str);
|
||||
#else
|
||||
return I18n.get(str);
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+116
-16
@@ -1,17 +1,27 @@
|
||||
package com.seibel.distanthorizons.common.wrappers.gui;
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
import org.lwjglx.opengl.Display;
|
||||
#else
|
||||
import com.mojang.blaze3d.platform.Window;
|
||||
|
||||
#endif
|
||||
|
||||
import com.seibel.distanthorizons.core.config.gui.AbstractScreen;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
|
||||
#if MC_VER > MC_1_12_2
|
||||
import net.minecraft.client.gui.components.ContainerObjectSelectionList;
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
#endif
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
#if MC_VER < MC_1_20_1
|
||||
#if MC_VER <= MC_1_12_2
|
||||
import net.minecraft.client.gui.GuiListExtended;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.gui.GuiSlot;
|
||||
#elif MC_VER < MC_1_20_1
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
#elif MC_VER <= MC_1_21_11
|
||||
import net.minecraft.client.gui.GuiGraphics;
|
||||
@@ -24,19 +34,29 @@ import java.util.*;
|
||||
|
||||
public class MinecraftScreen
|
||||
{
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public static GuiScreen getScreen(GuiScreen parent, AbstractScreen screen, String translationName)
|
||||
#else
|
||||
public static Screen getScreen(Screen parent, AbstractScreen screen, String translationName)
|
||||
#endif
|
||||
{
|
||||
return new ConfigScreenRenderer(parent, screen, translationName);
|
||||
}
|
||||
|
||||
private static class ConfigScreenRenderer extends DhScreen
|
||||
{
|
||||
#if MC_VER <= MC_1_12_2
|
||||
private final GuiScreen parent;
|
||||
#else
|
||||
private final Screen parent;
|
||||
#endif
|
||||
private ConfigListWidget configListWidget;
|
||||
private AbstractScreen screen;
|
||||
|
||||
|
||||
#if MC_VER < MC_1_19_2
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public static net.minecraft.util.text.TextComponentTranslation translate(String str, Object... args)
|
||||
{ return new net.minecraft.util.text.TextComponentTranslation(str, args); }
|
||||
#elif MC_VER < MC_1_19_2
|
||||
public static net.minecraft.network.chat.TranslatableComponent translate(String str, Object... args)
|
||||
{ return new net.minecraft.network.chat.TranslatableComponent(str, args); }
|
||||
#else
|
||||
@@ -44,10 +64,16 @@ public class MinecraftScreen
|
||||
{ return net.minecraft.network.chat.Component.translatable(str, args); }
|
||||
#endif
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
protected ConfigScreenRenderer(GuiScreen parent, AbstractScreen screen, String translationName)
|
||||
#else
|
||||
protected ConfigScreenRenderer(Screen parent, AbstractScreen screen, String translationName)
|
||||
#endif
|
||||
{
|
||||
super(translate(translationName));
|
||||
#if MC_VER < MC_1_21_9
|
||||
#if MC_VER <= MC_1_12_2
|
||||
screen.minecraftWindow = Display.getWindow();
|
||||
#elif MC_VER < MC_1_21_9
|
||||
screen.minecraftWindow = Minecraft.getInstance().getWindow().getWindow();
|
||||
#else
|
||||
screen.minecraftWindow = Minecraft.getInstance().getWindow().handle();
|
||||
@@ -57,30 +83,53 @@ public class MinecraftScreen
|
||||
}
|
||||
|
||||
@Override
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public void initGui()
|
||||
#else
|
||||
protected void init()
|
||||
#endif
|
||||
{
|
||||
super.init(); // Init Minecraft's screen
|
||||
#if MC_VER <= MC_1_12_2
|
||||
super.initGui();
|
||||
#else
|
||||
super.init();
|
||||
#endif
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
this.screen.width = Display.getWidth();
|
||||
this.screen.height = Display.getHeight();
|
||||
#else
|
||||
Window mcWindow = this.minecraft.getWindow();
|
||||
this.screen.width = mcWindow.getWidth();
|
||||
this.screen.height = mcWindow.getHeight();
|
||||
#endif
|
||||
this.screen.scaledWidth = this.width;
|
||||
this.screen.scaledHeight = this.height;
|
||||
this.screen.init(); // Init our own config screen
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
this.configListWidget = new ConfigListWidget(this.mc, this.width, this.height, 0, 0, 25); // Select the area to tint
|
||||
#else
|
||||
this.configListWidget = new ConfigListWidget(this.minecraft, this.width, this.height, 0, 0, 25); // Select the area to tint
|
||||
#endif
|
||||
|
||||
#if MC_VER < MC_1_20_6 // no background is rendered in MC 1.20.6+
|
||||
#if MC_VER <= MC_1_12_2
|
||||
#elif MC_VER < MC_1_20_6 // no background is rendered in MC 1.20.6+
|
||||
if (this.minecraft != null && this.minecraft.level != null) // Check if in game
|
||||
{
|
||||
this.configListWidget.setRenderBackground(false); // Disable from rendering
|
||||
}
|
||||
#endif
|
||||
|
||||
#if MC_VER > MC_1_12_2
|
||||
this.addWidget(this.configListWidget); // Add the tint to the things to be rendered
|
||||
#endif
|
||||
}
|
||||
|
||||
@Override
|
||||
#if MC_VER < MC_1_20_1
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public void drawScreen(int mouseX, int mouseY, float delta)
|
||||
#elif MC_VER < MC_1_20_1
|
||||
public void render(PoseStack matrices, int mouseX, int mouseY, float delta)
|
||||
#elif MC_VER <= MC_1_21_11
|
||||
public void render(GuiGraphics matrices, int mouseX, int mouseY, float delta)
|
||||
@@ -88,7 +137,9 @@ public class MinecraftScreen
|
||||
public void extractRenderState(GuiGraphicsExtractor matrices, int mouseX, int mouseY, float delta)
|
||||
#endif
|
||||
{
|
||||
#if MC_VER < MC_1_20_2
|
||||
#if MC_VER <= MC_1_12_2
|
||||
this.drawDefaultBackground();
|
||||
#elif MC_VER < MC_1_20_2
|
||||
this.renderBackground(matrices); // Render background
|
||||
#elif MC_VER < MC_1_21_6
|
||||
this.renderBackground(matrices, mouseX, mouseY, delta); // Render background
|
||||
@@ -96,7 +147,9 @@ public class MinecraftScreen
|
||||
// background blur is already being rendered, rendering again causes the game to crash
|
||||
#endif
|
||||
|
||||
#if MC_VER <= MC_1_21_11
|
||||
#if MC_VER <= MC_1_12_2
|
||||
this.configListWidget.drawScreen(mouseX, mouseY, delta);
|
||||
#elif MC_VER <= MC_1_21_11
|
||||
this.configListWidget.render(matrices, mouseX, mouseY, delta); // Renders the items in the render list (currently only used to tint background darker)
|
||||
#else
|
||||
this.configListWidget.extractRenderState(matrices, mouseX, mouseY, delta); // Renders the items in the render list (currently only used to tint background darker)
|
||||
@@ -106,55 +159,86 @@ public class MinecraftScreen
|
||||
this.screen.mouseY = mouseY;
|
||||
this.screen.render(delta); // Render everything on the main screen
|
||||
|
||||
#if MC_VER <= MC_1_21_11
|
||||
#if MC_VER <= MC_1_12_2
|
||||
super.drawScreen(mouseX, mouseY, delta); // Render the vanilla stuff (currently only used for the background and tint)
|
||||
#elif MC_VER <= MC_1_21_11
|
||||
super.render(matrices, mouseX, mouseY, delta); // Render the vanilla stuff (currently only used for the background and tint)
|
||||
#else
|
||||
super.extractRenderState(matrices, mouseX, mouseY, delta); // Renders the items in the render list (currently only used to tint background darker)
|
||||
#endif
|
||||
}
|
||||
|
||||
#if MC_VER <= MC_1_21_10
|
||||
@Override
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public void setWorldAndResolution(Minecraft mc, int width, int height)
|
||||
#elif MC_VER <= MC_1_21_10
|
||||
public void resize(Minecraft mc, int width, int height)
|
||||
#else
|
||||
@Override
|
||||
public void resize(int width, int height)
|
||||
#endif
|
||||
{
|
||||
// Resize Minecraft's screen
|
||||
#if MC_VER <= MC_1_21_10
|
||||
#if MC_VER <= MC_1_12_2
|
||||
super.setWorldAndResolution(mc, width, height);
|
||||
#elif MC_VER <= MC_1_21_10
|
||||
super.resize(mc, width, height);
|
||||
#else
|
||||
super.resize(width, height);
|
||||
#endif
|
||||
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
this.screen.width = Display.getWidth();
|
||||
this.screen.height = Display.getHeight();
|
||||
#else
|
||||
Window mcWindow = this.minecraft.getWindow();
|
||||
this.screen.width = mcWindow.getWidth();
|
||||
this.screen.height = mcWindow.getHeight();
|
||||
#endif;
|
||||
this.screen.scaledWidth = this.width;
|
||||
this.screen.scaledHeight = this.height;
|
||||
this.screen.onResize(); // Resize our screen
|
||||
}
|
||||
|
||||
@Override
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public void updateScreen()
|
||||
#else
|
||||
public void tick()
|
||||
#endif
|
||||
{
|
||||
#if MC_VER <= MC_1_12_2
|
||||
super.updateScreen(); // Tick Minecraft's screen
|
||||
#else
|
||||
super.tick(); // Tick Minecraft's screen
|
||||
#endif
|
||||
|
||||
this.screen.tick(); // Tick our screen
|
||||
if (this.screen.close) // If we decide to close the screen, then actually close the screen
|
||||
{
|
||||
#if MC_VER <= MC_1_12_2
|
||||
this.onGuiClosed();
|
||||
#else
|
||||
this.onClose();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public void onGuiClosed()
|
||||
#else
|
||||
public void onClose()
|
||||
#endif
|
||||
{
|
||||
this.screen.onClose(); // Close our screen
|
||||
#if MC_VER <= MC_1_12_2
|
||||
Objects.requireNonNull(this.mc).displayGuiScreen(this.parent); // Goto the parent screen
|
||||
#else
|
||||
Objects.requireNonNull(this.minecraft).setScreen(this.parent); // Goto the parent screen
|
||||
#endif
|
||||
}
|
||||
|
||||
#if MC_VER > MC_1_12_2
|
||||
@Override
|
||||
public void onFilesDrop(@NotNull List<Path> files)
|
||||
{ this.screen.onFilesDrop(files); }
|
||||
@@ -163,10 +247,14 @@ public class MinecraftScreen
|
||||
@Override
|
||||
public boolean shouldCloseOnEsc()
|
||||
{ return this.screen.shouldCloseOnEsc; }
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public static class ConfigListWidget extends GuiListExtended
|
||||
#else
|
||||
public static class ConfigListWidget extends ContainerObjectSelectionList
|
||||
#endif
|
||||
{
|
||||
public ConfigListWidget(Minecraft minecraftClient, int canvasWidth, int canvasHeight, int topMargin, int botMargin, int itemSpacing)
|
||||
{
|
||||
@@ -178,6 +266,18 @@ public class MinecraftScreen
|
||||
this.centerListVertically = false;
|
||||
}
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
@Override
|
||||
protected int getSize()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@Override
|
||||
public IGuiListEntry getListEntry(int index)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
package com.seibel.distanthorizons.common.wrappers.gui;
|
||||
|
||||
import org.lwjgl.util.tinyfd.TinyFileDialogs;
|
||||
|
||||
/**
|
||||
* Should be used instead of the direct call to {@link TinyFileDialogs}
|
||||
* so we can run additional validation and/or string cleanup.
|
||||
* Otherwise, we may get error messages back. <br><br>
|
||||
*
|
||||
* source:
|
||||
* https://sourceforge.net/projects/tinyfiledialogs/
|
||||
*
|
||||
* @see TinyFileDialogs
|
||||
*/
|
||||
public class NativeDialogUtil
|
||||
{
|
||||
/**
|
||||
* @param dialogType the dialog type. One of:<br><table><tr><td>"ok"</td><td>"okcancel"</td><td>"yesno"</td><td>"yesnocancel"</td></tr></table>
|
||||
* @param iconType the icon type. One of:<br><table><tr><td>"info"</td><td>"warning"</td><td>"error"</td><td>"question"</td></tr></table>
|
||||
*/
|
||||
public static void showDialog(String title, String message, String dialogType, String iconType)
|
||||
{
|
||||
// Tinyfd doesn't support the following characters, attempting to display them will cause the message
|
||||
// to be replaced with an error message
|
||||
String unsafeCharsRegex = "['\"`]";
|
||||
|
||||
title = title.replaceAll(unsafeCharsRegex, "");
|
||||
message = message.replaceAll(unsafeCharsRegex, "");
|
||||
|
||||
#if MC_VER <= MC_1_21_11
|
||||
TinyFileDialogs.tinyfd_messageBox(title, message, dialogType, iconType, false);
|
||||
#else
|
||||
// https://mfbridge.github.io/tinyfiledialogs/reference/messageBox.html
|
||||
TinyFileDialogs.tinyfd_messageBox(title, message, dialogType, iconType, 1 /* ok/yes */);
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.seibel.distanthorizons.common.wrappers.gui;
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
|
||||
public interface OnPressed {
|
||||
void pressed(GuiButton button);
|
||||
}
|
||||
#endif
|
||||
+69
-25
@@ -19,13 +19,21 @@
|
||||
|
||||
package com.seibel.distanthorizons.common.wrappers.gui;
|
||||
|
||||
#if MC_VER > MC_1_12_2
|
||||
import net.minecraft.network.chat.Component;
|
||||
#endif
|
||||
|
||||
#if MC_VER >= MC_1_17_1
|
||||
import net.minecraft.client.gui.components.Button;
|
||||
#endif
|
||||
|
||||
#if MC_VER < MC_1_17_1
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
#elif MC_VER < MC_1_17_1
|
||||
import net.minecraft.client.gui.components.ImageButton;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
@@ -53,7 +61,9 @@ import net.minecraft.client.gui.GuiGraphicsExtractor;
|
||||
import net.minecraft.client.renderer.RenderPipelines;
|
||||
#endif
|
||||
|
||||
#if MC_VER <= MC_1_21_10
|
||||
#if MC_VER <= MC_1_12_2
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
#elif MC_VER <= MC_1_21_10
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
#else
|
||||
import net.minecraft.resources.Identifier;
|
||||
@@ -65,7 +75,10 @@ import net.minecraft.resources.Identifier;
|
||||
* @author coolGi
|
||||
* @version 2023-10-03
|
||||
*/
|
||||
#if MC_VER < MC_1_20_2
|
||||
#if MC_VER <= MC_1_12_2
|
||||
@SuppressWarnings("deprecation") // we use a few deprecated Mojang functions (as expected when running on old MC versions)
|
||||
public class TexturedButtonWidget extends GuiButton
|
||||
#elif MC_VER < MC_1_20_2
|
||||
@SuppressWarnings("deprecation") // we use a few deprecated Mojang functions (as expected when running on old MC versions)
|
||||
public class TexturedButtonWidget extends ImageButton
|
||||
#else
|
||||
@@ -75,7 +88,7 @@ public class TexturedButtonWidget extends Button
|
||||
{
|
||||
public final boolean renderBackground;
|
||||
|
||||
#if MC_VER >= MC_1_20_2
|
||||
#if MC_VER >= MC_1_20_2 || MC_VER <= MC_1_12_2
|
||||
private final int u;
|
||||
private final int v;
|
||||
private final int hoveredVOffset;
|
||||
@@ -90,30 +103,41 @@ public class TexturedButtonWidget extends Button
|
||||
private final int textureHeight;
|
||||
#endif
|
||||
|
||||
|
||||
public TexturedButtonWidget(
|
||||
int x, int y, int width, int height, int u, int v, int hoveredVOffset,
|
||||
#if MC_VER <= MC_1_21_10 ResourceLocation textureResourceLocation,
|
||||
#else Identifier textureResourceLocation,
|
||||
#endif
|
||||
int textureWidth, int textureHeight, OnPress pressAction, Component text)
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public TexturedButtonWidget(int id, int x, int y, int width, int height, int u, int v, int hoveredVOffset, ResourceLocation textureResourceLocation, int textureWidth, int textureHeight, String text)
|
||||
{
|
||||
this(id, x, y, width, height, u, v, hoveredVOffset, textureResourceLocation, textureWidth, textureHeight, text, true);
|
||||
}
|
||||
#elif MC_VER <= MC_1_21_10
|
||||
public TexturedButtonWidget(int x, int y, int width, int height, int u, int v, int hoveredVOffset, ResourceLocation textureResourceLocation, int textureWidth, int textureHeight, OnPress pressAction, Component text)
|
||||
{
|
||||
this(x, y, width, height, u, v, hoveredVOffset, textureResourceLocation, textureWidth, textureHeight, pressAction, text, true);
|
||||
}
|
||||
public TexturedButtonWidget(
|
||||
int x, int y, int width, int height, int u, int v, int hoveredVOffset,
|
||||
#if MC_VER <= MC_1_21_10 ResourceLocation textureResourceLocation,
|
||||
#else Identifier textureResourceLocation,
|
||||
#endif
|
||||
int textureWidth, int textureHeight, OnPress pressAction, Component text,
|
||||
boolean renderBackground)
|
||||
#else
|
||||
public TexturedButtonWidget(int x, int y, int width, int height, int u, int v, int hoveredVOffset, Identifier textureResourceLocation, int textureWidth, int textureHeight, OnPress pressAction, Component text)
|
||||
{
|
||||
#if MC_VER < MC_1_20_2
|
||||
this(x, y, width, height, u, v, hoveredVOffset, textureResourceLocation, textureWidth, textureHeight, pressAction, text, true);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public TexturedButtonWidget(int id, int x, int y, int width, int height, int u, int v, int hoveredVOffset, ResourceLocation textureResourceLocation, int textureWidth, int textureHeight, String text, boolean renderBackground)
|
||||
#elif MC_VER <= MC_1_21_10
|
||||
public TexturedButtonWidget(int x, int y, int width, int height, int u, int v, int hoveredVOffset, ResourceLocation textureResourceLocation, int textureWidth, int textureHeight, OnPress pressAction, Component text, boolean renderBackground)
|
||||
#else
|
||||
public TexturedButtonWidget(int x, int y, int width, int height, int u, int v, int hoveredVOffset, Identifier textureResourceLocation, int textureWidth, int textureHeight, OnPress pressAction, Component text, boolean renderBackground)
|
||||
#endif
|
||||
{
|
||||
#if MC_VER <= MC_1_12_2
|
||||
super(id, x, y, width, height, text);
|
||||
#elif MC_VER < MC_1_20_2
|
||||
super(x, y, width, height, u, v, hoveredVOffset, textureResourceLocation, textureWidth, textureHeight, pressAction, text);
|
||||
#else
|
||||
// We don't pass in the text option since it will render (we normally pass it in for narration)
|
||||
super(x, y, width, height, Component.empty(), pressAction, DEFAULT_NARRATION);
|
||||
#endif
|
||||
|
||||
#if MC_VER >= MC_1_20_2 || MC_VER <= MC_1_12_2
|
||||
this.u = u;
|
||||
this.v = v;
|
||||
this.hoveredVOffset = hoveredVOffset;
|
||||
@@ -127,7 +151,27 @@ public class TexturedButtonWidget extends Button
|
||||
this.renderBackground = renderBackground;
|
||||
}
|
||||
|
||||
#if MC_VER < MC_1_20_2
|
||||
#if MC_VER <= MC_1_12_2
|
||||
@Override
|
||||
public void drawButton(Minecraft mc, int mouseX, int mouseY, float partialTicks) {
|
||||
if (this.visible) {
|
||||
//Render vanilla background
|
||||
mc.getTextureManager().bindTexture(BUTTON_TEXTURES);
|
||||
GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
|
||||
this.hovered = mouseX >= this.x && mouseY >= this.y && mouseX < this.x + this.width && mouseY < this.y + this.height;
|
||||
int i = this.getHoverState(this.hovered);
|
||||
GlStateManager.enableBlend();
|
||||
GlStateManager.tryBlendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO);
|
||||
GlStateManager.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA);
|
||||
this.drawTexturedModalRect(this.x, this.y, 0, 46 + i * 20, this.width / 2, this.height);
|
||||
this.drawTexturedModalRect(this.x + this.width / 2, this.y, 200 - this.width / 2, 46 + i * 20, this.width / 2, this.height);
|
||||
|
||||
//Render DH texture
|
||||
mc.getTextureManager().bindTexture(textureResourceLocation);
|
||||
drawModalRectWithCustomSizedTexture(this.x, this.y, this.u, (hoveredVOffset * (i - 1)), this.width, this.height, this.textureWidth, this.textureHeight);
|
||||
}
|
||||
}
|
||||
#elif MC_VER < MC_1_20_2
|
||||
#if MC_VER < MC_1_19_4
|
||||
@Override
|
||||
public void renderButton(PoseStack matrices, int mouseX, int mouseY, float delta)
|
||||
@@ -218,11 +262,11 @@ public class TexturedButtonWidget extends Button
|
||||
this.getX(), this.getY(),
|
||||
this.getWidth(), this.getHeight());
|
||||
#else
|
||||
//matrices.blitSprite(
|
||||
// RenderPipelines.GUI_TEXTURED,
|
||||
// SPRITES.get(this.active, this.isHoveredOrFocused()),
|
||||
// this.getX(), this.getY(),
|
||||
// this.getWidth(), this.getHeight());
|
||||
matrices.blitSprite(
|
||||
RenderPipelines.GUI_TEXTURED,
|
||||
SPRITES.get(this.active, this.isHoveredOrFocused()),
|
||||
this.getX(), this.getY(),
|
||||
this.getWidth(), this.getHeight());
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
+581
@@ -0,0 +1,581 @@
|
||||
package com.seibel.distanthorizons.common.wrappers.gui.classicConfig;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import com.seibel.distanthorizons.core.config.types.*;
|
||||
|
||||
import com.seibel.distanthorizons.core.config.types.enums.EConfigCommentTextPosition;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.config.IConfigGui;
|
||||
import net.minecraft.client.Minecraft;
|
||||
#if MC_VER <= MC_1_12_2
|
||||
import net.minecraft.client.gui.*;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
#else
|
||||
import net.minecraft.client.gui.Font;
|
||||
import net.minecraft.client.gui.components.AbstractWidget;
|
||||
import net.minecraft.client.gui.components.ContainerObjectSelectionList;
|
||||
import net.minecraft.client.gui.components.events.GuiEventListener;
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
import net.minecraft.network.chat.Component;
|
||||
#endif
|
||||
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
#elif MC_VER < MC_1_20_1
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.minecraft.client.gui.GuiComponent;
|
||||
#elif MC_VER <= MC_1_21_11
|
||||
import net.minecraft.client.gui.GuiGraphics;
|
||||
#else
|
||||
import net.minecraft.client.gui.GuiGraphicsExtractor;
|
||||
#endif
|
||||
|
||||
#if MC_VER >= MC_1_17_1
|
||||
import net.minecraft.client.gui.narration.NarratableEntry;
|
||||
#endif
|
||||
|
||||
#if MC_VER <= MC_1_21_10
|
||||
#else
|
||||
import net.minecraft.resources.Identifier;
|
||||
#endif
|
||||
|
||||
import static com.seibel.distanthorizons.common.wrappers.gui.GuiHelper.*;
|
||||
|
||||
|
||||
/*
|
||||
* Based upon TinyConfig but is highly modified
|
||||
* https://github.com/Minenash/TinyConfig
|
||||
*
|
||||
* @author coolGi
|
||||
* @author Motschen
|
||||
* @author James Seibel
|
||||
* @version 5-21-2022
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class ClassicConfigGUI
|
||||
{
|
||||
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||
public static final DhLogger RATE_LIMITED_LOGGER = new DhLoggerBuilder()
|
||||
.maxCountPerSecond(1)
|
||||
.build();
|
||||
|
||||
public static final ConfigCoreInterface CONFIG_CORE_INTERFACE = new ConfigCoreInterface();
|
||||
|
||||
|
||||
|
||||
//==============//
|
||||
// Initializers //
|
||||
//==============//
|
||||
//region
|
||||
|
||||
// Some regexes to check if an input is valid
|
||||
public static final Pattern INTEGER_ONLY_REGEX = Pattern.compile("(-?[0-9]*)");
|
||||
public static final Pattern DECIMAL_ONLY_REGEX = Pattern.compile("-?([\\d]+\\.?[\\d]*|[\\d]*\\.?[\\d]+|\\.)");
|
||||
|
||||
public static class ConfigScreenConfigs
|
||||
{
|
||||
// This contains all the configs for the configs
|
||||
public static final int SPACE_FROM_RIGHT_SCREEN = 10;
|
||||
public static final int SPACE_BETWEEN_TEXT_AND_OPTION_FIELD = 8;
|
||||
public static final int BUTTON_WIDTH_SPACING = 5;
|
||||
public static final int RESET_BUTTON_WIDTH = 60;
|
||||
public static final int RESET_BUTTON_HEIGHT = 20;
|
||||
public static final int OPTION_FIELD_WIDTH = 150;
|
||||
public static final int OPTION_FIELD_HEIGHT = 20;
|
||||
public static final int CATEGORY_BUTTON_WIDTH = 200;
|
||||
public static final int CATEGORY_BUTTON_HEIGHT = 20;
|
||||
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//==============//
|
||||
// GUI handling //
|
||||
//==============//
|
||||
//region
|
||||
/** if you want to get this config gui's screen call this */
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public static GuiScreen getScreen(GuiScreen parent, String category)
|
||||
#else
|
||||
public static Screen getScreen(Screen parent, String category)
|
||||
#endif
|
||||
{ return new DhConfigScreen(parent, category); }
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//================//
|
||||
// helper classes //
|
||||
//================//
|
||||
//region
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public static class ConfigListWidget extends GuiListExtended
|
||||
#else
|
||||
public static class ConfigListWidget extends ContainerObjectSelectionList<DhButtonEntry>
|
||||
#endif
|
||||
{
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public List<DhButtonEntry> children = new ArrayList<>();
|
||||
#endif
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
FontRenderer textRenderer;
|
||||
#else
|
||||
Font textRenderer;
|
||||
#endif
|
||||
|
||||
public ConfigListWidget(Minecraft minecraftClient, int canvasWidth, int canvasHeight, int topMargin, int botMargin, int itemSpacing)
|
||||
{
|
||||
#if MC_VER < MC_1_20_4
|
||||
super(minecraftClient, canvasWidth, canvasHeight, topMargin, canvasHeight - botMargin, itemSpacing);
|
||||
#else
|
||||
super(minecraftClient, canvasWidth, canvasHeight - (topMargin + botMargin), topMargin, itemSpacing);
|
||||
#endif
|
||||
|
||||
this.centerListVertically = false;
|
||||
#if MC_VER <= MC_1_12_2
|
||||
this.textRenderer = minecraftClient.fontRenderer;
|
||||
#else
|
||||
this.textRenderer = minecraftClient.font;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
@Override
|
||||
protected int getSize()
|
||||
{
|
||||
return this.children.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IGuiListEntry getListEntry(int index)
|
||||
{
|
||||
return this.children.get(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawContainerBackground(Tessellator tessellator)
|
||||
{
|
||||
if (this.mc.world != null)
|
||||
{
|
||||
return; // in-game don't draw dirt background
|
||||
}
|
||||
super.drawContainerBackground(tessellator);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public void addButton(DhConfigScreen gui, AbstractConfigBase dhConfigType, Gui button, GuiButton resetButton, GuiButton indexButton, ITextComponent text)
|
||||
#else
|
||||
public void addButton(DhConfigScreen gui, AbstractConfigBase dhConfigType, AbstractWidget button, AbstractWidget resetButton, AbstractWidget indexButton, Component text)
|
||||
#endif
|
||||
{
|
||||
#if MC_VER <= MC_1_12_2
|
||||
this.children.add(new DhButtonEntry(gui, dhConfigType, button, text, resetButton, indexButton));
|
||||
#else
|
||||
this.addEntry(new DhButtonEntry(gui, dhConfigType, button, text, resetButton, indexButton));
|
||||
#endif
|
||||
}
|
||||
|
||||
@Override
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public int getListWidth()
|
||||
#else
|
||||
public int getRowWidth()
|
||||
#endif
|
||||
{ return 10_000; }
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public Gui getHoveredButton(double mouseX, double mouseY)
|
||||
#else
|
||||
public AbstractWidget getHoveredButton(double mouseX, double mouseY)
|
||||
#endif
|
||||
{
|
||||
#if MC_VER <= MC_1_12_2
|
||||
for (DhButtonEntry buttonEntry : this.children)
|
||||
#else
|
||||
for (DhButtonEntry buttonEntry : this.children())
|
||||
#endif
|
||||
{
|
||||
#if MC_VER <= MC_1_12_2
|
||||
Gui gui = buttonEntry.button;
|
||||
if (gui == null) continue;
|
||||
|
||||
double minX, minY, maxX, maxY;
|
||||
|
||||
if (gui instanceof GuiButton button)
|
||||
{
|
||||
if (!button.visible) continue;
|
||||
minX = button.x;
|
||||
minY = button.y;
|
||||
maxX = minX + button.width;
|
||||
maxY = minY + button.height;
|
||||
}
|
||||
else if (gui instanceof GuiTextField field)
|
||||
{
|
||||
if (!field.getVisible()) continue;
|
||||
minX = field.x;
|
||||
minY = field.y;
|
||||
maxX = minX + field.width;
|
||||
maxY = minY + field.height;
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mouseX >= minX && mouseX < maxX && mouseY >= minY && mouseY < maxY)
|
||||
{
|
||||
return gui;
|
||||
}
|
||||
#else
|
||||
AbstractWidget button = (AbstractWidget) buttonEntry.button;
|
||||
if (button == null || !button.visible) continue;
|
||||
|
||||
#if MC_VER < MC_1_19_4
|
||||
double minX = button.x;
|
||||
double minY = button.y;
|
||||
#else
|
||||
double minX = button.getX();
|
||||
double minY = button.getY();
|
||||
#endif
|
||||
|
||||
double maxX = minX + button.getWidth();
|
||||
double maxY = minY + button.getHeight();
|
||||
|
||||
if (mouseX >= minX && mouseX < maxX && mouseY >= minY && mouseY < maxY)
|
||||
{
|
||||
return button;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public static class DhButtonEntry implements GuiListExtended.IGuiListEntry
|
||||
#else
|
||||
public static class DhButtonEntry extends ContainerObjectSelectionList.Entry<DhButtonEntry>
|
||||
#endif
|
||||
{
|
||||
#if MC_VER <= MC_1_12_2
|
||||
private static final FontRenderer textRenderer = Minecraft.getMinecraft().fontRenderer;
|
||||
#else
|
||||
private static final Font textRenderer = Minecraft.getInstance().font;
|
||||
#endif
|
||||
|
||||
private final DhConfigScreen gui;
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public final Gui button;
|
||||
public final Gui resetButton;
|
||||
public final Gui indexButton;
|
||||
#else
|
||||
private final AbstractWidget indexButton;
|
||||
private final AbstractWidget resetButton;
|
||||
private final AbstractWidget button;
|
||||
#endif
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
private final ITextComponent text;
|
||||
#else
|
||||
private final Component text;
|
||||
#endif
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
private final List<Gui> children = new ArrayList<>();
|
||||
#else
|
||||
private final List<AbstractWidget> children = new ArrayList<>();
|
||||
#endif
|
||||
|
||||
@NotNull
|
||||
private final EConfigCommentTextPosition textPosition;
|
||||
public final AbstractConfigBase dhConfigType;
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public static final Map<Gui, ITextComponent> TEXT_BY_WIDGET = new HashMap<>();
|
||||
public static final Map<Gui, DhButtonEntry> BUTTON_BY_WIDGET = new HashMap<>();
|
||||
#else
|
||||
public static final Map<AbstractWidget, Component> TEXT_BY_WIDGET = new HashMap<>();
|
||||
public static final Map<AbstractWidget, DhButtonEntry> BUTTON_BY_WIDGET = new HashMap<>();
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public DhButtonEntry(DhConfigScreen gui, AbstractConfigBase dhConfigType, Gui button, ITextComponent text, GuiButton resetButton, GuiButton indexButton)
|
||||
#else
|
||||
public DhButtonEntry(DhConfigScreen gui, AbstractConfigBase dhConfigType, AbstractWidget button, Component text, AbstractWidget resetButton, AbstractWidget indexButton)
|
||||
#endif
|
||||
{
|
||||
TEXT_BY_WIDGET.put(button, text);
|
||||
BUTTON_BY_WIDGET.put(button, this);
|
||||
|
||||
this.gui = gui;
|
||||
this.dhConfigType = dhConfigType;
|
||||
|
||||
this.button = button;
|
||||
this.resetButton = resetButton;
|
||||
this.text = text;
|
||||
this.indexButton = indexButton;
|
||||
|
||||
if (button != null) { this.children.add(button); }
|
||||
if (resetButton != null) { this.children.add(resetButton); }
|
||||
if (indexButton != null) { this.children.add(indexButton); }
|
||||
|
||||
|
||||
EConfigCommentTextPosition textPosition = null;
|
||||
if (this.dhConfigType instanceof ConfigUIComment)
|
||||
{
|
||||
textPosition = ((ConfigUIComment)this.dhConfigType).textPosition;
|
||||
}
|
||||
|
||||
if (textPosition == null)
|
||||
{
|
||||
if (this.button != null)
|
||||
{
|
||||
// if a button is present
|
||||
textPosition = EConfigCommentTextPosition.RIGHT_JUSTIFIED;
|
||||
}
|
||||
else
|
||||
{
|
||||
textPosition = EConfigCommentTextPosition.CENTERED_OVER_BUTTONS;
|
||||
}
|
||||
}
|
||||
this.textPosition = textPosition;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public void drawEntry(int slotIndex, int x, int y, int listWidth, int slotHeight, int mouseX, int mouseY, boolean isSelected, float tickDelta)
|
||||
#elif MC_VER < MC_1_20_1
|
||||
public void render(PoseStack matrices, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta)
|
||||
#elif MC_VER < MC_1_21_9
|
||||
public void render(GuiGraphics matrices, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta)
|
||||
#elif MC_VER <= MC_1_21_11
|
||||
public void renderContent(GuiGraphics matrices, int mouseX, int mouseY, boolean hovered, float tickDelta)
|
||||
#else
|
||||
public void extractContent(GuiGraphicsExtractor matrices, int mouseX, int mouseY, boolean hovered, float tickDelta)
|
||||
#endif
|
||||
{
|
||||
try
|
||||
{
|
||||
// setting the "y" variable is necessary so each child item
|
||||
// renders at the correct height,
|
||||
// if not set they will render off-screen.
|
||||
#if MC_VER < MC_1_21_9
|
||||
// Y value passed in from method args
|
||||
#else
|
||||
int y = this.getY();
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
if (this.button != null)
|
||||
{
|
||||
#if MC_VER <= MC_1_12_2
|
||||
if (this.button instanceof GuiButton guiButton)
|
||||
{
|
||||
SetY(guiButton, y);
|
||||
guiButton.drawButton(Minecraft.getMinecraft(), mouseX, mouseY, tickDelta);
|
||||
}
|
||||
if (this.button instanceof GuiTextField guiTextField)
|
||||
{
|
||||
SetY(guiTextField, y);
|
||||
guiTextField.drawTextBox();
|
||||
}
|
||||
#else
|
||||
SetY(this.button, y);
|
||||
{
|
||||
#if MC_VER <= MC_1_21_11
|
||||
this.button.render(matrices, mouseX, mouseY, tickDelta);
|
||||
#else
|
||||
this.button.extractRenderState(matrices, mouseX, mouseY, tickDelta);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (this.resetButton != null)
|
||||
{
|
||||
#if MC_VER <= MC_1_12_2
|
||||
SetY((GuiButton) this.resetButton, y);
|
||||
#else
|
||||
SetY(this.resetButton, y);
|
||||
#endif
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
((GuiButton) this.resetButton).drawButton(Minecraft.getMinecraft(), mouseX, mouseY, tickDelta);
|
||||
#elif MC_VER <= MC_1_21_11
|
||||
this.resetButton.render(matrices, mouseX, mouseY, tickDelta);
|
||||
#else
|
||||
this.resetButton.extractRenderState(matrices, mouseX, mouseY, tickDelta);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (this.indexButton != null)
|
||||
{
|
||||
#if MC_VER <= MC_1_12_2
|
||||
SetY((GuiButton) this.indexButton, y);
|
||||
#else
|
||||
SetY(this.indexButton, y);
|
||||
#endif
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
((GuiButton) this.indexButton).drawButton(Minecraft.getMinecraft(), mouseX, mouseY, tickDelta);
|
||||
#elif MC_VER <= MC_1_21_11
|
||||
this.indexButton.render(matrices, mouseX, mouseY, tickDelta);
|
||||
#else
|
||||
this.indexButton.extractRenderState(matrices, mouseX, mouseY, tickDelta);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (this.text != null)
|
||||
{
|
||||
#if MC_VER <= MC_1_12_2
|
||||
int translatedLength = textRenderer.getStringWidth(this.text.getFormattedText());
|
||||
#else
|
||||
int translatedLength = textRenderer.width(this.text);
|
||||
#endif
|
||||
|
||||
int textXPos;
|
||||
if (this.textPosition == EConfigCommentTextPosition.RIGHT_JUSTIFIED)
|
||||
{
|
||||
// text right justified aligned against the buttons
|
||||
textXPos = this.gui.width
|
||||
- translatedLength
|
||||
- ConfigScreenConfigs.SPACE_BETWEEN_TEXT_AND_OPTION_FIELD
|
||||
- ConfigScreenConfigs.SPACE_FROM_RIGHT_SCREEN
|
||||
- ConfigScreenConfigs.OPTION_FIELD_WIDTH
|
||||
- ConfigScreenConfigs.BUTTON_WIDTH_SPACING
|
||||
- ConfigScreenConfigs.RESET_BUTTON_WIDTH;
|
||||
}
|
||||
else if (this.textPosition == EConfigCommentTextPosition.CENTERED_OVER_BUTTONS)
|
||||
{
|
||||
// have button centered relative to a category button
|
||||
textXPos = this.gui.width
|
||||
- (translatedLength / 2)
|
||||
- (ConfigScreenConfigs.CATEGORY_BUTTON_WIDTH / 2)
|
||||
- ConfigScreenConfigs.SPACE_FROM_RIGHT_SCREEN;
|
||||
}
|
||||
else if (this.textPosition == EConfigCommentTextPosition.CENTER_OF_SCREEN)
|
||||
{
|
||||
// have button centered in the screen
|
||||
textXPos = (this.gui.width / 2)
|
||||
- (translatedLength / 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new UnsupportedOperationException("No text position render defined for [" + this.textPosition + "]");
|
||||
}
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
textRenderer.drawString(
|
||||
this.text.getFormattedText(),
|
||||
textXPos, y + 5,
|
||||
0xFFFFFF);
|
||||
#elif MC_VER < MC_1_20_1
|
||||
GuiComponent.drawString(matrices, textRenderer,
|
||||
this.text,
|
||||
textXPos, y + 5,
|
||||
0xFFFFFF);
|
||||
#elif MC_VER < MC_1_21_6
|
||||
matrices.drawString(textRenderer,
|
||||
this.text,
|
||||
textXPos, y + 5,
|
||||
0xFFFFFF);
|
||||
#elif MC_VER <= MC_1_21_11
|
||||
matrices.drawString(textRenderer,
|
||||
this.text,
|
||||
textXPos, y + 5,
|
||||
0xFFFFFFFF);
|
||||
#else
|
||||
matrices.text(textRenderer,
|
||||
this.text,
|
||||
textXPos, y + 5,
|
||||
0xFFFFFFFF);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// should prevent crashing the game if there's an issue
|
||||
RATE_LIMITED_LOGGER.error("Unexpected gui rendering issue: ["+e.getMessage()+"]", e);
|
||||
}
|
||||
}
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
@Override
|
||||
public void updatePosition(int slotIndex, int x, int y, float partialTicks) { }
|
||||
|
||||
@Override
|
||||
public boolean mousePressed(int slotIndex, int mouseX, int mouseY, int mouseEvent, int relativeX, int relativeY)
|
||||
{
|
||||
return false; // handled in DhConfigScreen.mouseClicked
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseReleased(int slotIndex, int x, int y, int mouseEvent, int relativeX, int relativeY) { }
|
||||
#endif
|
||||
|
||||
#if MC_VER > MC_1_12_2
|
||||
@Override
|
||||
public @NotNull List<? extends GuiEventListener> children()
|
||||
{ return this.children; }
|
||||
#endif
|
||||
|
||||
#if MC_VER >= MC_1_17_1
|
||||
@Override
|
||||
public @NotNull List<? extends NarratableEntry> narratables()
|
||||
{ return this.children; }
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//================//
|
||||
// event handling //
|
||||
//================//
|
||||
//region
|
||||
|
||||
public static class ConfigCoreInterface implements IConfigGui
|
||||
{
|
||||
/**
|
||||
* in the future it would be good to pass in the current page and other variables,
|
||||
* but for now just knowing when the page is closed is good enough
|
||||
*/
|
||||
public final ArrayList<Runnable> onScreenChangeListenerList = new ArrayList<>();
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void addOnScreenChangeListener(Runnable newListener) { this.onScreenChangeListenerList.add(newListener); }
|
||||
@Override
|
||||
public void removeOnScreenChangeListener(Runnable oldListener) { this.onScreenChangeListenerList.remove(oldListener); }
|
||||
|
||||
}
|
||||
|
||||
//endregion
|
||||
}
|
||||
+1119
File diff suppressed because it is too large
Load Diff
+22
-1
@@ -2,9 +2,16 @@ package com.seibel.distanthorizons.common.wrappers.gui.config;
|
||||
|
||||
import com.seibel.distanthorizons.core.config.gui.IConfigGuiInfo;
|
||||
import com.seibel.distanthorizons.core.config.types.AbstractConfigBase;
|
||||
#if MC_VER <= MC_1_12_2
|
||||
import com.seibel.distanthorizons.common.wrappers.gui.OnPressed;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.GuiTextField;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
#else
|
||||
import net.minecraft.client.gui.components.Button;
|
||||
import net.minecraft.client.gui.components.EditBox;
|
||||
import net.minecraft.network.chat.Component;
|
||||
#endif
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.AbstractMap;
|
||||
@@ -23,11 +30,25 @@ public class ConfigGuiInfo implements IConfigGuiInfo
|
||||
* Used to display validation errors.
|
||||
* Null if no error is present.
|
||||
*/
|
||||
|
||||
@Nullable
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public ITextComponent errorMessage;
|
||||
#else
|
||||
public Component errorMessage;
|
||||
#endif
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public BiFunction<GuiTextField, GuiButton, Predicate<String>> tooltipFunction;
|
||||
#else
|
||||
public BiFunction<EditBox, Button , Predicate<String>> tooltipFunction;
|
||||
#endif
|
||||
|
||||
public BiFunction<EditBox, Button, Predicate<String>> tooltipFunction;
|
||||
/** determines which options the button will show */
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public AbstractMap.SimpleEntry<OnPressed, Function<Object, ITextComponent>> buttonOptionMap;
|
||||
#else
|
||||
public AbstractMap.SimpleEntry<Button.OnPress, Function<Object, Component>> buttonOptionMap;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
+3
-2
@@ -1,5 +1,5 @@
|
||||
package com.seibel.distanthorizons.common.wrappers.gui.updater;
|
||||
|
||||
#if MC_VER > MC_1_12_2
|
||||
import com.seibel.distanthorizons.common.wrappers.gui.DhScreen;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
@@ -296,4 +296,5 @@ public class ChangelogScreen extends DhScreen
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
+3
-2
@@ -1,5 +1,5 @@
|
||||
package com.seibel.distanthorizons.common.wrappers.gui.updater;
|
||||
|
||||
#if MC_VER > MC_1_12_2
|
||||
import com.seibel.distanthorizons.api.enums.config.EDhApiUpdateBranch;
|
||||
import com.seibel.distanthorizons.common.wrappers.gui.DhScreen;
|
||||
import com.seibel.distanthorizons.common.wrappers.gui.TexturedButtonWidget;
|
||||
@@ -221,4 +221,5 @@ public class UpdateModScreen extends DhScreen
|
||||
Objects.requireNonNull(this.minecraft).setScreen(this.parent); // Go to the parent screen
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
+131
-11
@@ -1,20 +1,43 @@
|
||||
package com.seibel.distanthorizons.common.wrappers.level;
|
||||
|
||||
import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper;
|
||||
import com.seibel.distanthorizons.core.level.IServerKeyedClientLevel;
|
||||
import com.seibel.distanthorizons.core.level.IKeyedClientLevelManager;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||
#if MC_VER <= MC_1_12_2
|
||||
import net.minecraft.client.multiplayer.WorldClient;
|
||||
#else
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
#endif
|
||||
import net.minecraft.client.Minecraft;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class KeyedClientLevelManager implements IKeyedClientLevelManager
|
||||
{
|
||||
public static final KeyedClientLevelManager INSTANCE = new KeyedClientLevelManager();
|
||||
|
||||
/** This is set and managed by the ClientApi for servers with support for DH. */
|
||||
@Nullable
|
||||
private IServerKeyedClientLevel serverKeyedLevel = null;
|
||||
private static class KeyInfo {
|
||||
public final String serverKey;
|
||||
public final String levelKey;
|
||||
public KeyInfo(String serverKey, String levelKey) {
|
||||
this.serverKey = serverKey;
|
||||
this.levelKey = levelKey;
|
||||
}
|
||||
}
|
||||
|
||||
/** Stores the server-provided keys indexed by dimension name for persistence. */
|
||||
private final Map<String, KeyInfo> keysByDimensionName = new ConcurrentHashMap<>();
|
||||
|
||||
/** Cache for already keyed level wrappers to maintain object identity. */
|
||||
private final Map<#if MC_VER > MC_1_12_2 ClientLevel #else WorldClient #endif, IServerKeyedClientLevel> keyedLevelsCache = Collections.synchronizedMap(new WeakHashMap<>());
|
||||
|
||||
/** Allows to keep level manager enabled between loading different keyed levels */
|
||||
private boolean enabled = false;
|
||||
private volatile boolean enabled = false;
|
||||
|
||||
|
||||
|
||||
@@ -22,34 +45,131 @@ public class KeyedClientLevelManager implements IKeyedClientLevelManager
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
//region
|
||||
|
||||
private KeyedClientLevelManager() { }
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//======================//
|
||||
// level override logic //
|
||||
//======================//
|
||||
//region
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public IServerKeyedClientLevel getServerKeyedLevel() { return this.serverKeyedLevel; }
|
||||
public IServerKeyedClientLevel getServerKeyedLevel()
|
||||
{
|
||||
#if MC_VER > MC_1_12_2
|
||||
return this.getServerKeyedLevel(Minecraft.getInstance().level);
|
||||
#else
|
||||
return this.getServerKeyedLevel(Minecraft.getMinecraft().world);
|
||||
#endif
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public IServerKeyedClientLevel getServerKeyedLevel(@Nullable #if MC_VER > MC_1_12_2 ClientLevel #else WorldClient #endif level)
|
||||
{
|
||||
if (level == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// We synchronize on the cache map to ensure atomicity of the lookup-and-populate sequence.
|
||||
// This prevents multiple threads from creating duplicate wrappers for the same level.
|
||||
synchronized (this.keyedLevelsCache)
|
||||
{
|
||||
// Check the cache first
|
||||
IServerKeyedClientLevel cached = this.keyedLevelsCache.get(level);
|
||||
if (cached != null)
|
||||
{
|
||||
return cached;
|
||||
}
|
||||
|
||||
// Determine the dimension name for this level
|
||||
// We use bypassLevelKeyManager=true to avoid recursion back into this manager
|
||||
IClientLevelWrapper wrappedLevel = ClientLevelWrapper.getWrapper(level, true);
|
||||
if (wrappedLevel == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
String dimensionName = wrappedLevel.getDimensionName();
|
||||
KeyInfo info = this.keysByDimensionName.get(dimensionName);
|
||||
if (info == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// Create and cache a new keyed wrapper
|
||||
IServerKeyedClientLevel keyedLevel = new ServerKeyedClientLevelWrapper(level, info.serverKey, info.levelKey);
|
||||
this.keyedLevelsCache.put(level, keyedLevel);
|
||||
return keyedLevel;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IServerKeyedClientLevel setServerKeyedLevel(IClientLevelWrapper clientLevel, String serverKey, String levelKey)
|
||||
{
|
||||
IServerKeyedClientLevel keyedLevel = new ServerKeyedClientLevelWrapper((ClientLevel) clientLevel.getWrappedMcObject(), serverKey, levelKey);
|
||||
this.serverKeyedLevel = keyedLevel;
|
||||
// 1. Determine the target dimension name
|
||||
String targetDimensionName = clientLevel.getDimensionName();
|
||||
int separatorIndex = levelKey.lastIndexOf("@");
|
||||
if (separatorIndex != -1)
|
||||
{
|
||||
targetDimensionName = levelKey.substring(separatorIndex + 1);
|
||||
}
|
||||
|
||||
final String finalTargetDimensionName = targetDimensionName;
|
||||
|
||||
// 2. Store the key for this dimension
|
||||
this.keysByDimensionName.put(finalTargetDimensionName, new KeyInfo(serverKey, levelKey));
|
||||
this.enabled = true;
|
||||
return keyedLevel;
|
||||
|
||||
// 3. Clear the cache for this dimension to ensure new wrappers are created with the new key
|
||||
// (though in practice keys shouldn't change mid-session)
|
||||
//
|
||||
// We synchronize manually on the map to ensure atomicity of the compound removal operation
|
||||
// and to prevent race conditions or deadlocks with other threads accessing the map.
|
||||
// We avoid calling ClientLevelWrapper.getWrapper() inside the lock to prevent circular lock dependencies.
|
||||
synchronized (this.keyedLevelsCache)
|
||||
{
|
||||
this.keyedLevelsCache.keySet().removeIf(level -> {
|
||||
#if MC_VER <= MC_1_12_2
|
||||
String levelDim = level.provider.getDimensionType().getName() + ":" + level.provider.getDimension();
|
||||
#elif MC_VER <= MC_1_21_10
|
||||
String levelDim = level.dimension().location().toString();
|
||||
#else
|
||||
String levelDim = level.dimension().identifier().toString();
|
||||
#endif
|
||||
return levelDim.equals(finalTargetDimensionName);
|
||||
});
|
||||
}
|
||||
|
||||
// 4. Return the keyed wrapper for whatever level the core passed us,
|
||||
// but only if it matches the dimension we just keyed.
|
||||
return this.getServerKeyedLevel((#if MC_VER > MC_1_12_2 ClientLevel #else WorldClient #endif) clientLevel.getWrappedMcObject());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearKeyedLevel() { this.serverKeyedLevel = null; }
|
||||
public void clearKeyedLevel()
|
||||
{
|
||||
synchronized (this.keyedLevelsCache)
|
||||
{
|
||||
this.keyedLevelsCache.clear();
|
||||
this.keysByDimensionName.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() { return this.enabled; }
|
||||
@Override
|
||||
public void disable() { this.enabled = false; }
|
||||
|
||||
@Override
|
||||
public void disable()
|
||||
{
|
||||
this.enabled = false;
|
||||
this.clearKeyedLevel();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+17
-2
@@ -2,7 +2,11 @@ package com.seibel.distanthorizons.common.wrappers.level;
|
||||
|
||||
import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper;
|
||||
import com.seibel.distanthorizons.core.level.IServerKeyedClientLevel;
|
||||
#if MC_VER <= MC_1_12_2
|
||||
import net.minecraft.client.multiplayer.WorldClient;
|
||||
#else
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
#endif
|
||||
|
||||
public class ServerKeyedClientLevelWrapper extends ClientLevelWrapper implements IServerKeyedClientLevel
|
||||
{
|
||||
@@ -17,21 +21,30 @@ public class ServerKeyedClientLevelWrapper extends ClientLevelWrapper implements
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
//region
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public ServerKeyedClientLevelWrapper(WorldClient level, String serverKey, String serverLevelKey)
|
||||
#else
|
||||
public ServerKeyedClientLevelWrapper(ClientLevel level, String serverKey, String serverLevelKey)
|
||||
#endif
|
||||
{
|
||||
super(level);
|
||||
this.serverKey = serverKey;
|
||||
this.serverLevelKey = serverLevelKey;
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
@Override
|
||||
public String getServerKey() { return this.serverKey; }
|
||||
|
||||
//======================//
|
||||
// level identification //
|
||||
//======================//
|
||||
//region
|
||||
|
||||
@Override
|
||||
public String getServerKey() { return this.serverKey; }
|
||||
|
||||
@Override
|
||||
public String getServerLevelKey() { return this.serverLevelKey; }
|
||||
@@ -39,6 +52,8 @@ public class ServerKeyedClientLevelWrapper extends ClientLevelWrapper implements
|
||||
@Override
|
||||
public String getDhIdentifier() { return this.getServerLevelKey(); }
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
+278
-32
@@ -20,12 +20,20 @@
|
||||
package com.seibel.distanthorizons.common.wrappers.minecraft;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
|
||||
#if MC_VER > MC_1_12_2
|
||||
import com.mojang.blaze3d.platform.Window;
|
||||
#endif
|
||||
import com.seibel.distanthorizons.common.wrappers.gui.NativeDialogUtil;
|
||||
import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper;
|
||||
import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector;
|
||||
import com.seibel.distanthorizons.core.file.structure.ClientOnlySaveStructure;
|
||||
import com.seibel.distanthorizons.core.render.RenderThreadTaskHandler;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IImmersivePortalsAccessor;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper;
|
||||
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||
@@ -35,19 +43,35 @@ import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos;
|
||||
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
||||
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.ServerData;
|
||||
#if MC_VER <= MC_1_12_2
|
||||
import net.minecraft.client.entity.EntityPlayerSP;
|
||||
import net.minecraft.client.multiplayer.WorldClient;
|
||||
import net.minecraft.crash.CrashReport;
|
||||
import net.minecraft.profiler.Profiler;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
import net.minecraft.util.text.TextComponentString;
|
||||
import net.minecraft.world.DimensionType;
|
||||
import net.minecraft.world.WorldServer;
|
||||
import net.minecraftforge.common.DimensionManager;
|
||||
#else
|
||||
import net.minecraft.CrashReport;
|
||||
import net.minecraft.client.CloudStatus;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.client.multiplayer.ServerData;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.util.profiling.ProfilerFiller;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import net.minecraft.world.level.Level;
|
||||
#endif
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
#if MC_VER < MC_1_19_2
|
||||
#if MC_VER < MC_1_19_2 && MC_VER > MC_1_12_2
|
||||
import net.minecraft.network.chat.TextComponent;
|
||||
#endif
|
||||
|
||||
@@ -56,11 +80,26 @@ import net.minecraft.network.chat.TextComponent;
|
||||
import net.minecraft.util.profiling.Profiler;
|
||||
#endif
|
||||
|
||||
#if MC_VER <= MC_1_21_10
|
||||
#if MC_VER <= MC_1_21_10 && MC_VER > MC_1_12_2
|
||||
import net.minecraft.client.GraphicsStatus;
|
||||
#else
|
||||
#endif
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
#elif MC_VER <= MC_1_21_10
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
#else
|
||||
import net.minecraft.resources.Identifier;
|
||||
#endif
|
||||
|
||||
#if MC_VER > MC_1_19_2
|
||||
import net.minecraft.core.registries.Registries;
|
||||
#elif MC_VER > MC_1_12_2
|
||||
import net.minecraft.core.Registry;
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* A singleton that wraps the Minecraft object.
|
||||
*
|
||||
@@ -69,13 +108,23 @@ import net.minecraft.client.GraphicsStatus;
|
||||
public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecraftSharedWrapper
|
||||
{
|
||||
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
private static final Minecraft MINECRAFT = Minecraft.getMinecraft();
|
||||
#else
|
||||
private static final Minecraft MINECRAFT = Minecraft.getInstance();
|
||||
#endif
|
||||
|
||||
public static final MinecraftClientWrapper INSTANCE = new MinecraftClientWrapper();
|
||||
|
||||
|
||||
private ProfilerWrapper profilerWrapper;
|
||||
|
||||
// Need to classload this field later because otherwise it will be null even when Immersive Portals is present.
|
||||
public static class Late {
|
||||
private static final IImmersivePortalsAccessor IMMERSIVE_PORTALS = ModAccessorInjector.INSTANCE.get(IImmersivePortalsAccessor.class);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//======================//
|
||||
@@ -84,19 +133,36 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
|
||||
//region
|
||||
|
||||
@Override
|
||||
public boolean hasSinglePlayerServer() { return MINECRAFT.hasSingleplayerServer(); }
|
||||
@Override
|
||||
public boolean clientConnectedToDedicatedServer()
|
||||
{
|
||||
return MINECRAFT.getCurrentServer() != null
|
||||
&& !this.hasSinglePlayerServer();
|
||||
public boolean hasSinglePlayerServer()
|
||||
{
|
||||
#if MC_VER <= MC_1_12_2
|
||||
return MINECRAFT.isSingleplayer();
|
||||
#else
|
||||
return MINECRAFT.hasSingleplayerServer();
|
||||
#endif
|
||||
}
|
||||
@Override
|
||||
public boolean connectedToReplay()
|
||||
{
|
||||
return MINECRAFT.getCurrentServer() == null
|
||||
&& !this.hasSinglePlayerServer() ;
|
||||
public boolean clientConnectedToDedicatedServer()
|
||||
{
|
||||
return this.hasServerConnection()
|
||||
&& !this.hasSinglePlayerServer();
|
||||
}
|
||||
@Override
|
||||
public boolean connectedToReplay()
|
||||
{
|
||||
return !this.hasServerConnection()
|
||||
&& !this.hasSinglePlayerServer() ;
|
||||
}
|
||||
|
||||
private boolean hasServerConnection()
|
||||
{
|
||||
#if MC_VER <= MC_1_12_2
|
||||
return MINECRAFT.getCurrentServerData() != null;
|
||||
#else
|
||||
return MINECRAFT.getCurrentServer() != null;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getCurrentServerName()
|
||||
@@ -107,8 +173,13 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
|
||||
}
|
||||
else
|
||||
{
|
||||
#if MC_VER <= MC_1_12_2
|
||||
ServerData server = MINECRAFT.getCurrentServerData();
|
||||
return (server != null) ? server.serverName : "NULL";
|
||||
#else
|
||||
ServerData server = MINECRAFT.getCurrentServer();
|
||||
return (server != null) ? server.name : "NULL";
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@Override
|
||||
@@ -120,17 +191,46 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
|
||||
}
|
||||
else
|
||||
{
|
||||
ServerData server = MINECRAFT.getCurrentServer();
|
||||
return (server != null) ? server.ip : "NA";
|
||||
ServerData server = getCurrentServerData();
|
||||
return getServerIp(server);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public String getCurrentServerVersion()
|
||||
{
|
||||
ServerData server = MINECRAFT.getCurrentServer();
|
||||
return (server != null) ? server.version.getString() : "UNKOWN";
|
||||
ServerData server = getCurrentServerData();
|
||||
return getServerVersion(server);
|
||||
}
|
||||
|
||||
private ServerData getCurrentServerData()
|
||||
{
|
||||
#if MC_VER <= MC_1_12_2
|
||||
return MINECRAFT.getCurrentServerData();
|
||||
#else
|
||||
return MINECRAFT.getCurrentServer();
|
||||
#endif
|
||||
}
|
||||
private String getServerIp(ServerData server)
|
||||
{
|
||||
if (server == null) { return "NA"; }
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
return server.serverIP;
|
||||
#else
|
||||
return server.ip;
|
||||
#endif
|
||||
}
|
||||
private String getServerVersion(ServerData server)
|
||||
{
|
||||
if (server == null) { return "UNKOWN"; }
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
return server.gameVersion;
|
||||
#else
|
||||
return server.version.getString();
|
||||
#endif
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
@@ -140,7 +240,11 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
|
||||
//=================//
|
||||
//region
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public EntityPlayerSP getPlayer() { return MINECRAFT.player; }
|
||||
#else
|
||||
public LocalPlayer getPlayer() { return MINECRAFT.player; }
|
||||
#endif
|
||||
|
||||
@Override
|
||||
public boolean playerExists() { return MINECRAFT.player != null; }
|
||||
@@ -148,26 +252,52 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
|
||||
@Override
|
||||
public DhBlockPos getPlayerBlockPos()
|
||||
{
|
||||
#if MC_VER <= MC_1_12_2
|
||||
EntityPlayerSP player = this.getPlayer();
|
||||
#else
|
||||
LocalPlayer player = this.getPlayer();
|
||||
#endif
|
||||
if (player == null)
|
||||
{
|
||||
return new DhBlockPos(0, 0, 0);
|
||||
}
|
||||
|
||||
if (Late.IMMERSIVE_PORTALS != null)
|
||||
{
|
||||
DhBlockPos pos = Late.IMMERSIVE_PORTALS.getOriginalPlayerBlockPos();
|
||||
if (pos != null) return pos;
|
||||
}
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
BlockPos playerPos = player.getPosition();
|
||||
#else
|
||||
BlockPos playerPos = player.blockPosition();
|
||||
#endif
|
||||
return new DhBlockPos(playerPos.getX(), playerPos.getY(), playerPos.getZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
public DhChunkPos getPlayerChunkPos()
|
||||
{
|
||||
#if MC_VER <= MC_1_12_2
|
||||
EntityPlayerSP player = this.getPlayer();
|
||||
#else
|
||||
LocalPlayer player = this.getPlayer();
|
||||
#endif
|
||||
if (player == null)
|
||||
{
|
||||
return new DhChunkPos(0, 0);
|
||||
}
|
||||
|
||||
#if MC_VER < MC_1_17_1
|
||||
if (Late.IMMERSIVE_PORTALS != null)
|
||||
{
|
||||
DhChunkPos pos = Late.IMMERSIVE_PORTALS.getOriginalPlayerChunkPos();
|
||||
if (pos != null) return pos;
|
||||
}
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
ChunkPos playerPos = new ChunkPos(player.getPosition());
|
||||
#elif MC_VER < MC_1_17_1
|
||||
ChunkPos playerPos = new ChunkPos(player.blockPosition());
|
||||
#else
|
||||
ChunkPos playerPos = player.chunkPosition();
|
||||
@@ -197,7 +327,16 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
|
||||
@Nullable
|
||||
public IClientLevelWrapper getWrappedClientLevel(boolean bypassLevelKeyManager)
|
||||
{
|
||||
if (!bypassLevelKeyManager && Late.IMMERSIVE_PORTALS != null)
|
||||
{
|
||||
IClientLevelWrapper level = Late.IMMERSIVE_PORTALS.getOriginalClientLevelWrapper();
|
||||
if (level != null) return level;
|
||||
}
|
||||
#if MC_VER <= MC_1_12_2
|
||||
WorldClient level = MINECRAFT.world;
|
||||
#else
|
||||
ClientLevel level = MINECRAFT.level;
|
||||
#endif
|
||||
if (level == null)
|
||||
{
|
||||
return null;
|
||||
@@ -218,13 +357,19 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
|
||||
@Override
|
||||
public void sendChatMessage(String string)
|
||||
{
|
||||
#if MC_VER <= MC_1_12_2
|
||||
EntityPlayerSP player = this.getPlayer();
|
||||
#else
|
||||
LocalPlayer player = this.getPlayer();
|
||||
#endif
|
||||
if (player == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#if MC_VER < MC_1_19_2
|
||||
#if MC_VER <= MC_1_12_2
|
||||
player.sendMessage(new TextComponentString(string));
|
||||
#elif MC_VER < MC_1_19_2
|
||||
player.sendMessage(new TextComponent(string), getPlayer().getUUID());
|
||||
#elif MC_VER < MC_1_21_9
|
||||
player.displayClientMessage(net.minecraft.network.chat.Component.translatable(string), /*isOverlay*/false);
|
||||
@@ -244,13 +389,19 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
|
||||
@Override
|
||||
public void sendOverlayMessage(String string)
|
||||
{
|
||||
#if MC_VER <= MC_1_12_2
|
||||
EntityPlayerSP player = this.getPlayer();
|
||||
#else
|
||||
LocalPlayer player = this.getPlayer();
|
||||
#endif
|
||||
if (player == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#if MC_VER < MC_1_19_2
|
||||
#if MC_VER <= MC_1_12_2
|
||||
MINECRAFT.ingameGUI.setOverlayMessage(string, /*animateColor*/false);
|
||||
#elif MC_VER < MC_1_19_2
|
||||
player.displayClientMessage(new TextComponent(string), /*isOverlay*/true);
|
||||
#elif MC_VER <= MC_1_21_11
|
||||
player.displayClientMessage(net.minecraft.network.chat.Component.translatable(string), /*isOverlay*/true);
|
||||
@@ -272,7 +423,9 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
|
||||
{
|
||||
LOGGER.info("Disabling vanilla clouds... This is done to prevent vanilla clouds from rendering on top of Distant Horizons LODs.");
|
||||
|
||||
#if MC_VER <= MC_1_18_2
|
||||
#if MC_VER <= MC_1_12_2
|
||||
MINECRAFT.gameSettings.clouds = 0;
|
||||
#elif MC_VER <= MC_1_18_2
|
||||
MINECRAFT.options.renderClouds = CloudStatus.OFF;
|
||||
#else
|
||||
MINECRAFT.options.cloudStatus().set(CloudStatus.OFF);
|
||||
@@ -281,11 +434,13 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
|
||||
|
||||
public void disableVanillaChunkFadeIn()
|
||||
{
|
||||
LOGGER.info("Disabling vanilla chunk fade in... This is done to prevent vanilla chunks from flashing on the Distant Horizons boarder when moving (which is distracting).");
|
||||
String message = "Disabling vanilla chunk fade in... This is done to prevent vanilla chunks from flashing on the Distant Horizons boarder when moving (which is distracting).";
|
||||
|
||||
#if MC_VER <= MC_1_21_10
|
||||
// chunk fade in was added MC 1.21.11
|
||||
#else
|
||||
LOGGER.info(message);
|
||||
|
||||
MINECRAFT.options.chunkSectionFadeInTime().set(0.0);
|
||||
#endif
|
||||
}
|
||||
@@ -294,7 +449,9 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
|
||||
{
|
||||
String reasoning = "This is done to fix vanilla chunks (specifically water blocks) not fading into Distant Horizons LODs when DH's 'Vanilla Fade' option is enabled.";
|
||||
|
||||
#if MC_VER <= MC_1_18_2
|
||||
#if MC_VER <= MC_1_12_2
|
||||
// fabulous graphics was added in MC 1.16
|
||||
#elif MC_VER <= MC_1_18_2
|
||||
LOGGER.info("Disabling fabulous graphics... "+reasoning);
|
||||
|
||||
GraphicsStatus oldGraphicsStatus = MINECRAFT.options.graphicsMode;
|
||||
@@ -330,6 +487,7 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
|
||||
* no override and not included in {@link IMinecraftClientWrapper}
|
||||
* since this would only be used in common/client, not core.
|
||||
*/
|
||||
#if MC_VER > MC_1_12_2
|
||||
public
|
||||
#if MC_VER < MC_1_21_9 long
|
||||
#else Window
|
||||
@@ -343,12 +501,20 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
|
||||
return MINECRAFT.getWindow();
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
@Override
|
||||
public IProfilerWrapper getProfiler()
|
||||
{
|
||||
#if MC_VER <= MC_1_12_2
|
||||
Profiler profiler;
|
||||
#else
|
||||
ProfilerFiller profiler;
|
||||
#if MC_VER < MC_1_21_3
|
||||
#endif
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
profiler = MINECRAFT.profiler;
|
||||
#elif MC_VER < MC_1_21_3
|
||||
profiler = MINECRAFT.getProfiler();
|
||||
#else
|
||||
profiler = Profiler.get();
|
||||
@@ -370,16 +536,36 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
|
||||
public void crashMinecraft(String errorMessage, Throwable exception)
|
||||
{
|
||||
LOGGER.fatal(ModInfo.READABLE_NAME + " had the following error: [" + errorMessage + "]. Crashing Minecraft...", exception);
|
||||
CrashReport report = new CrashReport(errorMessage, exception);
|
||||
#if MC_VER < MC_1_20_4
|
||||
Minecraft.crash(report);
|
||||
|
||||
// Only crash once the renderer has been set up.
|
||||
// If the renderer hasn't been set up yet crashing MC will
|
||||
// cause a Blaze3D/UI error instead of the error we're trying to send.
|
||||
executeOnRenderThread(() ->
|
||||
{
|
||||
CrashReport report = new CrashReport(errorMessage, exception);
|
||||
#if MC_VER <= MC_1_12_2
|
||||
MINECRAFT.crashed(report);
|
||||
#elif MC_VER < MC_1_20_4
|
||||
Minecraft.crash(report);
|
||||
#else
|
||||
MINECRAFT.delayCrash(report);
|
||||
#endif
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executeOnRenderThread(Runnable runnable)
|
||||
{
|
||||
#if MC_VER <= MC_1_12_2
|
||||
MINECRAFT.addScheduledTask(runnable);
|
||||
#else
|
||||
MINECRAFT.delayCrash(report);
|
||||
MINECRAFT.execute(runnable);
|
||||
#endif
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executeOnRenderThread(Runnable runnable) { MINECRAFT.execute(runnable); }
|
||||
public void showDialog(String title, String message, String dialogType, String iconType)
|
||||
{ NativeDialogUtil.showDialog(title, message, dialogType, iconType); }
|
||||
|
||||
//endregion
|
||||
|
||||
@@ -391,7 +577,14 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
|
||||
//region
|
||||
|
||||
@Override
|
||||
public Object getOptionsObject() { return MINECRAFT.options; }
|
||||
public Object getOptionsObject()
|
||||
{
|
||||
#if MC_VER <= MC_1_12_2
|
||||
return MINECRAFT.gameSettings;
|
||||
#else
|
||||
return MINECRAFT.options;
|
||||
#endif
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
@@ -406,22 +599,75 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
|
||||
public boolean isDedicatedServer() { return false; }
|
||||
|
||||
@Override
|
||||
public File getInstallationDirectory() { return MINECRAFT.gameDirectory; }
|
||||
public File getInstallationDirectory()
|
||||
{
|
||||
#if MC_VER <= MC_1_12_2
|
||||
return MINECRAFT.gameDir;
|
||||
#else
|
||||
return MINECRAFT.gameDirectory;
|
||||
#endif
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPlayerCount()
|
||||
{
|
||||
// can be null if the server hasn't finished booting up yet
|
||||
#if MC_VER <= MC_1_12_2
|
||||
if (MINECRAFT.getIntegratedServer() == null)
|
||||
#else
|
||||
if (MINECRAFT.getSingleplayerServer() == null)
|
||||
#endif
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
#if MC_VER <= MC_1_12_2
|
||||
return MINECRAFT.getIntegratedServer().getCurrentPlayerCount();
|
||||
#else
|
||||
return MINECRAFT.getSingleplayerServer().getPlayerCount();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IServerLevelWrapper getWrappedServerLevel(String levelKey)
|
||||
{
|
||||
if (!hasSinglePlayerServer()) return null;
|
||||
#if MC_VER <= MC_1_12_2
|
||||
int dimensionID;
|
||||
try
|
||||
{
|
||||
dimensionID = Integer.parseInt(levelKey.substring(levelKey.indexOf(":")+1));
|
||||
}
|
||||
catch (NumberFormatException ignored)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
#else
|
||||
#if MC_VER <= MC_1_21_10
|
||||
ResourceLocation levelID = ResourceLocation.tryParse(levelKey);
|
||||
#else
|
||||
Identifier levelID = Identifier.tryParse(levelKey);
|
||||
#endif
|
||||
if (levelID == null) return null;
|
||||
|
||||
#if MC_VER > MC_1_19_2
|
||||
ResourceKey<Level> resourceKey = ResourceKey.create(Registries.DIMENSION, levelID);
|
||||
#else
|
||||
ResourceKey<Level> resourceKey = ResourceKey.create(Registry.DIMENSION_REGISTRY, levelID);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
WorldServer level = MINECRAFT.getIntegratedServer().getWorld(dimensionID);
|
||||
#else
|
||||
ServerLevel level = MINECRAFT.getSingleplayerServer().getLevel(resourceKey);
|
||||
#endif
|
||||
return ServerLevelWrapper.getWrapper(level);
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
+102
-31
@@ -19,7 +19,9 @@
|
||||
|
||||
package com.seibel.distanthorizons.common.wrappers.minecraft;
|
||||
|
||||
#if MC_VER < MC_1_21_5
|
||||
#if MC_VER <= MC_1_12_2
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
#elif MC_VER < MC_1_21_5
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
#else
|
||||
import com.mojang.blaze3d.opengl.GlStateManager;
|
||||
@@ -36,7 +38,7 @@ import org.lwjgl.opengl.GL32;
|
||||
* <b>Why does DH often call GL methods twice? </b><br>
|
||||
* Once using the base {@link GL32} function and a second time using
|
||||
* Minecraft's {@link GlStateManager}?<br><br>
|
||||
*
|
||||
*
|
||||
* <b>Answer: </b><br>
|
||||
* Compatibility and robustness<br>
|
||||
* In general all MC rendering should go through MC's {@link GlStateManager},
|
||||
@@ -66,16 +68,20 @@ public class MinecraftGLWrapper
|
||||
// scissor //
|
||||
|
||||
/** @see GL32#GL_SCISSOR_TEST */
|
||||
public void enableScissorTest()
|
||||
public void enableScissorTest()
|
||||
{
|
||||
GL32.glEnable(GL32.GL_SCISSOR_TEST);
|
||||
#if MC_VER > MC_1_12_2
|
||||
GlStateManager._enableScissorTest();
|
||||
#endif
|
||||
}
|
||||
/** @see GL32#GL_SCISSOR_TEST */
|
||||
public void disableScissorTest()
|
||||
{
|
||||
public void disableScissorTest()
|
||||
{
|
||||
GL32.glDisable(GL32.GL_SCISSOR_TEST);
|
||||
GlStateManager._disableScissorTest();
|
||||
#if MC_VER > MC_1_12_2
|
||||
GlStateManager._disableScissorTest();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -90,78 +96,113 @@ public class MinecraftGLWrapper
|
||||
// depth //
|
||||
|
||||
/** @see GL32#GL_DEPTH_TEST */
|
||||
public void enableDepthTest()
|
||||
public void enableDepthTest()
|
||||
{
|
||||
GL32.glEnable(GL32.GL_DEPTH_TEST);
|
||||
#if MC_VER <= MC_1_12_2
|
||||
GlStateManager.enableDepth();
|
||||
#else
|
||||
GlStateManager._enableDepthTest();
|
||||
#endif
|
||||
}
|
||||
/** @see GL32#GL_DEPTH_TEST */
|
||||
public void disableDepthTest()
|
||||
public void disableDepthTest()
|
||||
{
|
||||
GL32.glDisable(GL32.GL_DEPTH_TEST);
|
||||
#if MC_VER <= MC_1_12_2
|
||||
GlStateManager.disableDepth();
|
||||
#else
|
||||
GlStateManager._disableDepthTest();
|
||||
#endif
|
||||
}
|
||||
|
||||
/** @see GL32#glDepthFunc(int) */
|
||||
public void glDepthFunc(int func)
|
||||
{
|
||||
public void glDepthFunc(int func)
|
||||
{
|
||||
GL32.glDepthFunc(func);
|
||||
#if MC_VER <= MC_1_12_2
|
||||
GlStateManager.depthFunc(func);
|
||||
#else
|
||||
GlStateManager._depthFunc(func);
|
||||
#endif
|
||||
}
|
||||
|
||||
/** @see GL32#glDepthMask(boolean) */
|
||||
public void enableDepthMask()
|
||||
public void enableDepthMask()
|
||||
{
|
||||
GL32.glDepthMask(true);
|
||||
GlStateManager._depthMask(true);
|
||||
#if MC_VER <= MC_1_12_2
|
||||
GlStateManager.depthMask(true);
|
||||
#else
|
||||
GlStateManager._depthMask(true);
|
||||
#endif
|
||||
}
|
||||
/** @see GL32#glDepthMask(boolean) */
|
||||
public void disableDepthMask()
|
||||
public void disableDepthMask()
|
||||
{
|
||||
GL32.glDepthMask(false);
|
||||
#if MC_VER <= MC_1_12_2
|
||||
GlStateManager.depthMask(false);
|
||||
#else
|
||||
GlStateManager._depthMask(false);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// blending //
|
||||
|
||||
/** @see GL32#GL_BLEND */
|
||||
public void enableBlend()
|
||||
public void enableBlend()
|
||||
{
|
||||
GL32.glEnable(GL32.GL_BLEND);
|
||||
#if MC_VER <= MC_1_12_2
|
||||
GlStateManager.enableBlend();
|
||||
#else
|
||||
GlStateManager._enableBlend();
|
||||
#endif
|
||||
}
|
||||
/** @see GL32#GL_BLEND */
|
||||
public void disableBlend()
|
||||
public void disableBlend()
|
||||
{
|
||||
GL32.glDisable(GL32.GL_BLEND);
|
||||
#if MC_VER <= MC_1_12_2
|
||||
GlStateManager.disableBlend();
|
||||
#else
|
||||
GlStateManager._disableBlend();
|
||||
#endif
|
||||
}
|
||||
|
||||
/** @see GL32#glBlendFunc */
|
||||
public void glBlendFunc(int sfactor, int dfactor)
|
||||
public void glBlendFunc(int sfactor, int dfactor)
|
||||
{
|
||||
GL32.glBlendFunc(sfactor, dfactor);
|
||||
|
||||
#if MC_VER < MC_1_21_5
|
||||
#if MC_VER <= MC_1_12_2
|
||||
GlStateManager.blendFunc(sfactor, dfactor);
|
||||
#elif MC_VER < MC_1_21_5
|
||||
GlStateManager._blendFunc(sfactor, dfactor);
|
||||
#endif
|
||||
}
|
||||
/** @see GL32#glBlendFuncSeparate */
|
||||
public void glBlendFuncSeparate(int sfactorRGB, int dfactorRGB, int sfactorAlpha, int dfactorAlpha)
|
||||
public void glBlendFuncSeparate(int sfactorRGB, int dfactorRGB, int sfactorAlpha, int dfactorAlpha)
|
||||
{
|
||||
GL32.glBlendFuncSeparate(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha);
|
||||
GlStateManager._blendFuncSeparate(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha);
|
||||
#if MC_VER <= MC_1_12_2
|
||||
GlStateManager.tryBlendFuncSeparate(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha);
|
||||
#else
|
||||
GlStateManager._blendFuncSeparate(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// frame buffers //
|
||||
|
||||
/** @see GL32#glBindFramebuffer */
|
||||
public void glBindFramebuffer(int target, int framebuffer)
|
||||
public void glBindFramebuffer(int target, int framebuffer)
|
||||
{
|
||||
GL32.glBindFramebuffer(target, framebuffer);
|
||||
GlStateManager._glBindFramebuffer(target, framebuffer);
|
||||
#if MC_VER > MC_1_12_2
|
||||
GlStateManager._glBindFramebuffer(target, framebuffer);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -187,31 +228,57 @@ public class MinecraftGLWrapper
|
||||
// culling //
|
||||
|
||||
/** @see GL32#GL_CULL_FACE */
|
||||
public void enableFaceCulling()
|
||||
public void enableFaceCulling()
|
||||
{
|
||||
GL32.glEnable(GL32.GL_CULL_FACE);
|
||||
GlStateManager._enableCull();
|
||||
#if MC_VER <= MC_1_12_2
|
||||
GlStateManager.enableCull();
|
||||
#else
|
||||
GlStateManager._enableCull();
|
||||
#endif
|
||||
}
|
||||
/** @see GL32#GL_CULL_FACE */
|
||||
public void disableFaceCulling()
|
||||
public void disableFaceCulling()
|
||||
{
|
||||
GL32.glDisable(GL32.GL_CULL_FACE);
|
||||
GlStateManager._disableCull();
|
||||
#if MC_VER <= MC_1_12_2
|
||||
GlStateManager.disableCull();
|
||||
#else
|
||||
GlStateManager._disableCull();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// textures //
|
||||
|
||||
/** @see GL32#glGenTextures() */
|
||||
public int glGenTextures() { return GlStateManager._genTexture(); }
|
||||
public int glGenTextures()
|
||||
{
|
||||
#if MC_VER <= MC_1_12_2
|
||||
return GlStateManager.generateTexture();
|
||||
#else
|
||||
return GlStateManager._genTexture();
|
||||
#endif
|
||||
}
|
||||
/** @see GL32#glDeleteTextures(int) */
|
||||
public void glDeleteTextures(int texture) { GlStateManager._deleteTexture(texture); }
|
||||
public void glDeleteTextures(int texture)
|
||||
{
|
||||
#if MC_VER <= MC_1_12_2
|
||||
GlStateManager.deleteTexture(texture);
|
||||
#else
|
||||
GlStateManager._deleteTexture(texture);
|
||||
#endif
|
||||
}
|
||||
|
||||
/** @see GL32#glActiveTexture(int) */
|
||||
public void glActiveTexture(int textureId)
|
||||
{
|
||||
public void glActiveTexture(int textureId)
|
||||
{
|
||||
GL32.glActiveTexture(textureId);
|
||||
#if MC_VER <= MC_1_12_2
|
||||
GlStateManager.setActiveTexture(textureId);
|
||||
#else
|
||||
GlStateManager._activeTexture(textureId);
|
||||
#endif
|
||||
}
|
||||
public int getActiveTexture() { return GL32.glGetInteger(GL32.GL_TEXTURE_BINDING_2D); }
|
||||
|
||||
@@ -219,10 +286,14 @@ public class MinecraftGLWrapper
|
||||
* Always binds to {@link GL32#GL_TEXTURE_2D}
|
||||
* @see GL32#glBindTexture(int, int)
|
||||
*/
|
||||
public void glBindTexture(int texture)
|
||||
public void glBindTexture(int texture)
|
||||
{
|
||||
GL32.glBindTexture(GL32.GL_TEXTURE_2D, texture);
|
||||
#if MC_VER <= MC_1_12_2
|
||||
GlStateManager.bindTexture(texture);
|
||||
#else
|
||||
GlStateManager._bindTexture(texture);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
+158
-75
@@ -20,26 +20,34 @@
|
||||
package com.seibel.distanthorizons.common.wrappers.minecraft;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
#if MC_VER > MC_1_12_2
|
||||
import com.mojang.blaze3d.pipeline.RenderTarget;
|
||||
import com.mojang.blaze3d.platform.NativeImage;
|
||||
#endif
|
||||
import com.seibel.distanthorizons.api.enums.config.EDhApiLodShading;
|
||||
import com.seibel.distanthorizons.common.wrappers.McObjectConverter;
|
||||
import com.seibel.distanthorizons.common.wrappers.misc.LightMapWrapper;
|
||||
import com.seibel.distanthorizons.core.api.internal.ClientApi;
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.enums.EDhDirection;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.util.ColorUtil;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.ILightMapWrapper;
|
||||
|
||||
#if MC_VER < MC_1_17_1
|
||||
#elif MC_VER < MC_1_21_6
|
||||
#elif MC_VER < MC_1_21_3
|
||||
import net.minecraft.client.renderer.FogRenderer;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
#elif MC_VER < MC_1_21_6
|
||||
import com.seibel.distanthorizons.coreapi.util.ColorUtil;
|
||||
import net.minecraft.client.renderer.FogRenderer;
|
||||
#else
|
||||
import com.seibel.distanthorizons.coreapi.util.ColorUtil;
|
||||
import net.minecraft.client.renderer.fog.FogData;
|
||||
import net.minecraft.client.renderer.fog.FogRenderer;
|
||||
#endif
|
||||
@@ -50,26 +58,38 @@ import org.joml.Vector3f;
|
||||
#else
|
||||
#endif
|
||||
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.AbstractOptifineAccessor;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IDimensionTypeWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
||||
import com.seibel.distanthorizons.core.util.math.Vec3d;
|
||||
import com.seibel.distanthorizons.core.util.math.Vec3f;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IImmersivePortalsAccessor;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IOptifineAccessor;
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraftforge.fluids.IFluidBlock;
|
||||
import net.minecraft.init.MobEffects;
|
||||
import net.minecraft.client.renderer.entity.RenderManager;
|
||||
#else
|
||||
import net.minecraft.client.Camera;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.effect.MobEffects;
|
||||
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
#endif
|
||||
import net.minecraft.client.Minecraft;
|
||||
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.joml.Vector4f;
|
||||
|
||||
#if MC_VER < MC_1_17_1
|
||||
#if MC_VER <= MC_1_12_2
|
||||
import org.lwjgl.opengl.GL15;
|
||||
#elif MC_VER < MC_1_17_1
|
||||
import net.minecraft.tags.FluidTags;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.level.material.FluidState;
|
||||
@@ -97,8 +117,21 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
|
||||
{
|
||||
public static final MinecraftRenderWrapper INSTANCE = new MinecraftRenderWrapper();
|
||||
|
||||
private static final IOptifineAccessor OPTIFINE_ACCESSOR = ModAccessorInjector.INSTANCE.get(IOptifineAccessor.class);
|
||||
private static final IMinecraftClientWrapper MC_CLIENT = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
|
||||
|
||||
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
private static final Minecraft MC = Minecraft.getMinecraft();
|
||||
#else
|
||||
private static final Minecraft MC = Minecraft.getInstance();
|
||||
#endif
|
||||
|
||||
// Need to classload this field later because otherwise it will be null even when Immersive Portals is present.
|
||||
public static class Late {
|
||||
private static final IImmersivePortalsAccessor IMMERSIVE_PORTALS = ModAccessorInjector.INSTANCE.get(IImmersivePortalsAccessor.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* In the case of immersive portals multiple levels may be active at once, causing conflicting lightmaps. <br>
|
||||
@@ -129,7 +162,10 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
|
||||
@Override
|
||||
public Vec3f getLookAtVector()
|
||||
{
|
||||
#if MC_VER <= MC_1_21_10
|
||||
#if MC_VER <= MC_1_12_2
|
||||
net.minecraft.util.math.Vec3d lookVector = (MC.getRenderViewEntity().getLook(MC.getRenderPartialTicks()));
|
||||
return new Vec3f((float) lookVector.x, (float) lookVector.y, (float) lookVector.z);
|
||||
#elif MC_VER <= MC_1_21_10
|
||||
Camera camera = MC.gameRenderer.getMainCamera();
|
||||
return new Vec3f(camera.getLookVector().x(), camera.getLookVector().y(), camera.getLookVector().z());
|
||||
#else
|
||||
@@ -149,37 +185,57 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (MC.player.getActiveEffectsMap() == null)
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
if (MC.player.getActivePotionMap() == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
|
||||
return MC.player.getActivePotionEffect(MobEffects.BLINDNESS) != null;
|
||||
#else
|
||||
if (MC.player.getActiveEffectsMap() == null)
|
||||
{
|
||||
return MC.player.getActiveEffectsMap().get(MobEffects.BLINDNESS) != null
|
||||
#if MC_VER >= MC_1_19_2
|
||||
|| MC.player.getActiveEffectsMap().get(MobEffects.DARKNESS) != null // Deep dark effect
|
||||
#endif
|
||||
;
|
||||
return false;
|
||||
}
|
||||
|
||||
return MC.player.getActiveEffectsMap().get(MobEffects.BLINDNESS) != null
|
||||
#if MC_VER >= MC_1_19_2
|
||||
|| MC.player.getActiveEffectsMap().get(MobEffects.DARKNESS) != null // Deep dark effect
|
||||
#endif
|
||||
;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vec3d getCameraExactPosition()
|
||||
{
|
||||
if (Late.IMMERSIVE_PORTALS != null)
|
||||
{
|
||||
Vec3d cameraPos = Late.IMMERSIVE_PORTALS.getOriginalCameraPos();
|
||||
if (cameraPos != null) return cameraPos;
|
||||
}
|
||||
#if MC_VER <= MC_1_12_2
|
||||
RenderManager rm = MC.getRenderManager();
|
||||
return new Vec3d(rm.viewerPosX, rm.viewerPosY, rm.viewerPosZ);
|
||||
#else
|
||||
Camera camera = MC.gameRenderer.getMainCamera();
|
||||
#if MC_VER <= MC_1_21_10
|
||||
Vec3 projectedView = camera.getPosition();
|
||||
#else
|
||||
Vec3 projectedView = camera.position();
|
||||
#endif
|
||||
|
||||
return new Vec3d(projectedView.x, projectedView.y, projectedView.z);
|
||||
#endif
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getPartialTickTime()
|
||||
{
|
||||
#if MC_VER < MC_1_21_1
|
||||
#if MC_VER <= MC_1_12_2
|
||||
return MC.getRenderPartialTicks();
|
||||
#elif MC_VER < MC_1_21_1
|
||||
return MC.getFrameTime();
|
||||
#elif MC_VER < MC_1_21_3
|
||||
return MC.getTimer().getRealtimeDeltaTicks();
|
||||
@@ -292,9 +348,17 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
|
||||
@Override
|
||||
public Color getSkyColor()
|
||||
{
|
||||
#if MC_VER <= MC_1_12_2
|
||||
if (MC.world.provider.hasSkyLight())
|
||||
#else
|
||||
if (MC.level.dimensionType().hasSkyLight())
|
||||
#endif
|
||||
{
|
||||
#if MC_VER < MC_1_17_1
|
||||
#if MC_VER <= MC_1_12_2
|
||||
float frameTime = this.getPartialTickTime();
|
||||
net.minecraft.util.math.Vec3d colorValues = MC.world.getSkyColor(MC.getRenderViewEntity(), frameTime);
|
||||
return new Color((float) colorValues.x, (float) colorValues.y, (float) colorValues.z);
|
||||
#elif MC_VER < MC_1_17_1
|
||||
float frameTime = this.getPartialTickTime();
|
||||
Vec3 colorValues = MC.level.getSkyColor(MC.gameRenderer.getMainCamera().getBlockPosition(), frameTime);
|
||||
return new Color((float) colorValues.x, (float) colorValues.y, (float) colorValues.z);
|
||||
@@ -321,7 +385,9 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
|
||||
@Override
|
||||
public int getRenderDistance()
|
||||
{
|
||||
#if MC_VER <= MC_1_17_1
|
||||
#if MC_VER <= MC_1_12_2
|
||||
return MC.gameSettings.renderDistanceChunks;
|
||||
#elif MC_VER <= MC_1_17_1
|
||||
return MC.options.renderDistance;
|
||||
#else
|
||||
return MC.options.getEffectiveRenderDistance();
|
||||
@@ -331,14 +397,18 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
|
||||
@Override
|
||||
public int getFrameLimit()
|
||||
{
|
||||
#if MC_VER <= MC_1_18_2
|
||||
#if MC_VER <= MC_1_12_2
|
||||
return MC.gameSettings.limitFramerate;
|
||||
#elif MC_VER <= MC_1_18_2
|
||||
return MC.options.framerateLimit;
|
||||
#else
|
||||
return MC.options.framerateLimit().get();
|
||||
#endif
|
||||
}
|
||||
|
||||
#if MC_VER > MC_1_12_2
|
||||
protected RenderTarget getRenderTarget() { return MC.getMainRenderTarget(); }
|
||||
#endif
|
||||
|
||||
@Override
|
||||
public boolean mcRendersToFrameBuffer()
|
||||
@@ -364,12 +434,14 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
|
||||
public int getTargetFramebuffer()
|
||||
{
|
||||
// used so we can access the framebuffer shaders end up rendering to
|
||||
if (AbstractOptifineAccessor.optifinePresent())
|
||||
if (OPTIFINE_ACCESSOR != null)
|
||||
{
|
||||
return this.finalLevelFrameBufferId;
|
||||
}
|
||||
|
||||
#if MC_VER < MC_1_21_5
|
||||
#if MC_VER <= MC_1_12_2
|
||||
return MC.getFramebuffer().framebufferObject;
|
||||
#elif MC_VER < MC_1_21_5
|
||||
return this.getRenderTarget().frameBufferId;
|
||||
#else
|
||||
// MC renders to a texture and then directly to the default FBO now
|
||||
@@ -384,7 +456,10 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
|
||||
@Override
|
||||
public int getDepthTextureId()
|
||||
{
|
||||
#if MC_VER < MC_1_21_5
|
||||
#if MC_VER <= MC_1_12_2
|
||||
//1.12.2 is using renderbuffer instead of framebuffer for depth texture
|
||||
return -1;
|
||||
#elif MC_VER < MC_1_21_5
|
||||
return this.getRenderTarget().getDepthTextureId();
|
||||
#else
|
||||
try
|
||||
@@ -414,7 +489,9 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
|
||||
@Override
|
||||
public int getColorTextureId()
|
||||
{
|
||||
#if MC_VER < MC_1_21_5
|
||||
#if MC_VER <= MC_1_12_2
|
||||
return MC.getFramebuffer().framebufferTexture;
|
||||
#elif MC_VER < MC_1_21_5
|
||||
return this.getRenderTarget().getColorTextureId();
|
||||
#else
|
||||
try
|
||||
@@ -444,7 +521,9 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
|
||||
@Override
|
||||
public int getTargetFramebufferViewportWidth()
|
||||
{
|
||||
#if MC_VER < MC_1_21_9
|
||||
#if MC_VER <= MC_1_12_2
|
||||
return MC.getFramebuffer().framebufferWidth;
|
||||
#elif MC_VER < MC_1_21_9
|
||||
return this.getRenderTarget().viewWidth;
|
||||
#else
|
||||
return this.getRenderTarget().width;
|
||||
@@ -454,20 +533,23 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
|
||||
@Override
|
||||
public int getTargetFramebufferViewportHeight()
|
||||
{
|
||||
#if MC_VER < MC_1_21_9
|
||||
#if MC_VER <= MC_1_12_2
|
||||
return MC.getFramebuffer().framebufferHeight;
|
||||
#elif MC_VER < MC_1_21_9
|
||||
return this.getRenderTarget().viewHeight;
|
||||
#else
|
||||
return this.getRenderTarget().height;
|
||||
#endif
|
||||
}
|
||||
|
||||
@Override
|
||||
public ILightMapWrapper getLightmapWrapper(@NotNull ILevelWrapper level) { return this.lightmapByDimensionType.get(level.getDimensionType()); }
|
||||
|
||||
@Override
|
||||
public boolean isFogStateSpecial()
|
||||
{
|
||||
#if MC_VER < MC_1_17_1
|
||||
#if MC_VER <= MC_1_12_2
|
||||
BlockPos blockPos = new BlockPos(MC.getRenderViewEntity().getPositionEyes(MC.getRenderPartialTicks()));
|
||||
IBlockState fluidState = MC.getRenderViewEntity().world.getBlockState(blockPos);
|
||||
return this.playerHasBlindingEffect() || fluidState.getMaterial().isLiquid() || fluidState.getBlock() instanceof IFluidBlock;
|
||||
#elif MC_VER < MC_1_17_1
|
||||
Camera camera = Minecraft.getInstance().gameRenderer.getMainCamera();
|
||||
FluidState fluidState = camera.getFluidInCamera();
|
||||
Entity entity = camera.getEntity();
|
||||
@@ -481,88 +563,89 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
//==========//
|
||||
// lightmap //
|
||||
//==========//
|
||||
//region
|
||||
|
||||
@Override
|
||||
public ILightMapWrapper getLightmapWrapper(@NotNull ILevelWrapper level) { return this.lightmapByDimensionType.get(level.getDimensionType()); }
|
||||
|
||||
/**
|
||||
* It's better to use {@link MinecraftRenderWrapper#setLightmapId(int, IClientLevelWrapper)} if possible,
|
||||
* It's better to use {@link MinecraftRenderWrapper#setLightmapId(int)} if possible,
|
||||
* however old MC versions don't support it.
|
||||
*/
|
||||
public void updateLightmap(NativeImage lightPixels, IClientLevelWrapper level)
|
||||
#if MC_VER > MC_1_12_2
|
||||
public void updateLightmap(NativeImage lightPixels)
|
||||
{
|
||||
IClientLevelWrapper clientLevel = getLightmapClientLevelWrapper();
|
||||
if (clientLevel == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Using ClientLevelWrapper as the key would be better, but we don't have a consistent way to create the same
|
||||
// object for the same MC level and/or the same hash,
|
||||
// so this will have to do for now
|
||||
IDimensionTypeWrapper dimensionType = level.getDimensionType();
|
||||
IDimensionTypeWrapper dimensionType = clientLevel.getDimensionType();
|
||||
|
||||
LightMapWrapper wrapper = this.lightmapByDimensionType.computeIfAbsent(dimensionType, (dimType) -> new LightMapWrapper());
|
||||
wrapper.uploadLightmap(lightPixels);
|
||||
}
|
||||
public void setLightmapId(int tetxureId, IClientLevelWrapper level)
|
||||
#endif
|
||||
|
||||
public void setLightmapId(int textureId)
|
||||
{
|
||||
IClientLevelWrapper clientLevel = getLightmapClientLevelWrapper();
|
||||
if (clientLevel == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Using ClientLevelWrapper as the key would be better, but we don't have a consistent way to create the same
|
||||
// object for the same MC level and/or the same hash,
|
||||
// so this will have to do for now
|
||||
IDimensionTypeWrapper dimensionType = level.getDimensionType();
|
||||
IDimensionTypeWrapper dimensionType = clientLevel.getDimensionType();
|
||||
|
||||
LightMapWrapper wrapper = this.lightmapByDimensionType.computeIfAbsent(dimensionType, (dimType) -> new LightMapWrapper());
|
||||
wrapper.setLightmapId(tetxureId);
|
||||
wrapper.setLightmapId(textureId);
|
||||
}
|
||||
|
||||
#if MC_VER <= MC_1_21_10
|
||||
#else
|
||||
public void setLightmapGpuTexture(GpuTexture gpuTexture, IClientLevelWrapper level)
|
||||
public void setLightmapGpuTexture(GpuTexture gpuTexture)
|
||||
{
|
||||
IClientLevelWrapper clientLevel = getLightmapClientLevelWrapper();
|
||||
if (clientLevel == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Using ClientLevelWrapper as the key would be better, but we don't have a consistent way to create the same
|
||||
// object for the same MC level and/or the same hash,
|
||||
// so this will have to do for now
|
||||
IDimensionTypeWrapper dimensionType = level.getDimensionType();
|
||||
IDimensionTypeWrapper dimensionType = clientLevel.getDimensionType();
|
||||
|
||||
LightMapWrapper wrapper = this.lightmapByDimensionType.computeIfAbsent(dimensionType, (dimType) -> new LightMapWrapper());
|
||||
wrapper.setLightmapGpuTexture(gpuTexture);
|
||||
}
|
||||
#endif
|
||||
|
||||
@Override
|
||||
public float getShade(EDhDirection lodDirection)
|
||||
private static @Nullable IClientLevelWrapper getLightmapClientLevelWrapper()
|
||||
{
|
||||
EDhApiLodShading lodShading = Config.Client.Advanced.Graphics.Quality.lodShading.get();
|
||||
switch (lodShading)
|
||||
IClientLevelWrapper clientLevel = ClientApi.RENDER_STATE.clientLevelWrapper;
|
||||
if (clientLevel == null)
|
||||
{
|
||||
default:
|
||||
case AUTO:
|
||||
if (MC.level != null)
|
||||
{
|
||||
Direction mcDir = McObjectConverter.Convert(lodDirection);
|
||||
#if MC_VER <= MC_1_21_11
|
||||
return MC.level.getShade(mcDir, true);
|
||||
#else
|
||||
return MC.level.cardinalLighting().byFace(mcDir);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
case ENABLED:
|
||||
switch (lodDirection)
|
||||
{
|
||||
case DOWN:
|
||||
return 0.5F;
|
||||
default:
|
||||
case UP:
|
||||
return 1.0F;
|
||||
case NORTH:
|
||||
case SOUTH:
|
||||
return 0.8F;
|
||||
case WEST:
|
||||
case EAST:
|
||||
return 0.6F;
|
||||
}
|
||||
|
||||
case DISABLED:
|
||||
return 1.0F;
|
||||
clientLevel = MC_CLIENT.getWrappedClientLevel();
|
||||
}
|
||||
|
||||
return clientLevel;
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
+67
-2
@@ -1,9 +1,32 @@
|
||||
package com.seibel.distanthorizons.common.wrappers.minecraft;
|
||||
|
||||
import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftSharedWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper;
|
||||
import net.minecraft.server.dedicated.DedicatedServer;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
#if MC_VER > MC_1_12_2
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.level.Level;
|
||||
#else
|
||||
import net.minecraft.world.WorldServer;
|
||||
#endif
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
#elif MC_VER <= MC_1_21_10
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
#else
|
||||
import net.minecraft.resources.Identifier;
|
||||
#endif
|
||||
|
||||
#if MC_VER > MC_1_19_2
|
||||
import net.minecraft.core.registries.Registries;
|
||||
#elif MC_VER > MC_1_12_2
|
||||
import net.minecraft.core.Registry;
|
||||
#endif
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class MinecraftServerWrapper implements IMinecraftSharedWrapper
|
||||
@@ -39,7 +62,9 @@ public class MinecraftServerWrapper implements IMinecraftSharedWrapper
|
||||
throw new IllegalStateException("Trying to get Installation Direction before dedicated server completed initialization!");
|
||||
}
|
||||
|
||||
#if MC_VER < MC_1_21_1
|
||||
#if MC_VER <= MC_1_12_2
|
||||
return this.dedicatedServer.getDataDirectory();
|
||||
#elif MC_VER < MC_1_21_1
|
||||
return this.dedicatedServer.getServerDirectory();
|
||||
#else
|
||||
return this.dedicatedServer.getServerDirectory().toFile();
|
||||
@@ -54,9 +79,49 @@ public class MinecraftServerWrapper implements IMinecraftSharedWrapper
|
||||
throw new IllegalStateException("Trying to get player count before dedicated server completed initialization!");
|
||||
}
|
||||
|
||||
return this.dedicatedServer.getPlayerCount();
|
||||
#if MC_VER <= MC_1_12_2
|
||||
return this.dedicatedServer.getCurrentPlayerCount();
|
||||
#else
|
||||
return this.dedicatedServer.getPlayerCount();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public IServerLevelWrapper getWrappedServerLevel(String levelKey)
|
||||
{
|
||||
#if MC_VER <= MC_1_12_2
|
||||
int dimensionID;
|
||||
try
|
||||
{
|
||||
dimensionID = Integer.parseInt(levelKey.substring(levelKey.indexOf(":")+1));
|
||||
}
|
||||
catch (NumberFormatException ignored)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
#else
|
||||
#if MC_VER <= MC_1_21_10
|
||||
ResourceLocation levelID = ResourceLocation.tryParse(levelKey);
|
||||
#else
|
||||
Identifier levelID = Identifier.tryParse(levelKey);
|
||||
#endif
|
||||
if (levelID == null) return null;
|
||||
|
||||
#if MC_VER > MC_1_19_2
|
||||
ResourceKey<Level> resourceKey = ResourceKey.create(Registries.DIMENSION, levelID);
|
||||
#else
|
||||
ResourceKey<Level> resourceKey = ResourceKey.create(Registry.DIMENSION_REGISTRY, levelID);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if MC_VER > MC_1_12_2
|
||||
ServerLevel level = dedicatedServer.getLevel(resourceKey);
|
||||
#else
|
||||
WorldServer level = dedicatedServer.getWorld(dimensionID);
|
||||
#endif
|
||||
return ServerLevelWrapper.getWrapper(level);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+71
-13
@@ -21,29 +21,87 @@ package com.seibel.distanthorizons.common.wrappers.minecraft;
|
||||
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IProfilerWrapper;
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
import net.minecraft.profiler.Profiler;
|
||||
#else
|
||||
import net.minecraft.util.profiling.ProfilerFiller;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @author James Seibel
|
||||
* @version 11-20-2021
|
||||
*/
|
||||
public class ProfilerWrapper implements IProfilerWrapper
|
||||
{
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public Profiler profiler;
|
||||
#else
|
||||
public ProfilerFiller profiler;
|
||||
|
||||
public ProfilerWrapper(ProfilerFiller newProfiler) { this.profiler = newProfiler; }
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public ProfilerWrapper(Profiler newProfiler)
|
||||
#else
|
||||
public ProfilerWrapper(ProfilerFiller newProfiler)
|
||||
#endif
|
||||
{ this.profiler = newProfiler; }
|
||||
|
||||
|
||||
|
||||
/** starts a new section inside the currently running section */
|
||||
@Override
|
||||
public void push(String newSection) { this.profiler.push(newSection); }
|
||||
public IProfileBlock push(String newSection)
|
||||
{
|
||||
#if MC_VER <= MC_1_12_2
|
||||
this.profiler.startSection(newSection);
|
||||
#else
|
||||
this.profiler.push(newSection);
|
||||
#endif
|
||||
return new ProfileBlock(this.profiler);
|
||||
}
|
||||
|
||||
/** ends the currently running section and starts a new one */
|
||||
@Override
|
||||
public void popPush(String newSection) { this.profiler.popPush(newSection); }
|
||||
public void popPush(String newSection)
|
||||
{
|
||||
#if MC_VER <= MC_1_12_2
|
||||
this.profiler.endStartSection(newSection);
|
||||
#else
|
||||
this.profiler.popPush(newSection) ;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
//================//
|
||||
// helper classes //
|
||||
//================//
|
||||
//region
|
||||
|
||||
public static class ProfileBlock implements IProfileBlock
|
||||
{
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public Profiler profiler;
|
||||
#else
|
||||
public ProfilerFiller profiler;
|
||||
#endif
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public ProfileBlock(Profiler newProfiler)
|
||||
#else
|
||||
public ProfileBlock(ProfilerFiller newProfiler)
|
||||
#endif
|
||||
{ this.profiler = newProfiler; }
|
||||
|
||||
@Override
|
||||
public void close()
|
||||
{
|
||||
#if MC_VER <= MC_1_12_2
|
||||
this.profiler.endSection();
|
||||
#else
|
||||
this.profiler.pop();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
/** ends the currently running section */
|
||||
@Override
|
||||
public void pop() { this.profiler.pop(); }
|
||||
|
||||
}
|
||||
|
||||
+9
@@ -1,12 +1,21 @@
|
||||
package com.seibel.distanthorizons.common.wrappers.misc;
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
import net.minecraft.world.WorldServer;
|
||||
#else
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
#endif
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface IMixinServerPlayer
|
||||
{
|
||||
@Nullable
|
||||
#if MC_VER <= MC_1_12_2
|
||||
WorldServer distantHorizons$getDimensionChangeDestination();
|
||||
#else
|
||||
ServerLevel distantHorizons$getDimensionChangeDestination();
|
||||
#endif
|
||||
|
||||
#if MC_VER == MC_1_16_5
|
||||
void distantHorizons$setDimensionChangeDestination(ServerLevel dimensionChangeDestination);
|
||||
|
||||
+7
-1
@@ -19,9 +19,13 @@
|
||||
|
||||
package com.seibel.distanthorizons.common.wrappers.misc;
|
||||
|
||||
#if MC_VER > MC_1_12_2
|
||||
import com.mojang.blaze3d.platform.NativeImage;
|
||||
import com.seibel.distanthorizons.common.render.blaze.wrappers.texture.BlazeTextureViewWrapper;
|
||||
#endif
|
||||
import com.seibel.distanthorizons.common.render.blaze.wrappers.texture.BlazeTextureViewWrapper;
|
||||
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftGLWrapper;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.ILightMapWrapper;
|
||||
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||
@@ -58,7 +62,6 @@ public class LightMapWrapper implements ILightMapWrapper
|
||||
private final BlazeTextureViewWrapper lightmapTextureWrapper = new BlazeTextureViewWrapper();
|
||||
|
||||
|
||||
|
||||
//==============//
|
||||
// constructors //
|
||||
//==============//
|
||||
@@ -75,6 +78,7 @@ public class LightMapWrapper implements ILightMapWrapper
|
||||
//==================//
|
||||
//region
|
||||
|
||||
#if MC_VER > MC_1_12_2
|
||||
public void uploadLightmap(NativeImage image)
|
||||
{
|
||||
#if MC_VER < MC_1_21_3
|
||||
@@ -110,6 +114,7 @@ public class LightMapWrapper implements ILightMapWrapper
|
||||
throw new UnsupportedOperationException("setLightmapId should be used for MC versions after 1.21.3");
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
public void setLightmapId(int minecraftLightmapTextureId)
|
||||
{
|
||||
@@ -126,6 +131,7 @@ public class LightMapWrapper implements ILightMapWrapper
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
+12
@@ -1,7 +1,11 @@
|
||||
package com.seibel.distanthorizons.common.wrappers.misc;
|
||||
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IMutableBlockPosWrapper;
|
||||
#if MC_VER <= MC_1_12_2
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
#else
|
||||
import net.minecraft.core.BlockPos;
|
||||
#endif
|
||||
|
||||
public class MutableBlockPosWrapper implements IMutableBlockPosWrapper
|
||||
{
|
||||
@@ -12,19 +16,27 @@ public class MutableBlockPosWrapper implements IMutableBlockPosWrapper
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
//region
|
||||
|
||||
public MutableBlockPosWrapper()
|
||||
{
|
||||
this.pos = new BlockPos.MutableBlockPos();
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//===========//
|
||||
// overrides //
|
||||
//===========//
|
||||
//region
|
||||
|
||||
@Override
|
||||
public Object getWrappedMcObject() { return this.pos; }
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
+79
-6
@@ -6,53 +6,114 @@ import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IServerPlayerWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper;
|
||||
import com.seibel.distanthorizons.core.util.math.Vec3d;
|
||||
#if MC_VER <= MC_1_12_2
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.network.NetHandlerPlayServer;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.WorldServer;
|
||||
#else
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.server.network.ServerGamePacketListenerImpl;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
#endif
|
||||
|
||||
import java.net.SocketAddress;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
|
||||
/**
|
||||
* This wrapper transparently ensures that the underlying {@link EntityPlayerMP} is always valid,
|
||||
* unless the player has disconnected.
|
||||
*/
|
||||
#else
|
||||
/**
|
||||
* This wrapper transparently ensures that the underlying {@link ServerPlayer} is always valid,
|
||||
* unless the player has disconnected.
|
||||
*/
|
||||
#endif
|
||||
public class ServerPlayerWrapper implements IServerPlayerWrapper
|
||||
{
|
||||
#if MC_VER <= MC_1_12_2
|
||||
private static final ConcurrentMap<NetHandlerPlayServer, ServerPlayerWrapper> serverPlayerWrapperMap = new MapMaker().weakKeys().weakValues().makeMap();
|
||||
#else
|
||||
private static final ConcurrentMap<ServerGamePacketListenerImpl, ServerPlayerWrapper> serverPlayerWrapperMap = new MapMaker().weakKeys().weakValues().makeMap();
|
||||
#endif
|
||||
|
||||
#if MC_VER <= MC_1_12_2
|
||||
private final NetHandlerPlayServer connection;
|
||||
#else
|
||||
private final ServerGamePacketListenerImpl connection;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
//region
|
||||
|
||||
public static ServerPlayerWrapper getWrapper(ServerPlayer serverPlayer)
|
||||
#if MC_VER <= MC_1_12_2
|
||||
public static ServerPlayerWrapper getWrapper(EntityPlayerMP serverPlayer)
|
||||
#else
|
||||
public static ServerPlayerWrapper getWrapper(ServerPlayer serverPlayer)
|
||||
#endif
|
||||
{ return serverPlayerWrapperMap.computeIfAbsent(serverPlayer.connection, ignored -> new ServerPlayerWrapper(serverPlayer.connection)); }
|
||||
|
||||
private ServerPlayerWrapper(ServerGamePacketListenerImpl connection) { this.connection = connection; }
|
||||
#if MC_VER <= MC_1_12_2
|
||||
private ServerPlayerWrapper(NetHandlerPlayServer connection)
|
||||
#else
|
||||
private ServerPlayerWrapper(ServerGamePacketListenerImpl connection)
|
||||
#endif
|
||||
{ this.connection = connection; }
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//=========//
|
||||
// getters //
|
||||
//=========//
|
||||
//region
|
||||
|
||||
private ServerPlayer getServerPlayer() { return this.connection.player; }
|
||||
#if MC_VER <= MC_1_12_2
|
||||
private EntityPlayerMP getServerPlayer()
|
||||
#else
|
||||
private ServerPlayer getServerPlayer()
|
||||
#endif
|
||||
{ return this.connection.player; }
|
||||
|
||||
@Override
|
||||
public String getName() { return this.getServerPlayer().getName().getString(); }
|
||||
public String getName()
|
||||
{
|
||||
#if MC_VER <= MC_1_12_2
|
||||
return this.getServerPlayer().getName();
|
||||
#else
|
||||
return this.getServerPlayer().getName().getString();
|
||||
#endif
|
||||
}
|
||||
|
||||
@Override
|
||||
public IServerLevelWrapper getLevel()
|
||||
{
|
||||
ServerLevel level = ((IMixinServerPlayer) this.getServerPlayer()).distantHorizons$getDimensionChangeDestination();
|
||||
#if MC_VER <= MC_1_12_2
|
||||
WorldServer level = null;
|
||||
if (this.getServerPlayer() instanceof IMixinServerPlayer mixinPlayer)
|
||||
{
|
||||
level = mixinPlayer.distantHorizons$getDimensionChangeDestination();
|
||||
}
|
||||
#else
|
||||
ServerLevel level = ((IMixinServerPlayer) this.getServerPlayer()).distantHorizons$getDimensionChangeDestination();
|
||||
#endif
|
||||
|
||||
if (level == null)
|
||||
{
|
||||
#if MC_VER < MC_1_20_1
|
||||
#if MC_VER <= MC_1_12_2
|
||||
MinecraftServer server = this.getServerPlayer().getServer();
|
||||
level = (server != null) ? server.getWorld(this.getServerPlayer().dimension) : this.getServerPlayer().getServerWorld();
|
||||
#elif MC_VER < MC_1_20_1
|
||||
level = this.getServerPlayer().getLevel();
|
||||
#elif MC_VER < MC_1_21_6
|
||||
level = this.getServerPlayer().serverLevel();
|
||||
@@ -67,15 +128,23 @@ public class ServerPlayerWrapper implements IServerPlayerWrapper
|
||||
@Override
|
||||
public Vec3d getPosition()
|
||||
{
|
||||
#if MC_VER <= MC_1_12_2
|
||||
BlockPos position = this.getServerPlayer().getPosition();
|
||||
return new Vec3d(position.getX(), position.getY(), position.getZ());
|
||||
#else
|
||||
Vec3 position = this.getServerPlayer().position();
|
||||
return new Vec3d(position.x, position.y, position.z);
|
||||
#endif
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
//================//
|
||||
// base overrides //
|
||||
//================//
|
||||
//region
|
||||
|
||||
@Override
|
||||
public Object getWrappedMcObject() { return this.getServerPlayer(); }
|
||||
@@ -101,4 +170,8 @@ public class ServerPlayerWrapper implements IServerPlayerWrapper
|
||||
@Override
|
||||
public int hashCode() { return Objects.hashCode(this.connection); }
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user