Compare commits

..

86 Commits

Author SHA1 Message Date
Ran 865923b0dc Update Readme.md 2022-04-17 17:01:21 +00:00
James Seibel b9b023691a remove a few compiler warnings and update core 2022-04-01 21:00:33 -05:00
coolGi2007 5c7dfc5905 Downgraded stuff (removes fabric api) and updated gitlab cd 2022-04-01 17:35:00 +10:30
coolGi2007 b70fc86516 Downgraded 1.18 to 1.17 (that took a long time) tough still needs some fixing 2022-03-30 17:35:09 +10:30
coolGi2007 9c3ecc6deb Downgraded stuff from 1.18 to 1.17 and updated core 2022-03-10 17:38:07 +10:30
coolGi2007 d688a53d74 Added the multiplayer folder thing from 1.18 2022-03-08 17:24:31 +10:30
James Seibel 2cf4b42c5c Rename MinecraftWrapper -> MinecraftClientWrapper 2022-03-05 18:29:37 -06:00
James Seibel c726a49c82 remove WorldWrapper.isEmpty()
It wasn't used and there was a comment saying not to use it
2022-03-05 18:15:17 -06:00
James Seibel 0b0a69aabe (No Fabric) Update the DependencyHandler to support circular references 2022-03-05 17:41:37 -06:00
James Seibel 96ac022cbf Merge branch '1.17.X' of gitlab.com:jeseibel/minecraft-lod-mod into 1.17.X 2022-03-03 19:42:07 -06:00
James Seibel fa325b2eb8 Start updating for changed core 2022-03-03 19:41:31 -06:00
coolGi2007 c87233eb10 Fixed everything 2022-03-03 17:08:17 +10:30
James Seibel 88497593c4 Refactor the dependency injectors 2022-03-01 21:30:40 -06:00
coolGi2007 9817dcf022 Renamed readme to 1.17.X 2022-02-28 11:06:22 +00:00
coolGi2007 898eda7355 Updated the readme and updated the DHJarMerger (now marks the jar as an executable so linux users have an easier time when runnung the jar) 2022-02-22 17:55:03 +10:30
coolGi2007 7363231361 Updated fabric, core, readme and added a way to run jar 2022-02-21 16:30:02 +10:30
cola98765 40fbca33f4 actually fix tint on custom water textures. 2022-02-19 22:32:03 +01:00
cola98765 62712cfab4 actually fix tint on custom water textures. 2022-02-19 22:30:01 +01:00
James Seibel 8d94988be1 Update the version number to 1.6.2a 2022-02-17 20:22:36 -06:00
cola98765 99ce73feee update BlockColorWrapper, and fix "wraning" 2022-02-15 12:11:29 +01:00
coolGi2007 b7e3db12d9 Fixed some stuff in the modinfo 2022-02-15 05:00:41 +00:00
coolGi2007 e0a7010abf Updated gradle stuff to be more like 1.18 2022-02-14 17:36:37 +10:30
James Seibel f1b8616329 Update the forge version 2022-02-13 16:58:52 -06:00
James Seibel b6a84a454b Prepare for 1.6.1a 2022-02-12 12:03:23 -06:00
tom lee b8aabc59cd Fix forge mixin loading class prematurely 2022-02-12 23:45:08 +08:00
tom lee 66f169bd78 Backport 1.18 changes 2022-02-12 23:20:27 +08:00
tom lee e038861b7a Update core 2022-02-12 16:29:14 +08:00
tom lee c41fd1ab5b Backport changes from 1.16 2022-02-12 16:28:50 +08:00
James Seibel a12a55a953 Update the version number to 1.6.1a-pre and re-enable dev code 2022-02-11 22:07:58 -06:00
James Seibel 42068fc152 Update the mod homepage 2022-02-11 20:30:44 -06:00
James Seibel 791d2c881a Update the version number for 1.6.0a 2022-02-11 20:17:34 -06:00
coolGi2007 9fff802baf Fixed shadow jar problem with toml in fabric 2022-02-11 13:35:20 +00:00
coolGi2007 d5c0f714fa Added _Version to config for future me 2022-02-11 13:07:24 +00:00
tom lee 09914af897 Hotfix Forge 1.17.1 non IDE IllegalAccessError 2022-02-11 19:29:36 +08:00
tom lee 7dd57345a4 Update core + Add missing MixinChunkGenerator back. (Which fix crashes) 2022-02-11 15:48:27 +08:00
James Seibel aff52ce926 Slightly improve the tooltips for the config GUI 2022-02-10 22:08:31 -06:00
tom lee 98ed33e2bf Update core + Config + fix blindness Fog 2022-02-10 22:16:30 +08:00
tom lee d4f4e7e24d Update core 2022-02-10 17:07:33 +08:00
tom lee cfc5f4cede Update core 2022-02-10 16:14:39 +08:00
tom lee e3611b00e1 Update core + Fixed the debug button not working 2022-02-10 14:54:34 +08:00
tom lee 8f6fb9cecc Update core 2022-02-10 11:40:11 +08:00
tom lee ba3f1fd0d0 Make chunk return true on isLightCorrect same as 1.16. 2022-02-10 11:12:40 +08:00
coolGi2007 932f3ca19a Made sodium use cursedforge and added toml to core 2022-02-10 13:10:01 +10:30
tom lee 7eb4339a1b Update everything up to latest state 2022-02-09 19:04:39 +08:00
James Seibel 21fd19d8d8 Add an expiration to the archives 2022-02-05 15:43:29 +00:00
coolGi2007 cfbca82905 Removed clouds 2022-02-05 09:46:52 +00:00
tom lee 11989b310e Middle-ported the Batch Generator 2022-02-05 16:08:18 +08:00
coolGi2007 c75f50a29a Cleaned up some gradle stuff 2022-01-30 16:02:20 +10:30
coolGi2007 3a0deb5111 Down-ported everything from 1.18 to 1.17 (not including world gen) 2022-01-28 19:46:02 +10:30
coolGi2007 c2462846db Downgraded stuff from 1.18 to 1.17 2022-01-26 05:06:37 +00:00
coolGi2007 66c183ba4f Added comments to the file 2022-01-25 05:09:31 +00:00
James Seibel 3966c668d9 Delete OptiFine_1.17.1_HD_U_H1.jar 2022-01-25 01:00:04 +00:00
coolGi2007 d1cc7740d3 Fixed accsesswideners 2022-01-24 23:41:22 +10:30
coolGi2007 9586cfe90d After all these years, the ints show up correctly after restarting (it was literally a 1 line fix) 2022-01-24 19:50:32 +10:30
coolGi2007 5a8194fc0d Updated everything from 1.18 to 1.17 2022-01-24 17:50:23 +10:30
coolGi2007 15a7678da2 Downgraded stuff from 1.18 to 1.17 2022-01-21 13:12:03 +10:30
cola98765 59f7a8571f resolved warnings 2022-01-18 14:21:58 +01:00
coolGi2007 e878954763 Added 1 jar thing 2022-01-18 10:09:34 +00:00
jas35484 a07282dd36 Add the missing minor version number 1.6a -> 1.6.0a 2022-01-17 20:35:50 -06:00
jas35484 df5923ea8e Increment the version from 'a1.5.4' to 'a1.6-pre' 2022-01-17 20:26:04 -06:00
jas35484 19350cc5d4 Add .gitlab-ci.yml 2022-01-17 19:51:19 -06:00
coolGi2007 1fd639a3f7 Escape button saves config 2022-01-14 14:05:44 +10:30
tom lee 69efd93ec3 Update core + Add DisableVanillaFog for Forge 2022-01-14 00:04:20 +08:00
tom lee c7575887ea Fixed Sodium Fog 2022-01-13 20:05:04 +08:00
tom lee 7902d483ec Update core. Port back fix for onChunkLoad light issue 2022-01-12 18:02:02 +08:00
coolGi2007 2bd74d379c Fixed immersive portals with cloud rendering 2022-01-12 16:31:36 +10:30
coolGi2007 1db8d3599b Fixes all (hopefully) problems with saving the config file 2022-01-11 17:37:20 +10:30
tom lee e80ccd38fe Fixed up SodiumAccessor 2022-01-10 22:05:31 +08:00
coolGi2007 12b7723017 Added cloud warning 2022-01-10 05:12:22 +00:00
coolGi2007 51341f14a3 Updated readme since fabric version was updated 2022-01-10 14:38:49 +10:30
coolGi2007 f07783deb1 Removed forge fog renderer to fix a crash 2022-01-10 14:18:07 +10:30
coolGi2007 c7e41973d3 Update accesswidener to fox something 2022-01-09 10:39:21 +00:00
coolGi2007 f90276d8a1 Fixed everything 2022-01-09 10:18:18 +00:00
tom lee 384fe016cd Updated common 2022-01-09 17:49:46 +08:00
coolGi2007 06301a42d6 oops 2022-01-09 09:45:59 +00:00
coolGi2007 b13626689b Updated everything(need to update the sodium stuff) 2022-01-09 20:09:06 +10:30
coolGi2007 ae820320de Updated everything 2022-01-07 07:15:29 +00:00
coolGi2007 4da96d094e Update Config.java 2022-01-02 08:58:50 +00:00
coolGi2007 d8196c2069 Removed the need for any config category. The config now guesses the category 2022-01-02 06:06:44 +00:00
coolGi2007 c5e0f35a63 Reordered the forge mixin 2022-01-02 05:15:35 +00:00
coolGi2007 8a76887386 Updated core and fixed config crash 2022-01-02 03:49:50 +00:00
coolGi2007 2d495b981f Updated core 2022-01-01 22:28:57 +10:30
coolGi2007 95b5d94596 Updated stuff 2021-12-31 21:35:13 +10:30
coolGi2007 b4de7cbd0b Fixed ConfigGui 2021-12-29 05:47:09 +00:00
coolGi2007 27b4cde1dc Fixed a broken thing 2021-12-28 11:40:41 +00:00
coolGi2007 ed2b28aa30 More universal config (works with java 8 & 16) 2021-12-28 10:46:13 +00:00
84 changed files with 3508 additions and 2422 deletions
+3
View File
@@ -51,3 +51,6 @@ Merged/
# file from notepad++
*.bak
# file genearated via MC version switching using preprocessor
build.properties
+19 -86
View File
@@ -3,16 +3,9 @@ image: gradle:eclipse-temurin
# all stages need to be defined here
stages:
- gradleSetup
- build
- merge
- build_17_1
variables:
# Disable the Gradle daemon for Continuous Integration servers as correctness
# is usually a priority over speed in CI environments. Using a fresh
# runtime for each build is more reliable since the runtime is completely
# isolated from any previous builds.
GRADLE_OPTS: "-Dorg.gradle.daemon=false"
# Pull core when building
GIT_SUBMODULE_STRATEGY: recursive
@@ -23,91 +16,30 @@ before_script:
- echo GE_JOB_ID=$CI_JOB_ID >> generate_jars.env
# first stage
# This prevents us from re-downloading Gradle every stage
gradleSetup:
stage: gradleSetup
script: ./gradlew --build-cache --gradle-user-home cache/ check
# build using Java 17
image: eclipse-temurin:17
cache:
key:
files:
- gradle/wrapper/gradle-wrapper.properties
policy: push
paths:
- cache/
# second stage
build:
stage: build
script: ./gradlew build --gradle-user-home cache/
# build using Java 17
image: eclipse-temurin:17
cache:
key: "$CI_COMMIT_REF_NAME"
policy: pull-push
paths:
- .architectury-transformer
- .gradle
- build
- common/.gradle
- common/build
- core/.gradle
- core/build
- fabric/.gradle
- fabric/src/generated
- forge/.gradle
- forge/src/generated
- build
- .gradle
- cache/
# 1.17.1 build
build_17_1:
stage: build_17_1
script:
- ./gradlew deleteMerged --gradle-user-home cache/; # make sure any previously merged jars are removed before running this job
- ./gradlew build -PmcVer=1.17.1 --gradle-user-home cache/;
- ./gradlew merge --gradle-user-home cache/;
# build using Java 16
image: eclipse-temurin:16
artifacts:
name: "NightlyBuild-$CI_COMMIT_SHORT_SHA}-${CI_COMMIT_TIMESTAMP}"
paths:
# relative to the root directory
- fabric/build/libs
- forge/build/libs
exclude:
- fabric/build/libs/*-dev.jar
- fabric/build/libs/*-dev-shadow.jar
- fabric/build/libs/*-sources-dev.jar
- fabric/build/libs/*-sources.jar
- forge/build/libs/*-dev.jar
- forge/build/libs/*-dev-shadow.jar
- forge/build/libs/*-sources-dev.jar
- forge/build/libs/*-sources.jar
reports:
# To ensure we've access to these files in the next stage
dotenv: generate_jars.env
expire_in: 1 day
# third stage
merge:
stage: merge
script: ./gradlew merge --gradle-user-home cache/
# build using Java 17
image: eclipse-temurin:17
cache:
key: "$CI_COMMIT_REF_NAME"
policy: pull-push
paths:
- build
- .gradle
- cache/
artifacts:
name: "Merged_NightlyBuild-${CI_COMMIT_SHORT_SHA}-${CI_COMMIT_TIMESTAMP}"
name: "Merged_NightlyBuild_1_17_1-${CI_COMMIT_SHORT_SHA}-${CI_COMMIT_TIMESTAMP}"
paths:
# relative to the root directory
- Merged
expire_in: 1 day
cache:
key: "gradleCache"
policy: pull-push
paths:
- .gradle
- cache/
## forth stage
# unused deployment stage
#deploy:
# stage: deploy
# image: registry.gitlab.com/gitlab-org/release-cli:latest
@@ -130,3 +62,4 @@ merge:
# url: 'https://gitlab.com/jeseibel/minecraft-lod-mod/cw/-/jobs/${GE_JOB_ID}/artifacts/file/fabric/build/libs'
# - name: 'Forge Jars'
# url: 'https://gitlab.com/jeseibel/minecraft-lod-mod/cw/-/jobs/${GE_JOB_ID}/artifacts/file/forge/build/libs'
+1
View File
@@ -1,3 +1,4 @@
[submodule "core"]
path = core
url = https://gitlab.com/jeseibel/distant-horizons-core.git
branch = main
+36
View File
@@ -0,0 +1,36 @@
org.gradle.jvmargs=-Xmx2048M
minecraft_version=1.17.1
java_version=16
# Fabric loader
fabric_loader_version=0.13.2
fabric_api_version=0.46.1+1.17
# Fabric mod versions
modmenu_version=2.0.14
starlight_version_fabric=3442770
lithium_version=mc1.17.1-0.7.5
sodium_version=3605275
iris_version=1.17.x-v1.1.4
immersive_portals_version = 0.14-1.17
# Fabric mod run
# 0 = Dont enable and dont run
# 1 = Can be refranced in code but dosnt run
# 2 = Can be refranced in code and runs in client
enable_starlight=0
enable_lithium=0
enable_sodium=1
enable_iris=0
# Forge loader
forge_version=37.1.1
# Forge mod versions
starlight_version_forge=3457784
# Forge mod run
# 0 = Dont enable and dont run
# 1 = Can be refranced in code but dosnt run
# 2 = Can be refranced in code and runs in client
enable_starlight_forge=0
+47 -27
View File
@@ -1,4 +1,11 @@
# Distant Horizons
# THIS VERSION IS NO LONGER MAINTAINED! ALL DEVELOPMENT HAVE BEEN MOVED OVER TO THE MAIN BRANCH
# <img src="https://gitlab.com/jeseibel/distant-horizons-core/-/raw/main/_logo%20files/LOD%20logo%20flat%20-%20with%20boarder.png" width="32"> Distant Horizons
> A mod that adds a Level of Detail System to Minecraft
# What is Distant Horizons?
This mod adds a Level Of Detail (LOD) system to Minecraft.\
This implementation renders simplified chunks outside the normal render distance\
@@ -9,52 +16,66 @@ If you want to see a quick demo, check out a video covering the mod here:
<a href="https://www.youtube.com/watch?v=H2tnvEVbO1c" target="_blank">![Minecraft Level Of Detail (LOD) mod - Alpha 1.5](https://i.ytimg.com/vi_webp/H2tnvEVbO1c/mqdefault.webp)</a>
### Versions
Architectury version: 3.4-SNAPSHOT\
Forge version: 36.1.0\
Fabric version: 0.12.3\
Fabric API version: 0.34.2+1.16
Java Compiler plugin: Manifold Preprocessor
Modmenu version: 1.16.22\
Sodium version: mc1.16.5-0.2.0
Notes:\
This version has been confirmed to work in Eclipse and Retail Minecraft.\
(Retail running forge version 1.16.5-36.1.0 and fabric version 1.16.5-0.12.3)
#### 1.17.1 mods
Forge version: 37.1.1\
Fabric version: 0.13.2\
Fabric API version: 0.46.1+1.17\
Modmenu version: 2.0.14
## source code installation
## Source Code Installation
See the Forge Documentation online for more detailed instructions:\
http://mcforge.readthedocs.io/en/latest/gettingstarted/
See the Fabric Documentation online for more detailed instructions:\
https://fabricmc.net/wiki/tutorial:setup
### Prerequisites
* A Java Development Kit (JDK) for Java 16 (recommended) or newer. Visit https://www.oracle.com/java/technologies/downloads/ for installers.
* A Java Development Kit (JDK) for Java 17 (recommended) or newer. Visit https://www.oracle.com/java/technologies/downloads/ for installers.
* Git or someway to clone git projects. Visit https://git-scm.com/ for installers.
* (Not required) Any Java IDE, for example Intellij IDEA and Eclipse. You may also use any other code editors, such as Visual Studio Code. (Optional)
It's better to use IntelliJ IDEA since Eclipse is not supported by Architectury, but it still works.
* (Not required) Any Java IDE with plugins that support Manifold, for example Intellij IDEA.
**If using IntelliJ:**
0. Install Manifold plugin
1. open IDEA and import the build.gradle
2. refresh the Gradle project in IDEA if required
**If using Ecplise:**
Not supported...
**If using Ecplise: (Note that Eclispe currently 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
Side note: invalidate caches and restart if required
## Switching Versions
This branch support 1 built versions:
- 1.17.1 (which also runs on 1.17)
To switch between active versions, change `mcVer=1.17.?` in `gradle.properties` file.
If running on IDE, to ensure IDE pickup the changed versions, you will need to run a gradle command again to allow gradle to update all the libs. (In IntellJ you will also need to do a gradle sync again if it didn't start it automatically.)
>Note: There may be a `java.nio.file.FileSystemException` thrown on running the command after switching versions. To fix it, either restart your IDE (as your IDE is locking up a file) or use tools like LockHunter to unlock the linked file. (Often a lib file under `common\build\lib` or `forge\build\lib` or `fabric\build\lib`). If anyone knows how to solve this issue please comment to this issue: https://gitlab.com/jeseibel/minecraft-lod-mod/-/issues/233
## Compiling
**Using GUI**
1. Open a command line in the project folder
2. Run the command: `./gradlew build`
3. The compiled jar file will be in the folder `fabric/build/libs/` and `forge/build/libs/`
1. Download the zip of the project and extract it
2. Download the core from https://gitlab.com/jeseibel/distant-horizons-core and extract into a folder called `core`
3. Open a command line in the project folder
4. Run the command: `./gradlew assemble`
5. Then run command: `./gradlew mergeJars`
6. The compiled jar file will be in the folder `Merged`
**If in terminal:**
1. `git clone -b 1.16.5_architectury --recurse-submodules https://gitlab.com/jeseibel/minecraft-lod-mod.git`
1. `git clone -b preprocessor_test --recurse-submodules https://gitlab.com/jeseibel/minecraft-lod-mod.git`
2. `cd minecraft-lod-mod`
3. `./gradlew assemble` or `./gradlew build`
4. The build should be in `fabric/build/libs/` and `forge/build/libs/`
3. `./gradlew assemble`
4. `./gradlew mergeJars`
5. The compiled jar file will be in the folder `Merged`
>Note: You can add the arg: `-PmcVer=1.17.?` to tell gradle to build a selected MC version instead of having to manually modify the `gradle.properties` file.
## Other commands
@@ -75,8 +96,7 @@ Source code uses Mojang mappings.
Build only Fabric: `./gradlew fabric:assemble` or `./gradlew fabric:build`\
Build only Forge: `./gradlew fabric:assemble` or `./gradlew forge:build`\
Run the Fabric client (for debugging): `./gradlew fabric:runClient`\
Run the Forge client (**THIS DOST WORK** due to a bug with architectury): `./gradlew forge:runClient`\
To use a custom version of Java use `-D` then the path for Java
Run the Forge client (for debugging): `./gradlew forge:runClient`
## Open Source Acknowledgements
+102 -9
View File
@@ -1,5 +1,6 @@
import io.github.ran.jarmerger.JarMergerPlugin
buildscript {
dependencies{
classpath files('plugins/DHJarMerger-1.0.jar')
@@ -8,9 +9,34 @@ buildscript {
plugins {
id "architectury-plugin" version "3.4-SNAPSHOT"
id "dev.architectury.loom" version "0.10.0-SNAPSHOT" apply false
id "dev.architectury.loom" version "0.10.0.195" apply false
}
def writeBuildGradlePredefine() {
def excapedMCVersion = rootProject.minecraft_version.replace(".", "_")
new File(projectDir, "build.properties").text = "MC_VERSION_${excapedMCVersion}=\n"
}
def loadProperties() {
def defaultMcVersion = '1.17.1'
if (!project.hasProperty("mcVer")) {
println "No mcVer set! Defaulting to ${defaultMcVersion}."
println "Tip: Use -PmcVer='${defaultMcVersion}' in cmd arg to set mcVer."
}
def mcVersion = project.hasProperty("mcVer") ? mcVer : defaultMcVersion
println "Loading properties file at " + mcVersion + ".properties"
def props = new Properties()
props.load(new FileInputStream("$rootProject.rootDir/"+"$mcVersion"+".properties"))
props.each { prop ->
rootProject.ext.set(prop.key, prop.value)
// println "Added prop [key:" + prop.key + ", value:" + prop.value + "]"
}
writeBuildGradlePredefine()
}
loadProperties()
apply plugin: JarMergerPlugin
architectury {
@@ -35,6 +61,9 @@ subprojects { p ->
// The following line declares the mojmap mappings
mappings loom.officialMojangMappings()
//Manifold
annotationProcessor "systems.manifold:manifold-preprocessor:${rootProject.manifold_version}"
// Toml
implementation("com.electronwill.night-config:toml:${rootProject.toml_version}")
@@ -50,6 +79,14 @@ subprojects { p ->
shadowMe(project(":core")) { transitive false }
}
}
jar {
manifest {
attributes 'Implementation-Title': rootProject.archives_base_name,
'Implementation-Version': rootProject.mod_version,
'Main-Class': 'com.seibel.lod.core.JarMain'
}
}
}
allprojects {
@@ -66,6 +103,9 @@ allprojects {
// used to download and compile dependencies from git repos
maven { url 'https://jitpack.io' }
// For Manifold Preprocessor
maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }
// Required for importing Modrinth mods
maven {
name = "Modrinth"
@@ -98,19 +138,72 @@ allprojects {
}
}
tasks.withType(JavaCompile) {
options.encoding = "UTF-8"
// Put stuff from gradle.properties into the mod info
processResources {
def resourceTargets = ["fabric.mod.json", "META-INF/mods.toml"] // Location of where to put
def intoTargets = ["$buildDir/resources/main/"] // Location of the built resources folder
def replaceProperties = [
version: mod_version,
mod_name: mod_name,
authors: mod_authors,
description: mod_description,
homepage: mod_homepage,
source: mod_source,
issues: mod_issues,
minecraft_version: minecraft_version,
java_version: java_version
] // The left side is what gets replaced in the mod info and the right side is where to get it from in the gradle.properties
//TODO: Make Forge loader version also be relaced with non hardcoded value instead of "[36,41)"
// The Minecraft launcher currently installs Java 8 for users, so your mod probably wants to target Java 8 too
// JDK 9 introduced a new way of specifying this that will make sure no newer classes or methods are used.
// We'll use that if it's available, but otherwise we'll use the older option.
def targetVersion = 8
if (JavaVersion.current().isJava9Compatible()) {
options.release = targetVersion
inputs.properties replaceProperties
replaceProperties.put 'project', project
filesMatching(resourceTargets) {
expand replaceProperties
}
intoTargets.each { target ->
if (file(target).exists()) {
copy {
from(sourceSets.main.resources) {
include resourceTargets
expand replaceProperties
}
into target
}
}
}
}
tasks.withType(JavaCompile) {
// // Add Manifold Preprocessor
//// def excapedMCVersion = rootProject.minecraft_version.replace(".", "_")
//// options.compilerArgs += ['-Xplugin:Manifold', "-AMC_VERSION_${excapedMCVersion}"]
////
// //options.compilerArgs += ['-deprecation']
// //options.compilerArgs += ['-verbose']
// //options.compilerArgs += ['-Xlint:unchecked']
// //options.compilerArgs += ['-Xdiags:verbose']
// //options.compilerArgs += ['-Xprint']
// //options.compilerArgs += ['-XprintProcessorInfo']
// //options.compilerArgs += ['-XprintRounds']
//
// // println options.compilerArgs
// if (p != project(":core")) {
// options.compilerArgs += ['-Xplugin:Manifold']
// options.release = rootProject.java_version as Integer
// }
options.encoding = "UTF-8"
options.release = 16
}
java {
withSourcesJar()
}
}
// this deletes the merged folder so we don't carry over
// the previous merges to each new build job in the CI/CD pipeline
task deleteMerged(type: Delete) {
delete files("./Merged")
}
@@ -26,8 +26,12 @@ import com.seibel.lod.core.enums.rendering.*;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton.IClient.IAdvanced.*;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton.IClient.IGraphics.*;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton.IClient.IGraphics.IFogQuality.IAdvancedFog;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton.IClient.IGraphics.IFogQuality.IAdvancedFog.IHeightFog;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton.IClient.IMultiplayer;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton.IClient.IWorldGenerator;
import net.minecraft.client.renderer.DimensionSpecialEffects;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton.IClient.IAdvanced;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton.IClient.IAdvanced.IDebugging.*;
/**
* This handles any configuration the user has access to.
@@ -65,20 +69,21 @@ public class Config extends ConfigGui
@ConfigAnnotations.Entry
public static boolean optionsButton = true;
public static class Client
{
public static class Client {
@ConfigAnnotations.ScreenEntry
public static Graphics graphics;
@ConfigAnnotations.ScreenEntry
public static WorldGenerator worldGenerator;
@ConfigAnnotations.ScreenEntry
public static Multiplayer multiplayer;
@ConfigAnnotations.ScreenEntry
public static Advanced advanced;
public static class Graphics
{
public static class Graphics {
@ConfigAnnotations.ScreenEntry
public static Quality quality;
@@ -89,8 +94,7 @@ public class Config extends ConfigGui
public static AdvancedGraphics advancedGraphics;
public static class Quality
{
public static class Quality {
@ConfigAnnotations.FileComment
public static String _drawResolution = IQuality.DRAW_RESOLUTION_DESC;
@ConfigAnnotations.Entry
@@ -120,11 +124,15 @@ public class Config extends ConfigGui
public static String _dropoffQuality = IQuality.DROPOFF_QUALITY_DESC;
@ConfigAnnotations.Entry
public static DropoffQuality dropoffQuality = IQuality.DROPOFF_QUALITY_DEFAULT;
@ConfigAnnotations.FileComment
public static String _lodBiomeBlending = IQuality.LOD_BIOME_BLENDING_DESC;
@ConfigAnnotations.Entry(minValue = 0, maxValue = 7)
public static int lodBiomeBlending = IQuality.LOD_BIOME_BLENDING_MIN_DEFAULT_MAX.defaultValue;
}
public static class FogQuality
{
public static class FogQuality {
@ConfigAnnotations.FileComment
public static String _fogDistance = IFogQuality.FOG_DISTANCE_DESC;
@ConfigAnnotations.Entry
@@ -144,11 +152,97 @@ public class Config extends ConfigGui
public static String _disableVanillaFog = IFogQuality.DISABLE_VANILLA_FOG_DESC;
@ConfigAnnotations.Entry
public static boolean disableVanillaFog = IFogQuality.DISABLE_VANILLA_FOG_DEFAULT;
@ConfigAnnotations.ScreenEntry
public static AdvancedFog advancedFog;
public static class AdvancedFog {
static final double SQRT2 = 1.4142135623730951;
@ConfigAnnotations.FileComment
public static String _farFogStart = IAdvancedFog.FAR_FOG_START_DESC;
@ConfigAnnotations.Entry(minValue = 0.0, maxValue = SQRT2)
public static double farFogStart = IAdvancedFog.FAR_FOG_START_MIN_DEFAULT_MAX.defaultValue;
@ConfigAnnotations.FileComment
public static String _farFogEnd = IAdvancedFog.FAR_FOG_END_DESC;
@ConfigAnnotations.Entry(minValue = 0.0, maxValue = SQRT2)
public static double farFogEnd = IAdvancedFog.FAR_FOG_END_MIN_DEFAULT_MAX.defaultValue;
@ConfigAnnotations.FileComment
public static String _farFogMin = IAdvancedFog.FAR_FOG_MIN_DESC;
@ConfigAnnotations.Entry(minValue = -5.0, maxValue = SQRT2)
public static double farFogMin = IAdvancedFog.FAR_FOG_MIN_MIN_DEFAULT_MAX.defaultValue;
@ConfigAnnotations.FileComment
public static String _farFogMax = IAdvancedFog.FAR_FOG_MAX_DESC;
@ConfigAnnotations.Entry(minValue = 0.0, maxValue = 5.0)
public static double farFogMax = IAdvancedFog.FAR_FOG_MAX_MIN_DEFAULT_MAX.defaultValue;
@ConfigAnnotations.FileComment
public static String _farFogType = IAdvancedFog.FAR_FOG_TYPE_DESC;
@ConfigAnnotations.Entry
public static FogSetting.FogType farFogType = IAdvancedFog.FAR_FOG_TYPE_DEFAULT;
@ConfigAnnotations.FileComment
public static String _farFogDensity = IAdvancedFog.FAR_FOG_DENSITY_DESC;
@ConfigAnnotations.Entry(minValue = 0.01, maxValue = 50.0)
public static double farFogDensity = IAdvancedFog.FAR_FOG_DENSITY_MIN_DEFAULT_MAX.defaultValue;
@ConfigAnnotations.ScreenEntry
public static HeightFog heightFog;
public static class HeightFog {
@ConfigAnnotations.FileComment
public static String _heightFogMixMode = IHeightFog.HEIGHT_FOG_MIX_MODE_DESC;
@ConfigAnnotations.Entry
public static HeightFogMixMode heightFogMixMode = IHeightFog.HEIGHT_FOG_MIX_MODE_DEFAULT;
@ConfigAnnotations.FileComment
public static String _heightFogMode = IHeightFog.HEIGHT_FOG_MODE_DESC;
@ConfigAnnotations.Entry
public static HeightFogMode heightFogMode = IHeightFog.HEIGHT_FOG_MODE_DEFAULT;
@ConfigAnnotations.FileComment
public static String _heightFogHeight = IHeightFog.HEIGHT_FOG_HEIGHT_DESC;
@ConfigAnnotations.Entry(minValue = -4096.0, maxValue = 4096.0)
public static double heightFogHeight = IHeightFog.HEIGHT_FOG_HEIGHT_MIN_DEFAULT_MAX.defaultValue;
@ConfigAnnotations.FileComment
public static String _heightFogStart = IHeightFog.HEIGHT_FOG_START_DESC;
@ConfigAnnotations.Entry(minValue = 0.0, maxValue = SQRT2)
public static double heightFogStart = IHeightFog.HEIGHT_FOG_START_MIN_DEFAULT_MAX.defaultValue;
@ConfigAnnotations.FileComment
public static String _heightFogEnd = IHeightFog.HEIGHT_FOG_END_DESC;
@ConfigAnnotations.Entry(minValue = 0.0, maxValue = SQRT2)
public static double heightFogEnd = IHeightFog.HEIGHT_FOG_END_MIN_DEFAULT_MAX.defaultValue;
@ConfigAnnotations.FileComment
public static String _heightFogMin = IHeightFog.HEIGHT_FOG_MIN_DESC;
@ConfigAnnotations.Entry(minValue = -5.0, maxValue = SQRT2)
public static double heightFogMin = IHeightFog.HEIGHT_FOG_MIN_MIN_DEFAULT_MAX.defaultValue;
@ConfigAnnotations.FileComment
public static String _heightFogMax = IHeightFog.HEIGHT_FOG_MAX_DESC;
@ConfigAnnotations.Entry(minValue = 0.0, maxValue = 5.0)
public static double heightFogMax = IHeightFog.HEIGHT_FOG_MAX_MIN_DEFAULT_MAX.defaultValue;
@ConfigAnnotations.FileComment
public static String _heightFogType = IHeightFog.HEIGHT_FOG_TYPE_DESC;
@ConfigAnnotations.Entry
public static FogSetting.FogType heightFogType = IHeightFog.HEIGHT_FOG_TYPE_DEFAULT;
@ConfigAnnotations.FileComment
public static String _heightFogDensity = IHeightFog.HEIGHT_FOG_DENSITY_DESC;
@ConfigAnnotations.Entry(minValue = 0.01, maxValue = 50.0)
public static double heightFogDensity = IHeightFog.HEIGHT_FOG_DENSITY_MIN_DEFAULT_MAX.defaultValue;
}
}
}
public static class AdvancedGraphics
{
public static class AdvancedGraphics {
@ConfigAnnotations.FileComment
public static String _disableDirectionalCulling = IAdvancedGraphics.DISABLE_DIRECTIONAL_CULLING_DESC;
@ConfigAnnotations.Entry
@@ -159,11 +253,36 @@ public class Config extends ConfigGui
@ConfigAnnotations.Entry
public static VanillaOverdraw vanillaOverdraw = IAdvancedGraphics.VANILLA_OVERDRAW_DEFAULT;
@ConfigAnnotations.FileComment
public static String _overdrawOffset = IAdvancedGraphics.OVERDRAW_OFFSET_DESC;
@ConfigAnnotations.Entry(minValue = -16, maxValue = 16)
public static int overdrawOffset = IAdvancedGraphics.OVERDRAW_OFFSET_MIN_DEFAULT_MAX.defaultValue;
@ConfigAnnotations.FileComment
public static String _useExtendedNearClipPlane = IAdvancedGraphics.USE_EXTENDED_NEAR_CLIP_PLANE_DESC;
@ConfigAnnotations.Entry
public static boolean useExtendedNearClipPlane = IAdvancedGraphics.USE_EXTENDED_NEAR_CLIP_PLANE_DEFAULT;
@ConfigAnnotations.FileComment
public static String _brightnessMultiplier = IAdvancedGraphics.BRIGHTNESS_MULTIPLIER_DESC;
@ConfigAnnotations.Entry
public static double brightnessMultiplier = IAdvancedGraphics.BRIGHTNESS_MULTIPLIER_DEFAULT;
@ConfigAnnotations.FileComment
public static String _saturationMultiplier = IAdvancedGraphics.SATURATION_MULTIPLIER_DESC;
@ConfigAnnotations.Entry
public static double saturationMultiplier = IAdvancedGraphics.SATURATION_MULTIPLIER_DEFAULT;
@ConfigAnnotations.FileComment
public static String _enableCaveCulling = IAdvancedGraphics.ENABLE_CAVE_CULLING_DESC;
@ConfigAnnotations.Entry
public static boolean enableCaveCulling = IAdvancedGraphics.ENABLE_CAVE_CULLING_DEFAULT;
@ConfigAnnotations.FileComment
public static String _caveCullingHeight = IAdvancedGraphics.CAVE_CULLING_HEIGHT_DESC;
@ConfigAnnotations.Entry(minValue = -4096, maxValue = 4096)
public static int caveCullingHeight = IAdvancedGraphics.CAVE_CULLING_HEIGHT_MIN_DEFAULT_MAX.defaultValue;
/*
@ConfigAnnotations.FileComment
public static String _backsideCullingRange = IAdvancedGraphics.VANILLA_CULLING_RANGE_DESC;
@@ -174,8 +293,7 @@ public class Config extends ConfigGui
}
public static class WorldGenerator
{
public static class WorldGenerator {
@ConfigAnnotations.FileComment
public static String _enableDistantGeneration = IWorldGenerator.ENABLE_DISTANT_GENERATION_DESC;
@ConfigAnnotations.Entry
@@ -199,8 +317,9 @@ public class Config extends ConfigGui
/*
@ConfigAnnotations.FileComment
public static String _allowUnstableFeatureGeneration = IWorldGenerator.ALLOW_UNSTABLE_FEATURE_GENERATION_DESC;
// FIXME: Temperary override. In 1.18, the newer Unstable gnerator is more usable
@ConfigAnnotations.Entry
public static boolean allowUnstableFeatureGeneration = IWorldGenerator.ALLOW_UNSTABLE_FEATURE_GENERATION_DEFAULT;
public static boolean allowUnstableFeatureGeneration = true;//IWorldGenerator.ALLOW_UNSTABLE_FEATURE_GENERATION_DEFAULT;
*/
@ConfigAnnotations.FileComment
@@ -209,8 +328,21 @@ public class Config extends ConfigGui
public static BlocksToAvoid blocksToAvoid = IWorldGenerator.BLOCKS_TO_AVOID_DEFAULT;
}
public static class Advanced
{
public static class Multiplayer {
@ConfigAnnotations.FileComment
public static String _serverFolderNameMode = IMultiplayer.SERVER_FOLDER_NAME_MODE_DESC;
@ConfigAnnotations.Entry
public static ServerFolderNameMode serverFolderNameMode = IMultiplayer.SERVER_FOLDER_NAME_MODE_DEFAULT;
@ConfigAnnotations.FileComment
public static String _multiDimensionRequiredSimilarity = IMultiplayer.MULTI_DIMENSION_REQUIRED_SIMILARITY_DESC;
@ConfigAnnotations.Entry(minValue = 0.0, maxValue = 1.0)
public static double multiDimensionRequiredSimilarity = IMultiplayer.MULTI_DIMENSION_REQUIRED_SIMILARITY_MIN_DEFAULT_MAX.defaultValue;
}
public static class Advanced {
@ConfigAnnotations.ScreenEntry
public static Threading threading;
@@ -220,9 +352,13 @@ public class Config extends ConfigGui
@ConfigAnnotations.ScreenEntry
public static Buffers buffers;
@ConfigAnnotations.FileComment
public static String _lodOnlyMode = IAdvanced.LOD_ONLY_MODE_DESC;
@ConfigAnnotations.Entry
public static boolean lodOnlyMode = IAdvanced.LOD_ONLY_MODE_DEFAULT;
public static class Threading
{
public static class Threading {
@ConfigAnnotations.FileComment
public static String _numberOfWorldGenerationThreads = IThreading.NUMBER_OF_WORLD_GENERATION_THREADS_DESC;
@ConfigAnnotations.Entry(minValue = 1, maxValue = 50)
@@ -235,12 +371,11 @@ public class Config extends ConfigGui
}
public static class Debugging
{
public static class Debugging {
@ConfigAnnotations.FileComment
public static String _drawLods = IDebugging.DRAW_LODS_DESC;
public static String _rendererType = IDebugging.RENDERER_TYPE_DESC;
@ConfigAnnotations.Entry
public static boolean drawLods = IDebugging.DRAW_LODS_DEFAULT;
public static RendererType rendererType = IDebugging.RENDERER_TYPE_DEFAULT;
@ConfigAnnotations.FileComment
public static String _debugMode = IDebugging.DEBUG_MODE_DESC;
@@ -254,8 +389,69 @@ public class Config extends ConfigGui
}
public static class Buffers
{
@ConfigAnnotations.ScreenEntry
public static DebugSwitch debugSwitch;
public static class DebugSwitch {
/* The logging switches available:
* WorldGenEvent
* WorldGenPerformance
* WorldGenLoadEvent
* LodBuilderEvent
* RendererBufferEvent
* RendererGLEvent
* FileReadWriteEvent
* FileSubDimEvent
* NetworkEvent //NOT IMPL YET
*/
@ConfigAnnotations.FileComment
public static String _logWorldGenEvent = IDebugSwitch.LOG_WORLDGEN_EVENT_DESC;
@ConfigAnnotations.Entry
public static LoggerMode logWorldGenEvent = IDebugSwitch.LOG_WORLDGEN_EVENT_DEFAULT;
@ConfigAnnotations.FileComment
public static String _logWorldGenPerformance = IDebugSwitch.LOG_WORLDGEN_PERFORMANCE_DESC;
@ConfigAnnotations.Entry
public static LoggerMode logWorldGenPerformance = IDebugSwitch.LOG_WORLDGEN_PERFORMANCE_DEFAULT;
@ConfigAnnotations.FileComment
public static String _logWorldGenLoadEvent = IDebugSwitch.LOG_WORLDGEN_LOAD_EVENT_DESC;
@ConfigAnnotations.Entry
public static LoggerMode logWorldGenLoadEvent = IDebugSwitch.LOG_WORLDGEN_LOAD_EVENT_DEFAULT;
@ConfigAnnotations.FileComment
public static String _logLodBuilderEvent = IDebugSwitch.LOG_LODBUILDER_EVENT_DESC;
@ConfigAnnotations.Entry
public static LoggerMode logLodBuilderEvent = IDebugSwitch.LOG_LODBUILDER_EVENT_DEFAULT;
@ConfigAnnotations.FileComment
public static String _logRendererBufferEvent = IDebugSwitch.LOG_RENDERER_BUFFER_EVENT_DESC;
@ConfigAnnotations.Entry
public static LoggerMode logRendererBufferEvent = IDebugSwitch.LOG_RENDERER_BUFFER_EVENT_DEFAULT;
@ConfigAnnotations.FileComment
public static String _logRendererGLEvent = IDebugSwitch.LOG_RENDERER_GL_EVENT_DESC;
@ConfigAnnotations.Entry
public static LoggerMode logRendererGLEvent = IDebugSwitch.LOG_RENDERER_GL_EVENT_DEFAULT;
@ConfigAnnotations.FileComment
public static String _logFileReadWriteEvent = IDebugSwitch.LOG_FILE_READWRITE_EVENT_DESC;
@ConfigAnnotations.Entry
public static LoggerMode logFileReadWriteEvent = IDebugSwitch.LOG_FILE_READWRITE_EVENT_DEFAULT;
@ConfigAnnotations.FileComment
public static String _logFileSubDimEvent = IDebugSwitch.LOG_FILE_SUB_DIM_EVENT_DESC;
@ConfigAnnotations.Entry
public static LoggerMode logFileSubDimEvent = IDebugSwitch.LOG_FILE_SUB_DIM_EVENT_DEFAULT;
@ConfigAnnotations.FileComment
public static String _logNetworkEvent = IDebugSwitch.LOG_NETWORK_EVENT_DESC;
@ConfigAnnotations.Entry
public static LoggerMode logNetworkEvent = IDebugSwitch.LOG_NETWORK_EVENT_DEFAULT;
}
public static class Buffers {
@ConfigAnnotations.FileComment
public static String _gpuUploadMethod = IBuffers.GPU_UPLOAD_METHOD_DESC;
@ConfigAnnotations.Entry
@@ -263,7 +459,7 @@ public class Config extends ConfigGui
@ConfigAnnotations.FileComment
public static String _gpuUploadPerMegabyteInMilliseconds = IBuffers.GPU_UPLOAD_PER_MEGABYTE_IN_MILLISECONDS_DESC;
@ConfigAnnotations.Entry(minValue = 0, maxValue = 50)
@ConfigAnnotations.Entry(minValue = 0, maxValue = 5000)
public static int gpuUploadPerMegabyteInMilliseconds = IBuffers.GPU_UPLOAD_PER_MEGABYTE_IN_MILLISECONDS_DEFAULT.defaultValue;
@ConfigAnnotations.FileComment
@@ -4,7 +4,6 @@ import com.seibel.lod.common.forge.LodForgeMethodCaller;
import com.seibel.lod.common.networking.NetworkInterface;
import com.seibel.lod.common.wrappers.DependencySetup;
import com.seibel.lod.common.wrappers.config.ConfigGui;
import com.seibel.lod.core.ModInfo;
/**
* This is the common main class
@@ -1,7 +1,8 @@
package com.seibel.lod.common.forge;
import com.seibel.lod.common.wrappers.minecraft.MinecraftWrapper;
import com.seibel.lod.common.wrappers.minecraft.MinecraftClientWrapper;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.core.Direction;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
@@ -15,5 +16,6 @@ import java.util.Random;
* @author Ran
*/
public interface LodForgeMethodCaller {
List<BakedQuad> getQuads(MinecraftWrapper mc, Block block, BlockState blockState, Direction direction, Random random);
List<BakedQuad> getQuads(MinecraftClientWrapper mc, Block block, BlockState blockState, Direction direction, Random random);
int getPixelRGBA(TextureAtlasSprite sprite, int frameIndex, int x, int y);
}
@@ -1,11 +1,8 @@
package com.seibel.lod.common.networking;
import com.seibel.lod.common.LodCommonMain;
import io.netty.buffer.Unpooled;
import net.minecraft.network.FriendlyByteBuf;
import java.nio.charset.StandardCharsets;
/**
* This class holds most of the networking code for the mod.
* @author Ran
@@ -1,17 +1,15 @@
package com.seibel.lod.common.wrappers;
import com.seibel.lod.common.LodCommonMain;
import com.seibel.lod.common.wrappers.block.BlockColorSingletonWrapper;
import com.seibel.lod.common.wrappers.minecraft.MinecraftRenderWrapper;
import com.seibel.lod.common.wrappers.minecraft.MinecraftWrapper;
import com.seibel.lod.common.wrappers.minecraft.MinecraftClientWrapper;
import com.seibel.lod.core.handlers.IReflectionHandler;
import com.seibel.lod.core.handlers.ReflectionHandler;
import com.seibel.lod.core.util.SingletonHandler;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.wrapperInterfaces.IVersionConstants;
import com.seibel.lod.core.wrapperInterfaces.IWrapperFactory;
import com.seibel.lod.core.wrapperInterfaces.block.IBlockColorSingletonWrapper;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftWrapper;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
/**
* Binds all necessary dependencies, so we
@@ -25,13 +23,13 @@ import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftWrapper;
*/
public class DependencySetup {
public static void createInitialBindings() {
SingletonHandler.bind(IBlockColorSingletonWrapper.class, BlockColorSingletonWrapper.INSTANCE);
SingletonHandler.bind(IVersionConstants.class, VersionConstants.INSTANCE);
if (!LodCommonMain.serverSided) {
SingletonHandler.bind(IMinecraftWrapper.class, MinecraftWrapper.INSTANCE);
SingletonHandler.bind(IMinecraftClientWrapper.class, MinecraftClientWrapper.INSTANCE);
SingletonHandler.bind(IMinecraftRenderWrapper.class, MinecraftRenderWrapper.INSTANCE);
SingletonHandler.bind(IReflectionHandler.class, ReflectionHandler.createSingleton(MinecraftWrapper.INSTANCE.getOptions().getClass().getDeclaredFields(), MinecraftWrapper.INSTANCE.getOptions()));
SingletonHandler.bind(IVersionConstants.class, VersionConstants.INSTANCE);
SingletonHandler.bind(IReflectionHandler.class, ReflectionHandler.createSingleton(MinecraftClientWrapper.INSTANCE.getOptions().getClass().getDeclaredFields(), MinecraftClientWrapper.INSTANCE.getOptions()));
}
SingletonHandler.bind(IWrapperFactory.class, WrapperFactory.INSTANCE);
DependencySetupDoneCheck.isDone = true;
}
}
@@ -0,0 +1,8 @@
package com.seibel.lod.common.wrappers;
import java.util.function.Supplier;
public class DependencySetupDoneCheck {
public static boolean isDone = false;
public static Supplier<Boolean> getIsCurrentThreadDistantGeneratorThread = (() -> {return false;});
}
@@ -24,7 +24,9 @@ import java.nio.FloatBuffer;
import com.mojang.math.Matrix4f;
import com.seibel.lod.core.enums.LodDirection;
import com.seibel.lod.core.objects.math.Mat4f;
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
/**
@@ -47,8 +49,29 @@ public class McObjectConverter
}
static final Direction[] directions;
static final LodDirection[] lodDirections;
static {
LodDirection[] lodDirs = LodDirection.values();
directions = new Direction[lodDirs.length];
lodDirections = new LodDirection[lodDirs.length];
for (LodDirection lodDir : lodDirs) {
Direction dir = Direction.byName(lodDir.name());
directions[lodDir.ordinal()] = dir;
lodDirections[dir.ordinal()] = lodDir;
}
}
public static BlockPos Convert(AbstractBlockPosWrapper wrappedPos) {
return new BlockPos(wrappedPos.getX(),wrappedPos.getY(), wrappedPos.getZ());
}
public static Direction Convert(LodDirection lodDirection)
{
return Direction.byName(lodDirection.name());
return directions[lodDirection.ordinal()];
}
public static LodDirection Convert(Direction direction)
{
return lodDirections[direction.ordinal()];
}
}
@@ -5,7 +5,7 @@ import com.seibel.lod.core.wrapperInterfaces.IVersionConstants;
/**
* @author James Seibel
* @version 12-11-2021
* @version 3-3-2022
*/
public class VersionConstants implements IVersionConstants {
public static final VersionConstants INSTANCE = new VersionConstants();
@@ -21,35 +21,14 @@ public class VersionConstants implements IVersionConstants {
return 0;
}
@Override
public boolean isWorldGeneratorSingleThreaded(DistanceGenerationMode distanceGenerationMode) {
// We are always asking the server to generate the chunk,
// so no use running this stuff multithreaded.
return true;
/*
switch (distanceGenerationMode) {
default:
case NONE:
case BIOME_ONLY:
case BIOME_ONLY_SIMULATE_HEIGHT:
case SURFACE:
case FEATURES:
return false;
case FULL:
return true;
}
*/
}
@Override
public int getWorldGenerationCountPerThread() {
return 1;
}
@Override
public boolean hasBatchGenerationImplementation() {
return true;
public boolean isVanillaRenderedChunkSquare()
{
return false;
}
}
@@ -26,11 +26,9 @@ import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
import com.seibel.lod.core.wrapperInterfaces.chunk.AbstractChunkPosWrapper;
import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
import com.seibel.lod.core.wrapperInterfaces.worldGeneration.AbstractBatchGenerationEnvionmentWrapper;
import com.seibel.lod.core.wrapperInterfaces.worldGeneration.AbstractWorldGeneratorWrapper;
import com.seibel.lod.common.wrappers.block.BlockPosWrapper;
import com.seibel.lod.common.wrappers.chunk.ChunkPosWrapper;
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment;
import com.seibel.lod.common.wrappers.worldGeneration.WorldGeneratorWrapper;
/**
* This handles creating abstract wrapper objects.
@@ -76,15 +74,10 @@ public class WrapperFactory implements IWrapperFactory {
public AbstractChunkPosWrapper createChunkPos(AbstractBlockPosWrapper blockPos) {
return new ChunkPosWrapper(blockPos);
}
@Override
public AbstractWorldGeneratorWrapper createWorldGenerator(LodBuilder newLodBuilder, LodDimension newLodDimension, IWorldWrapper worldWrapper) {
return new WorldGeneratorWrapper(newLodBuilder, newLodDimension, worldWrapper);
}
@Override
public AbstractBatchGenerationEnvionmentWrapper createBatchGenerator(LodBuilder newLodBuilder, LodDimension newLodDimension, IWorldWrapper worldWrapper) {
public AbstractBatchGenerationEnvionmentWrapper createBatchGenerator(LodBuilder newLodBuilder,
LodDimension newLodDimension, IWorldWrapper worldWrapper) {
return new BatchGenerationEnvironment(worldWrapper, newLodBuilder, newLodDimension);
}
}
@@ -1,46 +0,0 @@
/*
* This file is part of the Distant Horizon mod (formerly the LOD Mod),
* licensed under the GNU GPL 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 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.lod.common.wrappers.block;
import com.seibel.lod.core.wrapperInterfaces.block.IBlockColorSingletonWrapper;
import com.seibel.lod.core.wrapperInterfaces.block.IBlockColorWrapper;
import net.minecraft.world.level.block.Blocks;
/**
* Contains methods that would have been static in BlockColorWrapper.
* Since interfaces can't create/implement static methods we have
* to split the object up in two.
*
* @author James Seibel
* @version 11-17-2021
*/
public class BlockColorSingletonWrapper implements IBlockColorSingletonWrapper
{
public static final BlockColorSingletonWrapper INSTANCE = new BlockColorSingletonWrapper();
@Override
public IBlockColorWrapper getWaterColor()
{
return BlockColorWrapper.getBlockColorWrapper(Blocks.WATER);
}
}
@@ -1,329 +0,0 @@
package com.seibel.lod.common.wrappers.block;
import java.util.List;
import java.util.Objects;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import com.seibel.lod.common.LodCommonMain;
import com.seibel.lod.common.wrappers.minecraft.MinecraftWrapper;
import com.seibel.lod.core.util.ColorUtil;
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
import com.seibel.lod.core.wrapperInterfaces.block.IBlockColorWrapper;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.core.Direction;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.BushBlock;
import net.minecraft.world.level.block.FlowerBlock;
import net.minecraft.world.level.block.GrassBlock;
import net.minecraft.world.level.block.LeavesBlock;
import net.minecraft.world.level.block.TallGrassBlock;
import net.minecraft.world.level.block.state.BlockState;
/**
* @author James Seibel
* @version 11-21-2021
*/
public class BlockColorWrapper implements IBlockColorWrapper
{
//set of block which require tint
public static final ConcurrentMap<Block, BlockColorWrapper> blockColorWrapperMap = new ConcurrentHashMap<>();
// public static final ModelDataMap dataMap = new ModelDataMap.Builder().build();
public static final AbstractBlockPosWrapper blockPos = new BlockPosWrapper(0, 0, 0);
public static final Random random = new Random(0);
//public static BlockColourWrapper WATER_COLOR = getBlockColorWrapper(Blocks.WATER);
public static final Direction[] directions = new Direction[] { Direction.UP, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.NORTH, Direction.DOWN };
private final Block block;
private int color;
private boolean isColored;
private boolean toTint;
private boolean foliageTint;
private boolean grassTint;
private boolean waterTint;
/**Constructor only require for the block instance we are wrapping**/
public BlockColorWrapper(Block block)
{
this.block = block;
this.color = 0;
this.isColored = true;
this.toTint = false;
this.foliageTint = false;
this.grassTint = false;
this.waterTint = false;
setupColorAndTint();
/*StringBuilder s = new StringBuilder();
s.append(block + "\n"
+ Integer.toHexString(
Minecraft.getInstance().getBlockColors().createDefault().getColor(
block.defaultBlockState(),
(World) MinecraftWrapper.INSTANCE.getWrappedServerLevel().getLevel(),
blockPosWrapper.getBlockPos())) + "\n"
);
for(Property x : Minecraft.getInstance().getBlockColors().getColoringProperties(block))
s.append(x.getName() + " " + x.getPossibleValues() + '\n');
System.out.println(s);*/
//System.out.println(block + " color " + Integer.toHexString(color) + " to tint " + toTint + " folliageTint " + folliageTint + " grassTint " + grassTint + " waterTint " + waterTint);
}
/**
* this return a wrapper of the block in input
* @param block object of the block to wrap
*/
public static IBlockColorWrapper getBlockColorWrapper(Block block)
{
//first we check if the block has already been wrapped
if (blockColorWrapperMap.containsKey(block) && blockColorWrapperMap.get(block) != null)
return blockColorWrapperMap.get(block);
//if it hasn't been created yet, we create it and save it in the map
BlockColorWrapper blockWrapper = new BlockColorWrapper(block);
blockColorWrapperMap.put(block, blockWrapper);
//we return the newly created wrapper
return blockWrapper;
}
/**
* Generate the color of the given block from its texture
* and store it for later use.
*/
private void setupColorAndTint()
{
BlockState blockState = block.defaultBlockState();
//BlockPosWrapper blockPosWrapper = new BlockPosWrapper();
MinecraftWrapper mc = MinecraftWrapper.INSTANCE;
TextureAtlasSprite texture;
List<BakedQuad> quads = null;
//boolean isTinted = false;
//int listSize = 0;
// first step is to check if this block has a tinted face
//for (Direction direction : directions)
//{
// quads = mc.getModelManager().getBlockModelShaper().getBlockModel(block.defaultBlockState()).getQuads(blockState, direction, random);
// listSize = Math.max(listSize, quads.size());
// for (BakedQuad bakedQuad : quads)
// {
// isTinted |= bakedQuad.isTinted();
// }
//}
//if it contains a tinted face then we store this block in the toTint set
//if (isTinted)
// this.toTint = true;
//now we get the first non-empty face
for (Direction direction : directions)
{
quads = mc.getModelManager().getBlockModelShaper().getBlockModel(block.defaultBlockState()).getQuads(blockState, direction, random);
if (!quads.isEmpty())
break;
}
//the quads list is not empty we extract the first one
if (!quads.isEmpty())
{
isColored = true;
texture = quads.get(0).sprite;
}
else
{
isColored = true;
texture = mc.getModelManager().getBlockModelShaper().getParticleIcon(block.defaultBlockState());
texture = mc.getModelManager().getBlockModelShaper().getParticleIcon(block.defaultBlockState());
}
int count = 0;
int alpha = 0;
int red = 0;
int green = 0;
int blue = 0;
int numberOfGreyPixel = 0;
int tempColor;
int colorMultiplier;
// generate the block's color
// for (int frameIndex = 0; frameIndex < texture.getFrameCount(); frameIndex++)
boolean lookForTint = false;
if (grassInstance() || leavesInstance() || waterIstance())
lookForTint = true;
// generate the block's color
for (int frameIndex = 0; frameIndex < texture.getFrameCount(); frameIndex++)
{
// textures normally use u and v instead of x and y
for (int u = 0; u < texture.getWidth(); u++)
{
for (int v = 0; v < texture.getHeight(); v++)
{
tempColor = TextureAtlasSpriteWrapper.getPixelRGBA(texture, frameIndex, u, v);
if (texture.isTransparent(frameIndex, u, v))
continue;
if (lookForTint)
{
// determine if this pixel is gray
int colorMax = Math.max(Math.max(ColorUtil.getBlue(tempColor), ColorUtil.getGreen(tempColor)), ColorUtil.getRed(tempColor));
int colorMin = 4 + Math.min(Math.min(ColorUtil.getBlue(tempColor), ColorUtil.getGreen(tempColor)), ColorUtil.getRed(tempColor));
boolean isGray = colorMax < colorMin;
if (isGray)
numberOfGreyPixel++;
}
// for flowers, weight their non-green color higher
if (block instanceof FlowerBlock && (!(ColorUtil.getGreen(tempColor) > (ColorUtil.getBlue(tempColor) + 30)) || !(ColorUtil.getGreen(tempColor) > (ColorUtil.getRed(tempColor) + 30))))
colorMultiplier = 5;
else
colorMultiplier = 1;
// add to the running averages
count += colorMultiplier;
alpha += ColorUtil.getAlpha(tempColor) * colorMultiplier;
red += ColorUtil.getBlue(tempColor) * colorMultiplier;
green += ColorUtil.getGreen(tempColor) * colorMultiplier;
blue += ColorUtil.getRed(tempColor) * colorMultiplier;
}
}
}
if (count == 0)
// this block is entirely transparent
tempColor = 0;
else
{
// determine the average color
alpha /= count;
red /= count;
green /= count;
blue /= count;
tempColor = ColorUtil.rgbToInt(alpha, red, green, blue);
}
// determine if this block should use the biome color tint
if (lookForTint && (float) numberOfGreyPixel / count > 0.75f)
this.toTint = true;
// we check which kind of tint we need to apply
this.grassTint = grassInstance() && toTint;
this.foliageTint = leavesInstance() && toTint;
this.waterTint = waterIstance() && toTint;
//hardcoded leaves
if (block == Blocks.SPRUCE_LEAVES)
color = ColorUtil.multiplyRGBcolors(tempColor, 0xFF619961);
else if (block == Blocks.BIRCH_LEAVES)
color = ColorUtil.multiplyRGBcolors(tempColor, 0xFF80A755);
else
color = tempColor;
}
/** determine if the given block should use the biome's grass color */
private boolean grassInstance()
{
return block instanceof GrassBlock
|| block instanceof BushBlock
// || block instanceof IGrowable
// || block instanceof AbstractPlantBlock
// || block instanceof AbstractTopPlantBlock
|| block instanceof TallGrassBlock;
}
/** determine if the given block should use the biome's foliage color */
private boolean leavesInstance()
{
return (block instanceof LeavesBlock && block != Blocks.SPRUCE_LEAVES && block != Blocks.BIRCH_LEAVES/* && block != Blocks.AZALEA_LEAVES && block != Blocks.FLOWERING_AZALEA_LEAVES*/)
|| block == Blocks.VINE
|| block == Blocks.SUGAR_CANE;
}
/** determine if the given block should use the biome's foliage color */
private boolean waterIstance()
{
return block == Blocks.WATER;
}
@Override
public String getName(){
return block.getName().toString();
}
//--------------//
//Colors getters//
//--------------//
@Override
public boolean hasColor()
{
return isColored;
}
@Override
public int getColor()
{
return color;
}
//------------//
//Tint getters//
//------------//
@Override
public boolean hasTint()
{
return toTint;
}
@Override
public boolean hasGrassTint()
{
return grassTint;
}
@Override
public boolean hasFolliageTint()
{
return foliageTint;
}
@Override
public boolean hasWaterTint()
{
return waterTint;
}
@Override public boolean equals(Object o)
{
if (this == o)
return true;
if (!(o instanceof BlockColorWrapper))
return false;
BlockColorWrapper that = (BlockColorWrapper) o;
return Objects.equals(block, that.block);
}
@Override public int hashCode()
{
return Objects.hash(block);
}
}
@@ -0,0 +1,26 @@
package com.seibel.lod.common.wrappers.block;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.state.BlockState;
import java.util.concurrent.ConcurrentHashMap;
public class BlockDetailMap
{
private static ConcurrentHashMap<BlockState, BlockDetailWrapper> map = new ConcurrentHashMap<BlockState, BlockDetailWrapper>();
private BlockDetailMap() {}
public static BlockDetailWrapper getOrMakeBlockDetailCache(BlockState bs, BlockPos pos, LevelReader getter) {
BlockDetailWrapper cache = map.get(bs);
if (cache != null) return cache;
if (bs.getFluidState().isEmpty()) {
cache = BlockDetailWrapper.make(bs, pos, getter);
} else {
cache = BlockDetailWrapper.make(bs.getFluidState().createLegacyBlock(), pos, getter);
}
BlockDetailWrapper cacheCAS = map.putIfAbsent(bs, cache);
return cacheCAS==null ? cache : cacheCAS;
}
}
@@ -0,0 +1,326 @@
package com.seibel.lod.common.wrappers.block;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.Random;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Stream;
import com.seibel.lod.common.Config;
import com.seibel.lod.common.wrappers.McObjectConverter;
import com.seibel.lod.common.wrappers.chunk.ChunkWrapper;
import com.seibel.lod.core.api.ApiShared;
import com.seibel.lod.core.enums.LodDirection;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.util.ColorUtil;
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
import com.seibel.lod.core.wrapperInterfaces.block.IBlockDetailWrapper;
import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
import net.minecraft.Util;
import net.minecraft.client.Minecraft;
import net.minecraft.client.color.block.BlockTintCache;
import net.minecraft.client.renderer.BiomeColors;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Cursor3D;
import net.minecraft.core.Direction;
import net.minecraft.world.level.*;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.FlowerBlock;
import net.minecraft.world.level.block.LeavesBlock;
import net.minecraft.world.level.block.RenderShape;
import net.minecraft.world.level.block.RotatedPillarBlock;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.lighting.LevelLightEngine;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.phys.shapes.VoxelShape;
import org.jetbrains.annotations.Nullable;
public class BlockDetailWrapper extends IBlockDetailWrapper
{
private static final ILodConfigWrapperSingleton CONFIG = SingletonHandler.get(ILodConfigWrapperSingleton.class);
public static final int FLOWER_COLOR_SCALE = 5;
public static final Random random = new Random(0);
enum ColorMode {
Default,
Flower,
Leaves;
static ColorMode getColorMode(Block b) {
if (b instanceof LeavesBlock) return Leaves;
if (b instanceof FlowerBlock) return Flower;
return Default;
}
}
//TODO: Perhaps make this not just use the first frame?
private static int calculateColorFromTexture(TextureAtlasSprite texture, ColorMode colorMode) {
int count = 0;
double alpha = 0;
double red = 0;
double green = 0;
double blue = 0;
int tempColor;
{
// textures normally use u and v instead of x and y
for (int u = 0; u < texture.getWidth(); u++)
{
for (int v = 0; v < texture.getHeight(); v++)
{
//note: Minecraft color format is: 0xAA BB GG RR
//________ DH mod color format is: 0xAA RR GG BB
//OpenGL RGBA format native order: 0xRR GG BB AA
//_ OpenGL RGBA format Java Order: 0xAA BB GG RR
tempColor = TextureAtlasSpriteWrapper.getPixelRGBA(texture, 0, u, v);
double r = ((tempColor & 0x000000FF) )/255.;
double g = ((tempColor & 0x0000FF00) >>> 8)/255.;
double b = ((tempColor & 0x00FF0000) >>> 16)/255.;
double a = ((tempColor & 0xFF000000) >>> 24)/255.;
int scale = 1;
if (colorMode == ColorMode.Leaves) {
r *= a;
g *= a;
b *= a;
a = 1.;
} else if (a==0.) {
continue;
} else if (colorMode == ColorMode.Flower && (g+0.1<b || g+0.1<r)) {
scale = FLOWER_COLOR_SCALE;
}
count += scale;
alpha += a*a*scale;
red += r*r*scale;
green += g*g*scale;
blue += b*b*scale;
}
}
}
if (count == 0)
// this block is entirely transparent
tempColor = ColorUtil.rgbToInt(255,255,0,255);
else
{
// determine the average color
tempColor = ColorUtil.rgbToInt(
(int) (Math.sqrt(alpha/count)*255.),
(int) (Math.sqrt(red / count)*255.),
(int) (Math.sqrt(green / count)*255.),
(int) (Math.sqrt(blue / count)*255.));
}
// TODO: Remove this when transparency is added!
double colorAlpha = ColorUtil.getAlpha(tempColor)/255.;
tempColor = ColorUtil.rgbToInt(
ColorUtil.getAlpha(tempColor),
(int)(ColorUtil.getRed(tempColor) * colorAlpha),
(int)(ColorUtil.getGreen(tempColor) * colorAlpha),
(int)(ColorUtil.getBlue(tempColor) * colorAlpha)
);
return tempColor;
}
private static final Block[] BLOCK_TO_AVOID = {Blocks.AIR, Blocks.CAVE_AIR, Blocks.BARRIER};
private static final Direction[] DIRECTION_ORDER = {Direction.UP, Direction.NORTH, Direction.EAST, Direction.WEST, Direction.SOUTH, Direction.DOWN};
private static boolean isBlockToBeAvoid(Block b) {
for (Block bta : BLOCK_TO_AVOID)
if (bta==b) return true;
return false;
}
final BlockState state;
final BlockPos samplePos;
final LevelReader sampleGetter;
boolean isShapeResolved = false;
boolean[] dontOccludeFaces = null;
boolean noCollision = false;
boolean noFullFace = false;
boolean isColorResolved = false;
int baseColor = 0; //TODO: Impl per-face color
boolean needShade = true;
boolean needPostTinting = false;
int tintIndex = 0;
public static BlockDetailWrapper NULL_BLOCK_DETAIL = new BlockDetailWrapper();
public BlockDetailWrapper(BlockState state, BlockPos pos, LevelReader getter) {
this.state = state;
this.samplePos = pos;
this.sampleGetter = getter;
}
private BlockDetailWrapper() {
this.state = null;
this.samplePos = null;
this.sampleGetter = null;
}
static BlockDetailWrapper make(BlockState bs, BlockPos pos, LevelReader getter) {
if(!bs.getFluidState().isEmpty()) { // Is a fluidBlock
if (isBlockToBeAvoid(bs.getBlock())) return NULL_BLOCK_DETAIL;
if (bs.isAir()) return NULL_BLOCK_DETAIL;
return new BlockDetailWrapper(bs, pos, getter);
} else {
if (bs.getRenderShape() != RenderShape.MODEL) return NULL_BLOCK_DETAIL;
if (isBlockToBeAvoid(bs.getBlock())) return NULL_BLOCK_DETAIL;
return new BlockDetailWrapper(bs, pos, getter);
}
}
private void resolveShapes() {
if (isShapeResolved) return;
if (state.getFluidState().isEmpty()) {
noCollision = state.getCollisionShape(sampleGetter, samplePos).isEmpty();
dontOccludeFaces = new boolean[6];
if (state.canOcclude()) {
/* FIXME: Figure out how or if needed to impl per-face culling?
for (Direction dir : Direction.values()) {
dontOccludeFaces[McObjectConverter.Convert(dir).ordinal()]
= state.getFaceOcclusionShape(sampleGetter, samplePos, dir).isEmpty();
}*/
} else {
Arrays.fill(dontOccludeFaces, true);
}
VoxelShape voxelShape = state.getShape(sampleGetter, samplePos);
if (voxelShape.isEmpty()) {
noFullFace = true;
} else {
AABB bbox = voxelShape.bounds();
double xWidth = (bbox.maxX - bbox.minX);
double yWidth = (bbox.maxY - bbox.minY);
double zWidth = (bbox.maxZ - bbox.minZ);
noFullFace = xWidth < 1 && zWidth < 1 && yWidth < 1;
}
} else { // Liquid Block
dontOccludeFaces = new boolean[6];
}
isShapeResolved = true;
}
private void resolveColors() {
if (isColorResolved) return;
if (state.getFluidState().isEmpty()) {
List<BakedQuad> quads = null;
for (Direction direction : DIRECTION_ORDER)
{
quads = Minecraft.getInstance().getModelManager().getBlockModelShaper().
getBlockModel(state).getQuads(state, direction, random);
if (!quads.isEmpty() &&
!(state.getBlock() instanceof RotatedPillarBlock && direction == Direction.UP))
break;
};
if (quads == null || quads.isEmpty()) {
quads = Minecraft.getInstance().getModelManager().getBlockModelShaper().
getBlockModel(state).getQuads(state, null, random);
}
if (quads != null && !quads.isEmpty()) {
needPostTinting = quads.get(0).isTinted();
needShade = quads.get(0).isShade();
tintIndex = quads.get(0).getTintIndex();
baseColor = calculateColorFromTexture(quads.get(0).getSprite(),
ColorMode.getColorMode(state.getBlock()));
} else { // Backup method.
needPostTinting = false;
needShade = false;
tintIndex = 0;
baseColor = calculateColorFromTexture(Minecraft.getInstance().getModelManager().getBlockModelShaper().getParticleIcon(state),
ColorMode.getColorMode(state.getBlock()));
}
} else { // Liquid Block
needPostTinting = true;
needShade = false;
tintIndex = 0;
baseColor = calculateColorFromTexture(Minecraft.getInstance().getModelManager().getBlockModelShaper().getParticleIcon(state),
ColorMode.getColorMode(state.getBlock()));
}
isColorResolved = true;
}
private BlockAndTintGetter wrapColorResolver(LevelReader level) {
int blendDistance = CONFIG.client().graphics().quality().getLodBiomeBlending();
if (blendDistance == 0) {
return new TintGetterOverrideFast(level);
} else {
return new TintGetterOverrideSmooth(level, blendDistance);
}
}
@Override
public int getAndResolveFaceColor(LodDirection dir, IChunkWrapper chunk, AbstractBlockPosWrapper blockPos)
{
// FIXME: impl per-face colors
resolveColors();
if (!needPostTinting) return baseColor;
int tintColor = Minecraft.getInstance().getBlockColors()
.getColor(state, wrapColorResolver(((ChunkWrapper)chunk).getColorResolver()),
McObjectConverter.Convert(blockPos), tintIndex);
if (tintColor == -1) return baseColor;
return ColorUtil.multiplyARGBwithRGB(baseColor, tintColor);
}
@Override
public boolean hasFaceCullingFor(LodDirection dir)
{
resolveShapes();
return !dontOccludeFaces[dir.ordinal()];
}
@Override
public boolean hasNoCollision()
{
resolveShapes();
return noCollision;
}
@Override
public boolean noFaceIsFullFace()
{
resolveShapes();
return noFullFace;
}
@Override
public String serialize()
{
// FIXME: Impl this for the blockState Storage stuff
return null;
}
@Override
protected boolean isSame(IBlockDetailWrapper iBlockDetail)
{
return ((BlockDetailWrapper)iBlockDetail).state.getBlock().equals(state.getBlock());
}
}
@@ -1,159 +0,0 @@
package com.seibel.lod.common.wrappers.block;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
import com.seibel.lod.core.wrapperInterfaces.block.IBlockShapeWrapper;
import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper;
import com.seibel.lod.common.wrappers.chunk.ChunkWrapper;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.shapes.VoxelShape;
/**
* @author James Seibel
* @version 11-21-2021
*/
public class BlockShapeWrapper implements IBlockShapeWrapper
{
//set of block which require tint
public static final ConcurrentMap<Block, BlockShapeWrapper> blockShapeWrapperMap = new ConcurrentHashMap<>();
public static BlockShapeWrapper WATER_SHAPE = new BlockShapeWrapper();
private final Block block;
private final boolean toAvoid;
private boolean nonFull;
private boolean noCollision;
/**Constructor only require for the block instance we are wrapping**/
public BlockShapeWrapper(Block block, IChunkWrapper chunkWrapper, int x, int y, int z)
{
this.block = block;
this.nonFull = false;
this.noCollision = false;
this.toAvoid = ofBlockToAvoid();
setupShapes(chunkWrapper, x, y, z);
//System.out.println(block + " non full " + nonFull + " no collision " + noCollision + " to avoid " + toAvoid);
}
private BlockShapeWrapper()
{
this.block = Blocks.WATER;
this.nonFull = false;
this.noCollision = false;
this.toAvoid = false;
}
/**
* this return a wrapper of the block in input
* @param block Block object to wrap
*/
static public BlockShapeWrapper getBlockShapeWrapper(Block block, ChunkWrapper chunkWrapper, int x, int y, int z)
{
//first we check if the block has already been wrapped
if (blockShapeWrapperMap.containsKey(block) && blockShapeWrapperMap.get(block) != null)
return blockShapeWrapperMap.get(block);
//if it hasn't been created yet, we create it and save it in the map
BlockShapeWrapper blockWrapper = new BlockShapeWrapper(block, chunkWrapper, x, y, z);
blockShapeWrapperMap.put(block, blockWrapper);
//we return the newly created wrapper
return blockWrapper;
}
private void setupShapes(IChunkWrapper chunkWrapper, int x, int y, int z)
{
ChunkAccess chunk = ((ChunkWrapper) chunkWrapper).getChunk();
BlockPos blockPos = new BlockPos(x, y, z);
boolean noCollisionSetted = false;
boolean nonFullSetted = false;
if (!block.defaultBlockState().getFluidState().isEmpty())// || block instanceof SixWayBlock)
{
noCollisionSetted = true;
nonFullSetted = true;
noCollision = false;
nonFull = false;
}
if (!nonFullSetted)
{
VoxelShape voxelShape = block.defaultBlockState().getShape(chunk, blockPos);
if (!voxelShape.isEmpty())
{
AABB bbox = voxelShape.bounds();
double xWidth = (bbox.maxX - bbox.minX);
double yWidth = (bbox.maxY - bbox.minY);
double zWidth = (bbox.maxZ - bbox.minZ);
nonFull = xWidth < 1 && zWidth < 1 && yWidth < 1;
}
else
{
nonFull = false;
}
}
if (!noCollisionSetted)
{
VoxelShape collisionShape = block.defaultBlockState().getCollisionShape(chunk, blockPos);
noCollision = collisionShape.isEmpty();
}
}
@Override
public boolean ofBlockToAvoid()
{
return block.equals(Blocks.AIR)
|| block.equals(Blocks.CAVE_AIR)
|| block.equals(Blocks.BARRIER);
}
//-----------------//
//Avoidance getters//
//-----------------//
@Override
public boolean isNonFull()
{
return nonFull;
}
@Override
public boolean hasNoCollision()
{
return noCollision;
}
@Override
public boolean isToAvoid()
{
return toAvoid;
}
@Override public boolean equals(Object o)
{
if (this == o)
return true;
if (!(o instanceof BlockShapeWrapper))
return false;
BlockShapeWrapper that = (BlockShapeWrapper) o;
return Objects.equals(block, that.block);
}
@Override public int hashCode()
{
return Objects.hash(block);
}
}
@@ -18,7 +18,11 @@ public class TextureAtlasSpriteWrapper {
* The code has been modified to use TextureAtlasSprite
*/
public static int getPixelRGBA(TextureAtlasSprite sprite, int frameIndex, int x, int y) {
// Require access widener
return sprite.mainImage[0].getPixelRGBA(x + sprite.framesX[frameIndex] * sprite.getWidth(), y + sprite.framesY[frameIndex] * sprite.getHeight());
if (sprite.animatedTexture != null) {
x += sprite.animatedTexture.getFrameX(frameIndex) * sprite.width;
y += sprite.animatedTexture.getFrameY(frameIndex) * sprite.height;
}
return sprite.mainImage[0].getPixelRGBA(x, y);
}
}
@@ -0,0 +1,192 @@
package com.seibel.lod.common.wrappers.block;
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
import net.minecraft.Util;
import net.minecraft.client.color.block.BlockTintCache;
import net.minecraft.client.renderer.BiomeColors;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Cursor3D;
import net.minecraft.core.Direction;
import net.minecraft.world.level.*;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.lighting.LevelLightEngine;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.phys.shapes.VoxelShape;
import org.jetbrains.annotations.Nullable;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Supplier;
import java.util.stream.Stream;
public class TintGetterOverrideFast implements BlockAndTintGetter {
LevelReader parent;
private final Object2ObjectArrayMap<ColorResolver, ConcurrentHashMap<Biome, Integer>> tintCaches;
public TintGetterOverrideFast(LevelReader parent) {
this.parent = parent;
this.tintCaches = Util.make(new Object2ObjectArrayMap(3), object2ObjectArrayMap -> {
object2ObjectArrayMap.put(BiomeColors.GRASS_COLOR_RESOLVER, new ConcurrentHashMap<Biome, Integer>());
object2ObjectArrayMap.put(BiomeColors.FOLIAGE_COLOR_RESOLVER, new ConcurrentHashMap<Biome, Integer>());
object2ObjectArrayMap.put(BiomeColors.WATER_COLOR_RESOLVER, new ConcurrentHashMap<Biome, Integer>());
});
}
private Biome _getBiome(BlockPos pos) {
return parent.getBiome(pos);
}
@Override
public int getBlockTint(BlockPos blockPos, ColorResolver colorResolver) {
Biome b = _getBiome(blockPos);
return tintCaches.get(colorResolver).computeIfAbsent(b, (key) -> colorResolver.getColor(b, blockPos.getX(), blockPos.getZ()));
}
@Override
public float getShade(Direction direction, boolean bl) {
return parent.getShade(direction, bl);
}
@Override
public LevelLightEngine getLightEngine() {
return parent.getLightEngine();
}
@Override
public int getBrightness(LightLayer lightLayer, BlockPos blockPos) {
return parent.getBrightness(lightLayer, blockPos);
}
@Override
public int getRawBrightness(BlockPos blockPos, int i) {
return parent.getRawBrightness(blockPos, i);
}
@Override
public boolean canSeeSky(BlockPos blockPos) {
return parent.canSeeSky(blockPos);
}
@Override
@Nullable
public BlockEntity getBlockEntity(BlockPos blockPos) {
return parent.getBlockEntity(blockPos);
}
@Override
public <T extends BlockEntity> Optional<T> getBlockEntity(BlockPos blockPos, BlockEntityType<T> blockEntityType) {
return parent.getBlockEntity(blockPos, blockEntityType);
}
@Override
public BlockState getBlockState(BlockPos blockPos) {
return parent.getBlockState(blockPos);
}
@Override
public FluidState getFluidState(BlockPos blockPos) {
return parent.getFluidState(blockPos);
}
@Override
public int getLightEmission(BlockPos blockPos) {
return parent.getLightEmission(blockPos);
}
@Override
public int getMaxLightLevel() {
return parent.getMaxLightLevel();
}
@Override
public Stream<BlockState> getBlockStates(AABB aABB) {
return parent.getBlockStates(aABB);
}
@Override
public BlockHitResult isBlockInLine(ClipBlockStateContext clipBlockStateContext) {
return parent.isBlockInLine(clipBlockStateContext);
}
@Override
public BlockHitResult clip(ClipContext clipContext) {
return parent.clip(clipContext);
}
@Override
@Nullable
public BlockHitResult clipWithInteractionOverride(Vec3 vec3, Vec3 vec32, BlockPos blockPos, VoxelShape voxelShape, BlockState blockState) {
return parent.clipWithInteractionOverride(vec3, vec32, blockPos, voxelShape, blockState);
}
@Override
public double getBlockFloorHeight(VoxelShape voxelShape, Supplier<VoxelShape> supplier) {
return parent.getBlockFloorHeight(voxelShape, supplier);
}
@Override
public double getBlockFloorHeight(BlockPos blockPos) {
return parent.getBlockFloorHeight(blockPos);
}
@Override
public int getHeight() {
return parent.getHeight();
}
@Override
public int getMinBuildHeight() {
return parent.getMinBuildHeight();
}
@Override
public int getMaxBuildHeight() {
return parent.getMaxBuildHeight();
}
@Override
public int getSectionsCount() {
return parent.getSectionsCount();
}
@Override
public int getMinSection() {
return parent.getMinSection();
}
@Override
public int getMaxSection() {
return parent.getMaxSection();
}
@Override
public boolean isOutsideBuildHeight(BlockPos blockPos) {
return parent.isOutsideBuildHeight(blockPos);
}
@Override
public boolean isOutsideBuildHeight(int i) {
return parent.isOutsideBuildHeight(i);
}
@Override
public int getSectionIndex(int i) {
return parent.getSectionIndex(i);
}
@Override
public int getSectionIndexFromSectionY(int i) {
return parent.getSectionIndexFromSectionY(i);
}
@Override
public int getSectionYFromSectionIndex(int i) {
return parent.getSectionYFromSectionIndex(i);
}
}
@@ -0,0 +1,215 @@
package com.seibel.lod.common.wrappers.block;
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
import net.minecraft.Util;
import net.minecraft.client.color.block.BlockTintCache;
import net.minecraft.client.renderer.BiomeColors;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Cursor3D;
import net.minecraft.core.Direction;
import net.minecraft.world.level.*;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.lighting.LevelLightEngine;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.phys.shapes.VoxelShape;
import org.jetbrains.annotations.Nullable;
import java.util.Optional;
import java.util.function.Supplier;
import java.util.stream.Stream;
public class TintGetterOverrideSmooth implements BlockAndTintGetter {
LevelReader parent;
private final Object2ObjectArrayMap<ColorResolver, BlockTintCache> tintCaches;
public int smoothingRange;
public TintGetterOverrideSmooth(LevelReader parent, int smoothingRange) {
this.parent = parent;
this.smoothingRange = smoothingRange;
this.tintCaches = Util.make(new Object2ObjectArrayMap<>(3), object2ObjectArrayMap -> {
object2ObjectArrayMap.put(BiomeColors.GRASS_COLOR_RESOLVER, new BlockTintCache((pos) -> calculateBlockTint(pos, BiomeColors.GRASS_COLOR_RESOLVER)));
object2ObjectArrayMap.put(BiomeColors.FOLIAGE_COLOR_RESOLVER, new BlockTintCache((pos) -> calculateBlockTint(pos, BiomeColors.FOLIAGE_COLOR_RESOLVER)));
object2ObjectArrayMap.put(BiomeColors.WATER_COLOR_RESOLVER, new BlockTintCache((pos) -> calculateBlockTint(pos, BiomeColors.WATER_COLOR_RESOLVER)));
});
}
private Biome _getBiome(BlockPos pos) {
return parent.getBiome(pos);
}
public int calculateBlockTint(BlockPos blockPos, ColorResolver colorResolver)
{
int i = smoothingRange;
if (i == 0)
return colorResolver.getColor(_getBiome(blockPos), blockPos.getX(), blockPos.getZ());
int j = (i * 2 + 1) * (i * 2 + 1);
int k = 0;
int l = 0;
int m = 0;
Cursor3D cursor3D = new Cursor3D(blockPos.getX() - i, blockPos.getY(), blockPos.getZ() - i, blockPos.getX() + i, blockPos.getY(), blockPos.getZ() + i);
BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos();
while (cursor3D.advance())
{
mutableBlockPos.set(cursor3D.nextX(), cursor3D.nextY(), cursor3D.nextZ());
int n = colorResolver.getColor(_getBiome(mutableBlockPos), mutableBlockPos.getX(), mutableBlockPos.getZ());
k += (n & 0xFF0000) >> 16;
l += (n & 0xFF00) >> 8;
m += n & 0xFF;
}
return (k / j & 0xFF) << 16 | (l / j & 0xFF) << 8 | m / j & 0xFF;
}
@Override
public int getBlockTint(BlockPos blockPos, ColorResolver colorResolver) {
BlockTintCache blockTintCache = this.tintCaches.get(colorResolver);
return blockTintCache.getColor(blockPos, null); //FIXME
}
@Override
public float getShade(Direction direction, boolean bl) {
return parent.getShade(direction, bl);
}
@Override
public LevelLightEngine getLightEngine() {
return parent.getLightEngine();
}
@Override
public int getBrightness(LightLayer lightLayer, BlockPos blockPos) {
return parent.getBrightness(lightLayer, blockPos);
}
@Override
public int getRawBrightness(BlockPos blockPos, int i) {
return parent.getRawBrightness(blockPos, i);
}
@Override
public boolean canSeeSky(BlockPos blockPos) {
return parent.canSeeSky(blockPos);
}
@Override
@Nullable
public BlockEntity getBlockEntity(BlockPos blockPos) {
return parent.getBlockEntity(blockPos);
}
@Override
public <T extends BlockEntity> Optional<T> getBlockEntity(BlockPos blockPos, BlockEntityType<T> blockEntityType) {
return parent.getBlockEntity(blockPos, blockEntityType);
}
@Override
public BlockState getBlockState(BlockPos blockPos) {
return parent.getBlockState(blockPos);
}
@Override
public FluidState getFluidState(BlockPos blockPos) {
return parent.getFluidState(blockPos);
}
@Override
public int getLightEmission(BlockPos blockPos) {
return parent.getLightEmission(blockPos);
}
@Override
public int getMaxLightLevel() {
return parent.getMaxLightLevel();
}
@Override
public Stream<BlockState> getBlockStates(AABB aABB) {
return parent.getBlockStates(aABB);
}
@Override
public BlockHitResult isBlockInLine(ClipBlockStateContext clipBlockStateContext) {
return parent.isBlockInLine(clipBlockStateContext);
}
@Override
public BlockHitResult clip(ClipContext clipContext) {
return parent.clip(clipContext);
}
@Override
@Nullable
public BlockHitResult clipWithInteractionOverride(Vec3 vec3, Vec3 vec32, BlockPos blockPos, VoxelShape voxelShape, BlockState blockState) {
return parent.clipWithInteractionOverride(vec3, vec32, blockPos, voxelShape, blockState);
}
@Override
public double getBlockFloorHeight(VoxelShape voxelShape, Supplier<VoxelShape> supplier) {
return parent.getBlockFloorHeight(voxelShape, supplier);
}
@Override
public double getBlockFloorHeight(BlockPos blockPos) {
return parent.getBlockFloorHeight(blockPos);
}
@Override
public int getHeight() {
return parent.getHeight();
}
@Override
public int getMinBuildHeight() {
return parent.getMinBuildHeight();
}
@Override
public int getMaxBuildHeight() {
return parent.getMaxBuildHeight();
}
@Override
public int getSectionsCount() {
return parent.getSectionsCount();
}
@Override
public int getMinSection() {
return parent.getMinSection();
}
@Override
public int getMaxSection() {
return parent.getMaxSection();
}
@Override
public boolean isOutsideBuildHeight(BlockPos blockPos) {
return parent.isOutsideBuildHeight(blockPos);
}
@Override
public boolean isOutsideBuildHeight(int i) {
return parent.isOutsideBuildHeight(i);
}
@Override
public int getSectionIndex(int i) {
return parent.getSectionIndex(i);
}
@Override
public int getSectionIndexFromSectionY(int i) {
return parent.getSectionIndexFromSectionY(i);
}
@Override
public int getSectionYFromSectionIndex(int i) {
return parent.getSectionYFromSectionIndex(i);
}
}
@@ -44,12 +44,13 @@ public class ChunkPosWrapper extends AbstractChunkPosWrapper
{
this.chunkPos = new ChunkPos(chunkX, chunkZ);
}
public ChunkPosWrapper(long l)
{
this.chunkPos = new ChunkPos(l);
}
public ChunkPosWrapper(ChunkPos pos)
{
this.chunkPos = pos;
@@ -85,13 +86,13 @@ public class ChunkPosWrapper extends AbstractChunkPosWrapper
@Override
public int getRegionX()
{
return LevelPosUtil.convert(LodUtil.CHUNK_DETAIL_LEVEL, chunkPos.x, LodUtil.REGION_DETAIL_LEVEL);
return LevelPosUtil.convert(LodUtil.CHUNK_DETAIL_LEVEL, chunkPos.x, LodUtil.REGION_DETAIL_LEVEL);
}
@Override
public int getRegionZ()
{
return LevelPosUtil.convert(LodUtil.CHUNK_DETAIL_LEVEL, chunkPos.z, LodUtil.REGION_DETAIL_LEVEL);
return LevelPosUtil.convert(LodUtil.CHUNK_DETAIL_LEVEL, chunkPos.z, LodUtil.REGION_DETAIL_LEVEL);
}
public ChunkPos getChunkPos()
@@ -129,7 +130,7 @@ public class ChunkPosWrapper extends AbstractChunkPosWrapper
public AbstractBlockPosWrapper getWorldPosition()
{
// the parameter here is the y position
BlockPos blockPos = chunkPos.getWorldPosition();
BlockPos blockPos = chunkPos.getMiddleBlockPosition(0);
return new BlockPosWrapper(blockPos.getX(), blockPos.getY(), blockPos.getZ());
}
@@ -1,46 +1,57 @@
package com.seibel.lod.common.wrappers.chunk;
import com.seibel.lod.common.wrappers.block.BlockDetailWrapper;
import com.seibel.lod.core.enums.LodDirection;
import com.seibel.lod.core.util.LevelPosUtil;
import com.seibel.lod.core.util.LodUtil;
import com.seibel.lod.core.wrapperInterfaces.block.IBlockColorWrapper;
import com.seibel.lod.core.wrapperInterfaces.block.IBlockShapeWrapper;
import com.seibel.lod.core.wrapperInterfaces.block.IBlockDetailWrapper;
import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper;
import com.seibel.lod.core.wrapperInterfaces.world.IBiomeWrapper;
import com.seibel.lod.common.wrappers.WrapperUtil;
import com.seibel.lod.common.wrappers.block.BlockColorWrapper;
import com.seibel.lod.common.wrappers.block.BlockShapeWrapper;
import com.seibel.lod.common.wrappers.block.BlockDetailMap;
import com.seibel.lod.common.wrappers.world.BiomeWrapper;
import com.seibel.lod.common.wrappers.worldGeneration.mimicObject.LightedWorldGenRegion;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.BlockAndTintGetter;
import net.minecraft.core.QuartPos;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.LightLayer;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.LiquidBlockContainer;
import net.minecraft.world.level.block.SimpleWaterloggedBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.levelgen.Heightmap;
/**
*
* @author James Seibel
* @version 11-21-2021
* @version 3-5-2022
*/
public class ChunkWrapper implements IChunkWrapper
{
private ChunkAccess chunk;
private BlockAndTintGetter lightSource;
private final ChunkAccess chunk;
private final LevelReader lightSource;
public ChunkWrapper(ChunkAccess chunk, LevelReader lightSource)
{
this.chunk = chunk;
this.lightSource = lightSource;
}
@Override
public int getHeight(){
return 255;
return chunk.getHeight();
}
@Override
public int getMinBuildHeight()
{
return 0;
return chunk.getMinBuildHeight();
}
@Override
public int getMaxBuildHeight()
@@ -58,34 +69,31 @@ public class ChunkWrapper implements IChunkWrapper
public IBiomeWrapper getBiome(int x, int y, int z)
{
return BiomeWrapper.getBiomeWrapper(chunk.getBiomes().getNoiseBiome(
x >> 2, y >> 2, z >> 2));
QuartPos.fromBlock(x), QuartPos.fromBlock(y), QuartPos.fromBlock(z)));
}
@Override
public IBlockColorWrapper getBlockColorWrapper(int x, int y, int z)
{
BlockState blockState = chunk.getBlockState(new BlockPos(x,y,z));
Block block = blockState.getBlock();
return BlockColorWrapper.getBlockColorWrapper(block);
public IBlockDetailWrapper getBlockDetail(int x, int y, int z) {
BlockPos pos = new BlockPos(x,y,z);
BlockState blockState = chunk.getBlockState(pos);
IBlockDetailWrapper blockDetail = BlockDetailMap.getOrMakeBlockDetailCache(blockState, pos, lightSource);
return blockDetail == BlockDetailWrapper.NULL_BLOCK_DETAIL ? null : blockDetail;
}
@Override
public IBlockShapeWrapper getBlockShapeWrapper(int x, int y, int z)
{
BlockState blockState = chunk.getBlockState(new BlockPos(x,y,z));
Block block = blockState.getBlock();
return BlockShapeWrapper.getBlockShapeWrapper(block, this, x, y, z);
}
@Deprecated
public ChunkWrapper(ChunkAccess chunk)
{
this.chunk = chunk;
this.lightSource = null;
}
public ChunkWrapper(ChunkAccess chunk, BlockAndTintGetter lightSource) {
this.chunk = chunk;
this.lightSource = lightSource;
public IBlockDetailWrapper getBlockDetailAtFace(int x, int y, int z, LodDirection dir) {
int fy = y+dir.getNormal().y;
if (fy < getMinBuildHeight() || fy > getMaxBuildHeight()) return null;
BlockPos pos = new BlockPos(x+dir.getNormal().x,fy,z+dir.getNormal().z);
BlockState blockState;
if (blockPosInsideChunk(x,y,z))
blockState = chunk.getBlockState(pos);
else {
blockState = lightSource.getBlockState(pos);
}
if (blockState == null || blockState.isAir()) return null;
IBlockDetailWrapper blockDetail = BlockDetailMap.getOrMakeBlockDetailCache(blockState, pos, lightSource);
return blockDetail == BlockDetailWrapper.NULL_BLOCK_DETAIL ? null : blockDetail;
}
public ChunkAccess getChunk() {
@@ -104,12 +112,12 @@ public class ChunkWrapper implements IChunkWrapper
@Override
public int getRegionPosX(){
return LevelPosUtil.convert(LodUtil.CHUNK_DETAIL_LEVEL, getChunkPosX(), LodUtil.REGION_DETAIL_LEVEL);
return LevelPosUtil.convert(LodUtil.CHUNK_DETAIL_LEVEL, chunk.getPos().x, LodUtil.REGION_DETAIL_LEVEL);
}
@Override
public int getRegionPosZ(){
return LevelPosUtil.convert(LodUtil.CHUNK_DETAIL_LEVEL, getChunkPosZ(), LodUtil.REGION_DETAIL_LEVEL);
return LevelPosUtil.convert(LodUtil.CHUNK_DETAIL_LEVEL, chunk.getPos().z, LodUtil.REGION_DETAIL_LEVEL);
}
@Override
@@ -134,9 +142,19 @@ public class ChunkWrapper implements IChunkWrapper
return chunk.getPos().getMinBlockZ();
}
@Override
public long getLongChunkPos() {
return chunk.getPos().toLong();
}
@Override
public boolean isLightCorrect(){
return true;//chunk.isLightCorrect();
return true;
// TODO
// if (chunk instanceof LevelChunk) {
// return ((LevelChunk) chunk).isClientLightReady();
// }
// return chunk.isLightCorrect();
}
public boolean isWaterLogged(int x, int y, int z)
@@ -163,11 +181,24 @@ public class ChunkWrapper implements IChunkWrapper
@Override
public int getSkyLight(int x, int y, int z) {
if (lightSource == null) return -1;
return lightSource.getBrightness(LightLayer.SKY, new BlockPos(x, y, z));
return lightSource.getBrightness(LightLayer.SKY, new BlockPos(x,y,z));
}
@Override
public boolean doesNearbyChunksExist() {
if (lightSource instanceof LightedWorldGenRegion) return true;
for (int dx = -1; dx <= 1; dx++) {
for (int dz = -1; dz <= 1; dz++) {
if (dx==0 && dz==0) continue;
if (lightSource.getChunk(dx+getChunkPosX(), dz+getChunkPosZ(), ChunkStatus.BIOMES, false) == null) return false;
}
}
return true;
}
public LevelReader getColorResolver()
{
return lightSource;
}
@Override
public long getLongChunkPos() {
return chunk.getPos().toLong();
}
}
File diff suppressed because it is too large Load Diff
@@ -28,6 +28,7 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
{
public final IGraphics graphics;
public final IWorldGenerator worldGenerator;
public final IMultiplayer multiplayer;
public final IAdvanced advanced;
@@ -43,6 +44,11 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
return worldGenerator;
}
@Override
public IMultiplayer multiplayer() {
return multiplayer;
}
@Override
public IAdvanced advanced()
{
@@ -70,6 +76,7 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
{
graphics = new Graphics();
worldGenerator = new WorldGenerator();
multiplayer = new Multiplayer();
advanced = new Advanced();
}
@@ -187,11 +194,29 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
ConfigGui.editSingleOption.getEntry("client.graphics.quality.dropoffQuality").value = newDropoffQuality;
ConfigGui.editSingleOption.saveOption("client.graphics.quality.dropoffQuality");
}
@Override
public int getLodBiomeBlending() {
return Config.Client.Graphics.Quality.lodBiomeBlending;
}
@Override
public void setLodBiomeBlending(int newLodBiomeBlending) {
ConfigGui.editSingleOption.getEntry("client.graphics.quality.lodBiomeBlending").value = newLodBiomeBlending;
ConfigGui.editSingleOption.saveOption("client.graphics.quality.lodBiomeBlending");
}
}
public static class FogQuality implements IFogQuality
{
public final IAdvancedFog advancedFog;
FogQuality()
{
advancedFog = new AdvancedFog();
}
@Override
public FogDistance getFogDistance()
{
@@ -244,6 +269,167 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
ConfigGui.editSingleOption.getEntry("client.graphics.fogQuality.disableVanillaFog").value = newDisableVanillaFog;
ConfigGui.editSingleOption.saveOption("client.graphics.fogQuality.disableVanillaFog");
}
@Override
public IAdvancedFog advancedFog() {
return advancedFog;
}
public static class AdvancedFog implements IAdvancedFog {
public final IHeightFog heightFog;
public AdvancedFog() {
heightFog = new HeightFog();
}
@Override
public double getFarFogStart() {
return Config.Client.Graphics.FogQuality.AdvancedFog.farFogStart;
}
@Override
public double getFarFogEnd() {
return Config.Client.Graphics.FogQuality.AdvancedFog.farFogEnd;
}
@Override
public double getFarFogMin() {
return Config.Client.Graphics.FogQuality.AdvancedFog.farFogMin;
}
@Override
public double getFarFogMax() {
return Config.Client.Graphics.FogQuality.AdvancedFog.farFogMax;
}
@Override
public FogSetting.FogType getFarFogType() {
return Config.Client.Graphics.FogQuality.AdvancedFog.farFogType;
}
@Override
public double getFarFogDensity() {
return Config.Client.Graphics.FogQuality.AdvancedFog.farFogDensity;
}
@Override
public void setFarFogStart(double newFarFogStart) {
ConfigGui.editSingleOption.getEntry("client.graphics.fogQuality.advancedFog.farFogStart").value = newFarFogStart;
ConfigGui.editSingleOption.saveOption("client.graphics.fogQuality.advancedFog.farFogStart");
}
@Override
public void setFarFogEnd(double newFarFogEnd) {
ConfigGui.editSingleOption.getEntry("client.graphics.fogQuality.advancedFog.farFogEnd").value = newFarFogEnd;
ConfigGui.editSingleOption.saveOption("client.graphics.fogQuality.advancedFog.farFogEnd");
}
@Override
public void setFarFogMin(double newFarFogMin) {
ConfigGui.editSingleOption.getEntry("client.graphics.fogQuality.advancedFog.farFogMin").value = newFarFogMin;
ConfigGui.editSingleOption.saveOption("client.graphics.fogQuality.advancedFog.farFogMin");
}
@Override
public void setFarFogMax(double newFarFogMax) {
ConfigGui.editSingleOption.getEntry("client.graphics.fogQuality.advancedFog.farFogMax").value = newFarFogMax;
ConfigGui.editSingleOption.saveOption("client.graphics.fogQuality.advancedFog.farFogMax");
}
@Override
public void setFarFogType(FogSetting.FogType newFarFogType) {
ConfigGui.editSingleOption.getEntry("client.graphics.fogQuality.advancedFog.farFogType").value = newFarFogType;
ConfigGui.editSingleOption.saveOption("client.graphics.fogQuality.advancedFog.farFogType");
}
@Override
public void setFarFogDensity(double newFarFogDensity) {
ConfigGui.editSingleOption.getEntry("client.graphics.fogQuality.advancedFog.farFogDensity").value = newFarFogDensity;
ConfigGui.editSingleOption.saveOption("client.graphics.fogQuality.advancedFog.farFogDensity");
}
@Override
public IHeightFog heightFog() {
return heightFog;
}
public static class HeightFog implements IHeightFog {
@Override
public HeightFogMixMode getHeightFogMixMode() {
return Config.Client.Graphics.FogQuality.AdvancedFog.heightFog.heightFogMixMode;
}
@Override
public HeightFogMode getHeightFogMode() {
return Config.Client.Graphics.FogQuality.AdvancedFog.heightFog.heightFogMode;
}
@Override
public double getHeightFogHeight() {
return Config.Client.Graphics.FogQuality.AdvancedFog.heightFog.heightFogHeight;
}
@Override
public double getHeightFogStart() {
return Config.Client.Graphics.FogQuality.AdvancedFog.heightFog.heightFogStart;
}
@Override
public double getHeightFogEnd() {
return Config.Client.Graphics.FogQuality.AdvancedFog.heightFog.heightFogEnd;
}
@Override
public double getHeightFogMin() {
return Config.Client.Graphics.FogQuality.AdvancedFog.heightFog.heightFogMin;
}
@Override
public double getHeightFogMax() {
return Config.Client.Graphics.FogQuality.AdvancedFog.heightFog.heightFogMax;
}
@Override
public FogSetting.FogType getHeightFogType() {
return Config.Client.Graphics.FogQuality.AdvancedFog.heightFog.heightFogType;
}
@Override
public double getHeightFogDensity() {
return Config.Client.Graphics.FogQuality.AdvancedFog.heightFog.heightFogDensity;
}
@Override
public void setHeightFogMixMode(HeightFogMixMode newHeightFogMixMode) {
ConfigGui.editSingleOption.getEntry("client.graphics.fogQuality.advancedFog.heightFog.heightFogMixMode").value = newHeightFogMixMode;
ConfigGui.editSingleOption.saveOption("client.graphics.fogQuality.advancedFog.heightFog.heightFogMixMode");
}
@Override
public void setHeightFogMode(HeightFogMode newHeightFogMode) {
ConfigGui.editSingleOption.getEntry("client.graphics.fogQuality.advancedFog.heightFog.heightFogMode").value = newHeightFogMode;
ConfigGui.editSingleOption.saveOption("client.graphics.fogQuality.advancedFog.heightFog.heightFogMode");
}
@Override
public void setHeightFogHeight(double newHeightFogHeight) {
ConfigGui.editSingleOption.getEntry("client.graphics.fogQuality.advancedFog.heightFog.heightFogHeight").value = newHeightFogHeight;
ConfigGui.editSingleOption.saveOption("client.graphics.fogQuality.advancedFog.heightFog.heightFogHeight");
}
@Override
public void setHeightFogStart(double newHeightFogStart) {
ConfigGui.editSingleOption.getEntry("client.graphics.fogQuality.advancedFog.heightFog.heightFogStart").value = newHeightFogStart;
ConfigGui.editSingleOption.saveOption("client.graphics.fogQuality.advancedFog.heightFog.heightFogStart");
}
@Override
public void setHeightFogEnd(double newHeightFogEnd) {
ConfigGui.editSingleOption.getEntry("client.graphics.fogQuality.advancedFog.heightFog.heightFogEnd").value = newHeightFogEnd;
ConfigGui.editSingleOption.saveOption("client.graphics.fogQuality.advancedFog.heightFog.heightFogEnd");
}
@Override
public void setHeightFogMin(double newHeightFogMin) {
ConfigGui.editSingleOption.getEntry("client.graphics.fogQuality.advancedFog.heightFog.heightFogMin").value = newHeightFogMin;
ConfigGui.editSingleOption.saveOption("client.graphics.fogQuality.advancedFog.heightFog.heightFogMin");
}
@Override
public void setHeightFogMax(double newHeightFogMax) {
ConfigGui.editSingleOption.getEntry("client.graphics.fogQuality.advancedFog.heightFog.heightFogMax").value = newHeightFogMax;
ConfigGui.editSingleOption.saveOption("client.graphics.fogQuality.advancedFog.heightFog.heightFogMax");
}
@Override
public void setHeightFogType(FogSetting.FogType newHeightFogType) {
ConfigGui.editSingleOption.getEntry("client.graphics.fogQuality.advancedFog.heightFog.heightFogType").value = newHeightFogType;
ConfigGui.editSingleOption.saveOption("client.graphics.fogQuality.advancedFog.heightFog.heightFogType");
}
@Override
public void setHeightFogDensity(double newHeightFogDensity) {
ConfigGui.editSingleOption.getEntry("client.graphics.fogQuality.advancedFog.heightFog.heightFogDensity").value = newHeightFogDensity;
ConfigGui.editSingleOption.saveOption("client.graphics.fogQuality.advancedFog.heightFog.heightFogDensity");
}
}
}
}
@@ -273,6 +459,17 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
ConfigGui.editSingleOption.getEntry("client.graphics.advancedGraphics.vanillaOverdraw").value = newVanillaOverdraw;
ConfigGui.editSingleOption.saveOption("client.graphics.advancedGraphics.vanillaOverdraw");
}
@Override
public int getOverdrawOffset() {
return Config.Client.Graphics.AdvancedGraphics.overdrawOffset;
}
@Override
public void setOverdrawOffset(int newOverdrawOffset) {
ConfigGui.editSingleOption.getEntry("client.graphics.advancedGraphics.overdrawOffset").value = newOverdrawOffset;
ConfigGui.editSingleOption.saveOption("client.graphics.advancedGraphics.overdrawOffset");
}
/*
@Override
public int getBacksideCullingRange()
@@ -297,6 +494,54 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
ConfigGui.editSingleOption.getEntry("client.graphics.advancedGraphics.useExtendedNearClipPlane").value = newUseExtendedNearClipPlane;
ConfigGui.editSingleOption.saveOption("client.graphics.advancedGraphics.useExtendedNearClipPlane");
}
@Override
public double getBrightnessMultiplier()
{
return Config.Client.Graphics.AdvancedGraphics.brightnessMultiplier;
}
@Override
public void setBrightnessMultiplier(double newBrightnessMultiplier)
{
ConfigGui.editSingleOption.getEntry("client.graphics.advancedGraphics.brightnessMultiplier").value = newBrightnessMultiplier;
ConfigGui.editSingleOption.saveOption("client.graphics.advancedGraphics.brightnessMultiplier");
}
@Override
public double getSaturationMultiplier()
{
return Config.Client.Graphics.AdvancedGraphics.saturationMultiplier;
}
@Override
public void setSaturationMultiplier(double newSaturationMultiplier)
{
ConfigGui.editSingleOption.getEntry("client.graphics.advancedGraphics.saturationMultiplier").value = newSaturationMultiplier;
ConfigGui.editSingleOption.saveOption("client.graphics.advancedGraphics.saturationMultiplier");
}
@Override
public boolean getEnableCaveCulling() {
return Config.Client.Graphics.AdvancedGraphics.enableCaveCulling;
}
@Override
public void setEnableCaveCulling(boolean newEnableCaveCulling) {
ConfigGui.editSingleOption.getEntry("client.graphics.advancedGraphics.enableCaveCulling").value = newEnableCaveCulling;
ConfigGui.editSingleOption.saveOption("client.graphics.advancedGraphics.enableCaveCulling");
}
@Override
public int getCaveCullingHeight() {
return Config.Client.Graphics.AdvancedGraphics.caveCullingHeight;
}
@Override
public void setCaveCullingHeight(int newCaveCullingHeight) {
ConfigGui.editSingleOption.getEntry("client.graphics.advancedGraphics.caveCullingHeight").value = newCaveCullingHeight;
ConfigGui.editSingleOption.saveOption("client.graphics.advancedGraphics.caveCullingHeight");
}
}
}
@@ -361,7 +606,7 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
@Override
public boolean getEnableDistantGeneration()
{
return Config.Client.WorldGenerator.enableDistantGeneration;
return (boolean) ConfigGui.editSingleOption.getEntry("client.worldGenerator.enableDistantGeneration").value;
}
@Override
public void setEnableDistantGeneration(boolean newEnableDistantGeneration)
@@ -384,6 +629,38 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
//=====================//
// Multiplayer Configs //
//=====================//
public static class Multiplayer implements IMultiplayer
{
@Override
public ServerFolderNameMode getServerFolderNameMode()
{
return Config.Client.Multiplayer.serverFolderNameMode;
}
@Override
public void setServerFolderNameMode(ServerFolderNameMode newServerFolderNameMode)
{
ConfigGui.editSingleOption.getEntry("client.multiplayer.serverFolderNameMode").value = newServerFolderNameMode;
ConfigGui.editSingleOption.saveOption("client.multiplayer.serverFolderNameMode");
}
@Override
public double getMultiDimensionRequiredSimilarity()
{
return Config.Client.Multiplayer.multiDimensionRequiredSimilarity;
}
@Override
public void setMultiDimensionRequiredSimilarity(double newMultiDimensionMinimumSimilarityPercent)
{
ConfigGui.editSingleOption.getEntry("client.multiplayer.multiDimensionMinimumSimilarityPercent").value = newMultiDimensionMinimumSimilarityPercent;
ConfigGui.editSingleOption.saveOption("client.multiplayer.multiDimensionMinimumSimilarityPercent");
}
}
//============================//
// AdvancedModOptions Configs //
@@ -459,18 +736,28 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
//===============//
public static class Debugging implements IDebugging
{
public final IDebugSwitch debugSwitch;
@Override
public boolean getDrawLods()
public IDebugSwitch debugSwitch()
{
return (boolean) ConfigGui.editSingleOption.getEntry("client.advanced.debugging.drawLods").value;
}
@Override
public void setDrawLods(boolean newDrawLods)
{
ConfigGui.editSingleOption.getEntry("client.advanced.debugging.drawLods").value = newDrawLods;
ConfigGui.editSingleOption.saveOption("client.advanced.debugging.drawLods");
return debugSwitch;
}
/* RendererType:
* DEFAULT
* DEBUG
* DISABLED
* */
@Override
public RendererType getRendererType() {
return (RendererType) ConfigGui.editSingleOption.getEntry("client.advanced.debugging.rendererType").value;
}
@Override
public void setRendererType(RendererType newRenderType) {
ConfigGui.editSingleOption.getEntry("client.advanced.debugging.rendererType").value = newRenderType;
ConfigGui.editSingleOption.saveOption("client.advanced.debugging.rendererType");
}
@Override
public DebugMode getDebugMode()
@@ -496,6 +783,116 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
ConfigGui.editSingleOption.getEntry("client.advanced.debugging.enableDebugKeybindings").value = newEnableDebugKeybindings;
ConfigGui.editSingleOption.saveOption("client.advanced.debugging.enableDebugKeybindings");
}
public Debugging()
{
debugSwitch = new DebugSwitch();
}
public static class DebugSwitch implements IDebugSwitch {
/* The logging switches available:
* WorldGenEvent
* WorldGenPerformance
* WorldGenLoadEvent
* LodBuilderEvent
* RendererBufferEvent
* RendererGLEvent
* FileReadWriteEvent
* FileSubDimEvent
* NetworkEvent //NOT IMPL YET
*/
@Override
public LoggerMode getLogWorldGenEvent() {
return (LoggerMode) ConfigGui.editSingleOption.getEntry("client.advanced.debugging.debugSwitch.logWorldGenEvent").value;
}
@Override
public void setLogWorldGenEvent(LoggerMode newLogWorldGenEvent) {
ConfigGui.editSingleOption.getEntry("client.advanced.debugging.debugSwitch.logWorldGenEvent").value = newLogWorldGenEvent;
ConfigGui.editSingleOption.saveOption("client.advanced.debugging.debugSwitch.logWorldGenEvent");
}
@Override
public LoggerMode getLogWorldGenPerformance() {
return (LoggerMode) ConfigGui.editSingleOption.getEntry("client.advanced.debugging.debugSwitch.logWorldGenPerformance").value;
}
@Override
public void setLogWorldGenPerformance(LoggerMode newLogWorldGenPerformance) {
ConfigGui.editSingleOption.getEntry("client.advanced.debugging.debugSwitch.logWorldGenPerformance").value = newLogWorldGenPerformance;
ConfigGui.editSingleOption.saveOption("client.advanced.debugging.debugSwitch.logWorldGenPerformance");
}
@Override
public LoggerMode getLogWorldGenLoadEvent() {
return (LoggerMode) ConfigGui.editSingleOption.getEntry("client.advanced.debugging.debugSwitch.logWorldGenLoadEvent").value;
}
@Override
public void setLogWorldGenLoadEvent(LoggerMode newLogWorldGenLoadEvent) {
ConfigGui.editSingleOption.getEntry("client.advanced.debugging.debugSwitch.logWorldGenLoadEvent").value = newLogWorldGenLoadEvent;
ConfigGui.editSingleOption.saveOption("client.advanced.debugging.debugSwitch.logWorldGenLoadEvent");
}
@Override
public LoggerMode getLogLodBuilderEvent() {
return (LoggerMode) ConfigGui.editSingleOption.getEntry("client.advanced.debugging.debugSwitch.logLodBuilderEvent").value;
}
@Override
public void setLogLodBuilderEvent(LoggerMode newLogLodBuilderEvent) {
ConfigGui.editSingleOption.getEntry("client.advanced.debugging.debugSwitch.logLodBuilderEvent").value = newLogLodBuilderEvent;
ConfigGui.editSingleOption.saveOption("client.advanced.debugging.debugSwitch.logLodBuilderEvent");
}
@Override
public LoggerMode getLogRendererBufferEvent() {
return (LoggerMode) ConfigGui.editSingleOption.getEntry("client.advanced.debugging.debugSwitch.logRendererBufferEvent").value;
}
@Override
public void setLogRendererBufferEvent(LoggerMode newLogRendererBufferEvent) {
ConfigGui.editSingleOption.getEntry("client.advanced.debugging.debugSwitch.logRendererBufferEvent").value = newLogRendererBufferEvent;
ConfigGui.editSingleOption.saveOption("client.advanced.debugging.debugSwitch.logRendererBufferEvent");
}
@Override
public LoggerMode getLogRendererGLEvent() {
return (LoggerMode) ConfigGui.editSingleOption.getEntry("client.advanced.debugging.debugSwitch.logRendererGLEvent").value;
}
@Override
public void setLogRendererGLEvent(LoggerMode newLogRendererGLEvent) {
ConfigGui.editSingleOption.getEntry("client.advanced.debugging.debugSwitch.logRendererGLEvent").value = newLogRendererGLEvent;
ConfigGui.editSingleOption.saveOption("client.advanced.debugging.debugSwitch.logRendererGLEvent");
}
@Override
public LoggerMode getLogFileReadWriteEvent() {
return (LoggerMode) ConfigGui.editSingleOption.getEntry("client.advanced.debugging.debugSwitch.logFileReadWriteEvent").value;
}
@Override
public void setLogFileReadWriteEvent(LoggerMode newLogFileReadWriteEvent) {
ConfigGui.editSingleOption.getEntry("client.advanced.debugging.debugSwitch.logFileReadWriteEvent").value = newLogFileReadWriteEvent;
ConfigGui.editSingleOption.saveOption("client.advanced.debugging.debugSwitch.logFileReadWriteEvent");
}
@Override
public LoggerMode getLogFileSubDimEvent() {
return (LoggerMode) ConfigGui.editSingleOption.getEntry("client.advanced.debugging.debugSwitch.logFileSubDimEvent").value;
}
@Override
public void setLogFileSubDimEvent(LoggerMode newLogFileSubDimEvent) {
ConfigGui.editSingleOption.getEntry("client.advanced.debugging.debugSwitch.logFileSubDimEvent").value = newLogFileSubDimEvent;
ConfigGui.editSingleOption.saveOption("client.advanced.debugging.debugSwitch.logFileSubDimEvent");
}
@Override
public LoggerMode getLogNetworkEvent() {
return (LoggerMode) ConfigGui.editSingleOption.getEntry("client.advanced.debugging.debugSwitch.logNetworkEvent").value;
}
@Override
public void setLogNetworkEvent(LoggerMode newLogNetworkEvent) {
ConfigGui.editSingleOption.getEntry("client.advanced.debugging.debugSwitch.logNetworkEvent").value = newLogNetworkEvent;
ConfigGui.editSingleOption.saveOption("client.advanced.debugging.debugSwitch.logNetworkEvent");
}
}
}
@@ -539,6 +936,18 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
ConfigGui.editSingleOption.saveOption("client.advanced.buffers.newBufferRebuildTimes");
}
}
@Override
public boolean getLodOnlyMode() {
return Config.Client.Advanced.lodOnlyMode;
}
@Override
public void setLodOnlyMode(boolean newLodOnlyMode) {
ConfigGui.editSingleOption.getEntry("client.advanced.buffers.lodOnlyMode").value = newLodOnlyMode;
ConfigGui.editSingleOption.saveOption("client.advanced.buffers.lodOnlyMode");
}
}
}
}
@@ -2,9 +2,8 @@ package com.seibel.lod.common.wrappers.config;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.components.ImageButton;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
@@ -12,9 +11,9 @@ import net.minecraft.resources.ResourceLocation;
* Creates a button with a texture on it
*/
public class TexturedButtonWidget extends ImageButton {
// public TexturedButtonWidget(int x, int y, int width, int height, int u, int v, ResourceLocation texture, OnPress pressAction) {
// super(x, y, width, height, u, v, texture, pressAction);
// }
public TexturedButtonWidget(int x, int y, int width, int height, int u, int v, ResourceLocation texture, OnPress pressAction) {
super(x, y, width, height, u, v, texture, pressAction);
}
public TexturedButtonWidget(int x, int y, int width, int height, int u, int v, int hoveredVOffset, ResourceLocation texture, int textureWidth, int textureHeight, OnPress pressAction) {
super(x, y, width, height, u, v, hoveredVOffset, texture, textureWidth, textureHeight, pressAction);
}
@@ -27,20 +26,18 @@ public class TexturedButtonWidget extends ImageButton {
super(x, y, width, height, u, v, hoveredVOffset, texture, textureWidth, textureHeight, pressAction, tooltipSupplier, text);
}
@Override
public void renderButton(PoseStack matrices, int mouseX, int mouseY, float delta) {
@Override
public void renderButton(PoseStack matrices, int mouseX, int mouseY, float delta) {
RenderSystem.setShader(GameRenderer::getPositionTexShader);
RenderSystem.setShaderTexture(0, WIDGETS_LOCATION);
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, this.alpha);
int i = this.getYImage(this.isHovered);
RenderSystem.enableBlend();
RenderSystem.defaultBlendFunc();
RenderSystem.enableDepthTest();
this.blit(matrices, this.x, this.y, 0, 46 + i * 20, this.width / 2, this.height);
this.blit(matrices, this.x + this.width / 2, this.y, 200 - this.width / 2, 46 + i * 20, this.width / 2, this.height);
Minecraft.getInstance().getTextureManager().bind(WIDGETS_LOCATION);
RenderSystem.color4f(1.0F, 1.0F, 1.0F, this.alpha);
int i = getYImage(isHovered());
RenderSystem.enableBlend();
RenderSystem.defaultBlendFunc();
RenderSystem.enableDepthTest();
this.blit(matrices, this.x, this.y, 0, 46 + i * 20, this.width / 2, this.height);
this.blit(matrices, this.x + this.width / 2, this.y, 200 - this.width / 2, 46 + i * 20, this.width / 2,
this.height);
super.renderButton(matrices, mouseX, mouseY, delta);
}
super.renderButton(matrices, mouseX, mouseY, delta);
}
}
@@ -26,10 +26,11 @@ import java.util.ArrayList;
import com.mojang.blaze3d.platform.NativeImage;
import com.mojang.blaze3d.platform.Window;
import com.seibel.lod.core.ModInfo;
import com.seibel.lod.core.api.ApiShared;
import com.seibel.lod.core.api.ClientApi;
import com.seibel.lod.core.enums.LodDirection;
import com.seibel.lod.core.util.LodUtil;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftWrapper;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IProfilerWrapper;
import com.seibel.lod.core.wrapperInterfaces.misc.ILightMapWrapper;
import com.seibel.lod.core.wrapperInterfaces.world.IDimensionTypeWrapper;
@@ -69,9 +70,9 @@ import org.jetbrains.annotations.Nullable;
* @author James Seibel
* @version 9-16-2021
*/
public class MinecraftWrapper implements IMinecraftWrapper
public class MinecraftClientWrapper implements IMinecraftClientWrapper
{
public static final MinecraftWrapper INSTANCE = new MinecraftWrapper();
public static final MinecraftClientWrapper INSTANCE = new MinecraftClientWrapper();
public final Minecraft mc = Minecraft.getInstance();
@@ -84,7 +85,7 @@ public class MinecraftWrapper implements IMinecraftWrapper
private ProfilerWrapper profilerWrapper;
private MinecraftWrapper()
private MinecraftClientWrapper()
{
}
@@ -188,7 +189,7 @@ public class MinecraftWrapper implements IMinecraftWrapper
{
if (lightMap == null)
{
sendChatMessage("new");
//sendChatMessage("new");
// make sure the lightMap is up-to-date
getCurrentLightMap();
}
@@ -196,22 +197,6 @@ public class MinecraftWrapper implements IMinecraftWrapper
return lightMap.getPixelRGBA(blockLight, skyLight);
}
/**
* Returns the Color at the given pixel coordinates
* from the current lightmap.
* @param blockLight x location in texture space
* @param skyLight z location in texture space
*/
@Override
public Color getColorFromLightMap(int blockLight, int skyLight) {
if (lightMap == null) {
// make sure the lightMap is up-to-date
getCurrentLightMap();
}
return LodUtil.intToColor(lightMap.getPixelRGBA(blockLight, skyLight));
}
@@ -240,7 +225,8 @@ public class MinecraftWrapper implements IMinecraftWrapper
@Override
public ChunkPosWrapper getPlayerChunkPos()
{
return new ChunkPosWrapper(getPlayer().xChunk, getPlayer().zChunk);
ChunkPos playerPos = getPlayer().chunkPosition();
return new ChunkPosWrapper(playerPos.x, playerPos.z);
}
public Options getOptions()
@@ -417,7 +403,7 @@ public class MinecraftWrapper implements IMinecraftWrapper
@Override
public void crashMinecraft(String errorMessage, Throwable exception)
{
ClientApi.LOGGER.error(ModInfo.READABLE_NAME + " had the following error: [" + errorMessage + "]. Crashing Minecraft...");
ApiShared.LOGGER.error(ModInfo.READABLE_NAME + " had the following error: [" + errorMessage + "]. Crashing Minecraft...");
CrashReport report = new CrashReport(errorMessage, exception);
Minecraft.crash(report);
}
@@ -5,49 +5,44 @@ import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.stream.Collectors;
import com.mojang.blaze3d.pipeline.RenderTarget;
import com.mojang.blaze3d.platform.NativeImage;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.math.Vector3d;
import com.seibel.lod.common.wrappers.WrapperFactory;
import com.seibel.lod.common.wrappers.misc.LightMapWrapper;
import com.seibel.lod.core.api.ApiShared;
import com.seibel.lod.core.api.ClientApi;
import com.seibel.lod.core.api.ModAccessorApi;
import com.seibel.lod.core.handlers.IReflectionHandler;
import com.seibel.lod.core.handlers.ReflectionHandler;
import com.seibel.lod.core.handlers.dependencyInjection.ModAccessorHandler;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.util.LodUtil;
import com.seibel.lod.core.util.SingletonHandler;
import com.seibel.lod.core.wrapperInterfaces.IWrapperFactory;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftWrapper;
import com.seibel.lod.core.wrapperInterfaces.modAccessor.IOptifineAccessor;
import com.seibel.lod.core.wrapperInterfaces.modAccessor.ISodiumAccessor;
import it.unimi.dsi.fastutil.objects.ObjectList;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import net.minecraft.client.renderer.LightTexture;
import net.minecraft.world.phys.AABB;
import org.lwjgl.opengl.GL15;
import org.lwjgl.opengl.GL20;
import com.mojang.math.Vector3f;
import com.seibel.lod.core.objects.math.Mat4f;
import com.seibel.lod.core.objects.math.Vec3d;
import com.seibel.lod.core.objects.math.Vec3f;
import com.seibel.lod.core.wrapperInterfaces.IWrapperFactory;
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
import com.seibel.lod.core.wrapperInterfaces.chunk.AbstractChunkPosWrapper;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
import com.seibel.lod.core.wrapperInterfaces.modAccessor.IOptifineAccessor;
import com.seibel.lod.core.wrapperInterfaces.modAccessor.ISodiumAccessor;
import com.seibel.lod.common.wrappers.McObjectConverter;
import com.seibel.lod.common.wrappers.WrapperFactory;
import com.seibel.lod.common.wrappers.block.BlockPosWrapper;
import com.seibel.lod.common.wrappers.chunk.ChunkPosWrapper;
import net.minecraft.client.Camera;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.FogRenderer;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.client.renderer.LevelRenderer;
import net.minecraft.client.renderer.chunk.ChunkRenderDispatcher.CompiledChunk;
import net.minecraft.core.BlockPos;
import net.minecraft.tags.FluidTags;
import net.minecraft.world.effect.MobEffects;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.material.FogType;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3;
@@ -56,7 +51,7 @@ import net.minecraft.world.phys.Vec3;
* related to rendering in Minecraft.
*
* @author James Seibel
* @version 12-14-2021
* @version 12-12-2021
*/
public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
{
@@ -64,9 +59,7 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
private static final Minecraft MC = Minecraft.getInstance();
private static final GameRenderer GAME_RENDERER = MC.gameRenderer;
private static final WrapperFactory FACTORY = WrapperFactory.INSTANCE;
private static final IWrapperFactory FACTORY = WrapperFactory.INSTANCE;
@Override
public Vec3f getLookAtVector()
@@ -102,7 +95,7 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
@Override
public Mat4f getDefaultProjectionMatrix(float partialTicks)
{
return McObjectConverter.Convert(GAME_RENDERER.getProjectionMatrix(GAME_RENDERER.getMainCamera(), partialTicks, true));
return McObjectConverter.Convert(GAME_RENDERER.getProjectionMatrix(GAME_RENDERER.getFov(GAME_RENDERER.getMainCamera(), partialTicks, true)));
}
@Override
@@ -112,9 +105,9 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
}
@Override
public Color getFogColor(float partialTick) {
float[] colorValues = new float[4];
GL15.glGetFloatv(GL15.GL_FOG_COLOR, colorValues);
public Color getFogColor(float partialTicks) {
FogRenderer.setupColor(GAME_RENDERER.getMainCamera(), partialTicks, MC.level, 1, GAME_RENDERER.getDarkenWorldAmount(partialTicks));
float[] colorValues = RenderSystem.getShaderFogColor();
return new Color(colorValues[0], colorValues[1], colorValues[2], colorValues[3]);
}
// getSpecialFogColor() is the same as getFogColor()
@@ -122,7 +115,7 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
@Override
public Color getSkyColor() {
if (MC.level.dimensionType().hasSkyLight()) {
Vec3 colorValues = MC.level.getSkyColor(MC.gameRenderer.getMainCamera().getBlockPosition(), MC.getFrameTime());
Vec3 colorValues = MC.level.getSkyColor(MC.gameRenderer.getMainCamera().getPosition(), MC.getFrameTime());
return new Color((float) colorValues.x, (float) colorValues.y, (float) colorValues.z);
} else
return new Color(0, 0, 0);
@@ -152,62 +145,73 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
return MC.getWindow().getHeight();
}
private RenderTarget getRenderTarget() {
RenderTarget r = null; //MC.levelRenderer.getCloudsTarget();
return r!=null ? r : MC.getMainRenderTarget();
}
@Override
public int getTargetFrameBuffer() {
return getRenderTarget().frameBufferId;
}
@Override
public int getTargetFrameBufferViewportWidth() {
return getRenderTarget().viewWidth;
}
@Override
public int getTargetFrameBufferViewportHeight() {
return getRenderTarget().viewHeight;
}
/**
* This method returns the ChunkPos of all chunks that Minecraft
* is going to render this frame. <br><br>
* <p>
*/
public boolean usingBackupGetVanillaRenderedChunks = false;
@Override
public HashSet<AbstractChunkPosWrapper> getVanillaRenderedChunks()
{
ISodiumAccessor sodium = ModAccessorApi.get(ISodiumAccessor.class);
ISodiumAccessor sodium = ModAccessorHandler.get(ISodiumAccessor.class);
if (sodium != null)
{
return sodium.getNormalRenderedChunks();
}
IOptifineAccessor optifine = ModAccessorApi.get(IOptifineAccessor.class);
IOptifineAccessor optifine = ModAccessorHandler.get(IOptifineAccessor.class);
if (optifine != null)
{
HashSet<AbstractChunkPosWrapper> pos = optifine.getNormalRenderedChunks();
if (pos==null) pos = getMaximumRenderedChunks();
if (pos == null)
pos = getMaximumRenderedChunks();
return pos;
}
LevelRenderer levelRenderer = MC.levelRenderer;
ObjectList<LevelRenderer.RenderChunkInfo> chunks = levelRenderer.renderChunks;
return (chunks.stream().map((chunk) -> {
AABB chunkBoundingBox = chunk.chunk.bb;
return FACTORY.createChunkPos(Math.floorDiv((int) chunkBoundingBox.minX, 16),
Math.floorDiv((int) chunkBoundingBox.minZ, 16));
}).collect(Collectors.toCollection(HashSet::new)));
}
@Override
public HashSet<AbstractChunkPosWrapper> getMaximumRenderedChunks()
{
IMinecraftWrapper mcWrapper = SingletonHandler.get(IMinecraftWrapper.class);
IWrapperFactory factory = SingletonHandler.get(IWrapperFactory.class);
int chunkRenderDist = this.getRenderDistance();
AbstractChunkPosWrapper centerChunkPos = mcWrapper.getPlayerChunkPos();
int startChunkX = centerChunkPos.getX() - chunkRenderDist;
int startChunkZ = centerChunkPos.getZ() - chunkRenderDist;
// add every position within render distance
HashSet<AbstractChunkPosWrapper> renderedPos = new HashSet<AbstractChunkPosWrapper>();
for (int chunkX = 0; chunkX < (chunkRenderDist * 2+1); chunkX++)
{
for(int chunkZ = 0; chunkZ < (chunkRenderDist * 2+1); chunkZ++)
{
renderedPos.add(factory.createChunkPos(startChunkX + chunkX, startChunkZ + chunkZ));
if (!usingBackupGetVanillaRenderedChunks) {
try {
LevelRenderer levelRenderer = MC.levelRenderer;
ObjectArrayList<LevelRenderer.RenderChunkInfo> chunks = levelRenderer.renderChunks;
return (chunks.stream().map((chunk) -> {
AABB chunkBoundingBox = chunk.chunk.bb;
return FACTORY.createChunkPos(Math.floorDiv((int) chunkBoundingBox.minX, 16),
Math.floorDiv((int) chunkBoundingBox.minZ, 16));
}).collect(Collectors.toCollection(HashSet::new)));
} catch (LinkageError e) {
try {
MinecraftClientWrapper.INSTANCE.sendChatMessage(
"\u00A7e\u00A7l\u00A7uWARNING: Distant Horizons: getVanillaRenderedChunks method failed."
+ " Using Backup Method.");
MinecraftClientWrapper.INSTANCE.sendChatMessage(
"\u00A7eOverdraw prevention will be worse than normal.");
} catch (Exception e2) {}
ApiShared.LOGGER.error("getVanillaRenderedChunks Error: ", e);
usingBackupGetVanillaRenderedChunks = true;
}
}
return renderedPos;
return getMaximumRenderedChunks();
}
@Override
public int[] getLightmapPixels()
{
@@ -220,7 +224,7 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
int lightMapHeight = getLightmapTextureHeight();
int lightMapWidth = getLightmapTextureWidth();
int pixels[] = new int[lightMapWidth * lightMapHeight];
int[] pixels = new int[lightMapWidth * lightMapHeight];
for (int u = 0; u < lightMapWidth; u++)
{
for (int v = 0; v < lightMapWidth; v++)
@@ -228,7 +232,7 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
// this could probably be kept as a int, but
// it is easier to test and see the colors when debugging this way.
// When creating a new release this should be changed to the int version.
Color c = LodUtil.intToColor(lightMap.getLightValue(u, v));
int col = lightMap.getLightValue(u, v);
// these should both create a totally white image
// int col =
@@ -239,13 +243,12 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
// (0b11111111 << 16) + // blue
// (0b11111111 << 24); // blue
int col =
((c.getRed() & 0xFF) << 16) | // blue
((c.getGreen() & 0xFF) << 8) | // green
((c.getBlue() & 0xFF)) | // red
((c.getAlpha() & 0xFF) << 24); // alpha
// int col =
// ((c.getRed() & 0xFF) << 16) | // blue
// ((c.getGreen() & 0xFF) << 8) | // green
// ((c.getBlue() & 0xFF)) | // red
// ((c.getAlpha() & 0xFF) << 24); // alpha
// 2D array stored in a 1D array.
// Thank you Tim from College ;)
pixels[u * lightMapWidth + v] = col;
@@ -310,17 +313,13 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
@Override
public boolean isFogStateSpecial() {
Camera camera = GAME_RENDERER.getMainCamera();
FluidState fluidState = camera.getFluidInCamera();
Entity entity = camera.getEntity();
boolean isUnderWater = (entity instanceof LivingEntity) && ((LivingEntity)entity).hasEffect(MobEffects.BLINDNESS);
isUnderWater |= fluidState.is(FluidTags.WATER);
isUnderWater |= fluidState.is(FluidTags.LAVA);
return isUnderWater;
Entity entity = GAME_RENDERER.getMainCamera().getEntity();
boolean isBlind = (entity instanceof LivingEntity) && ((LivingEntity)entity).hasEffect(MobEffects.BLINDNESS);
return GAME_RENDERER.getMainCamera().getFluidInCamera() != FogType.NONE || isBlind;
}
@Override
public boolean tryDisableVanillaFog() {
return true; // Handled via the MixinFogRenderer at fabric and forge
}
public boolean tryDisableVanillaFog() {
return true; // Handled via MixinFogRenderer in both forge and fabric
}
}
@@ -65,7 +65,7 @@ public class BiomeWrapper implements IBiomeWrapper
{
int colorInt;
switch (biome.getBiomeCategory())
switch (biome.biomeCategory)
{
case NETHER:
@@ -110,9 +110,11 @@ public class BiomeWrapper implements IBiomeWrapper
case SAVANNA:
case SWAMP:
default:
Color tmp = LodUtil.intToColor(biome.getGrassColor(x, z));
tmp = tmp.darker();
colorInt = LodUtil.colorToInt(tmp);
colorInt = biome.getGrassColor(x,z);
//FIXME: Repair what James did - LeeTom
// Color tmp = LodUtil.intToColor(biome.getGrassColor(x, z));
// tmp = tmp.darker();
// colorInt = LodUtil.colorToInt(tmp);
break;
}
@@ -23,13 +23,11 @@ import java.io.File;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import com.seibel.lod.common.wrappers.chunk.ChunkWrapper;
import com.seibel.lod.core.enums.WorldType;
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
import com.seibel.lod.core.wrapperInterfaces.chunk.AbstractChunkPosWrapper;
import com.seibel.lod.core.wrapperInterfaces.world.IBiomeWrapper;
import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper;
import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
import com.seibel.lod.common.wrappers.block.BlockPosWrapper;
import com.seibel.lod.common.wrappers.chunk.ChunkWrapper;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.core.BlockPos;
@@ -38,7 +36,9 @@ import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.LightLayer;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkSource;
import net.minecraft.world.level.chunk.ChunkStatus;
import org.jetbrains.annotations.Nullable;
/**
@@ -129,18 +129,18 @@ public class WorldWrapper implements IWorldWrapper
return world.dimensionType().hasSkyLight();
}
@Override
public boolean isEmpty()
{
return world == null;
}
@Override
public int getHeight()
{
return world.getHeight();
}
@Override
public short getMinHeight()
{
return (short) world.getMinBuildHeight();
}
/** @throws UnsupportedOperationException if the WorldWrapper isn't for a ServerWorld */
@Override
public File getSaveFolder() throws UnsupportedOperationException
@@ -170,9 +170,18 @@ public class WorldWrapper implements IWorldWrapper
}
@Override
public ChunkWrapper tryGetChunk(AbstractChunkPosWrapper pos) {
public IChunkWrapper tryGetChunk(AbstractChunkPosWrapper pos) {
ChunkAccess chunk = world.getChunk(pos.getX(), pos.getZ(), ChunkStatus.EMPTY, false);
if (chunk == null) return null;
return new ChunkWrapper(chunk, world);
}
@Override
public boolean hasChunkLoaded(int chunkX, int chunkZ) {
// world.hasChunk(chunkX, chunkZ); THIS DOES NOT WORK FOR CLIENT LEVEL CAUSE MOJANG ALWAYS RETURN TRUE FOR THAT!
ChunkSource source = world.getChunkSource();
return source.hasChunk(chunkX, chunkZ);
}
}
@@ -19,15 +19,20 @@
package com.seibel.lod.common.wrappers.worldGeneration;
import com.seibel.lod.core.api.ApiShared;
import com.seibel.lod.core.api.ClientApi;
import com.seibel.lod.core.builders.lodBuilding.LodBuilder;
import com.seibel.lod.core.builders.lodBuilding.LodBuilderConfig;
import com.seibel.lod.core.enums.config.DistanceGenerationMode;
import com.seibel.lod.core.enums.config.LightGenerationMode;
import com.seibel.lod.core.logging.ConfigBasedLogger;
import com.seibel.lod.core.logging.ConfigBasedSpamLogger;
import com.seibel.lod.core.objects.lod.LodDimension;
import com.seibel.lod.core.util.GridList;
import com.seibel.lod.core.util.LodThreadFactory;
import com.seibel.lod.core.util.SingletonHandler;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.util.gridList.ArrayGridList;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
import com.seibel.lod.core.wrapperInterfaces.worldGeneration.AbstractBatchGenerationEnvionmentWrapper;
@@ -35,10 +40,12 @@ import java.io.IOException;
import java.time.Duration;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import com.seibel.lod.common.wrappers.DependencySetupDoneCheck;
import com.seibel.lod.common.wrappers.chunk.ChunkWrapper;
import com.seibel.lod.common.wrappers.world.WorldWrapper;
import com.seibel.lod.common.wrappers.worldGeneration.mimicObject.ChunkLoader;
@@ -56,12 +63,17 @@ import com.seibel.lod.common.wrappers.worldGeneration.step.StepSurface;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.chunk.ProtoChunk;
import net.minecraft.world.level.chunk.UpgradeData;
import net.minecraft.world.level.levelgen.DebugLevelSource;
import net.minecraft.world.level.levelgen.FlatLevelSource;
import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.level.lighting.LevelLightEngine;
import org.apache.logging.log4j.LogManager;
/*
Total: 3.135214124s
@@ -77,14 +89,22 @@ Feature Step: 0.389072425s
Lod Generation: 0.269023348s
*/
public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnvionmentWrapper {
public static final boolean ENABLE_PERF_LOGGING = false;
public static final boolean ENABLE_EVENT_LOGGING = false;
public static final boolean ENABLE_LOAD_EVENT_LOGGING = false;
public static final boolean DISABLE_LOADING_SAVES = false;
// TODO: Make actual proper support for StarLight
public static class PrefEvent {
public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnvionmentWrapper
{
private static final ILodConfigWrapperSingleton CONFIG = SingletonHandler.get(ILodConfigWrapperSingleton.class);
public static final ConfigBasedSpamLogger PREF_LOGGER =
new ConfigBasedSpamLogger(LogManager.getLogger("LodWorldGen"),
() -> CONFIG.client().advanced().debugging().debugSwitch().getLogWorldGenPerformance(),1);
public static final ConfigBasedLogger EVENT_LOGGER =
new ConfigBasedLogger(LogManager.getLogger("LodWorldGen"),
() -> CONFIG.client().advanced().debugging().debugSwitch().getLogWorldGenEvent());
public static final ConfigBasedLogger LOAD_LOGGER =
new ConfigBasedLogger(LogManager.getLogger("LodWorldGen"),
() -> CONFIG.client().advanced().debugging().debugSwitch().getLogWorldGenLoadEvent());
//TODO: Make actual proper support for StarLight
public static class PrefEvent
{
long beginNano = 0;
long emptyNano = 0;
long structStartNano = 0;
@@ -96,20 +116,27 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
long featureNano = 0;
long lightNano = 0;
long endNano = 0;
@Override
public String toString() {
return "beginNano: " + beginNano + ",\n" + "emptyNano: " + emptyNano + ",\n" + "structStartNano: "
+ structStartNano + ",\n" + "structRefNano: " + structRefNano + ",\n" + "biomeNano: " + biomeNano
+ ",\n" + "noiseNano: " + noiseNano + ",\n" + "surfaceNano: " + surfaceNano + ",\n" + "carverNano: "
+ carverNano + ",\n" + "featureNano: " + featureNano + ",\n" + "lightNano: " + lightNano + ",\n"
+ "endNano: " + endNano + "\n";
public String toString()
{
return "beginNano: " + beginNano + ",\n" +
"emptyNano: " + emptyNano + ",\n" +
"structStartNano: " + structStartNano + ",\n" +
"structRefNano: " + structRefNano + ",\n" +
"biomeNano: " + biomeNano + ",\n" +
"noiseNano: " + noiseNano + ",\n" +
"surfaceNano: " + surfaceNano + ",\n" +
"carverNano: " + carverNano + ",\n" +
"featureNano: " + featureNano + ",\n" +
"lightNano: " + lightNano + ",\n" +
"endNano: " + endNano + "\n";
}
}
public static class PerfCalculator {
public static final int SIZE = 10;
private int dataCount = 0;
public static class PerfCalculator
{
public static final int SIZE = 50;
Rolling totalTime = new Rolling(SIZE);
Rolling emptyTime = new Rolling(SIZE);
Rolling structStartTime = new Rolling(SIZE);
@@ -121,56 +148,64 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
Rolling featureTime = new Rolling(SIZE);
Rolling lightTime = new Rolling(SIZE);
Rolling lodTime = new Rolling(SIZE);
public void recordEvent(PrefEvent e) {
dataCount++;
public void recordEvent(PrefEvent e)
{
long preTime = e.beginNano;
totalTime.add(e.endNano - preTime);
if (e.emptyNano != 0) {
if (e.emptyNano != 0)
{
emptyTime.add(e.emptyNano - preTime);
preTime = e.emptyNano;
}
if (e.structStartNano != 0) {
if (e.structStartNano != 0)
{
structStartTime.add(e.structStartNano - preTime);
preTime = e.structStartNano;
}
if (e.structRefNano != 0) {
if (e.structRefNano != 0)
{
structRefTime.add(e.structRefNano - preTime);
preTime = e.structRefNano;
}
if (e.biomeNano != 0) {
if (e.biomeNano != 0)
{
biomeTime.add(e.biomeNano - preTime);
preTime = e.biomeNano;
}
if (e.noiseNano != 0) {
if (e.noiseNano != 0)
{
noiseTime.add(e.noiseNano - preTime);
preTime = e.noiseNano;
}
if (e.surfaceNano != 0) {
if (e.surfaceNano != 0)
{
surfaceTime.add(e.surfaceNano - preTime);
preTime = e.surfaceNano;
}
if (e.carverNano != 0) {
if (e.carverNano != 0)
{
carverTime.add(e.carverNano - preTime);
preTime = e.carverNano;
}
if (e.featureNano != 0) {
if (e.featureNano != 0)
{
featureTime.add(e.featureNano - preTime);
preTime = e.featureNano;
}
if (e.lightNano != 0) {
if (e.lightNano != 0)
{
lightTime.add(e.lightNano - preTime);
preTime = e.lightNano;
}
if (e.endNano != 0) {
if (e.endNano != 0)
{
lodTime.add(e.endNano - preTime);
preTime = e.endNano;
}
}
public String toString() {
if (dataCount < SIZE)
return "Pref Calculator collecting samples...";
public String toString()
{
return "Total: " + Duration.ofNanos((long) totalTime.getAverage()) + ", Empty/LoadChunk: "
+ Duration.ofNanos((long) emptyTime.getAverage()) + ", StructStart: "
+ Duration.ofNanos((long) structStartTime.getAverage()) + ", StructRef: "
@@ -184,40 +219,67 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
+ Duration.ofNanos((long) lodTime.getAverage());
}
}
public static final int TIMEOUT_SECONDS = 30;
// =================Generation Step===================
public final LinkedList<GenerationEvent> events = new LinkedList<GenerationEvent>();
public static final int TIMEOUT_SECONDS = 60;
//=================Generation Step===================
public final LinkedList<GenerationEvent> events = new LinkedList<>();
public final GlobalParameters params;
public final StepStructureStart stepStructureStart = new StepStructureStart(this);
public final StepStructureReference stepStructureReference = new StepStructureReference();
public final StepStructureReference stepStructureReference = new StepStructureReference(this);
public final StepBiomes stepBiomes = new StepBiomes(this);
public final StepNoise stepNoise = new StepNoise(this);
public final StepSurface stepSurface = new StepSurface(this);
public final StepFeatures stepFeatures = new StepFeatures(this);
public final StepLight stepLight = new StepLight(this);
static private final ILodConfigWrapperSingleton CONFIG = SingletonHandler.get(ILodConfigWrapperSingleton.class);
public boolean unsafeThreadingRecorded = false;
//public boolean safeMode = false;
private static final IMinecraftClientWrapper MC = SingletonHandler.get(IMinecraftClientWrapper.class);
public static final long EXCEPTION_TIMER_RESET_TIME = TimeUnit.NANOSECONDS.convert(1, TimeUnit.SECONDS);
public static final int EXCEPTION_COUNTER_TRIGGER = 20;
public static final int RANGE_TO_RANGE_EMPTY_EXTENSION = 1;
public int unknownExceptionCount = 0;
public long lastExceptionTriggerTime = 0;
public static final LodThreadFactory threadFactory = new LodThreadFactory("Gen-Worker-Thread", Thread.MIN_PRIORITY);
public static ThreadLocal<Boolean> isDistantGeneratorThread = new ThreadLocal<>();
public static boolean isCurrentThreadDistantGeneratorThread() {
return (isDistantGeneratorThread.get() != null);
}
static {
DependencySetupDoneCheck.getIsCurrentThreadDistantGeneratorThread = BatchGenerationEnvironment::isCurrentThreadDistantGeneratorThread;
}
public ExecutorService executors = Executors.newFixedThreadPool(
CONFIG.client().advanced().threading().getNumberOfWorldGenerationThreads(), threadFactory);
public <T> T joinSync(CompletableFuture<T> f) {
if (!unsafeThreadingRecorded && !f.isDone()) {
EVENT_LOGGER.error("Unsafe Threading in Chunk Generator: ", new RuntimeException("Concurrent future"));
EVENT_LOGGER.error("To increase stability, it is recommended to set world generation threads count to 1.");
unsafeThreadingRecorded = true;
}
return f.join();
}
@Override
public void resizeThreadPool(int newThreadCount) {
public void resizeThreadPool(int newThreadCount)
{
executors = Executors.newFixedThreadPool(newThreadCount,
new LodThreadFactory("Gen-Worker-Thread", Thread.MIN_PRIORITY));
}
@Override
public boolean tryAddPoint(int px, int pz, int range, Steps target, boolean genAllDetails) {
public boolean tryAddPoint(int px, int pz, int range, Steps target, boolean genAllDetails)
{
int boxSize = range * 2 + 1;
int x = Math.floorDiv(px, boxSize) * boxSize + range;
int z = Math.floorDiv(pz, boxSize) * boxSize + range;
for (GenerationEvent event : events) {
for (GenerationEvent event : events)
{
if (event.tooClose(x, z, range))
return false;
}
@@ -225,118 +287,160 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
events.add(new GenerationEvent(new ChunkPos(x, z), range, this, target, genAllDetails));
return true;
}
@Override
public void updateAllFutures() {
public void updateAllFutures()
{
if (unknownExceptionCount > 0) {
if (System.nanoTime() - lastExceptionTriggerTime >= EXCEPTION_TIMER_RESET_TIME) {
unknownExceptionCount = 0;
}
}
// Update all current out standing jobs
Iterator<GenerationEvent> iter = events.iterator();
while (iter.hasNext()) {
while (iter.hasNext())
{
GenerationEvent event = iter.next();
if (event.isCompleted()) {
try {
if (event.isCompleted())
{
try
{
event.join();
} catch (Throwable e) {
e.printStackTrace();
while (e.getCause() != null) {
e = e.getCause();
e.printStackTrace();
}
} finally {
}
catch (Throwable e)
{
EVENT_LOGGER.error("Batching World Generator: Event {} gotten an exception", event);
EVENT_LOGGER.error("Exception: ", e);
unknownExceptionCount++;
lastExceptionTriggerTime = System.nanoTime();
}
finally
{
iter.remove();
}
} else if (event.hasTimeout(TIMEOUT_SECONDS, TimeUnit.SECONDS)) {
ClientApi.LOGGER.error("Batching World Generator: " + event + " timed out and terminated!");
ClientApi.LOGGER.info("Dump PrefEvent: " + event.pEvent);
try {
}
else if (event.hasTimeout(TIMEOUT_SECONDS, TimeUnit.SECONDS))
{
EVENT_LOGGER.error("Batching World Generator: " + event + " timed out and terminated!");
EVENT_LOGGER.info("Dump PrefEvent: " + event.pEvent);
try
{
if (!event.terminate())
ClientApi.LOGGER.error("Failed to terminate the stuck generation event!");
} finally {
EVENT_LOGGER.error("Failed to terminate the stuck generation event!");
}
finally
{
iter.remove();
}
}
}
if (unknownExceptionCount > EXCEPTION_COUNTER_TRIGGER) {
EVENT_LOGGER.error("Too many exceptions in Batching World Generator! Disabling the generator.");
unknownExceptionCount = 0;
CONFIG.client().worldGenerator().setEnableDistantGeneration(false);
}
}
public BatchGenerationEnvironment(IWorldWrapper serverlevel, LodBuilder lodBuilder, LodDimension lodDim) {
public BatchGenerationEnvironment(IWorldWrapper serverlevel, LodBuilder lodBuilder, LodDimension lodDim)
{
super(serverlevel, lodBuilder, lodDim);
ClientApi.LOGGER.info("================WORLD_GEN_STEP_INITING=============");
EVENT_LOGGER.info("================WORLD_GEN_STEP_INITING=============");
ChunkGenerator generator = ((WorldWrapper) serverlevel).getServerWorld().getChunkSource().getGenerator();
if (!(generator instanceof NoiseBasedChunkGenerator ||
generator instanceof DebugLevelSource ||
generator instanceof FlatLevelSource)) {
EVENT_LOGGER.warn("Unknown Chunk Generator detected: [{}], Distant Generation May Fail!", generator.getClass());
EVENT_LOGGER.warn("If it does crash, set Distant Generation to OFF or Generation Mode to None.");
ApiShared.LOGGER.warn("Unknown Chunk Generator detected: {}", generator.getClass());
}
params = new GlobalParameters((ServerLevel) ((WorldWrapper) serverlevel).getWorld(), lodBuilder, lodDim);
}
@SuppressWarnings("resource")
private static ChunkAccess loadOrMakeChunk(ChunkPos chunkPos, ServerLevel level, LevelLightEngine lightEngine) {
if (DISABLE_LOADING_SAVES) {
return new ProtoChunk(chunkPos, UpgradeData.EMPTY);
}
public static ChunkAccess loadOrMakeChunk(ChunkPos chunkPos, ServerLevel level, LevelLightEngine lightEngine)
{
CompoundTag chunkData = null;
try {
try
{
chunkData = level.getChunkSource().chunkMap.readChunk(chunkPos);
} catch (IOException e) {
ClientApi.LOGGER.error("DistantHorizons: Couldn't load chunk {}", chunkPos, e);
}
if (chunkData == null) {
return new ProtoChunk(chunkPos, UpgradeData.EMPTY);
} else {
return ChunkLoader.read(level, lightEngine, chunkPos, chunkData);
catch (Exception e)
{
LOAD_LOGGER.error("DistantHorizons: Couldn't load chunk {}", chunkPos, e);
}
if (chunkData == null)
{
return new ProtoChunk(chunkPos, UpgradeData.EMPTY, level);
}
else
{
try {
return ChunkLoader.read(level, lightEngine, chunkPos, chunkData);
} catch (Exception e) {
LOAD_LOGGER.error("DistantHorizons: Couldn't load chunk {}", chunkPos, e);
return new ProtoChunk(chunkPos, UpgradeData.EMPTY, level);
}
}
}
void generateLodFromList(GenerationEvent e) {
if (ENABLE_EVENT_LOGGING)
ClientApi.LOGGER.info("Lod Generate Event: " + e.pos);
public void generateLodFromList(GenerationEvent e)
{
EVENT_LOGGER.debug("Lod Generate Event: " + e.pos);
e.pEvent.beginNano = System.nanoTime();
GridList<ChunkAccess> referencedChunks;
ArrayGridList<ChunkAccess> referencedChunks;
ArrayGridList<ChunkAccess> genChunks;
DistanceGenerationMode generationMode;
LightedWorldGenRegion region;
WorldGenLevelLightEngine lightEngine;
LightGetterAdaptor adaptor;
int refRange = e.range + RANGE_TO_RANGE_EMPTY_EXTENSION;
int refOffsetX = e.pos.x - refRange;
int refOffsetZ = e.pos.z - refRange;
try {
try
{
adaptor = new LightGetterAdaptor(params.level);
lightEngine = new WorldGenLevelLightEngine(adaptor);
int cx = e.pos.x;
int cy = e.pos.z;
int rangeEmpty = e.range + 1;
GridList<ChunkAccess> chunks = new GridList<ChunkAccess>(rangeEmpty);
@SuppressWarnings("resource")
EmptyChunkGenerator generator = (int x, int z) -> {
EmptyChunkGenerator generator = (int x, int z) ->
{
ChunkPos chunkPos = new ChunkPos(x, z);
ChunkAccess target = null;
try {
try
{
target = loadOrMakeChunk(chunkPos, params.level, lightEngine);
} catch (RuntimeException e2) {
}
catch (RuntimeException e2)
{
// Continue...
e2.printStackTrace();
}
if (target == null)
target = new ProtoChunk(chunkPos, UpgradeData.EMPTY);
target = new ProtoChunk(chunkPos, UpgradeData.EMPTY, params.level);
return target;
};
for (int oy = -rangeEmpty; oy <= rangeEmpty; oy++) {
for (int ox = -rangeEmpty; ox <= rangeEmpty; ox++) {
ChunkAccess target = generator.generate(cx + ox, cy + oy);
chunks.add(target);
}
}
referencedChunks = new ArrayGridList<>(refRange*2+1,
(x,z) -> generator.generate(x + refOffsetX,z + refOffsetZ)
);
e.pEvent.emptyNano = System.nanoTime();
e.refreshTimeout();
region = new LightedWorldGenRegion(params.level, lightEngine, e.tParam.structFeat, chunks,
ChunkStatus.STRUCTURE_STARTS, rangeEmpty, e.lightMode, generator);
region = new LightedWorldGenRegion(params.level, lightEngine, referencedChunks,
ChunkStatus.STRUCTURE_STARTS, refRange, e.lightMode, generator);
adaptor.setRegion(region);
e.tParam.makeStructFeat(region);
referencedChunks = chunks.subGrid(e.range);
referencedChunks = generateDirect(e, referencedChunks, e.target, region);
} catch (StructStartCorruptedException f) {
e.tParam.makeStructFeat(region, params);
genChunks = new ArrayGridList<>(referencedChunks, RANGE_TO_RANGE_EMPTY_EXTENSION,
referencedChunks.gridSize - RANGE_TO_RANGE_EMPTY_EXTENSION);
generateDirect(e, genChunks, e.target, region);
}
catch (StepStructureStart.StructStartCorruptedException f)
{
e.tParam.markAsInvalid();
return;
}
switch (e.target) {
switch (e.target)
{
case Empty:
case StructureStart:
case StructureReference:
@@ -344,7 +448,6 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
break;
case Biomes:
generationMode = DistanceGenerationMode.BIOME_ONLY;
break;
case Noise:
generationMode = DistanceGenerationMode.BIOME_ONLY_SIMULATE_HEIGHT;
break;
@@ -360,86 +463,106 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
default:
return;
}
int centreIndex = referencedChunks.size() / 2;
for (int oy = -e.range; oy <= e.range; oy++) {
for (int ox = -e.range; ox <= e.range; ox++) {
int targetIndex = referencedChunks.offsetOf(centreIndex, ox, oy);
ChunkAccess target = referencedChunks.get(targetIndex);
for (int oy = 0; oy < genChunks.gridSize; oy++)
{
for (int ox = 0; ox < genChunks.gridSize; ox++)
{
ChunkAccess target = genChunks.get(ox, oy);
target.setLightCorrect(true);
//if (target instanceof LevelChunk)
// ((LevelChunk) target).setClientLightReady(true);
boolean isFull = target.getStatus() == ChunkStatus.FULL || target instanceof LevelChunk;
if (isFull) {
if (ENABLE_LOAD_EVENT_LOGGING)
ClientApi.LOGGER.info("Detected full existing chunk at {}", target.getPos());
//boolean isPartial = target.isOldNoiseGeneration();
if (isFull)
{
LOAD_LOGGER.info("Detected full existing chunk at {}", target.getPos());
params.lodBuilder.generateLodNodeFromChunk(params.lodDim, new ChunkWrapper(target, region),
new LodBuilderConfig(DistanceGenerationMode.FULL), true, e.genAllDetails);
} else if (target.getStatus() == ChunkStatus.EMPTY && generationMode == DistanceGenerationMode.NONE) {
}
else if (target.getStatus() == ChunkStatus.EMPTY && generationMode == DistanceGenerationMode.NONE)
{
params.lodBuilder.generateLodNodeFromChunk(params.lodDim, new ChunkWrapper(target, region),
LodBuilderConfig.getFillVoidConfig(), true, e.genAllDetails);
} else {
}
else
{
params.lodBuilder.generateLodNodeFromChunk(params.lodDim, new ChunkWrapper(target, region),
new LodBuilderConfig(generationMode), true, e.genAllDetails);
}
lightEngine.retainData(target.getPos(), false);
if (e.lightMode == LightGenerationMode.FANCY || isFull)
{
lightEngine.retainData(target.getPos(), false);
}
}
}
e.pEvent.endNano = System.nanoTime();
e.refreshTimeout();
if (ENABLE_PERF_LOGGING) {
if (PREF_LOGGER.canMaybeLog())
{
e.tParam.perf.recordEvent(e.pEvent);
ClientApi.LOGGER.info(e.tParam.perf);
PREF_LOGGER.infoInc("{}", e.tParam.perf);
}
}
GridList<ChunkAccess> generateDirect(GenerationEvent e, GridList<ChunkAccess> subRange, Steps step,
LightedWorldGenRegion region) {
try {
subRange.forEach((chunk) -> {
if (chunk instanceof ProtoChunk) {
public void generateDirect(GenerationEvent e, ArrayGridList<ChunkAccess> subRange, Steps step,
LightedWorldGenRegion region)
{
try
{
subRange.forEach((chunk) ->
{
if (chunk instanceof ProtoChunk)
{
((ProtoChunk) chunk).setLightEngine(region.getLightEngine());
//region.getLightEngine().retainData(chunk.getPos(), true);
region.getLightEngine().retainData(chunk.getPos(), true);
}
});
if (step == Steps.Empty)
return subRange;
return;
stepStructureStart.generateGroup(e.tParam, region, subRange);
e.pEvent.structStartNano = System.nanoTime();
e.refreshTimeout();
if (step == Steps.StructureStart)
return subRange;
return;
stepStructureReference.generateGroup(e.tParam, region, subRange);
e.pEvent.structRefNano = System.nanoTime();
e.refreshTimeout();
if (step == Steps.StructureReference)
return subRange;
return;
stepBiomes.generateGroup(e.tParam, region, subRange);
e.pEvent.biomeNano = System.nanoTime();
e.refreshTimeout();
if (step == Steps.Biomes)
return subRange;
return;
stepNoise.generateGroup(e.tParam, region, subRange);
e.pEvent.noiseNano = System.nanoTime();
e.refreshTimeout();
if (step == Steps.Noise)
return subRange;
return;
stepSurface.generateGroup(e.tParam, region, subRange);
e.pEvent.surfaceNano = System.nanoTime();
e.refreshTimeout();
if (step == Steps.Surface)
return subRange;
return;
if (step == Steps.Carvers)
return subRange;
return;
stepFeatures.generateGroup(e.tParam, region, subRange);
e.pEvent.featureNano = System.nanoTime();
e.refreshTimeout();
return subRange;
} finally {
switch (region.lightMode) {
return;
}
finally
{
switch (region.lightMode)
{
case FANCY:
stepLight.generateGroup(region.getLightEngine(), subRange);
break;
case FAST:
subRange.forEach((p) -> {
subRange.forEach((p) ->
{
if (p instanceof ProtoChunk)
((ProtoChunk) p).setLightCorrect(true);
});
@@ -449,8 +572,9 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
e.refreshTimeout();
}
}
public interface EmptyChunkGenerator {
public interface EmptyChunkGenerator
{
ChunkAccess generate(int x, int z);
}
@@ -461,16 +585,14 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
@Override
public void stop(boolean blocking) {
ClientApi.LOGGER.info("Batch Chunk Generator shutting down...");
EVENT_LOGGER.info("Batch Chunk Generator shutting down...");
executors.shutdownNow();
if (blocking) {
try {
if (!executors.awaitTermination(10, TimeUnit.SECONDS)) {
ClientApi.LOGGER.error("Batch Chunk Generator shutdown failed! Ignoring child threads...");
}
} catch (InterruptedException e) {
ClientApi.LOGGER.error("Batch Chunk Generator shutdown failed! Ignoring child threads...", e);
if (blocking) try {
if (!executors.awaitTermination(10, TimeUnit.SECONDS)) {
EVENT_LOGGER.error("Batch Chunk Generator shutdown failed! Ignoring child threads...");
}
} catch (InterruptedException e) {
EVENT_LOGGER.error("Batch Chunk Generator shutdown failed! Ignoring child threads...", e);
}
}
}
}
@@ -1,3 +1,4 @@
package com.seibel.lod.common.wrappers.worldGeneration;
import java.util.concurrent.ExecutionException;
@@ -5,18 +6,20 @@ import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment.PrefEvent;
import com.seibel.lod.core.api.ApiShared;
import com.seibel.lod.core.api.ClientApi;
import com.seibel.lod.core.enums.config.LightGenerationMode;
import com.seibel.lod.core.util.SingletonHandler;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
import com.seibel.lod.core.wrapperInterfaces.worldGeneration.AbstractBatchGenerationEnvionmentWrapper.Steps;
import net.minecraft.world.level.ChunkPos;
//======================= Main Event class======================
public final class GenerationEvent {
public final class GenerationEvent
{
static private final ILodConfigWrapperSingleton CONFIG = SingletonHandler.get(ILodConfigWrapperSingleton.class);
private static int generationFutureDebugIDs = 0;
final ThreadedParameters tParam;
final ChunkPos pos;
@@ -28,8 +31,9 @@ public final class GenerationEvent {
final LightGenerationMode lightMode;
final PrefEvent pEvent = new PrefEvent();
final boolean genAllDetails;
public GenerationEvent(ChunkPos pos, int range, BatchGenerationEnvironment generationGroup, Steps target, boolean genAllDetails) {
public GenerationEvent(ChunkPos pos, int range, BatchGenerationEnvironment generationGroup, Steps target, boolean genAllDetails)
{
nanotime = System.nanoTime();
this.pos = pos;
this.range = range;
@@ -37,54 +41,70 @@ public final class GenerationEvent {
this.target = target;
this.tParam = ThreadedParameters.getOrMake(generationGroup.params);
LightGenerationMode mode = CONFIG.client().worldGenerator().getLightGenerationMode();
this.lightMode = mode;
this.genAllDetails = genAllDetails;
future = generationGroup.executors.submit(() -> {
generationGroup.generateLodFromList(this);
future = generationGroup.executors.submit(() ->
{
BatchGenerationEnvironment.isDistantGeneratorThread.set(true);
try {
generationGroup.generateLodFromList(this);
} finally {
BatchGenerationEnvironment.isDistantGeneratorThread.remove();
}
});
}
public boolean isCompleted() {
public boolean isCompleted()
{
return future.isDone();
}
public boolean hasTimeout(int duration, TimeUnit unit) {
public boolean hasTimeout(int duration, TimeUnit unit)
{
long currentTime = System.nanoTime();
long delta = currentTime - nanotime;
return (delta > TimeUnit.NANOSECONDS.convert(duration, unit));
}
public boolean terminate() {
public boolean terminate()
{
future.cancel(true);
ClientApi.LOGGER.info("======================DUMPING ALL THREADS FOR WORLD GEN=======================");
ApiShared.LOGGER.info("======================DUMPING ALL THREADS FOR WORLD GEN=======================");
BatchGenerationEnvironment.threadFactory.dumpAllThreadStacks();
return future.isCancelled();
}
public void join() {
try {
public void join()
{
try
{
future.get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
catch (InterruptedException | ExecutionException e)
{
throw new RuntimeException(e.getCause()==null? e : e.getCause());
}
}
public boolean tooClose(int cx, int cz, int cr) {
public boolean tooClose(int cx, int cz, int cr)
{
int distX = Math.abs(cx - pos.x);
int distZ = Math.abs(cz - pos.z);
int minRange = cr + range + 1; // Need one to account for the center
minRange += 1 + 1; // Account for required empty chunks
return distX < minRange && distZ < minRange;
}
public void refreshTimeout() {
public void refreshTimeout()
{
nanotime = System.nanoTime();
}
@Override
public String toString() {
public String toString()
{
return id + ":" + range + "@" + pos + "(" + target + ")";
}
}
@@ -1,3 +1,4 @@
package com.seibel.lod.common.wrappers.worldGeneration;
import com.mojang.datafixers.DataFixer;
@@ -15,9 +16,11 @@ import net.minecraft.world.level.levelgen.WorldGenSettings;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager;
import net.minecraft.world.level.storage.WorldData;
public final class GlobalParameters {
public final class GlobalParameters
{
public final ChunkGenerator generator;
public final StructureManager structures;
//public final BiomeManager biomeManager;
public final WorldGenSettings worldGenSettings;
public final ThreadedLevelLightEngine lightEngine;
public final LodBuilder lodBuilder;
@@ -27,8 +30,9 @@ public final class GlobalParameters {
public final long worldSeed;
public final ServerLevel level; // TODO: Figure out a way to remove this. Maybe ClientLevel also works?
public final DataFixer fixerUpper;
public GlobalParameters(ServerLevel level, LodBuilder lodBuilder, LodDimension lodDim) {
public GlobalParameters(ServerLevel level, LodBuilder lodBuilder, LodDimension lodDim)
{
this.lodBuilder = lodBuilder;
this.lodDim = lodDim;
this.level = level;
@@ -39,8 +43,7 @@ public final class GlobalParameters {
registry = server.registryAccess();
biomes = registry.registryOrThrow(Registry.BIOME_REGISTRY);
worldSeed = worldGenSettings.seed();
// biomeManager = new BiomeManager(level,
// BiomeManager.obfuscateSeed(worldSeed));
//biomeManager = new BiomeManager(level, BiomeManager.obfuscateSeed(worldSeed));
structures = server.getStructureManager();
generator = level.getChunkSource().getGenerator();
fixerUpper = server.getFixerUpper();
@@ -1,29 +1,34 @@
package com.seibel.lod.common.wrappers.worldGeneration;
//FIXME: Move this outside the WorldGenerationStep thingy
public class Rolling {
public class Rolling
{
private final int size;
private double total = 0d;
private int index = 0;
private final double[] samples;
public Rolling(int size) {
public Rolling(int size)
{
this.size = size;
samples = new double[size];
for (int i = 0; i < size; i++)
samples[i] = 0d;
}
public void add(double x) {
public void add(double x)
{
total -= samples[index];
samples[index] = x;
total += x;
if (++index == size)
index = 0; // cheaper than modulus
}
public double getAverage() {
public double getAverage()
{
return total / size;
}
}
@@ -1,11 +0,0 @@
package com.seibel.lod.common.wrappers.worldGeneration;
public class StructStartCorruptedException extends RuntimeException {
private static final long serialVersionUID = -8987434342051563358L;
public StructStartCorruptedException(ArrayIndexOutOfBoundsException e) {
super("StructStartCorruptedException");
super.initCause(e);
fillInStackTrace();
}
}
@@ -1,3 +1,4 @@
package com.seibel.lod.common.wrappers.worldGeneration;
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment.PerfCalculator;
@@ -7,14 +8,16 @@ import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.levelgen.WorldGenSettings;
public final class ThreadedParameters {
public final class ThreadedParameters
{
private static final ThreadLocal<ThreadedParameters> localParam = new ThreadLocal<ThreadedParameters>();
final ServerLevel level;
public final WorldGenStructFeatManager structFeat;
public WorldGenStructFeatManager structFeat = null;
boolean isValid = true;
public final PerfCalculator perf = new PerfCalculator();
public static ThreadedParameters getOrMake(GlobalParameters param) {
public static ThreadedParameters getOrMake(GlobalParameters param)
{
ThreadedParameters tParam = localParam.get();
if (tParam != null && tParam.isValid && tParam.level == param.level)
return tParam;
@@ -22,17 +25,18 @@ public final class ThreadedParameters {
localParam.set(tParam);
return tParam;
}
public void markAsInvalid() {
public void markAsInvalid()
{
isValid = false;
}
private ThreadedParameters(GlobalParameters param) {
private ThreadedParameters(GlobalParameters param)
{
level = param.level;
structFeat = new WorldGenStructFeatManager(level, param.worldGenSettings, null);
structFeat = new WorldGenStructFeatManager(level, param.worldGenSettings);
}
public void makeStructFeat(WorldGenLevel genLevel) {
structFeat.setGenLevel(genLevel);
public void makeStructFeat(WorldGenLevel genLevel, GlobalParameters param) {
structFeat = new WorldGenStructFeatManager(param.worldGenSettings, genLevel);
}
}
@@ -1,144 +0,0 @@
package com.seibel.lod.common.wrappers.worldGeneration;
import java.util.concurrent.ExecutionException;
import com.seibel.lod.core.builders.lodBuilding.LodBuilder;
import com.seibel.lod.core.builders.lodBuilding.LodBuilderConfig;
import com.seibel.lod.core.enums.config.DistanceGenerationMode;
import com.seibel.lod.core.objects.lod.LodDimension;
//import com.seibel.lod.core.util.SingletonHandler;
import com.seibel.lod.core.wrapperInterfaces.chunk.AbstractChunkPosWrapper;
//import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
import com.seibel.lod.core.wrapperInterfaces.worldGeneration.AbstractWorldGeneratorWrapper;
import com.seibel.lod.common.wrappers.chunk.ChunkWrapper;
import com.seibel.lod.common.wrappers.world.WorldWrapper;
import net.minecraft.server.level.ChunkHolder;
import net.minecraft.server.level.ServerChunkCache;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.chunk.*;
/**
* @author James Seibel
* @version 11-13-2021
*/
public class WorldGeneratorWrapper extends AbstractWorldGeneratorWrapper {
public final ServerLevel serverWorld;
public final LodDimension lodDim;
public final LodBuilder lodBuilder;
public WorldGeneratorWrapper(LodBuilder newLodBuilder, LodDimension newLodDimension, IWorldWrapper worldWrapper) {
super(newLodBuilder, newLodDimension, worldWrapper);
lodBuilder = newLodBuilder;
lodDim = newLodDimension;
serverWorld = ((WorldWrapper) worldWrapper).getServerWorld();
}
/** takes about 2-5 ms */
@Override
public void generateBiomesOnly(AbstractChunkPosWrapper pos, DistanceGenerationMode generationMode) {
generate(pos.getX(), pos.getZ(), generationMode);
}
/** takes about 10 - 20 ms */
@Override
public void generateSurface(AbstractChunkPosWrapper pos) {
generate(pos.getX(), pos.getZ(), DistanceGenerationMode.SURFACE);
}
/**
* takes about 15 - 20 ms
* <p>
*/
@Override
public void generateFeatures(AbstractChunkPosWrapper pos) {
generate(pos.getX(), pos.getZ(), DistanceGenerationMode.FEATURES);
}
/**
* Generates using MC's ServerWorld.
* <p>
* on pre generated chunks 0 - 1 ms <br>
* on un generated chunks 0 - 50 ms <br>
* with the median seeming to hover around 15 - 30 ms <br>
* and outliers in the 100 - 200 ms range <br>
* <p>
* Note this should not be multithreaded and does cause server/simulation lag
* (Higher lag for generating than loading)
*/
@Override
public void generateFull(AbstractChunkPosWrapper pos) {
generate(pos.getX(), pos.getZ(), DistanceGenerationMode.FULL);
}
private void generate(int chunkX, int chunkZ, DistanceGenerationMode generationMode) {
// long t = System.nanoTime();
ChunkStatus targetStatus;
switch (generationMode) {
case NONE:
return;
case BIOME_ONLY:
targetStatus = ChunkStatus.BIOMES;
break;
case BIOME_ONLY_SIMULATE_HEIGHT:
targetStatus = ChunkStatus.NOISE;
break;
case SURFACE:
targetStatus = ChunkStatus.SURFACE;
break;
case FEATURES:
targetStatus = ChunkStatus.FEATURES;
break;
case FULL:
targetStatus = ChunkStatus.FULL;
break;
default:
return;
}
// The bool=true means that we wants to generate chunk, and that the returned
// ChunkAccess must not be null
ChunkAccess ca = serverWorld.getChunkSource().getChunk(chunkX, chunkZ, targetStatus, true);
if (ca == null)
throw new RuntimeException("This should NEVER be null due to bool being true");
lodBuilder.generateLodNodeFromChunk(lodDim, new ChunkWrapper(ca, serverWorld),
new LodBuilderConfig(generationMode), false, true);
// long duration = System.nanoTime()-t;
// Debug print the duration
// System.out.println("LodChunkGenFull["+chunkX+","+chunkZ+"]:
// "+(double)(duration)/1000.);
}
/*
* TODO: Ask leetom to update chart performance/generation tests related to
* serverWorld.getChunk(x, z, ChunkStatus. *** )
*
* true/false is whether they generated blocks or not the time is how long it
* took to generate
*
* ChunkStatus.EMPTY 0 - 1 ms false (empty, what did you expect? :P)
* ChunkStatus.STRUCTURE_REFERENCES 1 - 2 ms false (no height, only generates
* some chunks) ChunkStatus.BIOMES 1 - 10 ms false (no height) ChunkStatus.NOISE
* 4 - 15 ms true (all blocks are stone) ChunkStatus.LIQUID_CARVERS 6 - 12 ms
* true (no snow/trees, just grass) ChunkStatus.SURFACE 5 - 15 ms true (no
* snow/trees, just grass) ChunkStatus.CARVERS 5 - 30 ms true (no snow/trees,
* just grass) ChunkStatus.FEATURES 7 - 25 ms true ChunkStatus.HEIGHTMAPS 20 -
* 40 ms true ChunkStatus.LIGHT 20 - 40 ms true ChunkStatus.FULL 30 - 50 ms true
* ChunkStatus.SPAWN 50 - 80 ms true
*
*
* At this point I would suggest using FEATURES, as it generates snow and trees
* (and any other object that are needed to make biomes distinct)
*
* Otherwise, if snow/trees aren't necessary SURFACE is the next fastest
* (although not by much)
*/
}
@@ -1,10 +1,12 @@
package com.seibel.lod.common.wrappers.worldGeneration.mimicObject;
import com.seibel.lod.core.api.ClientApi;
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment;
import com.seibel.lod.core.api.ApiShared;
import java.util.Objects;
import com.seibel.lod.core.logging.ConfigBasedLogger;
import net.minecraft.core.Registry;
import net.minecraft.core.SectionPos;
import net.minecraft.nbt.CompoundTag;
@@ -16,7 +18,6 @@ import net.minecraft.world.level.TickList;
import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.chunk.ChunkBiomeContainer;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.chunk.DataLayer;
import net.minecraft.world.level.chunk.LevelChunk;
@@ -31,13 +32,14 @@ import net.minecraft.world.level.material.Fluids;
import org.apache.logging.log4j.Logger;
public class ChunkLoader {
private static final Logger LOGGER = ClientApi.LOGGER;
private static final ConfigBasedLogger LOGGER = BatchGenerationEnvironment.LOAD_LOGGER;
private static LevelChunkSection[] readSections(WorldGenLevel level, LevelLightEngine lightEngine,
ChunkPos chunkPos, CompoundTag tagLevel) {
boolean isLightOn = tagLevel.getBoolean("isLightOn");
ListTag listTag = tagLevel.getList("Sections", 10);
LevelChunkSection[] levelChunkSections = new LevelChunkSection[16];
int i = level.getSectionsCount();
LevelChunkSection[] levelChunkSections = new LevelChunkSection[i];
boolean bl2 = level.getLevel().dimensionType().hasSkyLight();
if (isLightOn)
lightEngine.retainData(chunkPos, true);
@@ -50,7 +52,7 @@ public class ChunkLoader {
compoundTag3.getLongArray("BlockStates"));
levelChunkSection.recalcBlockCounts();
if (!levelChunkSection.isEmpty())
levelChunkSections[k] = levelChunkSection;
levelChunkSections[level.getSectionIndexFromSectionY(k)] = levelChunkSection;
}
if (isLightOn) {
if (compoundTag3.contains("BlockLight", 7))
@@ -102,32 +104,30 @@ public class ChunkLoader {
ChunkPos actualPos = new ChunkPos(tagLevel.getInt("xPos"), tagLevel.getInt("zPos"));
if (!Objects.equals(chunkPos, actualPos)) {
LOGGER.error("Distant Horizons: Chunk file at {} is in the wrong location; Ignoring. (Expected {}, got {})",
(Object) chunkPos, (Object) chunkPos, (Object) actualPos);
LOGGER.error("Chunk file at {} is in the wrong location; Ignoring. (Expected {}, got {})", (Object) chunkPos, (Object) chunkPos, (Object) actualPos);
return null;
}
// ====================== Read params for making the LevelChunk
// ============================
ChunkBiomeContainer chunkBiomeContainer = new ChunkBiomeContainer(
level.getLevel().registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), chunkPos,
level.getLevel().registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), level, chunkPos,
level.getLevel().getChunkSource().getGenerator().getBiomeSource(),
tagLevel.contains("Biomes", 11) ? tagLevel.getIntArray("Biomes") : null);
UpgradeData upgradeData = tagLevel.contains("UpgradeData", 10)
? new UpgradeData(tagLevel.getCompound("UpgradeData"))
? new UpgradeData(tagLevel.getCompound("UpgradeData"), level)
: UpgradeData.EMPTY;
TickList<Block> blockTicks = tagLevel.contains("TileTicks", 9)
? ChunkTickList.create(tagLevel.getList("TileTicks", 10), Registry.BLOCK::getKey, Registry.BLOCK::get)
: new ProtoTickList<Block>(block -> (block == null || block.defaultBlockState().isAir()), chunkPos,
tagLevel.getList("ToBeTicked", 9));
tagLevel.getList("ToBeTicked", 9), level);
TickList<Fluid> liquidTicks = tagLevel.contains("LiquidTicks", 9)
? ChunkTickList.create(tagLevel.getList("LiquidTicks", 10), Registry.FLUID::getKey, Registry.FLUID::get)
: new ProtoTickList<Fluid>(fluid -> (fluid == null || fluid == Fluids.EMPTY), chunkPos,
tagLevel.getList("LiquidsToBeTicked", 9));
tagLevel.getList("LiquidsToBeTicked", 9), level);
long inhabitedTime = tagLevel.getLong("InhabitedTime");
@@ -143,7 +143,7 @@ public class ChunkLoader {
chunk.setLightCorrect(tagLevel.getBoolean("isLightOn"));
readHeightmaps(chunk, tagLevel);
readPostPocessings(chunk, tagLevel);
// ClientApi.LOGGER.info("Loaded chunk @ "+chunk.getPos());
// ApiShared.LOGGER.info("Loaded chunk @ "+chunk.getPos());
return chunk;
}
}
@@ -1,9 +1,10 @@
package com.seibel.lod.common.wrappers.worldGeneration.mimicObject;
import com.seibel.lod.core.api.ModAccessorApi;
import com.seibel.lod.core.handlers.dependencyInjection.ModAccessorHandler;
import com.seibel.lod.core.wrapperInterfaces.modAccessor.IStarlightAccessor;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.LevelHeightAccessor;
import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.chunk.LightChunkGetter;
@@ -14,7 +15,7 @@ public class LightGetterAdaptor implements LightChunkGetter {
public LightGetterAdaptor(BlockGetter heightAccessor) {
this.heightGetter = heightAccessor;
shouldReturnNull = ModAccessorApi.get(IStarlightAccessor.class) != null;
shouldReturnNull = ModAccessorHandler.get(IStarlightAccessor.class) != null;
}
public void setRegion(LightedWorldGenRegion region) {
@@ -33,4 +34,7 @@ public class LightGetterAdaptor implements LightChunkGetter {
public BlockGetter getLevel() {
return shouldReturnNull ? null : (genRegion != null ? genRegion : heightGetter);
}
public LevelHeightAccessor getLevelHeightAccessor() {
return heightGetter;
}
}
@@ -3,22 +3,32 @@ package com.seibel.lod.common.wrappers.worldGeneration.mimicObject;
import java.util.List;
import java.util.stream.Stream;
import com.seibel.lod.core.api.ApiShared;
import org.jetbrains.annotations.Nullable;
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment.EmptyChunkGenerator;
import com.seibel.lod.core.api.ApiShared;
import com.seibel.lod.core.api.ClientApi;
import com.seibel.lod.core.enums.config.LightGenerationMode;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
import net.minecraft.Util;
import net.minecraft.client.Minecraft;
import net.minecraft.client.color.block.BlockTintCache;
import net.minecraft.client.renderer.BiomeColors;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Cursor3D;
import net.minecraft.core.SectionPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.WorldGenRegion;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.ColorResolver;
import net.minecraft.world.level.LightLayer;
import net.minecraft.world.level.StructureFeatureManager;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
@@ -39,39 +49,54 @@ public class LightedWorldGenRegion extends WorldGenRegion {
public final int size;
private final ChunkPos firstPos;
private final List<ChunkAccess> cache;
private final StructureFeatureManager structFeat;
Long2ObjectOpenHashMap<ChunkAccess> chunkMap = new Long2ObjectOpenHashMap<ChunkAccess>();
private ChunkPos overrideCenterPos = null;
public void setOverrideCenter(ChunkPos pos) {overrideCenterPos = pos;}
@Override
public int getCenterX() {
return overrideCenterPos==null ? super.getCenterX() : overrideCenterPos.x;
}
@Override
public int getCenterZ() {
return overrideCenterPos==null ? super.getCenterZ() : overrideCenterPos.z;
public ChunkPos getCenter() {
return overrideCenterPos==null ? super.getCenter() : overrideCenterPos;
}
public LightedWorldGenRegion(ServerLevel serverLevel, WorldGenLevelLightEngine lightEngine,
StructureFeatureManager structFeat, List<ChunkAccess> list, ChunkStatus chunkStatus, int i,
List<ChunkAccess> list, ChunkStatus chunkStatus, int i,
LightGenerationMode lightMode, EmptyChunkGenerator generator) {
super(serverLevel, list);
super(serverLevel, list, chunkStatus, i);
this.lightMode = lightMode;
this.firstPos = list.get(0).getPos();
this.generator = generator;
this.structFeat = structFeat;
light = lightEngine;
writeRadius = i;
cache = list;
size = Mth.floor(Math.sqrt(list.size()));
this.tintCaches = Util.make(new Object2ObjectArrayMap(3), object2ObjectArrayMap -> {
object2ObjectArrayMap.put(BiomeColors.GRASS_COLOR_RESOLVER, new BlockTintCache());
object2ObjectArrayMap.put(BiomeColors.FOLIAGE_COLOR_RESOLVER, new BlockTintCache());
object2ObjectArrayMap.put(BiomeColors.WATER_COLOR_RESOLVER, new BlockTintCache());
});
}
@Override
public Stream<? extends StructureStart<?>> startsForFeature(SectionPos sectionPos,
StructureFeature<?> structureFeature) {
return structFeat.startsForFeature(sectionPos, structureFeature);
}
// Bypass BCLib mixin overrides.
@Override
public boolean ensureCanWrite(BlockPos blockPos) {
int i = SectionPos.blockToSectionCoord(blockPos.getX());
int j = SectionPos.blockToSectionCoord(blockPos.getZ());
ChunkPos chunkPos = this.getCenter();
int k = Math.abs(chunkPos.x - i);
int l = Math.abs(chunkPos.z - j);
if (k > this.writeRadius || l > this.writeRadius) {
return false;
}
return true;
}
// TODO Check this
// @Override
// public List<? extends StructureStart<?>> startsForFeature(SectionPos sectionPos,
// StructureFeature<?> structureFeature) {
// return structFeat.startsForFeature(sectionPos, structureFeature);
// }
// Skip updating the related tile entities
@Override
@@ -173,7 +198,7 @@ public class LightedWorldGenRegion extends WorldGenRegion {
}
}
if (chunkStatus != ChunkStatus.EMPTY && chunkStatus != debugTriggeredForStatus) {
ClientApi.LOGGER.info("WorldGen requiring " + chunkStatus
ApiShared.LOGGER.info("WorldGen requiring " + chunkStatus
+ " outside expected range detected. Force passing EMPTY chunk and seeing if it works.");
debugTriggeredForStatus = chunkStatus;
}
@@ -214,4 +239,37 @@ public class LightedWorldGenRegion extends WorldGenRegion {
return (getBrightness(LightLayer.SKY, blockPos) >= getMaxLightLevel());
}
private final Object2ObjectArrayMap<ColorResolver, BlockTintCache> tintCaches;
public int getBlockTint(BlockPos blockPos, ColorResolver colorResolver)
{
BlockTintCache blockTintCache = (BlockTintCache) this.tintCaches.get(colorResolver);
return blockTintCache.getColor(blockPos, null); // FIXME[Generator]: Replace this null with something else
}
private Biome _getBiome(BlockPos pos) {
return getBiome(pos);
}
public int calculateBlockTint(BlockPos blockPos, ColorResolver colorResolver)
{
int i = (Minecraft.getInstance()).options.biomeBlendRadius;
if (i == 0)
return colorResolver.getColor((Biome) getBiome(blockPos), blockPos.getX(), blockPos.getZ());
int j = (i * 2 + 1) * (i * 2 + 1);
int k = 0;
int l = 0;
int m = 0;
Cursor3D cursor3D = new Cursor3D(blockPos.getX() - i, blockPos.getY(), blockPos.getZ() - i, blockPos.getX() + i, blockPos.getY(), blockPos.getZ() + i);
BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos();
while (cursor3D.advance())
{
mutableBlockPos.set(cursor3D.nextX(), cursor3D.nextY(), cursor3D.nextZ());
int n = colorResolver.getColor((Biome) getBiome((BlockPos) mutableBlockPos), mutableBlockPos.getX(), mutableBlockPos.getZ());
k += (n & 0xFF0000) >> 16;
l += (n & 0xFF00) >> 8;
m += n & 0xFF;
}
return (k / j & 0xFF) << 16 | (l / j & 0xFF) << 8 | m / j & 0xFF;
}
}
@@ -5,6 +5,7 @@ import org.jetbrains.annotations.Nullable;
import net.minecraft.core.BlockPos;
import net.minecraft.core.SectionPos;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.LevelHeightAccessor;
import net.minecraft.world.level.LightLayer;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.DataLayer;
@@ -16,149 +17,161 @@ import net.minecraft.world.level.lighting.SkyLightEngine;
public class WorldGenLevelLightEngine extends LevelLightEngine {
public static final int MAX_SOURCE_LEVEL = 15;
public static final int LIGHT_SECTION_PADDING = 1;
@Nullable
public final BlockLightEngine blockEngine;
@Nullable
public final SkyLightEngine skyEngine;
public static final int LIGHT_SECTION_PADDING = 1;
protected final LevelHeightAccessor levelHeightAccessor;
@Nullable
public final BlockLightEngine blockEngine;
@Nullable
public final SkyLightEngine skyEngine;
public WorldGenLevelLightEngine(LightGetterAdaptor genRegion) {
super(genRegion, false, false);
this.blockEngine = new BlockLightEngine(genRegion);
this.skyEngine = new SkyLightEngine(genRegion);
}
public WorldGenLevelLightEngine(LightGetterAdaptor genRegion) {
super(genRegion, false, false);
this.levelHeightAccessor = genRegion.getLevelHeightAccessor();
this.blockEngine = new BlockLightEngine(genRegion);
this.skyEngine = new SkyLightEngine(genRegion);
}
@Override
public void checkBlock(BlockPos blockPos) {
if (this.blockEngine != null) {
this.blockEngine.checkBlock(blockPos);
}
if (this.skyEngine != null) {
this.skyEngine.checkBlock(blockPos);
}
}
@Override
public void checkBlock(BlockPos blockPos) {
if (this.blockEngine != null) {
this.blockEngine.checkBlock(blockPos);
}
if (this.skyEngine != null) {
this.skyEngine.checkBlock(blockPos);
}
}
@Override
public void onBlockEmissionIncrease(BlockPos blockPos, int i) {
if (this.blockEngine != null) {
this.blockEngine.onBlockEmissionIncrease(blockPos, i);
}
}
@Override
public void onBlockEmissionIncrease(BlockPos blockPos, int i) {
if (this.blockEngine != null) {
this.blockEngine.onBlockEmissionIncrease(blockPos, i);
}
}
@Override
public boolean hasLightWork() {
if (this.skyEngine != null && this.skyEngine.hasLightWork()) {
return true;
}
return this.blockEngine != null && this.blockEngine.hasLightWork();
}
@Override
public boolean hasLightWork() {
if (this.skyEngine != null && this.skyEngine.hasLightWork()) {
return true;
}
return this.blockEngine != null && this.blockEngine.hasLightWork();
}
@Override
public int runUpdates(int i, boolean bl, boolean bl2) {
if (this.blockEngine != null && this.skyEngine != null) {
int j = i / 2;
int k = this.blockEngine.runUpdates(j, bl, bl2);
int l = i - j + k;
int m = this.skyEngine.runUpdates(l, bl, bl2);
if (k == 0 && m > 0) {
return this.blockEngine.runUpdates(m, bl, bl2);
}
return m;
}
if (this.blockEngine != null) {
return this.blockEngine.runUpdates(i, bl, bl2);
}
if (this.skyEngine != null) {
return this.skyEngine.runUpdates(i, bl, bl2);
}
return i;
}
@Override
public int runUpdates(int i, boolean bl, boolean bl2) {
if (this.blockEngine != null && this.skyEngine != null) {
int j = i / 2;
int k = this.blockEngine.runUpdates(j, bl, bl2);
int l = i - j + k;
int m = this.skyEngine.runUpdates(l, bl, bl2);
if (k == 0 && m > 0) {
return this.blockEngine.runUpdates(m, bl, bl2);
}
return m;
}
if (this.blockEngine != null) {
return this.blockEngine.runUpdates(i, bl, bl2);
}
if (this.skyEngine != null) {
return this.skyEngine.runUpdates(i, bl, bl2);
}
return i;
}
@Override
public void updateSectionStatus(SectionPos sectionPos, boolean bl) {
if (this.blockEngine != null) {
this.blockEngine.updateSectionStatus(sectionPos, bl);
}
if (this.skyEngine != null) {
this.skyEngine.updateSectionStatus(sectionPos, bl);
}
}
@Override
public void updateSectionStatus(SectionPos sectionPos, boolean bl) {
if (this.blockEngine != null) {
this.blockEngine.updateSectionStatus(sectionPos, bl);
}
if (this.skyEngine != null) {
this.skyEngine.updateSectionStatus(sectionPos, bl);
}
}
@Override
public void enableLightSources(ChunkPos chunkPos, boolean bl) {
if (this.blockEngine != null) {
this.blockEngine.enableLightSources(chunkPos, bl);
}
if (this.skyEngine != null) {
this.skyEngine.enableLightSources(chunkPos, bl);
}
}
@Override
public void enableLightSources(ChunkPos chunkPos, boolean bl) {
if (this.blockEngine != null) {
this.blockEngine.enableLightSources(chunkPos, bl);
}
if (this.skyEngine != null) {
this.skyEngine.enableLightSources(chunkPos, bl);
}
}
@Override
public LayerLightEventListener getLayerListener(LightLayer lightLayer) {
if (lightLayer == LightLayer.BLOCK) {
if (this.blockEngine == null) {
return LayerLightEventListener.DummyLightLayerEventListener.INSTANCE;
}
return this.blockEngine;
}
if (this.skyEngine == null) {
return LayerLightEventListener.DummyLightLayerEventListener.INSTANCE;
}
return this.skyEngine;
}
@Override
public LayerLightEventListener getLayerListener(LightLayer lightLayer) {
if (lightLayer == LightLayer.BLOCK) {
if (this.blockEngine == null) {
return LayerLightEventListener.DummyLightLayerEventListener.INSTANCE;
}
return this.blockEngine;
}
if (this.skyEngine == null) {
return LayerLightEventListener.DummyLightLayerEventListener.INSTANCE;
}
return this.skyEngine;
}
@Override
public int getRawBrightness(BlockPos blockPos, int i) {
int j = this.skyEngine == null ? 0 : this.skyEngine.getLightValue(blockPos) - i;
int k = this.blockEngine == null ? 0 : this.blockEngine.getLightValue(blockPos);
return Math.max(k, j);
}
@Override
public int getRawBrightness(BlockPos blockPos, int i) {
int j = this.skyEngine == null ? 0 : this.skyEngine.getLightValue(blockPos) - i;
int k = this.blockEngine == null ? 0 : this.blockEngine.getLightValue(blockPos);
return Math.max(k, j);
}
public void lightChunk(ChunkAccess chunkAccess, boolean needLightBlockUpdate) {
ChunkPos chunkPos = chunkAccess.getPos();
chunkAccess.setLightCorrect(false);
LevelChunkSection[] levelChunkSections = chunkAccess.getSections();
for (int i = 0; i < 16; i++) {
LevelChunkSection levelChunkSection = levelChunkSections[i];
public void lightChunk(ChunkAccess chunkAccess, boolean needLightBlockUpdate) {
ChunkPos chunkPos = chunkAccess.getPos();
chunkAccess.setLightCorrect(false);
LevelChunkSection[] levelChunkSections = chunkAccess.getSections();
for (int i = 0; i < chunkAccess.getSectionsCount(); ++i) {
LevelChunkSection levelChunkSection = levelChunkSections[i];
if (!LevelChunkSection.isEmpty(levelChunkSection)) {
updateSectionStatus(SectionPos.of(chunkPos, i), false);
int j = this.levelHeightAccessor.getSectionYFromSectionIndex(i);
updateSectionStatus(SectionPos.of(chunkPos, j), false);
}
}
enableLightSources(chunkPos, true);
if (needLightBlockUpdate) {
chunkAccess.getLights()
.forEach(blockPos -> onBlockEmissionIncrease(blockPos, chunkAccess.getLightEmission(blockPos)));
}
}
enableLightSources(chunkPos, true);
if (needLightBlockUpdate) {
chunkAccess.getLights().forEach(blockPos ->
onBlockEmissionIncrease(blockPos, chunkAccess.getLightEmission(blockPos)));
}
chunkAccess.setLightCorrect(true);
}
chunkAccess.setLightCorrect(true);
}
@Override
public String getDebugData(LightLayer lightLayer, SectionPos sectionPos) {
throw new UnsupportedOperationException("This should never be used!");
}
@Override
public void queueSectionData(LightLayer lightLayer, SectionPos sectionPos, @Nullable DataLayer dataLayer,
boolean bl) {
if (lightLayer == LightLayer.BLOCK) {
if (this.blockEngine != null) {
this.blockEngine.queueSectionData(sectionPos.asLong(), dataLayer, bl);
}
} else if (this.skyEngine != null) {
this.skyEngine.queueSectionData(sectionPos.asLong(), dataLayer, bl);
}
}
@Override
public void retainData(ChunkPos chunkPos, boolean bl) {
if (this.blockEngine != null) {
this.blockEngine.retainData(chunkPos, bl);
}
if (this.skyEngine != null) {
this.skyEngine.retainData(chunkPos, bl);
}
}
@Override
public String getDebugData(LightLayer lightLayer, SectionPos sectionPos) {
throw new UnsupportedOperationException("This should never be used!");
}
@Override
public void queueSectionData(LightLayer lightLayer, SectionPos sectionPos, @Nullable DataLayer dataLayer, boolean bl) {
if (lightLayer == LightLayer.BLOCK) {
if (this.blockEngine != null) {
this.blockEngine.queueSectionData(sectionPos.asLong(), dataLayer, bl);
}
} else if (this.skyEngine != null) {
this.skyEngine.queueSectionData(sectionPos.asLong(), dataLayer, bl);
}
}
@Override
public void retainData(ChunkPos chunkPos, boolean bl) {
if (this.blockEngine != null) {
this.blockEngine.retainData(chunkPos, bl);
}
if (this.skyEngine != null) {
this.skyEngine.retainData(chunkPos, bl);
}
}
@Override
public int getLightSectionCount() {
throw new UnsupportedOperationException("This should never be used!");
}
@Override
public int getMinLightSection() {
throw new UnsupportedOperationException("This should never be used!");
}
@Override
public int getMaxLightSection() {
throw new UnsupportedOperationException("This should never be used!");
}
}
@@ -15,25 +15,25 @@ import net.minecraft.world.level.levelgen.feature.StructureFeature;
import net.minecraft.world.level.levelgen.structure.StructureStart;
public class WorldGenStructFeatManager extends StructureFeatureManager {
WorldGenLevel genLevel;
final WorldGenLevel genLevel;
WorldGenSettings worldGenSettings;
public WorldGenStructFeatManager(LevelAccessor levelAccessor, WorldGenSettings worldGenSettings,
public WorldGenStructFeatManager(WorldGenSettings worldGenSettings,
WorldGenLevel genLevel) {
super(levelAccessor, worldGenSettings);
super(genLevel, worldGenSettings);
this.genLevel = genLevel;
this.worldGenSettings = worldGenSettings;
}
public void setGenLevel(WorldGenLevel genLevel) {
this.genLevel = genLevel;
}
@Override
public WorldGenStructFeatManager forWorldGenRegion(WorldGenRegion worldGenRegion) {
if (worldGenRegion == genLevel)
return this;
return new WorldGenStructFeatManager(worldGenRegion, worldGenSettings, worldGenRegion);
return new WorldGenStructFeatManager(worldGenSettings, worldGenRegion);
}
private ChunkAccess _getChunk(int x, int z, ChunkStatus status) {
if (genLevel == null) return null;
return genLevel.getChunk(x, z, status, false);
}
@Override
@@ -5,8 +5,8 @@ import java.util.ArrayList;
import com.seibel.lod.common.wrappers.worldGeneration.ThreadedParameters;
import com.seibel.lod.common.wrappers.worldGeneration.mimicObject.LightedWorldGenRegion;
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment;
import com.seibel.lod.core.util.GridList;
import com.seibel.lod.core.util.gridList.ArrayGridList;
import net.minecraft.ReportedException;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkStatus;
@@ -27,7 +27,7 @@ public final class StepFeatures {
public final ChunkStatus STATUS = ChunkStatus.FEATURES;
public void generateGroup(ThreadedParameters tParams, LightedWorldGenRegion worldGenRegion, GridList<ChunkAccess> chunks) {
public void generateGroup(ThreadedParameters tParams, LightedWorldGenRegion worldGenRegion, ArrayGridList<ChunkAccess> chunks) {
ArrayList<ChunkAccess> chunksToDo = new ArrayList<ChunkAccess>();
for (ChunkAccess chunk : chunks) {
@@ -2,52 +2,53 @@ package com.seibel.lod.common.wrappers.worldGeneration.step;
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment;
import com.seibel.lod.common.wrappers.worldGeneration.mimicObject.WorldGenLevelLightEngine;
import com.seibel.lod.core.util.GridList;
import com.seibel.lod.core.util.gridList.ArrayGridList;
import net.minecraft.server.level.ThreadedLevelLightEngine;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.chunk.ProtoChunk;
import net.minecraft.world.level.lighting.LevelLightEngine;
import net.minecraft.world.level.lighting.LightEventListener;
public final class StepLight {
/**
*
*/
private final BatchGenerationEnvironment envionment;
private final BatchGenerationEnvironment environment;
/**
* @param worldGenerationEnvironment
* @param batchGenerationEnvironment
*/
public StepLight(BatchGenerationEnvironment worldGenerationEnvironment) {
envionment = worldGenerationEnvironment;
public StepLight(BatchGenerationEnvironment batchGenerationEnvironment)
{
environment = batchGenerationEnvironment;
}
public final ChunkStatus STATUS = ChunkStatus.LIGHT;
public void generateGroup(LevelLightEngine lightEngine, GridList<ChunkAccess> chunks) {
// ArrayList<ChunkAccess> chunksToDo = new ArrayList<ChunkAccess>();
public void generateGroup(LightEventListener lightEngine,
ArrayGridList<ChunkAccess> chunks) {
//ArrayList<ChunkAccess> chunksToDo = new ArrayList<ChunkAccess>();
for (ChunkAccess chunk : chunks) {
if (chunk.getStatus().isOrAfter(STATUS))
continue;
if (chunk.getStatus().isOrAfter(STATUS)) continue;
((ProtoChunk) chunk).setStatus(STATUS);
}
for (ChunkAccess chunk : chunks) {
boolean hasCorrectBlockLight = (chunk instanceof LevelChunk && chunk.isLightCorrect());
try {
if (lightEngine == null) {
// Do nothing
} else if (lightEngine instanceof WorldGenLevelLightEngine) {
((WorldGenLevelLightEngine) lightEngine).lightChunk(chunk, !hasCorrectBlockLight);
((WorldGenLevelLightEngine)lightEngine).lightChunk(chunk, !hasCorrectBlockLight);
} else if (lightEngine instanceof ThreadedLevelLightEngine) {
((ThreadedLevelLightEngine) lightEngine).lightChunk(chunk, !hasCorrectBlockLight).join();
} else {
assert (false);
assert(false);
}
} catch (Exception e) {
e.printStackTrace();
}
@@ -1,45 +1,55 @@
package com.seibel.lod.common.wrappers.worldGeneration.step;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import com.seibel.lod.common.wrappers.worldGeneration.ThreadedParameters;
import com.google.common.collect.Sets;
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment;
import com.seibel.lod.common.wrappers.worldGeneration.ThreadedParameters;
import net.minecraft.core.QuartPos;
import net.minecraft.server.level.WorldGenRegion;
import net.minecraft.util.Mth;
import net.minecraft.world.level.StructureFeatureManager;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.chunk.LevelChunkSection;
import net.minecraft.world.level.chunk.ProtoChunk;
import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator;
import net.minecraft.world.level.levelgen.NoiseSettings;
public final class StepNoise {
/**
*
*/
private final BatchGenerationEnvironment envionment;
private final BatchGenerationEnvironment environment;
/**
* @param worldGenerationEnvironment
* @param batchGenerationEnvironment
*/
public StepNoise(BatchGenerationEnvironment worldGenerationEnvironment) {
envionment = worldGenerationEnvironment;
public StepNoise(BatchGenerationEnvironment batchGenerationEnvironment)
{
environment = batchGenerationEnvironment;
}
public final ChunkStatus STATUS = ChunkStatus.NOISE;
public void generateGroup(ThreadedParameters tParams, WorldGenRegion worldGenRegion, List<ChunkAccess> chunks) {
public void generateGroup(ThreadedParameters tParams, WorldGenRegion worldGenRegion,
List<ChunkAccess> chunks) {
ArrayList<ChunkAccess> chunksToDo = new ArrayList<ChunkAccess>();
for (ChunkAccess chunk : chunks) {
if (chunk.getStatus().isOrAfter(STATUS))
continue;
if (chunk.getStatus().isOrAfter(STATUS)) continue;
((ProtoChunk) chunk).setStatus(STATUS);
chunksToDo.add(chunk);
}
for (ChunkAccess chunk : chunksToDo) {
// System.out.println("StepNoise: "+chunk.getPos());
envionment.params.generator.fillFromNoise(worldGenRegion, tParams.structFeat, chunk);
chunk = environment.joinSync(environment.params.generator.fillFromNoise(Runnable::run,
tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk));
}
}
}
@@ -3,8 +3,8 @@ package com.seibel.lod.common.wrappers.worldGeneration.step;
import java.util.ArrayList;
import java.util.List;
import com.seibel.lod.common.wrappers.worldGeneration.ThreadedParameters;
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment;
import com.seibel.lod.common.wrappers.worldGeneration.ThreadedParameters;
import net.minecraft.CrashReport;
import net.minecraft.CrashReportCategory;
@@ -20,59 +20,35 @@ import net.minecraft.world.level.chunk.ProtoChunk;
import net.minecraft.world.level.levelgen.structure.StructureStart;
public final class StepStructureReference {
public final ChunkStatus STATUS = ChunkStatus.STRUCTURE_REFERENCES;
/**
*
*/
private final BatchGenerationEnvironment environment;
private void createReferences(WorldGenRegion worldGenLevel, StructureFeatureManager structureFeatureManager,
ChunkAccess chunkAccess) {
ChunkPos chunkPos = chunkAccess.getPos();
int j = chunkPos.x;
int k = chunkPos.z;
int l = chunkPos.getMinBlockX();
int m = chunkPos.getMinBlockZ();
SectionPos sectionPos = SectionPos.of(chunkAccess.getPos(), 0);
for (int n = j - 8; n <= j + 8; n++) {
for (int o = k - 8; o <= k + 8; o++) {
if (!worldGenLevel.hasChunk(n, o))
continue;
long p = ChunkPos.asLong(n, o);
for (StructureStart<?> structureStart : worldGenLevel.getChunk(n, o).getAllStarts().values()) {
try {
if (structureStart.isValid()
&& structureStart.getBoundingBox().intersects(l, m, l + 15, m + 15)) {
structureFeatureManager.addReferenceForFeature(sectionPos, structureStart.getFeature(), p,
chunkAccess);
}
} catch (Exception exception) {
CrashReport crashReport = CrashReport.forThrowable(exception, "Generating structure reference");
CrashReportCategory crashReportCategory = crashReport.addCategory("Structure");
crashReportCategory.setDetail("Id",
() -> Registry.STRUCTURE_FEATURE.getKey(structureStart.getFeature()).toString());
crashReportCategory.setDetail("Name", () -> structureStart.getFeature().getFeatureName());
crashReportCategory.setDetail("Class",
() -> structureStart.getFeature().getClass().getCanonicalName());
throw new ReportedException(crashReport);
}
}
}
}
/**
* @param batchGenerationEnvironment
*/
public StepStructureReference(BatchGenerationEnvironment batchGenerationEnvironment)
{
environment = batchGenerationEnvironment;
}
public void generateGroup(ThreadedParameters tParams, WorldGenRegion worldGenRegion, List<ChunkAccess> chunks) {
public final ChunkStatus STATUS = ChunkStatus.STRUCTURE_REFERENCES;
public void generateGroup(ThreadedParameters tParams, WorldGenRegion worldGenRegion,
List<ChunkAccess> chunks) {
ArrayList<ChunkAccess> chunksToDo = new ArrayList<ChunkAccess>();
for (ChunkAccess chunk : chunks) {
if (chunk.getStatus().isOrAfter(STATUS))
continue;
if (chunk.getStatus().isOrAfter(STATUS)) continue;
((ProtoChunk) chunk).setStatus(STATUS);
chunksToDo.add(chunk);
}
for (ChunkAccess chunk : chunksToDo) {
// System.out.println("StepStructureReference: "+chunk.getPos());
createReferences(worldGenRegion, tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk);
environment.params.generator.createReferences(worldGenRegion, tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk);
}
}
}
@@ -3,8 +3,8 @@ package com.seibel.lod.common.wrappers.worldGeneration.step;
import java.util.ArrayList;
import java.util.List;
import com.seibel.lod.common.wrappers.worldGeneration.ThreadedParameters;
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment;
import com.seibel.lod.common.wrappers.worldGeneration.ThreadedParameters;
import net.minecraft.server.level.WorldGenRegion;
import net.minecraft.world.level.chunk.ChunkAccess;
@@ -15,33 +15,44 @@ public final class StepStructureStart {
/**
*
*/
private final BatchGenerationEnvironment envionment;
private final BatchGenerationEnvironment environment;
/**
* @param worldGenerationEnvironment
* @param batchGenerationEnvironment
*/
public StepStructureStart(BatchGenerationEnvironment worldGenerationEnvironment) {
envionment = worldGenerationEnvironment;
public StepStructureStart(BatchGenerationEnvironment batchGenerationEnvironment)
{
environment = batchGenerationEnvironment;
}
public final ChunkStatus STATUS = ChunkStatus.STRUCTURE_STARTS;
public static class StructStartCorruptedException extends RuntimeException {
private static final long serialVersionUID = -8987434342051563358L;
public void generateGroup(ThreadedParameters tParams, WorldGenRegion worldGenRegion, List<ChunkAccess> chunks) {
public StructStartCorruptedException(ArrayIndexOutOfBoundsException e) {
super("StructStartCorruptedException");
super.initCause(e);
fillInStackTrace();
}
}
public void generateGroup(ThreadedParameters tParams, WorldGenRegion worldGenRegion,
List<ChunkAccess> chunks) {
ArrayList<ChunkAccess> chunksToDo = new ArrayList<ChunkAccess>();
for (ChunkAccess chunk : chunks) {
if (chunk.getStatus().isOrAfter(STATUS))
continue;
if (chunk.getStatus().isOrAfter(STATUS)) continue;
((ProtoChunk) chunk).setStatus(STATUS);
chunksToDo.add(chunk);
}
if (envionment.params.worldGenSettings.generateFeatures()) {
if (environment.params.worldGenSettings.generateFeatures()) {
for (ChunkAccess chunk : chunksToDo) {
// System.out.println("StepStructureStart: "+chunk.getPos());
envionment.params.generator.createStructures(envionment.params.registry, tParams.structFeat, chunk,
envionment.params.structures, envionment.params.worldSeed);
environment.params.generator.createStructures(environment.params.registry, tParams.structFeat, chunk, environment.params.structures,
environment.params.worldSeed);
}
}
}
@@ -3,8 +3,8 @@ package com.seibel.lod.common.wrappers.worldGeneration.step;
import java.util.ArrayList;
import java.util.List;
import com.seibel.lod.common.wrappers.worldGeneration.ThreadedParameters;
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment;
import com.seibel.lod.common.wrappers.worldGeneration.ThreadedParameters;
import net.minecraft.server.level.WorldGenRegion;
import net.minecraft.world.level.chunk.ChunkAccess;
@@ -15,30 +15,31 @@ public final class StepSurface {
/**
*
*/
private final BatchGenerationEnvironment envionment;
private final BatchGenerationEnvironment environment;
/**
* @param worldGenerationEnvironment
* @param batchGenerationEnvironment
*/
public StepSurface(BatchGenerationEnvironment worldGenerationEnvironment) {
envionment = worldGenerationEnvironment;
public StepSurface(BatchGenerationEnvironment batchGenerationEnvironment)
{
environment = batchGenerationEnvironment;
}
public final ChunkStatus STATUS = ChunkStatus.SURFACE;
public void generateGroup(ThreadedParameters tParams, WorldGenRegion worldGenRegion, List<ChunkAccess> chunks) {
public void generateGroup(ThreadedParameters tParams, WorldGenRegion worldGenRegion,
List<ChunkAccess> chunks) {
ArrayList<ChunkAccess> chunksToDo = new ArrayList<ChunkAccess>();
for (ChunkAccess chunk : chunks) {
if (chunk.getStatus().isOrAfter(STATUS))
continue;
if (chunk.getStatus().isOrAfter(STATUS)) continue;
((ProtoChunk) chunk).setStatus(STATUS);
chunksToDo.add(chunk);
}
for (ChunkAccess chunk : chunksToDo) {
// System.out.println("StepSurface: "+chunk.getPos());
envionment.params.generator.buildSurfaceAndBedrock(worldGenRegion, chunk);
environment.params.generator.buildSurfaceAndBedrock(worldGenRegion, chunk);
}
}
}
+24 -5
View File
@@ -1,13 +1,19 @@
accessWidener v1 named
# used when determining where to save files too
# used when determining where to save files to
accessible field net/minecraft/world/level/storage/DimensionDataStorage dataFolder Ljava/io/File;
# used when rendering
accessible field com/mojang/blaze3d/vertex/VertexBuffer indexCount I
accessible field com/mojang/blaze3d/vertex/VertexBuffer vertextBufferId I
accessible method net/minecraft/client/renderer/GameRenderer getFov (Lnet/minecraft/client/Camera;FZ)D
# pre-render setup
accessible field net/minecraft/client/renderer/LevelRenderer renderChunks Lit/unimi/dsi/fastutil/objects/ObjectArrayList;
accessible class net/minecraft/client/renderer/LevelRenderer$RenderChunkInfo
accessible field net/minecraft/client/renderer/LevelRenderer$RenderChunkInfo chunk Lnet/minecraft/client/renderer/chunk/ChunkRenderDispatcher$RenderChunk;
# used for grabbing vanilla rendered chunks
accessible field net/minecraft/client/renderer/LevelRenderer renderChunks Lit/unimi/dsi/fastutil/objects/ObjectList;
accessible class net/minecraft/client/renderer/LevelRenderer$RenderChunkInfo
accessible field net/minecraft/client/renderer/LevelRenderer$RenderChunkInfo chunk Lnet/minecraft/client/renderer/chunk/ChunkRenderDispatcher$RenderChunk;
@@ -19,6 +25,12 @@ accessible field net/minecraft/world/level/lighting/LevelLightEngine skyEngine L
# world generation
accessible method net/minecraft/world/level/levelgen/Heightmap setHeight (III)V
accessible field net/minecraft/world/level/biome/Biome generationSettings Lnet/minecraft/world/level/biome/BiomeGenerationSettings;
accessible field net/minecraft/world/level/biome/Biome biomeCategory Lnet/minecraft/world/level/biome/Biome$BiomeCategory;
# accessible field net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator settings Lnet/minecraft/core/Holder;
accessible field net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator settings Ljava/util/function/Supplier;
#accessible method net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator doCreateBiomes (Lnet/minecraft/core/Registry;Lnet/minecraft/world/level/levelgen/blending/Blender;Lnet/minecraft/world/level/StructureFeatureManager;Lnet/minecraft/world/level/chunk/ChunkAccess;)V
accessible method net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator doFill (Lnet/minecraft/world/level/StructureFeatureManager;Lnet/minecraft/world/level/chunk/ChunkAccess;II)Lnet/minecraft/world/level/chunk/ChunkAccess;
accessible method net/minecraft/world/level/lighting/LayerLightEngine queueSectionData (JLnet/minecraft/world/level/chunk/DataLayer;Z)V
accessible field net/minecraft/world/level/chunk/ChunkGenerator biomeSource Lnet/minecraft/world/level/biome/BiomeSource;
@@ -27,7 +39,14 @@ accessible field net/minecraft/server/level/ChunkMap mainThreadExecutor Lnet/min
accessible method net/minecraft/server/level/ChunkMap readChunk (Lnet/minecraft/world/level/ChunkPos;)Lnet/minecraft/nbt/CompoundTag;
# grabbing textures
accessible field net/minecraft/client/renderer/block/model/BakedQuad sprite Lnet/minecraft/client/renderer/texture/TextureAtlasSprite;
accessible field net/minecraft/client/renderer/texture/TextureAtlasSprite framesX [I
accessible field net/minecraft/client/renderer/texture/TextureAtlasSprite framesY [I
accessible field net/minecraft/client/renderer/texture/TextureAtlasSprite animatedTexture Lnet/minecraft/client/renderer/texture/TextureAtlasSprite$AnimatedTexture;
accessible field net/minecraft/client/renderer/texture/TextureAtlasSprite width I
accessible field net/minecraft/client/renderer/texture/TextureAtlasSprite height I
accessible field net/minecraft/client/renderer/texture/TextureAtlasSprite mainImage [Lcom/mojang/blaze3d/platform/NativeImage;
accessible method net/minecraft/client/renderer/texture/TextureAtlasSprite$AnimatedTexture getFrameX (I)I
accessible method net/minecraft/client/renderer/texture/TextureAtlasSprite$AnimatedTexture getFrameY (I)I
extendable class com/mojang/math/Matrix4f
# hacky stuff
accessible field net/minecraft/world/level/chunk/PalettedContainer lock Ljava/util/concurrent/Semaphore;
mutable field net/minecraft/world/level/chunk/PalettedContainer lock Ljava/util/concurrent/Semaphore;
+1 -1
Submodule core updated: 67f12c136c...4bac38c99f
+32 -33
View File
@@ -1,6 +1,5 @@
plugins {
id "com.github.johnrengelman.shadow" version "7.0.0"
id "com.modrinth.minotaur" version "1.2.1"
}
version = rootProject.mod_version+"-"+rootProject.minecraft_version+"-"+new Date().format("yyyy_MM_dd_HH_mm")
@@ -18,6 +17,10 @@ configurations {
compileClasspath.extendsFrom common
runtimeClasspath.extendsFrom common
developmentFabric.extendsFrom common
addModJar
include.extendsFrom addModJar
modImplementation.extendsFrom addModJar
}
repositories {
@@ -25,13 +28,21 @@ repositories {
maven { url "https://maven.terraformersmc.com/" }
}
def addMod(path, enabled) {
if (enabled == "2")
dependencies { modImplementation(path) }
else if (enabled == "1")
dependencies { modCompileOnly(path) }
}
dependencies {
// Fabric loader
modImplementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}"
// Fabric API
modApi "net.fabricmc.fabric-api:fabric-api:${rootProject.fabric_api_version}"
addModJar(fabricApi.module("fabric-lifecycle-events-v1", rootProject.fabric_api_version))
addModJar(fabricApi.module("fabric-key-binding-api-v1", rootProject.fabric_api_version))
addModJar(fabricApi.module("fabric-networking-api-v1", rootProject.fabric_api_version))
// Mod Menu
modImplementation("com.terraformersmc:modmenu:${rootProject.modmenu_version}") {
@@ -39,14 +50,30 @@ dependencies {
}
// Sodium
modImplementation "curse.maven:sodium-394468:${rootProject.sodium_version}"
addMod("curse.maven:sodium-394468:${rootProject.sodium_version}", rootProject.enable_sodium)
implementation "org.joml:joml:1.10.2"
// Lithium
// modImplementation "maven.modrinth:lithium:${rootProject.lithium_version}"
addMod("maven.modrinth:lithium:${rootProject.lithium_version}", rootProject.enable_lithium)
// Iris
// modImplementation "maven.modrinth:iris:${rootProject.iris_version}"
addMod("maven.modrinth:iris:${rootProject.iris_version}", rootProject.enable_iris)
// Immersive Portals
/*
modImplementation("com.github.qouteall.ImmersivePortalsMod:build:${rootProject.immersive_portals_version}") {
exclude(group: "net.fabricmc.fabric-api")
transitive(false)
}
modImplementation("com.github.qouteall.ImmersivePortalsMod:imm_ptl_core:${rootProject.immersive_portals_version}") {
exclude(group: "net.fabricmc.fabric-api")
transitive(false)
}
modImplementation("com.github.qouteall.ImmersivePortalsMod:q_misc_util:${rootProject.immersive_portals_version}") {
exclude(group: "net.fabricmc.fabric-api")
transitive(false)
}
*/
@@ -90,36 +117,8 @@ runClient {
finalizedBy(deleteResources)
}
// Put stuff from gradle.properties into the mod info stuff
def resourceTargets = ["fabric.mod.json"]
def intoTargets = ["$buildDir/resources/main/"]
def replaceProperties = [
version: mod_version,
mod_name: mod_name,
authors: mod_authors,
description: mod_description
]
processResources {
dependsOn(copyAccessWidener)
inputs.properties replaceProperties
replaceProperties.put 'project', project
filesMatching(resourceTargets) {
expand replaceProperties
}
intoTargets.each { target ->
if (file(target).exists()) {
copy {
from(sourceSets.main.resources) {
include resourceTargets
expand replaceProperties
}
into target
}
}
}
}
shadowJar {
@@ -19,6 +19,7 @@
package com.seibel.lod.fabric;
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment;
import com.seibel.lod.core.api.ClientApi;
import com.seibel.lod.core.api.EventApi;
import com.mojang.blaze3d.platform.InputConstants;
@@ -26,22 +27,15 @@ import com.seibel.lod.common.wrappers.chunk.ChunkWrapper;
import com.seibel.lod.common.wrappers.world.DimensionTypeWrapper;
import com.seibel.lod.common.wrappers.world.WorldWrapper;
import com.seibel.lod.core.util.SingletonHandler;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
import com.seibel.lod.fabric.mixins.events.MixinClientLevel;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientChunkEvents;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerChunkEvents;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerWorldEvents;
import net.fabricmc.fabric.mixin.event.lifecycle.client.ClientChunkManagerMixin;
import net.minecraft.client.KeyMapping;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientChunkCache;
import net.minecraft.core.BlockPos;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.level.Level;
@@ -49,7 +43,7 @@ import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.chunk.LevelChunk;
import java.util.HashSet;
import java.util.List;
import java.util.function.Supplier;
import org.lwjgl.glfw.GLFW;
@@ -66,6 +60,7 @@ public class ClientProxy
private final EventApi eventApi = EventApi.INSTANCE;
private final ClientApi clientApi = ClientApi.INSTANCE;
public static Supplier<Boolean> isGenerationThreadChecker = null;
/**
* Registers Fabric Events
@@ -74,6 +69,8 @@ public class ClientProxy
public void registerEvents() {
// TODO: Fix this if it's wrong
/* Registor the mod accessor*/
/* World Events */
//ServerTickEvents.START_SERVER_TICK.register(this::serverTickEvent);
ServerTickEvents.END_SERVER_TICK.register(this::serverTickEvent);
@@ -82,8 +79,6 @@ public class ClientProxy
//ServerChunkEvents.CHUNK_LOAD.register(this::chunkLoadEvent);
ClientChunkEvents.CHUNK_LOAD.register(this::chunkLoadEvent);
/* World Events */
ServerWorldEvents.LOAD.register((server, level) -> this.worldLoadEvent(level));
ServerWorldEvents.UNLOAD.register((server, level) -> this.worldUnloadEvent(level));
@@ -97,6 +92,7 @@ public class ClientProxy
ClientTickEvents.END_CLIENT_TICK.register(client -> {
if (client.player != null) onKeyInput();
});
isGenerationThreadChecker = BatchGenerationEnvironment::isCurrentThreadDistantGeneratorThread;
}
@@ -21,16 +21,17 @@ package com.seibel.lod.fabric;
import com.seibel.lod.common.LodCommonMain;
import com.seibel.lod.core.ModInfo;
import com.seibel.lod.core.api.ApiShared;
import com.seibel.lod.core.api.ClientApi;
import com.seibel.lod.core.api.ModAccessorApi;
import com.seibel.lod.core.util.SingletonHandler;
import com.seibel.lod.core.handlers.dependencyInjection.ModAccessorHandler;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.wrapperInterfaces.modAccessor.IModChecker;
import com.seibel.lod.core.wrapperInterfaces.modAccessor.IOptifineAccessor;
import com.seibel.lod.core.wrapperInterfaces.modAccessor.ISodiumAccessor;
import com.seibel.lod.fabric.wrappers.FabricDependencySetup;
import com.seibel.lod.fabric.wrappers.modAccessor.ModChecker;
import com.seibel.lod.fabric.wrappers.modAccessor.OptifineAccessor;
import com.seibel.lod.fabric.wrappers.modAccessor.SodiumAccessor;
import com.seibel.lod.fabric.wrappers.DependencySetup;
import net.fabricmc.api.ClientModInitializer;
@@ -45,7 +46,7 @@ import net.fabricmc.api.ClientModInitializer;
*/
public class Main implements ClientModInitializer
{
// This is a client mod so it should implement ClientModInitializer and in fabric.mod.json it should have "environment": "client"
// This is a client mod, so it should implement ClientModInitializer and in fabric.mod.json it should have "environment": "client"
// Once it works on servers change the implement to ModInitializer and in fabric.mod.json it should be "environment": "*"
public static ClientProxy client_proxy;
@@ -62,25 +63,28 @@ public class Main implements ClientModInitializer
public static void init() {
LodCommonMain.initConfig();
LodCommonMain.startup(null, false);
DependencySetup.createInitialBindings();
SingletonHandler.bind(IModChecker.class, ModChecker.INSTANCE);
ClientApi.LOGGER.info(ModInfo.READABLE_NAME + ", Version: " + ModInfo.VERSION);
FabricDependencySetup.createInitialBindings();
FabricDependencySetup.finishBinding();
ApiShared.LOGGER.info(ModInfo.READABLE_NAME + ", Version: " + ModInfo.VERSION);
// Check if this works
client_proxy = new ClientProxy();
client_proxy.registerEvents();
if (SingletonHandler.get(IModChecker.class).isModLoaded("sodium")) {
ModAccessorApi.bind(ISodiumAccessor.class, new SodiumAccessor());
ModAccessorHandler.bind(ISodiumAccessor.class, new SodiumAccessor());
}
if (SingletonHandler.get(IModChecker.class).isModLoaded("optifine")) {
ModAccessorApi.bind(IOptifineAccessor.class, new OptifineAccessor());
ModAccessorHandler.bind(IOptifineAccessor.class, new OptifineAccessor());
}
ModAccessorHandler.finishBinding();
}
public static void initServer() {
LodCommonMain.initConfig();
LodCommonMain.startup(null, true);
DependencySetup.createInitialBindings();
ClientApi.LOGGER.info(ModInfo.READABLE_NAME + ", Version: " + ModInfo.VERSION);
FabricDependencySetup.createInitialBindings();
FabricDependencySetup.finishBinding();
ApiShared.LOGGER.info(ModInfo.READABLE_NAME + ", Version: " + ModInfo.VERSION);
}
}
@@ -6,40 +6,35 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import com.mojang.blaze3d.systems.RenderSystem;
import com.seibel.lod.core.api.ClientApi;
import com.seibel.lod.core.util.SingletonHandler;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
import net.minecraft.client.Camera;
import net.minecraft.client.renderer.FogRenderer;
import net.minecraft.client.renderer.FogRenderer.FogMode;
import net.minecraft.tags.FluidTags;
import net.minecraft.world.effect.MobEffects;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.material.FogType;
@Mixin(FogRenderer.class)
public class MixinFogRenderer {
private static final ILodConfigWrapperSingleton CONFIG = SingletonHandler.get(ILodConfigWrapperSingleton.class);
// Using this instead of Float.MAX_VALUE because Sodium don't like it.
private static final float A_REALLY_REALLY_BIG_VALUE = 4206942069.F;
private static final float A_EVEN_LARGER_VALUE = 420694206942069.F;
private static final float A_REALLY_REALLY_BIG_VALUE = 420694206942069.F;
private static final float A_EVEN_LARGER_VALUE = 42069420694206942069.F;
@Inject(at = @At("RETURN"), method = "setupFog(Lnet/minecraft/client/Camera;Lnet/minecraft/client/renderer/FogRenderer$FogMode;FZ)V")
private static final void disableSetupFog(Camera camera, FogMode fogMode, float f, boolean bl, CallbackInfo callback) {
FluidState fluidState = camera.getFluidInCamera();
private static void disableSetupFog(Camera camera, FogMode fogMode, float f, boolean bl, CallbackInfo callback) {
FogType fogTypes = camera.getFluidInCamera();
Entity entity = camera.getEntity();
boolean isUnderWater = (entity instanceof LivingEntity) && ((LivingEntity)entity).hasEffect(MobEffects.BLINDNESS);
isUnderWater |= fluidState.is(FluidTags.WATER);
isUnderWater |= fluidState.is(FluidTags.LAVA);
if (!isUnderWater) {
if (fogMode == FogMode.FOG_TERRAIN && CONFIG.client().graphics().fogQuality().getDisableVanillaFog()) {
RenderSystem.fogStart(A_REALLY_REALLY_BIG_VALUE);
RenderSystem.fogEnd(A_EVEN_LARGER_VALUE);
if (fogMode == FogMode.FOG_TERRAIN && fogTypes == FogType.NONE && CONFIG.client().graphics().fogQuality().getDisableVanillaFog()) {
RenderSystem.setShaderFogStart(A_REALLY_REALLY_BIG_VALUE);
RenderSystem.setShaderFogEnd(A_EVEN_LARGER_VALUE);
}
}
}
}
}
@@ -3,7 +3,7 @@ package com.seibel.lod.fabric.mixins;
import com.seibel.lod.common.wrappers.config.ConfigGui;
import com.seibel.lod.common.wrappers.config.TexturedButtonWidget;
import com.seibel.lod.core.ModInfo;
import com.seibel.lod.core.util.SingletonHandler;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
import net.minecraft.client.gui.screens.OptionsScreen;
import net.minecraft.client.gui.screens.Screen;
@@ -34,7 +34,7 @@ public class MixinOptionsScreen extends Screen {
@Inject(at = @At("HEAD"),method = "init")
private void lodconfig$init(CallbackInfo ci) {
if (SingletonHandler.get(ILodConfigWrapperSingleton.class).client().getOptionsButton())
this.addButton(new TexturedButtonWidget(
this.addRenderableWidget(new TexturedButtonWidget(
// Where the button is on the screen
this.width / 2 - 180, this.height / 6 - 12,
// Width and height of the button
@@ -0,0 +1,49 @@
package com.seibel.lod.fabric.mixins;
import java.util.concurrent.Executor;
import com.seibel.lod.fabric.ClientProxy;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import com.seibel.lod.common.wrappers.DependencySetupDoneCheck;
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.wrapperInterfaces.IWrapperFactory;
import net.minecraft.Util;
@Mixin(Util.class)
public class MixinUtilBackgroudThread
{
private static boolean doTriggerOverride() {
try {
return DependencySetupDoneCheck.getIsCurrentThreadDistantGeneratorThread.get();
} catch (NullPointerException e) {
return false;
}
}
@Inject(method = "wrapThreadWithTaskName(Ljava/lang/String;Ljava/lang/Runnable;)Ljava/lang/Runnable;",
at = @At("HEAD"), cancellable = true)
private static void overrideUtil$wrapThreadWithTaskName(String string, Runnable r, CallbackInfoReturnable<Runnable> ci)
{
if (ClientProxy.isGenerationThreadChecker != null && ClientProxy.isGenerationThreadChecker.get())
{
// ApiShared.LOGGER.info("util wrapThreadWithTaskName(Runnable) triggered");
ci.setReturnValue(r);
}
}
@Inject(method = "backgroundExecutor", at = @At("HEAD"), cancellable = true)
private static void overrideUtil$backgroundExecutor(CallbackInfoReturnable<Executor> ci)
{
if (ClientProxy.isGenerationThreadChecker != null && ClientProxy.isGenerationThreadChecker.get())
{
// ApiShared.LOGGER.info("util backgroundExecutor triggered");
ci.setReturnValue(Runnable::run);
}
}
}
@@ -20,19 +20,18 @@
package com.seibel.lod.fabric.mixins;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.math.Matrix4f;
import com.seibel.lod.common.Config;
import com.seibel.lod.common.wrappers.McObjectConverter;
import com.seibel.lod.core.api.ClientApi;
import com.seibel.lod.core.objects.math.Mat4f;
import net.minecraft.client.renderer.LevelRenderer;
import org.lwjgl.opengl.GL15;
import net.minecraft.client.renderer.RenderType;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import com.seibel.lod.core.api.ClientApi;
import com.seibel.lod.core.objects.math.Mat4f;
import net.minecraft.client.renderer.RenderType;
/**
* This class is used to mix in my rendering code
* before Minecraft starts rendering blocks.
@@ -49,37 +48,36 @@ import net.minecraft.client.renderer.RenderType;
@Mixin(LevelRenderer.class)
public class MixinWorldRenderer
{
// TODO: Fix clouds
private static float previousPartialTicks = 0;
@Inject(at = @At("RETURN"), method = "renderSky(Lcom/mojang/blaze3d/vertex/PoseStack;F)V")
private void renderSky(PoseStack matrixStackIn, float partialTicks, CallbackInfo callback)
{
// get the partial ticks since renderBlockLayer doesn't
// have access to them
previousPartialTicks = partialTicks;
public MixinWorldRenderer() {
throw new NullPointerException("Null cannot be cast to non-null type.");
}
@Inject(method = "renderClouds", at = @At("HEAD"), cancellable = true)
public void renderClouds(PoseStack poseStack, Matrix4f projectionMatrix, float tickDelta, double cameraX, double cameraY, double cameraZ, CallbackInfo ci) {
// get the partial ticks since renderChunkLayer doesn't
// have access to them
previousPartialTicks = tickDelta;
}
// Inject rendering at first call to renderChunkLayer
// HEAD or RETURN
@Inject(at = @At("HEAD"), method = "renderChunkLayer(Lnet/minecraft/client/renderer/RenderType;Lcom/mojang/blaze3d/vertex/PoseStack;DDD)V")
private void renderChunkLayer(RenderType renderType, PoseStack matrixStackIn, double xIn, double yIn, double zIn, CallbackInfo callback)
@Inject(at = @At("HEAD"),
method = "renderChunkLayer(Lnet/minecraft/client/renderer/RenderType;Lcom/mojang/blaze3d/vertex/PoseStack;DDDLcom/mojang/math/Matrix4f;)V",
cancellable = true)
private void renderChunkLayer(RenderType renderType, PoseStack modelViewMatrixStack, double cameraXBlockPos, double cameraYBlockPos, double cameraZBlockPos, Matrix4f projectionMatrix, CallbackInfo callback)
{
// only render before solid blocks
if (renderType.equals(RenderType.solid()))
{
// get MC's current projection matrix
float[] mcProjMatrixRaw = new float[16];
GL15.glGetFloatv(GL15.GL_PROJECTION_MATRIX, mcProjMatrixRaw);
Mat4f mcProjectionMatrix = new Mat4f(mcProjMatrixRaw);
// OpenGl outputs their matrices in col,row form instead of row,col
// (or maybe vice versa I have no idea :P)
mcProjectionMatrix.transpose();
Mat4f mcModelViewMatrix = McObjectConverter.Convert(matrixStackIn.last().pose());
Mat4f mcModelViewMatrix = McObjectConverter.Convert(modelViewMatrixStack.last().pose());
Mat4f mcProjectionMatrix = McObjectConverter.Convert(projectionMatrix);
ClientApi.INSTANCE.renderLods(mcModelViewMatrix, mcProjectionMatrix, previousPartialTicks);
}
if (Config.Client.Advanced.lodOnlyMode) {
callback.cancel();
}
}
}
@@ -4,7 +4,6 @@ import com.seibel.lod.fabric.Main;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.server.level.ServerLevel;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin;
@@ -14,8 +14,13 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
*/
@Mixin(ServerLevel.class)
public class MixinServerLevel {
@Inject(method = "save", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerChunkCache;save(Z)V", shift = At.Shift.AFTER))
private void saveWorldEvent(ProgressListener progressListener, boolean bl, boolean bl2, CallbackInfo ci) {
@Inject(method = "save", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/entity/PersistentEntitySectionManager;saveAll()V", shift = At.Shift.AFTER))
private void saveWorldEvent_sA(ProgressListener progressListener, boolean bl, boolean bl2, CallbackInfo ci) {
Main.client_proxy.worldSaveEvent();
}
@Inject(method = "save", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/entity/PersistentEntitySectionManager;autoSave()V", shift = At.Shift.AFTER))
private void saveWorldEvent_aS(ProgressListener progressListener, boolean bl, boolean bl2, CallbackInfo ci) {
Main.client_proxy.worldSaveEvent();
}
}
@@ -1,10 +1,8 @@
package com.seibel.lod.fabric.mixins.unsafe;
import net.minecraft.world.level.chunk.PalettedContainer;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
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;
@@ -19,13 +17,11 @@ import java.util.concurrent.Semaphore;
*/
@Mixin(PalettedContainer.class)
public class MixinPalettedContainer {
@Mutable
private Semaphore lock;
@Inject(method = "acquire", at = @At("HEAD"), cancellable = true)
private void acquire_skip(CallbackInfo ci) {
ci.cancel();
}
@Inject(method = "release", at = @At("HEAD"), cancellable = true)
private void release_skip(CallbackInfo ci) {
ci.cancel();
@Inject(method = "<init>", at = @At("RETURN"))
private void setSemaphore(CallbackInfo ci) {
this.lock = new Semaphore(2);
}
}
@@ -1,8 +1,10 @@
package com.seibel.lod.fabric.wrappers;
import com.seibel.lod.core.util.SingletonHandler;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
import com.seibel.lod.common.wrappers.config.LodConfigWrapperSingleton;
import com.seibel.lod.core.wrapperInterfaces.modAccessor.IModChecker;
import com.seibel.lod.fabric.wrappers.modAccessor.ModChecker;
/**
* Binds all necessary dependencies, so we
@@ -14,10 +16,16 @@ import com.seibel.lod.common.wrappers.config.LodConfigWrapperSingleton;
* @author Ran
* @version 12-1-2021
*/
public class DependencySetup
public class FabricDependencySetup
{
public static void createInitialBindings()
{
SingletonHandler.bind(ILodConfigWrapperSingleton.class, LodConfigWrapperSingleton.INSTANCE);;
SingletonHandler.bind(IModChecker.class, ModChecker.INSTANCE);
SingletonHandler.bind(ILodConfigWrapperSingleton.class, LodConfigWrapperSingleton.INSTANCE);
}
public static void finishBinding() {
SingletonHandler.finishBinding();
}
}
@@ -6,9 +6,6 @@ import com.terraformersmc.modmenu.api.ModMenuApi;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import java.util.HashMap;
import java.util.Map;
/**
* For making the config show up in modmenu
*/
@@ -1,3 +1,4 @@
package com.seibel.lod.fabric.wrappers.modAccessor;
import com.seibel.lod.core.wrapperInterfaces.modAccessor.IModChecker;
@@ -1,4 +1,3 @@
package com.seibel.lod.fabric.wrappers.modAccessor;
import java.util.HashSet;
@@ -22,4 +21,4 @@ public class OptifineAccessor implements IOptifineAccessor
return null;
}
}
}
@@ -3,65 +3,34 @@ package com.seibel.lod.fabric.wrappers.modAccessor;
import java.util.HashSet;
import java.util.stream.Collectors;
import com.seibel.lod.core.api.ClientApi;
import com.seibel.lod.core.util.SingletonHandler;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.wrapperInterfaces.chunk.AbstractChunkPosWrapper;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
import com.seibel.lod.core.wrapperInterfaces.modAccessor.ISodiumAccessor;
import me.jellysquid.mods.sodium.client.render.SodiumWorldRenderer;
import net.minecraft.client.Minecraft;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.protocol.Packet;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.level.LevelHeightAccessor;
public class SodiumAccessor implements ISodiumAccessor {
private final IMinecraftRenderWrapper MC_RENDER = SingletonHandler.get(IMinecraftRenderWrapper.class);
@Override
public String getModName() {
return "Sodium-Fabric-1.16.5";
}
return "Sodium-Fabric-1.17.1";
}
@Override
public HashSet<AbstractChunkPosWrapper> getNormalRenderedChunks() {
SodiumWorldRenderer renderer = SodiumWorldRenderer.getInstance();
LevelAccessor height = Minecraft.getInstance().level;
SodiumWorldRenderer renderer = SodiumWorldRenderer.instance();
LevelHeightAccessor height = Minecraft.getInstance().level;
// TODO: Maybe use a mixin to make this more efficient
return MC_RENDER.getMaximumRenderedChunks().stream().filter((AbstractChunkPosWrapper chunk) -> {
FakeChunkEntity AABB = new FakeChunkEntity(chunk.getX(), chunk.getZ(), height.getMaxBuildHeight());
return (renderer.isEntityVisible(AABB));
return (renderer.isBoxVisible(
chunk.getMinBlockX()+1, height.getMinBuildHeight()+1, chunk.getMinBlockZ()+1,
chunk.getMinBlockX()+15, height.getMaxBuildHeight()-1, chunk.getMinBlockZ()+15));
}).collect(Collectors.toCollection(HashSet::new));
}
private static class FakeChunkEntity extends Entity {
public int cx;
public int cz;
public int my;
public FakeChunkEntity(int chunkX, int chunkZ, int maxHeight) {
super(EntityType.AREA_EFFECT_CLOUD, null);
cx = chunkX;
cz = chunkZ;
my = maxHeight;
}
@Override
public AABB getBoundingBoxForCulling() {
return new AABB(cx*16+1, 1, cz*16+1,
cx*16+15, my-1, cz*16+15);
}
@Override
protected void defineSynchedData() {}
@Override
protected void readAdditionalSaveData(CompoundTag paramCompoundTag) {}
@Override
protected void addAdditionalSaveData(CompoundTag paramCompoundTag) {}
@Override
public Packet<?> getAddEntityPacket() {
throw new UnsupportedOperationException("This is a FAKE CHUNK ENTITY... For tricking the Sodium to check a AABB.");
}}
}
@@ -2,11 +2,12 @@
"required": true,
"minVersion": "0.8",
"package": "com.seibel.lod.fabric.mixins",
"compatibilityLevel": "JAVA_8",
"compatibilityLevel": "JAVA_16",
"mixins": [
"events.MixinServerLevel",
"unsafe.MixinPalettedContainer",
"MixinChunkGenerator"
"MixinChunkGenerator",
"MixinUtilBackgroudThread"
],
"client": [
"MixinMinecraft",
+8 -6
View File
@@ -8,9 +8,9 @@
"authors": ["${authors}"],
"contact": {
"homepage": "https://www.curseforge.com/minecraft/mc-mods/lod-level-of-detail",
"sources": "https://gitlab.com/jeseibel/minecraft-lod-mod/",
"issues": "https://gitlab.com/jeseibel/minecraft-lod-mod/-/issues"
"homepage": "${homepage}",
"sources": "${source}",
"issues": "${issues}"
},
"license": "CC0-1.0",
@@ -33,9 +33,11 @@
"accessWidener" : "lod.accesswidener",
"depends": {
"fabricloader": "*",
"fabric": "*",
"minecraft": "1.16.5",
"java": ">=8"
"fabric-lifecycle-events-v1": "*",
"fabric-key-binding-api-v1": "*",
"fabric-networking-api-v1": "*",
"minecraft": "${minecraft_version}",
"java": ">=${java_version}"
},
"suggests": {
"another-mod": "*"
+11 -29
View File
@@ -19,6 +19,13 @@ architectury {
forge()
}
def addMod(path, enabled) {
if (enabled == "2")
dependencies { modImplementation(path) }
else if (enabled == "1")
dependencies { modCompileOnly(path) }
}
configurations {
compileClasspath.extendsFrom common
runtimeClasspath.extendsFrom common
@@ -32,6 +39,9 @@ dependencies {
common(project(path: ":common", configuration: "namedElements")) { transitive false }
shadowMe(project(path: ":common", configuration: "transformProductionForge")) { transitive = false }
// Starlight
addMod("curse.maven:starlight-forge-526854:${rootProject.starlight_version_forge}", rootProject.enable_starlight_forge)
// forgeDependencies(project(":core")) { transitive false }
@@ -54,37 +64,9 @@ task copyCommonResources(type: Copy) {
into file("build/resources/main")
}
// Put stuff from gradle.properties into the mod info stuff
def resourceTargets = ["META-INF/mods.toml"]
def intoTargets = ["$buildDir/resources/main/"]
def replaceProperties = [
version: mod_version,
mod_name: mod_name,
authors: mod_authors,
description: mod_description
]
processResources {
dependsOn(copyCoreResources)
dependsOn(copyCommonResources)
inputs.properties replaceProperties
replaceProperties.put 'project', project
filesMatching(resourceTargets) {
expand replaceProperties
}
intoTargets.each { target ->
if (file(target).exists()) {
copy {
from(sourceSets.main.resources) {
include resourceTargets
expand replaceProperties
}
into target
}
}
}
}
shadowJar {
@@ -95,7 +77,7 @@ shadowJar {
configurations = [project.configurations.shadowMe]
relocate 'org.tukaani', 'shaded.tukaani'
relocate 'org.apache.commons.compress', 'shaded.apache.commons.compress'
relocate 'com.electronwill.nightconfig', 'shaded.electronwill.nightconfig'
relocate 'com.electronwill.nightconfig', 'shaded.electronwill.nightconfig' // This is already included with forge
relocate 'com.seibel.lod.common', 'forge.com.seibel.lod.common'
@@ -111,6 +111,4 @@ public class ForgeClientProxy
clientApi.keyPressedEvent(event.getKey());
}
}
@@ -22,12 +22,13 @@ package com.seibel.lod.forge;
import com.seibel.lod.common.LodCommonMain;
import com.seibel.lod.common.forge.LodForgeMethodCaller;
import com.seibel.lod.common.wrappers.config.ConfigGui;
import com.seibel.lod.common.wrappers.minecraft.MinecraftWrapper;
import com.seibel.lod.common.wrappers.minecraft.MinecraftClientWrapper;
import com.seibel.lod.core.ModInfo;
import com.seibel.lod.core.api.ApiShared;
import com.seibel.lod.core.api.ClientApi;
import com.seibel.lod.core.api.ModAccessorApi;
import com.seibel.lod.core.handlers.dependencyInjection.ModAccessorHandler;
import com.seibel.lod.core.handlers.ReflectionHandler;
import com.seibel.lod.core.util.SingletonHandler;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.wrapperInterfaces.modAccessor.IModChecker;
import com.seibel.lod.core.wrapperInterfaces.modAccessor.IOptifineAccessor;
import com.seibel.lod.forge.wrappers.ForgeDependencySetup;
@@ -35,18 +36,19 @@ import com.seibel.lod.forge.wrappers.ForgeDependencySetup;
import com.seibel.lod.forge.wrappers.modAccessor.ModChecker;
import com.seibel.lod.forge.wrappers.modAccessor.OptifineAccessor;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.core.Direction;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraftforge.client.model.data.ModelDataMap;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.ExtensionPoint;
import net.minecraftforge.fml.ModLoadingContext;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.fml.loading.FMLLoader;
import net.minecraftforge.fmlclient.ConfigGuiHandler;
import java.util.List;
import java.util.Random;
@@ -66,16 +68,11 @@ public class ForgeMain implements LodForgeMethodCaller
private void init(final FMLCommonSetupEvent event)
{
// make sure the dependencies are set up before the mod needs them
LodCommonMain.initConfig();
LodCommonMain.startup(this, !FMLLoader.getDist().isClient());
ForgeDependencySetup.createInitialBindings();
ClientApi.LOGGER.info("Distant Horizons initializing...");
SingletonHandler.bind(IModChecker.class, ModChecker.INSTANCE);
if (ReflectionHandler.instance.optifinePresent()) {
ModAccessorApi.bind(IOptifineAccessor.class, new OptifineAccessor());
}
ForgeDependencySetup.finishBinding();
ApiShared.LOGGER.info("Distant Horizons initializing...");
}
@@ -91,15 +88,30 @@ public class ForgeMain implements LodForgeMethodCaller
private void onClientStart(final FMLClientSetupEvent event)
{
ModLoadingContext.get().registerExtensionPoint(ExtensionPoint.CONFIGGUIFACTORY,
() -> (client, parent) -> ConfigGui.getScreen(parent, ""));
if (ReflectionHandler.instance.optifinePresent()) {
ModAccessorHandler.bind(IOptifineAccessor.class, new OptifineAccessor());
}
ModAccessorHandler.finishBinding();
ModAccessorHandler.finishBinding();
ModLoadingContext.get().registerExtensionPoint(ConfigGuiHandler.ConfigGuiFactory.class,
() -> new ConfigGuiHandler.ConfigGuiFactory((client, parent) -> ConfigGui.getScreen(parent, "")));
forgeClientProxy = new ForgeClientProxy();
MinecraftForge.EVENT_BUS.register(forgeClientProxy);
}
private ModelDataMap dataMap = new ModelDataMap.Builder().build();
@Override
public List<BakedQuad> getQuads(MinecraftWrapper mc, Block block, BlockState blockState, Direction direction, Random random) {
public List<BakedQuad> getQuads(MinecraftClientWrapper mc, Block block, BlockState blockState, Direction direction, Random random) {
return mc.getModelManager().getBlockModelShaper().getBlockModel(block.defaultBlockState()).getQuads(blockState, direction, random, dataMap);
}
@Override
public int getPixelRGBA(TextureAtlasSprite sprite, int frameIndex, int x, int y) {
return sprite.getPixelRGBA(frameIndex, x, y);
}
}
@@ -5,49 +5,42 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.systems.RenderSystem;
import com.seibel.lod.core.api.ClientApi;
import com.seibel.lod.core.util.SingletonHandler;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
import net.minecraft.client.Camera;
import net.minecraft.client.renderer.FogRenderer;
import net.minecraft.client.renderer.FogRenderer.FogMode;
import net.minecraft.tags.FluidTags;
import net.minecraft.world.effect.MobEffects;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.material.FogType;
@Mixin(FogRenderer.class)
public class MixinFogRenderer {
// Using this instead of Float.MAX_VALUE because Sodium don't like it. (And keeping it for forge just in case)
private static final float A_REALLY_REALLY_BIG_VALUE = 4206942069.F;
private static final float A_EVEN_LARGER_VALUE = 420694206942069.F;
// Using this instead of Float.MAX_VALUE because Sodium don't like it. (And just in case it's here also for forge)
private static final float A_REALLY_REALLY_BIG_VALUE = 420694206942069.F;
private static final float A_EVEN_LARGER_VALUE = 42069420694206942069.F;
@Inject(at = @At("RETURN"),
method = "setupFog(Lnet/minecraft/client/Camera;Lnet/minecraft/client/renderer/FogRenderer$FogMode;FZF)V")
private static final void disableSetupFog(Camera camera, FogMode fogMode, float f, boolean bl, float ticks, CallbackInfo callback) {
ILodConfigWrapperSingleton CONFIG;
method = "setupFog(Lnet/minecraft/client/Camera;Lnet/minecraft/client/renderer/FogRenderer$FogMode;FZF)V",
remap = false) // Due to this being a forge added method
private static void disableSetupFog(Camera camera, FogMode fogMode, float f, boolean bl, float tick, CallbackInfo callback) {
ILodConfigWrapperSingleton CONFIG;
try {
CONFIG = SingletonHandler.get(ILodConfigWrapperSingleton.class);
} catch (NullPointerException e) {
return; // Can happen due to forge calling this before setting up the mod
return; // Happens on forge not loading the mod before this.
}
ClientApi.LOGGER.debug("LOD: MixinSetupFog called!");
FluidState fluidState = camera.getFluidInCamera();
FogType fogTypes = camera.getFluidInCamera();
Entity entity = camera.getEntity();
boolean isUnderWater = (entity instanceof LivingEntity) && ((LivingEntity)entity).hasEffect(MobEffects.BLINDNESS);
isUnderWater |= fluidState.is(FluidTags.WATER);
isUnderWater |= fluidState.is(FluidTags.LAVA);
if (!isUnderWater) {
if (fogMode == FogMode.FOG_TERRAIN && CONFIG.client().graphics().fogQuality().getDisableVanillaFog()) {
RenderSystem.fogStart(A_REALLY_REALLY_BIG_VALUE);
RenderSystem.fogEnd(A_EVEN_LARGER_VALUE);
if (fogMode == FogMode.FOG_TERRAIN && fogTypes == FogType.NONE && CONFIG.client().graphics().fogQuality().getDisableVanillaFog()) {
RenderSystem.setShaderFogStart(A_REALLY_REALLY_BIG_VALUE);
RenderSystem.setShaderFogEnd(A_EVEN_LARGER_VALUE);
}
}
}
}
}
@@ -3,7 +3,7 @@ package com.seibel.lod.forge.mixins;
import com.seibel.lod.common.wrappers.config.ConfigGui;
import com.seibel.lod.common.wrappers.config.TexturedButtonWidget;
import com.seibel.lod.core.ModInfo;
import com.seibel.lod.core.util.SingletonHandler;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
import net.minecraft.client.gui.screens.OptionsScreen;
import net.minecraft.client.gui.screens.Screen;
@@ -34,7 +34,7 @@ public class MixinOptionsScreen extends Screen {
@Inject(at = @At("HEAD"),method = "init")
private void lodconfig$init(CallbackInfo ci) {
if (SingletonHandler.get(ILodConfigWrapperSingleton.class).client().getOptionsButton())
this.addButton(new TexturedButtonWidget(
this.addRenderableWidget(new TexturedButtonWidget(
// Where the button is on the screen
this.width / 2 - 180, this.height / 6 - 12,
// Width and height of the button
@@ -0,0 +1,48 @@
package com.seibel.lod.forge.mixins;
import java.util.concurrent.Executor;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import com.seibel.lod.common.wrappers.DependencySetupDoneCheck;
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.wrapperInterfaces.IWrapperFactory;
import net.minecraft.Util;
@Mixin(Util.class)
public class MixinUtilBackgroudThread
{
private static boolean doTriggerOverride() {
try {
return DependencySetupDoneCheck.getIsCurrentThreadDistantGeneratorThread.get();
} catch (NullPointerException e) {
return false;
}
}
@Inject(method = "wrapThreadWithTaskName(Ljava/lang/String;Ljava/lang/Runnable;)Ljava/lang/Runnable;",
at = @At("HEAD"), cancellable = true)
private static void overrideUtil$wrapThreadWithTaskName(String string, Runnable r, CallbackInfoReturnable<Runnable> ci)
{
if (DependencySetupDoneCheck.isDone && doTriggerOverride())
{
// ApiShared.LOGGER.info("util wrapThreadWithTaskName(Runnable) triggered");
ci.setReturnValue(r);
}
}
@Inject(method = "backgroundExecutor", at = @At("HEAD"), cancellable = true)
private static void overrideUtil$backgroundExecutor(CallbackInfoReturnable<Executor> ci)
{
if (DependencySetupDoneCheck.isDone && doTriggerOverride())
{
// ApiShared.LOGGER.info("util backgroundExecutor triggered");
ci.setReturnValue(Runnable::run);
}
}
}
@@ -20,19 +20,18 @@
package com.seibel.lod.forge.mixins;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.math.Matrix4f;
import com.seibel.lod.common.Config;
import com.seibel.lod.common.wrappers.McObjectConverter;
import com.seibel.lod.core.api.ClientApi;
import com.seibel.lod.core.objects.math.Mat4f;
import net.minecraft.client.renderer.LevelRenderer;
import org.lwjgl.opengl.GL15;
import net.minecraft.client.renderer.RenderType;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import com.seibel.lod.core.api.ClientApi;
import com.seibel.lod.core.objects.math.Mat4f;
import net.minecraft.client.renderer.RenderType;
/**
* This class is used to mix in my rendering code
* before Minecraft starts rendering blocks.
@@ -49,37 +48,35 @@ import net.minecraft.client.renderer.RenderType;
@Mixin(LevelRenderer.class)
public class MixinWorldRenderer
{
// TODO: Fix clouds
private static float previousPartialTicks = 0;
public MixinWorldRenderer() {
throw new NullPointerException("Null cannot be cast to non-null type.");
}
@Inject(at = @At("RETURN"), method = "renderSky(Lcom/mojang/blaze3d/vertex/PoseStack;F)V")
private void renderSky(PoseStack matrixStackIn, float partialTicks, CallbackInfo callback)
{
// get the partial ticks since renderBlockLayer doesn't
@Inject(method = "renderClouds", at = @At("HEAD"), cancellable = true)
public void renderClouds(PoseStack poseStack, Matrix4f projectionMatrix, float tickDelta, double cameraX, double cameraY, double cameraZ, CallbackInfo ci) {
// get the partial ticks since renderChunkLayer doesn't
// have access to them
previousPartialTicks = partialTicks;
previousPartialTicks = tickDelta;
}
// HEAD or RETURN
@Inject(at = @At("HEAD"), method = "renderChunkLayer(Lnet/minecraft/client/renderer/RenderType;Lcom/mojang/blaze3d/vertex/PoseStack;DDD)V")
private void renderChunkLayer(RenderType renderType, PoseStack matrixStackIn, double xIn, double yIn, double zIn, CallbackInfo callback)
@Inject(at = @At("HEAD"),
method = "renderChunkLayer(Lnet/minecraft/client/renderer/RenderType;Lcom/mojang/blaze3d/vertex/PoseStack;DDDLcom/mojang/math/Matrix4f;)V",
cancellable = true)
private void renderChunkLayer(RenderType renderType, PoseStack modelViewMatrixStack, double cameraXBlockPos, double cameraYBlockPos, double cameraZBlockPos, Matrix4f projectionMatrix, CallbackInfo callback)
{
// only render before solid blocks
if (renderType.equals(RenderType.solid()))
{
// get MC's current projection matrix
float[] mcProjMatrixRaw = new float[16];
GL15.glGetFloatv(GL15.GL_PROJECTION_MATRIX, mcProjMatrixRaw);
Mat4f mcProjectionMatrix = new Mat4f(mcProjMatrixRaw);
// OpenGl outputs their matrices in col,row form instead of row,col
// (or maybe vice versa I have no idea :P)
mcProjectionMatrix.transpose();
Mat4f mcModelViewMatrix = McObjectConverter.Convert(matrixStackIn.last().pose());
Mat4f mcModelViewMatrix = McObjectConverter.Convert(modelViewMatrixStack.last().pose());
Mat4f mcProjectionMatrix = McObjectConverter.Convert(projectionMatrix);
ClientApi.INSTANCE.renderLods(mcModelViewMatrix, mcProjectionMatrix, previousPartialTicks);
}
if (Config.Client.Advanced.lodOnlyMode) {
callback.cancel();
}
}
}
@@ -1,8 +1,10 @@
package com.seibel.lod.forge.wrappers;
import com.seibel.lod.common.wrappers.config.LodConfigWrapperSingleton;
import com.seibel.lod.core.util.SingletonHandler;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
import com.seibel.lod.core.wrapperInterfaces.modAccessor.IModChecker;
import com.seibel.lod.forge.wrappers.modAccessor.ModChecker;
/**
* Binds all necessary dependencies so we
@@ -12,12 +14,18 @@ import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
*
* @author James Seibel
* @author Ran
* @version 12-1-2021
* @version 3-5-2022
*/
public class ForgeDependencySetup
{
public static void createInitialBindings()
{
SingletonHandler.bind(ILodConfigWrapperSingleton.class, LodConfigWrapperSingleton.INSTANCE);
SingletonHandler.bind(IModChecker.class, ModChecker.INSTANCE);
}
public static void finishBinding()
{
SingletonHandler.finishBinding();
}
}
@@ -10,4 +10,4 @@ public class ModChecker implements IModChecker {
public boolean isModLoaded(String modid) {
return ModList.get().isLoaded(modid);
}
}
}
@@ -1,4 +1,3 @@
package com.seibel.lod.forge.wrappers.modAccessor;
import java.util.HashSet;
@@ -22,4 +21,4 @@ public class OptifineAccessor implements IOptifineAccessor
return null;
}
}
}
+2 -2
View File
@@ -2,7 +2,7 @@
modLoader="javafml" #//mandatory
loaderVersion="[36,)" # // mandatory. This is typically bumped every Minecraft version by Forge. See our download page for lists of versions.
license="GNU GPLv3"
issueTrackerURL="https://gitlab.com/jeseibel/minecraft-lod-mod/-/issues"
issueTrackerURL="${issues}"
[[mods]] #//mandatory
@@ -10,7 +10,7 @@ issueTrackerURL="https://gitlab.com/jeseibel/minecraft-lod-mod/-/issues"
version= "${version}" #//mandatory, gets the version number from jar populated by the build.gradle script
displayName="${mod_name}" #//mandatory
#//updateJSONURL="https://change.me.example.invalid/updates.json" # A URL to query for updates for this mod. See the JSON update specification https://mcforge.readthedocs.io/en/latest/gettingstarted/autoupdate/
displayURL="https://www.curseforge.com/minecraft/mc-mods/lod-level-of-detail"
displayURL="${homepage}"
logoFile="logo.png"
catalogueImageIcon="icon.png"
credits="Massive thanks to: Leonardo, Cola, Ran, and CoolGi. For their hard work to bring Distant Horizons to where it is today. - James"
+4 -3
View File
@@ -2,9 +2,10 @@
"required": true,
"minVersion": "0.8",
"package": "com.seibel.lod.forge.mixins",
"compatibilityLevel": "JAVA_8",
"compatibilityLevel": "JAVA_16",
"mixins": [
"MixinChunkGenerator"
"MixinChunkGenerator",
"MixinUtilBackgroudThread"
],
"client": [
"MixinOptionsScreen",
@@ -12,4 +13,4 @@
"MixinFogRenderer"
],
"server": []
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"pack": {
"description": "",
"pack_format": 6
"pack_format": 7
}
}
+10 -17
View File
@@ -1,28 +1,21 @@
org.gradle.jvmargs=-Xmx2048M
org.gradle.daemon=false
minecraft_version=1.16.5
archives_base_name=DistantHorizons
mod_version=1.6.0a
maven_group=com.seibel.lod
toml_version=3.6.4
archives_base_name=DistantHorizons
# Mod info
mod_version=1.6.2a
mod_name=Distant Horizons
mod_description=This mod generates and renders simplified terrain beyond the normal view distance at a low performance cost. Allowing you to see much farther without turning your game into a slideshow.
mod_authors=James Seibel, Leonardo Amato, Cola, coolGi2007, Ran, Leetom
mod_homepage=https://www.curseforge.com/minecraft/mc-mods/distant-horizons
mod_source=https://gitlab.com/jeseibel/minecraft-lod-mod/
mod_issues=https://gitlab.com/jeseibel/minecraft-lod-mod/-/issues
# Fabric loader
fabric_loader_version=0.12.3
fabric_api_version=0.34.2+1.16
# Fabric mods
modmenu_version=1.16.22
lithium_version=mc1.16.5-0.6.6
sodium_version=3488820
iris_version=1.16.x-v1.1.4
# Global Plugin versions
toml_version=3.6.4
manifold_version=2022.1.7
# Forge loader
forge_version=36.2.23
# Forge mods
## currentlly no mods ##
##### FOR IDE SUPPORT AND TELL IDE TO USE CERTIAN MC VERSION: SWITCH THIS:
mcVer=1.17.1
Binary file not shown.