Compare commits
59 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1860729256 | |||
| d0b0fae54e | |||
| 7786e1fea6 | |||
| e5ad718ed0 | |||
| bda34d0a6d | |||
| 2584afbd05 | |||
| 72e4b520db | |||
| 3220ad0f7a | |||
| aba99f8210 | |||
| 430579be28 | |||
| 30cc294a04 | |||
| aa79d5b5d4 | |||
| 509ae5aba0 | |||
| 44dc7c96af | |||
| 89cc3513f3 | |||
| 7a94db77ef | |||
| f2fc669b37 | |||
| a3d4163b67 | |||
| aea4542616 | |||
| a489810d68 | |||
| 806a1e99db | |||
| 4843027e43 | |||
| af4ba453ca | |||
| adc5853f0b | |||
| c42ddd29a9 | |||
| 9b7d3c083f | |||
| 87bb4ae840 | |||
| b34f5e7f5f | |||
| a053a79d99 | |||
| 73c041e02f | |||
| f96a5fc794 | |||
| d591458cd6 | |||
| 88305d8db3 | |||
| 40b0517656 | |||
| 2289826363 | |||
| e1c2b2a0a9 | |||
| 70f7a2422b | |||
| 8ad6f184dd | |||
| 4a93bde7be | |||
| b9dfd93b56 | |||
| 5e78c98f17 | |||
| 31035ccb1e | |||
| e840a23d01 | |||
| 08b8f8778a | |||
| 044f87eef2 | |||
| 30cd7fd4e0 | |||
| fbf5dfaa9d | |||
| 58d4bc7f0f | |||
| 511a771351 | |||
| e806098544 | |||
| 4316cfbfd7 | |||
| 6be4c0303f | |||
| 7633c7bc70 | |||
| 0bc96a98cf | |||
| a0529a310b | |||
| ace3c03019 | |||
| 16b44695ec | |||
| 151ca3902f | |||
| 1ba24659bc |
@@ -1,65 +1,15 @@
|
||||
# Distant Horizons
|
||||
|
||||
This mod adds a Level Of Detail (LOD) system to Minecraft.\
|
||||
This implementation renders simplified chunks outside the normal render distance\
|
||||
allowing for an increased view distance without harming performance.
|
||||
|
||||
Or in other words: this mod lets you see farther without turning your game into a slide show.\
|
||||
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"></a>
|
||||
|
||||
|
||||
Forge version: 1.16.5-36.1.0
|
||||
|
||||
Notes:\
|
||||
This version has been confirmed to work in Eclipse and Retail Minecraft.\
|
||||
(Retail running forge version 1.16.5-36.1.0)
|
||||
This repo is for the Distant Horizons mod.
|
||||
The purpose of this submodule is to isolate code that isn't tied to a specific version of minecraft. This prevents us from having duplicate code; reducing errors and potentially helping us port to different versions faster and easier.
|
||||
|
||||
Check out the mod's main GitLab page here:
|
||||
https://gitlab.com/jeseibel/minecraft-lod-mod
|
||||
|
||||
## source code installation
|
||||
|
||||
See the Forge Documentation online for more detailed instructions:\
|
||||
http://mcforge.readthedocs.io/en/latest/gettingstarted/
|
||||
|
||||
1. Create a system variable called "JAVA_MC_HOME" with the location of the JDK 1.8.0_251 (This is needed for gradle to work correctly)
|
||||
2. replace JAVA_HOME with JAVA_MC_HOME in gradle.bat
|
||||
3. open a command line in the project folder
|
||||
|
||||
**If using Ecplise:**
|
||||
1. run the command: `./gradlew geneclipseruns`
|
||||
2. run the command: `./gradlew eclipse`
|
||||
3. Make sure eclipse has the JDK 1.8.0_251 installed. (This is needed so that eclipse can run minecraft)
|
||||
4. Import the project into eclipse
|
||||
|
||||
**If using IntelliJ:**
|
||||
1. open IDEA and import the build.gradle
|
||||
2. run the command: `./gradlew genIntellijRuns`
|
||||
3. refresh the Gradle project in IDEA if required
|
||||
|
||||
|
||||
## Compiling
|
||||
|
||||
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 `build\libs`
|
||||
|
||||
|
||||
## Other commands
|
||||
|
||||
`./gradlew --refresh-dependencies` to refresh local dependencies.
|
||||
|
||||
`./gradlew clean` to reset everything (this does not affect your code) and then start the process again.
|
||||
|
||||
|
||||
## Note to self
|
||||
|
||||
The Minecraft source code is NOT added to your workspace in an editable way. Minecraft is treated like a normal Library. Sources are there for documentation and research purposes only.
|
||||
|
||||
Source code uses Mojang mappings.
|
||||
|
||||
The source code can be 'created' with the `./eclipse` command and can be found in the following path:\
|
||||
`minecraft-lod-mod\build\fg_cache\mcp\ VERSION \joined\ RANDOM_STRING \patch\output.jar`
|
||||
You shouldn't download this repo directly.
|
||||
It should be automatically included when pulling the full mod.
|
||||
|
||||
|
||||
## Open Source Acknowledgements
|
||||
|
||||
File diff suppressed because one or more lines are too long
Binary file not shown.
|
After Width: | Height: | Size: 101 KiB |
-234
@@ -1,234 +0,0 @@
|
||||
buildscript {
|
||||
repositories {
|
||||
maven { url = 'https://files.minecraftforge.net' }
|
||||
mavenCentral()
|
||||
// potential replacement in case of problems:
|
||||
// https://dist.creeper.host/Sponge/maven
|
||||
maven { url = 'https://repo.spongepowered.org/maven/' }
|
||||
// used to download and compile dependencies from git repos
|
||||
maven { url 'https://jitpack.io' }
|
||||
}
|
||||
dependencies {
|
||||
classpath group: 'net.minecraftforge.gradle', name: 'ForgeGradle', version: '3.+', changing: true
|
||||
classpath group: 'org.spongepowered', name: 'mixingradle', version: '0.7-SNAPSHOT'
|
||||
classpath 'com.github.jengelman.gradle.plugins:shadow:2.0.2'
|
||||
}
|
||||
}
|
||||
apply plugin: 'net.minecraftforge.gradle'
|
||||
apply plugin: 'org.spongepowered.mixin'
|
||||
// Only edit below this line, the above code adds and enables the necessary things for Forge to be setup.
|
||||
apply plugin: 'eclipse'
|
||||
apply plugin: 'maven-publish'
|
||||
apply plugin: 'com.github.johnrengelman.shadow'
|
||||
|
||||
version = 'a1.5.3'
|
||||
group = 'com.seibel.lod'
|
||||
archivesBaseName = 'Distant-Horizons_1.16.5'
|
||||
|
||||
|
||||
sourceCompatibility = targetCompatibility = compileJava.sourceCompatibility = compileJava.targetCompatibility = '1.8' // Need this here so eclipse task generates correctly.
|
||||
|
||||
println('Java: ' + System.getProperty('java.version') + ' JVM: ' + System.getProperty('java.vm.version') + '(' + System.getProperty('java.vendor') + ') Arch: ' + System.getProperty('os.arch'))
|
||||
minecraft {
|
||||
// The mappings can be changed at any time, and must be in the following format.
|
||||
// snapshot_YYYYMMDD Snapshot are built nightly.
|
||||
// stable_# Stables are built at the discretion of the MCP team.
|
||||
// Use non-default mappings at your own risk. they may not always work.
|
||||
// Simply re-run your setup task after changing the mappings to update your workspace.
|
||||
mappings channel: 'official', version: '1.16.5'
|
||||
|
||||
// makeObfSourceJar = false // an Srg named sources jar is made by default. uncomment this to disable.
|
||||
|
||||
accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg')
|
||||
|
||||
// Default run configurations.
|
||||
// These can be tweaked, removed, or duplicated as needed.
|
||||
runs {
|
||||
client {
|
||||
workingDirectory project.file('run')
|
||||
arg "-mixin.config=lod.mixins.json"
|
||||
|
||||
// Recommended logging data for a userdev environment
|
||||
// The markers can be changed as needed.
|
||||
// "SCAN": For mods scan.
|
||||
// "REGISTRIES": For firing of registry events.
|
||||
// "REGISTRYDUMP": For getting the contents of all registries.
|
||||
property 'forge.logging.markers', 'REGISTRIES'
|
||||
|
||||
// Recommended logging level for the console
|
||||
// You can set various levels here.
|
||||
// Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels
|
||||
property 'forge.logging.console.level', 'debug'
|
||||
|
||||
mods {
|
||||
examplemod {
|
||||
source sourceSets.main
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
server {
|
||||
workingDirectory project.file('run')
|
||||
arg "-mixin.config=lod.mixins.json"
|
||||
|
||||
// Recommended logging data for a userdev environment
|
||||
// The markers can be changed as needed.
|
||||
// "SCAN": For mods scan.
|
||||
// "REGISTRIES": For firing of registry events.
|
||||
// "REGISTRYDUMP": For getting the contents of all registries.
|
||||
property 'forge.logging.markers', 'REGISTRIES'
|
||||
|
||||
// Recommended logging level for the console
|
||||
// You can set various levels here.
|
||||
// Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels
|
||||
property 'forge.logging.console.level', 'debug'
|
||||
|
||||
mods {
|
||||
examplemod {
|
||||
source sourceSets.main
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data {
|
||||
workingDirectory project.file('run')
|
||||
|
||||
// Recommended logging data for a userdev environment
|
||||
// The markers can be changed as needed.
|
||||
// "SCAN": For mods scan.
|
||||
// "REGISTRIES": For firing of registry events.
|
||||
// "REGISTRYDUMP": For getting the contents of all registries.
|
||||
property 'forge.logging.markers', 'REGISTRIES'
|
||||
|
||||
// Recommended logging level for the console
|
||||
// You can set various levels here.
|
||||
// Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels
|
||||
property 'forge.logging.console.level', 'debug'
|
||||
|
||||
// Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources.
|
||||
args '--mod', 'lod', '--all', '--output', file('src/generated/resources/'), '--existing', file('src/main/resources/')
|
||||
|
||||
mods {
|
||||
examplemod {
|
||||
source sourceSets.main
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Include resources generated by data generators.
|
||||
sourceSets.main.resources { srcDir 'src/generated/resources' }
|
||||
|
||||
// this is required so that we can use
|
||||
// jitpack in the dependencies section below
|
||||
repositories {
|
||||
mavenCentral()
|
||||
// used to download and compile dependencies from git repos
|
||||
maven { url 'https://jitpack.io' }
|
||||
}
|
||||
|
||||
configurations {
|
||||
shadowMe
|
||||
compileOnly.extendsFrom(embed)
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// Specify the version of Minecraft to use, If this is any group other then 'net.minecraft' it is assumed
|
||||
// that the dep is a ForgeGradle 'patcher' dependency. And it's patches will be applied.
|
||||
// The userdev artifact is a special name and will get all sorts of transformations applied to it.
|
||||
minecraft 'net.minecraftforge:forge:1.16.5-36.1.0'
|
||||
|
||||
|
||||
compile 'org.tukaani:xz:1.9'
|
||||
shadowMe 'org.tukaani:xz:1.9'
|
||||
compile 'org.apache.commons:commons-compress:1.21'
|
||||
shadowMe 'org.apache.commons:commons-compress:1.21'
|
||||
|
||||
// these were added to hopefully allow for cloning
|
||||
// configuredFeatures to allow for safe
|
||||
// multi threaded feature generation. Sadly I couldn't find
|
||||
// a way to duplicate lambda functions (which features use)
|
||||
// so for now I'm not sure what to do.
|
||||
//implementation 'io.github.kostaskougios:cloning:1.10.3'
|
||||
//
|
||||
//implementation ('com.esotericsoftware:kryo:5.1.1') {
|
||||
// exclude group: "org.objenesis"
|
||||
//}
|
||||
//implementation 'org.objenesis:objenesis:3.2'
|
||||
|
||||
|
||||
// You may put jars on which you depend on in ./libs or you may define them like so..
|
||||
// compile "some.group:artifact:version:classifier"
|
||||
// compile "some.group:artifact:version"
|
||||
|
||||
// Real examples
|
||||
// compile 'com.mod-buildcraft:buildcraft:6.0.8:dev' // adds buildcraft to the dev env
|
||||
// compile 'com.googlecode.efficient-java-matrix-library:ejml:0.24' // adds ejml to the dev env
|
||||
|
||||
// The 'provided' configuration is for optional dependencies that exist at compile-time but might not at runtime.
|
||||
// provided 'com.mod-buildcraft:buildcraft:6.0.8:dev'
|
||||
|
||||
// These dependencies get remapped to your current MCP mappings
|
||||
// deobf 'com.mod-buildcraft:buildcraft:6.0.8:dev'
|
||||
|
||||
// For more info...
|
||||
// http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html
|
||||
// http://www.gradle.org/docs/current/userguide/dependency_management.html
|
||||
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
duplicatesStrategy = DuplicatesStrategy.INCLUDE
|
||||
configurations = [project.configurations.getByName("shadowMe")]
|
||||
relocate 'org.tukaani', 'shaded.tukaani'
|
||||
relocate 'org.apache.commons.compress', 'shaded.apache.commons.compress'
|
||||
classifier = ''
|
||||
}
|
||||
|
||||
reobf {
|
||||
shadowJar {
|
||||
dependsOn tasks.createMcpToSrg
|
||||
mappings = tasks.createMcpToSrg.outputs.files.singleFile
|
||||
}
|
||||
}
|
||||
|
||||
artifacts {
|
||||
archives tasks.shadowJar
|
||||
}
|
||||
|
||||
// Example for how to get properties into the manifest for reading by the runtime..
|
||||
jar {
|
||||
manifest {
|
||||
attributes([
|
||||
"Specification-Title": "LOD",
|
||||
"Specification-Version": "1", // We are version 1 of ourselves
|
||||
"Implementation-Title": project.name,
|
||||
"Implementation-Version": "1",
|
||||
"Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ"),
|
||||
"MixinConfigs": "lod.mixins.json",
|
||||
])
|
||||
}
|
||||
}
|
||||
// Example configuration to allow publishing using the maven-publish task
|
||||
// This is the preferred method to reobfuscate your jar file
|
||||
jar.finalizedBy('reobfJar')
|
||||
// However if you are in a multi-project build, dev time needs unobfed jar files, so you can delay the obfuscation until publishing by doing
|
||||
//publish.dependsOn('reobfJar')
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
mavenJava(MavenPublication) {
|
||||
artifact jar
|
||||
}
|
||||
}
|
||||
repositories {
|
||||
maven {
|
||||
url "file:///${project.projectDir}/mcmodsrepo"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mixin {
|
||||
add sourceSets.main, "lod.refmap.json"
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
# Sets default memory used for gradle commands. Can be overridden by user or command line properties.
|
||||
# This is required to provide enough memory for the Minecraft decompilation process.
|
||||
org.gradle.jvmargs=-Xmx3G
|
||||
org.gradle.daemon=false
|
||||
Vendored
BIN
Binary file not shown.
-5
@@ -1,5 +0,0 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.3-bin.zip
|
||||
@@ -1,172 +0,0 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >/dev/null
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS=""
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
NONSTOP* )
|
||||
nonstop=true
|
||||
;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
MAX_FD="$MAX_FD_LIMIT"
|
||||
fi
|
||||
ulimit -n $MAX_FD
|
||||
if [ $? -ne 0 ] ; then
|
||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||
fi
|
||||
else
|
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock
|
||||
if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
SEP=""
|
||||
for dir in $ROOTDIRSRAW ; do
|
||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||
SEP="|"
|
||||
done
|
||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||
# Add a user-defined pattern to the cygpath arguments
|
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||
fi
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "$@" ; do
|
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=$((i+1))
|
||||
done
|
||||
case $i in
|
||||
(0) set -- ;;
|
||||
(1) set -- "$args0" ;;
|
||||
(2) set -- "$args0" "$args1" ;;
|
||||
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Escape application args
|
||||
save () {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
}
|
||||
APP_ARGS=$(save "$@")
|
||||
|
||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||
|
||||
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
||||
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
||||
cd "$(dirname "$0")"
|
||||
fi
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
Vendored
-84
@@ -1,84 +0,0 @@
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS=
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_MC_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_MC_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_MC_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_MC_HOME=%JAVA_MC_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_MC_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_MC_HOME is set to an invalid directory: %JAVA_MC_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_MC_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:init
|
||||
@rem Get command-line arguments, handling Windows variants
|
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||
|
||||
:win9xME_args
|
||||
@rem Slurp the command line arguments.
|
||||
set CMD_LINE_ARGS=
|
||||
set _SKIP=2
|
||||
|
||||
:win9xME_args_slurp
|
||||
if "x%~1" == "x" goto execute
|
||||
|
||||
set CMD_LINE_ARGS=%*
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
@@ -28,7 +28,7 @@ package com.seibel.lod.core;
|
||||
* Pretty much all of the mod stems from there.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 11-13-2021
|
||||
* @version 11-29-2021
|
||||
*/
|
||||
public final class ModInfo
|
||||
{
|
||||
@@ -38,5 +38,5 @@ public final class ModInfo
|
||||
/** Human readable version of NAME */
|
||||
public static final String READABLE_NAME = "Distant Horizons";
|
||||
public static final String API = "LodAPI";
|
||||
public static final String VERSION = "a1.5.3";
|
||||
public static final String VERSION = "a1.5.4";
|
||||
}
|
||||
@@ -23,14 +23,12 @@ import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import com.seibel.lod.core.ModInfo;
|
||||
import com.seibel.lod.core.builders.worldGeneration.LodGenWorker;
|
||||
import com.seibel.lod.core.objects.lod.LodDimension;
|
||||
import com.seibel.lod.core.objects.math.Mat4f;
|
||||
import com.seibel.lod.core.render.GLProxy;
|
||||
import com.seibel.lod.core.render.LodRenderer;
|
||||
import com.seibel.lod.core.util.DetailDistanceUtil;
|
||||
import com.seibel.lod.core.util.SingletonHandler;
|
||||
import com.seibel.lod.core.util.ThreadMapUtil;
|
||||
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
|
||||
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftWrapper;
|
||||
@@ -103,19 +101,24 @@ public class ClientApi
|
||||
lodDim.expandOrLoadRegionsAsync(MC.getPlayerBlockPos().getX(), MC.getPlayerBlockPos().getZ());
|
||||
|
||||
|
||||
// Note to self:
|
||||
// if "unspecified" shows up in the pie chart, it is
|
||||
// possibly because the amount of time between sections
|
||||
// is too small for the profiler to measure
|
||||
IProfilerWrapper profiler = MC.getProfiler();
|
||||
profiler.pop(); // get out of "terrain"
|
||||
profiler.push("LOD");
|
||||
|
||||
if (CONFIG.client().advanced().debugging().getDrawLods())
|
||||
{
|
||||
// Note to self:
|
||||
// if "unspecified" shows up in the pie chart, it is
|
||||
// possibly because the amount of time between sections
|
||||
// is too small for the profiler to measure
|
||||
IProfilerWrapper profiler = MC.getProfiler();
|
||||
profiler.pop(); // get out of "terrain"
|
||||
profiler.push("LOD");
|
||||
|
||||
|
||||
ClientApi.renderer.drawLODs(lodDim, mcModelViewMatrix, mcProjectionMatrix, partialTicks, MC.getProfiler());
|
||||
|
||||
profiler.pop(); // end LOD
|
||||
profiler.push("terrain"); // go back into "terrain"
|
||||
}
|
||||
|
||||
ClientApi.renderer.drawLODs(lodDim, mcModelViewMatrix, mcProjectionMatrix, partialTicks, MC.getProfiler());
|
||||
|
||||
profiler.pop(); // end LOD
|
||||
profiler.push("terrain"); // go back into "terrain"
|
||||
|
||||
|
||||
// these can't be set until after the buffers are built (in renderer.drawLODs)
|
||||
@@ -143,10 +146,18 @@ public class ClientApi
|
||||
configOverrideReminderPrinted = true;
|
||||
}
|
||||
|
||||
// CONFIG.client().worldGenerator().setDistanceGenerationMode(DistanceGenerationMode.SURFACE);
|
||||
// CONFIG.client().worldGenerator().setDistanceGenerationMode(DistanceGenerationMode.FULL);
|
||||
|
||||
// CONFIG.client().worldGenerator().setGenerationPriority(GenerationPriority.AUTO);
|
||||
|
||||
// CONFIG.client().graphics().advancedGraphics().setGpuUploadMethod(GpuUploadMethod.BUFFER_STORAGE);
|
||||
// CONFIG.client().graphics().quality().setLodChunkRenderDistance(128);
|
||||
|
||||
// CONFIG.client().graphics().fogQuality().setFogDrawMode(FogDrawMode.FOG_ENABLED);
|
||||
// CONFIG.client().graphics().fogQuality().setFogDistance(FogDistance.FAR);
|
||||
// CONFIG.client().graphics().fogQuality().setDisableVanillaFog(true);
|
||||
|
||||
// CONFIG.client().advanced().buffers().setRebuildTimes(BufferRebuildTimes.FREQUENT);
|
||||
|
||||
|
||||
CONFIG.client().advanced().debugging().setDebugKeybindingsEnabled(true);
|
||||
@@ -168,14 +179,6 @@ public class ClientApi
|
||||
firstTimeSetupComplete = true;
|
||||
}
|
||||
|
||||
/** this method reset some static data every time we change world */
|
||||
private void resetMod()
|
||||
{
|
||||
// TODO when should this be used?
|
||||
ThreadMapUtil.clearMaps();
|
||||
LodGenWorker.restartExecutorService();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ package com.seibel.lod.core.api;
|
||||
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
|
||||
import com.seibel.lod.core.builders.worldGeneration.LodGenWorker;
|
||||
import com.seibel.lod.core.builders.worldGeneration.LodWorldGenerator;
|
||||
import com.seibel.lod.core.enums.config.DistanceGenerationMode;
|
||||
import com.seibel.lod.core.objects.lod.LodDimension;
|
||||
@@ -103,7 +104,7 @@ public class EventApi
|
||||
/** This is also called when a new dimension loads */
|
||||
public void worldLoadEvent(IWorldWrapper world)
|
||||
{
|
||||
DataPointUtil.worldHeight = world.getHeight();
|
||||
DataPointUtil.WORLD_HEIGHT = world.getHeight();
|
||||
//LodNodeGenWorker.restartExecutorService();
|
||||
//ThreadMapUtil.clearMaps();
|
||||
|
||||
@@ -115,13 +116,30 @@ public class EventApi
|
||||
ClientApi.renderer.regenerateLODsNextFrame();
|
||||
}
|
||||
|
||||
/** This is also called when the user disconnects from a server+ */
|
||||
public void worldUnloadEvent()
|
||||
{
|
||||
// the player just unloaded a world/dimension
|
||||
ThreadMapUtil.clearMaps();
|
||||
|
||||
new Thread(() -> checkIfDisconnectedFromServer()).start();
|
||||
}
|
||||
private void checkIfDisconnectedFromServer()
|
||||
{
|
||||
try
|
||||
{
|
||||
// world unloading events are called before disconnecting from the server,
|
||||
// so we need to wait a second for MC to disconnect
|
||||
Thread.sleep(1000);
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
// this should never happen, but just in case
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
if (MC.getWrappedClientWorld() == null)
|
||||
|
||||
if (MC.getWrappedClientWorld() == null || (!MC.connectedToServer() && !MC.hasSinglePlayerServer()))
|
||||
{
|
||||
// the player just left the server
|
||||
|
||||
@@ -129,15 +147,14 @@ public class EventApi
|
||||
|
||||
// if this isn't done unfinished tasks may be left in the queue
|
||||
// preventing new LodChunks form being generated
|
||||
//LodNodeGenWorker.restartExecutorService(); // TODO why was this commented out? -James
|
||||
//ThreadMapUtil.clearMaps();
|
||||
LodGenWorker.restartExecutorService();
|
||||
|
||||
LodWorldGenerator.INSTANCE.numberOfChunksWaitingToGenerate.set(0);
|
||||
ApiShared.lodWorld.deselectWorld();
|
||||
|
||||
|
||||
// prevent issues related to the buffer builder
|
||||
// breaking when changing worlds.
|
||||
// breaking or retaining previous data when changing worlds.
|
||||
ClientApi.renderer.destroyBuffers();
|
||||
recalculateWidths = true;
|
||||
ClientApi.renderer = new LodRenderer(ApiShared.lodBufferBuilderFactory);
|
||||
|
||||
+310
-218
@@ -30,6 +30,7 @@ import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import com.seibel.lod.core.objects.VertexOptimizer;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL15;
|
||||
import org.lwjgl.opengl.GL30;
|
||||
@@ -41,8 +42,8 @@ import com.seibel.lod.core.enums.LodDirection;
|
||||
import com.seibel.lod.core.enums.config.GpuUploadMethod;
|
||||
import com.seibel.lod.core.enums.config.VanillaOverdraw;
|
||||
import com.seibel.lod.core.enums.rendering.GLProxyContext;
|
||||
import com.seibel.lod.core.objects.Box;
|
||||
import com.seibel.lod.core.objects.PosToRenderContainer;
|
||||
import com.seibel.lod.core.objects.VertexOptimizer;
|
||||
import com.seibel.lod.core.objects.lod.LodDimension;
|
||||
import com.seibel.lod.core.objects.lod.LodRegion;
|
||||
import com.seibel.lod.core.objects.lod.RegionPos;
|
||||
@@ -68,7 +69,7 @@ import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftWrapper;
|
||||
* rendered by the LodRenderer.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 11-21-2021
|
||||
* @version 11-29-2021
|
||||
*/
|
||||
public class LodBufferBuilderFactory
|
||||
{
|
||||
@@ -81,6 +82,8 @@ public class LodBufferBuilderFactory
|
||||
/** The threads used to generate buffers. */
|
||||
public static final ExecutorService bufferBuilderThreads = Executors.newFixedThreadPool(CONFIG.client().advanced().threading().getNumberOfBufferBuilderThreads(), new ThreadFactoryBuilder().setNameFormat("Buffer-Builder-%d").build());
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* When uploading to a buffer that is too small,
|
||||
* recreate it this many times bigger than the upload payload
|
||||
@@ -94,6 +97,8 @@ public class LodBufferBuilderFactory
|
||||
*/
|
||||
public static final int DEFAULT_MEMORY_ALLOCATION = 1024;
|
||||
|
||||
|
||||
|
||||
public static int skyLightPlayer = 15;
|
||||
|
||||
/**
|
||||
@@ -138,7 +143,7 @@ public class LodBufferBuilderFactory
|
||||
/** this is used to prevent multiple threads creating, destroying, or using the buffers at the same time */
|
||||
private final ReentrantLock bufferLock = new ReentrantLock();
|
||||
|
||||
private volatile Box[][] boxCache;
|
||||
private volatile VertexOptimizer[][] vertexOptimizerCache;
|
||||
private volatile PosToRenderContainer[][] setsToRender;
|
||||
private volatile RegionPos center;
|
||||
|
||||
@@ -180,6 +185,10 @@ public class LodBufferBuilderFactory
|
||||
// setupBuffers hasn't been called yet
|
||||
return;
|
||||
|
||||
if (MC.getCurrentLightMap() == null)
|
||||
// the lighting hasn't loaded yet
|
||||
return;
|
||||
|
||||
generatingBuffers = true;
|
||||
|
||||
|
||||
@@ -220,11 +229,11 @@ public class LodBufferBuilderFactory
|
||||
if (setsToRender.length != lodDim.getWidth())
|
||||
setsToRender = new PosToRenderContainer[lodDim.getWidth()][lodDim.getWidth()];
|
||||
|
||||
if (boxCache == null)
|
||||
boxCache = new Box[lodDim.getWidth()][lodDim.getWidth()];
|
||||
if (vertexOptimizerCache == null)
|
||||
vertexOptimizerCache = new VertexOptimizer[lodDim.getWidth()][lodDim.getWidth()];
|
||||
|
||||
if (boxCache.length != lodDim.getWidth())
|
||||
boxCache = new Box[lodDim.getWidth()][lodDim.getWidth()];
|
||||
if (vertexOptimizerCache.length != lodDim.getWidth())
|
||||
vertexOptimizerCache = new VertexOptimizer[lodDim.getWidth()][lodDim.getWidth()];
|
||||
|
||||
// this will be the center of the VBOs once they have been built
|
||||
buildableCenterChunkPos = playerChunkPos;
|
||||
@@ -256,7 +265,10 @@ public class LodBufferBuilderFactory
|
||||
// make sure the buffers weren't
|
||||
// changed while we were running this method
|
||||
if (currentBuffers == null || !currentBuffers[0].building())
|
||||
{
|
||||
ClientApi.LOGGER.info("Buffer building quit early");
|
||||
return;
|
||||
}
|
||||
|
||||
byte minDetail = region.getMinDetailLevel();
|
||||
|
||||
@@ -276,14 +288,16 @@ public class LodBufferBuilderFactory
|
||||
int bufferIndex;
|
||||
boolean posNotInPlayerChunk;
|
||||
boolean adjPosInPlayerChunk;
|
||||
Box box = ThreadMapUtil.getBox();
|
||||
VertexOptimizer vertexOptimizer = ThreadMapUtil.getBox();
|
||||
boolean[] adjShadeDisabled = ThreadMapUtil.getAdjShadeDisabledArray();
|
||||
|
||||
// determine how many LODs we can stack vertically
|
||||
int maxVerticalData = DetailDistanceUtil.getMaxVerticalData((byte) 0);
|
||||
|
||||
//we get or create the map that will contain the adj data
|
||||
Map<LodDirection, long[]> adjData = ThreadMapUtil.getAdjDataArray(maxVerticalData);
|
||||
|
||||
Map<LodDirection, int[]> adjData = ThreadMapUtil.getAdjDataArray(maxVerticalData);
|
||||
Map<LodDirection, byte[]> adjFlags = ThreadMapUtil.getAdjFlagsArray(maxVerticalData);
|
||||
|
||||
//previous setToRender cache
|
||||
if (setsToRender[xR][zR] == null)
|
||||
@@ -338,12 +352,14 @@ public class LodBufferBuilderFactory
|
||||
Arrays.fill(adjShadeDisabled, false);
|
||||
|
||||
//We check every adj block in each direction
|
||||
for (LodDirection lodDirection : Box.ADJ_DIRECTIONS)
|
||||
for (LodDirection lodDirection : VertexOptimizer.ADJ_DIRECTIONS)
|
||||
{
|
||||
|
||||
xAdj = posX + Box.DIRECTION_NORMAL_MAP.get(lodDirection).x;
|
||||
zAdj = posZ + Box.DIRECTION_NORMAL_MAP.get(lodDirection).z;
|
||||
long data;
|
||||
xAdj = posX + VertexOptimizer.DIRECTION_NORMAL_MAP.get(lodDirection).x;
|
||||
zAdj = posZ + VertexOptimizer.DIRECTION_NORMAL_MAP.get(lodDirection).z;
|
||||
int color;
|
||||
int data;
|
||||
byte flags;
|
||||
chunkXdist = LevelPosUtil.getChunkPos(detailLevel, xAdj) - playerChunkPos.getX();
|
||||
chunkZdist = LevelPosUtil.getChunkPos(detailLevel, zAdj) - playerChunkPos.getZ();
|
||||
adjPosInPlayerChunk = (chunkXdist == 0 && chunkZdist == 0);
|
||||
@@ -360,64 +376,81 @@ public class LodBufferBuilderFactory
|
||||
for (int verticalIndex = 0; verticalIndex < lodDim.getMaxVerticalData(detailLevel, xAdj, zAdj); verticalIndex++)
|
||||
{
|
||||
data = lodDim.getData(detailLevel, xAdj, zAdj, verticalIndex);
|
||||
adjShadeDisabled[Box.DIRECTION_INDEX.get(lodDirection)] = false;
|
||||
flags = lodDim.getFlags(detailLevel, xAdj, zAdj, verticalIndex);
|
||||
adjShadeDisabled[VertexOptimizer.DIRECTION_INDEX.get(lodDirection)] = false;
|
||||
adjData.get(lodDirection)[verticalIndex] = data;
|
||||
adjFlags.get(lodDirection)[verticalIndex] = flags;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//Otherwise, we check if this position is
|
||||
data = lodDim.getSingleData(detailLevel, xAdj, zAdj);
|
||||
data = lodDim.getData(detailLevel, xAdj, zAdj, 0);
|
||||
flags = lodDim.getFlags(detailLevel, xAdj, zAdj, 0);
|
||||
|
||||
adjData.get(lodDirection)[0] = DataPointUtil.EMPTY_DATA;
|
||||
adjData.get(lodDirection)[0] = 0;
|
||||
adjFlags.get(lodDirection)[0] = 0;
|
||||
|
||||
if ((isThisPositionGoingToBeRendered(detailLevel, xAdj, zAdj, playerChunkPos, vanillaRenderedChunks, gameChunkRenderDistance) || (posNotInPlayerChunk && adjPosInPlayerChunk))
|
||||
&& !DataPointUtil.isVoid(data))
|
||||
&& DataPointUtil.doesItExist(flags) && !DataPointUtil.isVoid(flags))
|
||||
{
|
||||
adjShadeDisabled[Box.DIRECTION_INDEX.get(lodDirection)] = DataPointUtil.getAlpha(data) < 255;
|
||||
adjShadeDisabled[VertexOptimizer.DIRECTION_INDEX.get(lodDirection)] = DataPointUtil.getAlpha(data) < 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// We render every vertical lod present in this position
|
||||
// We only stop when we find a block that is void or non existing block
|
||||
long data;
|
||||
// We only stop when we find a block that is void or non-existing block
|
||||
int color;
|
||||
int data;
|
||||
byte flags;
|
||||
for (int verticalIndex = 0; verticalIndex < lodDim.getMaxVerticalData(detailLevel, posX, posZ); verticalIndex++)
|
||||
{
|
||||
|
||||
//we get the above block as adj UP
|
||||
if (verticalIndex > 0)
|
||||
{
|
||||
adjData.get(LodDirection.UP)[0] = lodDim.getData(detailLevel, posX, posZ, verticalIndex - 1);
|
||||
adjFlags.get(LodDirection.UP)[0] = lodDim.getFlags(detailLevel, posX, posZ, verticalIndex - 1);
|
||||
}
|
||||
else
|
||||
adjData.get(LodDirection.UP)[0] = DataPointUtil.EMPTY_DATA;
|
||||
|
||||
{
|
||||
adjData.get(LodDirection.UP)[0] = 0;
|
||||
adjFlags.get(LodDirection.UP)[0] = 0;
|
||||
}
|
||||
|
||||
//we get the below block as adj DOWN
|
||||
if (verticalIndex < lodDim.getMaxVerticalData(detailLevel, posX, posZ) - 1)
|
||||
{
|
||||
adjData.get(LodDirection.DOWN)[0] = lodDim.getData(detailLevel, posX, posZ, verticalIndex + 1);
|
||||
adjFlags.get(LodDirection.DOWN)[0] = lodDim.getFlags(detailLevel, posX, posZ, verticalIndex + 1);
|
||||
}
|
||||
else
|
||||
adjData.get(LodDirection.DOWN)[0] = DataPointUtil.EMPTY_DATA;
|
||||
{
|
||||
adjData.get(LodDirection.DOWN)[0] = 0;
|
||||
adjFlags.get(LodDirection.DOWN)[0] = 0;
|
||||
}
|
||||
|
||||
//We extract the data to render
|
||||
color = lodDim.getColor(detailLevel, posX, posZ, verticalIndex);
|
||||
data = lodDim.getData(detailLevel, posX, posZ, verticalIndex);
|
||||
flags = lodDim.getFlags(detailLevel, posX, posZ, verticalIndex);
|
||||
|
||||
//If the data is not renderable (Void or non existing) we stop since there is no data left in this position
|
||||
if (DataPointUtil.isVoid(data) || !DataPointUtil.doesItExist(data))
|
||||
//If the data is not renderable (Void or non-existing) we stop since there is no data left in this position
|
||||
if (!DataPointUtil.doesItExist(flags) || DataPointUtil.isVoid(flags))
|
||||
break;
|
||||
|
||||
//We send the call to create the vertices
|
||||
CONFIG.client().graphics().advancedGraphics().getLodTemplate().template.addLodToBuffer(currentBuffers[bufferIndex], playerBlockPosRounded, data, adjData,
|
||||
detailLevel, posX, posZ, box, renderer.previousDebugMode, adjShadeDisabled);
|
||||
CONFIG.client().graphics().advancedGraphics().getLodTemplate().template.addLodToBuffer(currentBuffers[bufferIndex], playerBlockPosRounded, color, data, flags, adjData, adjFlags,
|
||||
detailLevel, posX, posZ, vertexOptimizer, renderer.previousDebugMode, adjShadeDisabled);
|
||||
}
|
||||
|
||||
} // for pos to in list to render
|
||||
// the thread executed successfully
|
||||
return true;
|
||||
};
|
||||
|
||||
nodeToRenderThreads.add(dataToRenderThread);
|
||||
|
||||
}
|
||||
} // region z
|
||||
} // region z
|
||||
@@ -455,12 +488,12 @@ public class LodBufferBuilderFactory
|
||||
}
|
||||
finally
|
||||
{
|
||||
// clean up any potentially open resources
|
||||
if (buildableBuffers != null)
|
||||
closeBuffers(fullRegen, lodDim);
|
||||
|
||||
try
|
||||
{
|
||||
// clean up any potentially open resources
|
||||
if (buildableBuffers != null)
|
||||
closeBuffers(fullRegen, lodDim);
|
||||
|
||||
// upload the new buffers
|
||||
uploadBuffers(fullRegen, lodDim);
|
||||
}
|
||||
@@ -520,108 +553,120 @@ public class LodBufferBuilderFactory
|
||||
*/
|
||||
public void setupBuffers(LodDimension lodDimension)
|
||||
{
|
||||
bufferLock.lock();
|
||||
int numbRegionsWide = lodDimension.getWidth();
|
||||
long regionMemoryRequired;
|
||||
int numberOfBuffers;
|
||||
|
||||
GLProxy glProxy = GLProxy.getInstance();
|
||||
GLProxyContext oldContext = glProxy.getGlContext();
|
||||
glProxy.setGlContext(GLProxyContext.LOD_BUILDER);
|
||||
|
||||
|
||||
previousRegionWidth = numbRegionsWide;
|
||||
numberOfBuffersPerRegion = new int[numbRegionsWide][numbRegionsWide];
|
||||
buildableBuffers = new LodBufferBuilder[numbRegionsWide][numbRegionsWide][];
|
||||
|
||||
buildableVbos = new LodVertexBuffer[numbRegionsWide][numbRegionsWide][];
|
||||
drawableVbos = new LodVertexBuffer[numbRegionsWide][numbRegionsWide][];
|
||||
|
||||
if (glProxy.bufferStorageSupported)
|
||||
try
|
||||
{
|
||||
buildableStorageBufferIds = new int[numbRegionsWide][numbRegionsWide][];
|
||||
drawableStorageBufferIds = new int[numbRegionsWide][numbRegionsWide][];
|
||||
}
|
||||
|
||||
for (int x = 0; x < numbRegionsWide; x++)
|
||||
{
|
||||
for (int z = 0; z < numbRegionsWide; z++)
|
||||
bufferLock.lock();
|
||||
|
||||
int numbRegionsWide = lodDimension.getWidth();
|
||||
long regionMemoryRequired;
|
||||
int numberOfBuffers;
|
||||
|
||||
GLProxy glProxy = GLProxy.getInstance();
|
||||
GLProxyContext oldContext = glProxy.getGlContext();
|
||||
glProxy.setGlContext(GLProxyContext.LOD_BUILDER);
|
||||
|
||||
|
||||
previousRegionWidth = numbRegionsWide;
|
||||
numberOfBuffersPerRegion = new int[numbRegionsWide][numbRegionsWide];
|
||||
buildableBuffers = new LodBufferBuilder[numbRegionsWide][numbRegionsWide][];
|
||||
|
||||
buildableVbos = new LodVertexBuffer[numbRegionsWide][numbRegionsWide][];
|
||||
drawableVbos = new LodVertexBuffer[numbRegionsWide][numbRegionsWide][];
|
||||
|
||||
if (glProxy.bufferStorageSupported)
|
||||
{
|
||||
regionMemoryRequired = DEFAULT_MEMORY_ALLOCATION;
|
||||
|
||||
// if the memory required is greater than the max buffer
|
||||
// capacity, divide the memory across multiple buffers
|
||||
if (regionMemoryRequired > LodUtil.MAX_ALLOCATABLE_DIRECT_MEMORY)
|
||||
buildableStorageBufferIds = new int[numbRegionsWide][numbRegionsWide][];
|
||||
drawableStorageBufferIds = new int[numbRegionsWide][numbRegionsWide][];
|
||||
}
|
||||
|
||||
for (int x = 0; x < numbRegionsWide; x++)
|
||||
{
|
||||
for (int z = 0; z < numbRegionsWide; z++)
|
||||
{
|
||||
numberOfBuffers = (int) regionMemoryRequired / LodUtil.MAX_ALLOCATABLE_DIRECT_MEMORY + 1;
|
||||
regionMemoryRequired = DEFAULT_MEMORY_ALLOCATION;
|
||||
|
||||
// TODO shouldn't this be determined with regionMemoryRequired?
|
||||
// always allocating the max memory is a bit expensive isn't it?
|
||||
regionMemoryRequired = LodUtil.MAX_ALLOCATABLE_DIRECT_MEMORY;
|
||||
numberOfBuffersPerRegion[x][z] = numberOfBuffers;
|
||||
buildableBuffers[x][z] = new LodBufferBuilder[numberOfBuffers];
|
||||
buildableVbos[x][z] = new LodVertexBuffer[numberOfBuffers];
|
||||
drawableVbos[x][z] = new LodVertexBuffer[numberOfBuffers];
|
||||
|
||||
if (glProxy.bufferStorageSupported)
|
||||
// if the memory required is greater than the max buffer
|
||||
// capacity, divide the memory across multiple buffers
|
||||
if (regionMemoryRequired > LodUtil.MAX_ALLOCATABLE_DIRECT_MEMORY)
|
||||
{
|
||||
buildableStorageBufferIds[x][z] = new int[numberOfBuffers];
|
||||
drawableStorageBufferIds[x][z] = new int[numberOfBuffers];
|
||||
numberOfBuffers = (int) regionMemoryRequired / LodUtil.MAX_ALLOCATABLE_DIRECT_MEMORY + 1;
|
||||
|
||||
// TODO shouldn't this be determined with regionMemoryRequired?
|
||||
// always allocating the max memory is a bit expensive isn't it?
|
||||
regionMemoryRequired = LodUtil.MAX_ALLOCATABLE_DIRECT_MEMORY;
|
||||
numberOfBuffersPerRegion[x][z] = numberOfBuffers;
|
||||
buildableBuffers[x][z] = new LodBufferBuilder[numberOfBuffers];
|
||||
buildableVbos[x][z] = new LodVertexBuffer[numberOfBuffers];
|
||||
drawableVbos[x][z] = new LodVertexBuffer[numberOfBuffers];
|
||||
|
||||
if (glProxy.bufferStorageSupported)
|
||||
{
|
||||
buildableStorageBufferIds[x][z] = new int[numberOfBuffers];
|
||||
drawableStorageBufferIds[x][z] = new int[numberOfBuffers];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// we only need one buffer for this region
|
||||
numberOfBuffersPerRegion[x][z] = 1;
|
||||
buildableBuffers[x][z] = new LodBufferBuilder[1];
|
||||
buildableVbos[x][z] = new LodVertexBuffer[1];
|
||||
drawableVbos[x][z] = new LodVertexBuffer[1];
|
||||
|
||||
if (glProxy.bufferStorageSupported)
|
||||
else
|
||||
{
|
||||
buildableStorageBufferIds[x][z] = new int[1];
|
||||
drawableStorageBufferIds[x][z] = new int[1];
|
||||
// we only need one buffer for this region
|
||||
numberOfBuffersPerRegion[x][z] = 1;
|
||||
buildableBuffers[x][z] = new LodBufferBuilder[1];
|
||||
buildableVbos[x][z] = new LodVertexBuffer[1];
|
||||
drawableVbos[x][z] = new LodVertexBuffer[1];
|
||||
|
||||
if (glProxy.bufferStorageSupported)
|
||||
{
|
||||
buildableStorageBufferIds[x][z] = new int[1];
|
||||
drawableStorageBufferIds[x][z] = new int[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (int i = 0; i < numberOfBuffersPerRegion[x][z]; i++)
|
||||
{
|
||||
buildableBuffers[x][z][i] = new LodBufferBuilder((int) regionMemoryRequired);
|
||||
|
||||
buildableVbos[x][z][i] = new LodVertexBuffer();
|
||||
drawableVbos[x][z][i] = new LodVertexBuffer();
|
||||
|
||||
|
||||
// create the initial mapped buffers (system memory)
|
||||
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, buildableVbos[x][z][i].id);
|
||||
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, regionMemoryRequired, GL15.GL_DYNAMIC_DRAW);
|
||||
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
|
||||
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, drawableVbos[x][z][i].id);
|
||||
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, regionMemoryRequired, GL15.GL_DYNAMIC_DRAW);
|
||||
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
|
||||
|
||||
if (glProxy.bufferStorageSupported)
|
||||
for (int i = 0; i < numberOfBuffersPerRegion[x][z]; i++)
|
||||
{
|
||||
// create the buffer storage (GPU memory)
|
||||
buildableStorageBufferIds[x][z][i] = GL15.glGenBuffers();
|
||||
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, buildableStorageBufferIds[x][z][i]);
|
||||
GL45.glBufferStorage(GL15.GL_ARRAY_BUFFER, regionMemoryRequired, 0); // the 0 flag means to create the storage in the GPUs memory
|
||||
buildableBuffers[x][z][i] = new LodBufferBuilder((int) regionMemoryRequired);
|
||||
|
||||
buildableVbos[x][z][i] = new LodVertexBuffer();
|
||||
drawableVbos[x][z][i] = new LodVertexBuffer();
|
||||
|
||||
|
||||
// create the initial mapped buffers (system memory)
|
||||
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, buildableVbos[x][z][i].id);
|
||||
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, regionMemoryRequired, GL15.GL_STATIC_DRAW);
|
||||
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
|
||||
drawableStorageBufferIds[x][z][i] = GL15.glGenBuffers();
|
||||
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, drawableStorageBufferIds[x][z][i]);
|
||||
GL45.glBufferStorage(GL15.GL_ARRAY_BUFFER, regionMemoryRequired, 0);
|
||||
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, drawableVbos[x][z][i].id);
|
||||
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, regionMemoryRequired, GL15.GL_STATIC_DRAW);
|
||||
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
|
||||
|
||||
if (glProxy.bufferStorageSupported)
|
||||
{
|
||||
// create the buffer storage (GPU memory)
|
||||
buildableStorageBufferIds[x][z][i] = GL15.glGenBuffers();
|
||||
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, buildableStorageBufferIds[x][z][i]);
|
||||
GL45.glBufferStorage(GL15.GL_ARRAY_BUFFER, regionMemoryRequired, 0); // the 0 flag means to create the storage in the GPUs memory
|
||||
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
|
||||
drawableStorageBufferIds[x][z][i] = GL15.glGenBuffers();
|
||||
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, drawableStorageBufferIds[x][z][i]);
|
||||
GL45.glBufferStorage(GL15.GL_ARRAY_BUFFER, regionMemoryRequired, 0);
|
||||
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
glProxy.setGlContext(oldContext);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ClientApi.LOGGER.info("setupBuffers ran into trouble: " + e.getMessage(), e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
// this shouldn't normally happen, but just in case it sill prevent deadlock
|
||||
bufferLock.unlock();
|
||||
}
|
||||
|
||||
glProxy.setGlContext(oldContext);
|
||||
bufferLock.unlock();
|
||||
}
|
||||
|
||||
|
||||
@@ -634,85 +679,95 @@ public class LodBufferBuilderFactory
|
||||
*/
|
||||
public void destroyBuffers()
|
||||
{
|
||||
bufferLock.lock();
|
||||
|
||||
|
||||
// destroy the buffer storages if they aren't already
|
||||
if (buildableStorageBufferIds != null)
|
||||
try
|
||||
{
|
||||
for (int x = 0; x < buildableStorageBufferIds.length; x++)
|
||||
bufferLock.lock();
|
||||
|
||||
|
||||
// destroy the buffer storages if they aren't already
|
||||
if (buildableStorageBufferIds != null)
|
||||
{
|
||||
for (int z = 0; z < buildableStorageBufferIds.length; z++)
|
||||
for (int x = 0; x < buildableStorageBufferIds.length; x++)
|
||||
{
|
||||
for (int i = 0; i < buildableStorageBufferIds[x][z].length; i++)
|
||||
for (int z = 0; z < buildableStorageBufferIds.length; z++)
|
||||
{
|
||||
int buildableId = buildableStorageBufferIds[x][z][i];
|
||||
int drawableId = drawableStorageBufferIds[x][z][i];
|
||||
|
||||
// make sure the buffers are deleted in a openGL context
|
||||
GLProxy.getInstance().recordOpenGlCall(() ->
|
||||
for (int i = 0; i < buildableStorageBufferIds[x][z].length; i++)
|
||||
{
|
||||
GL15.glDeleteBuffers(buildableId);
|
||||
GL15.glDeleteBuffers(drawableId);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buildableStorageBufferIds = null;
|
||||
drawableStorageBufferIds = null;
|
||||
|
||||
|
||||
|
||||
|
||||
// destroy the VBOs if they aren't already
|
||||
if (buildableVbos != null)
|
||||
{
|
||||
for (int i = 0; i < buildableVbos.length; i++)
|
||||
{
|
||||
for (int j = 0; j < buildableVbos.length; j++)
|
||||
{
|
||||
for (int k = 0; k < buildableVbos[i][j].length; k++)
|
||||
{
|
||||
int buildableId;
|
||||
int drawableId;
|
||||
|
||||
// variables passed into a lambda expression
|
||||
// need to be effectively final, so we have
|
||||
// to use an else statement here
|
||||
if (buildableVbos[i][j][k] != null)
|
||||
buildableId = buildableVbos[i][j][k].id;
|
||||
else
|
||||
buildableId = 0;
|
||||
|
||||
if (drawableVbos[i][j][k] != null)
|
||||
drawableId = drawableVbos[i][j][k].id;
|
||||
else
|
||||
drawableId = 0;
|
||||
|
||||
|
||||
GLProxy.getInstance().recordOpenGlCall(() ->
|
||||
{
|
||||
if (buildableId != 0)
|
||||
int buildableId = buildableStorageBufferIds[x][z][i];
|
||||
int drawableId = drawableStorageBufferIds[x][z][i];
|
||||
|
||||
// make sure the buffers are deleted in a openGL context
|
||||
GLProxy.getInstance().recordOpenGlCall(() ->
|
||||
{
|
||||
GL15.glDeleteBuffers(buildableId);
|
||||
if (drawableId != 0)
|
||||
GL15.glDeleteBuffers(drawableId);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buildableStorageBufferIds = null;
|
||||
drawableStorageBufferIds = null;
|
||||
|
||||
|
||||
|
||||
|
||||
// destroy the VBOs if they aren't already
|
||||
if (buildableVbos != null)
|
||||
{
|
||||
for (int i = 0; i < buildableVbos.length; i++)
|
||||
{
|
||||
for (int j = 0; j < buildableVbos.length; j++)
|
||||
{
|
||||
for (int k = 0; k < buildableVbos[i][j].length; k++)
|
||||
{
|
||||
int buildableId;
|
||||
int drawableId;
|
||||
|
||||
// variables passed into a lambda expression
|
||||
// need to be effectively final, so we have
|
||||
// to use an else statement here
|
||||
if (buildableVbos[i][j][k] != null)
|
||||
buildableId = buildableVbos[i][j][k].id;
|
||||
else
|
||||
buildableId = 0;
|
||||
|
||||
if (drawableVbos[i][j][k] != null)
|
||||
drawableId = drawableVbos[i][j][k].id;
|
||||
else
|
||||
drawableId = 0;
|
||||
|
||||
|
||||
GLProxy.getInstance().recordOpenGlCall(() ->
|
||||
{
|
||||
if (buildableId != 0)
|
||||
GL15.glDeleteBuffers(buildableId);
|
||||
if (drawableId != 0)
|
||||
GL15.glDeleteBuffers(drawableId);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buildableVbos = null;
|
||||
drawableVbos = null;
|
||||
|
||||
|
||||
// these don't contain any OpenGL objects, so
|
||||
// they don't require any special clean-up
|
||||
buildableBuffers = null;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ClientApi.LOGGER.info("destroyBuffers ran into trouble: " + e.getMessage(), e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
// this shouldn't normally happen, but just in case it sill prevent deadlock
|
||||
bufferLock.unlock();
|
||||
}
|
||||
|
||||
buildableVbos = null;
|
||||
drawableVbos = null;
|
||||
|
||||
|
||||
// these don't contain any OpenGL objects, so
|
||||
// they don't require any special clean-up
|
||||
buildableBuffers = null;
|
||||
|
||||
bufferLock.unlock();
|
||||
}
|
||||
|
||||
/** Calls begin on each of the buildable BufferBuilders. */
|
||||
@@ -753,6 +808,7 @@ public class LodBufferBuilderFactory
|
||||
private void uploadBuffers(boolean fullRegen, LodDimension lodDim)
|
||||
{
|
||||
GLProxy glProxy = GLProxy.getInstance();
|
||||
long fence = 0;
|
||||
|
||||
try
|
||||
{
|
||||
@@ -761,15 +817,26 @@ public class LodBufferBuilderFactory
|
||||
glProxy.setGlContext(GLProxyContext.LOD_BUILDER);
|
||||
|
||||
// determine the upload method
|
||||
GpuUploadMethod uploadMethod = CONFIG.client().graphics().advancedGraphics().getGpuUploadMethod();
|
||||
GpuUploadMethod uploadMethod = CONFIG.client().advanced().buffers().getGpuUploadMethod();
|
||||
if (!glProxy.bufferStorageSupported && uploadMethod == GpuUploadMethod.BUFFER_STORAGE)
|
||||
{
|
||||
// if buffer storage isn't supported
|
||||
// default to SUB_DATA
|
||||
CONFIG.client().graphics().advancedGraphics().setGpuUploadMethod(GpuUploadMethod.SUB_DATA);
|
||||
CONFIG.client().advanced().buffers().setGpuUploadMethod(GpuUploadMethod.SUB_DATA);
|
||||
uploadMethod = GpuUploadMethod.SUB_DATA;
|
||||
}
|
||||
|
||||
// determine the upload timeout
|
||||
int uploadTimeoutInMS = CONFIG.client().advanced().buffers().getGpuUploadTimeoutInMilliseconds();
|
||||
|
||||
// James has no idea if this does anything helpful,
|
||||
// but in theory it should prevent OpenGL from drawing and
|
||||
// writing to a buffer at the same time.
|
||||
GL45.glMemoryBarrier(GL45.GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT);
|
||||
fence = GL45.glFenceSync(GL45.GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||
|
||||
|
||||
|
||||
// actually upload the buffers
|
||||
for (int x = 0; x < buildableVbos.length; x++)
|
||||
{
|
||||
@@ -780,16 +847,22 @@ public class LodBufferBuilderFactory
|
||||
for (int i = 0; i < buildableBuffers[x][z].length; i++)
|
||||
{
|
||||
ByteBuffer uploadBuffer = buildableBuffers[x][z][i].getCleanedByteBuffer();
|
||||
int storageBufferId = 0;
|
||||
if (buildableStorageBufferIds != null)
|
||||
storageBufferId = buildableStorageBufferIds[x][z][i];
|
||||
|
||||
vboUpload(buildableVbos[x][z][i], storageBufferId, uploadBuffer, true, uploadMethod);
|
||||
vboUpload(x,z,i, uploadBuffer, true, uploadMethod);
|
||||
lodDim.setRegenRegionBufferByArrayIndex(x, z, false);
|
||||
|
||||
|
||||
// upload buffers over an extended period of time
|
||||
// to hopefully prevent stuttering.
|
||||
if (uploadTimeoutInMS != 0)
|
||||
Thread.sleep(uploadTimeoutInMS);
|
||||
GL15.glFinish();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// make sure all of the uploads finish before continuing
|
||||
GL45.glClientWaitSync(fence, GL45.GL_SYNC_FLUSH_COMMANDS_BIT, 5L * 1000000000); // wait up to 5 seconds
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -800,7 +873,9 @@ public class LodBufferBuilderFactory
|
||||
finally
|
||||
{
|
||||
GL15.glFinish();
|
||||
|
||||
if (fence != 0)
|
||||
GL45.glDeleteSync(fence);
|
||||
|
||||
// close the context so it can be re-used later.
|
||||
// I'm guessing we can't just leave it because the executor service
|
||||
// does something that invalidates the OpenGL context.
|
||||
@@ -809,9 +884,19 @@ public class LodBufferBuilderFactory
|
||||
}
|
||||
|
||||
/** Uploads the uploadBuffer so the GPU can use it. */
|
||||
private void vboUpload(LodVertexBuffer vbo, int storageBufferId, ByteBuffer uploadBuffer,
|
||||
private void vboUpload(int xIndex, int zIndex, int iIndex, ByteBuffer uploadBuffer,
|
||||
boolean allowBufferExpansion, GpuUploadMethod uploadMethod)
|
||||
{
|
||||
// get the vbos, buffers, ids, etc.
|
||||
int storageBufferId = 0;
|
||||
if (buildableStorageBufferIds != null)
|
||||
storageBufferId = buildableStorageBufferIds[xIndex][zIndex][iIndex];
|
||||
|
||||
LodVertexBuffer vbo = buildableVbos[xIndex][zIndex][iIndex];
|
||||
|
||||
|
||||
|
||||
|
||||
// this shouldn't happen, but just to be safe
|
||||
if (vbo.id != -1 && GLProxy.getInstance().getGlContext() == GLProxyContext.LOD_BUILDER)
|
||||
{
|
||||
@@ -855,7 +940,7 @@ public class LodBufferBuilderFactory
|
||||
// recursively try to upload into the newly created buffer storage
|
||||
// but don't recurse again if that fails
|
||||
// (we don't want an infinitely expanding buffer!)
|
||||
vboUpload(vbo, storageBufferId, uploadBuffer, false, uploadMethod);
|
||||
vboUpload(xIndex,zIndex,iIndex, uploadBuffer, false, uploadMethod);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -868,11 +953,6 @@ public class LodBufferBuilderFactory
|
||||
// (uploading into GPU memory directly can only be done
|
||||
// through the glCopyBufferSubData/glCopyNamed... methods)
|
||||
GL45.glCopyNamedBufferSubData(vbo.id, storageBufferId, 0, 0, uploadBuffer.capacity());
|
||||
|
||||
// alternative way that doesn't require GL45
|
||||
// GL15.glBindBuffer(GL45.GL_COPY_WRITE_BUFFER, storageBufferId);
|
||||
// GL45.glCopyBufferSubData(GL15.GL_ARRAY_BUFFER, GL45.GL_COPY_WRITE_BUFFER, 0, 0, uploadBuffer.capacity());
|
||||
// GL15.glBindBuffer(GL45.GL_COPY_WRITE_BUFFER, 0);
|
||||
}
|
||||
}
|
||||
else if (uploadMethod == GpuUploadMethod.BUFFER_MAPPING)
|
||||
@@ -888,14 +968,14 @@ public class LodBufferBuilderFactory
|
||||
|
||||
// map buffer range is better since it can be explicitly unsynchronized
|
||||
if (GLProxy.getInstance().mapBufferRangeSupported)
|
||||
vboBuffer = GL30.glMapBufferRange(GL30.GL_ARRAY_BUFFER, 0, uploadBuffer.capacity(), GL30.GL_MAP_WRITE_BIT | GL30.GL_MAP_UNSYNCHRONIZED_BIT);
|
||||
vboBuffer = GL30.glMapBufferRange(GL30.GL_ARRAY_BUFFER, 0, uploadBuffer.capacity(), GL30.GL_MAP_WRITE_BIT | GL30.GL_MAP_UNSYNCHRONIZED_BIT | GL30.GL_MAP_INVALIDATE_BUFFER_BIT);
|
||||
else
|
||||
vboBuffer = GL15.glMapBuffer(GL30.GL_ARRAY_BUFFER, uploadBuffer.capacity());
|
||||
|
||||
|
||||
if (vboBuffer == null)
|
||||
{
|
||||
GL15.glBufferData(GL45.GL_ARRAY_BUFFER, (int) (uploadBuffer.capacity() * BUFFER_EXPANSION_MULTIPLIER), GL15.GL_DYNAMIC_DRAW);
|
||||
GL15.glBufferData(GL45.GL_ARRAY_BUFFER, (int) (uploadBuffer.capacity() * BUFFER_EXPANSION_MULTIPLIER), GL15.GL_STATIC_DRAW);
|
||||
GL15.glBufferSubData(GL15.GL_ARRAY_BUFFER, 0, uploadBuffer);
|
||||
}
|
||||
else
|
||||
@@ -909,7 +989,8 @@ public class LodBufferBuilderFactory
|
||||
// high stutter, low GPU usage
|
||||
// But simplest/most compatible
|
||||
|
||||
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, uploadBuffer, GL15.GL_DYNAMIC_DRAW);
|
||||
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, uploadBuffer.capacity(), GL15.GL_STATIC_DRAW);
|
||||
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, uploadBuffer, GL15.GL_STATIC_DRAW);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -919,7 +1000,7 @@ public class LodBufferBuilderFactory
|
||||
long size = GL15.glGetBufferParameteri(GL15.GL_ARRAY_BUFFER, GL15.GL_BUFFER_SIZE);
|
||||
if (size < uploadBuffer.capacity() * BUFFER_EXPANSION_MULTIPLIER)
|
||||
{
|
||||
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, (int) (uploadBuffer.capacity() * BUFFER_EXPANSION_MULTIPLIER), GL15.GL_DYNAMIC_DRAW);
|
||||
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, (int) (uploadBuffer.capacity() * BUFFER_EXPANSION_MULTIPLIER), GL15.GL_STATIC_DRAW);
|
||||
}
|
||||
GL15.glBufferSubData(GL15.GL_ARRAY_BUFFER, 0, uploadBuffer);
|
||||
}
|
||||
@@ -947,19 +1028,30 @@ public class LodBufferBuilderFactory
|
||||
// since this is called on the main render thread
|
||||
if (bufferLock.tryLock())
|
||||
{
|
||||
LodVertexBuffer[][][] tmpVbo = drawableVbos;
|
||||
drawableVbos = buildableVbos;
|
||||
buildableVbos = tmpVbo;
|
||||
|
||||
int[][][] tmpStorage = drawableStorageBufferIds;
|
||||
drawableStorageBufferIds = buildableStorageBufferIds;
|
||||
buildableStorageBufferIds = tmpStorage;
|
||||
|
||||
drawableCenterChunkPos = buildableCenterChunkPos;
|
||||
|
||||
// the vbos have been swapped
|
||||
switchVbos = false;
|
||||
bufferLock.unlock();
|
||||
try
|
||||
{
|
||||
LodVertexBuffer[][][] tmpVbo = drawableVbos;
|
||||
drawableVbos = buildableVbos;
|
||||
buildableVbos = tmpVbo;
|
||||
|
||||
int[][][] tmpStorage = drawableStorageBufferIds;
|
||||
drawableStorageBufferIds = buildableStorageBufferIds;
|
||||
buildableStorageBufferIds = tmpStorage;
|
||||
|
||||
drawableCenterChunkPos = buildableCenterChunkPos;
|
||||
|
||||
// the vbos have been swapped
|
||||
switchVbos = false;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// this shouldn't normally happen, but just in case it sill prevent deadlock
|
||||
ClientApi.LOGGER.info("getVertexBuffers ran into trouble: " + e.getMessage(), e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
bufferLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
return new VertexBuffersAndOffset(drawableVbos, drawableStorageBufferIds, drawableCenterChunkPos);
|
||||
|
||||
+3
-3
@@ -23,7 +23,7 @@ import java.util.Map;
|
||||
|
||||
import com.seibel.lod.core.enums.LodDirection;
|
||||
import com.seibel.lod.core.enums.rendering.DebugMode;
|
||||
import com.seibel.lod.core.objects.Box;
|
||||
import com.seibel.lod.core.objects.VertexOptimizer;
|
||||
import com.seibel.lod.core.objects.opengl.LodBufferBuilder;
|
||||
import com.seibel.lod.core.util.ColorUtil;
|
||||
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
|
||||
@@ -37,8 +37,8 @@ import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
|
||||
public abstract class AbstractLodTemplate
|
||||
{
|
||||
/** Uploads the given LOD to the buffer. */
|
||||
public abstract void addLodToBuffer(LodBufferBuilder buffer, AbstractBlockPosWrapper bufferCenterBlockPos, long data, Map<LodDirection, long[]> adjData,
|
||||
byte detailLevel, int posX, int posZ, Box box, DebugMode debugging, boolean[] adjShadeDisabled);
|
||||
public abstract void addLodToBuffer(LodBufferBuilder buffer, AbstractBlockPosWrapper bufferCenterBlockPos, int color, int data, byte flags, Map<LodDirection, int[]> adjData, Map<LodDirection, byte[]> adjFlags,
|
||||
byte detailLevel, int posX, int posZ, VertexOptimizer vertexOptimizer, DebugMode debugging, boolean[] adjShadeDisabled);
|
||||
|
||||
/** add the given position and color to the buffer */
|
||||
protected void addPosAndColor(LodBufferBuilder buffer,
|
||||
|
||||
+30
-30
@@ -23,7 +23,7 @@ import java.util.Map;
|
||||
|
||||
import com.seibel.lod.core.enums.LodDirection;
|
||||
import com.seibel.lod.core.enums.rendering.DebugMode;
|
||||
import com.seibel.lod.core.objects.Box;
|
||||
import com.seibel.lod.core.objects.VertexOptimizer;
|
||||
import com.seibel.lod.core.objects.opengl.LodBufferBuilder;
|
||||
import com.seibel.lod.core.util.ColorUtil;
|
||||
import com.seibel.lod.core.util.DataPointUtil;
|
||||
@@ -44,43 +44,43 @@ public class CubicLodTemplate extends AbstractLodTemplate
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addLodToBuffer(LodBufferBuilder buffer, AbstractBlockPosWrapper bufferCenterBlockPos, long data, Map<LodDirection, long[]> adjData,
|
||||
byte detailLevel, int posX, int posZ, Box box, DebugMode debugging, boolean[] adjShadeDisabled)
|
||||
public void addLodToBuffer(LodBufferBuilder buffer, AbstractBlockPosWrapper bufferCenterBlockPos,
|
||||
int color, int data, byte flags,
|
||||
Map<LodDirection, int[]> adjData, Map<LodDirection, byte[]> adjFlags,
|
||||
byte detailLevel, int posX, int posZ, VertexOptimizer vertexOptimizer, DebugMode debugging, boolean[] adjShadeDisabled)
|
||||
{
|
||||
if (box == null)
|
||||
if (vertexOptimizer == null)
|
||||
return;
|
||||
|
||||
// equivalent to 2^detailLevel
|
||||
int blockWidth = 1 << detailLevel;
|
||||
|
||||
int color;
|
||||
if (debugging != DebugMode.OFF)
|
||||
color = LodUtil.DEBUG_DETAIL_LEVEL_COLORS[detailLevel].getRGB();
|
||||
else
|
||||
color = DataPointUtil.getColor(data);
|
||||
|
||||
|
||||
generateBoundingBox(
|
||||
box,
|
||||
vertexOptimizer,
|
||||
DataPointUtil.getHeight(data),
|
||||
DataPointUtil.getDepth(data),
|
||||
blockWidth,
|
||||
posX * blockWidth, 0, posZ * blockWidth, // x, y, z offset
|
||||
bufferCenterBlockPos,
|
||||
adjData,
|
||||
adjFlags,
|
||||
color,
|
||||
DataPointUtil.getLightSkyAlt(data),
|
||||
DataPointUtil.getLightSkyAlt(data, flags),
|
||||
DataPointUtil.getLightBlock(data),
|
||||
adjShadeDisabled);
|
||||
|
||||
addBoundingBoxToBuffer(buffer, box);
|
||||
addBoundingBoxToBuffer(buffer, vertexOptimizer);
|
||||
}
|
||||
|
||||
private void generateBoundingBox(Box box,
|
||||
private void generateBoundingBox(VertexOptimizer vertexOptimizer,
|
||||
int height, int depth, int width,
|
||||
double xOffset, double yOffset, double zOffset,
|
||||
AbstractBlockPosWrapper bufferCenterBlockPos,
|
||||
Map<LodDirection, long[]> adjData,
|
||||
Map<LodDirection, int[]> adjData,
|
||||
Map<LodDirection, byte[]> adjFlags,
|
||||
int color,
|
||||
int skyLight,
|
||||
int blockLight,
|
||||
@@ -100,38 +100,38 @@ public class CubicLodTemplate extends AbstractLodTemplate
|
||||
// which only uses floats
|
||||
double x = -bufferCenterBlockPos.getX();
|
||||
double z = -bufferCenterBlockPos.getZ();
|
||||
box.reset();
|
||||
box.setColor(color, adjShadeDisabled);
|
||||
box.setLights(skyLight, blockLight);
|
||||
box.setWidth(width, height - depth, width);
|
||||
box.setOffset((int) (xOffset + x), (int) (depth + yOffset), (int) (zOffset + z));
|
||||
box.setUpCulling(32, bufferCenterBlockPos);
|
||||
box.setAdjData(adjData);
|
||||
vertexOptimizer.reset();
|
||||
vertexOptimizer.setColor(color, adjShadeDisabled);
|
||||
vertexOptimizer.setLights(skyLight, blockLight);
|
||||
vertexOptimizer.setWidth(width, height - depth, width);
|
||||
vertexOptimizer.setOffset((int) (xOffset + x), (int) (depth + yOffset), (int) (zOffset + z));
|
||||
vertexOptimizer.setUpCulling(32, bufferCenterBlockPos);
|
||||
vertexOptimizer.setAdjData(adjData, adjFlags);
|
||||
}
|
||||
|
||||
private void addBoundingBoxToBuffer(LodBufferBuilder buffer, Box box)
|
||||
private void addBoundingBoxToBuffer(LodBufferBuilder buffer, VertexOptimizer vertexOptimizer)
|
||||
{
|
||||
int color;
|
||||
int skyLight;
|
||||
int blockLight;
|
||||
for (LodDirection lodDirection : Box.DIRECTIONS)
|
||||
for (LodDirection lodDirection : VertexOptimizer.DIRECTIONS)
|
||||
{
|
||||
if(box.isCulled(lodDirection))
|
||||
if(vertexOptimizer.isCulled(lodDirection))
|
||||
continue;
|
||||
|
||||
int verticalFaceIndex = 0;
|
||||
while (box.shouldRenderFace(lodDirection, verticalFaceIndex))
|
||||
while (vertexOptimizer.shouldRenderFace(lodDirection, verticalFaceIndex))
|
||||
{
|
||||
for (int vertexIndex = 0; vertexIndex < 6; vertexIndex++)
|
||||
{
|
||||
color = box.getColor(lodDirection);
|
||||
skyLight = box.getSkyLight(lodDirection, verticalFaceIndex);
|
||||
blockLight = box.getBlockLight();
|
||||
color = vertexOptimizer.getColor(lodDirection);
|
||||
skyLight = vertexOptimizer.getSkyLight(lodDirection, verticalFaceIndex);
|
||||
blockLight = vertexOptimizer.getBlockLight();
|
||||
color = ColorUtil.applyLightValue(color, skyLight, blockLight);
|
||||
addPosAndColor(buffer,
|
||||
box.getX(lodDirection, vertexIndex),
|
||||
box.getY(lodDirection, vertexIndex, verticalFaceIndex),
|
||||
box.getZ(lodDirection, vertexIndex),
|
||||
vertexOptimizer.getX(lodDirection, vertexIndex),
|
||||
vertexOptimizer.getY(lodDirection, vertexIndex, verticalFaceIndex) + DataPointUtil.VERTICAL_OFFSET,
|
||||
vertexOptimizer.getZ(lodDirection, vertexIndex),
|
||||
color);
|
||||
}
|
||||
verticalFaceIndex++;
|
||||
|
||||
+4
-3
@@ -24,7 +24,7 @@ import java.util.Map;
|
||||
import com.seibel.lod.core.api.ClientApi;
|
||||
import com.seibel.lod.core.enums.LodDirection;
|
||||
import com.seibel.lod.core.enums.rendering.DebugMode;
|
||||
import com.seibel.lod.core.objects.Box;
|
||||
import com.seibel.lod.core.objects.VertexOptimizer;
|
||||
import com.seibel.lod.core.objects.opengl.LodBufferBuilder;
|
||||
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
|
||||
|
||||
@@ -39,8 +39,9 @@ import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
|
||||
public class DynamicLodTemplate extends AbstractLodTemplate
|
||||
{
|
||||
@Override
|
||||
public void addLodToBuffer(LodBufferBuilder buffer, AbstractBlockPosWrapper bufferCenterBlockPos, long data, Map<LodDirection, long[]> adjData,
|
||||
byte detailLevel, int posX, int posZ, Box box, DebugMode debugging, boolean[] adjShadeDisabled)
|
||||
public void addLodToBuffer(LodBufferBuilder buffer, AbstractBlockPosWrapper bufferCenterBlockPos, int color, int data, byte flags,
|
||||
Map<LodDirection, int[]> adjData, Map<LodDirection, byte[]> adjFlags,
|
||||
byte detailLevel, int posX, int posZ, VertexOptimizer vertexOptimizer, DebugMode debugging, boolean[] adjShadeDisabled)
|
||||
{
|
||||
ClientApi.LOGGER.error(DynamicLodTemplate.class.getSimpleName() + " is not implemented!");
|
||||
}
|
||||
|
||||
+4
-3
@@ -24,7 +24,7 @@ import java.util.Map;
|
||||
import com.seibel.lod.core.api.ClientApi;
|
||||
import com.seibel.lod.core.enums.LodDirection;
|
||||
import com.seibel.lod.core.enums.rendering.DebugMode;
|
||||
import com.seibel.lod.core.objects.Box;
|
||||
import com.seibel.lod.core.objects.VertexOptimizer;
|
||||
import com.seibel.lod.core.objects.opengl.LodBufferBuilder;
|
||||
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
|
||||
|
||||
@@ -37,8 +37,9 @@ import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
|
||||
public class TriangularLodTemplate extends AbstractLodTemplate
|
||||
{
|
||||
@Override
|
||||
public void addLodToBuffer(LodBufferBuilder buffer, AbstractBlockPosWrapper bufferCenterBlockPos, long data, Map<LodDirection, long[]> adjData,
|
||||
byte detailLevel, int posX, int posZ, Box box, DebugMode debugging, boolean[] adjShadeDisabled)
|
||||
public void addLodToBuffer(LodBufferBuilder buffer, AbstractBlockPosWrapper bufferCenterBlockPos, int color, int data, byte flags,
|
||||
Map<LodDirection, int[]> adjData, Map<LodDirection, byte[]> adjFlags,
|
||||
byte detailLevel, int posX, int posZ, VertexOptimizer vertexOptimizer, DebugMode debugging, boolean[] adjShadeDisabled)
|
||||
{
|
||||
ClientApi.LOGGER.error(DynamicLodTemplate.class.getSimpleName() + " is not implemented!");
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
|
||||
* @author James Seibel
|
||||
* @version 10-22-2021
|
||||
*/
|
||||
public class LodBuilder
|
||||
@SuppressWarnings("GrazieInspection") public class LodBuilder
|
||||
{
|
||||
private static final IMinecraftWrapper MC = SingletonHandler.get(IMinecraftWrapper.class);
|
||||
private static final IBlockColorSingletonWrapper BLOCK_COLOR = SingletonHandler.get(IBlockColorSingletonWrapper.class);
|
||||
@@ -109,6 +109,7 @@ public class LodBuilder
|
||||
|
||||
Thread thread = new Thread(() ->
|
||||
{
|
||||
//noinspection GrazieInspection
|
||||
try
|
||||
{
|
||||
// we need a loaded client world in order to
|
||||
@@ -194,105 +195,107 @@ public class LodBuilder
|
||||
startX = detail.startX[i];
|
||||
startZ = detail.startZ[i];
|
||||
|
||||
long[] data;
|
||||
long[] dataToMergeVertical = createVerticalDataToMerge(detail, chunk, config, startX, startZ);
|
||||
data = DataPointUtil.mergeMultiData(dataToMergeVertical, DataPointUtil.worldHeight / 2 + 1, DetailDistanceUtil.getMaxVerticalData(detailLevel));
|
||||
// creates a vertical DataPoint
|
||||
// equivalent to 2^detailLevel
|
||||
int size = 1 << detail.detailLevel;
|
||||
|
||||
int[] dataToMergeColor = ThreadMapUtil.getBuilderVerticalArrayColor(detail.detailLevel);
|
||||
int[] dataToMergeData = ThreadMapUtil.getBuilderVerticalArrayData(detail.detailLevel);
|
||||
byte[] dataToMergeFlags = ThreadMapUtil.getBuilderVerticalArrayFlags(detail.detailLevel);
|
||||
int verticalData = DataPointUtil.WORLD_HEIGHT / 2 + 1;
|
||||
|
||||
AbstractChunkPosWrapper chunkPos = chunk.getPos();
|
||||
int height;
|
||||
int depth;
|
||||
int color;
|
||||
int light;
|
||||
int lightSky;
|
||||
int lightBlock;
|
||||
byte generation = config.distanceGenerationMode.complexity;
|
||||
|
||||
int xRel;
|
||||
int zRel;
|
||||
int xAbs;
|
||||
int yAbs;
|
||||
int zAbs;
|
||||
boolean hasCeiling = MC.getWrappedClientWorld().getDimensionType().hasCeiling();
|
||||
boolean hasSkyLight = MC.getWrappedClientWorld().getDimensionType().hasSkyLight();
|
||||
boolean isDefault;
|
||||
AbstractBlockPosWrapper blockPos = FACTORY.createBlockPos();
|
||||
int index;
|
||||
|
||||
for (index = 0; index < size * size; index++)
|
||||
{
|
||||
xRel = startX + index % size;
|
||||
zRel = startZ + index / size;
|
||||
xAbs = chunkPos.getMinBlockX() + xRel;
|
||||
zAbs = chunkPos.getMinBlockZ() + zRel;
|
||||
|
||||
//Calculate the height of the lod
|
||||
yAbs = DataPointUtil.WORLD_HEIGHT - DataPointUtil.VERTICAL_OFFSET + 1;
|
||||
int count = 0;
|
||||
boolean topBlock = true;
|
||||
while (yAbs > 0)
|
||||
{
|
||||
height = determineHeightPointFrom(chunk, config, xRel, yAbs, zRel, blockPos);
|
||||
|
||||
// If the lod is at the default height, it must be void data
|
||||
if (height == DEFAULT_HEIGHT)
|
||||
{
|
||||
if (topBlock)
|
||||
dataToMergeFlags[index * verticalData] = DataPointUtil.createVoidDataPoint(generation);
|
||||
break;
|
||||
}
|
||||
|
||||
yAbs = height - 1;
|
||||
// We search light on above air block
|
||||
depth = determineBottomPointFrom(chunk, config, xRel, yAbs, zRel, blockPos);
|
||||
if (hasCeiling && topBlock)
|
||||
{
|
||||
yAbs = depth;
|
||||
blockPos.set(xAbs, yAbs, zAbs);
|
||||
light = getLightValue(chunk, blockPos, true, hasSkyLight, true);
|
||||
color = generateLodColor(chunk, config, xAbs, yAbs, zAbs, blockPos);
|
||||
blockPos.set(xAbs, yAbs - 1, zAbs);
|
||||
}
|
||||
else
|
||||
{
|
||||
blockPos.set(xAbs, yAbs, zAbs);
|
||||
light = getLightValue(chunk, blockPos, hasCeiling, hasSkyLight, topBlock);
|
||||
color = generateLodColor(chunk, config, xRel, yAbs, zRel, blockPos);
|
||||
blockPos.set(xAbs, yAbs + 1, zAbs);
|
||||
}
|
||||
lightBlock = light & 0b1111;
|
||||
lightSky = (light >> 4) & 0b1111;
|
||||
isDefault = ((light >> 8)) == 1;
|
||||
DataPointUtil.createDataPoint(height - DataPointUtil.VERTICAL_OFFSET, depth - DataPointUtil.VERTICAL_OFFSET, color, lightSky, lightBlock, generation, isDefault);
|
||||
dataToMergeColor[index * verticalData + count] = ThreadMapUtil.dataPointColor;
|
||||
dataToMergeData[index * verticalData + count] = ThreadMapUtil.dataPointData;
|
||||
dataToMergeFlags[index * verticalData + count] = ThreadMapUtil.dataPointFlags;
|
||||
|
||||
topBlock = false;
|
||||
yAbs = depth - 1;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DataPointUtil.mergeMultiData(dataToMergeColor, dataToMergeData, dataToMergeFlags, DataPointUtil.WORLD_HEIGHT / 2 + 1, DetailDistanceUtil.getMaxVerticalData(detailLevel));
|
||||
int[] mergedColor = ThreadMapUtil.getRawVerticalDataArrayColor();
|
||||
int[] mergedData = ThreadMapUtil.getRawVerticalDataArrayData();
|
||||
byte[] mergedFlags = ThreadMapUtil.getRawVerticalDataArrayFlags();
|
||||
|
||||
//lodDim.clear(detailLevel, posX, posZ);
|
||||
if (data != null && data.length != 0)
|
||||
if (mergedFlags.length != 0)
|
||||
{
|
||||
posX = LevelPosUtil.convert((byte) 0, chunk.getPos().getX() * 16 + startX, detail.detailLevel);
|
||||
posZ = LevelPosUtil.convert((byte) 0, chunk.getPos().getZ() * 16 + startZ, detail.detailLevel);
|
||||
lodDim.addVerticalData(detailLevel, posX, posZ, data, false);
|
||||
lodDim.addVerticalData(detailLevel, posX, posZ, mergedColor, mergedData, mergedFlags, false);
|
||||
}
|
||||
}
|
||||
lodDim.updateData(LodUtil.CHUNK_DETAIL_LEVEL, chunk.getPos().getX(), chunk.getPos().getZ());
|
||||
}
|
||||
|
||||
/** creates a vertical DataPoint */
|
||||
private long[] createVerticalDataToMerge(HorizontalResolution detail, IChunkWrapper chunk, LodBuilderConfig config, int startX, int startZ)
|
||||
{
|
||||
// equivalent to 2^detailLevel
|
||||
int size = 1 << detail.detailLevel;
|
||||
|
||||
long[] dataToMerge = ThreadMapUtil.getBuilderVerticalArray(detail.detailLevel);
|
||||
int verticalData = DataPointUtil.worldHeight / 2 + 1;
|
||||
|
||||
AbstractChunkPosWrapper chunkPos = chunk.getPos();
|
||||
int height;
|
||||
int depth;
|
||||
int color;
|
||||
int light;
|
||||
int lightSky;
|
||||
int lightBlock;
|
||||
int generation = config.distanceGenerationMode.complexity;
|
||||
|
||||
int xRel;
|
||||
int zRel;
|
||||
int xAbs;
|
||||
int yAbs;
|
||||
int zAbs;
|
||||
boolean hasCeiling = MC.getWrappedClientWorld().getDimensionType().hasCeiling();
|
||||
boolean hasSkyLight = MC.getWrappedClientWorld().getDimensionType().hasSkyLight();
|
||||
boolean isDefault;
|
||||
AbstractBlockPosWrapper blockPos = FACTORY.createBlockPos();
|
||||
int index;
|
||||
|
||||
for (index = 0; index < size * size; index++)
|
||||
{
|
||||
xRel = startX + index % size;
|
||||
zRel = startZ + index / size;
|
||||
xAbs = chunkPos.getMinBlockX() + xRel;
|
||||
zAbs = chunkPos.getMinBlockZ() + zRel;
|
||||
|
||||
//Calculate the height of the lod
|
||||
yAbs = DataPointUtil.worldHeight + 1;
|
||||
int count = 0;
|
||||
boolean topBlock = true;
|
||||
while (yAbs > 0)
|
||||
{
|
||||
height = determineHeightPointFrom(chunk, config, xRel, yAbs, zRel, blockPos);
|
||||
|
||||
// If the lod is at the default height, it must be void data
|
||||
if (height == DEFAULT_HEIGHT)
|
||||
{
|
||||
if (topBlock)
|
||||
dataToMerge[index * verticalData] = DataPointUtil.createVoidDataPoint(generation);
|
||||
break;
|
||||
}
|
||||
|
||||
yAbs = height - 1;
|
||||
// We search light on above air block
|
||||
depth = determineBottomPointFrom(chunk, config, xRel, yAbs, zRel, blockPos);
|
||||
if (hasCeiling && topBlock)
|
||||
{
|
||||
yAbs = depth;
|
||||
blockPos.set(xAbs, yAbs, zAbs);
|
||||
light = getLightValue(chunk, blockPos, true, hasSkyLight, true);
|
||||
color = generateLodColor(chunk, config, xAbs, yAbs, zAbs, blockPos);
|
||||
blockPos.set(xAbs, yAbs - 1, zAbs);
|
||||
}
|
||||
else
|
||||
{
|
||||
blockPos.set(xAbs, yAbs, zAbs);
|
||||
light = getLightValue(chunk, blockPos, hasCeiling, hasSkyLight, topBlock);
|
||||
color = generateLodColor(chunk, config, xRel, yAbs, zRel, blockPos);
|
||||
blockPos.set(xAbs, yAbs + 1, zAbs);
|
||||
}
|
||||
lightBlock = light & 0b1111;
|
||||
lightSky = (light >> 4) & 0b1111;
|
||||
isDefault = ((light >> 8)) == 1;
|
||||
|
||||
dataToMerge[index * verticalData + count] = DataPointUtil.createDataPoint(height, depth, color, lightSky, lightBlock, generation, isDefault);
|
||||
topBlock = false;
|
||||
yAbs = depth - 1;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return dataToMerge;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the lowest valid point from the bottom.
|
||||
* Used when creating a vertical LOD.
|
||||
@@ -400,7 +403,7 @@ public class LodBuilder
|
||||
|
||||
|
||||
|
||||
if (world != null && !world.isEmpty())
|
||||
if (world != null)
|
||||
{
|
||||
// server world sky light (always accurate)
|
||||
blockLight = world.getBlockLight(blockPos);
|
||||
@@ -428,39 +431,42 @@ public class LodBuilder
|
||||
}
|
||||
else
|
||||
{
|
||||
world = MC.getWrappedServerWorld();
|
||||
if (world.isEmpty())
|
||||
return 0;
|
||||
// client world sky light (almost never accurate)
|
||||
blockLight = world.getBlockLight(blockPos);
|
||||
// estimate what the lighting should be
|
||||
if (hasSkyLight || !hasCeiling)
|
||||
world = MC.getWrappedClientWorld();
|
||||
if (world==null)
|
||||
{
|
||||
if (topBlock)
|
||||
skyLight = DEFAULT_MAX_LIGHT;
|
||||
else
|
||||
blockLight = 0;
|
||||
skyLight = 12;
|
||||
isDefault = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// client world sky light (almost never accurate)
|
||||
blockLight = world.getBlockLight(blockPos);
|
||||
// estimate what the lighting should be
|
||||
if (hasSkyLight || !hasCeiling)
|
||||
{
|
||||
|
||||
if (hasSkyLight)
|
||||
skyLight = world.getSkyLight(blockPos);
|
||||
//else
|
||||
// skyLight = 0;
|
||||
|
||||
if (!chunk.isLightCorrect() && (skyLight == 0 || skyLight == 15))
|
||||
if (topBlock)
|
||||
skyLight = DEFAULT_MAX_LIGHT;
|
||||
else
|
||||
{
|
||||
// we don't know what the light here is,
|
||||
// lets just take a guess
|
||||
if (blockPos.getY() >= MC.getWrappedClientWorld().getSeaLevel() - 5)
|
||||
if (hasSkyLight)
|
||||
skyLight = world.getSkyLight(blockPos);
|
||||
//else
|
||||
// skyLight = 0;
|
||||
if (!chunk.isLightCorrect() && (skyLight == 0 || skyLight == 15))
|
||||
{
|
||||
skyLight = 12;
|
||||
isDefault = 1;
|
||||
// we don't know what the light here is,
|
||||
// lets just take a guess
|
||||
if (blockPos.getY() >= MC.getWrappedClientWorld().getSeaLevel() - 5)
|
||||
{
|
||||
skyLight = 12;
|
||||
isDefault = 1;
|
||||
}
|
||||
else
|
||||
skyLight = 0;
|
||||
}
|
||||
else
|
||||
skyLight = 0;
|
||||
}
|
||||
}
|
||||
if (hasSkyLight)
|
||||
skyLight = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ public class LodGenWorker
|
||||
// to queue up a bunch of generation requests,
|
||||
// because MC's internal server (as of 1.16.5) only
|
||||
// responds with a single thread. And we don't
|
||||
// want to cause more lag then necessary or queue up
|
||||
// want to cause more lag than necessary or queue up
|
||||
// requests that may end up being unneeded.
|
||||
thread.run();
|
||||
}
|
||||
@@ -105,7 +105,7 @@ public class LodGenWorker
|
||||
|
||||
private static class LodChunkGenThread implements Runnable
|
||||
{
|
||||
private AbstractWorldGeneratorWrapper worldGenWrapper;
|
||||
private final AbstractWorldGeneratorWrapper worldGenWrapper;
|
||||
|
||||
public final LodDimension lodDim;
|
||||
public final DistanceGenerationMode generationMode;
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.seibel.lod.core.dataFormat;
|
||||
|
||||
public class BlockDataFormat
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.seibel.lod.core.dataFormat;
|
||||
|
||||
public class ColorFormat
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.seibel.lod.core.dataFormat;
|
||||
|
||||
public class DepthHeightFormat
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.seibel.lod.core.dataFormat;
|
||||
|
||||
public class LightFormat
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.seibel.lod.core.dataFormat;
|
||||
|
||||
public class PositionDataFormat
|
||||
{
|
||||
}
|
||||
@@ -6,8 +6,6 @@ import java.util.Map;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.seibel.lod.core.objects.math.Vec3i;
|
||||
|
||||
/**
|
||||
@@ -73,7 +71,7 @@ public enum LodDirection
|
||||
|
||||
|
||||
|
||||
private LodDirection(int p_i46016_3_, int p_i46016_4_, int p_i46016_5_, String p_i46016_6_, LodDirection.AxisDirection p_i46016_7_, LodDirection.Axis p_i46016_8_, Vec3i p_i46016_9_)
|
||||
LodDirection(int p_i46016_3_, int p_i46016_4_, int p_i46016_5_, String p_i46016_6_, LodDirection.AxisDirection p_i46016_7_, LodDirection.Axis p_i46016_8_, Vec3i p_i46016_9_)
|
||||
{
|
||||
// this.data3d = p_i46016_3_;
|
||||
// this.data2d = p_i46016_5_;
|
||||
@@ -227,9 +225,8 @@ public enum LodDirection
|
||||
{
|
||||
return this.axis;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static LodDirection byName(@Nullable String name)
|
||||
|
||||
public static LodDirection byName(String name)
|
||||
{
|
||||
return name == null ? null : BY_NAME.get(name.toLowerCase(Locale.ROOT));
|
||||
}
|
||||
@@ -328,7 +325,7 @@ public enum LodDirection
|
||||
// return this.normal.getX() * f1 + this.normal.getZ() * f2 > 0.0F;
|
||||
// }
|
||||
|
||||
public static enum Axis implements Predicate<LodDirection>
|
||||
public enum Axis implements Predicate<LodDirection>
|
||||
{
|
||||
X("x")
|
||||
{
|
||||
@@ -381,12 +378,11 @@ public enum LodDirection
|
||||
}));
|
||||
private final String name;
|
||||
|
||||
private Axis(String name)
|
||||
Axis(String name)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
public static LodDirection.Axis byName(String name)
|
||||
{
|
||||
return BY_NAME.get(name.toLowerCase(Locale.ROOT));
|
||||
@@ -419,7 +415,7 @@ public enum LodDirection
|
||||
// }
|
||||
|
||||
@Override
|
||||
public boolean test(@Nullable LodDirection p_test_1_)
|
||||
public boolean test(LodDirection p_test_1_)
|
||||
{
|
||||
return p_test_1_ != null && p_test_1_.getAxis() == this;
|
||||
}
|
||||
@@ -443,7 +439,7 @@ public enum LodDirection
|
||||
public abstract double choose(double p_196051_1_, double p_196051_3_, double p_196051_5_);
|
||||
}
|
||||
|
||||
public static enum AxisDirection
|
||||
public enum AxisDirection
|
||||
{
|
||||
POSITIVE(1, "Towards positive"),
|
||||
NEGATIVE(-1, "Towards negative");
|
||||
@@ -451,7 +447,7 @@ public enum LodDirection
|
||||
private final int step;
|
||||
private final String name;
|
||||
|
||||
private AxisDirection(int newStep, String newName)
|
||||
AxisDirection(int newStep, String newName)
|
||||
{
|
||||
this.step = newStep;
|
||||
this.name = newName;
|
||||
|
||||
@@ -31,20 +31,22 @@ package com.seibel.lod.core.enums.config;
|
||||
*/
|
||||
public enum BufferRebuildTimes
|
||||
{
|
||||
FREQUENT(1000, 500, 2500),
|
||||
FREQUENT(1000, 500, 2500, 1),
|
||||
|
||||
NORMAL(2000, 1000, 5000),
|
||||
NORMAL(2000, 1000, 5000, 4),
|
||||
|
||||
RARE(5000, 2000, 10000);
|
||||
RARE(5000, 2000, 10000, 16);
|
||||
|
||||
public final int playerMoveTimeout;
|
||||
public final int renderedChunkTimeout;
|
||||
public final int chunkChangeTimeout;
|
||||
public final int playerMoveDistance;
|
||||
|
||||
BufferRebuildTimes(int playerMoveTimeout, int renderedChunkTimeout, int chunkChangeTimeout)
|
||||
BufferRebuildTimes(int playerMoveTimeout, int renderedChunkTimeout, int chunkChangeTimeout, int playerMoveDistance)
|
||||
{
|
||||
this.playerMoveTimeout = playerMoveTimeout;
|
||||
this.renderedChunkTimeout = renderedChunkTimeout;
|
||||
this.chunkChangeTimeout = chunkChangeTimeout;
|
||||
this.playerMoveDistance = playerMoveDistance;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
package com.seibel.lod.core.enums.config;
|
||||
|
||||
/**
|
||||
* AUTO <br>
|
||||
* Near_First <br>
|
||||
* Far_First <br>
|
||||
* <br>
|
||||
@@ -27,10 +28,13 @@ package com.seibel.lod.core.enums.config;
|
||||
* outside the normal view distance.
|
||||
*
|
||||
* @author Leonardo Amato
|
||||
* @version 9-25-2021
|
||||
* @version 12-1-2021
|
||||
*/
|
||||
public enum GenerationPriority
|
||||
{
|
||||
/** NEAR_FIRST when connected to servers and FAR_FIRST when on single player */
|
||||
AUTO,
|
||||
|
||||
NEAR_FIRST,
|
||||
|
||||
FAR_FIRST
|
||||
|
||||
@@ -20,22 +20,40 @@
|
||||
package com.seibel.lod.core.enums.config;
|
||||
|
||||
/**
|
||||
* Buffer_Storage, Sub_Data, Buffer_Mapping
|
||||
* Auto, Buffer_Storage, Sub_Data, Buffer_Mapping, Data
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 11-21-2021
|
||||
* @version 12-1-2021
|
||||
*/
|
||||
public enum GpuUploadMethod
|
||||
{
|
||||
/** Default if OpenGL 4.5 is supported. Fast rendering, no stuttering. */
|
||||
/** Picks the best option based on the GPU the user has. */
|
||||
AUTO,
|
||||
|
||||
/**
|
||||
* Default for NVIDIA if OpenGL 4.5 is supported. <br>
|
||||
* Fast rendering, no stuttering.
|
||||
*/
|
||||
BUFFER_STORAGE,
|
||||
|
||||
/** Default if OpenGL 4.5 is NOT supported. Fast rendering but may stutter when uploading. */
|
||||
/**
|
||||
* Backup option for NVIDIA. <br>
|
||||
* Fast rendering but may stutter when uploading.
|
||||
*/
|
||||
SUB_DATA,
|
||||
|
||||
/** Fast rendering but will stutter when uploading. */
|
||||
/**
|
||||
* Default option for AMD/Intel. <br>
|
||||
* May end up storing buffers in System memory. <br>
|
||||
* Fast rending if in GPU memory, slow if in system memory, <br>
|
||||
* but won't stutter when uploading.
|
||||
*/
|
||||
BUFFER_MAPPING,
|
||||
|
||||
/**
|
||||
* Backup option for AMD/Intel. <br>
|
||||
* Fast rendering but may stutter when uploading.
|
||||
*/
|
||||
DATA,
|
||||
|
||||
/** May end up storing buffers in System memory. Slower rendering but won't stutter when uploading. */
|
||||
BUFFER_MAPPING,
|
||||
}
|
||||
+15
-6
@@ -20,14 +20,23 @@
|
||||
package com.seibel.lod.core.enums.rendering;
|
||||
|
||||
/**
|
||||
* fast, fancy, or off
|
||||
* USE_DEFAULT_FOG_COLOR, <br>
|
||||
* USE_SKY_COLOR, <br>
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 02-14-2021
|
||||
* @version 11-27-2021
|
||||
*/
|
||||
public enum FogQuality
|
||||
public enum FogColorMode
|
||||
{
|
||||
FAST,
|
||||
FANCY,
|
||||
OFF
|
||||
/** Fog uses Minecraft's fog color. */
|
||||
USE_WORLD_FOG_COLOR,
|
||||
|
||||
/**
|
||||
* Replicates the effect of the clear sky mod.
|
||||
* Making the fog blend in with the sky better
|
||||
* https://www.curseforge.com/minecraft/mc-mods/clear-skies
|
||||
* https://www.curseforge.com/minecraft/mc-mods/clear-skies-forge-port
|
||||
* For it to look good you need one of those mods
|
||||
*/
|
||||
USE_SKY_COLOR,
|
||||
}
|
||||
@@ -23,16 +23,11 @@ package com.seibel.lod.core.enums.rendering;
|
||||
* NEAR, FAR, or NEAR_AND_FAR.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 02-14-2021
|
||||
* @version 11-26-2021
|
||||
*/
|
||||
public enum FogDistance
|
||||
{
|
||||
/** good for fast or fancy fog qualities. */
|
||||
NEAR,
|
||||
|
||||
/** good for fast or fancy fog qualities. */
|
||||
FAR,
|
||||
|
||||
/** only looks good if the fog quality is set to Fancy. */
|
||||
NEAR_AND_FAR
|
||||
}
|
||||
+8
-15
@@ -21,27 +21,20 @@ package com.seibel.lod.core.enums.rendering;
|
||||
|
||||
/**
|
||||
* USE_OPTIFINE_FOG_SETTING, <br>
|
||||
* NEVER_DRAW_FOG, <br>
|
||||
* ALWAYS_DRAW_FOG_FAST, <br>
|
||||
* ALWAYS_DRAW_FOG_FANCY <br>
|
||||
* FOG_ENABLED, <br>
|
||||
* FOG_DISABLED <br>
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 7-3-2021
|
||||
* @version 11-27-2021
|
||||
*/
|
||||
public enum FogDrawOverride
|
||||
public enum FogDrawMode
|
||||
{
|
||||
/**
|
||||
* Use whatever Fog setting optifine is using.
|
||||
* If optifine isn't installed this defaults to ALWAYS_DRAW_FOG.
|
||||
*/
|
||||
OPTIFINE_SETTING,
|
||||
USE_OPTIFINE_SETTING,
|
||||
|
||||
/** Never draw fog on the LODs */
|
||||
NO_FOG,
|
||||
|
||||
/** Always draw fast fog on the LODs */
|
||||
FAST,
|
||||
|
||||
/** Always draw fancy fog on the LODs */
|
||||
FANCY
|
||||
}
|
||||
FOG_ENABLED,
|
||||
FOG_DISABLED
|
||||
}
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
package com.seibel.lod.core.handlers;
|
||||
|
||||
import com.seibel.lod.core.enums.rendering.FogQuality;
|
||||
import com.seibel.lod.core.enums.rendering.FogDrawMode;
|
||||
import com.seibel.lod.core.objects.math.Mat4f;
|
||||
|
||||
/**
|
||||
@@ -35,15 +35,15 @@ import com.seibel.lod.core.objects.math.Mat4f;
|
||||
* different MC versions.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 11-20-2021
|
||||
* @version 11-26-2021
|
||||
*/
|
||||
public interface IReflectionHandler
|
||||
{
|
||||
/** @returns the type of fog optifine is currently set to render. */
|
||||
public FogQuality getFogQuality();
|
||||
/** @returns Whether Optifine is set to render fog or not. */
|
||||
FogDrawMode getFogDrawMode();
|
||||
|
||||
/** @returns if Vivecraft is present. Attempts to find the "VRRenderer" class. */
|
||||
public boolean vivecraftPresent();
|
||||
boolean vivecraftPresent();
|
||||
|
||||
/**
|
||||
* Modifies the projection matrix's clip planes.
|
||||
@@ -54,5 +54,5 @@ public interface IReflectionHandler
|
||||
* @param newFarClipPlane the new far clip plane value.
|
||||
* @return The modified matrix.
|
||||
*/
|
||||
public Mat4f ModifyProjectionClipPlanes(Mat4f projectionMatrix, float newNearClipPlane, float newFarClipPlane);
|
||||
Mat4f ModifyProjectionClipPlanes(Mat4f projectionMatrix, float newNearClipPlane, float newFarClipPlane);
|
||||
}
|
||||
|
||||
@@ -21,8 +21,8 @@ package com.seibel.lod.core.handlers;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
@@ -77,7 +77,7 @@ public class LodDimensionFileHandler
|
||||
* file handler, older versions (smaller numbers) will be deleted and overwritten,
|
||||
* newer versions (larger numbers) will be ignored and won't be read.
|
||||
*/
|
||||
public static final int LOD_SAVE_FILE_VERSION = 6;
|
||||
public static final int LOD_SAVE_FILE_VERSION = 8;
|
||||
|
||||
/**
|
||||
* Allow saving asynchronously, but never try to save multiple regions
|
||||
@@ -129,28 +129,40 @@ public class LodDimensionFileHandler
|
||||
{
|
||||
//there is no file for current gen mode
|
||||
//search others above current from the most to the least detailed
|
||||
DistanceGenerationMode tempGenMode = DistanceGenerationMode.FULL;
|
||||
while (tempGenMode != generationMode)
|
||||
{
|
||||
fileName = getFileNameAndPathForRegion(regionX, regionZ, tempGenMode, tempDetailLevel, verticalQuality);
|
||||
VerticalQuality tempVerticalQuality = VerticalQuality.HIGH;
|
||||
do {
|
||||
DistanceGenerationMode tempGenMode = DistanceGenerationMode.FULL;
|
||||
do {
|
||||
fileName = getFileNameAndPathForRegion(regionX, regionZ, tempGenMode, tempDetailLevel, verticalQuality);
|
||||
if (fileName != null)
|
||||
{
|
||||
file = new File(fileName);
|
||||
if (file.exists())
|
||||
break;
|
||||
}
|
||||
//decrease gen mode
|
||||
if (tempGenMode == DistanceGenerationMode.FULL)
|
||||
tempGenMode = DistanceGenerationMode.FEATURES;
|
||||
else if (tempGenMode == DistanceGenerationMode.FEATURES)
|
||||
tempGenMode = DistanceGenerationMode.SURFACE;
|
||||
else if (tempGenMode == DistanceGenerationMode.SURFACE)
|
||||
tempGenMode = DistanceGenerationMode.BIOME_ONLY_SIMULATE_HEIGHT;
|
||||
else if (tempGenMode == DistanceGenerationMode.BIOME_ONLY_SIMULATE_HEIGHT)
|
||||
tempGenMode = DistanceGenerationMode.BIOME_ONLY;
|
||||
else if (tempGenMode == DistanceGenerationMode.BIOME_ONLY)
|
||||
tempGenMode = DistanceGenerationMode.NONE;
|
||||
} while (tempGenMode != generationMode);
|
||||
if (fileName != null)
|
||||
{
|
||||
file = new File(fileName);
|
||||
if (file.exists())
|
||||
break;
|
||||
}
|
||||
//decrease gen mode
|
||||
if (tempGenMode == DistanceGenerationMode.FULL)
|
||||
tempGenMode = DistanceGenerationMode.FEATURES;
|
||||
else if (tempGenMode == DistanceGenerationMode.FEATURES)
|
||||
tempGenMode = DistanceGenerationMode.SURFACE;
|
||||
else if (tempGenMode == DistanceGenerationMode.SURFACE)
|
||||
tempGenMode = DistanceGenerationMode.BIOME_ONLY_SIMULATE_HEIGHT;
|
||||
else if (tempGenMode == DistanceGenerationMode.BIOME_ONLY_SIMULATE_HEIGHT)
|
||||
tempGenMode = DistanceGenerationMode.BIOME_ONLY;
|
||||
else if (tempGenMode == DistanceGenerationMode.BIOME_ONLY)
|
||||
tempGenMode = DistanceGenerationMode.NONE;
|
||||
}
|
||||
if (tempVerticalQuality == VerticalQuality.HIGH)
|
||||
tempVerticalQuality = VerticalQuality.MEDIUM;
|
||||
else if (tempVerticalQuality == VerticalQuality.MEDIUM)
|
||||
tempVerticalQuality = VerticalQuality.LOW;
|
||||
} while (tempVerticalQuality != verticalQuality);
|
||||
if (!file.exists())
|
||||
//there wasn't a file, don't return anything
|
||||
continue;
|
||||
@@ -169,7 +181,7 @@ public class LodDimensionFileHandler
|
||||
fileVersion = inputStream.read();
|
||||
|
||||
// check if this file can be read by this file handler
|
||||
if (fileVersion < LOD_SAVE_FILE_VERSION)
|
||||
if (fileVersion < 6)
|
||||
{
|
||||
// the file we are reading is an older version,
|
||||
// close the reader and delete the file.
|
||||
@@ -195,17 +207,24 @@ public class LodDimensionFileHandler
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// this file is a readable version,
|
||||
// read the file
|
||||
byte[] data = ThreadMapUtil.getSaveContainer(tempDetailLevel);
|
||||
inputStream.read(data);
|
||||
inputStream.close();
|
||||
|
||||
|
||||
// add the data to our region
|
||||
region.addLevelContainer(new VerticalLevelContainer(data));
|
||||
else if (fileVersion < LOD_SAVE_FILE_VERSION)
|
||||
{
|
||||
//this is old, but readable version
|
||||
byte[] data = ThreadMapUtil.getSaveContainer(tempDetailLevel);
|
||||
inputStream.read(data);
|
||||
inputStream.close();
|
||||
// add the data to our region
|
||||
region.addLevelContainer(new VerticalLevelContainer(data, fileVersion));
|
||||
} else
|
||||
{
|
||||
// this file is a readable version,
|
||||
// read the file
|
||||
byte[] data = ThreadMapUtil.getSaveContainer(tempDetailLevel);
|
||||
inputStream.read(data);
|
||||
inputStream.close();
|
||||
// add the data to our region
|
||||
region.addLevelContainer(new VerticalLevelContainer(data, LOD_SAVE_FILE_VERSION));
|
||||
}
|
||||
}
|
||||
catch (IOException ioEx)
|
||||
{
|
||||
@@ -365,27 +384,69 @@ public class LodDimensionFileHandler
|
||||
}
|
||||
|
||||
|
||||
public void saveRegionFile (byte[] regionFile, RegionPos regionPos, DistanceGenerationMode generationMode, byte detailLevel, VerticalQuality verticalQuality)
|
||||
{
|
||||
int regionX = regionPos.x;
|
||||
int regionZ = regionPos.z;
|
||||
String fileName = getFileNameAndPathForRegion(regionX, regionZ, generationMode, detailLevel, verticalQuality);
|
||||
|
||||
if (fileName != null)
|
||||
{
|
||||
File oldFile = new File(fileName);
|
||||
File newFile = new File(fileName + TMP_FILE_EXTENSION);
|
||||
try (OutputStream os = new FileOutputStream(newFile))
|
||||
{
|
||||
os.write(regionFile);
|
||||
Files.move(newFile.toPath(), oldFile.toPath(), StandardCopyOption.ATOMIC_MOVE, StandardCopyOption.REPLACE_EXISTING);
|
||||
os.close();
|
||||
}
|
||||
catch (IOException ioEx)
|
||||
{
|
||||
ClientApi.LOGGER.error("LOD file write error. Unable to write to [" + fileName + "] error [" + ioEx.getMessage() + "]: ");
|
||||
ioEx.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] getRegionFile (RegionPos regionPos, DistanceGenerationMode generationMode, byte detailLevel, VerticalQuality verticalQuality)
|
||||
{
|
||||
int regionX = regionPos.x;
|
||||
int regionZ = regionPos.z;
|
||||
String fileName = getFileNameAndPathForRegion(regionX, regionZ, generationMode, detailLevel, verticalQuality);
|
||||
if (fileName != null)
|
||||
{
|
||||
File file = new File(fileName);
|
||||
try (InputStream is = new FileInputStream(file))
|
||||
{
|
||||
byte[] data = ThreadMapUtil.getSaveContainer(detailLevel);
|
||||
is.read(data);
|
||||
is.close();
|
||||
return Arrays.copyOf(data, (int) file.length());
|
||||
}
|
||||
catch (IOException ioEx)
|
||||
{
|
||||
ClientApi.LOGGER.error("LOD file read error. Unable to read to [" + fileName + "] error [" + ioEx.getMessage() + "]: ");
|
||||
ioEx.printStackTrace();
|
||||
}
|
||||
}
|
||||
return new byte[0];
|
||||
}
|
||||
|
||||
|
||||
//================//
|
||||
// helper methods //
|
||||
//================//
|
||||
|
||||
public byte[] getHashFromFile(byte detailLevel, RegionPos regionPos, DistanceGenerationMode generationMode, VerticalQuality verticalQuality)
|
||||
public int getHashFromFile(RegionPos regionPos, DistanceGenerationMode generationMode, byte detailLevel, VerticalQuality verticalQuality)
|
||||
{
|
||||
int regionX = regionPos.x;
|
||||
int regionZ = regionPos.z;
|
||||
String fileName = getFileNameAndPathForRegion(regionX, regionZ, generationMode, detailLevel, verticalQuality);
|
||||
try (InputStream is = Files.newInputStream(Paths.get(fileName))) {
|
||||
return org.apache.commons.codec.digest.DigestUtils.md5(is);
|
||||
}
|
||||
catch (IOException ioEx)
|
||||
{
|
||||
ClientApi.LOGGER.error("LOD file read error. Unable to read to [" + fileName + "] error [" + ioEx.getMessage() + "]: ");
|
||||
ioEx.printStackTrace();
|
||||
}
|
||||
return new byte[0];
|
||||
if (fileName == null)
|
||||
return 0;
|
||||
|
||||
File file = new File(fileName);
|
||||
return file.hashCode();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import com.seibel.lod.core.ModInfo;
|
||||
import com.seibel.lod.core.enums.rendering.FogQuality;
|
||||
import com.seibel.lod.core.enums.rendering.FogDrawMode;
|
||||
import com.seibel.lod.core.objects.math.Mat4f;
|
||||
|
||||
/**
|
||||
@@ -35,7 +35,7 @@ import com.seibel.lod.core.objects.math.Mat4f;
|
||||
* presence/absence of other mods.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 11-20-2021
|
||||
* @version 11-26-2021
|
||||
*/
|
||||
public class ReflectionHandler implements IReflectionHandler
|
||||
{
|
||||
@@ -100,14 +100,14 @@ public class ReflectionHandler implements IReflectionHandler
|
||||
* @return the fog quality
|
||||
*/
|
||||
@Override
|
||||
public FogQuality getFogQuality()
|
||||
public FogDrawMode getFogDrawMode()
|
||||
{
|
||||
if (ofFogField == null)
|
||||
{
|
||||
// either optifine isn't installed,
|
||||
// the variable name was changed, or
|
||||
// the setup method wasn't called yet.
|
||||
return FogQuality.FANCY;
|
||||
return FogDrawMode.FOG_ENABLED;
|
||||
}
|
||||
|
||||
int returnNum = 0;
|
||||
@@ -129,12 +129,11 @@ public class ReflectionHandler implements IReflectionHandler
|
||||
// it should never be called in this case
|
||||
|
||||
// normal options
|
||||
case 1:
|
||||
return FogQuality.FAST;
|
||||
case 2:
|
||||
return FogQuality.FANCY;
|
||||
case 3:
|
||||
return FogQuality.OFF;
|
||||
case 1: // fast
|
||||
case 2: // fancy
|
||||
return FogDrawMode.FOG_ENABLED;
|
||||
case 3: // off
|
||||
return FogDrawMode.FOG_DISABLED;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,9 +28,9 @@ package com.seibel.lod.core.objects;
|
||||
*/
|
||||
public class MinDefaultMax<T>
|
||||
{
|
||||
public T minValue;
|
||||
public T defaultValue;
|
||||
public T maxValue;
|
||||
public final T minValue;
|
||||
public final T defaultValue;
|
||||
public final T maxValue;
|
||||
|
||||
public MinDefaultMax(T newMinValue, T newDefaultValue, T newMaxValue)
|
||||
{
|
||||
|
||||
+33
-29
@@ -35,12 +35,11 @@ import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
|
||||
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftWrapper;
|
||||
|
||||
/**
|
||||
* Similar to Minecraft's AxisAlignedBoundingBox.
|
||||
*
|
||||
* This class handles all the vertex optimization that's needed for a column of lods. W
|
||||
* @author Leonardo Amato
|
||||
* @version 10-2-2021
|
||||
*/
|
||||
public class Box
|
||||
public class VertexOptimizer
|
||||
{
|
||||
private static final IMinecraftWrapper MC = SingletonHandler.get(IMinecraftWrapper.class);
|
||||
private static final ILodConfigWrapperSingleton CONFIG = SingletonHandler.get(ILodConfigWrapperSingleton.class);
|
||||
@@ -207,7 +206,7 @@ public class Box
|
||||
|
||||
/** creates an empty box */
|
||||
@SuppressWarnings("serial")
|
||||
public Box()
|
||||
public VertexOptimizer()
|
||||
{
|
||||
boxOffset = new int[3];
|
||||
boxWidth = new int[3];
|
||||
@@ -339,25 +338,27 @@ public class Box
|
||||
* This method create all the shared face culling based on the adjacent data
|
||||
* @param adjData data adjacent to the column we are going to render
|
||||
*/
|
||||
public void setAdjData(Map<LodDirection, long[]> adjData)
|
||||
public void setAdjData(Map<LodDirection, int[]> adjData, Map<LodDirection, byte[]> adjFlags)
|
||||
{
|
||||
int height;
|
||||
int depth;
|
||||
int minY = getMinY();
|
||||
int maxY = getMaxY();
|
||||
long singleAdjDataPoint;
|
||||
int singleAdjData;
|
||||
byte singleAdjFlags;
|
||||
|
||||
/* TODO implement attached vertical face culling
|
||||
//Up direction case
|
||||
if(DataPointUtil.doesItExist(adjData.get(Direction.UP)))
|
||||
{
|
||||
height = DataPointUtil.getHeight(singleAdjDataPoint);
|
||||
depth = DataPointUtil.getDepth(singleAdjDataPoint);
|
||||
height = DataPointUtil.getHeight(singleAdjData);
|
||||
depth = DataPointUtil.getDepth(singleAdjData);
|
||||
}*/
|
||||
//Down direction case
|
||||
singleAdjDataPoint = adjData.get(LodDirection.DOWN)[0];
|
||||
if(DataPointUtil.doesItExist(singleAdjDataPoint))
|
||||
skyLights.get(LodDirection.DOWN)[0] = DataPointUtil.getLightSkyAlt(singleAdjDataPoint);
|
||||
singleAdjData = adjData.get(LodDirection.DOWN)[0];
|
||||
singleAdjFlags = adjFlags.get(LodDirection.DOWN)[0];
|
||||
if(DataPointUtil.doesItExist(singleAdjFlags))
|
||||
skyLights.get(LodDirection.DOWN)[0] = DataPointUtil.getLightSkyAlt(singleAdjData, singleAdjFlags);
|
||||
else
|
||||
skyLights.get(LodDirection.DOWN)[0] = skyLights.get(LodDirection.UP)[0];
|
||||
//other sided
|
||||
@@ -367,14 +368,15 @@ public class Box
|
||||
if (isCulled(lodDirection))
|
||||
continue;
|
||||
|
||||
long[] dataPoint = adjData.get(lodDirection);
|
||||
if (dataPoint == null || DataPointUtil.isVoid(dataPoint[0]))
|
||||
int[] data = adjData.get(lodDirection);
|
||||
byte[] flags = adjFlags.get(lodDirection);
|
||||
if (DataPointUtil.isVoid(flags[0]))
|
||||
{
|
||||
adjHeight.get(lodDirection)[0] = maxY;
|
||||
adjDepth.get(lodDirection)[0] = minY;
|
||||
adjHeight.get(lodDirection)[1] = VOID_FACE;
|
||||
adjDepth.get(lodDirection)[1] = VOID_FACE;
|
||||
skyLights.get(lodDirection)[0] = 15; //in void set full sky light
|
||||
skyLights.get(lodDirection)[0] = 15; //in void set full skylight
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -384,15 +386,16 @@ public class Box
|
||||
boolean toFinish = false;
|
||||
int toFinishIndex = 0;
|
||||
boolean allAbove = true;
|
||||
for (i = 0; i < dataPoint.length; i++)
|
||||
for (i = 0; i < flags.length; i++)
|
||||
{
|
||||
singleAdjDataPoint = dataPoint[i];
|
||||
singleAdjData = data[i];
|
||||
singleAdjFlags = flags[i];
|
||||
|
||||
if (DataPointUtil.isVoid(singleAdjDataPoint) || !DataPointUtil.doesItExist(singleAdjDataPoint))
|
||||
if (DataPointUtil.isVoid(singleAdjFlags) || !DataPointUtil.doesItExist(singleAdjFlags))
|
||||
break;
|
||||
|
||||
height = DataPointUtil.getHeight(singleAdjDataPoint);
|
||||
depth = DataPointUtil.getDepth(singleAdjDataPoint);
|
||||
height = DataPointUtil.getHeight(singleAdjData);
|
||||
depth = DataPointUtil.getDepth(singleAdjData);
|
||||
|
||||
if (depth <= maxY)
|
||||
{
|
||||
@@ -405,12 +408,12 @@ public class Box
|
||||
{
|
||||
adjHeight.get(lodDirection)[0] = getMaxY();
|
||||
adjDepth.get(lodDirection)[0] = getMinY();
|
||||
skyLights.get(lodDirection)[0] = DataPointUtil.getLightSkyAlt(singleAdjDataPoint); //skyLights.get(Direction.UP)[0];
|
||||
skyLights.get(lodDirection)[0] = DataPointUtil.getLightSkyAlt(singleAdjData, singleAdjFlags); //skyLights.get(Direction.UP)[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
adjDepth.get(lodDirection)[faceToDraw] = getMinY();
|
||||
skyLights.get(lodDirection)[faceToDraw] = DataPointUtil.getLightSkyAlt(singleAdjDataPoint);
|
||||
skyLights.get(lodDirection)[faceToDraw] = DataPointUtil.getLightSkyAlt(singleAdjData, singleAdjFlags);
|
||||
}
|
||||
faceToDraw++;
|
||||
toFinish = false;
|
||||
@@ -436,12 +439,12 @@ public class Box
|
||||
{
|
||||
adjHeight.get(lodDirection)[0] = getMaxY();
|
||||
adjDepth.get(lodDirection)[0] = height;
|
||||
skyLights.get(lodDirection)[0] = DataPointUtil.getLightSkyAlt(singleAdjDataPoint); //skyLights.get(Direction.UP)[0];
|
||||
skyLights.get(lodDirection)[0] = DataPointUtil.getLightSkyAlt(singleAdjData, singleAdjFlags); //skyLights.get(Direction.UP)[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
adjDepth.get(lodDirection)[faceToDraw] = height;
|
||||
skyLights.get(lodDirection)[faceToDraw] = DataPointUtil.getLightSkyAlt(singleAdjDataPoint);
|
||||
skyLights.get(lodDirection)[faceToDraw] = DataPointUtil.getLightSkyAlt(singleAdjData, singleAdjFlags);
|
||||
}
|
||||
toFinish = false;
|
||||
faceToDraw++;
|
||||
@@ -453,7 +456,7 @@ public class Box
|
||||
// the adj data intersects the higher part of the current data
|
||||
// we start the creation of a new face
|
||||
adjHeight.get(lodDirection)[faceToDraw] = depth;
|
||||
//skyLights.get(direction)[faceToDraw] = (byte) DataPointUtil.getLightSkyAlt(singleAdjDataPoint);
|
||||
//skyLights.get(direction)[faceToDraw] = (byte) DataPointUtil.getLightSkyAlt(singleAdjData);
|
||||
firstFace = false;
|
||||
toFinish = true;
|
||||
toFinishIndex = i + 1;
|
||||
@@ -469,7 +472,7 @@ public class Box
|
||||
}
|
||||
|
||||
adjDepth.get(lodDirection)[faceToDraw] = height;
|
||||
skyLights.get(lodDirection)[faceToDraw] = DataPointUtil.getLightSkyAlt(singleAdjDataPoint);
|
||||
skyLights.get(lodDirection)[faceToDraw] = DataPointUtil.getLightSkyAlt(singleAdjData, singleAdjFlags);
|
||||
faceToDraw++;
|
||||
adjHeight.get(lodDirection)[faceToDraw] = depth;
|
||||
firstFace = false;
|
||||
@@ -489,11 +492,12 @@ public class Box
|
||||
else if (toFinish)
|
||||
{
|
||||
adjDepth.get(lodDirection)[faceToDraw] = minY;
|
||||
if(toFinishIndex < dataPoint.length)
|
||||
if(toFinishIndex < flags.length)
|
||||
{
|
||||
singleAdjDataPoint = dataPoint[toFinishIndex];
|
||||
if (DataPointUtil.doesItExist(singleAdjDataPoint))
|
||||
skyLights.get(lodDirection)[faceToDraw] = DataPointUtil.getLightSkyAlt(singleAdjDataPoint);
|
||||
singleAdjData = data[toFinishIndex];
|
||||
singleAdjFlags = flags[toFinishIndex];
|
||||
if (DataPointUtil.doesItExist(singleAdjFlags))
|
||||
skyLights.get(lodDirection)[faceToDraw] = DataPointUtil.getLightSkyAlt(singleAdjData, singleAdjFlags);
|
||||
else
|
||||
skyLights.get(lodDirection)[faceToDraw] = skyLights.get(LodDirection.UP)[0];
|
||||
}
|
||||
@@ -32,7 +32,7 @@ public interface LevelContainer
|
||||
* @param index z position in the detail level
|
||||
* @return true if correctly added, false otherwise
|
||||
*/
|
||||
boolean addData(long data, int posX, int posZ, int index);
|
||||
boolean addData(int color, int data, byte flags, int posX, int posZ, int index);
|
||||
|
||||
/**
|
||||
* With this you can add data to the level container
|
||||
@@ -41,7 +41,7 @@ public interface LevelContainer
|
||||
* @param posZ z position in the detail level
|
||||
* @return true if correctly added, false otherwise
|
||||
*/
|
||||
boolean addVerticalData(long[] data, int posX, int posZ);
|
||||
boolean addVerticalData(int[] color, int[] data, byte[] flags, int posX, int posZ);
|
||||
|
||||
/**
|
||||
* With this you can add data to the level container
|
||||
@@ -50,25 +50,18 @@ public interface LevelContainer
|
||||
* @param posZ z position in the detail level
|
||||
* @return true if correctly added, false otherwise
|
||||
*/
|
||||
boolean addSingleData(long data, int posX, int posZ);
|
||||
|
||||
/**
|
||||
* With this you can get data from the level container
|
||||
* @param posX x position in the detail level
|
||||
* @param posZ z position in the detail level
|
||||
* @return the data in long array format
|
||||
*/
|
||||
long getData(int posX, int posZ, int index);
|
||||
|
||||
/**
|
||||
* With this you can get data from the level container
|
||||
* @param posX x position in the detail level
|
||||
* @param posZ z position in the detail level
|
||||
* @return the data in long array format
|
||||
*/
|
||||
long getSingleData(int posX, int posZ);
|
||||
boolean addSingleData(int color, int data, byte flags, int posX, int posZ);
|
||||
|
||||
int getColor(int posX, int posZ, int verticalIndex);
|
||||
|
||||
int getData(int posX, int posZ, int index);
|
||||
|
||||
byte getFlags(int posX, int posZ, int index);
|
||||
|
||||
byte getSingleFlags(int posX, int posZ);
|
||||
|
||||
/**
|
||||
* data is returned to ThreadMapUtil variables
|
||||
* @param posX x position in the detail level
|
||||
* @param posZ z position in the detail level
|
||||
* @return true only if the data exist
|
||||
|
||||
@@ -30,12 +30,7 @@ import com.seibel.lod.core.enums.config.VerticalQuality;
|
||||
import com.seibel.lod.core.handlers.LodDimensionFileHandler;
|
||||
import com.seibel.lod.core.objects.PosToGenerateContainer;
|
||||
import com.seibel.lod.core.objects.PosToRenderContainer;
|
||||
import com.seibel.lod.core.util.DataPointUtil;
|
||||
import com.seibel.lod.core.util.DetailDistanceUtil;
|
||||
import com.seibel.lod.core.util.LevelPosUtil;
|
||||
import com.seibel.lod.core.util.LodThreadFactory;
|
||||
import com.seibel.lod.core.util.LodUtil;
|
||||
import com.seibel.lod.core.util.SingletonHandler;
|
||||
import com.seibel.lod.core.util.*;
|
||||
import com.seibel.lod.core.wrapperInterfaces.IWrapperFactory;
|
||||
import com.seibel.lod.core.wrapperInterfaces.chunk.AbstractChunkPosWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
|
||||
@@ -128,7 +123,7 @@ public class LodDimension
|
||||
// connected to server
|
||||
|
||||
saveDir = new File(MC.getGameDirectory().getCanonicalFile().getPath() +
|
||||
File.separatorChar + "lod server data" + File.separatorChar + MC.getCurrentDimensionId());
|
||||
File.separatorChar + "Distant_Horizons_server_data" + File.separatorChar + MC.getCurrentDimensionId());
|
||||
}
|
||||
|
||||
fileHandler = new LodDimensionFileHandler(saveDir, this);
|
||||
@@ -445,7 +440,7 @@ public class LodDimension
|
||||
* stored in the LOD. If an LOD already exists at the given
|
||||
* coordinate it will be overwritten.
|
||||
*/
|
||||
public Boolean addData(byte detailLevel, int posX, int posZ, int verticalIndex, long data, boolean dontSave)
|
||||
public Boolean addData(byte detailLevel, int posX, int posZ, int verticalIndex, int color, int data, byte flags, boolean dontSave)
|
||||
{
|
||||
int regionPosX = LevelPosUtil.getRegion(detailLevel, posX);
|
||||
int regionPosZ = LevelPosUtil.getRegion(detailLevel, posZ);
|
||||
@@ -455,7 +450,7 @@ public class LodDimension
|
||||
if (region == null)
|
||||
return false;
|
||||
|
||||
boolean nodeAdded = region.addData(detailLevel, posX, posZ, verticalIndex, data);
|
||||
boolean nodeAdded = region.addData(detailLevel, posX, posZ, verticalIndex, color, data, flags);
|
||||
|
||||
// only save valid LODs to disk
|
||||
if (!dontSave && fileHandler != null)
|
||||
@@ -487,7 +482,7 @@ public class LodDimension
|
||||
* stored in the LOD. If an LOD already exists at the given
|
||||
* coordinate it will be overwritten.
|
||||
*/
|
||||
public Boolean addVerticalData(byte detailLevel, int posX, int posZ, long[] data, boolean dontSave)
|
||||
public Boolean addVerticalData(byte detailLevel, int posX, int posZ, int[] color, int[] data, byte[] flags, boolean dontSave)
|
||||
{
|
||||
int regionPosX = LevelPosUtil.getRegion(detailLevel, posX);
|
||||
int regionPosZ = LevelPosUtil.getRegion(detailLevel, posZ);
|
||||
@@ -497,7 +492,7 @@ public class LodDimension
|
||||
if (region == null)
|
||||
return false;
|
||||
|
||||
boolean nodeAdded = region.addVerticalData(detailLevel, posX, posZ, data);
|
||||
boolean nodeAdded = region.addVerticalData(detailLevel, posX, posZ, color, data, flags);
|
||||
|
||||
// only save valid LODs to disk
|
||||
if (!dontSave && fileHandler != null)
|
||||
@@ -566,7 +561,9 @@ public class LodDimension
|
||||
byte detailLevel;
|
||||
int posX;
|
||||
int posZ;
|
||||
long data;
|
||||
int color;
|
||||
int data;
|
||||
byte flags;
|
||||
int numbChunksWide = (width) * 32;
|
||||
int circleLimit = Integer.MAX_VALUE;
|
||||
|
||||
@@ -614,11 +611,11 @@ public class LodDimension
|
||||
posX = LevelPosUtil.convert(LodUtil.CHUNK_DETAIL_LEVEL, xChunkToCheck, detailLevel);
|
||||
posZ = LevelPosUtil.convert(LodUtil.CHUNK_DETAIL_LEVEL, zChunkToCheck, detailLevel);
|
||||
|
||||
data = getSingleData(detailLevel, posX, posZ);
|
||||
flags = getSingleFlags(detailLevel, posX, posZ);
|
||||
|
||||
//we will generate the position only if the current generation complexity is lower than the target one.
|
||||
//an un-generated area will always have 0 generation
|
||||
if (DataPointUtil.getGenerationMode(data) < complexity)
|
||||
if (DataPointUtil.getGenerationMode(flags) < complexity)
|
||||
{
|
||||
posToGenerate.addPosToGenerate(detailLevel, posX, posZ);
|
||||
if (maxDataToGenerate >= 0)
|
||||
@@ -680,8 +677,13 @@ public class LodDimension
|
||||
int playerPosZ)
|
||||
{
|
||||
LodRegion region = getRegion(regionPos.x, regionPos.z);
|
||||
|
||||
// use FAR_FIRST on local worlds and NEAR_FIRST on servers
|
||||
GenerationPriority generationPriority = CONFIG.client().worldGenerator().getGenerationPriority() == GenerationPriority.AUTO && MC.hasSinglePlayerServer() ? GenerationPriority.FAR_FIRST : GenerationPriority.NEAR_FIRST;
|
||||
boolean requireCorrectDetailLevel = generationPriority == GenerationPriority.NEAR_FIRST;
|
||||
|
||||
if (region != null)
|
||||
region.getPosToRender(posToRender, playerPosX, playerPosZ, CONFIG.client().worldGenerator().getGenerationPriority() == GenerationPriority.NEAR_FIRST);
|
||||
region.getPosToRender(posToRender, playerPosX, playerPosZ, requireCorrectDetailLevel);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -700,43 +702,52 @@ public class LodDimension
|
||||
return region.getMaxVerticalData(detailLevel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the data point at the given X and Z coordinates
|
||||
* in this dimension.
|
||||
* <br>
|
||||
* Returns null if the LodChunk doesn't exist or
|
||||
* is outside the loaded area.
|
||||
*/
|
||||
public long getData(byte detailLevel, int posX, int posZ, int verticalIndex)
|
||||
public int getColor(byte detailLevel, int posX, int posZ, int verticalIndex)
|
||||
{
|
||||
if (detailLevel > LodUtil.REGION_DETAIL_LEVEL)
|
||||
throw new IllegalArgumentException("getLodFromCoordinates given a level of \"" + detailLevel + "\" when \"" + LodUtil.REGION_DETAIL_LEVEL + "\" is the max.");
|
||||
|
||||
LodRegion region = getRegion(detailLevel, posX, posZ);
|
||||
if (region == null)
|
||||
return DataPointUtil.EMPTY_DATA;
|
||||
|
||||
return region.getData(detailLevel, posX, posZ, verticalIndex);
|
||||
return 0;
|
||||
else
|
||||
return region.getColor(detailLevel, posX, posZ, verticalIndex);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the data point at the given X and Z coordinates
|
||||
* in this dimension.
|
||||
* <br>
|
||||
* Returns null if the LodChunk doesn't exist or
|
||||
* is outside the loaded area.
|
||||
*/
|
||||
public long getSingleData(byte detailLevel, int posX, int posZ)
|
||||
public int getData(byte detailLevel, int posX, int posZ, int verticalIndex)
|
||||
{
|
||||
if (detailLevel > LodUtil.REGION_DETAIL_LEVEL)
|
||||
throw new IllegalArgumentException("getLodFromCoordinates given a level of \"" + detailLevel + "\" when \"" + LodUtil.REGION_DETAIL_LEVEL + "\" is the max.");
|
||||
|
||||
LodRegion region = getRegion(detailLevel, posX, posZ);
|
||||
if (region == null)
|
||||
return DataPointUtil.EMPTY_DATA;
|
||||
return 0;
|
||||
else
|
||||
return region.getData(detailLevel, posX, posZ, verticalIndex);
|
||||
}
|
||||
|
||||
public byte getFlags(byte detailLevel, int posX, int posZ, int verticalIndex)
|
||||
{
|
||||
if (detailLevel > LodUtil.REGION_DETAIL_LEVEL)
|
||||
throw new IllegalArgumentException("getLodFromCoordinates given a level of \"" + detailLevel + "\" when \"" + LodUtil.REGION_DETAIL_LEVEL + "\" is the max.");
|
||||
|
||||
return region.getSingleData(detailLevel, posX, posZ);
|
||||
LodRegion region = getRegion(detailLevel, posX, posZ);
|
||||
if (region == null)
|
||||
return 0;
|
||||
else
|
||||
return region.getFlags(detailLevel, posX, posZ, verticalIndex);
|
||||
}
|
||||
|
||||
public byte getSingleFlags(byte detailLevel, int posX, int posZ)
|
||||
{
|
||||
if (detailLevel > LodUtil.REGION_DETAIL_LEVEL)
|
||||
throw new IllegalArgumentException("getLodFromCoordinates given a level of \"" + detailLevel + "\" when \"" + LodUtil.REGION_DETAIL_LEVEL + "\" is the max.");
|
||||
|
||||
LodRegion region = getRegion(detailLevel, posX, posZ);
|
||||
if (region == null)
|
||||
return (byte) 0;
|
||||
else
|
||||
return region.getSingleFlags(detailLevel, posX, posZ);
|
||||
}
|
||||
|
||||
/** Clears the given region */
|
||||
|
||||
@@ -154,7 +154,7 @@ public class LodRegion
|
||||
* TODO this will always return true unless it has
|
||||
* @return true if the data was added successfully
|
||||
*/
|
||||
public boolean addData(byte detailLevel, int posX, int posZ, int verticalIndex, long data)
|
||||
public boolean addData(byte detailLevel, int posX, int posZ, int verticalIndex, int color, int data, byte flags)
|
||||
{
|
||||
posX = LevelPosUtil.getRegionModule(detailLevel, posX);
|
||||
posZ = LevelPosUtil.getRegionModule(detailLevel, posZ);
|
||||
@@ -166,7 +166,7 @@ public class LodRegion
|
||||
this.dataContainer[detailLevel] = new VerticalLevelContainer(detailLevel);
|
||||
}
|
||||
|
||||
this.dataContainer[detailLevel].addData(data, posX, posZ, verticalIndex);
|
||||
this.dataContainer[detailLevel].addData(color, data, flags, posX, posZ, verticalIndex);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -177,7 +177,7 @@ public class LodRegion
|
||||
* TODO this will always return true unless it has
|
||||
* @return true if the data was added successfully
|
||||
*/
|
||||
public boolean addVerticalData(byte detailLevel, int posX, int posZ, long[] data)
|
||||
public boolean addVerticalData(byte detailLevel, int posX, int posZ, int[] color, int[] data, byte[] flags)
|
||||
{
|
||||
//position is already relative
|
||||
//posX = LevelPosUtil.getRegionModule(detailLevel, posX);
|
||||
@@ -188,29 +188,35 @@ public class LodRegion
|
||||
if (this.dataContainer[detailLevel] == null)
|
||||
this.dataContainer[detailLevel] = new VerticalLevelContainer(detailLevel);
|
||||
|
||||
return this.dataContainer[detailLevel].addVerticalData(data, posX, posZ);
|
||||
return this.dataContainer[detailLevel].addVerticalData(color, data, flags, posX, posZ);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the dataPoint at the given relative position.
|
||||
* @return the data at the relative pos and detail level,
|
||||
* 0 if the data doesn't exist.
|
||||
*/
|
||||
public long getData(byte detailLevel, int posX, int posZ, int verticalIndex)
|
||||
public int getColor(byte detailLevel, int posX, int posZ, int verticalIndex)
|
||||
{
|
||||
return dataContainer[detailLevel].getColor(posX, posZ, verticalIndex);
|
||||
}
|
||||
|
||||
public int getData(byte detailLevel, int posX, int posZ, int verticalIndex)
|
||||
{
|
||||
return dataContainer[detailLevel].getData(posX, posZ, verticalIndex);
|
||||
}
|
||||
|
||||
public byte getFlags(byte detailLevel, int posX, int posZ, int verticalIndex)
|
||||
{
|
||||
return dataContainer[detailLevel].getFlags(posX, posZ, verticalIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the dataPoint at the given relative position.
|
||||
* Get the flags at the given relative position.
|
||||
* @return the data at the relative pos and detail level,
|
||||
* 0 if the data doesn't exist.
|
||||
*/
|
||||
public long getSingleData(byte detailLevel, int posX, int posZ)
|
||||
public byte getSingleFlags(byte detailLevel, int posX, int posZ)
|
||||
{
|
||||
return dataContainer[detailLevel].getSingleData(posX, posZ);
|
||||
return dataContainer[detailLevel].getSingleFlags(posX, posZ);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Clears the datapoint at the given relative position
|
||||
*/
|
||||
@@ -358,6 +364,7 @@ public class LodRegion
|
||||
posZ + regionPosZ * size);
|
||||
}
|
||||
else
|
||||
{
|
||||
//if (desiredLevel > detailLevel)
|
||||
//{
|
||||
// we have gone beyond the target Detail level
|
||||
@@ -408,6 +415,7 @@ public class LodRegion
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -479,7 +487,7 @@ public class LodRegion
|
||||
if (dataContainer[detailLevel].doesItExist(posX, posZ))
|
||||
// We take the bottom information always
|
||||
// TODO what does that mean? bottom of what?
|
||||
return DataPointUtil.getGenerationMode(dataContainer[detailLevel].getSingleData(posX, posZ));
|
||||
return DataPointUtil.getGenerationMode(dataContainer[detailLevel].getSingleFlags(posX, posZ));
|
||||
else
|
||||
return DistanceGenerationMode.NONE.complexity;
|
||||
}
|
||||
|
||||
@@ -37,14 +37,19 @@ public class VerticalLevelContainer implements LevelContainer
|
||||
public final int size;
|
||||
public final int maxVerticalData;
|
||||
|
||||
public final long[] dataContainer;
|
||||
public final int[] dataContainerColor;
|
||||
public final int[] dataContainerData;
|
||||
public final byte[] dataContainerFlags;
|
||||
|
||||
public VerticalLevelContainer(byte detailLevel)
|
||||
{
|
||||
this.detailLevel = detailLevel;
|
||||
size = 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel);
|
||||
maxVerticalData = DetailDistanceUtil.getMaxVerticalData(detailLevel);
|
||||
dataContainer = new long[size * size * DetailDistanceUtil.getMaxVerticalData(detailLevel)];
|
||||
final int i = size * size * maxVerticalData;
|
||||
dataContainerColor = new int[i];
|
||||
dataContainerData = new int[i];
|
||||
dataContainerFlags = new byte[i];
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -60,47 +65,77 @@ public class VerticalLevelContainer implements LevelContainer
|
||||
posZ = LevelPosUtil.getRegionModule(detailLevel, posZ);
|
||||
for (int verticalIndex = 0; verticalIndex < maxVerticalData; verticalIndex++)
|
||||
{
|
||||
dataContainer[posX * size * maxVerticalData + posZ * maxVerticalData + verticalIndex] = DataPointUtil.EMPTY_DATA;
|
||||
final int i = (posX * size + posZ) * maxVerticalData + verticalIndex;
|
||||
dataContainerColor[i] = 0;
|
||||
dataContainerData[i] = 0;
|
||||
dataContainerFlags[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addData(long data, int posX, int posZ, int verticalIndex)
|
||||
public boolean addData(int color, int data, byte flags, int posX, int posZ, int verticalIndex)
|
||||
{
|
||||
posX = LevelPosUtil.getRegionModule(detailLevel, posX);
|
||||
posZ = LevelPosUtil.getRegionModule(detailLevel, posZ);
|
||||
dataContainer[posX * size * maxVerticalData + posZ * maxVerticalData + verticalIndex] = data;
|
||||
final int i = (posX * size + posZ) * maxVerticalData + verticalIndex;
|
||||
dataContainerColor[i] = color;
|
||||
dataContainerData[i] = data;
|
||||
dataContainerFlags[i] = flags;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addVerticalData(long[] data, int posX, int posZ)
|
||||
public boolean addVerticalData(int[] color, int[] data, byte[] flags, int posX, int posZ)
|
||||
{
|
||||
posX = LevelPosUtil.getRegionModule(detailLevel, posX);
|
||||
posZ = LevelPosUtil.getRegionModule(detailLevel, posZ);
|
||||
for (int verticalIndex = 0; verticalIndex < maxVerticalData; verticalIndex++)
|
||||
dataContainer[posX * size * maxVerticalData + posZ * maxVerticalData + verticalIndex] = data[verticalIndex];
|
||||
{
|
||||
final int i = (posX * size + posZ) * maxVerticalData + verticalIndex;
|
||||
dataContainerColor[i] = color[verticalIndex];
|
||||
dataContainerData[i] = data[verticalIndex];
|
||||
dataContainerFlags[i] = flags[verticalIndex];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addSingleData(long data, int posX, int posZ)
|
||||
public boolean addSingleData(int color, int data, byte flags, int posX, int posZ)
|
||||
{
|
||||
return addData(data, posX, posZ, 0);
|
||||
return addData(color, data, flags, posX, posZ, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getData(int posX, int posZ, int verticalIndex)
|
||||
public int getColor(int posX, int posZ, int verticalIndex)
|
||||
{
|
||||
posX = LevelPosUtil.getRegionModule(detailLevel, posX);
|
||||
posZ = LevelPosUtil.getRegionModule(detailLevel, posZ);
|
||||
return dataContainer[posX * size * maxVerticalData + posZ * maxVerticalData + verticalIndex];
|
||||
return dataContainerColor[(posX * size + posZ) * maxVerticalData + verticalIndex];
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getData(int posX, int posZ, int verticalIndex)
|
||||
{
|
||||
posX = LevelPosUtil.getRegionModule(detailLevel, posX);
|
||||
posZ = LevelPosUtil.getRegionModule(detailLevel, posZ);
|
||||
return dataContainerData[(posX * size + posZ) * maxVerticalData + verticalIndex];
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSingleData(int posX, int posZ)
|
||||
public byte getFlags(int posX, int posZ, int verticalIndex)
|
||||
{
|
||||
return getData(posX, posZ, 0);
|
||||
posX = LevelPosUtil.getRegionModule(detailLevel, posX);
|
||||
posZ = LevelPosUtil.getRegionModule(detailLevel, posZ);
|
||||
return dataContainerFlags[(posX * size + posZ) * maxVerticalData + verticalIndex];
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getSingleFlags(int posX, int posZ)
|
||||
{
|
||||
posX = LevelPosUtil.getRegionModule(detailLevel, posX);
|
||||
posZ = LevelPosUtil.getRegionModule(detailLevel, posZ);
|
||||
return dataContainerFlags[(posX * size + posZ) * maxVerticalData];
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -119,28 +154,139 @@ public class VerticalLevelContainer implements LevelContainer
|
||||
{
|
||||
posX = LevelPosUtil.getRegionModule(detailLevel, posX);
|
||||
posZ = LevelPosUtil.getRegionModule(detailLevel, posZ);
|
||||
return DataPointUtil.doesItExist(getSingleData(posX, posZ));
|
||||
return DataPointUtil.doesItExist(dataContainerFlags[(posX * size + posZ) * maxVerticalData]);
|
||||
}
|
||||
|
||||
public VerticalLevelContainer(byte[] inputData)
|
||||
public VerticalLevelContainer(byte[] inputData, int version)
|
||||
{
|
||||
int tempMaxVerticalData;
|
||||
int tempIndex;
|
||||
int index = 0;
|
||||
long newData;
|
||||
detailLevel = inputData[index];
|
||||
index++;
|
||||
maxVerticalData = inputData[index] & 0b01111111;
|
||||
tempMaxVerticalData = inputData[index] & 0b01111111;
|
||||
index++;
|
||||
size = 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel);
|
||||
int x = size * size * maxVerticalData;
|
||||
this.dataContainer = new long[x];
|
||||
for (int i = 0; i < x; i++)
|
||||
int x = size * size * tempMaxVerticalData;
|
||||
int[] tempDataContainerColor = new int[x];
|
||||
int[] tempDataContainerData = new int[x];
|
||||
byte[] tempDataContainerFlags = new byte[x];
|
||||
|
||||
if (version == 6)
|
||||
{
|
||||
newData = 0;
|
||||
for (tempIndex = 0; tempIndex < 8; tempIndex++)
|
||||
newData += (((long) inputData[index + tempIndex]) & 0xff) << (8 * tempIndex);
|
||||
index += 8;
|
||||
dataContainer[i] = newData;
|
||||
long oldData;
|
||||
for (int i = 0; i < x; i++)
|
||||
{
|
||||
oldData = 0;
|
||||
for (tempIndex = 0; tempIndex < 8; tempIndex++)
|
||||
oldData += (((long) inputData[index + tempIndex]) & 0xff) << (8 * tempIndex);
|
||||
index += 8;
|
||||
/*
|
||||
|a |a |a |a |r |r |r |r |
|
||||
|r |r |r |r |g |g |g |g |
|
||||
|g |g |g |g |b |b |b |b |
|
||||
|b |b |b |b |h |h |h |h |
|
||||
|h |h |h |h |h |h |d |d |
|
||||
|d |d |d |d |d |d |d |d |
|
||||
|bl |bl |bl |bl |sl |sl |sl |sl |
|
||||
|l |l |f |g |g |g |v |e |
|
||||
*/
|
||||
DataPointUtil.createDataPoint(
|
||||
(int)((oldData >> 60) << 4) + 15,
|
||||
(int)(oldData >> 52) & 0xFF,
|
||||
(int)(oldData >> 44) & 0xFF,
|
||||
(int)(oldData >> 36) & 0xFF,
|
||||
(int)(oldData >> 26) & 0x3FF - DataPointUtil.VERTICAL_OFFSET,
|
||||
(int)(oldData >> 16) & 0x3FF - DataPointUtil.VERTICAL_OFFSET,
|
||||
(int)(oldData >> 8) & 0xF,
|
||||
(int)(oldData >> 12) & 0xF,
|
||||
(int)(oldData >> 5) & 0x1,
|
||||
((oldData >> 5) & 0x1) == 1
|
||||
);
|
||||
tempDataContainerColor[i] = ThreadMapUtil.dataPointColor;
|
||||
tempDataContainerData[i] = ThreadMapUtil.dataPointData;
|
||||
tempDataContainerFlags[i] = ThreadMapUtil.dataPointFlags;
|
||||
}
|
||||
}
|
||||
else if (version == 7)
|
||||
{
|
||||
long oldData;
|
||||
for (int i = 0; i < x; i++)
|
||||
{
|
||||
oldData = 0;
|
||||
for (tempIndex = 0; tempIndex < 8; tempIndex++)
|
||||
oldData += (((long) inputData[index + tempIndex]) & 0xff) << (8 * tempIndex);
|
||||
index += 8;
|
||||
DataPointUtil.createDataPoint(
|
||||
(int)((oldData >> 60) << 4) + 15,
|
||||
(int)(oldData >> 52) & 0xFF,
|
||||
(int)(oldData >> 44) & 0xFF,
|
||||
(int)(oldData >> 36) & 0xFF,
|
||||
(int)(oldData >> 26) & 0x3FF - DataPointUtil.VERTICAL_OFFSET - 64,
|
||||
(int)(oldData >> 16) & 0x3FF - DataPointUtil.VERTICAL_OFFSET - 64,
|
||||
(int)(oldData >> 8) & 0xF,
|
||||
(int)(oldData >> 12) & 0xF,
|
||||
(int)(oldData >> 5) & 0x1,
|
||||
((oldData >> 5) & 0x1) == 1
|
||||
);
|
||||
tempDataContainerColor[i] = ThreadMapUtil.dataPointColor;
|
||||
tempDataContainerData[i] = ThreadMapUtil.dataPointData;
|
||||
tempDataContainerFlags[i] = ThreadMapUtil.dataPointFlags;
|
||||
}
|
||||
}
|
||||
else //if (version == 8)
|
||||
{
|
||||
int color;
|
||||
int data;
|
||||
for (int i = 0; i < x; i++)
|
||||
{
|
||||
byte flags = inputData[index];
|
||||
index++;
|
||||
data = 0;
|
||||
color = 0;
|
||||
for (tempIndex = 0; tempIndex < 4; tempIndex++)
|
||||
{
|
||||
data += (((int) inputData[index + tempIndex]) & 0xff) << (8 * tempIndex);
|
||||
color += (((int) inputData[index + tempIndex + 4]) & 0xff) << (8 * tempIndex);
|
||||
}
|
||||
index += 8;
|
||||
|
||||
tempDataContainerColor[i] = color;
|
||||
tempDataContainerData[i] = data;
|
||||
tempDataContainerFlags[i] = flags;
|
||||
}
|
||||
}
|
||||
|
||||
if (tempMaxVerticalData > DetailDistanceUtil.getMaxVerticalData(detailLevel))
|
||||
{
|
||||
int tempMaxVerticalData2 = DetailDistanceUtil.getMaxVerticalData(detailLevel);
|
||||
int[] dataToMergeColor = new int[tempMaxVerticalData];
|
||||
int[] dataToMergeData = new int[tempMaxVerticalData];
|
||||
byte[] dataToMergeFlags = new byte[tempMaxVerticalData];
|
||||
int[] tempDataContainer2Color = new int[size * size * tempMaxVerticalData2];
|
||||
int[] tempDataContainer2Data = new int[size * size * tempMaxVerticalData2];
|
||||
byte[] tempDataContainer2Flags = new byte[size * size * tempMaxVerticalData2];
|
||||
for (int i = 0; i < size * size; i++)
|
||||
{
|
||||
System.arraycopy(tempDataContainerColor, i * tempMaxVerticalData, dataToMergeColor, 0, tempMaxVerticalData);
|
||||
System.arraycopy(tempDataContainerData, i * tempMaxVerticalData, dataToMergeData, 0, tempMaxVerticalData);
|
||||
System.arraycopy(tempDataContainerFlags, i * tempMaxVerticalData, dataToMergeFlags, 0, tempMaxVerticalData);
|
||||
DataPointUtil.mergeMultiData(dataToMergeColor, dataToMergeData, dataToMergeFlags, tempMaxVerticalData, tempMaxVerticalData2);
|
||||
System.arraycopy(ThreadMapUtil.getRawVerticalDataArrayColor(), 0, tempDataContainer2Color, i * tempMaxVerticalData2, tempMaxVerticalData2);
|
||||
System.arraycopy(ThreadMapUtil.getRawVerticalDataArrayData(), 0, tempDataContainer2Data, i * tempMaxVerticalData2, tempMaxVerticalData2);
|
||||
System.arraycopy(ThreadMapUtil.getRawVerticalDataArrayFlags(), 0, tempDataContainer2Flags, i * tempMaxVerticalData2, tempMaxVerticalData2);
|
||||
}
|
||||
maxVerticalData = tempMaxVerticalData2;
|
||||
this.dataContainerColor = tempDataContainer2Color;
|
||||
this.dataContainerData = tempDataContainer2Data;
|
||||
this.dataContainerFlags = tempDataContainer2Flags;
|
||||
}
|
||||
else
|
||||
{
|
||||
maxVerticalData = tempMaxVerticalData;
|
||||
this.dataContainerColor = tempDataContainerColor;
|
||||
this.dataContainerData = tempDataContainerData;
|
||||
this.dataContainerFlags = tempDataContainerFlags;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,12 +300,13 @@ public class VerticalLevelContainer implements LevelContainer
|
||||
public void updateData(LevelContainer lowerLevelContainer, int posX, int posZ)
|
||||
{
|
||||
//We reset the array
|
||||
long[] dataToMerge = ThreadMapUtil.getVerticalUpdateArray(detailLevel);
|
||||
int[] dataToMergeColor = ThreadMapUtil.getVerticalUpdateArrayColor(detailLevel);
|
||||
int[] dataToMergeData = ThreadMapUtil.getVerticalUpdateArrayData(detailLevel);
|
||||
byte[] dataToMergeFlags = ThreadMapUtil.getVerticalUpdateArrayFlags(detailLevel);
|
||||
|
||||
int lowerMaxVertical = dataToMerge.length / 4;
|
||||
int lowerMaxVertical = dataToMergeFlags.length / 4;
|
||||
int childPosX;
|
||||
int childPosZ;
|
||||
long[] data;
|
||||
posX = LevelPosUtil.getRegionModule(detailLevel, posX);
|
||||
posZ = LevelPosUtil.getRegionModule(detailLevel, posZ);
|
||||
for (int x = 0; x <= 1; x++)
|
||||
@@ -169,12 +316,17 @@ public class VerticalLevelContainer implements LevelContainer
|
||||
childPosX = 2 * posX + x;
|
||||
childPosZ = 2 * posZ + z;
|
||||
for (int verticalIndex = 0; verticalIndex < lowerMaxVertical; verticalIndex++)
|
||||
dataToMerge[(z * 2 + x) * lowerMaxVertical + verticalIndex] = lowerLevelContainer.getData(childPosX, childPosZ, verticalIndex);
|
||||
{
|
||||
|
||||
final int i = (z * 2 + x) * lowerMaxVertical + verticalIndex;
|
||||
dataToMergeColor[i] = lowerLevelContainer.getColor(childPosX, childPosZ, verticalIndex);
|
||||
dataToMergeData[i] = lowerLevelContainer.getData(childPosX, childPosZ, verticalIndex);
|
||||
dataToMergeFlags[i] = lowerLevelContainer.getFlags(childPosX, childPosZ, verticalIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
data = DataPointUtil.mergeMultiData(dataToMerge, lowerMaxVertical, getMaxVerticalData());
|
||||
|
||||
addVerticalData(data, posX, posZ);
|
||||
DataPointUtil.mergeMultiData(dataToMergeColor, dataToMergeData, dataToMergeFlags, lowerMaxVertical, getMaxVerticalData());
|
||||
addVerticalData(ThreadMapUtil.getRawVerticalDataArrayColor(), ThreadMapUtil.getRawVerticalDataArrayData(), ThreadMapUtil.getRawVerticalDataArrayFlags(), posX, posZ);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -183,7 +335,8 @@ public class VerticalLevelContainer implements LevelContainer
|
||||
int index = 0;
|
||||
int x = size * size;
|
||||
int tempIndex;
|
||||
long current;
|
||||
int currentColor;
|
||||
int currentData;
|
||||
boolean allGenerated = true;
|
||||
byte[] tempData = ThreadMapUtil.getSaveContainer(detailLevel);
|
||||
|
||||
@@ -196,12 +349,18 @@ public class VerticalLevelContainer implements LevelContainer
|
||||
{
|
||||
for (j = 0; j < maxVerticalData; j++)
|
||||
{
|
||||
current = dataContainer[i * maxVerticalData + j];
|
||||
for (tempIndex = 0; tempIndex < 8; tempIndex++)
|
||||
tempData[index + tempIndex] = (byte) (current >>> (8 * tempIndex));
|
||||
currentColor = dataContainerColor[i * maxVerticalData + j];
|
||||
currentData = dataContainerData[i * maxVerticalData + j];
|
||||
tempData[index] = dataContainerFlags[i * maxVerticalData + j];
|
||||
index++;
|
||||
for (tempIndex = 0; tempIndex < 4; tempIndex++)
|
||||
{
|
||||
tempData[index + tempIndex] = (byte) (currentData >>> (8 * tempIndex));
|
||||
tempData[index + tempIndex + 4] = (byte) (currentColor >>> (8 * tempIndex));
|
||||
}
|
||||
index += 8;
|
||||
}
|
||||
if(!DataPointUtil.doesItExist(dataContainer[i]))
|
||||
if(!DataPointUtil.doesItExist(dataContainerFlags[i]))
|
||||
allGenerated = false;
|
||||
}
|
||||
if (allGenerated)
|
||||
|
||||
@@ -161,41 +161,11 @@ public class Mat4f
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder stringbuilder = new StringBuilder();
|
||||
stringbuilder.append("Matrix4f:\n");
|
||||
stringbuilder.append(this.m00);
|
||||
stringbuilder.append(" ");
|
||||
stringbuilder.append(this.m01);
|
||||
stringbuilder.append(" ");
|
||||
stringbuilder.append(this.m02);
|
||||
stringbuilder.append(" ");
|
||||
stringbuilder.append(this.m03);
|
||||
stringbuilder.append("\n");
|
||||
stringbuilder.append(this.m10);
|
||||
stringbuilder.append(" ");
|
||||
stringbuilder.append(this.m11);
|
||||
stringbuilder.append(" ");
|
||||
stringbuilder.append(this.m12);
|
||||
stringbuilder.append(" ");
|
||||
stringbuilder.append(this.m13);
|
||||
stringbuilder.append("\n");
|
||||
stringbuilder.append(this.m20);
|
||||
stringbuilder.append(" ");
|
||||
stringbuilder.append(this.m21);
|
||||
stringbuilder.append(" ");
|
||||
stringbuilder.append(this.m22);
|
||||
stringbuilder.append(" ");
|
||||
stringbuilder.append(this.m23);
|
||||
stringbuilder.append("\n");
|
||||
stringbuilder.append(this.m30);
|
||||
stringbuilder.append(" ");
|
||||
stringbuilder.append(this.m31);
|
||||
stringbuilder.append(" ");
|
||||
stringbuilder.append(this.m32);
|
||||
stringbuilder.append(" ");
|
||||
stringbuilder.append(this.m33);
|
||||
stringbuilder.append("\n");
|
||||
return stringbuilder.toString();
|
||||
return "Matrix4f:\n" +
|
||||
this.m00 + " " + this.m01 + " " + this.m02 + " " + this.m03 + "\n" +
|
||||
this.m10 + " " + this.m11 + " " + this.m12 + " " + this.m13 + "\n" +
|
||||
this.m20 + " " + this.m21 + " " + this.m22 + " " + this.m23 + "\n" +
|
||||
this.m30 + " " + this.m31 + " " + this.m32 + " " + this.m33 + "\n";
|
||||
}
|
||||
|
||||
|
||||
@@ -553,4 +523,21 @@ public class Mat4f
|
||||
this.m13 = y;
|
||||
this.m23 = z;
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the values that store the clipping planes.
|
||||
* Formula for calculating matrix values is the same that OpenGL uses when making matrices.
|
||||
*
|
||||
* @param nearClip New near clipping plane value.
|
||||
* @param farClip New far clipping plane value.
|
||||
*/
|
||||
public void setClipPlanes(float nearClip,float farClip)
|
||||
{
|
||||
//convert to matrix values, formula copied from a textbook / openGL specification.
|
||||
float matNearClip = -((farClip + nearClip) / (farClip - nearClip));
|
||||
float matFarClip = -((2 * farClip * nearClip) / (farClip - nearClip));
|
||||
//set new values for the clip planes.
|
||||
this.m22 = matNearClip;
|
||||
this.m23 = matFarClip;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,8 +25,6 @@ import java.nio.ByteOrder;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
@@ -53,7 +51,6 @@ public class LodBufferBuilder
|
||||
private int nextElementByte = 0;
|
||||
private int totalUploadedBytes = 0;
|
||||
private int vertices;
|
||||
@Nullable
|
||||
private LodVertexFormatElement currentElement;
|
||||
private int elementIndex;
|
||||
private int mode;
|
||||
@@ -97,9 +94,9 @@ public class LodBufferBuilder
|
||||
int j = i + roundUp(vertexSizeInBytes);
|
||||
//LOGGER.debug("Needed to grow BufferBuilder buffer: Old size {} bytes, new size {} bytes.", i, j);
|
||||
ByteBuffer bytebuffer = allocateByteBuffer(j);
|
||||
((Buffer) this.buffer).position(0);
|
||||
this.buffer.position(0);
|
||||
bytebuffer.put(this.buffer);
|
||||
((Buffer) bytebuffer).rewind();
|
||||
bytebuffer.rewind();
|
||||
this.buffer = bytebuffer;
|
||||
}
|
||||
}
|
||||
@@ -272,7 +269,7 @@ public class LodBufferBuilder
|
||||
this.switchFormat(LodVertexFormat);
|
||||
this.currentElement = LodVertexFormat.getElements().get(0);
|
||||
this.elementIndex = 0;
|
||||
((Buffer) this.buffer).clear();
|
||||
this.buffer.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -326,8 +323,7 @@ public class LodBufferBuilder
|
||||
ImmutableList<LodVertexFormatElement> immutablelist = this.format.getElements();
|
||||
this.elementIndex = (this.elementIndex + 1) % immutablelist.size();
|
||||
this.nextElementByte += this.currentElement.getByteSize();
|
||||
LodVertexFormatElement LodVertexFormatelement = immutablelist.get(this.elementIndex);
|
||||
this.currentElement = LodVertexFormatelement;
|
||||
this.currentElement = immutablelist.get(this.elementIndex);
|
||||
// if (LodVertexFormatelement.getUsage() == LodVertexFormatElement.Usage.PADDING)
|
||||
// {
|
||||
// this.nextElement();
|
||||
@@ -439,9 +435,9 @@ public class LodBufferBuilder
|
||||
public ByteBuffer getCleanedByteBuffer()
|
||||
{
|
||||
LodBufferBuilder.DrawState bufferbuilder$drawstate = this.vertexCounts.get(this.lastRenderedCountIndex++);
|
||||
((Buffer) this.buffer).position(this.totalUploadedBytes);
|
||||
this.buffer.position(this.totalUploadedBytes);
|
||||
this.totalUploadedBytes += bufferbuilder$drawstate.vertexCount() * bufferbuilder$drawstate.format().getVertexSize();
|
||||
((Buffer) this.buffer).limit(this.totalUploadedBytes);
|
||||
this.buffer.limit(this.totalUploadedBytes);
|
||||
if (this.lastRenderedCountIndex == this.vertexCounts.size() && this.vertices == 0)
|
||||
{
|
||||
this.clear();
|
||||
@@ -449,7 +445,7 @@ public class LodBufferBuilder
|
||||
|
||||
ByteBuffer bytebuffer = this.buffer.slice();
|
||||
bytebuffer.order(this.buffer.order()); // FORGE: Fix incorrect byte order
|
||||
((Buffer) this.buffer).clear();
|
||||
this.buffer.clear();
|
||||
return bytebuffer; // the original method also returned bufferbuilder$drawstate
|
||||
}
|
||||
|
||||
@@ -534,7 +530,7 @@ public class LodBufferBuilder
|
||||
public void putBulkData(ByteBuffer buffer)
|
||||
{
|
||||
ensureCapacity(buffer.limit() + this.format.getVertexSize());
|
||||
((Buffer) this.buffer).position(this.vertices * this.format.getVertexSize());
|
||||
this.buffer.position(this.vertices * this.format.getVertexSize());
|
||||
this.buffer.put(buffer);
|
||||
this.vertices += buffer.limit() / this.format.getVertexSize();
|
||||
this.nextElementByte += buffer.limit();
|
||||
|
||||
@@ -98,7 +98,7 @@ public class LodVertexFormat
|
||||
else if (obj != null && this.getClass() == obj.getClass())
|
||||
{
|
||||
LodVertexFormat vertexformat = (LodVertexFormat) obj;
|
||||
return this.vertexSize != vertexformat.vertexSize ? false : this.elements.equals(vertexformat.elements);
|
||||
return this.vertexSize == vertexformat.vertexSize && this.elements.equals(vertexformat.elements);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -71,7 +71,7 @@ public class LodVertexFormatElement
|
||||
|
||||
|
||||
|
||||
public static enum DataType
|
||||
public enum DataType
|
||||
{
|
||||
FLOAT(4, "Float", GL11.GL_FLOAT),
|
||||
UBYTE(1, "Unsigned Byte", GL11.GL_UNSIGNED_BYTE),
|
||||
@@ -85,7 +85,7 @@ public class LodVertexFormatElement
|
||||
private final String name;
|
||||
private final int glType;
|
||||
|
||||
private DataType(int sizeInBytes, String newName, int openGlDataType)
|
||||
DataType(int sizeInBytes, String newName, int openGlDataType)
|
||||
{
|
||||
this.size = sizeInBytes;
|
||||
this.name = newName;
|
||||
|
||||
+16
-8
@@ -17,19 +17,27 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.forge.wrappers;
|
||||
package com.seibel.lod.core.objects.rending;
|
||||
|
||||
import net.minecraft.world.gen.Heightmap;
|
||||
import com.seibel.lod.core.enums.rendering.FogDistance;
|
||||
import com.seibel.lod.core.enums.rendering.FogDrawMode;
|
||||
|
||||
/**
|
||||
* Stores any variables or code that
|
||||
* may be shared between wrapper objects.
|
||||
* This object is just a replacement for an array
|
||||
* to make things easier to understand in the LodRenderer.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 11-20-2021
|
||||
* @version 11-26-2021
|
||||
*/
|
||||
public class WrapperUtil
|
||||
public class LodFogConfig
|
||||
{
|
||||
/** If we ever need to use a heightmap for any reason, use this one. */
|
||||
public static final Heightmap.Type DEFAULT_HEIGHTMAP = Heightmap.Type.WORLD_SURFACE_WG;
|
||||
public FogDrawMode fogDrawMode;
|
||||
public FogDistance fogDistance;
|
||||
|
||||
|
||||
public float nearFogStart = 0;
|
||||
public float nearFogEnd = 0;
|
||||
|
||||
public float farFogStart = 0;
|
||||
public float farFogEnd = 0;
|
||||
}
|
||||
@@ -1,64 +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.core.objects.rending;
|
||||
|
||||
import com.seibel.lod.core.enums.rendering.FogDistance;
|
||||
import com.seibel.lod.core.enums.rendering.FogQuality;
|
||||
|
||||
/**
|
||||
* This object is just a replacement for an array
|
||||
* to make things easier to understand in the LodRenderer.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 7-03-2021
|
||||
*/
|
||||
public class NearFarFogSettings
|
||||
{
|
||||
public final NearOrFarSetting near = new NearOrFarSetting(FogDistance.NEAR);
|
||||
public final NearOrFarSetting far = new NearOrFarSetting(FogDistance.FAR);
|
||||
|
||||
/**
|
||||
* If true that means Minecraft is
|
||||
* rendering fog
|
||||
*/
|
||||
public boolean vanillaIsRenderingFog = true;
|
||||
|
||||
public NearFarFogSettings()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This holds all relevant data to rendering fog at either
|
||||
* near or far distances.
|
||||
*/
|
||||
public static class NearOrFarSetting
|
||||
{
|
||||
public FogQuality quality = FogQuality.FANCY;
|
||||
public FogDistance distance;
|
||||
|
||||
public NearOrFarSetting(FogDistance newFogDistance)
|
||||
{
|
||||
distance = newFogDistance;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,12 +19,14 @@
|
||||
|
||||
package com.seibel.lod.core.render;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
import org.lwjgl.opengl.GL;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL15;
|
||||
import org.lwjgl.opengl.GL20;
|
||||
import org.lwjgl.opengl.GL30;
|
||||
import org.lwjgl.opengl.GLCapabilities;
|
||||
@@ -32,10 +34,12 @@ import org.lwjgl.opengl.GLCapabilities;
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
import com.seibel.lod.core.ModInfo;
|
||||
import com.seibel.lod.core.api.ClientApi;
|
||||
import com.seibel.lod.core.enums.config.GpuUploadMethod;
|
||||
import com.seibel.lod.core.enums.rendering.GLProxyContext;
|
||||
import com.seibel.lod.core.render.shader.LodShader;
|
||||
import com.seibel.lod.core.render.shader.LodShaderProgram;
|
||||
import com.seibel.lod.core.util.SingletonHandler;
|
||||
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
|
||||
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftWrapper;
|
||||
|
||||
/**
|
||||
@@ -43,20 +47,24 @@ import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftWrapper;
|
||||
* and GPU capabilities.
|
||||
*
|
||||
* <p>
|
||||
* Helpful OpenGL resources: <br><br>
|
||||
* Helpful OpenGL resources:
|
||||
* <p>
|
||||
* https://www.seas.upenn.edu/~pcozzi/OpenGLInsights/OpenGLInsights-AsynchronousBufferTransfers.pdf <br>
|
||||
* https://learnopengl.com/Advanced-OpenGL/Advanced-Data <br>
|
||||
* https://gamedev.stackexchange.com/questions/91995/edit-vbo-data-or-create-a-new-one <br><br>
|
||||
* https://www.slideshare.net/CassEveritt/approaching-zero-driver-overhead <br><br>
|
||||
*
|
||||
* https://gamedev.stackexchange.com/questions/91995/edit-vbo-data-or-create-a-new-one <br>
|
||||
* https://stackoverflow.com/questions/63509735/massive-performance-loss-with-glmapbuffer <br><br>
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 11-21-2021
|
||||
* @version 12-1-2021
|
||||
*/
|
||||
public class GLProxy
|
||||
{
|
||||
private static final IMinecraftWrapper MC = SingletonHandler.get(IMinecraftWrapper.class);
|
||||
private static final ILodConfigWrapperSingleton CONFIG = SingletonHandler.get(ILodConfigWrapperSingleton.class);
|
||||
|
||||
private static ExecutorService workerThread = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder().setNameFormat(GLProxy.class.getSimpleName() + "-Worker-Thread").build());
|
||||
private static final ExecutorService workerThread = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder().setNameFormat(GLProxy.class.getSimpleName() + "-Worker-Thread").build());
|
||||
|
||||
|
||||
private static GLProxy instance = null;
|
||||
@@ -101,7 +109,7 @@ public class GLProxy
|
||||
// where the GL context is
|
||||
if (GLFW.glfwGetCurrentContext() == 0L)
|
||||
throw new IllegalStateException(GLProxy.class.getSimpleName() + " was created outside the render thread!");
|
||||
|
||||
|
||||
|
||||
|
||||
//============================//
|
||||
@@ -159,11 +167,9 @@ public class GLProxy
|
||||
|
||||
|
||||
// get specific capabilities
|
||||
// TODO re-add buffer storage support
|
||||
bufferStorageSupported = lodBuilderGlCapabilities.glBufferStorage != 0;
|
||||
mapBufferRangeSupported = lodBuilderGlCapabilities.glMapBufferRange != 0;
|
||||
|
||||
|
||||
// display the capabilities
|
||||
if (!bufferStorageSupported)
|
||||
{
|
||||
@@ -172,6 +178,43 @@ public class GLProxy
|
||||
}
|
||||
|
||||
|
||||
// if using AUTO gpuUpload
|
||||
// determine a good default for the GPU
|
||||
if (CONFIG.client().advanced().buffers().getGpuUploadMethod() == GpuUploadMethod.AUTO)
|
||||
{
|
||||
GpuUploadMethod uploadMethod;
|
||||
String vendor = GL15.glGetString(GL15.GL_VENDOR).toUpperCase(); // example return: "NVIDIA CORPORATION"
|
||||
if (vendor.contains("NVIDIA") || vendor.contains("GEFORCE"))
|
||||
{
|
||||
// NVIDIA card
|
||||
|
||||
if (bufferStorageSupported)
|
||||
{
|
||||
uploadMethod = GpuUploadMethod.BUFFER_STORAGE;
|
||||
}
|
||||
else
|
||||
{
|
||||
uploadMethod = GpuUploadMethod.SUB_DATA;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// AMD or Intel card
|
||||
|
||||
if (mapBufferRangeSupported)
|
||||
{
|
||||
uploadMethod = GpuUploadMethod.BUFFER_MAPPING;
|
||||
}
|
||||
else
|
||||
{
|
||||
uploadMethod = GpuUploadMethod.DATA;
|
||||
}
|
||||
}
|
||||
|
||||
CONFIG.client().advanced().buffers().setGpuUploadMethod(uploadMethod);
|
||||
ClientApi.LOGGER.info("GPU Vendor [" + vendor + "], Upload method set to [" + uploadMethod + "].");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -179,7 +222,6 @@ public class GLProxy
|
||||
// shader setup //
|
||||
//==============//
|
||||
|
||||
//setGlContext(GLProxyContext.LOD_RENDER);
|
||||
setGlContext(GLProxyContext.MINECRAFT);
|
||||
|
||||
createShaderProgram();
|
||||
@@ -213,13 +255,13 @@ public class GLProxy
|
||||
try
|
||||
{
|
||||
// get the shaders from the resource folder
|
||||
vertexShader = LodShader.loadShader(GL20.GL_VERTEX_SHADER, "shaders/unshaded.vert", false);
|
||||
fragmentShader = LodShader.loadShader(GL20.GL_FRAGMENT_SHADER, "shaders/unshaded.frag", false);
|
||||
vertexShader = LodShader.loadShader(GL20.GL_VERTEX_SHADER, "shaders" + File.separator + "standard.vert", false);
|
||||
fragmentShader = LodShader.loadShader(GL20.GL_FRAGMENT_SHADER, "shaders" + File.separator + "flat_shaded.frag", false);
|
||||
|
||||
// this can be used when testing shaders,
|
||||
// since we can't hot swap the files in the resource folder
|
||||
// vertexShader = LodShader.loadShader(GL20.GL_VERTEX_SHADER, "C:/Users/James Seibel/Desktop/shaders/unshaded.vert", true);
|
||||
// fragmentShader = LodShader.loadShader(GL20.GL_FRAGMENT_SHADER, "C:/Users/James Seibel/Desktop/shaders/unshaded.frag", true);
|
||||
// vertexShader = LodShader.loadShader(GL20.GL_VERTEX_SHADER, "C:/Users/James Seibel/Desktop/shaders/standard.vert", true);
|
||||
// fragmentShader = LodShader.loadShader(GL20.GL_FRAGMENT_SHADER, "C:/Users/James Seibel/Desktop/shaders/flat_shaded.frag", true);
|
||||
|
||||
|
||||
// create the shaders
|
||||
@@ -364,6 +406,29 @@ public class GLProxy
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If called from a legacy OpenGL context this will
|
||||
* set the fog end to infinity with a density of 0.
|
||||
* Effectively removing the fog.
|
||||
* <p>
|
||||
* This only works with Legacy OpenGL because James hasn't
|
||||
* looking into a way for it to work with Modern OpenGL.
|
||||
*/
|
||||
public void disableLegacyFog()
|
||||
{
|
||||
// make sure this is a legacy OpenGL context
|
||||
if (minecraftGlCapabilities.glFogf != 0)
|
||||
{
|
||||
// glFogf should only have an address if the current OpenGL
|
||||
// context can call it, and it should only be able to call it in
|
||||
// legacy OpenGL contexts; since it is disabled in Modern
|
||||
// OpenGL.
|
||||
|
||||
GL11.glFogf(GL11.GL_FOG_START, 0.0f);
|
||||
GL11.glFogf(GL11.GL_FOG_END, Float.MAX_VALUE);
|
||||
GL11.glFogf(GL11.GL_FOG_DENSITY, 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -19,20 +19,21 @@
|
||||
|
||||
package com.seibel.lod.core.render;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.util.HashSet;
|
||||
|
||||
import org.lwjgl.opengl.GL15;
|
||||
import org.lwjgl.opengl.GL20;
|
||||
import org.lwjgl.opengl.GL30;
|
||||
import org.lwjgl.opengl.NVFogDistance;
|
||||
|
||||
import com.seibel.lod.core.api.ApiShared;
|
||||
import com.seibel.lod.core.builders.bufferBuilding.LodBufferBuilderFactory;
|
||||
import com.seibel.lod.core.builders.bufferBuilding.LodBufferBuilderFactory.VertexBuffersAndOffset;
|
||||
import com.seibel.lod.core.enums.config.GpuUploadMethod;
|
||||
import com.seibel.lod.core.enums.rendering.DebugMode;
|
||||
import com.seibel.lod.core.enums.rendering.FogColorMode;
|
||||
import com.seibel.lod.core.enums.rendering.FogDistance;
|
||||
import com.seibel.lod.core.enums.rendering.FogDrawOverride;
|
||||
import com.seibel.lod.core.enums.rendering.FogQuality;
|
||||
import com.seibel.lod.core.enums.rendering.FogDrawMode;
|
||||
import com.seibel.lod.core.handlers.IReflectionHandler;
|
||||
import com.seibel.lod.core.objects.lod.LodDimension;
|
||||
import com.seibel.lod.core.objects.lod.RegionPos;
|
||||
@@ -40,7 +41,7 @@ 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.objects.opengl.LodVertexBuffer;
|
||||
import com.seibel.lod.core.objects.rending.NearFarFogSettings;
|
||||
import com.seibel.lod.core.objects.rending.LodFogConfig;
|
||||
import com.seibel.lod.core.render.shader.LodShaderProgram;
|
||||
import com.seibel.lod.core.util.DetailDistanceUtil;
|
||||
import com.seibel.lod.core.util.LevelPosUtil;
|
||||
@@ -50,32 +51,26 @@ 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.config.ILodConfigWrapperSingleton;
|
||||
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.minecraft.IProfilerWrapper;
|
||||
import com.seibel.lod.forge.wrappers.minecraft.MinecraftRenderWrapper;
|
||||
|
||||
/**
|
||||
* This is where all the magic happens. <br>
|
||||
* This is where LODs are draw to the world.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 11-8-2021
|
||||
* @version 11-27-2021
|
||||
*/
|
||||
public class LodRenderer
|
||||
{
|
||||
private static final IMinecraftWrapper MC = SingletonHandler.get(IMinecraftWrapper.class);
|
||||
private static final MinecraftRenderWrapper MC_RENDER = MinecraftRenderWrapper.INSTANCE;
|
||||
private static final IMinecraftRenderWrapper MC_RENDER = SingletonHandler.get(IMinecraftRenderWrapper.class);
|
||||
private static final ILodConfigWrapperSingleton CONFIG = SingletonHandler.get(ILodConfigWrapperSingleton.class);
|
||||
private static final IReflectionHandler REFLECTION_HANDLER = SingletonHandler.get(IReflectionHandler.class);
|
||||
private static final IWrapperFactory FACTORY = SingletonHandler.get(IWrapperFactory.class);
|
||||
|
||||
|
||||
// /**
|
||||
// * this is the light used when rendering the LODs,
|
||||
// * it should be something different from what is used by Minecraft
|
||||
// */
|
||||
// private static final int LOD_GL_LIGHT_NUMBER = GL15.GL_LIGHT2;
|
||||
|
||||
/**
|
||||
* If true the LODs colors will be replaced with
|
||||
* a checkerboard, this can be used for debugging.
|
||||
@@ -169,16 +164,19 @@ public class LodRenderer
|
||||
|
||||
if (MC_RENDER.playerHasBlindnessEffect())
|
||||
{
|
||||
// if the player is blind don't render LODs,
|
||||
// if the player is blind, don't render LODs,
|
||||
// and don't change minecraft's fog
|
||||
// which blindness relies on.
|
||||
return;
|
||||
}
|
||||
|
||||
if (CONFIG.client().graphics().fogQuality().getDisableVanillaFog())
|
||||
GLProxy.getInstance().disableLegacyFog();
|
||||
|
||||
|
||||
|
||||
// TODO move the buffer regeneration logic into its own class (probably called in the client proxy instead)
|
||||
|
||||
// TODO move the buffer regeneration logic into its own class (probably called in the client api instead)
|
||||
// starting here...
|
||||
determineIfLodsShouldRegenerate(lodDim, partialTicks);
|
||||
|
||||
@@ -203,7 +201,7 @@ public class LodRenderer
|
||||
partialRegen = false;
|
||||
}
|
||||
|
||||
// TODO move the buffer regeneration logic into its own class (probably called in the client proxy instead)
|
||||
// TODO move the buffer regeneration logic into its own class (probably called in the client api instead)
|
||||
// ...ending here
|
||||
|
||||
if (lodBufferBuilderFactory.newBuffersAvailable())
|
||||
@@ -243,7 +241,7 @@ public class LodRenderer
|
||||
int currentProgram = GL20.glGetInteger(GL20.GL_CURRENT_PROGRAM);
|
||||
|
||||
|
||||
Mat4f modelViewMatrix = offsetTheModelViewMatrix(mcModelViewMatrix, partialTicks);
|
||||
Mat4f modelViewMatrix = translateModelViewMatrix(mcModelViewMatrix, partialTicks);
|
||||
vanillaBlockRenderedDistance = MC_RENDER.getRenderDistance() * LodUtil.CHUNK_WIDTH;
|
||||
// required for setupFog and setupProjectionMatrix
|
||||
if (MC.getWrappedClientWorld().getDimensionType().hasCeiling())
|
||||
@@ -252,54 +250,23 @@ public class LodRenderer
|
||||
farPlaneBlockDistance = CONFIG.client().graphics().quality().getLodChunkRenderDistance() * LodUtil.CHUNK_WIDTH;
|
||||
|
||||
|
||||
Mat4f projectionMatrix = createProjectionMatrix(mcProjectionMatrix, vanillaBlockRenderedDistance, partialTicks);
|
||||
Mat4f projectionMatrix = createProjectionMatrix(mcProjectionMatrix, vanillaBlockRenderedDistance);
|
||||
|
||||
|
||||
// commented out until we can add shaders to handle lighting
|
||||
//setupLighting(lodDim, partialTicks);
|
||||
|
||||
|
||||
// // determine the current fog settings, so they can be
|
||||
// // reset after drawing the LODs
|
||||
// float defaultFogStartDist = GL15.glGetFloat(GL15.GL_FOG_START);
|
||||
// float defaultFogEndDist = GL15.glGetFloat(GL15.GL_FOG_END);
|
||||
// int defaultFogMode = GL15.glGetInteger(GL15.GL_FOG_MODE);
|
||||
// int defaultFogDistance = glProxy.fancyFogAvailable ? GL15.glGetInteger(NVFogDistance.GL_FOG_DISTANCE_MODE_NV) : -1;
|
||||
|
||||
//ShaderInstance mcShader = RenderSystem.getShader();
|
||||
|
||||
// NearFarFogSettings fogSettings = determineFogSettings();
|
||||
LodFogConfig fogSettings = determineFogConfig();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//===========//
|
||||
// rendering //
|
||||
//===========//
|
||||
|
||||
profiler.popPush("LOD draw");
|
||||
|
||||
if (vbos != null)
|
||||
{
|
||||
Vec3f cameraDir = MC_RENDER.getLookAtVector();
|
||||
|
||||
// TODO re-enable once rendering is totally working
|
||||
boolean cullingDisabled = true; //LodConfig.client().graphics.advancedGraphicsOption.disableDirectionalCulling.get();
|
||||
// boolean renderBufferStorage = config.client().graphics().advancedGraphics().getGpuUploadMethod() == GpuUploadMethod.BUFFER_STORAGE && glProxy.bufferStorageSupported;
|
||||
|
||||
// used to determine what type of fog to render
|
||||
// int halfWidth = vbos.length / 2;
|
||||
// int quarterWidth = vbos.length / 4;
|
||||
|
||||
// where the center of the built buffers is (needed when culling regions)
|
||||
RegionPos vboCenterRegionPos = new RegionPos(vbosCenter);
|
||||
|
||||
|
||||
|
||||
//==============//
|
||||
// shader setup //
|
||||
//==============//
|
||||
|
||||
// can be used when testing shaders
|
||||
//glProxy.createShaderProgram();
|
||||
// glProxy.createShaderProgram();
|
||||
|
||||
|
||||
LodShaderProgram shaderProgram = glProxy.lodShaderProgram;
|
||||
@@ -311,47 +278,89 @@ public class LodRenderer
|
||||
shaderProgram.enableVertexAttribute(posAttrib);
|
||||
int colAttrib = shaderProgram.getAttributeLocation("color");
|
||||
shaderProgram.enableVertexAttribute(colAttrib);
|
||||
|
||||
|
||||
|
||||
// upload the required uniforms
|
||||
// global uniforms
|
||||
int mvmUniform = shaderProgram.getUniformLocation("modelViewMatrix");
|
||||
shaderProgram.setUniform(mvmUniform, modelViewMatrix);
|
||||
int projUniform = shaderProgram.getUniformLocation("projectionMatrix");
|
||||
shaderProgram.setUniform(projUniform, projectionMatrix);
|
||||
|
||||
int cameraUniform = shaderProgram.getUniformLocation("cameraPos");
|
||||
shaderProgram.setUniform(cameraUniform, getTranslatedCameraPos());
|
||||
int fogColorUniform = shaderProgram.getUniformLocation("fogColor");
|
||||
shaderProgram.setUniform(fogColorUniform, getFogColor());
|
||||
|
||||
|
||||
// region dependent uniforms
|
||||
int fogEnabledUniform = shaderProgram.getUniformLocation("fogEnabled");
|
||||
int nearFogEnabledUniform = shaderProgram.getUniformLocation("nearFogEnabled");
|
||||
int farFogEnabledUniform = shaderProgram.getUniformLocation("farFogEnabled");
|
||||
// near
|
||||
int nearFogStartUniform = shaderProgram.getUniformLocation("nearFogStart");
|
||||
int nearFogEndUniform = shaderProgram.getUniformLocation("nearFogEnd");
|
||||
// far
|
||||
int farFogStartUniform = shaderProgram.getUniformLocation("farFogStart");
|
||||
int farFogEndUniform = shaderProgram.getUniformLocation("farFogEnd");
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//===========//
|
||||
// rendering //
|
||||
//===========//
|
||||
|
||||
profiler.popPush("LOD draw");
|
||||
|
||||
boolean cullingDisabled = CONFIG.client().graphics().advancedGraphics().getDisableDirectionalCulling();
|
||||
boolean renderBufferStorage = CONFIG.client().advanced().buffers().getGpuUploadMethod() == GpuUploadMethod.BUFFER_STORAGE && glProxy.bufferStorageSupported;
|
||||
|
||||
// where the center of the buffers is (needed when culling regions)
|
||||
RegionPos vboCenterRegionPos = new RegionPos(vbosCenter);
|
||||
RegionPos vboPos = new RegionPos();
|
||||
|
||||
|
||||
// render each of the buffers
|
||||
for (int x = 0; x < vbos.length; x++)
|
||||
{
|
||||
for (int z = 0; z < vbos.length; z++)
|
||||
{
|
||||
RegionPos vboPos = new RegionPos(
|
||||
x + vboCenterRegionPos.x - (lodDim.getWidth() / 2),
|
||||
z + vboCenterRegionPos.z - (lodDim.getWidth() / 2));
|
||||
vboPos.x = x + vboCenterRegionPos.x - (lodDim.getWidth() / 2);
|
||||
vboPos.z = z + vboCenterRegionPos.z - (lodDim.getWidth() / 2);
|
||||
|
||||
if (cullingDisabled || RenderUtil.isRegionInViewFrustum(MC_RENDER.getCameraBlockPosition(), cameraDir, vboPos.blockPos()))
|
||||
if (cullingDisabled || RenderUtil.isRegionInViewFrustum(MC_RENDER.getCameraBlockPosition(), MC_RENDER.getLookAtVector(), vboPos.blockPos()))
|
||||
{
|
||||
// TODO add fog to the fragment shader
|
||||
// if ((x > halfWidth - quarterWidth && x < halfWidth + quarterWidth)
|
||||
// && (z > halfWidth - quarterWidth && z < halfWidth + quarterWidth))
|
||||
// setupFog(fogSettings.near.distance, fogSettings.near.quality);
|
||||
// else
|
||||
// setupFog(fogSettings.far.distance, fogSettings.far.quality);
|
||||
// fog may be different from region to region
|
||||
applyFog(shaderProgram,
|
||||
fogSettings, fogEnabledUniform, nearFogEnabledUniform, farFogEnabledUniform,
|
||||
nearFogStartUniform, nearFogEndUniform, farFogStartUniform, farFogEndUniform);
|
||||
|
||||
|
||||
// actual rendering
|
||||
int bufferId = 0;
|
||||
for (int i = 0; i < vbos[x][z].length; i++)
|
||||
{
|
||||
bufferId = (storageBufferIds != null && renderBufferStorage) ? storageBufferIds[x][z][i] : vbos[x][z][i].id;
|
||||
drawArrays(bufferId, vbos[x][z][i].vertexCount, posAttrib, colAttrib);
|
||||
}
|
||||
|
||||
// if (storageBufferIds != null && renderBufferStorage)
|
||||
// for (int i = 0; i < storageBufferIds[x][z].length; i++)
|
||||
// drawArrays(storageBufferIds[x][z][i], vbos[x][z][i].vertexCount, posAttrib, colAttrib);
|
||||
// else
|
||||
for (int i = 0; i < vbos[x][z].length; i++)
|
||||
drawArrays(vbos[x][z][i].id, vbos[x][z][i].vertexCount, posAttrib, colAttrib);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
GL20.glDisableVertexAttribArray(posAttrib);
|
||||
GL20.glDisableVertexAttribArray(colAttrib);
|
||||
|
||||
|
||||
|
||||
//================//
|
||||
// render cleanup //
|
||||
//================//
|
||||
|
||||
// if this cleanup isn't done MC may crash
|
||||
// when trying to render its own terrain
|
||||
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
GL30.glBindVertexArray(0);
|
||||
|
||||
GL20.glDisableVertexAttribArray(posAttrib);
|
||||
GL20.glDisableVertexAttribArray(colAttrib);
|
||||
}
|
||||
|
||||
|
||||
@@ -368,16 +377,23 @@ public class LodRenderer
|
||||
GL15.glDisable(GL15.GL_BLEND); // TODO: what should this be reset to?
|
||||
|
||||
GL20.glUseProgram(currentProgram);
|
||||
//RenderSystem.setShader(() -> mcShader);
|
||||
|
||||
// clear the depth buffer so everything drawn is drawn
|
||||
// clear the depth buffer so everything is drawn
|
||||
// over the LODs
|
||||
GL15.glClear(GL15.GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
|
||||
|
||||
// end of internal LOD profiling
|
||||
profiler.pop();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/** This is where the actual drawing happens. */
|
||||
private void drawArrays(int glBufferId, int vertexCount, int posAttrib, int colAttrib)
|
||||
@@ -401,130 +417,84 @@ public class LodRenderer
|
||||
GL20.glEnableVertexAttribArray(colAttrib);
|
||||
GL20.glVertexAttribPointer(colAttrib, 4, GL15.GL_UNSIGNED_BYTE, true, vertexByteCount, Float.BYTES * 3);
|
||||
|
||||
|
||||
// draw the LODs
|
||||
GL30.glDrawArrays(GL30.GL_TRIANGLES, 0, vertexCount);
|
||||
|
||||
|
||||
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
GL30.glBindVertexArray(0);
|
||||
|
||||
GL20.glDisableVertexAttribArray(posAttrib);
|
||||
GL20.glDisableVertexAttribArray(colAttrib);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//=================//
|
||||
// Setup Functions //
|
||||
//=================//
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private void setupFog(FogDistance fogDistance, FogQuality fogQuality)
|
||||
|
||||
/** Create all buffers that will be used. */
|
||||
public void setupBuffers(LodDimension lodDim)
|
||||
{
|
||||
if (fogQuality == FogQuality.OFF)
|
||||
{
|
||||
GL15.glDisable(GL15.GL_FOG);
|
||||
return;
|
||||
}
|
||||
lodBufferBuilderFactory.setupBuffers(lodDim);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/** Return what fog settings should be used when rendering. */
|
||||
private LodFogConfig determineFogConfig()
|
||||
{
|
||||
LodFogConfig fogConfig = new LodFogConfig();
|
||||
|
||||
if (fogDistance == FogDistance.NEAR_AND_FAR)
|
||||
{
|
||||
throw new IllegalArgumentException("setupFog doesn't accept the NEAR_AND_FAR fog distance.");
|
||||
}
|
||||
|
||||
// determine the fog distance mode to use
|
||||
int glFogDistanceMode;
|
||||
if (fogQuality == FogQuality.FANCY)
|
||||
{
|
||||
// fancy fog (fragment distance based fog)
|
||||
glFogDistanceMode = NVFogDistance.GL_EYE_RADIAL_NV;
|
||||
}
|
||||
fogConfig.fogDrawMode = CONFIG.client().graphics().fogQuality().getFogDrawMode();
|
||||
if (fogConfig.fogDrawMode == FogDrawMode.USE_OPTIFINE_SETTING)
|
||||
fogConfig.fogDrawMode = REFLECTION_HANDLER.getFogDrawMode();
|
||||
|
||||
|
||||
// how different distances are drawn depends on the quality set
|
||||
fogConfig.fogDistance = CONFIG.client().graphics().fogQuality().getFogDistance();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// far fog //
|
||||
|
||||
if (CONFIG.client().graphics().fogQuality().getFogDistance() == FogDistance.NEAR_AND_FAR)
|
||||
fogConfig.farFogStart = farPlaneBlockDistance * 1.6f * 0.9f;
|
||||
else
|
||||
{
|
||||
// fast fog (frustum distance based fog)
|
||||
glFogDistanceMode = NVFogDistance.GL_EYE_PLANE_ABSOLUTE_NV;
|
||||
}
|
||||
// for more realistic fog when using FAR
|
||||
fogConfig.farFogStart = Math.min(vanillaBlockRenderedDistance * 1.5f, farPlaneBlockDistance * 0.9f * 1.6f);
|
||||
|
||||
// the multipliers are percentages
|
||||
// of the regular view distance.
|
||||
if (fogDistance == FogDistance.FAR)
|
||||
{
|
||||
// the reason that I wrote fogEnd then fogStart backwards
|
||||
// is because we are using fog backwards to how
|
||||
// it is normally used, with it hiding near objects
|
||||
// instead of far objects.
|
||||
|
||||
if (fogQuality == FogQuality.FANCY)
|
||||
{
|
||||
// for more realistic fog when using FAR
|
||||
if (CONFIG.client().graphics().fogQuality().getFogDistance() == FogDistance.NEAR_AND_FAR)
|
||||
GL15.glFogf(GL15.GL_FOG_START, farPlaneBlockDistance * 1.6f * 0.9f);
|
||||
else
|
||||
GL15.glFogf(GL15.GL_FOG_START, Math.min(vanillaBlockRenderedDistance * 1.5f, farPlaneBlockDistance * 0.9f * 1.6f));
|
||||
GL15.glFogf(GL15.GL_FOG_END, farPlaneBlockDistance * 1.6f);
|
||||
}
|
||||
else if (fogQuality == FogQuality.FAST)
|
||||
{
|
||||
// for the far fog of the normal chunks
|
||||
// to start right where the LODs' end use:
|
||||
// end = 0.8f, start = 1.5f
|
||||
GL15.glFogf(GL15.GL_FOG_START, farPlaneBlockDistance * 0.75f);
|
||||
GL15.glFogf(GL15.GL_FOG_END, farPlaneBlockDistance * 1.0f);
|
||||
}
|
||||
}
|
||||
else if (fogDistance == FogDistance.NEAR)
|
||||
{
|
||||
if (fogQuality == FogQuality.FANCY)
|
||||
{
|
||||
GL15.glFogf(GL15.GL_FOG_END, vanillaBlockRenderedDistance * 1.41f);
|
||||
GL15.glFogf(GL15.GL_FOG_START, vanillaBlockRenderedDistance * 1.6f);
|
||||
}
|
||||
else if (fogQuality == FogQuality.FAST)
|
||||
{
|
||||
GL15.glFogf(GL15.GL_FOG_END, vanillaBlockRenderedDistance * 1.0f);
|
||||
GL15.glFogf(GL15.GL_FOG_START, vanillaBlockRenderedDistance * 1.5f);
|
||||
}
|
||||
}
|
||||
fogConfig.farFogEnd = farPlaneBlockDistance * 1.6f;
|
||||
|
||||
|
||||
GL15.glEnable(GL15.GL_FOG);
|
||||
GL15.glFogi(GL15.GL_FOG_MODE, GL15.GL_LINEAR);
|
||||
// near fog //
|
||||
|
||||
// the reason that I wrote fogEnd then fogStart backwards
|
||||
// is because we are using fog backwards to how
|
||||
// it is normally used, hiding near objects
|
||||
// instead of far objects.
|
||||
fogConfig.nearFogEnd = vanillaBlockRenderedDistance * 1.41f;
|
||||
fogConfig.nearFogStart = vanillaBlockRenderedDistance * 1.6f;
|
||||
|
||||
|
||||
return fogConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Revert any changes that were made to the fog
|
||||
* and sets up the fog for Minecraft.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
private void cleanupFog(NearFarFogSettings fogSettings,
|
||||
float defaultFogStartDist, float defaultFogEndDist,
|
||||
int defaultFogMode, int defaultFogDistance)
|
||||
private Color getFogColor()
|
||||
{
|
||||
GL15.glFogf(GL15.GL_FOG_START, defaultFogStartDist);
|
||||
GL15.glFogf(GL15.GL_FOG_END, defaultFogEndDist);
|
||||
GL15.glFogi(GL15.GL_FOG_MODE, defaultFogMode);
|
||||
Color fogColor;
|
||||
|
||||
// disable fog if Minecraft wasn't rendering fog
|
||||
// or we want it disabled
|
||||
if (!fogSettings.vanillaIsRenderingFog
|
||||
|| CONFIG.client().graphics().fogQuality().getDisableVanillaFog())
|
||||
{
|
||||
// Make fog render a infinite distance away.
|
||||
// This doesn't technically disable Minecraft's fog
|
||||
// so performance will probably be the same regardless, unlike
|
||||
// Optifine's no fog setting.
|
||||
|
||||
// we can't disable minecraft's fog outright because by default
|
||||
// minecraft will re-enable the fog after our code
|
||||
|
||||
GL15.glFogf(GL15.GL_FOG_START, 0.0F);
|
||||
GL15.glFogf(GL15.GL_FOG_END, Float.MAX_VALUE);
|
||||
GL15.glFogf(GL15.GL_FOG_DENSITY, Float.MAX_VALUE);
|
||||
}
|
||||
if (CONFIG.client().graphics().fogQuality().getFogColorMode() == FogColorMode.USE_SKY_COLOR)
|
||||
fogColor = MC_RENDER.getSkyColor();
|
||||
else
|
||||
fogColor = MC_RENDER.getFogColor();
|
||||
|
||||
return fogColor;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Translate the camera relative to the LodDimension's center,
|
||||
* this is done since all LOD buffers are created in world space
|
||||
@@ -532,7 +502,7 @@ public class LodRenderer
|
||||
* (since AxisAlignedBoundingBoxes (LODs) use doubles and thus have a higher
|
||||
* accuracy vs the model view matrix, which only uses floats)
|
||||
*/
|
||||
private Mat4f offsetTheModelViewMatrix(Mat4f mcModelViewMatrix, float partialTicks)
|
||||
private Mat4f translateModelViewMatrix(Mat4f mcModelViewMatrix, float partialTicks)
|
||||
{
|
||||
// get all relevant camera info
|
||||
Vec3d projectedView = MC_RENDER.getCameraExactPosition();
|
||||
@@ -547,99 +517,68 @@ public class LodRenderer
|
||||
|
||||
return mcModelViewMatrix;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Similar to translateModelViewMatrix (above),
|
||||
* but for the camera position
|
||||
*/
|
||||
private Vec3f getTranslatedCameraPos()
|
||||
{
|
||||
AbstractBlockPosWrapper worldCenter = vbosCenter.getWorldPosition();
|
||||
Vec3d cameraPos = MC_RENDER.getCameraExactPosition();
|
||||
return new Vec3f((float)cameraPos.x - worldCenter.getX(), (float)cameraPos.y, (float)cameraPos.z - worldCenter.getZ());
|
||||
}
|
||||
|
||||
/**
|
||||
* create and return a new projection matrix based on MC's projection matrix
|
||||
* @param currentProjectionMatrix this is Minecraft's current projection matrix
|
||||
* @param vanillaBlockRenderedDistance Minecraft's vanilla far plane distance
|
||||
* @param partialTicks how many ticks into the frame we are
|
||||
*/
|
||||
private Mat4f createProjectionMatrix(Mat4f currentProjectionMatrix, float vanillaBlockRenderedDistance, float partialTicks)
|
||||
private Mat4f createProjectionMatrix(Mat4f currentProjectionMatrix, float vanillaBlockRenderedDistance)
|
||||
{
|
||||
// create the new projection matrix
|
||||
|
||||
Mat4f lodProj = Mat4f.perspective(
|
||||
MC_RENDER.getFov(partialTicks),
|
||||
(float) this.MC_RENDER.getScreenWidth() / (float) this.MC_RENDER.getScreenHeight(),
|
||||
//Create a copy of the current matrix, so the current matrix isn't modified.
|
||||
Mat4f lodProj = currentProjectionMatrix.copy();
|
||||
|
||||
//Set new far and near clip plane values.
|
||||
lodProj.setClipPlanes(
|
||||
CONFIG.client().graphics().advancedGraphics().getUseExtendedNearClipPlane() ? vanillaBlockRenderedDistance / 5 : 1,
|
||||
farPlaneBlockDistance * LodUtil.CHUNK_WIDTH / 2);
|
||||
|
||||
|
||||
// get Minecraft's un-edited projection matrix
|
||||
// (this is before it is zoomed, distorted, etc.)
|
||||
Mat4f defaultMcProj = MC_RENDER.getDefaultProjectionMatrix(partialTicks);
|
||||
// true here means use "use fov setting" (probably)
|
||||
|
||||
// this logic strips away the defaultMcProj matrix, so we
|
||||
// can get the distortionMatrix, which represents all
|
||||
// transformations, zooming, distortions, etc. done
|
||||
// to Minecraft's Projection matrix
|
||||
Mat4f defaultMcProjInv = defaultMcProj.copy();
|
||||
defaultMcProjInv.invert();
|
||||
|
||||
Mat4f distortionMatrix = defaultMcProjInv.copy();
|
||||
distortionMatrix.multiply(currentProjectionMatrix);
|
||||
|
||||
|
||||
// edit the lod projection to match Minecraft's
|
||||
// (so the LODs line up with the real world)
|
||||
lodProj.multiply(distortionMatrix);
|
||||
|
||||
|
||||
return lodProj;
|
||||
}
|
||||
|
||||
///** setup the lighting to be used for the LODs */
|
||||
/*private void setupLighting(LodDimension lodDimension, float partialTicks)
|
||||
private void applyFog(LodShaderProgram shaderProgram,
|
||||
LodFogConfig fogSettings, int fogEnabledUniform, int nearFogEnabledUniform, int farFogEnabledUniform,
|
||||
int nearFogStartUniform, int nearFogEndUniform, int farFogStartUniform, int farFogEndUniform)
|
||||
{
|
||||
// Determine if the player has night vision
|
||||
boolean playerHasNightVision = false;
|
||||
if (this.mc.getPlayer() != null)
|
||||
if (fogSettings.fogDrawMode != FogDrawMode.FOG_DISABLED)
|
||||
{
|
||||
Iterator<EffectInstance> iterator = this.mc.getPlayer().getActiveEffects().iterator();
|
||||
while (iterator.hasNext())
|
||||
{
|
||||
EffectInstance instance = iterator.next();
|
||||
if (instance.getEffect() == Effects.NIGHT_VISION)
|
||||
{
|
||||
playerHasNightVision = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
shaderProgram.setUniform(fogEnabledUniform, true);
|
||||
shaderProgram.setUniform(nearFogEnabledUniform, fogSettings.fogDistance != FogDistance.FAR);
|
||||
shaderProgram.setUniform(farFogEnabledUniform, fogSettings.fogDistance != FogDistance.NEAR);
|
||||
|
||||
// near
|
||||
shaderProgram.setUniform(nearFogStartUniform, fogSettings.nearFogStart);
|
||||
shaderProgram.setUniform(nearFogEndUniform, fogSettings.nearFogEnd);
|
||||
// far
|
||||
shaderProgram.setUniform(farFogStartUniform, fogSettings.farFogStart);
|
||||
shaderProgram.setUniform(farFogEndUniform, fogSettings.farFogEnd);
|
||||
}
|
||||
else
|
||||
{
|
||||
shaderProgram.setUniform(fogEnabledUniform, false);
|
||||
}
|
||||
|
||||
float sunBrightness = lodDimension.dimension.hasSkyLight() ? mc.getSkyDarken(partialTicks) : 0.2f;
|
||||
sunBrightness = playerHasNightVision ? 1.0f : sunBrightness;
|
||||
float gamma = (float) mc.getOptions().gamma - 0.0f;
|
||||
float dayEffect = (sunBrightness - 0.2f) * 1.25f;
|
||||
float lightStrength = (gamma * 0.34f - 0.01f) * (1.0f - dayEffect) + dayEffect - 0.20f; //gamma * 0.2980392157f + 0.1647058824f
|
||||
float blueLightStrength = (gamma * 0.44f + 0.12f) * (1.0f - dayEffect) + dayEffect - 0.20f; //gamma * 0.4235294118f + 0.2784313725f
|
||||
|
||||
float[] lightAmbient = {lightStrength, lightStrength, blueLightStrength, 1.0f};
|
||||
|
||||
|
||||
// can be used for debugging
|
||||
// if (partialTicks < 0.005)
|
||||
// ClientProxy.LOGGER.debug(lightStrength);
|
||||
|
||||
ByteBuffer temp = ByteBuffer.allocateDirect(16);
|
||||
temp.order(ByteOrder.nativeOrder());
|
||||
GL15.glLightfv(LOD_GL_LIGHT_NUMBER, GL15.GL_AMBIENT, (FloatBuffer) temp.asFloatBuffer().put(lightAmbient).flip());
|
||||
GL15.glEnable(LOD_GL_LIGHT_NUMBER); // Enable the above lighting
|
||||
|
||||
RenderSystem.enableLighting();
|
||||
}*/
|
||||
|
||||
/** Create all buffers that will be used. */
|
||||
public void setupBuffers(LodDimension lodDim)
|
||||
{
|
||||
lodBufferBuilderFactory.setupBuffers(lodDim);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//======================//
|
||||
// Other Misc Functions //
|
||||
//======================//
|
||||
|
||||
|
||||
/**
|
||||
* If this is called then the next time "drawLODs" is called
|
||||
* the LODs will be regenerated; the same as if the player moved.
|
||||
@@ -649,7 +588,6 @@ public class LodRenderer
|
||||
fullRegen = true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Replace the current Vertex Buffers with the newly
|
||||
* created buffers from the lodBufferBuilder. <br><br>
|
||||
@@ -672,98 +610,7 @@ public class LodRenderer
|
||||
{
|
||||
lodBufferBuilderFactory.destroyBuffers();
|
||||
}
|
||||
|
||||
/** Return what fog settings should be used when rendering. */
|
||||
@SuppressWarnings("unused")
|
||||
private NearFarFogSettings determineFogSettings()
|
||||
{
|
||||
NearFarFogSettings fogSettings = new NearFarFogSettings();
|
||||
|
||||
|
||||
FogQuality quality = REFLECTION_HANDLER.getFogQuality();
|
||||
FogDrawOverride override = CONFIG.client().graphics().fogQuality().getFogDrawOverride();
|
||||
|
||||
|
||||
fogSettings.vanillaIsRenderingFog = quality != FogQuality.OFF;
|
||||
|
||||
|
||||
// use any fog overrides the user may have set
|
||||
switch (override)
|
||||
{
|
||||
case FANCY:
|
||||
quality = FogQuality.FANCY;
|
||||
break;
|
||||
|
||||
case NO_FOG:
|
||||
quality = FogQuality.OFF;
|
||||
break;
|
||||
|
||||
case FAST:
|
||||
quality = FogQuality.FAST;
|
||||
break;
|
||||
|
||||
case OPTIFINE_SETTING:
|
||||
// don't override anything
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// how different distances are drawn depends on the quality set
|
||||
switch (quality)
|
||||
{
|
||||
case FANCY:
|
||||
fogSettings.near.quality = FogQuality.FANCY;
|
||||
fogSettings.far.quality = FogQuality.FANCY;
|
||||
|
||||
switch (CONFIG.client().graphics().fogQuality().getFogDistance())
|
||||
{
|
||||
case NEAR_AND_FAR:
|
||||
fogSettings.near.distance = FogDistance.NEAR;
|
||||
fogSettings.far.distance = FogDistance.FAR;
|
||||
break;
|
||||
|
||||
case NEAR:
|
||||
fogSettings.near.distance = FogDistance.NEAR;
|
||||
fogSettings.far.distance = FogDistance.NEAR;
|
||||
break;
|
||||
|
||||
case FAR:
|
||||
fogSettings.near.distance = FogDistance.FAR;
|
||||
fogSettings.far.distance = FogDistance.FAR;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case FAST:
|
||||
fogSettings.near.quality = FogQuality.FAST;
|
||||
fogSettings.far.quality = FogQuality.FAST;
|
||||
|
||||
// fast fog setting should only have one type of
|
||||
// fog, since the LODs are separated into a near
|
||||
// and far portion; and fast fog is rendered from the
|
||||
// frustrum's perspective instead of the camera
|
||||
switch (CONFIG.client().graphics().fogQuality().getFogDistance())
|
||||
{
|
||||
case NEAR_AND_FAR:
|
||||
case NEAR:
|
||||
fogSettings.near.distance = FogDistance.NEAR;
|
||||
fogSettings.far.distance = FogDistance.NEAR;
|
||||
break;
|
||||
|
||||
case FAR:
|
||||
fogSettings.near.distance = FogDistance.FAR;
|
||||
fogSettings.far.distance = FogDistance.FAR;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case OFF:
|
||||
fogSettings.near.quality = FogQuality.OFF;
|
||||
fogSettings.far.quality = FogQuality.OFF;
|
||||
break;
|
||||
}
|
||||
return fogSettings;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** Determines if the LODs should have a fullRegen or partialRegen */
|
||||
@@ -804,8 +651,8 @@ public class LodRenderer
|
||||
if (newTime - prevPlayerPosTime > CONFIG.client().advanced().buffers().getRebuildTimes().playerMoveTimeout)
|
||||
{
|
||||
if (LevelPosUtil.getDetailLevel(previousPos) == 0
|
||||
|| MC.getPlayerChunkPos().getX() != LevelPosUtil.getPosX(previousPos)
|
||||
|| MC.getPlayerChunkPos().getZ() != LevelPosUtil.getPosZ(previousPos))
|
||||
|| Math.abs(MC.getPlayerChunkPos().getX() - LevelPosUtil.getPosX(previousPos)) > CONFIG.client().advanced().buffers().getRebuildTimes().playerMoveDistance
|
||||
|| Math.abs(MC.getPlayerChunkPos().getZ() - LevelPosUtil.getPosZ(previousPos)) > CONFIG.client().advanced().buffers().getRebuildTimes().playerMoveDistance)
|
||||
{
|
||||
vanillaRenderedChunks = new boolean[vanillaRenderedChunksWidth][vanillaRenderedChunksWidth];
|
||||
fullRegen = true;
|
||||
|
||||
@@ -21,9 +21,10 @@ package com.seibel.lod.core.render;
|
||||
|
||||
import com.seibel.lod.core.objects.math.Vec3f;
|
||||
import com.seibel.lod.core.util.LodUtil;
|
||||
import com.seibel.lod.core.util.SingletonHandler;
|
||||
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.chunk.AbstractChunkPosWrapper;
|
||||
import com.seibel.lod.forge.wrappers.minecraft.MinecraftRenderWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
|
||||
/**
|
||||
* This holds miscellaneous helper code
|
||||
@@ -34,7 +35,7 @@ import com.seibel.lod.forge.wrappers.minecraft.MinecraftRenderWrapper;
|
||||
*/
|
||||
public class RenderUtil
|
||||
{
|
||||
private static final MinecraftRenderWrapper MC_RENDER = MinecraftRenderWrapper.INSTANCE;
|
||||
private static final IMinecraftRenderWrapper MC_RENDER = SingletonHandler.get(IMinecraftRenderWrapper.class);
|
||||
|
||||
|
||||
/**
|
||||
@@ -92,16 +93,15 @@ public class RenderUtil
|
||||
Vec3f playerVec = new Vec3f(playerBlockPos.getX(), playerBlockPos.getY(), playerBlockPos.getZ());
|
||||
|
||||
vboVec.subtract(playerVec);
|
||||
Vec3f vboCenterVec = vboVec;
|
||||
|
||||
|
||||
int halfRegionWidth = LodUtil.REGION_WIDTH / 2;
|
||||
|
||||
// calculate the 4 corners
|
||||
Vec3f vboSeVec = new Vec3f(vboCenterVec.x + halfRegionWidth, vboCenterVec.y, vboCenterVec.z + halfRegionWidth);
|
||||
Vec3f vboSwVec = new Vec3f(vboCenterVec.x - halfRegionWidth, vboCenterVec.y, vboCenterVec.z + halfRegionWidth);
|
||||
Vec3f vboNwVec = new Vec3f(vboCenterVec.x - halfRegionWidth, vboCenterVec.y, vboCenterVec.z - halfRegionWidth);
|
||||
Vec3f vboNeVec = new Vec3f(vboCenterVec.x + halfRegionWidth, vboCenterVec.y, vboCenterVec.z - halfRegionWidth);
|
||||
Vec3f vboSeVec = new Vec3f(vboVec.x + halfRegionWidth, vboVec.y, vboVec.z + halfRegionWidth);
|
||||
Vec3f vboSwVec = new Vec3f(vboVec.x - halfRegionWidth, vboVec.y, vboVec.z + halfRegionWidth);
|
||||
Vec3f vboNwVec = new Vec3f(vboVec.x - halfRegionWidth, vboVec.y, vboVec.z - halfRegionWidth);
|
||||
Vec3f vboNeVec = new Vec3f(vboVec.x + halfRegionWidth, vboVec.y, vboVec.z - halfRegionWidth);
|
||||
|
||||
// if any corner is visible, this region should be rendered
|
||||
return isNormalizedVectorInViewFrustum(vboSeVec, cameraDir) ||
|
||||
|
||||
@@ -100,7 +100,7 @@ public class LodShader
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles the shader and checks it's status afterwards.
|
||||
* Compiles the shader and checks its status afterwards.
|
||||
* @throws Exception if the shader fails to compile
|
||||
*/
|
||||
public void compile() throws Exception
|
||||
|
||||
@@ -19,12 +19,15 @@
|
||||
|
||||
package com.seibel.lod.core.render.shader;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.nio.FloatBuffer;
|
||||
|
||||
import org.lwjgl.opengl.GL20;
|
||||
import org.lwjgl.system.MemoryStack;
|
||||
|
||||
import com.seibel.lod.core.objects.math.Mat4f;
|
||||
import com.seibel.lod.core.objects.math.Vec3d;
|
||||
import com.seibel.lod.core.objects.math.Vec3f;
|
||||
|
||||
|
||||
/**
|
||||
@@ -34,7 +37,7 @@ import com.seibel.lod.core.objects.math.Mat4f;
|
||||
* can (and needs to be) done with a shader program.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 11-8-2021
|
||||
* @version 11-26-2021
|
||||
*/
|
||||
public class LodShaderProgram
|
||||
{
|
||||
@@ -140,7 +143,7 @@ public class LodShaderProgram
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the location of an uniform variable with specified name.
|
||||
* Gets the location of a uniform variable with specified name.
|
||||
* Calls GL20.glGetUniformLocation(id, name)
|
||||
*
|
||||
* @param name Uniform name
|
||||
@@ -152,23 +155,33 @@ public class LodShaderProgram
|
||||
return GL20.glGetUniformLocation(id, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the uniform variable for specified location.
|
||||
*
|
||||
* @param location Uniform location
|
||||
* @param value Value to set
|
||||
*/
|
||||
|
||||
|
||||
public void setUniform(int location, boolean value)
|
||||
{
|
||||
GL20.glUniform1i(location, value ? 1 : 0);
|
||||
}
|
||||
|
||||
public void setUniform(int location, int value)
|
||||
{
|
||||
GL20.glUniform1i(location, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the uniform variable for specified location.
|
||||
*
|
||||
* @param location Uniform location
|
||||
* @param value Value to set
|
||||
*/
|
||||
public void setUniform(int location, float value)
|
||||
{
|
||||
GL20.glUniform1f(location, value);
|
||||
}
|
||||
|
||||
public void setUniform(int location, Vec3f value)
|
||||
{
|
||||
GL20.glUniform3f(location, value.x, value.y, value.z);
|
||||
}
|
||||
|
||||
public void setUniform(int location, Vec3d value)
|
||||
{
|
||||
GL20.glUniform3f(location, (float) value.x, (float) value.y, (float) value.z);
|
||||
}
|
||||
|
||||
public void setUniform(int location, Mat4f value)
|
||||
{
|
||||
try (MemoryStack stack = MemoryStack.stackPush())
|
||||
@@ -179,6 +192,12 @@ public class LodShaderProgram
|
||||
}
|
||||
}
|
||||
|
||||
/** Converts the color's RGBA values into values between 0 and 1. */
|
||||
public void setUniform(int location, Color value)
|
||||
{
|
||||
GL20.glUniform4f(location, value.getRed() / 256.0f, value.getGreen() / 256.0f, value.getBlue() / 256.0f, value.getAlpha() / 256.0f);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -57,8 +57,9 @@ public class DataPointUtil
|
||||
//To be used in the future for negative value
|
||||
//public final static int MIN_DEPTH = -64;
|
||||
//public final static int MIN_HEIGHT = -64;
|
||||
public final static int EMPTY_DATA = 0;
|
||||
public static int worldHeight = 256;
|
||||
public final static byte EMPTY_DATA = 0;
|
||||
public static final short VERTICAL_OFFSET = -2048;
|
||||
public static int WORLD_HEIGHT = 4096;
|
||||
|
||||
public final static int ALPHA_DOWNSIZE_SHIFT = 4;
|
||||
|
||||
@@ -67,167 +68,159 @@ public class DataPointUtil
|
||||
//public final static int RED_COLOR_SHIFT = 16;
|
||||
//public final static int ALPHA_COLOR_SHIFT = 24;
|
||||
|
||||
public final static int BLUE_SHIFT = 36;
|
||||
public final static int GREEN_SHIFT = BLUE_SHIFT + 8;
|
||||
public final static int RED_SHIFT = BLUE_SHIFT + 16;
|
||||
public final static int ALPHA_SHIFT = BLUE_SHIFT + 24;
|
||||
public final static byte BLUE_SHIFT = 0;
|
||||
public final static byte GREEN_SHIFT = 8;
|
||||
public final static byte RED_SHIFT = 16;
|
||||
public final static byte ALPHA_SHIFT = 24;
|
||||
|
||||
public final static int COLOR_SHIFT = 36;
|
||||
//public final static byte COLOR_SHIFT = 36;
|
||||
|
||||
public final static int HEIGHT_SHIFT = 26;
|
||||
public final static int DEPTH_SHIFT = 16;
|
||||
public final static int BLOCK_LIGHT_SHIFT = 12;
|
||||
public final static int SKY_LIGHT_SHIFT = 8;
|
||||
//public final static int LIGHTS_SHIFT = SKY_LIGHT_SHIFT;
|
||||
//public final static int VERTICAL_INDEX_SHIFT = 6;
|
||||
public final static int FLAG_SHIFT = 5;
|
||||
public final static int GEN_TYPE_SHIFT = 2;
|
||||
public final static int VOID_SHIFT = 1;
|
||||
public final static int EXISTENCE_SHIFT = 0;
|
||||
public final static byte HEIGHT_SHIFT = 20;
|
||||
public final static byte DEPTH_SHIFT = 8;
|
||||
public final static byte BLOCK_LIGHT_SHIFT = 4;
|
||||
public final static byte SKY_LIGHT_SHIFT = 0;
|
||||
//public final static byte LIGHTS_SHIFT = SKY_LIGHT_SHIFT;
|
||||
//public final static byte VERTICAL_INDEX_SHIFT = 6;
|
||||
public final static byte FLAG_SHIFT = 5;
|
||||
public final static byte GEN_TYPE_SHIFT = 2;
|
||||
public final static byte VOID_SHIFT = 1;
|
||||
public final static byte EXISTENCE_SHIFT = 0;
|
||||
|
||||
public final static long ALPHA_MASK = 0b1111;
|
||||
public final static long RED_MASK = 0b1111_1111;
|
||||
public final static long GREEN_MASK = 0b1111_1111;
|
||||
public final static long BLUE_MASK = 0b1111_1111;
|
||||
public final static long COLOR_MASK = 0b11111111_11111111_11111111;
|
||||
public final static long HEIGHT_MASK = 0b11_1111_1111;
|
||||
public final static long DEPTH_MASK = 0b11_1111_1111;
|
||||
//public final static long LIGHTS_MASK = 0b1111_1111;
|
||||
public final static long BLOCK_LIGHT_MASK = 0b1111;
|
||||
public final static long SKY_LIGHT_MASK = 0b1111;
|
||||
//public final static long VERTICAL_INDEX_MASK = 0b11;
|
||||
public final static long FLAG_MASK = 0b1;
|
||||
public final static long GEN_TYPE_MASK = 0b111;
|
||||
public final static long VOID_MASK = 1;
|
||||
public final static long EXISTENCE_MASK = 1;
|
||||
public final static int ALPHA_MASK = 0xFF;
|
||||
public final static int RED_MASK = 0xFF;
|
||||
public final static int GREEN_MASK = 0xFF;
|
||||
public final static int BLUE_MASK = 0xFF;
|
||||
public final static int COLOR_MASK = 0xFFFFFFFF;
|
||||
public final static int HEIGHT_MASK = 0xFFF;
|
||||
public final static int DEPTH_MASK = 0xFFF;
|
||||
public final static int LIGHTS_MASK = 0xFF;
|
||||
public final static int BLOCK_LIGHT_MASK = 0xF;
|
||||
public final static int SKY_LIGHT_MASK = 0xF;
|
||||
public final static int VERTICAL_INDEX_MASK = 0x3;
|
||||
public final static byte FLAG_MASK = 0x1;
|
||||
public final static byte GEN_TYPE_MASK = 0x7;
|
||||
public final static byte VOID_MASK = 1;
|
||||
public final static byte EXISTENCE_MASK = 1;
|
||||
|
||||
|
||||
public static long createVoidDataPoint(int generationMode)
|
||||
/** Returns the Flags byte */
|
||||
public static byte createVoidDataPoint(byte generationMode)
|
||||
{
|
||||
long dataPoint = 0;
|
||||
dataPoint += (generationMode & GEN_TYPE_MASK) << GEN_TYPE_SHIFT;
|
||||
dataPoint += VOID_MASK << VOID_SHIFT;
|
||||
dataPoint += EXISTENCE_MASK << EXISTENCE_SHIFT;
|
||||
return dataPoint;
|
||||
generationMode = (byte) ((generationMode & GEN_TYPE_MASK) << GEN_TYPE_SHIFT);
|
||||
generationMode |= VOID_MASK << VOID_SHIFT;
|
||||
generationMode |= EXISTENCE_MASK << EXISTENCE_SHIFT;
|
||||
return generationMode;
|
||||
}
|
||||
|
||||
public static long createDataPoint(int height, int depth, int color, int lightSky, int lightBlock, int generationMode, boolean flag)
|
||||
/** Returned datapoint is in ThreadMapUtil */
|
||||
public static void createDataPoint(int height, int depth, int color, int lightSky, int lightBlock, int generationMode, boolean flag)
|
||||
{
|
||||
return createDataPoint(
|
||||
ColorUtil.getAlpha(color),
|
||||
ColorUtil.getRed(color),
|
||||
ColorUtil.getGreen(color),
|
||||
ColorUtil.getBlue(color),
|
||||
height, depth, lightSky, lightBlock, generationMode, flag);
|
||||
int data = (height & HEIGHT_MASK) << HEIGHT_SHIFT;
|
||||
data += (depth & DEPTH_MASK) << DEPTH_SHIFT;
|
||||
data += (lightBlock & BLOCK_LIGHT_MASK) << BLOCK_LIGHT_SHIFT;
|
||||
data += (lightSky & SKY_LIGHT_MASK) << SKY_LIGHT_SHIFT;
|
||||
byte flags = (byte) ((generationMode & GEN_TYPE_MASK) << GEN_TYPE_SHIFT);
|
||||
if (flag) flags += FLAG_MASK << FLAG_SHIFT;
|
||||
flags += EXISTENCE_MASK << EXISTENCE_SHIFT;
|
||||
ThreadMapUtil.saveDataPoint(color, data, flags);
|
||||
}
|
||||
|
||||
public static long createDataPoint(int alpha, int red, int green, int blue, int height, int depth, int lightSky, int lightBlock, int generationMode, boolean flag)
|
||||
public static void createDataPoint(int alpha, int red, int green, int blue, int height, int depth, int lightSky, int lightBlock, int generationMode, boolean flag)
|
||||
{
|
||||
long dataPoint = 0;
|
||||
dataPoint += (long) (alpha >>> ALPHA_DOWNSIZE_SHIFT) << ALPHA_SHIFT;
|
||||
dataPoint += (red & RED_MASK) << RED_SHIFT;
|
||||
dataPoint += (green & GREEN_MASK) << GREEN_SHIFT;
|
||||
dataPoint += (blue & BLUE_MASK) << BLUE_SHIFT;
|
||||
dataPoint += (height & HEIGHT_MASK) << HEIGHT_SHIFT;
|
||||
dataPoint += (depth & DEPTH_MASK) << DEPTH_SHIFT;
|
||||
dataPoint += (lightBlock & BLOCK_LIGHT_MASK) << BLOCK_LIGHT_SHIFT;
|
||||
dataPoint += (lightSky & SKY_LIGHT_MASK) << SKY_LIGHT_SHIFT;
|
||||
dataPoint += (generationMode & GEN_TYPE_MASK) << GEN_TYPE_SHIFT;
|
||||
if (flag) dataPoint += FLAG_MASK << FLAG_SHIFT;
|
||||
dataPoint += EXISTENCE_MASK << EXISTENCE_SHIFT;
|
||||
|
||||
return dataPoint;
|
||||
createDataPoint(
|
||||
height, depth,
|
||||
(alpha << ALPHA_SHIFT) | (red << RED_SHIFT) | (green << GREEN_SHIFT) | blue,
|
||||
lightSky, lightBlock, generationMode, flag);
|
||||
}
|
||||
|
||||
public static short getHeight(long dataPoint)
|
||||
public static short getHeight(int data)
|
||||
{
|
||||
return (short) ((dataPoint >>> HEIGHT_SHIFT) & HEIGHT_MASK);
|
||||
return (short) ((data >>> HEIGHT_SHIFT) & HEIGHT_MASK);
|
||||
}
|
||||
|
||||
public static short getDepth(long dataPoint)
|
||||
public static short getDepth(int data)
|
||||
{
|
||||
return (short) ((dataPoint >>> DEPTH_SHIFT) & DEPTH_MASK);
|
||||
return (short) ((data >>> DEPTH_SHIFT) & DEPTH_MASK);
|
||||
}
|
||||
|
||||
public static short getAlpha(long dataPoint)
|
||||
public static short getAlpha(int color)
|
||||
{
|
||||
return (short) ((((dataPoint >>> ALPHA_SHIFT) & ALPHA_MASK) << ALPHA_DOWNSIZE_SHIFT) | 0b1111);
|
||||
return (short) ((color >>> ALPHA_SHIFT) & ALPHA_MASK);
|
||||
}
|
||||
|
||||
public static short getRed(long dataPoint)
|
||||
public static short getRed(int color)
|
||||
{
|
||||
return (short) ((dataPoint >>> RED_SHIFT) & RED_MASK);
|
||||
return (short) ((color >>> RED_SHIFT) & RED_MASK);
|
||||
}
|
||||
|
||||
public static short getGreen(long dataPoint)
|
||||
public static short getGreen(int color)
|
||||
{
|
||||
return (short) ((dataPoint >>> GREEN_SHIFT) & GREEN_MASK);
|
||||
return (short) ((color >>> GREEN_SHIFT) & GREEN_MASK);
|
||||
}
|
||||
|
||||
public static short getBlue(long dataPoint)
|
||||
public static short getBlue(int color)
|
||||
{
|
||||
return (short) ((dataPoint >>> BLUE_SHIFT) & BLUE_MASK);
|
||||
return (short) ((color >>> BLUE_SHIFT) & BLUE_MASK);
|
||||
}
|
||||
|
||||
public static byte getLightSky(long dataPoint)
|
||||
public static byte getLightSky(int data)
|
||||
{
|
||||
return (byte) ((dataPoint >>> SKY_LIGHT_SHIFT) & SKY_LIGHT_MASK);
|
||||
return (byte) ((data >>> SKY_LIGHT_SHIFT) & SKY_LIGHT_MASK);
|
||||
}
|
||||
|
||||
public static byte getLightSkyAlt(long dataPoint)
|
||||
public static byte getLightSkyAlt(int data, byte flags)
|
||||
{
|
||||
if (skyLightPlayer == 0 && ((dataPoint >>> FLAG_SHIFT) & FLAG_MASK) == 1)
|
||||
if (skyLightPlayer == 0 && ((flags >>> FLAG_SHIFT) & FLAG_MASK) == 1)
|
||||
return 0;
|
||||
else
|
||||
return (byte) ((dataPoint >>> SKY_LIGHT_SHIFT) & SKY_LIGHT_MASK);
|
||||
return (byte) ((data >>> SKY_LIGHT_SHIFT) & SKY_LIGHT_MASK);
|
||||
}
|
||||
|
||||
public static byte getLightBlock(long dataPoint)
|
||||
public static byte getLightBlock(int data)
|
||||
{
|
||||
return (byte) ((dataPoint >>> BLOCK_LIGHT_SHIFT) & BLOCK_LIGHT_MASK);
|
||||
return (byte) ((data >>> BLOCK_LIGHT_SHIFT) & BLOCK_LIGHT_MASK);
|
||||
}
|
||||
|
||||
public static boolean getFlag(long dataPoint)
|
||||
public static boolean getFlag(byte flags)
|
||||
{
|
||||
return ((dataPoint >>> FLAG_SHIFT) & FLAG_MASK) == 1;
|
||||
return ((flags >>> FLAG_SHIFT) & FLAG_MASK) == 1;
|
||||
}
|
||||
|
||||
public static byte getGenerationMode(long dataPoint)
|
||||
public static byte getGenerationMode(byte flags)
|
||||
{
|
||||
return (byte) ((dataPoint >>> GEN_TYPE_SHIFT) & GEN_TYPE_MASK);
|
||||
return (byte) ((flags >>> GEN_TYPE_SHIFT) & GEN_TYPE_MASK);
|
||||
}
|
||||
|
||||
|
||||
public static boolean isVoid(long dataPoint)
|
||||
public static boolean isVoid(byte flags)
|
||||
{
|
||||
return (((dataPoint >>> VOID_SHIFT) & VOID_MASK) == 1);
|
||||
return (((flags >>> VOID_SHIFT) & VOID_MASK) == 1);
|
||||
}
|
||||
|
||||
public static boolean doesItExist(long dataPoint)
|
||||
public static boolean doesItExist(byte flags)
|
||||
{
|
||||
return (((dataPoint >>> EXISTENCE_SHIFT) & EXISTENCE_MASK) == 1);
|
||||
return ((flags >>> EXISTENCE_SHIFT) & EXISTENCE_MASK) == 1;
|
||||
}
|
||||
|
||||
public static int getColor(long dataPoint)
|
||||
@Deprecated
|
||||
public static int getColor(int color)
|
||||
{
|
||||
return (int) (((dataPoint >>> COLOR_SHIFT) & COLOR_MASK) | (/*((dataPoint >>> (ALPHA_SHIFT - ALPHA_DOWNSIZE_SHIFT)) | 0b1111)*/255 << 24));
|
||||
return color;
|
||||
}
|
||||
|
||||
/** This is used to convert a dataPoint to string (useful for the print function) */
|
||||
@SuppressWarnings("unused")
|
||||
public static String toString(long dataPoint)
|
||||
public static String toString(int color, int data, byte flags)
|
||||
{
|
||||
return getHeight(dataPoint) + " " +
|
||||
getDepth(dataPoint) + " " +
|
||||
getAlpha(dataPoint) + " " +
|
||||
getRed(dataPoint) + " " +
|
||||
getBlue(dataPoint) + " " +
|
||||
getGreen(dataPoint) + " " +
|
||||
getLightBlock(dataPoint) + " " +
|
||||
getLightSky(dataPoint) + " " +
|
||||
getGenerationMode(dataPoint) + " " +
|
||||
isVoid(dataPoint) + " " +
|
||||
doesItExist(dataPoint) + '\n';
|
||||
return getHeight(data) + " " +
|
||||
getDepth(data) + " " +
|
||||
getAlpha(color) + " " +
|
||||
getRed(color) + " " +
|
||||
getBlue(color) + " " +
|
||||
getGreen(color) + " " +
|
||||
getLightBlock(data) + " " +
|
||||
getLightSky(data) + " " +
|
||||
getGenerationMode(flags) + " " +
|
||||
isVoid(flags) + " " +
|
||||
doesItExist(flags) + '\n';
|
||||
}
|
||||
|
||||
public static void shrinkArray(short[] array, int packetSize, int start, int length, int arraySize)
|
||||
@@ -257,25 +250,30 @@ public class DataPointUtil
|
||||
|
||||
/**
|
||||
* This method merge column of multiple data together
|
||||
* @param dataToMerge one or more columns of data
|
||||
* Returned datapoint is in ThreadMapUtil
|
||||
* @param dataToMergeColor colors of one or more columns of data
|
||||
* @param dataToMergeData data of one or more columns of data
|
||||
* @param dataToMergeFlags flags of one or more columns of data
|
||||
* @param inputVerticalData vertical size of an input data
|
||||
* @param maxVerticalData max vertical size of the merged data
|
||||
* @return one column of correctly parsed data
|
||||
*/
|
||||
public static long[] mergeMultiData(long[] dataToMerge, int inputVerticalData, int maxVerticalData)
|
||||
public static void mergeMultiData(int[] dataToMergeColor, int[] dataToMergeData, byte[] dataToMergeFlags, int inputVerticalData, int maxVerticalData)
|
||||
{
|
||||
int size = dataToMerge.length / inputVerticalData;
|
||||
int size = dataToMergeData.length / inputVerticalData;
|
||||
|
||||
// We initialize the arrays that are going to be used
|
||||
short[] heightAndDepth = ThreadMapUtil.getHeightAndDepth((worldHeight / 2 + 1) * 2);
|
||||
long[] dataPoint = ThreadMapUtil.getVerticalDataArray(DetailDistanceUtil.getMaxVerticalData(0));
|
||||
short[] heightAndDepth = ThreadMapUtil.getHeightAndDepth((WORLD_HEIGHT / 2 + 1) * 2);
|
||||
int[] dataPointColor = ThreadMapUtil.getVerticalDataArrayColor(DetailDistanceUtil.getMaxVerticalData(0));
|
||||
int[] dataPointData = ThreadMapUtil.getVerticalDataArrayData(DetailDistanceUtil.getMaxVerticalData(0));
|
||||
byte[] dataPointFlags = ThreadMapUtil.getVerticalDataArrayFlags(DetailDistanceUtil.getMaxVerticalData(0));
|
||||
|
||||
|
||||
int genMode = DistanceGenerationMode.FULL.complexity;
|
||||
byte genMode = DistanceGenerationMode.FULL.complexity;
|
||||
boolean allEmpty = true;
|
||||
boolean allVoid = true;
|
||||
boolean allDefault;
|
||||
long singleData;
|
||||
int singleDataData;
|
||||
byte singleDataFlags;
|
||||
|
||||
|
||||
short depth;
|
||||
@@ -289,16 +287,17 @@ public class DataPointUtil
|
||||
{
|
||||
for (dataIndex = 0; dataIndex < inputVerticalData; dataIndex++)
|
||||
{
|
||||
singleData = dataToMerge[index * inputVerticalData + dataIndex];
|
||||
if (doesItExist(singleData))
|
||||
singleDataData = dataToMergeData[index * inputVerticalData + dataIndex];
|
||||
singleDataFlags = dataToMergeFlags[index * inputVerticalData + dataIndex];
|
||||
if (doesItExist(singleDataFlags))
|
||||
{
|
||||
genMode = Math.min(genMode, getGenerationMode(singleData));
|
||||
genMode = (byte) Math.min(genMode, getGenerationMode(singleDataFlags));
|
||||
allEmpty = false;
|
||||
if (!isVoid(singleData))
|
||||
if (!isVoid(singleDataFlags))
|
||||
{
|
||||
allVoid = false;
|
||||
depth = getDepth(singleData);
|
||||
height = getHeight(singleData);
|
||||
depth = getDepth(singleDataData);
|
||||
height = getHeight(singleDataData);
|
||||
|
||||
int botPos = -1;
|
||||
int topPos = -1;
|
||||
@@ -401,18 +400,18 @@ public class DataPointUtil
|
||||
|
||||
//We check if there is any data that's not empty or void
|
||||
if (allEmpty)
|
||||
return dataPoint;
|
||||
return;
|
||||
if (allVoid)
|
||||
{
|
||||
dataPoint[0] = createVoidDataPoint(genMode);
|
||||
return dataPoint;
|
||||
dataPointFlags[0] = createVoidDataPoint(genMode);
|
||||
return;
|
||||
}
|
||||
|
||||
//we limit the vertical portion to maxVerticalData
|
||||
int j = 0;
|
||||
while (count > maxVerticalData)
|
||||
{
|
||||
ii = worldHeight;
|
||||
ii = WORLD_HEIGHT - VERTICAL_OFFSET;
|
||||
for (i = 0; i < count - 1; i++)
|
||||
{
|
||||
if (heightAndDepth[i * 2 + 1] - heightAndDepth[(i + 1) * 2] <= ii)
|
||||
@@ -450,71 +449,90 @@ public class DataPointUtil
|
||||
allEmpty = true;
|
||||
allVoid = true;
|
||||
allDefault = true;
|
||||
long data = 0;
|
||||
int singleDataColor;
|
||||
int data = EMPTY_DATA;
|
||||
int color = EMPTY_DATA;
|
||||
byte flags = EMPTY_DATA;
|
||||
|
||||
for (int index = 0; index < size; index++)
|
||||
{
|
||||
for (dataIndex = 0; dataIndex < inputVerticalData; dataIndex++)
|
||||
{
|
||||
singleData = dataToMerge[index * inputVerticalData + dataIndex];
|
||||
if (doesItExist(singleData) && !isVoid(singleData))
|
||||
singleDataColor = dataToMergeColor[index * inputVerticalData + dataIndex];
|
||||
singleDataData = dataToMergeData[index * inputVerticalData + dataIndex];
|
||||
singleDataFlags = dataToMergeFlags[index * inputVerticalData + dataIndex];
|
||||
if (doesItExist(singleDataFlags) && !isVoid(singleDataFlags))
|
||||
{
|
||||
|
||||
if ((depth <= getDepth(singleData) && getDepth(singleData) <= height)
|
||||
|| (depth <= getHeight(singleData) && getHeight(singleData) <= height))
|
||||
if ((depth <= getDepth(singleDataData) && getDepth(singleDataData) <= height)
|
||||
|| (depth <= getHeight(singleDataData) && getHeight(singleDataData) <= height))
|
||||
{
|
||||
if (getHeight(singleData) > getHeight(data))
|
||||
data = singleData;
|
||||
if (getHeight(singleDataData) > getHeight(data))
|
||||
{
|
||||
color = singleDataColor;
|
||||
data = singleDataData;
|
||||
flags = singleDataFlags;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (!doesItExist(data))
|
||||
if (!doesItExist(flags))
|
||||
{
|
||||
singleData = dataToMerge[index * inputVerticalData];
|
||||
data = createVoidDataPoint(getGenerationMode(singleData));
|
||||
singleDataFlags = dataToMergeFlags[index * inputVerticalData];
|
||||
if (doesItExist(singleDataFlags))
|
||||
flags = createVoidDataPoint(getGenerationMode(singleDataFlags));
|
||||
else
|
||||
flags = createVoidDataPoint((byte) 0);
|
||||
data = EMPTY_DATA;
|
||||
color = EMPTY_DATA;
|
||||
}
|
||||
|
||||
if (doesItExist(data))
|
||||
if (doesItExist(flags))
|
||||
{
|
||||
allEmpty = false;
|
||||
if (!isVoid(data))
|
||||
if (!isVoid(flags))
|
||||
{
|
||||
numberOfChildren++;
|
||||
allVoid = false;
|
||||
tempAlpha += getAlpha(data);
|
||||
tempRed += getRed(data);
|
||||
tempGreen += getGreen(data);
|
||||
tempBlue += getBlue(data);
|
||||
tempAlpha += getAlpha(color);
|
||||
tempRed += getRed(color);
|
||||
tempGreen += getGreen(color);
|
||||
tempBlue += getBlue(color);
|
||||
tempLightBlock += getLightBlock(data);
|
||||
tempLightSky += getLightSky(data);
|
||||
if (!getFlag(data)) allDefault = false;
|
||||
if (!getFlag(flags))
|
||||
allDefault = false;
|
||||
}
|
||||
tempGenMode = (byte) Math.min(tempGenMode, getGenerationMode(data));
|
||||
tempGenMode = (byte) Math.min(tempGenMode, getGenerationMode(flags));
|
||||
}
|
||||
else
|
||||
tempGenMode = (byte) Math.min(tempGenMode, DistanceGenerationMode.NONE.complexity);
|
||||
}
|
||||
|
||||
if (allEmpty)
|
||||
//no child has been initialized
|
||||
dataPoint[j] = EMPTY_DATA;
|
||||
else if (allVoid)
|
||||
//all the children are void
|
||||
dataPoint[j] = createVoidDataPoint(tempGenMode);
|
||||
else
|
||||
if (!allEmpty)
|
||||
{
|
||||
//we have at least 1 child
|
||||
tempAlpha = tempAlpha / numberOfChildren;
|
||||
tempRed = tempRed / numberOfChildren;
|
||||
tempGreen = tempGreen / numberOfChildren;
|
||||
tempBlue = tempBlue / numberOfChildren;
|
||||
tempLightBlock = tempLightBlock / numberOfChildren;
|
||||
tempLightSky = tempLightSky / numberOfChildren;
|
||||
dataPoint[j] = createDataPoint(tempAlpha, tempRed, tempGreen, tempBlue, height, depth, tempLightSky, tempLightBlock, tempGenMode, allDefault);
|
||||
//child has been initialized
|
||||
if (allVoid)
|
||||
{
|
||||
//all the children are void
|
||||
dataPointFlags[j] = createVoidDataPoint(tempGenMode);
|
||||
}
|
||||
else
|
||||
{
|
||||
//we have at least 1 child
|
||||
tempAlpha = tempAlpha / numberOfChildren;
|
||||
tempRed = tempRed / numberOfChildren;
|
||||
tempGreen = tempGreen / numberOfChildren;
|
||||
tempBlue = tempBlue / numberOfChildren;
|
||||
tempLightBlock = tempLightBlock / numberOfChildren;
|
||||
tempLightSky = tempLightSky / numberOfChildren;
|
||||
createDataPoint(tempAlpha, tempRed, tempGreen, tempBlue, height, depth, tempLightSky, tempLightBlock, tempGenMode, allDefault);
|
||||
dataPointColor[j] = ThreadMapUtil.dataPointColor;
|
||||
dataPointData[j] = ThreadMapUtil.dataPointData;
|
||||
dataPointFlags[j] = ThreadMapUtil.dataPointFlags;
|
||||
}
|
||||
}
|
||||
}
|
||||
return dataPoint;
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,7 @@ import com.seibel.lod.core.enums.config.DistanceGenerationMode;
|
||||
import com.seibel.lod.core.enums.config.HorizontalQuality;
|
||||
import com.seibel.lod.core.enums.config.HorizontalResolution;
|
||||
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
|
||||
import com.seibel.lod.forge.wrappers.minecraft.MinecraftRenderWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -33,13 +33,13 @@ import com.seibel.lod.forge.wrappers.minecraft.MinecraftRenderWrapper;
|
||||
public class DetailDistanceUtil
|
||||
{
|
||||
private static final ILodConfigWrapperSingleton CONFIG = SingletonHandler.get(ILodConfigWrapperSingleton.class);
|
||||
private static final MinecraftRenderWrapper MC_RENDER = MinecraftRenderWrapper.INSTANCE;
|
||||
private static final IMinecraftRenderWrapper MC_RENDER = SingletonHandler.get(IMinecraftRenderWrapper.class);
|
||||
|
||||
private static final double genMultiplier = 1.0;
|
||||
private static final double treeGenMultiplier = 1.0;
|
||||
private static final double treeCutMultiplier = 1.0;
|
||||
private static byte minGenDetail = CONFIG.client().graphics().quality().getDrawResolution().detailLevel;
|
||||
private static byte minDrawDetail = (byte) Math.max(CONFIG.client().graphics().quality().getDrawResolution().detailLevel, CONFIG.client().graphics().quality().getDrawResolution().detailLevel);
|
||||
private static byte minDrawDetail = CONFIG.client().graphics().quality().getDrawResolution().detailLevel;
|
||||
private static final int maxDetail = LodUtil.REGION_DETAIL_LEVEL + 1;
|
||||
private static final int minDistance = 0;
|
||||
private static int minDetailDistance = (int) (MC_RENDER.getRenderDistance()*16 * 1.42f);
|
||||
@@ -79,7 +79,7 @@ public class DetailDistanceUtil
|
||||
if (CONFIG.client().graphics().advancedGraphics().getAlwaysDrawAtMaxQuality())
|
||||
return detail * 0x10000; //if you want more you are doing wrong
|
||||
|
||||
int distanceUnit = CONFIG.client().graphics().quality().getHorizontalScale().distanceUnit;
|
||||
int distanceUnit = CONFIG.client().graphics().quality().getHorizontalScale() * 16;
|
||||
if (CONFIG.client().graphics().quality().getHorizontalQuality() == HorizontalQuality.LOWEST)
|
||||
return (detail * distanceUnit);
|
||||
else
|
||||
@@ -96,14 +96,14 @@ public class DetailDistanceUtil
|
||||
|
||||
public static byte baseInverseFunction(int distance, byte minDetail, boolean useRenderMinDistance)
|
||||
{
|
||||
int detail;
|
||||
byte detail;
|
||||
if (distance == 0
|
||||
|| (distance < minDetailDistance && useRenderMinDistance)
|
||||
|| CONFIG.client().graphics().advancedGraphics().getAlwaysDrawAtMaxQuality())
|
||||
return minDetail;
|
||||
int distanceUnit = CONFIG.client().graphics().quality().getHorizontalScale().distanceUnit;
|
||||
int distanceUnit = CONFIG.client().graphics().quality().getHorizontalScale() * 16;
|
||||
if (CONFIG.client().graphics().quality().getHorizontalQuality() == HorizontalQuality.LOWEST)
|
||||
detail = (byte) distance / distanceUnit;
|
||||
detail = (byte) (distance / distanceUnit);
|
||||
else
|
||||
{
|
||||
double base = CONFIG.client().graphics().quality().getHorizontalQuality().quadraticBase;
|
||||
@@ -139,12 +139,12 @@ public class DetailDistanceUtil
|
||||
return CONFIG.client().worldGenerator().getDistanceGenerationMode();
|
||||
}
|
||||
|
||||
public static byte getLodDrawDetail(int detail)
|
||||
public static byte getLodDrawDetail(byte detail)
|
||||
{
|
||||
if (detail < minDrawDetail)
|
||||
return minDrawDetail;
|
||||
else
|
||||
return (byte) detail;
|
||||
detail += minDrawDetail;
|
||||
if (detail > 10)
|
||||
detail = 10;
|
||||
return detail;
|
||||
}
|
||||
|
||||
public static HorizontalResolution getLodGenDetail(int detail)
|
||||
|
||||
@@ -26,7 +26,7 @@ import java.util.HashSet;
|
||||
import com.seibel.lod.core.enums.LodDirection;
|
||||
import com.seibel.lod.core.enums.config.HorizontalResolution;
|
||||
import com.seibel.lod.core.enums.config.VanillaOverdraw;
|
||||
import com.seibel.lod.core.objects.Box;
|
||||
import com.seibel.lod.core.objects.VertexOptimizer;
|
||||
import com.seibel.lod.core.objects.lod.LodDimension;
|
||||
import com.seibel.lod.core.objects.lod.RegionPos;
|
||||
import com.seibel.lod.core.objects.opengl.DefaultLodVertexFormats;
|
||||
@@ -35,10 +35,10 @@ 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.config.ILodConfigWrapperSingleton;
|
||||
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.world.IDimensionTypeWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
|
||||
import com.seibel.lod.forge.wrappers.minecraft.MinecraftRenderWrapper;
|
||||
|
||||
/**
|
||||
* This class holds methods and constants that may be used in multiple places.
|
||||
@@ -49,7 +49,7 @@ import com.seibel.lod.forge.wrappers.minecraft.MinecraftRenderWrapper;
|
||||
public class LodUtil
|
||||
{
|
||||
private static final IMinecraftWrapper MC = SingletonHandler.get(IMinecraftWrapper.class);
|
||||
private static final MinecraftRenderWrapper MC_RENDER = MinecraftRenderWrapper.INSTANCE;
|
||||
private static final IMinecraftRenderWrapper MC_RENDER = SingletonHandler.get(IMinecraftRenderWrapper.class);
|
||||
private static final ILodConfigWrapperSingleton CONFIG = SingletonHandler.get(ILodConfigWrapperSingleton.class);
|
||||
private static final IWrapperFactory FACTORY = SingletonHandler.get(IWrapperFactory.class);
|
||||
|
||||
@@ -403,10 +403,10 @@ public class LodUtil
|
||||
return false;
|
||||
int tempX;
|
||||
int tempZ;
|
||||
for (LodDirection lodDirection : Box.ADJ_DIRECTIONS)
|
||||
for (LodDirection lodDirection : VertexOptimizer.ADJ_DIRECTIONS)
|
||||
{
|
||||
tempX = x + Box.DIRECTION_NORMAL_MAP.get(lodDirection).x;
|
||||
tempZ = z + Box.DIRECTION_NORMAL_MAP.get(lodDirection).z;
|
||||
tempX = x + VertexOptimizer.DIRECTION_NORMAL_MAP.get(lodDirection).x;
|
||||
tempZ = z + VertexOptimizer.DIRECTION_NORMAL_MAP.get(lodDirection).z;
|
||||
if (vanillaRenderedChunks[x][z] || (!(tempX < 0 || tempZ < 0 || tempX >= vanillaRenderedChunks.length || tempZ >= vanillaRenderedChunks[0].length)
|
||||
&& !vanillaRenderedChunks[tempX][tempZ]))
|
||||
return true;
|
||||
|
||||
@@ -40,7 +40,7 @@ public class SingletonHandler
|
||||
/**
|
||||
* Adds the given singleton so it can be referenced later.
|
||||
*
|
||||
* @param objectClass
|
||||
* @param interfaceClass
|
||||
* @param singletonReference
|
||||
* @throws IllegalStateException
|
||||
*/
|
||||
|
||||
@@ -26,7 +26,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
import com.seibel.lod.core.enums.LodDirection;
|
||||
import com.seibel.lod.core.objects.Box;
|
||||
import com.seibel.lod.core.objects.VertexOptimizer;
|
||||
|
||||
/**
|
||||
* Holds data used by specific threads so
|
||||
@@ -38,15 +38,18 @@ import com.seibel.lod.core.objects.Box;
|
||||
*/
|
||||
public class ThreadMapUtil
|
||||
{
|
||||
public static final ConcurrentMap<String, long[]> threadSingleUpdateMap = new ConcurrentHashMap<>();
|
||||
public static final ConcurrentMap<String, long[][]> threadBuilderArrayMap = new ConcurrentHashMap<>();
|
||||
public static final ConcurrentMap<String, long[][]> threadBuilderVerticalArrayMap = new ConcurrentHashMap<>();
|
||||
public static final ConcurrentMap<String, long[]> threadVerticalAddDataMap = new ConcurrentHashMap<>();
|
||||
public static final ConcurrentMap<String, int[][]> threadBuilderVerticalArrayMapColor = new ConcurrentHashMap<>();
|
||||
public static final ConcurrentMap<String, int[][]> threadBuilderVerticalArrayMapData = new ConcurrentHashMap<>();
|
||||
public static final ConcurrentMap<String, byte[][]> threadBuilderVerticalArrayMapFlags = new ConcurrentHashMap<>();
|
||||
public static final ConcurrentMap<String, int[]> threadVerticalAddDataMapColor = new ConcurrentHashMap<>();
|
||||
public static final ConcurrentMap<String, int[]> threadVerticalAddDataMapData = new ConcurrentHashMap<>();
|
||||
public static final ConcurrentMap<String, byte[]> threadVerticalAddDataMapFlags = new ConcurrentHashMap<>();
|
||||
public static final ConcurrentMap<String, byte[][]> saveContainer = new ConcurrentHashMap<>();
|
||||
public static final ConcurrentMap<String, short[]> projectionArrayMap = new ConcurrentHashMap<>();
|
||||
public static final ConcurrentMap<String, short[]> heightAndDepthMap = new ConcurrentHashMap<>();
|
||||
public static final ConcurrentMap<String, long[]> singleDataToMergeMap = new ConcurrentHashMap<>();
|
||||
public static final ConcurrentMap<String, long[][]> verticalUpdate = new ConcurrentHashMap<>();
|
||||
public static final ConcurrentMap<String, int[][]> verticalUpdateColor = new ConcurrentHashMap<>();
|
||||
public static final ConcurrentMap<String, int[][]> verticalUpdateData = new ConcurrentHashMap<>();
|
||||
public static final ConcurrentMap<String, byte[][]> verticalUpdateFlags = new ConcurrentHashMap<>();
|
||||
|
||||
|
||||
//________________________//
|
||||
@@ -54,8 +57,13 @@ public class ThreadMapUtil
|
||||
//________________________//
|
||||
|
||||
public static final ConcurrentMap<String, boolean[]> adjShadeDisabled = new ConcurrentHashMap<>();
|
||||
public static final ConcurrentMap<String, Map<LodDirection, long[]>> adjDataMap = new ConcurrentHashMap<>();
|
||||
public static final ConcurrentMap<String, Box> boxMap = new ConcurrentHashMap<>();
|
||||
public static final ConcurrentMap<String, Map<LodDirection, int[]>> adjDataMap = new ConcurrentHashMap<>();
|
||||
public static final ConcurrentMap<String, Map<LodDirection, byte[]>> adjFlagsMap = new ConcurrentHashMap<>();
|
||||
public static final ConcurrentMap<String, VertexOptimizer> boxMap = new ConcurrentHashMap<>();
|
||||
|
||||
public static int dataPointColor = 0;
|
||||
public static int dataPointData = 0;
|
||||
public static byte dataPointFlags = 0;
|
||||
|
||||
|
||||
|
||||
@@ -65,14 +73,14 @@ public class ThreadMapUtil
|
||||
if (!adjShadeDisabled.containsKey(Thread.currentThread().getName())
|
||||
|| (adjShadeDisabled.get(Thread.currentThread().getName()) == null))
|
||||
{
|
||||
adjShadeDisabled.put(Thread.currentThread().getName(), new boolean[Box.DIRECTIONS.length]);
|
||||
adjShadeDisabled.put(Thread.currentThread().getName(), new boolean[VertexOptimizer.DIRECTIONS.length]);
|
||||
}
|
||||
Arrays.fill(adjShadeDisabled.get(Thread.currentThread().getName()), false);
|
||||
return adjShadeDisabled.get(Thread.currentThread().getName());
|
||||
}
|
||||
|
||||
/** returns the array NOT cleared every time */
|
||||
public static Map<LodDirection, long[]> getAdjDataArray(int verticalData)
|
||||
public static Map<LodDirection, int[]> getAdjDataArray(int verticalData)
|
||||
{
|
||||
if (!adjDataMap.containsKey(Thread.currentThread().getName())
|
||||
|| (adjDataMap.get(Thread.currentThread().getName()) == null)
|
||||
@@ -80,26 +88,47 @@ public class ThreadMapUtil
|
||||
|| (adjDataMap.get(Thread.currentThread().getName()).get(LodDirection.NORTH).length != verticalData))
|
||||
{
|
||||
adjDataMap.put(Thread.currentThread().getName(), new HashMap<>());
|
||||
adjDataMap.get(Thread.currentThread().getName()).put(LodDirection.UP, new long[1]);
|
||||
adjDataMap.get(Thread.currentThread().getName()).put(LodDirection.DOWN, new long[1]);
|
||||
for (LodDirection lodDirection : Box.ADJ_DIRECTIONS)
|
||||
adjDataMap.get(Thread.currentThread().getName()).put(lodDirection, new long[verticalData]);
|
||||
adjDataMap.get(Thread.currentThread().getName()).put(LodDirection.UP, new int[1]);
|
||||
adjDataMap.get(Thread.currentThread().getName()).put(LodDirection.DOWN, new int[1]);
|
||||
for (LodDirection lodDirection : VertexOptimizer.ADJ_DIRECTIONS)
|
||||
adjDataMap.get(Thread.currentThread().getName()).put(lodDirection, new int[verticalData]);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
for (LodDirection lodDirection : Box.ADJ_DIRECTIONS)
|
||||
Arrays.fill(adjDataMap.get(Thread.currentThread().getName()).get(lodDirection), DataPointUtil.EMPTY_DATA);
|
||||
for (LodDirection lodDirection : VertexOptimizer.ADJ_DIRECTIONS)
|
||||
Arrays.fill(adjDataMap.get(Thread.currentThread().getName()).get(lodDirection), 0);
|
||||
}
|
||||
return adjDataMap.get(Thread.currentThread().getName());
|
||||
}
|
||||
|
||||
public static Box getBox()
|
||||
/** returns the array NOT cleared every time */
|
||||
public static Map<LodDirection, byte[]> getAdjFlagsArray(int verticalData)
|
||||
{
|
||||
if (!adjFlagsMap.containsKey(Thread.currentThread().getName())
|
||||
|| (adjFlagsMap.get(Thread.currentThread().getName()) == null)
|
||||
|| (adjFlagsMap.get(Thread.currentThread().getName()).get(LodDirection.NORTH) == null)
|
||||
|| (adjFlagsMap.get(Thread.currentThread().getName()).get(LodDirection.NORTH).length != verticalData))
|
||||
{
|
||||
adjFlagsMap.put(Thread.currentThread().getName(), new HashMap<>());
|
||||
adjFlagsMap.get(Thread.currentThread().getName()).put(LodDirection.UP, new byte[1]);
|
||||
adjFlagsMap.get(Thread.currentThread().getName()).put(LodDirection.DOWN, new byte[1]);
|
||||
for (LodDirection lodDirection : VertexOptimizer.ADJ_DIRECTIONS)
|
||||
adjFlagsMap.get(Thread.currentThread().getName()).put(lodDirection, new byte[verticalData]);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (LodDirection lodDirection : VertexOptimizer.ADJ_DIRECTIONS)
|
||||
Arrays.fill(adjFlagsMap.get(Thread.currentThread().getName()).get(lodDirection), (byte) 0);
|
||||
}
|
||||
return adjFlagsMap.get(Thread.currentThread().getName());
|
||||
}
|
||||
|
||||
public static VertexOptimizer getBox()
|
||||
{
|
||||
if (!boxMap.containsKey(Thread.currentThread().getName())
|
||||
|| (boxMap.get(Thread.currentThread().getName()) == null))
|
||||
{
|
||||
boxMap.put(Thread.currentThread().getName(), new Box());
|
||||
boxMap.put(Thread.currentThread().getName(), new VertexOptimizer());
|
||||
}
|
||||
boxMap.get(Thread.currentThread().getName()).reset();
|
||||
return boxMap.get(Thread.currentThread().getName());
|
||||
@@ -119,21 +148,57 @@ public class ThreadMapUtil
|
||||
|
||||
|
||||
/** returns the array filled with 0's */
|
||||
public static long[] getBuilderVerticalArray(int detailLevel)
|
||||
public static int[] getBuilderVerticalArrayColor(int detailLevel)
|
||||
{
|
||||
if (!threadBuilderVerticalArrayMap.containsKey(Thread.currentThread().getName()) || (threadBuilderVerticalArrayMap.get(Thread.currentThread().getName()) == null))
|
||||
if (!threadBuilderVerticalArrayMapColor.containsKey(Thread.currentThread().getName()) || (threadBuilderVerticalArrayMapColor.get(Thread.currentThread().getName()) == null))
|
||||
{
|
||||
long[][] array = new long[5][];
|
||||
int[][] array = new int[5][];
|
||||
int size;
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
size = 1 << i;
|
||||
array[i] = new long[size * size * (DataPointUtil.worldHeight / 2 + 1)];
|
||||
array[i] = new int[size * size * (DataPointUtil.WORLD_HEIGHT / 2 + 1)];
|
||||
}
|
||||
threadBuilderVerticalArrayMap.put(Thread.currentThread().getName(), array);
|
||||
threadBuilderVerticalArrayMapColor.put(Thread.currentThread().getName(), array);
|
||||
}
|
||||
Arrays.fill(threadBuilderVerticalArrayMap.get(Thread.currentThread().getName())[detailLevel], 0);
|
||||
return threadBuilderVerticalArrayMap.get(Thread.currentThread().getName())[detailLevel];
|
||||
Arrays.fill(threadBuilderVerticalArrayMapColor.get(Thread.currentThread().getName())[detailLevel], 0);
|
||||
return threadBuilderVerticalArrayMapColor.get(Thread.currentThread().getName())[detailLevel];
|
||||
}
|
||||
|
||||
/** returns the array filled with 0's */
|
||||
public static int[] getBuilderVerticalArrayData(int detailLevel)
|
||||
{
|
||||
if (!threadBuilderVerticalArrayMapData.containsKey(Thread.currentThread().getName()) || (threadBuilderVerticalArrayMapData.get(Thread.currentThread().getName()) == null))
|
||||
{
|
||||
int[][] array = new int[5][];
|
||||
int size;
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
size = 1 << i;
|
||||
array[i] = new int[size * size * (DataPointUtil.WORLD_HEIGHT / 2 + 1)];
|
||||
}
|
||||
threadBuilderVerticalArrayMapData.put(Thread.currentThread().getName(), array);
|
||||
}
|
||||
Arrays.fill(threadBuilderVerticalArrayMapData.get(Thread.currentThread().getName())[detailLevel], 0);
|
||||
return threadBuilderVerticalArrayMapData.get(Thread.currentThread().getName())[detailLevel];
|
||||
}
|
||||
|
||||
/** returns the array filled with 0's */
|
||||
public static byte[] getBuilderVerticalArrayFlags(int detailLevel)
|
||||
{
|
||||
if (!threadBuilderVerticalArrayMapFlags.containsKey(Thread.currentThread().getName()) || (threadBuilderVerticalArrayMapFlags.get(Thread.currentThread().getName()) == null))
|
||||
{
|
||||
byte[][] array = new byte[5][];
|
||||
int size;
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
size = 1 << i;
|
||||
array[i] = new byte[size * size * (DataPointUtil.WORLD_HEIGHT / 2 + 1)];
|
||||
}
|
||||
threadBuilderVerticalArrayMapFlags.put(Thread.currentThread().getName(), array);
|
||||
}
|
||||
Arrays.fill(threadBuilderVerticalArrayMapFlags.get(Thread.currentThread().getName())[detailLevel], (byte) 0);
|
||||
return threadBuilderVerticalArrayMapFlags.get(Thread.currentThread().getName())[detailLevel];
|
||||
}
|
||||
|
||||
/** returns the array NOT cleared every time */
|
||||
@@ -145,7 +210,7 @@ public class ThreadMapUtil
|
||||
int size = 1;
|
||||
for (int i = LodUtil.DETAIL_OPTIONS - 1; i >= 0; i--)
|
||||
{
|
||||
array[i] = new byte[2 + 8 * size * size * DetailDistanceUtil.getMaxVerticalData(i)];
|
||||
array[i] = new byte[2 + 9 * size * size * DetailDistanceUtil.getMaxVerticalData(i)];
|
||||
size = size << 1;
|
||||
}
|
||||
saveContainer.put(Thread.currentThread().getName(), array);
|
||||
@@ -156,19 +221,46 @@ public class ThreadMapUtil
|
||||
|
||||
|
||||
/** returns the array filled with 0's */
|
||||
public static long[] getVerticalDataArray(int arrayLength)
|
||||
public static int[] getVerticalDataArrayColor(int arrayLength)
|
||||
{
|
||||
if (!threadVerticalAddDataMap.containsKey(Thread.currentThread().getName()) || (threadVerticalAddDataMap.get(Thread.currentThread().getName()) == null))
|
||||
{
|
||||
threadVerticalAddDataMap.put(Thread.currentThread().getName(), new long[arrayLength]);
|
||||
}
|
||||
if (!threadVerticalAddDataMapColor.containsKey(Thread.currentThread().getName()) || (threadVerticalAddDataMapColor.get(Thread.currentThread().getName()) == null))
|
||||
threadVerticalAddDataMapColor.put(Thread.currentThread().getName(), new int[arrayLength]);
|
||||
else
|
||||
{
|
||||
Arrays.fill(threadVerticalAddDataMap.get(Thread.currentThread().getName()), 0);
|
||||
}
|
||||
return threadVerticalAddDataMap.get(Thread.currentThread().getName());
|
||||
Arrays.fill(threadVerticalAddDataMapColor.get(Thread.currentThread().getName()), 0);
|
||||
return threadVerticalAddDataMapColor.get(Thread.currentThread().getName());
|
||||
}
|
||||
public static int[] getRawVerticalDataArrayColor()
|
||||
{
|
||||
return threadVerticalAddDataMapColor.get(Thread.currentThread().getName());
|
||||
}
|
||||
|
||||
/** returns the array filled with 0's */
|
||||
public static int[] getVerticalDataArrayData(int arrayLength)
|
||||
{
|
||||
if (!threadVerticalAddDataMapData.containsKey(Thread.currentThread().getName()) || (threadVerticalAddDataMapData.get(Thread.currentThread().getName()) == null))
|
||||
threadVerticalAddDataMapData.put(Thread.currentThread().getName(), new int[arrayLength]);
|
||||
else
|
||||
Arrays.fill(threadVerticalAddDataMapData.get(Thread.currentThread().getName()), 0);
|
||||
return threadVerticalAddDataMapData.get(Thread.currentThread().getName());
|
||||
}
|
||||
public static int[] getRawVerticalDataArrayData()
|
||||
{
|
||||
return threadVerticalAddDataMapData.get(Thread.currentThread().getName());
|
||||
}
|
||||
|
||||
/** returns the array filled with 0's */
|
||||
public static byte[] getVerticalDataArrayFlags(int arrayLength)
|
||||
{
|
||||
if (!threadVerticalAddDataMapFlags.containsKey(Thread.currentThread().getName()) || (threadVerticalAddDataMapFlags.get(Thread.currentThread().getName()) == null))
|
||||
threadVerticalAddDataMapFlags.put(Thread.currentThread().getName(), new byte[arrayLength]);
|
||||
else
|
||||
Arrays.fill(threadVerticalAddDataMapFlags.get(Thread.currentThread().getName()), (byte) 0);
|
||||
return threadVerticalAddDataMapFlags.get(Thread.currentThread().getName());
|
||||
}
|
||||
public static byte[] getRawVerticalDataArrayFlags()
|
||||
{
|
||||
return threadVerticalAddDataMapFlags.get(Thread.currentThread().getName());
|
||||
}
|
||||
|
||||
|
||||
/** returns the array NOT cleared every time */
|
||||
@@ -181,22 +273,49 @@ public class ThreadMapUtil
|
||||
return heightAndDepthMap.get(Thread.currentThread().getName());
|
||||
}
|
||||
|
||||
|
||||
/** returns the array filled with 0's */
|
||||
public static long[] getVerticalUpdateArray(int detailLevel)
|
||||
public static int[] getVerticalUpdateArrayColor(int detailLevel)
|
||||
{
|
||||
if (!verticalUpdate.containsKey(Thread.currentThread().getName()) || (verticalUpdate.get(Thread.currentThread().getName()) == null))
|
||||
if (!verticalUpdateColor.containsKey(Thread.currentThread().getName()) || (verticalUpdateColor.get(Thread.currentThread().getName()) == null))
|
||||
{
|
||||
long[][] array = new long[LodUtil.DETAIL_OPTIONS][];
|
||||
int[][] array = new int[LodUtil.DETAIL_OPTIONS][];
|
||||
for (int i = 1; i < LodUtil.DETAIL_OPTIONS; i++)
|
||||
array[i] = new long[DetailDistanceUtil.getMaxVerticalData(i - 1) * 4];
|
||||
verticalUpdate.put(Thread.currentThread().getName(), array);
|
||||
array[i] = new int[DetailDistanceUtil.getMaxVerticalData(i - 1) * 4];
|
||||
verticalUpdateColor.put(Thread.currentThread().getName(), array);
|
||||
}
|
||||
else
|
||||
Arrays.fill(verticalUpdateColor.get(Thread.currentThread().getName())[detailLevel], 0);
|
||||
return verticalUpdateColor.get(Thread.currentThread().getName())[detailLevel];
|
||||
}
|
||||
|
||||
/** returns the array filled with 0's */
|
||||
public static int[] getVerticalUpdateArrayData(int detailLevel)
|
||||
{
|
||||
if (!verticalUpdateData.containsKey(Thread.currentThread().getName()) || (verticalUpdateData.get(Thread.currentThread().getName()) == null))
|
||||
{
|
||||
Arrays.fill(verticalUpdate.get(Thread.currentThread().getName())[detailLevel], 0);
|
||||
int[][] array = new int[LodUtil.DETAIL_OPTIONS][];
|
||||
for (int i = 1; i < LodUtil.DETAIL_OPTIONS; i++)
|
||||
array[i] = new int[DetailDistanceUtil.getMaxVerticalData(i - 1) * 4];
|
||||
verticalUpdateData.put(Thread.currentThread().getName(), array);
|
||||
}
|
||||
return verticalUpdate.get(Thread.currentThread().getName())[detailLevel];
|
||||
else
|
||||
Arrays.fill(verticalUpdateData.get(Thread.currentThread().getName())[detailLevel], 0);
|
||||
return verticalUpdateData.get(Thread.currentThread().getName())[detailLevel];
|
||||
}
|
||||
|
||||
/** returns the array filled with 0's */
|
||||
public static byte[] getVerticalUpdateArrayFlags(int detailLevel)
|
||||
{
|
||||
if (!verticalUpdateFlags.containsKey(Thread.currentThread().getName()) || (verticalUpdateFlags.get(Thread.currentThread().getName()) == null))
|
||||
{
|
||||
byte[][] array = new byte[LodUtil.DETAIL_OPTIONS][];
|
||||
for (int i = 1; i < LodUtil.DETAIL_OPTIONS; i++)
|
||||
array[i] = new byte[DetailDistanceUtil.getMaxVerticalData(i - 1) * 4];
|
||||
verticalUpdateFlags.put(Thread.currentThread().getName(), array);
|
||||
}
|
||||
else
|
||||
Arrays.fill(verticalUpdateFlags.get(Thread.currentThread().getName())[detailLevel], (byte) 0);
|
||||
return verticalUpdateFlags.get(Thread.currentThread().getName())[detailLevel];
|
||||
}
|
||||
|
||||
/** clears all arrays so they will have to be rebuilt */
|
||||
@@ -205,14 +324,24 @@ public class ThreadMapUtil
|
||||
adjShadeDisabled.clear();
|
||||
adjDataMap.clear();
|
||||
boxMap.clear();
|
||||
threadSingleUpdateMap.clear();
|
||||
threadBuilderArrayMap.clear();
|
||||
threadBuilderVerticalArrayMap.clear();
|
||||
threadVerticalAddDataMap.clear();
|
||||
threadBuilderVerticalArrayMapColor.clear();
|
||||
threadBuilderVerticalArrayMapData.clear();
|
||||
threadBuilderVerticalArrayMapFlags.clear();
|
||||
threadVerticalAddDataMapColor.clear();
|
||||
threadVerticalAddDataMapData.clear();
|
||||
threadVerticalAddDataMapFlags.clear();
|
||||
saveContainer.clear();
|
||||
projectionArrayMap.clear();
|
||||
heightAndDepthMap.clear();
|
||||
singleDataToMergeMap.clear();
|
||||
verticalUpdate.clear();
|
||||
verticalUpdateColor.clear();
|
||||
verticalUpdateData.clear();
|
||||
verticalUpdateFlags.clear();
|
||||
}
|
||||
|
||||
public static void saveDataPoint(int color, int data, byte flags)
|
||||
{
|
||||
dataPointColor = color;
|
||||
dataPointData = data;
|
||||
dataPointFlags = flags;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,15 +34,15 @@ import com.seibel.lod.core.wrapperInterfaces.worldGeneration.AbstractWorldGenera
|
||||
*/
|
||||
public interface IWrapperFactory
|
||||
{
|
||||
public AbstractBlockPosWrapper createBlockPos();
|
||||
public AbstractBlockPosWrapper createBlockPos(int x, int y, int z);
|
||||
AbstractBlockPosWrapper createBlockPos();
|
||||
AbstractBlockPosWrapper createBlockPos(int x, int y, int z);
|
||||
|
||||
|
||||
public AbstractChunkPosWrapper createChunkPos();
|
||||
public AbstractChunkPosWrapper createChunkPos(int x, int z);
|
||||
public AbstractChunkPosWrapper createChunkPos(AbstractChunkPosWrapper newChunkPos);
|
||||
public AbstractChunkPosWrapper createChunkPos(AbstractBlockPosWrapper blockPos);
|
||||
AbstractChunkPosWrapper createChunkPos();
|
||||
AbstractChunkPosWrapper createChunkPos(int x, int z);
|
||||
AbstractChunkPosWrapper createChunkPos(AbstractChunkPosWrapper newChunkPos);
|
||||
AbstractChunkPosWrapper createChunkPos(AbstractBlockPosWrapper blockPos);
|
||||
|
||||
|
||||
public AbstractWorldGeneratorWrapper createWorldGenerator(LodBuilder newLodBuilder, LodDimension newLodDimension, IWorldWrapper worldWrapper);
|
||||
AbstractWorldGeneratorWrapper createWorldGenerator(LodBuilder newLodBuilder, LodDimension newLodDimension, IWorldWrapper worldWrapper);
|
||||
}
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@ package com.seibel.lod.core.wrapperInterfaces.block;
|
||||
import com.seibel.lod.core.enums.LodDirection;
|
||||
|
||||
/**
|
||||
* BlockPos needs to be abstract instead of a interfaces
|
||||
* BlockPos needs to be abstract instead of an interfaces
|
||||
* so that we can define its constructors.
|
||||
*
|
||||
* @author James Seibel
|
||||
|
||||
+1
-1
@@ -30,6 +30,6 @@ package com.seibel.lod.core.wrapperInterfaces.block;
|
||||
public interface IBlockColorSingletonWrapper
|
||||
{
|
||||
/** @returns the base color of water (grey) */
|
||||
public IBlockColorWrapper getWaterColor();
|
||||
IBlockColorWrapper getWaterColor();
|
||||
}
|
||||
|
||||
|
||||
@@ -29,22 +29,22 @@ public interface IBlockColorWrapper
|
||||
//Colors getters//
|
||||
//--------------//
|
||||
|
||||
public boolean hasColor();
|
||||
boolean hasColor();
|
||||
|
||||
public int getColor();
|
||||
int getColor();
|
||||
|
||||
|
||||
//------------//
|
||||
//Tint getters//
|
||||
//------------//
|
||||
|
||||
public boolean hasTint();
|
||||
boolean hasTint();
|
||||
|
||||
public boolean hasGrassTint();
|
||||
boolean hasGrassTint();
|
||||
|
||||
public boolean hasFolliageTint();
|
||||
boolean hasFolliageTint();
|
||||
|
||||
public boolean hasWaterTint();
|
||||
boolean hasWaterTint();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -25,15 +25,15 @@ package com.seibel.lod.core.wrapperInterfaces.block;
|
||||
*/
|
||||
public interface IBlockShapeWrapper
|
||||
{
|
||||
public boolean ofBlockToAvoid();
|
||||
boolean ofBlockToAvoid();
|
||||
|
||||
//-----------------//
|
||||
//Avoidance getters//
|
||||
//-----------------//
|
||||
|
||||
public boolean isNonFull();
|
||||
boolean isNonFull();
|
||||
|
||||
public boolean hasNoCollision();
|
||||
boolean hasNoCollision();
|
||||
|
||||
public boolean isToAvoid();
|
||||
boolean isToAvoid();
|
||||
}
|
||||
+1
-1
@@ -23,7 +23,7 @@ import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
|
||||
|
||||
|
||||
/**
|
||||
* This is abstract instead of a interface so
|
||||
* This is abstract instead of an interface, so
|
||||
* we can define its constructors.
|
||||
*
|
||||
* @author James Seibel
|
||||
|
||||
@@ -22,7 +22,7 @@ package com.seibel.lod.core.wrapperInterfaces.chunk;
|
||||
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.block.IBlockColorWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.block.IBlockShapeWrapper;
|
||||
import com.seibel.lod.forge.wrappers.world.BiomeWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.world.IBiomeWrapper;
|
||||
|
||||
/**
|
||||
* @author James Seibel
|
||||
@@ -30,23 +30,23 @@ import com.seibel.lod.forge.wrappers.world.BiomeWrapper;
|
||||
*/
|
||||
public interface IChunkWrapper
|
||||
{
|
||||
public int getHeight();
|
||||
int getHeight();
|
||||
|
||||
public boolean isPositionInWater(AbstractBlockPosWrapper blockPos);
|
||||
boolean isPositionInWater(AbstractBlockPosWrapper blockPos);
|
||||
|
||||
public int getHeightMapValue(int xRel, int zRel);
|
||||
int getHeightMapValue(int xRel, int zRel);
|
||||
|
||||
public BiomeWrapper getBiome(int xRel, int yAbs, int zRel);
|
||||
IBiomeWrapper getBiome(int xRel, int yAbs, int zRel);
|
||||
|
||||
public IBlockColorWrapper getBlockColorWrapper(AbstractBlockPosWrapper blockPos);
|
||||
IBlockColorWrapper getBlockColorWrapper(AbstractBlockPosWrapper blockPos);
|
||||
|
||||
public IBlockShapeWrapper getBlockShapeWrapper(AbstractBlockPosWrapper blockPos);
|
||||
IBlockShapeWrapper getBlockShapeWrapper(AbstractBlockPosWrapper blockPos);
|
||||
|
||||
public AbstractChunkPosWrapper getPos();
|
||||
AbstractChunkPosWrapper getPos();
|
||||
|
||||
public boolean isLightCorrect();
|
||||
boolean isLightCorrect();
|
||||
|
||||
public boolean isWaterLogged(AbstractBlockPosWrapper blockPos);
|
||||
boolean isWaterLogged(AbstractBlockPosWrapper blockPos);
|
||||
|
||||
public int getEmittedBrightness(AbstractBlockPosWrapper blockPos);
|
||||
int getEmittedBrightness(AbstractBlockPosWrapper blockPos);
|
||||
}
|
||||
|
||||
+249
-163
@@ -31,8 +31,9 @@ import com.seibel.lod.core.enums.config.LodTemplate;
|
||||
import com.seibel.lod.core.enums.config.VanillaOverdraw;
|
||||
import com.seibel.lod.core.enums.config.VerticalQuality;
|
||||
import com.seibel.lod.core.enums.rendering.DebugMode;
|
||||
import com.seibel.lod.core.enums.rendering.FogColorMode;
|
||||
import com.seibel.lod.core.enums.rendering.FogDistance;
|
||||
import com.seibel.lod.core.enums.rendering.FogDrawOverride;
|
||||
import com.seibel.lod.core.enums.rendering.FogDrawMode;
|
||||
import com.seibel.lod.core.objects.MinDefaultMax;
|
||||
import com.seibel.lod.core.util.LodUtil;
|
||||
|
||||
@@ -42,120 +43,144 @@ import com.seibel.lod.core.util.LodUtil;
|
||||
* the options that should be implemented in a configWrapperSingleton.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 11-21-2021
|
||||
* @version 12-1-2021
|
||||
*/
|
||||
public interface ILodConfigWrapperSingleton
|
||||
{
|
||||
public IClient client();
|
||||
IClient client();
|
||||
|
||||
|
||||
public interface IClient
|
||||
interface IClient
|
||||
{
|
||||
public IGraphics graphics();
|
||||
public IWorldGenerator worldGenerator();
|
||||
public IAdvanced advanced();
|
||||
IGraphics graphics();
|
||||
IWorldGenerator worldGenerator();
|
||||
IAdvanced advanced();
|
||||
|
||||
|
||||
//==================//
|
||||
// Graphics Configs //
|
||||
//==================//
|
||||
public interface IGraphics
|
||||
interface IGraphics
|
||||
{
|
||||
public static final String DESC = "These settings control how the mod will look in game";
|
||||
String DESC = "These settings control how the mod will look in game";
|
||||
|
||||
public IQuality quality();
|
||||
public IFogQuality fogQuality();
|
||||
public IAdvancedGraphics advancedGraphics();
|
||||
IQuality quality();
|
||||
IFogQuality fogQuality();
|
||||
IAdvancedGraphics advancedGraphics();
|
||||
|
||||
|
||||
public interface IQuality
|
||||
interface IQuality
|
||||
{
|
||||
public static final String DESC = "These settings control how detailed the fake chunks will be.";
|
||||
String DESC = "These settings control how detailed the fake chunks will be.";
|
||||
|
||||
HorizontalResolution DRAW_RESOLUTION_DEFAULT = HorizontalResolution.BLOCK;
|
||||
public static final String DRAW_RESOLUTION_DESC = ""
|
||||
String DRAW_RESOLUTION_DESC = ""
|
||||
+ " What is the maximum detail fake chunks should be drawn at? \n"
|
||||
+ " This setting will only affect closer chunks.\n"
|
||||
+ " Higher settings will increase memory and GPU usage. \n"
|
||||
+ "\n"
|
||||
+ " " + HorizontalResolution.CHUNK + ": render 1 LOD for each Chunk. \n"
|
||||
+ " " + HorizontalResolution.HALF_CHUNK + ": render 4 LODs for each Chunk. \n"
|
||||
+ " " + HorizontalResolution.FOUR_BLOCKS + ": render 16 LODs for each Chunk. \n"
|
||||
+ " " + HorizontalResolution.TWO_BLOCKS + ": render 64 LODs for each Chunk. \n"
|
||||
+ " " + HorizontalResolution.BLOCK + ": render 256 LODs for each Chunk. \n";
|
||||
public HorizontalResolution getDrawResolution();
|
||||
public void setDrawResolution(HorizontalResolution newHorizontalResolution);
|
||||
+ " " + HorizontalResolution.BLOCK + ": render 256 LODs for each Chunk (width of one block). \n"
|
||||
+ "\n"
|
||||
+ " Lowest Quality: " + HorizontalResolution.CHUNK
|
||||
+ " Highest Quality: " + HorizontalResolution.BLOCK;
|
||||
HorizontalResolution getDrawResolution();
|
||||
void setDrawResolution(HorizontalResolution newHorizontalResolution);
|
||||
|
||||
MinDefaultMax<Integer> LOD_CHUNK_RENDER_DISTANCE_MIN_DEFAULT_MAX = new MinDefaultMax<Integer>(16, 64, 1024);
|
||||
String LOD_CHUNK_RENDER_DISTANCE_DESC = ""
|
||||
+ " The mod's render distance, measured in chunks. \n";
|
||||
public int getLodChunkRenderDistance();
|
||||
public void setLodChunkRenderDistance(int newLodChunkRenderDistance);
|
||||
+ " The radius of the mod's render distance. (measured in chunks) \n";
|
||||
int getLodChunkRenderDistance();
|
||||
void setLodChunkRenderDistance(int newLodChunkRenderDistance);
|
||||
|
||||
VerticalQuality VERTICAL_QUALITY_DEFAULT = VerticalQuality.MEDIUM;
|
||||
String VERTICAL_QUALITY_DESC = ""
|
||||
+ " This indicates how detailed fake chunks will represent \n"
|
||||
+ " overhangs, caves, floating islands, ect. \n"
|
||||
+ " Higher options will use more memory and increase GPU usage. \n"
|
||||
+ " Higher options will make the world more accurate, but"
|
||||
+ " will increase memory and GPU usage. \n"
|
||||
+ "\n"
|
||||
+ " " + VerticalQuality.LOW + ": uses at max 2 columns per position. \n"
|
||||
+ " " + VerticalQuality.MEDIUM + ": uses at max 4 columns per position. \n"
|
||||
+ " " + VerticalQuality.HIGH + ": uses at max 8 columns per position. \n";
|
||||
public VerticalQuality getVerticalQuality();
|
||||
public void setVerticalQuality(VerticalQuality newVerticalQuality);
|
||||
+ " " + VerticalQuality.HIGH + ": uses at max 8 columns per position. \n"
|
||||
+ "\n"
|
||||
+ " Lowest Quality: " + VerticalQuality.LOW
|
||||
+ " Highest Quality: " + VerticalQuality.HIGH;
|
||||
VerticalQuality getVerticalQuality();
|
||||
void setVerticalQuality(VerticalQuality newVerticalQuality);
|
||||
|
||||
HorizontalScale HORIZONTAL_SCALE_DEFAULT = HorizontalScale.MEDIUM;
|
||||
MinDefaultMax<Integer> HORIZONTAL_SCALE_MIN_DEFAULT_MAX = new MinDefaultMax<Integer>(2, 8, 32);
|
||||
String HORIZONTAL_SCALE_DESC = ""
|
||||
+ " This indicates how quickly fake chunks drop off in quality. \n"
|
||||
+ " " + HorizontalScale.LOW + ": quality drops every " + HorizontalScale.LOW.distanceUnit / 16 + " chunks. \n"
|
||||
+ " " + HorizontalScale.MEDIUM + ": quality drops every " + HorizontalScale.MEDIUM.distanceUnit / 16 + " chunks. \n"
|
||||
+ " " + HorizontalScale.HIGH + ": quality drops every " + HorizontalScale.HIGH.distanceUnit / 16 + " chunks. \n";
|
||||
public HorizontalScale getHorizontalScale();
|
||||
public void setHorizontalScale(HorizontalScale newHorizontalScale);
|
||||
+ " This indicates how quickly fake chunks decrease in quality the further away they are. \n"
|
||||
+ " Higher settings will render higher quality fake chunks farther away, \n"
|
||||
+ " but will increase memory and GPU usage.";
|
||||
int getHorizontalScale();
|
||||
void setHorizontalScale(int newHorizontalScale);
|
||||
|
||||
HorizontalQuality HORIZONTAL_QUALITY_DEFAULT = HorizontalQuality.MEDIUM;
|
||||
String HORIZONTAL_QUALITY_DESC = ""
|
||||
+ " This indicates the exponential base of the quadratic drop-off \n"
|
||||
+ "\n"
|
||||
+ " " + HorizontalQuality.LOWEST + ": base " + HorizontalQuality.LOWEST.quadraticBase + ". \n"
|
||||
+ " " + HorizontalQuality.LOW + ": base " + HorizontalQuality.LOW.quadraticBase + ". \n"
|
||||
+ " " + HorizontalQuality.MEDIUM + ": base " + HorizontalQuality.MEDIUM.quadraticBase + ". \n"
|
||||
+ " " + HorizontalQuality.HIGH + ": base " + HorizontalQuality.HIGH.quadraticBase + ". \n";
|
||||
public HorizontalQuality getHorizontalQuality();
|
||||
public void setHorizontalQuality(HorizontalQuality newHorizontalQuality);
|
||||
+ " " + HorizontalQuality.HIGH + ": base " + HorizontalQuality.HIGH.quadraticBase + ". \n"
|
||||
+ "\n"
|
||||
+ " Lowest Quality: " + HorizontalQuality.LOWEST
|
||||
+ " Highest Quality: " + HorizontalQuality.HIGH;
|
||||
HorizontalQuality getHorizontalQuality();
|
||||
void setHorizontalQuality(HorizontalQuality newHorizontalQuality);
|
||||
}
|
||||
|
||||
public interface IFogQuality
|
||||
interface IFogQuality
|
||||
{
|
||||
String DESC = "These settings control the fog quality.";
|
||||
|
||||
FogDistance FOG_DISTANCE_DEFAULT = FogDistance.FAR;
|
||||
String FOG_DISTANCE_DESC = ""
|
||||
+ " At what distance should Fog be drawn on the fake chunks? \n"
|
||||
+ " If the fog cuts off abruptly or you are using Optifine's \"fast\" fog option \n"
|
||||
+ " set this to " + FogDistance.NEAR + " or " + FogDistance.FAR + ". \n";
|
||||
public FogDistance getFogDistance();
|
||||
public void setFogDistance(FogDistance newFogDistance);
|
||||
+ "\n"
|
||||
+ " This setting shouldn't affect performance.";
|
||||
FogDistance getFogDistance();
|
||||
void setFogDistance(FogDistance newFogDistance);
|
||||
|
||||
FogDrawOverride FOG_DRAW_OVERRIDE_DEFAULT = FogDrawOverride.FANCY;
|
||||
String FOG_DRAW_OVERRIDE_DESC = ""
|
||||
FogDrawMode FOG_DRAW_MODE_DEFAULT = FogDrawMode.FOG_ENABLED;
|
||||
String FOG_DRAW_MODE_DESC = ""
|
||||
+ " When should fog be drawn? \n"
|
||||
+ " " + FogDrawOverride.OPTIFINE_SETTING + ": Use whatever Fog setting Optifine is using. If Optifine isn't installed this defaults to " + FogDrawOverride.FANCY + ". \n"
|
||||
+ " " + FogDrawOverride.NO_FOG + ": Never draw fog on the LODs \n"
|
||||
+ " " + FogDrawOverride.FAST + ": Always draw fast fog on the LODs \n"
|
||||
+ " " + FogDrawOverride.FANCY + ": Always draw fancy fog on the LODs (if your graphics card supports it) \n";
|
||||
public FogDrawOverride getFogDrawOverride();
|
||||
public void setFogDrawOverride(FogDrawOverride newFogDrawOverride);
|
||||
+ "\n"
|
||||
+ " " + FogDrawMode.USE_OPTIFINE_SETTING + ": Use whatever Fog setting Optifine is using. If Optifine isn't installed this defaults to " + FogDrawMode.FOG_ENABLED + ". \n"
|
||||
+ " " + FogDrawMode.FOG_ENABLED + ": Never draw fog on the LODs \n"
|
||||
+ " " + FogDrawMode.FOG_DISABLED + ": Always draw fast fog on the LODs \n"
|
||||
+ "\n"
|
||||
+ " Disabling fog will improve GPU performance.";
|
||||
FogDrawMode getFogDrawMode();
|
||||
void setFogDrawMode(FogDrawMode newFogDrawMode);
|
||||
|
||||
FogColorMode FOG_COLOR_MODE_DEFAULT = FogColorMode.USE_WORLD_FOG_COLOR;
|
||||
String FOG_COLOR_MODE_DESC = ""
|
||||
+ " What color should fog use? \n"
|
||||
+ "\n"
|
||||
+ " " + FogColorMode.USE_WORLD_FOG_COLOR + ": Use the world's fog color. \n"
|
||||
+ " " + FogColorMode.USE_SKY_COLOR + ": Use the sky's color. \n"
|
||||
+ "\n"
|
||||
+ " This setting doesn't affect performance.";
|
||||
FogColorMode getFogColorMode();
|
||||
void setFogColorMode(FogColorMode newFogColorMode);
|
||||
|
||||
boolean DISABLE_VANILLA_FOG_DEFAULT = false;
|
||||
String DISABLE_VANILLA_FOG_DESC = ""
|
||||
+ " If true disable Minecraft's fog. \n\n"
|
||||
+ ""
|
||||
+ " Experimental! May cause issues with Sodium. \n\n"
|
||||
+ ""
|
||||
+ " Unlike Optifine or Sodium's fog disabling option this won't change \n"
|
||||
+ " performance (we don't actually disable the fog, we just tell it to render a infinite distance away). \n"
|
||||
+ " May or may not play nice with other mods that edit fog. \n";
|
||||
public boolean getDisableVanillaFog();
|
||||
public void setDisableVanillaFog(boolean newDisableVanillaFog);
|
||||
+ " If true disable Minecraft's fog. \n"
|
||||
+ "\n"
|
||||
+ " Experimental! Will cause issues with Sodium and \n"
|
||||
+ " may not play nice with other mods that edit fog. \n";
|
||||
boolean getDisableVanillaFog();
|
||||
void setDisableVanillaFog(boolean newDisableVanillaFog);
|
||||
}
|
||||
|
||||
public interface IAdvancedGraphics
|
||||
interface IAdvancedGraphics
|
||||
{
|
||||
String DESC = "Graphics options that are a bit more technical.";
|
||||
|
||||
@@ -168,66 +193,58 @@ public interface ILodConfigWrapperSingleton
|
||||
+ " " + LodTemplate.TRIANGULAR + ": LOD Chunks smoothly transition between other. \n"
|
||||
+ " " + LodTemplate.DYNAMIC + ": LOD Chunks smoothly transition between each other, \n"
|
||||
+ " " + " unless a neighboring chunk is at a significantly different height. \n";
|
||||
public LodTemplate getLodTemplate();
|
||||
public void setLodTemplate(LodTemplate newLodTemplate);
|
||||
LodTemplate getLodTemplate();
|
||||
void setLodTemplate(LodTemplate newLodTemplate);
|
||||
|
||||
boolean DISABLE_DIRECTIONAL_CULLING_DEFAULT = false;
|
||||
String DISABLE_DIRECTIONAL_CULLING_DESC = ""
|
||||
+ " If false fake chunks behind the player's camera \n"
|
||||
+ " aren't drawn, increasing performance. \n\n"
|
||||
+ ""
|
||||
+ " aren't drawn, increasing GPU performance. \n"
|
||||
+ "\n"
|
||||
+ " If true all LODs are drawn, even those behind \n"
|
||||
+ " the player's camera, decreasing performance. \n\n"
|
||||
+ ""
|
||||
+ " Disable this if you see LODs disappearing. \n"
|
||||
+ " (Which may happen if you are using a camera mod) \n";
|
||||
public boolean getDisableDirectionalCulling();
|
||||
public void setDisableDirectionalCulling(boolean newDisableDirectionalCulling);
|
||||
+ " the player's camera, decreasing GPU performance. \n"
|
||||
+ "\n"
|
||||
+ " Disable this if you see LODs disappearing at the corners of your vision. \n";
|
||||
boolean getDisableDirectionalCulling();
|
||||
void setDisableDirectionalCulling(boolean newDisableDirectionalCulling);
|
||||
|
||||
boolean ALWAYS_DRAW_AT_MAD_QUALITY_DEFAULT = false;
|
||||
String ALWAYS_DRAW_AT_MAD_QUALITY_DESC = ""
|
||||
+ " Disable quality falloff, \n"
|
||||
+ " all fake chunks will be drawn at the highest \n"
|
||||
+ " available detail level. \n\n"
|
||||
+ " "
|
||||
+ " available detail level. \n"
|
||||
+ "\n"
|
||||
+ " WARNING: \n"
|
||||
+ " This could cause a Out Of Memory crash on render \n"
|
||||
+ " distances higher than 128 \n";
|
||||
public boolean getAlwaysDrawAtMaxQuality();
|
||||
public void setAlwaysDrawAtMaxQuality(boolean newAlwaysDrawAtMaxQuality);
|
||||
+ " This could cause an Out Of Memory crash when using render \n"
|
||||
+ " distances higher than 128 and will drastically increase GPU usage. \n";
|
||||
boolean getAlwaysDrawAtMaxQuality();
|
||||
void setAlwaysDrawAtMaxQuality(boolean newAlwaysDrawAtMaxQuality);
|
||||
|
||||
VanillaOverdraw VANILLA_OVERDRAW_DEFAULT = VanillaOverdraw.DYNAMIC;
|
||||
String VANILLA_OVERDRAW_DESC = ""
|
||||
+ " How often should LODs be drawn on top of regular chunks? \n"
|
||||
+ " HALF and ALWAYS will prevent holes in the world, but may look odd for transparent blocks or in caves. \n\n"
|
||||
+ " HALF and ALWAYS will prevent holes in the world, but may look odd for transparent blocks or in caves. \n"
|
||||
+ "\n"
|
||||
+ " " + VanillaOverdraw.NEVER + ": LODs won't render on top of vanilla chunks. \n"
|
||||
+ " " + VanillaOverdraw.BORDER + ": LODs will render only on the border of vanilla chunks preventing only some holes in the world. \n"
|
||||
+ " " + VanillaOverdraw.DYNAMIC + ": LODs will render on top of distant vanilla chunks to hide delayed loading. \n"
|
||||
+ " " + " More effective on higher render distances. \n"
|
||||
+ " " + " For vanilla render distances less than or equal to " + LodUtil.MINIMUM_RENDER_DISTANCE_FOR_PARTIAL_OVERDRAW + " \n"
|
||||
+ " " + " " + VanillaOverdraw.NEVER + " or " + VanillaOverdraw.ALWAYS + " may be used depending on the dimension. \n"
|
||||
+ " " + VanillaOverdraw.ALWAYS + ": LODs will render on all vanilla chunks preventing holes in the world. \n";
|
||||
public VanillaOverdraw getVanillaOverdraw();
|
||||
public void setVanillaOverdraw(VanillaOverdraw newVanillaOverdraw);
|
||||
|
||||
GpuUploadMethod GPU_UPLOAD_METHOD_DEFAULT = GpuUploadMethod.BUFFER_STORAGE;
|
||||
String GPU_UPLOAD_METHOD_DESC = ""
|
||||
+ " What method should be used to upload geometry to the GPU? \n"
|
||||
+ " Listed in the suggested order of best to worst. \n\n"
|
||||
+ ""
|
||||
+ " " + GpuUploadMethod.BUFFER_STORAGE + ": Default if OpenGL 4.5 is supported. Fast rendering, no stuttering. \n"
|
||||
+ " " + GpuUploadMethod.SUB_DATA + ": Default if OpenGL 4.5 is NOT supported. Fast rendering but may stutter when uploading. \n"
|
||||
+ " " + GpuUploadMethod.DATA + ": Fast rendering but will stutter when uploading. \n"
|
||||
+ " " + GpuUploadMethod.BUFFER_MAPPING + ": Slow rendering but won't stutter when uploading. Possibly better than " + GpuUploadMethod.SUB_DATA + " if using a integrated GPU. \n";
|
||||
public GpuUploadMethod getGpuUploadMethod();
|
||||
public void setGpuUploadMethod(GpuUploadMethod newDisableVanillaFog);
|
||||
+ " " + " " + VanillaOverdraw.NEVER + " or " + VanillaOverdraw.ALWAYS + " will be used depending on the dimension. \n"
|
||||
+ " " + VanillaOverdraw.ALWAYS + ": LODs will render on all vanilla chunks preventing holes in the world. \n"
|
||||
+ "\n"
|
||||
+ " This setting shouldn't affect performance. \n";
|
||||
VanillaOverdraw getVanillaOverdraw();
|
||||
void setVanillaOverdraw(VanillaOverdraw newVanillaOverdraw);
|
||||
|
||||
boolean USE_EXTENDED_NEAR_CLIP_PLANE_DEFAULT = false;
|
||||
String USE_EXTENDED_NEAR_CLIP_PLANE_DESC = ""
|
||||
+ " Will prevent some overdraw issues, but may cause nearby fake chunks to render incorrectly \n"
|
||||
+ " especially when in/near an ocean. \n";
|
||||
public boolean getUseExtendedNearClipPlane();
|
||||
public void setUseExtendedNearClipPlane(boolean newUseExtendedNearClipPlane);
|
||||
+ " especially when in/near an ocean. \n"
|
||||
+ "\n"
|
||||
+ " This setting shouldn't affect performance. \n";
|
||||
boolean getUseExtendedNearClipPlane();
|
||||
void setUseExtendedNearClipPlane(boolean newUseExtendedNearClipPlane);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -237,65 +254,77 @@ public interface ILodConfigWrapperSingleton
|
||||
//========================//
|
||||
// WorldGenerator Configs //
|
||||
//========================//
|
||||
public interface IWorldGenerator
|
||||
interface IWorldGenerator
|
||||
{
|
||||
String DESC = "These settings control how fake chunks outside your normal view range are generated.";
|
||||
|
||||
GenerationPriority GENERATION_PRIORITY_DEFAULT = GenerationPriority.FAR_FIRST;
|
||||
GenerationPriority GENERATION_PRIORITY_DEFAULT = GenerationPriority.AUTO;
|
||||
String GENERATION_PRIORITY_DESC = ""
|
||||
+ " In what order should fake chunks be generated outside the vanilla render distance? \n"
|
||||
+ "\n"
|
||||
+ " " + GenerationPriority.FAR_FIRST + " \n"
|
||||
+ " LODs are generated from low to high detail \n"
|
||||
+ " Fake chunks are generated from lowest to highest detail \n"
|
||||
+ " with a small priority for far away regions. \n"
|
||||
+ " This fills in the world fastest. \n\n"
|
||||
+ ""
|
||||
+ " This fills in the world fastest, but you will have large low detail \n"
|
||||
+ " blocks for a while while the generation happens. \n"
|
||||
+ "\n"
|
||||
+ " " + GenerationPriority.NEAR_FIRST + " \n"
|
||||
+ " LODs are generated around the player \n"
|
||||
+ " in a spiral, similar to vanilla minecraft. \n";
|
||||
public GenerationPriority getGenerationPriority();
|
||||
public void setGenerationPriority(GenerationPriority newGenerationPriority);
|
||||
+ " Fake chunks are generated around the player \n"
|
||||
+ " in a spiral, similar to vanilla minecraft. \n"
|
||||
+ " Best used when on a server since we can't generate \n"
|
||||
+ " fake chunks. \n"
|
||||
+ "\n"
|
||||
+ " " + GenerationPriority.AUTO + " \n"
|
||||
+ " Uses " + GenerationPriority.FAR_FIRST + " when on a single player world \n"
|
||||
+ " and " + GenerationPriority.NEAR_FIRST + " when connected to a server. \n"
|
||||
+ "\n"
|
||||
+ " This shouldn't affect performance.";
|
||||
GenerationPriority getGenerationPriority();
|
||||
void setGenerationPriority(GenerationPriority newGenerationPriority);
|
||||
|
||||
DistanceGenerationMode DISTANCE_GENERATION_MODE_DEFAULT = DistanceGenerationMode.SURFACE;
|
||||
String DISTANCE_GENERATION_MODE_DESC = ""
|
||||
+ " Note: The times listed here are the amount of time it took \n"
|
||||
+ " one of the developer's PC to generate 1 chunk, \n"
|
||||
+ " and are included so you can compare the \n"
|
||||
+ " different generation options. Your mileage may vary. \n\n"
|
||||
+ ""
|
||||
+ " How detailed should fake chunks be generated outside the vanilla render distance? \n"
|
||||
+ "\n"
|
||||
+ " " + DistanceGenerationMode.NONE + " \n"
|
||||
+ " Don't run the distance generator. \n\n"
|
||||
+ ""
|
||||
+ " Don't run the distance generator. \n"
|
||||
+ " No CPU usage - Fastest \n"
|
||||
+ "\n"
|
||||
+ " " + DistanceGenerationMode.BIOME_ONLY + " \n"
|
||||
+ " Only generate the biomes and use the biome's \n"
|
||||
+ " grass color, water color, or snow color. \n"
|
||||
+ " Doesn't generate height, everything is shown at sea level. \n"
|
||||
+ " Multithreaded - Fastest (2-5 ms) \n\n"
|
||||
+ ""
|
||||
+ " Multithreaded - Fastest (2-5 ms) \n"
|
||||
+ "\n"
|
||||
+ " " + DistanceGenerationMode.BIOME_ONLY_SIMULATE_HEIGHT + " \n"
|
||||
+ " Same as BIOME_ONLY, except instead \n"
|
||||
+ " Same as " + DistanceGenerationMode.BIOME_ONLY + ", except instead \n"
|
||||
+ " of always using sea level as the LOD height \n"
|
||||
+ " different biome types (mountain, ocean, forest, etc.) \n"
|
||||
+ " use predetermined heights to simulate having height data. \n"
|
||||
+ " Multithreaded - Fastest (2-5 ms) \n\n"
|
||||
+ ""
|
||||
+ " Multithreaded - Fastest (2-5 ms) \n"
|
||||
+ "\n"
|
||||
+ " " + DistanceGenerationMode.SURFACE + " \n"
|
||||
+ " Generate the world surface, \n"
|
||||
+ " this does NOT include trees, \n"
|
||||
+ " or structures. \n"
|
||||
+ " Multithreaded - Faster (10-20 ms) \n\n"
|
||||
+ ""
|
||||
+ " Multithreaded - Faster (10-20 ms) \n"
|
||||
+ "\n"
|
||||
+ " " + DistanceGenerationMode.FEATURES + " \n"
|
||||
+ " Generate everything except structures. \n"
|
||||
+ " WARNING: This may cause world generation bugs or instability! \n"
|
||||
+ " Multithreaded - Fast (15-20 ms) \n\n"
|
||||
+ ""
|
||||
+ " Multithreaded - Fast (15-20 ms) \n"
|
||||
+ "\n"
|
||||
+ " " + DistanceGenerationMode.FULL + " \n"
|
||||
+ " Ask the local server to generate/load each chunk. \n"
|
||||
+ " This will show player made structures, which can \n"
|
||||
+ " be useful if you are adding the mod to a pre-existing world. \n"
|
||||
+ " This is the most compatible, but causes server/simulation lag. \n"
|
||||
+ " SingleThreaded - Slow (15-50 ms, with spikes up to 200 ms) \n";
|
||||
public DistanceGenerationMode getDistanceGenerationMode();
|
||||
public void setDistanceGenerationMode(DistanceGenerationMode newDistanceGenerationMode);
|
||||
+ " SingleThreaded - Slow (15-50 ms, with spikes up to 200 ms) \n"
|
||||
+ "\n"
|
||||
+ " The multithreaded options may increase CPU load significantly (while generating) \n"
|
||||
+ " depending on how many world generation threads you have allocated. \n";
|
||||
DistanceGenerationMode getDistanceGenerationMode();
|
||||
void setDistanceGenerationMode(DistanceGenerationMode newDistanceGenerationMode);
|
||||
|
||||
boolean ALLOW_UNSTABLE_FEATURE_GENERATION_DEFAULT = false;
|
||||
String ALLOW_UNSTABLE_FEATURE_GENERATION_DESC = ""
|
||||
@@ -309,25 +338,29 @@ public interface ILodConfigWrapperSingleton
|
||||
+ " so some trees may not be generated.) \n"
|
||||
+ " By setting this to true, all features will be generated, \n"
|
||||
+ " but your game will be more unstable and crashes may occur. \n"
|
||||
+ " \n"
|
||||
+ "\n"
|
||||
+ " I would love to remove this option and always generate everything, \n"
|
||||
+ " but I'm not sure how to do that. \n"
|
||||
+ " If you are a Java wizard, check out the git issue here: \n"
|
||||
+ " https://gitlab.com/jeseibel/minecraft-lod-mod/-/issues/35 \n";
|
||||
public boolean getAllowUnstableFeatureGeneration();
|
||||
public void setAllowUnstableFeatureGeneration(boolean newAllowUnstableFeatureGeneration);
|
||||
boolean getAllowUnstableFeatureGeneration();
|
||||
void setAllowUnstableFeatureGeneration(boolean newAllowUnstableFeatureGeneration);
|
||||
|
||||
BlocksToAvoid BLOCKS_TO_AVOID_DEFAULT = BlocksToAvoid.BOTH;
|
||||
String BLOCKS_TO_AVOID_DESC = ""
|
||||
+ " " + BlocksToAvoid.NONE + ": Use all blocks when generating fake chunks \n\n"
|
||||
+ ""
|
||||
+ " " + BlocksToAvoid.NON_FULL + ": Only use full blocks when generating fake chunks (ignores slabs, lanterns, torches, grass, etc.) \n\n"
|
||||
+ ""
|
||||
+ " " + BlocksToAvoid.NO_COLLISION + ": Only use solid blocks when generating fake chunks (ignores grass, torches, etc.) \n"
|
||||
+ ""
|
||||
+ " " + BlocksToAvoid.BOTH + ": Only use full solid blocks when generating fake chunks \n";
|
||||
public BlocksToAvoid getBlocksToAvoid();
|
||||
public void setBlockToAvoid(BlocksToAvoid newBlockToAvoid);
|
||||
+ " When generating fake chunks, what blocks should be ignored? \n"
|
||||
+ " Ignored blocks don't affect the height of the fake chunk, but might affect the color. \n"
|
||||
+ " So using " + BlocksToAvoid.BOTH + " will prevent snow covered blocks from appearing one block too tall, \n"
|
||||
+ " but will still show the snow's color.\n"
|
||||
+ "\n"
|
||||
+ " " + BlocksToAvoid.NONE + ": Use all blocks when generating fake chunks \n"
|
||||
+ " " + BlocksToAvoid.NON_FULL + ": Only use full blocks when generating fake chunks (ignores slabs, lanterns, torches, tall grass, etc.) \n"
|
||||
+ " " + BlocksToAvoid.NO_COLLISION + ": Only use solid blocks when generating fake chunks (ignores tall grass, torches, etc.) \n"
|
||||
+ " " + BlocksToAvoid.BOTH + ": Only use full solid blocks when generating fake chunks \n"
|
||||
+ "\n"
|
||||
+ " This wont't affect performance.";
|
||||
BlocksToAvoid getBlocksToAvoid();
|
||||
void setBlockToAvoid(BlocksToAvoid newBlockToAvoid);
|
||||
}
|
||||
|
||||
|
||||
@@ -336,16 +369,16 @@ public interface ILodConfigWrapperSingleton
|
||||
//============================//
|
||||
// AdvancedModOptions Configs //
|
||||
//============================//
|
||||
public interface IAdvanced
|
||||
interface IAdvanced
|
||||
{
|
||||
public static final String DESC = "Advanced mod settings";
|
||||
String DESC = "Advanced mod settings";
|
||||
|
||||
public IThreading threading();
|
||||
public IDebugging debugging();
|
||||
public IBuffers buffers();
|
||||
IThreading threading();
|
||||
IDebugging debugging();
|
||||
IBuffers buffers();
|
||||
|
||||
|
||||
public interface IThreading
|
||||
interface IThreading
|
||||
{
|
||||
String DESC = "These settings control how many CPU threads the mod uses for different tasks.";
|
||||
|
||||
@@ -354,34 +387,45 @@ public interface ILodConfigWrapperSingleton
|
||||
Runtime.getRuntime().availableProcessors() / 2,
|
||||
Runtime.getRuntime().availableProcessors());
|
||||
String NUMBER_OF_WORLD_GENERATION_THREADS_DESC = ""
|
||||
+ " This is how many threads are used when generating LODs outside \n"
|
||||
+ " the normal render distance. \n"
|
||||
+ " How many threads should be used when generating fake chunks outside \n"
|
||||
+ " the normal render distance? \n"
|
||||
+ "\n"
|
||||
+ " If you experience stuttering when generating distant LODs, decrease \n"
|
||||
+ " this number. If you want to increase LOD generation speed, \n"
|
||||
+ " increase this number. \n\n"
|
||||
+ ""
|
||||
+ " increase this number. \n"
|
||||
+ "\n"
|
||||
+ " This and the number of buffer builder threads are independent, \n"
|
||||
+ " so if they add up to more threads than your CPU has cores, \n"
|
||||
+ " that shouldn't cause an issue. \n"
|
||||
+ "\n"
|
||||
+ " The maximum value is the number of logical processors on your CPU. \n"
|
||||
+ " Requires a restart to take effect. \n";
|
||||
public int getNumberOfWorldGenerationThreads();
|
||||
public void setNumberOfWorldGenerationThreads(int newNumberOfWorldGenerationThreads);
|
||||
int getNumberOfWorldGenerationThreads();
|
||||
void setNumberOfWorldGenerationThreads(int newNumberOfWorldGenerationThreads);
|
||||
|
||||
MinDefaultMax<Integer> NUMBER_OF_BUFFER_BUILDER_THREADS_MIN_DEFAULT_MAX
|
||||
= new MinDefaultMax<Integer>(1,
|
||||
Runtime.getRuntime().availableProcessors() / 2,
|
||||
Runtime.getRuntime().availableProcessors());
|
||||
String NUMBER_OF_BUFFER_BUILDER_THREADS_DESC = ""
|
||||
+ " This is how many threads are used when building vertex buffers \n"
|
||||
+ " How many threads are used when building vertex buffers? \n"
|
||||
+ " (The things sent to your GPU to draw the fake chunks). \n"
|
||||
+ "\n"
|
||||
+ " If you experience high CPU usage when NOT generating distant \n"
|
||||
+ " fake chunks, lower this number. \n"
|
||||
+ " \n"
|
||||
+ " fake chunks, lower this number. A higher number will make fake\n"
|
||||
+ " fake chunks' transition faster when moving around the world. \n"
|
||||
+ "\n"
|
||||
+ " This and the number of world generator threads are independent, \n"
|
||||
+ " so if they add up to more threads than your CPU has cores, \n"
|
||||
+ " that shouldn't cause an issue. \n"
|
||||
+ "\n"
|
||||
+ " The maximum value is the number of logical processors on your CPU. \n"
|
||||
+ " Requires a restart to take effect. \n";
|
||||
public int getNumberOfBufferBuilderThreads();
|
||||
public void setNumberOfBufferBuilderThreads(int newNumberOfWorldBuilderThreads);
|
||||
int getNumberOfBufferBuilderThreads();
|
||||
void setNumberOfBufferBuilderThreads(int newNumberOfWorldBuilderThreads);
|
||||
}
|
||||
|
||||
public interface IDebugging
|
||||
interface IDebugging
|
||||
{
|
||||
String DESC = "These settings can be used to look for bugs, or see how certain aspects of the mod work.";
|
||||
|
||||
@@ -389,36 +433,78 @@ public interface ILodConfigWrapperSingleton
|
||||
String DRAW_LODS_DESC = ""
|
||||
+ " If true, the mod is enabled and fake chunks will be drawn. \n"
|
||||
+ " If false, the mod will still generate fake chunks, \n"
|
||||
+ " but they won't be rendered. \n";
|
||||
public boolean getDrawLods();
|
||||
public void setDrawLods(boolean newDrawLods);
|
||||
+ " but they won't be rendered. \n"
|
||||
+ "\n"
|
||||
+ " Disabling rendering will reduce GPU usage \n";
|
||||
boolean getDrawLods();
|
||||
void setDrawLods(boolean newDrawLods);
|
||||
|
||||
DebugMode DEBUG_MODE_DEFAULT = DebugMode.OFF;
|
||||
String DEBUG_MODE_DESC = ""
|
||||
+ " Should specialized colors/rendering modes be used? \n"
|
||||
+ "\n"
|
||||
+ " " + DebugMode.OFF + ": Fake chunks will be drawn with their normal colors. \n"
|
||||
+ " " + DebugMode.SHOW_DETAIL + ": Fake chunks color will be based on their detail level. \n"
|
||||
+ " " + DebugMode.SHOW_DETAIL_WIREFRAME + ": Fake chunks color will be based on their detail level, drawn as a wireframe. \n";
|
||||
public DebugMode getDebugMode();
|
||||
public void setDebugMode(DebugMode newDebugMode);
|
||||
DebugMode getDebugMode();
|
||||
void setDebugMode(DebugMode newDebugMode);
|
||||
|
||||
boolean DEBUG_KEYBINDINGS_ENABLED_DEFAULT = true;
|
||||
String DEBUG_KEYBINDINGS_ENABLED_DESC = ""
|
||||
+ " If true the F4 key can be used to cycle through the different debug modes. \n"
|
||||
+ " and the F6 key can be used to enable and disable LOD rendering.";
|
||||
public boolean getDebugKeybindingsEnabled();
|
||||
public void setDebugKeybindingsEnabled(boolean newEnableDebugKeybindings);
|
||||
boolean getDebugKeybindingsEnabled();
|
||||
void setDebugKeybindingsEnabled(boolean newEnableDebugKeybindings);
|
||||
}
|
||||
|
||||
public interface IBuffers
|
||||
interface IBuffers
|
||||
{
|
||||
String DESC = "These settings affect how often geometry is rebuilt.";
|
||||
|
||||
GpuUploadMethod GPU_UPLOAD_METHOD_DEFAULT = GpuUploadMethod.AUTO;
|
||||
String GPU_UPLOAD_METHOD_DESC = ""
|
||||
+ " What method should be used to upload geometry to the GPU? \n"
|
||||
+ "\n"
|
||||
+ " " + GpuUploadMethod.AUTO + ": Picks the best option based on the GPU you have. \n"
|
||||
+ " " + GpuUploadMethod.BUFFER_STORAGE + ": Default for NVIDIA if OpenGL 4.5 is supported. \n"
|
||||
+ " Fast rendering, no stuttering. \n"
|
||||
+ " " + GpuUploadMethod.SUB_DATA + ": Backup option for NVIDIA. \n"
|
||||
+ " Fast rendering but may stutter when uploading. \n"
|
||||
+ " " + GpuUploadMethod.BUFFER_MAPPING + ": Slow rendering but won't stutter when uploading. Possibly the best option for integrated GPUs. \n"
|
||||
+ " Default option for AMD/Intel. \n"
|
||||
+ " May end up storing buffers in System memory. \n"
|
||||
+ " Fast rending if in GPU memory, slow if in system memory, \n"
|
||||
+ " but won't stutter when uploading. \n"
|
||||
+ " " + GpuUploadMethod.DATA + ": Fast rendering but will stutter when uploading. \n"
|
||||
+ " Backup option for AMD/Intel. \n"
|
||||
+ " Fast rendering but may stutter when uploading. \n"
|
||||
+ "\n"
|
||||
+ " If you don't see any difference when changing these settings, or the world looks corrupted: \n"
|
||||
+ " Restart the game to clear the old buffers. \n";
|
||||
GpuUploadMethod getGpuUploadMethod();
|
||||
void setGpuUploadMethod(GpuUploadMethod newGpuUploadMethod);
|
||||
|
||||
MinDefaultMax<Integer> GPU_UPLOAD_TIMEOUT_IN_MILLISECONDS_DEFAULT = new MinDefaultMax<Integer>(0, 0, 5000);
|
||||
String GPU_UPLOAD_TIMEOUT_IN_MILLISECONDS_DESC = ""
|
||||
+ " How long should we wait before uploading a buffer to the GPU? \n"
|
||||
+ " Helpful resource for frame times: https://fpstoms.com \n"
|
||||
+ "\n"
|
||||
+ " Longer times may reduce stuttering but will make fake chunks \n"
|
||||
+ " transition and load slower. \n"
|
||||
+ "\n"
|
||||
+ " NOTE:\n"
|
||||
+ " This should be a last resort option."
|
||||
+ " Only change this from [0], after you have tried all of the \n"
|
||||
+ " \"GPU Upload methods\" and determined even the best stutters with yoru hardware.";
|
||||
int getGpuUploadTimeoutInMilliseconds();
|
||||
void setGpuUploadTimeoutInMilliseconds(int newTimeoutInMilliseconds);
|
||||
|
||||
String REBUILD_TIMES_DESC = ""
|
||||
+ " How frequently should geometry be rebuilt and sent to the GPU? \n"
|
||||
+ " How frequently should vertex buffers (geometry) be rebuilt and sent to the GPU? \n"
|
||||
+ " Higher settings may cause stuttering, but will prevent holes in the world \n";
|
||||
BufferRebuildTimes REBUILD_TIMES_DEFAULT = BufferRebuildTimes.NORMAL;
|
||||
public BufferRebuildTimes getRebuildTimes();
|
||||
public void setRebuildTimes(BufferRebuildTimes newBufferRebuildTimes);
|
||||
BufferRebuildTimes getRebuildTimes();
|
||||
void setRebuildTimes(BufferRebuildTimes newBufferRebuildTimes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+17
-12
@@ -19,6 +19,7 @@
|
||||
|
||||
package com.seibel.lod.core.wrapperInterfaces.minecraft;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.util.HashSet;
|
||||
|
||||
import com.seibel.lod.core.objects.math.Mat4f;
|
||||
@@ -32,33 +33,37 @@ import com.seibel.lod.core.wrapperInterfaces.chunk.AbstractChunkPosWrapper;
|
||||
* rendering in Minecraft.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 11-18-2021
|
||||
* @version 11-26-2021
|
||||
*/
|
||||
public interface IMinecraftRenderWrapper
|
||||
{
|
||||
public Vec3f getLookAtVector();
|
||||
Vec3f getLookAtVector();
|
||||
|
||||
public AbstractBlockPosWrapper getCameraBlockPosition();
|
||||
AbstractBlockPosWrapper getCameraBlockPosition();
|
||||
|
||||
public boolean playerHasBlindnessEffect();
|
||||
boolean playerHasBlindnessEffect();
|
||||
|
||||
public Vec3d getCameraExactPosition();
|
||||
Vec3d getCameraExactPosition();
|
||||
|
||||
public Mat4f getDefaultProjectionMatrix(float partialTicks);
|
||||
Mat4f getDefaultProjectionMatrix(float partialTicks);
|
||||
|
||||
public double getGamma();
|
||||
double getGamma();
|
||||
|
||||
public double getFov(float partialTicks);
|
||||
Color getFogColor();
|
||||
|
||||
Color getSkyColor();
|
||||
|
||||
double getFov(float partialTicks);
|
||||
|
||||
/** Measured in chunks */
|
||||
public int getRenderDistance();
|
||||
int getRenderDistance();
|
||||
|
||||
public int getScreenWidth();
|
||||
public int getScreenHeight();
|
||||
int getScreenWidth();
|
||||
int getScreenHeight();
|
||||
|
||||
/**
|
||||
* This method returns the ChunkPos of all chunks that Minecraft
|
||||
* is going to render this frame.
|
||||
*/
|
||||
public HashSet<AbstractChunkPosWrapper> getRenderedChunks();
|
||||
HashSet<AbstractChunkPosWrapper> getRenderedChunks();
|
||||
}
|
||||
|
||||
+21
-21
@@ -50,7 +50,7 @@ public interface IMinecraftWrapper
|
||||
* <p>
|
||||
* This doesn't affect OpenGL objects in any way.
|
||||
*/
|
||||
public void clearFrameObjectCache();
|
||||
void clearFrameObjectCache();
|
||||
|
||||
|
||||
|
||||
@@ -58,18 +58,18 @@ public interface IMinecraftWrapper
|
||||
// method wrappers //
|
||||
//=================//
|
||||
|
||||
public float getShade(LodDirection lodDirection);
|
||||
float getShade(LodDirection lodDirection);
|
||||
|
||||
public boolean hasSinglePlayerServer();
|
||||
boolean hasSinglePlayerServer();
|
||||
|
||||
public String getCurrentServerName();
|
||||
public String getCurrentServerIp();
|
||||
public String getCurrentServerVersion();
|
||||
String getCurrentServerName();
|
||||
String getCurrentServerIp();
|
||||
String getCurrentServerVersion();
|
||||
|
||||
/** Returns the dimension the player is currently in */
|
||||
public IDimensionTypeWrapper getCurrentDimension();
|
||||
IDimensionTypeWrapper getCurrentDimension();
|
||||
|
||||
public String getCurrentDimensionId();
|
||||
String getCurrentDimensionId();
|
||||
|
||||
/** This texture changes every frame */
|
||||
ILightMapWrapper getCurrentLightMap();
|
||||
@@ -80,7 +80,7 @@ public interface IMinecraftWrapper
|
||||
* @param u x location in texture space
|
||||
* @param v z location in texture space
|
||||
*/
|
||||
public int getColorIntFromLightMap(int u, int v);
|
||||
int getColorIntFromLightMap(int u, int v);
|
||||
|
||||
/**
|
||||
* Returns the Color at the given pixel coordinates
|
||||
@@ -88,7 +88,7 @@ public interface IMinecraftWrapper
|
||||
* @param u x location in texture space
|
||||
* @param v z location in texture space
|
||||
*/
|
||||
public Color getColorFromLightMap(int u, int v);
|
||||
Color getColorFromLightMap(int u, int v);
|
||||
|
||||
|
||||
|
||||
@@ -97,35 +97,35 @@ public interface IMinecraftWrapper
|
||||
// Simple gets //
|
||||
//=============//
|
||||
|
||||
public boolean playerExists();
|
||||
boolean playerExists();
|
||||
|
||||
public AbstractBlockPosWrapper getPlayerBlockPos();
|
||||
AbstractBlockPosWrapper getPlayerBlockPos();
|
||||
|
||||
public AbstractChunkPosWrapper getPlayerChunkPos();
|
||||
AbstractChunkPosWrapper getPlayerChunkPos();
|
||||
|
||||
/**
|
||||
* Attempts to get the ServerWorld for the dimension
|
||||
* the user is currently in.
|
||||
* @returns null if no ServerWorld is available
|
||||
*/
|
||||
public IWorldWrapper getWrappedServerWorld();
|
||||
IWorldWrapper getWrappedServerWorld();
|
||||
|
||||
public IWorldWrapper getWrappedClientWorld();
|
||||
IWorldWrapper getWrappedClientWorld();
|
||||
|
||||
public File getGameDirectory();
|
||||
File getGameDirectory();
|
||||
|
||||
public IProfilerWrapper getProfiler();
|
||||
IProfilerWrapper getProfiler();
|
||||
|
||||
public float getSkyDarken(float partialTicks);
|
||||
float getSkyDarken(float partialTicks);
|
||||
|
||||
boolean connectedToServer();
|
||||
|
||||
/** Returns all worlds available to the server */
|
||||
public ArrayList<IWorldWrapper> getAllServerWorlds();
|
||||
ArrayList<IWorldWrapper> getAllServerWorlds();
|
||||
|
||||
|
||||
|
||||
public void sendChatMessage(String string);
|
||||
void sendChatMessage(String string);
|
||||
|
||||
/**
|
||||
* Crashes Minecraft, displaying the given errorMessage <br> <br>
|
||||
@@ -135,7 +135,7 @@ public interface IMinecraftWrapper
|
||||
* Error: <strong>ExceptionClass: exceptionErrorMessage</strong> <br>
|
||||
* Exit Code: -1 <br>
|
||||
*/
|
||||
public void crashMinecraft(String errorMessage, Throwable exception);
|
||||
void crashMinecraft(String errorMessage, Throwable exception);
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -25,9 +25,9 @@ package com.seibel.lod.core.wrapperInterfaces.minecraft;
|
||||
*/
|
||||
public interface IProfilerWrapper
|
||||
{
|
||||
public void push(String newSection);
|
||||
void push(String newSection);
|
||||
|
||||
public void popPush(String newSection);
|
||||
void popPush(String newSection);
|
||||
|
||||
public void pop();
|
||||
void pop();
|
||||
}
|
||||
|
||||
@@ -25,5 +25,5 @@ package com.seibel.lod.core.wrapperInterfaces.misc;
|
||||
*/
|
||||
public interface ILightMapWrapper
|
||||
{
|
||||
public int getLightValue(int skyLight, int blockLight);
|
||||
int getLightValue(int skyLight, int blockLight);
|
||||
}
|
||||
|
||||
+4
-4
@@ -30,9 +30,9 @@ import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
|
||||
*/
|
||||
public interface IBiomeColorWrapperSingleton
|
||||
{
|
||||
public IBiomeColorWrapperSingleton getInstance();
|
||||
IBiomeColorWrapperSingleton getInstance();
|
||||
|
||||
public int getGrassColor(IWorldWrapper world, AbstractBlockPosWrapper blockPos);
|
||||
public int getWaterColor(IWorldWrapper world, AbstractBlockPosWrapper blockPos);
|
||||
public int getFoliageColor(IWorldWrapper world, AbstractBlockPosWrapper blockPos);
|
||||
int getGrassColor(IWorldWrapper world, AbstractBlockPosWrapper blockPos);
|
||||
int getWaterColor(IWorldWrapper world, AbstractBlockPosWrapper blockPos);
|
||||
int getFoliageColor(IWorldWrapper world, AbstractBlockPosWrapper blockPos);
|
||||
}
|
||||
|
||||
@@ -26,12 +26,12 @@ package com.seibel.lod.core.wrapperInterfaces.world;
|
||||
public interface IBiomeWrapper
|
||||
{
|
||||
/** Returns a color int for the given biome. */
|
||||
public int getColorForBiome(int x, int z);
|
||||
int getColorForBiome(int x, int z);
|
||||
|
||||
public int getGrassTint(int x, int z);
|
||||
int getGrassTint(int x, int z);
|
||||
|
||||
public int getFolliageTint();
|
||||
int getFolliageTint();
|
||||
|
||||
public int getWaterTint();
|
||||
int getWaterTint();
|
||||
|
||||
}
|
||||
|
||||
+3
-3
@@ -25,9 +25,9 @@ package com.seibel.lod.core.wrapperInterfaces.world;
|
||||
*/
|
||||
public interface IDimensionTypeWrapper
|
||||
{
|
||||
public String getDimensionName();
|
||||
String getDimensionName();
|
||||
|
||||
public boolean hasCeiling();
|
||||
boolean hasCeiling();
|
||||
|
||||
public boolean hasSkyLight();
|
||||
boolean hasSkyLight();
|
||||
}
|
||||
|
||||
@@ -32,28 +32,30 @@ import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
|
||||
*/
|
||||
public interface IWorldWrapper
|
||||
{
|
||||
public IDimensionTypeWrapper getDimensionType();
|
||||
IDimensionTypeWrapper getDimensionType();
|
||||
|
||||
public WorldType getWorldType();
|
||||
WorldType getWorldType();
|
||||
|
||||
public int getBlockLight(AbstractBlockPosWrapper blockPos);
|
||||
int getBlockLight(AbstractBlockPosWrapper blockPos);
|
||||
|
||||
public int getSkyLight(AbstractBlockPosWrapper blockPos);
|
||||
int getSkyLight(AbstractBlockPosWrapper blockPos);
|
||||
|
||||
public IBiomeWrapper getBiome(AbstractBlockPosWrapper blockPos);
|
||||
IBiomeWrapper getBiome(AbstractBlockPosWrapper blockPos);
|
||||
|
||||
public boolean hasCeiling();
|
||||
boolean hasCeiling();
|
||||
|
||||
public boolean hasSkyLight();
|
||||
boolean hasSkyLight();
|
||||
|
||||
public boolean isEmpty();
|
||||
// Pls don't use this
|
||||
// If the world is null then this can't be called and gives an error
|
||||
boolean isEmpty();
|
||||
|
||||
public int getHeight();
|
||||
int getHeight();
|
||||
|
||||
public int getSeaLevel();
|
||||
int getSeaLevel();
|
||||
|
||||
/** @throws UnsupportedOperationException if the WorldWrapper isn't for a ServerWorld */
|
||||
public File getSaveFolder() throws UnsupportedOperationException;
|
||||
File getSaveFolder() throws UnsupportedOperationException;
|
||||
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@ import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
|
||||
* This is used for generating chunks
|
||||
* in a variety of detail and threading levels.
|
||||
* <p>
|
||||
* Abstract instead of a interface so
|
||||
* Abstract instead of an interface, so
|
||||
* we can define its constructors.
|
||||
*
|
||||
* @author James Seibel
|
||||
|
||||
@@ -1,105 +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.forge;
|
||||
|
||||
import com.seibel.lod.core.api.EventApi;
|
||||
import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||
import com.seibel.lod.forge.wrappers.chunk.ChunkWrapper;
|
||||
import com.seibel.lod.forge.wrappers.world.DimensionTypeWrapper;
|
||||
import com.seibel.lod.forge.wrappers.world.WorldWrapper;
|
||||
|
||||
import net.minecraftforge.client.event.InputEvent;
|
||||
import net.minecraftforge.event.TickEvent;
|
||||
import net.minecraftforge.event.world.BlockEvent;
|
||||
import net.minecraftforge.event.world.ChunkEvent;
|
||||
import net.minecraftforge.event.world.WorldEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
|
||||
/**
|
||||
* This handles all events sent to the client,
|
||||
* and is the starting point for most of the mod.
|
||||
*
|
||||
* @author James_Seibel
|
||||
* @version 11-12-2021
|
||||
*/
|
||||
public class ForgeClientProxy
|
||||
{
|
||||
private final EventApi eventApi = EventApi.INSTANCE;
|
||||
|
||||
|
||||
|
||||
@SubscribeEvent
|
||||
public void serverTickEvent(TickEvent.ServerTickEvent event)
|
||||
{
|
||||
eventApi.serverTickEvent();
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void chunkLoadEvent(ChunkEvent.Load event)
|
||||
{
|
||||
eventApi.chunkLoadEvent(new ChunkWrapper(event.getChunk()), DimensionTypeWrapper.getDimensionTypeWrapper(event.getWorld().dimensionType()));
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void worldSaveEvent(WorldEvent.Save event)
|
||||
{
|
||||
eventApi.worldSaveEvent();
|
||||
}
|
||||
|
||||
/** This is also called when a new dimension loads */
|
||||
@SubscribeEvent
|
||||
public void worldLoadEvent(WorldEvent.Load event)
|
||||
{
|
||||
eventApi.worldLoadEvent(WorldWrapper.getWorldWrapper(event.getWorld()));
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void worldUnloadEvent(WorldEvent.Unload event)
|
||||
{
|
||||
eventApi.worldUnloadEvent();
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void blockChangeEvent(BlockEvent event)
|
||||
{
|
||||
// we only care about certain block events
|
||||
if (event.getClass() == BlockEvent.BreakEvent.class ||
|
||||
event.getClass() == BlockEvent.EntityPlaceEvent.class ||
|
||||
event.getClass() == BlockEvent.EntityMultiPlaceEvent.class ||
|
||||
event.getClass() == BlockEvent.FluidPlaceBlockEvent.class ||
|
||||
event.getClass() == BlockEvent.PortalSpawnEvent.class)
|
||||
{
|
||||
IChunkWrapper chunk = new ChunkWrapper(event.getWorld().getChunk(event.getPos()));
|
||||
DimensionTypeWrapper dimType = DimensionTypeWrapper.getDimensionTypeWrapper(event.getWorld().dimensionType());
|
||||
|
||||
// recreate the LOD where the blocks were changed
|
||||
eventApi.blockChangeEvent(chunk, dimType);
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void onKeyInput(InputEvent.KeyInputEvent event)
|
||||
{
|
||||
eventApi.onKeyInput(event.getKey(), event.getAction());
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -1,437 +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.forge;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
|
||||
import com.electronwill.nightconfig.core.file.CommentedFileConfig;
|
||||
import com.electronwill.nightconfig.core.io.WritingMode;
|
||||
import com.seibel.lod.core.ModInfo;
|
||||
import com.seibel.lod.core.enums.config.BlocksToAvoid;
|
||||
import com.seibel.lod.core.enums.config.BufferRebuildTimes;
|
||||
import com.seibel.lod.core.enums.config.DistanceGenerationMode;
|
||||
import com.seibel.lod.core.enums.config.GenerationPriority;
|
||||
import com.seibel.lod.core.enums.config.GpuUploadMethod;
|
||||
import com.seibel.lod.core.enums.config.HorizontalQuality;
|
||||
import com.seibel.lod.core.enums.config.HorizontalResolution;
|
||||
import com.seibel.lod.core.enums.config.HorizontalScale;
|
||||
import com.seibel.lod.core.enums.config.LodTemplate;
|
||||
import com.seibel.lod.core.enums.config.VanillaOverdraw;
|
||||
import com.seibel.lod.core.enums.config.VerticalQuality;
|
||||
import com.seibel.lod.core.enums.rendering.DebugMode;
|
||||
import com.seibel.lod.core.enums.rendering.FogDistance;
|
||||
import com.seibel.lod.core.enums.rendering.FogDrawOverride;
|
||||
import com.seibel.lod.core.objects.MinDefaultMax;
|
||||
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.IWorldGenerator;
|
||||
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton.IClient.IAdvanced.IBuffers;
|
||||
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton.IClient.IAdvanced.IDebugging;
|
||||
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton.IClient.IAdvanced.IThreading;
|
||||
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton.IClient.IGraphics.IAdvancedGraphics;
|
||||
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton.IClient.IGraphics.IFogQuality;
|
||||
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton.IClient.IGraphics.IQuality;
|
||||
|
||||
import net.minecraftforge.common.ForgeConfigSpec;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.config.ModConfig;
|
||||
|
||||
/**
|
||||
* This handles any configuration the user has access to.
|
||||
* @author Leonardo Amato
|
||||
* @author James Seibel
|
||||
* @version 11-16-2021
|
||||
*/
|
||||
@Mod.EventBusSubscriber
|
||||
public class ForgeConfig
|
||||
{
|
||||
// CONFIG STRUCTURE
|
||||
// -> Client
|
||||
// |
|
||||
// |-> Graphics
|
||||
// | |-> QualityOption
|
||||
// | |-> FogQualityOption
|
||||
// | |-> AdvancedGraphicsOption
|
||||
// |
|
||||
// |-> World Generation
|
||||
// |
|
||||
// |-> Advanced Mod Option
|
||||
// |-> Threads
|
||||
// |-> Buffers
|
||||
// |-> Debugging
|
||||
|
||||
|
||||
|
||||
public static class Client
|
||||
{
|
||||
public final Graphics graphics;
|
||||
public final WorldGenerator worldGenerator;
|
||||
public final AdvancedModOptions advancedModOptions;
|
||||
|
||||
|
||||
//================//
|
||||
// Client Configs //
|
||||
//================//
|
||||
public Client(ForgeConfigSpec.Builder builder)
|
||||
{
|
||||
builder.push(this.getClass().getSimpleName());
|
||||
{
|
||||
graphics = new Graphics(builder);
|
||||
worldGenerator = new WorldGenerator(builder);
|
||||
advancedModOptions = new AdvancedModOptions(builder);
|
||||
}
|
||||
builder.pop();
|
||||
}
|
||||
|
||||
|
||||
//==================//
|
||||
// Graphics Configs //
|
||||
//==================//
|
||||
public static class Graphics
|
||||
{
|
||||
public final QualityOption qualityOption;
|
||||
public final FogQualityOption fogQuality;
|
||||
public final AdvancedGraphicsOption advancedGraphicsOption;
|
||||
|
||||
Graphics(ForgeConfigSpec.Builder builder)
|
||||
{
|
||||
builder.comment(IGraphics.DESC).push("Graphics");
|
||||
{
|
||||
qualityOption = new QualityOption(builder);
|
||||
advancedGraphicsOption = new AdvancedGraphicsOption(builder);
|
||||
fogQuality = new FogQualityOption(builder);
|
||||
}
|
||||
builder.pop();
|
||||
}
|
||||
|
||||
|
||||
public static class QualityOption
|
||||
{
|
||||
public final ForgeConfigSpec.EnumValue<HorizontalResolution> drawResolution;
|
||||
public final ForgeConfigSpec.IntValue lodChunkRenderDistance;
|
||||
public final ForgeConfigSpec.EnumValue<VerticalQuality> verticalQuality;
|
||||
public final ForgeConfigSpec.EnumValue<HorizontalScale> horizontalScale;
|
||||
public final ForgeConfigSpec.EnumValue<HorizontalQuality> horizontalQuality;
|
||||
|
||||
QualityOption(ForgeConfigSpec.Builder builder)
|
||||
{
|
||||
builder.comment(IQuality.DESC).push(this.getClass().getSimpleName());
|
||||
|
||||
verticalQuality = builder
|
||||
.comment("\n\n"
|
||||
+ IQuality.VERTICAL_QUALITY_DESC)
|
||||
.defineEnum("Vertical Quality", IQuality.VERTICAL_QUALITY_DEFAULT);
|
||||
|
||||
horizontalScale = builder
|
||||
.comment("\n\n"
|
||||
+ IQuality.HORIZONTAL_SCALE_DESC)
|
||||
.defineEnum("Horizontal Scale", IQuality.HORIZONTAL_SCALE_DEFAULT);
|
||||
|
||||
horizontalQuality = builder
|
||||
.comment("\n\n"
|
||||
+ IQuality.HORIZONTAL_QUALITY_DESC)
|
||||
.defineEnum("Horizontal Quality", IQuality.HORIZONTAL_QUALITY_DEFAULT);
|
||||
|
||||
drawResolution = builder
|
||||
.comment("\n\n"
|
||||
+ IQuality.DRAW_RESOLUTION_DESC)
|
||||
.defineEnum("Block size", IQuality.DRAW_RESOLUTION_DEFAULT);
|
||||
|
||||
MinDefaultMax<Integer> minDefaultMax = IQuality.LOD_CHUNK_RENDER_DISTANCE_MIN_DEFAULT_MAX;
|
||||
lodChunkRenderDistance = builder
|
||||
.comment("\n\n"
|
||||
+ IQuality.LOD_CHUNK_RENDER_DISTANCE_DESC)
|
||||
.defineInRange("Lod Render Distance", minDefaultMax.defaultValue, minDefaultMax.minValue, minDefaultMax.maxValue);
|
||||
|
||||
builder.pop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class FogQualityOption
|
||||
{
|
||||
public final ForgeConfigSpec.EnumValue<FogDistance> fogDistance;
|
||||
public final ForgeConfigSpec.EnumValue<FogDrawOverride> fogDrawOverride;
|
||||
public final ForgeConfigSpec.BooleanValue disableVanillaFog;
|
||||
|
||||
FogQualityOption(ForgeConfigSpec.Builder builder)
|
||||
{
|
||||
builder.comment(IFogQuality.DESC).push(this.getClass().getSimpleName());
|
||||
|
||||
fogDistance = builder
|
||||
.comment("\n\n"
|
||||
+ IFogQuality.FOG_DISTANCE_DESC)
|
||||
.defineEnum("Fog Distance", IFogQuality.FOG_DISTANCE_DEFAULT);
|
||||
|
||||
fogDrawOverride = builder
|
||||
.comment("\n\n"
|
||||
+ IFogQuality.FOG_DRAW_OVERRIDE_DESC)
|
||||
.defineEnum("Fog Draw Override", IFogQuality.FOG_DRAW_OVERRIDE_DEFAULT);
|
||||
|
||||
disableVanillaFog = builder
|
||||
.comment("\n\n"
|
||||
+ IFogQuality.DISABLE_VANILLA_FOG_DESC)
|
||||
.define("Experimental Disable Vanilla Fog", IFogQuality.DISABLE_VANILLA_FOG_DEFAULT);
|
||||
|
||||
builder.pop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class AdvancedGraphicsOption
|
||||
{
|
||||
public final ForgeConfigSpec.EnumValue<LodTemplate> lodTemplate;
|
||||
public final ForgeConfigSpec.BooleanValue disableDirectionalCulling;
|
||||
public final ForgeConfigSpec.BooleanValue alwaysDrawAtMaxQuality;
|
||||
public final ForgeConfigSpec.EnumValue<VanillaOverdraw> vanillaOverdraw;
|
||||
public final ForgeConfigSpec.EnumValue<GpuUploadMethod> gpuUploadMethod;
|
||||
public final ForgeConfigSpec.BooleanValue useExtendedNearClipPlane;
|
||||
|
||||
AdvancedGraphicsOption(ForgeConfigSpec.Builder builder)
|
||||
{
|
||||
builder.comment(IAdvancedGraphics.DESC).push(this.getClass().getSimpleName());
|
||||
|
||||
lodTemplate = builder
|
||||
.comment("\n\n"
|
||||
+ IAdvancedGraphics.LOD_TEMPLATE_DESC)
|
||||
.defineEnum("LOD Template", IAdvancedGraphics.LOD_TEMPLATE_DEFAULT);
|
||||
|
||||
disableDirectionalCulling = builder
|
||||
.comment("\n\n"
|
||||
+ IAdvancedGraphics.DISABLE_DIRECTIONAL_CULLING_DESC)
|
||||
.define("Disable Directional Culling", IAdvancedGraphics.DISABLE_DIRECTIONAL_CULLING_DEFAULT);
|
||||
|
||||
alwaysDrawAtMaxQuality = builder
|
||||
.comment("\n\n"
|
||||
+ IAdvancedGraphics.ALWAYS_DRAW_AT_MAD_QUALITY_DESC)
|
||||
.define("Always Use Max Quality", IAdvancedGraphics.ALWAYS_DRAW_AT_MAD_QUALITY_DEFAULT);
|
||||
|
||||
vanillaOverdraw = builder
|
||||
.comment("\n\n"
|
||||
+ IAdvancedGraphics.VANILLA_OVERDRAW_DESC)
|
||||
.defineEnum("Vanilla Overdraw", IAdvancedGraphics.VANILLA_OVERDRAW_DEFAULT);
|
||||
|
||||
gpuUploadMethod = builder
|
||||
.comment("\n\n"
|
||||
+ IAdvancedGraphics.GPU_UPLOAD_METHOD_DESC)
|
||||
.defineEnum("GPU Upload Method", IAdvancedGraphics.GPU_UPLOAD_METHOD_DEFAULT);
|
||||
|
||||
// This is a temporary fix (like vanilla overdraw)
|
||||
// hopefully we can remove both once we get individual chunk rendering figured out
|
||||
useExtendedNearClipPlane = builder
|
||||
.comment("\n\n"
|
||||
+ IAdvancedGraphics.USE_EXTENDED_NEAR_CLIP_PLANE_DESC)
|
||||
.define("Use Extended Near Clip Plane", IAdvancedGraphics.USE_EXTENDED_NEAR_CLIP_PLANE_DEFAULT);
|
||||
|
||||
|
||||
builder.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//========================//
|
||||
// WorldGenerator Configs //
|
||||
//========================//
|
||||
public static class WorldGenerator
|
||||
{
|
||||
public final ForgeConfigSpec.EnumValue<GenerationPriority> generationPriority;
|
||||
public final ForgeConfigSpec.EnumValue<DistanceGenerationMode> distanceGenerationMode;
|
||||
public final ForgeConfigSpec.BooleanValue allowUnstableFeatureGeneration;
|
||||
public final ForgeConfigSpec.EnumValue<BlocksToAvoid> blocksToAvoid;
|
||||
//public final ForgeConfigSpec.BooleanValue useExperimentalPreGenLoading;
|
||||
|
||||
WorldGenerator(ForgeConfigSpec.Builder builder)
|
||||
{
|
||||
builder.comment(IWorldGenerator.DESC).push("Generation");
|
||||
|
||||
generationPriority = builder
|
||||
.comment("\n\n"
|
||||
+ IWorldGenerator.GENERATION_PRIORITY_DESC)
|
||||
.defineEnum("Generation Priority", IWorldGenerator.GENERATION_PRIORITY_DEFAULT);
|
||||
|
||||
distanceGenerationMode = builder
|
||||
.comment("\n\n"
|
||||
+ IWorldGenerator.DISTANCE_GENERATION_MODE_DESC)
|
||||
.defineEnum("Distance Generation Mode", IWorldGenerator.DISTANCE_GENERATION_MODE_DEFAULT);
|
||||
|
||||
allowUnstableFeatureGeneration = builder
|
||||
.comment("\n\n"
|
||||
+ IWorldGenerator.ALLOW_UNSTABLE_FEATURE_GENERATION_DESC)
|
||||
.define("Allow Unstable Feature Generation", IWorldGenerator.ALLOW_UNSTABLE_FEATURE_GENERATION_DEFAULT);
|
||||
|
||||
blocksToAvoid = builder
|
||||
.comment("\n\n"
|
||||
+ IWorldGenerator.BLOCKS_TO_AVOID_DESC)
|
||||
.defineEnum("Blocks to avoid", IWorldGenerator.BLOCKS_TO_AVOID_DEFAULT);
|
||||
|
||||
/*useExperimentalPreGenLoading = builder
|
||||
.comment("\n\n"
|
||||
+ " if a chunk has been pre-generated, then the mod would use the real chunk for the \n"
|
||||
+ "fake chunk creation. May require a deletion of the lod file to see the result. \n")
|
||||
.define("Use pre-generated chunks", false);*/
|
||||
builder.pop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//============================//
|
||||
// AdvancedModOptions Configs //
|
||||
//============================//
|
||||
public static class AdvancedModOptions
|
||||
{
|
||||
public final Threading threading;
|
||||
public final Debugging debugging;
|
||||
public final Buffers buffers;
|
||||
|
||||
public AdvancedModOptions(ForgeConfigSpec.Builder builder)
|
||||
{
|
||||
builder.comment(IAdvanced.DESC).push(this.getClass().getSimpleName());
|
||||
{
|
||||
threading = new Threading(builder);
|
||||
debugging = new Debugging(builder);
|
||||
buffers = new Buffers(builder);
|
||||
}
|
||||
builder.pop();
|
||||
}
|
||||
|
||||
public static class Threading
|
||||
{
|
||||
public final ForgeConfigSpec.IntValue numberOfWorldGenerationThreads;
|
||||
public final ForgeConfigSpec.IntValue numberOfBufferBuilderThreads;
|
||||
|
||||
Threading(ForgeConfigSpec.Builder builder)
|
||||
{
|
||||
builder.comment(IThreading.DESC).push(this.getClass().getSimpleName());
|
||||
|
||||
MinDefaultMax<Integer> minDefaultMax = IThreading.NUMBER_OF_WORLD_GENERATION_THREADS_DEFAULT;
|
||||
numberOfWorldGenerationThreads = builder
|
||||
.comment("\n\n"
|
||||
+ IThreading.NUMBER_OF_WORLD_GENERATION_THREADS_DESC)
|
||||
.defineInRange("numberOfWorldGenerationThreads", minDefaultMax.defaultValue, minDefaultMax.minValue, minDefaultMax.maxValue);
|
||||
|
||||
|
||||
minDefaultMax = IThreading.NUMBER_OF_BUFFER_BUILDER_THREADS_MIN_DEFAULT_MAX;
|
||||
numberOfBufferBuilderThreads = builder
|
||||
.comment("\n\n"
|
||||
+ IThreading.NUMBER_OF_BUFFER_BUILDER_THREADS_MIN_DEFAULT_MAX)
|
||||
.defineInRange("numberOfBufferBuilderThreads", minDefaultMax.defaultValue, minDefaultMax.minValue, minDefaultMax.maxValue);
|
||||
|
||||
builder.pop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//===============//
|
||||
// Debug Options //
|
||||
//===============//
|
||||
public static class Debugging
|
||||
{
|
||||
public final ForgeConfigSpec.BooleanValue drawLods;
|
||||
public final ForgeConfigSpec.EnumValue<DebugMode> debugMode;
|
||||
public final ForgeConfigSpec.BooleanValue enableDebugKeybindings;
|
||||
|
||||
Debugging(ForgeConfigSpec.Builder builder)
|
||||
{
|
||||
builder.comment(IDebugging.DESC).push(this.getClass().getSimpleName());
|
||||
|
||||
drawLods = builder
|
||||
.comment("\n\n"
|
||||
+ IDebugging.DRAW_LODS_DESC)
|
||||
.define("Enable Rendering", IDebugging.DRAW_LODS_DEFAULT);
|
||||
|
||||
debugMode = builder
|
||||
.comment("\n\n"
|
||||
+ IDebugging.DEBUG_MODE_DESC)
|
||||
.defineEnum("Debug Mode", IDebugging.DEBUG_MODE_DEFAULT);
|
||||
|
||||
enableDebugKeybindings = builder
|
||||
.comment("\n\n"
|
||||
+ IDebugging.DEBUG_KEYBINDINGS_ENABLED_DESC)
|
||||
.define("Enable Debug Keybinding", IDebugging.DEBUG_KEYBINDINGS_ENABLED_DEFAULT);
|
||||
|
||||
builder.pop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class Buffers
|
||||
{
|
||||
public final ForgeConfigSpec.EnumValue<BufferRebuildTimes> rebuildTimes;
|
||||
|
||||
Buffers(ForgeConfigSpec.Builder builder)
|
||||
{
|
||||
builder.comment(IBuffers.DESC).push(this.getClass().getSimpleName());
|
||||
|
||||
rebuildTimes = builder
|
||||
.comment("\n\n"
|
||||
+ IBuffers.REBUILD_TIMES_DESC)
|
||||
.defineEnum("rebuildFrequency", IBuffers.REBUILD_TIMES_DEFAULT);
|
||||
|
||||
builder.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** {@link Path} to the configuration file of this mod */
|
||||
private static final Path CONFIG_PATH = Paths.get("config", ModInfo.NAME + ".toml");
|
||||
|
||||
public static final ForgeConfigSpec CLIENT_SPEC;
|
||||
public static final Client CLIENT;
|
||||
|
||||
static
|
||||
{
|
||||
final Pair<Client, ForgeConfigSpec> specPair = new ForgeConfigSpec.Builder().configure(Client::new);
|
||||
CLIENT_SPEC = specPair.getRight();
|
||||
CLIENT = specPair.getLeft();
|
||||
CommentedFileConfig clientConfig = CommentedFileConfig.builder(CONFIG_PATH)
|
||||
.writingMode(WritingMode.REPLACE)
|
||||
.build();
|
||||
clientConfig.load();
|
||||
clientConfig.save();
|
||||
CLIENT_SPEC.setConfig(clientConfig);
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onLoad(final ModConfig.Loading configEvent)
|
||||
{
|
||||
LogManager.getLogger().debug(ModInfo.NAME, "Loaded forge config file {}", configEvent.getConfig().getFileName());
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onFileChange(final ModConfig.Reloading configEvent)
|
||||
{
|
||||
LogManager.getLogger().debug(ModInfo.NAME, "Forge config just got changed on the file system!");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,80 +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.forge;
|
||||
|
||||
import com.seibel.lod.core.ModInfo;
|
||||
import com.seibel.lod.forge.wrappers.ForgeDependencySetup;
|
||||
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.ModLoadingContext;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.config.ModConfig;
|
||||
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
|
||||
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
|
||||
import net.minecraftforge.fml.event.server.FMLServerStartingEvent;
|
||||
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
|
||||
|
||||
/**
|
||||
* Initialize and setup the Mod. <br>
|
||||
* If you are looking for the real start of the mod
|
||||
* check out the ClientProxy.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 11-16-2021
|
||||
*/
|
||||
@Mod(ModInfo.ID)
|
||||
public class ForgeMain
|
||||
{
|
||||
public static ForgeClientProxy forgeClientProxy;
|
||||
|
||||
private void init(final FMLCommonSetupEvent event)
|
||||
{
|
||||
// make sure the dependencies are set up before the mod needs them
|
||||
ForgeDependencySetup.createInitialBindings();
|
||||
ModLoadingContext.get().registerConfig(ModConfig.Type.CLIENT, ForgeConfig.CLIENT_SPEC);
|
||||
}
|
||||
|
||||
|
||||
public ForgeMain()
|
||||
{
|
||||
// Register the methods
|
||||
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::init);
|
||||
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::onClientStart);
|
||||
|
||||
// Register ourselves for server and other game events we are interested in
|
||||
MinecraftForge.EVENT_BUS.register(this);
|
||||
}
|
||||
|
||||
private void onClientStart(final FMLClientSetupEvent event)
|
||||
{
|
||||
forgeClientProxy = new ForgeClientProxy();
|
||||
MinecraftForge.EVENT_BUS.register(forgeClientProxy);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@SubscribeEvent
|
||||
public void onServerStarting(FMLServerStartingEvent event)
|
||||
{
|
||||
// this is called when the server starts
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,80 +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.forge.mixins;
|
||||
|
||||
import org.lwjgl.opengl.GL15;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
import com.seibel.lod.core.api.ClientApi;
|
||||
import com.seibel.lod.core.objects.math.Mat4f;
|
||||
import com.seibel.lod.forge.wrappers.McObjectConverter;
|
||||
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.WorldRenderer;
|
||||
|
||||
/**
|
||||
* This class is used to mix in my rendering code
|
||||
* before Minecraft starts rendering blocks.
|
||||
* If this wasn't done, and we used Forge's
|
||||
* render last event, the LODs would render on top
|
||||
* of the normal terrain.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 9-19-2021
|
||||
*/
|
||||
@Mixin(WorldRenderer.class)
|
||||
public class MixinWorldRenderer
|
||||
{
|
||||
private static float previousPartialTicks = 0;
|
||||
|
||||
@Inject(at = @At("RETURN"), method = "renderSky(Lcom/mojang/blaze3d/matrix/MatrixStack;F)V")
|
||||
private void renderSky(MatrixStack matrixStackIn, float partialTicks, CallbackInfo callback)
|
||||
{
|
||||
// get the partial ticks since renderBlockLayer doesn't
|
||||
// have access to them
|
||||
previousPartialTicks = partialTicks;
|
||||
}
|
||||
|
||||
@Inject(at = @At("HEAD"), method = "renderChunkLayer(Lnet/minecraft/client/renderer/RenderType;Lcom/mojang/blaze3d/matrix/MatrixStack;DDD)V")
|
||||
private void renderChunkLayer(RenderType renderType, MatrixStack matrixStackIn, double xIn, double yIn, double zIn, CallbackInfo callback)
|
||||
{
|
||||
// only render if LODs are enabled and
|
||||
// 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());
|
||||
|
||||
ClientApi.INSTANCE.renderLods(mcModelViewMatrix, mcProjectionMatrix, previousPartialTicks);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
package com.seibel.lod.forge.wrappers;
|
||||
|
||||
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.wrapperInterfaces.IWrapperFactory;
|
||||
import com.seibel.lod.core.wrapperInterfaces.block.IBlockColorSingletonWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
|
||||
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftWrapper;
|
||||
import com.seibel.lod.forge.wrappers.block.BlockColorSingletonWrapper;
|
||||
import com.seibel.lod.forge.wrappers.config.LodConfigWrapperSingleton;
|
||||
import com.seibel.lod.forge.wrappers.minecraft.MinecraftRenderWrapper;
|
||||
import com.seibel.lod.forge.wrappers.minecraft.MinecraftWrapper;
|
||||
|
||||
/**
|
||||
* Binds all necessary dependencies so we
|
||||
* can access them in Core. <br>
|
||||
* This needs to be called before any Core classes
|
||||
* are loaded.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 11-20-2021
|
||||
*/
|
||||
public class ForgeDependencySetup
|
||||
{
|
||||
public static void createInitialBindings()
|
||||
{
|
||||
SingletonHandler.bind(ILodConfigWrapperSingleton.class, LodConfigWrapperSingleton.INSTANCE);
|
||||
SingletonHandler.bind(IBlockColorSingletonWrapper.class, BlockColorSingletonWrapper.INSTANCE);
|
||||
SingletonHandler.bind(IMinecraftWrapper.class, MinecraftWrapper.INSTANCE);
|
||||
SingletonHandler.bind(IMinecraftRenderWrapper.class, MinecraftRenderWrapper.INSTANCE);
|
||||
SingletonHandler.bind(IWrapperFactory.class, WrapperFactory.INSTANCE);
|
||||
|
||||
SingletonHandler.bind(IReflectionHandler.class, ReflectionHandler.createSingleton(MinecraftWrapper.INSTANCE.getOptions().getClass().getDeclaredFields(), MinecraftWrapper.INSTANCE.getOptions()));
|
||||
}
|
||||
}
|
||||
@@ -1,56 +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.forge.wrappers;
|
||||
|
||||
import java.nio.FloatBuffer;
|
||||
|
||||
import com.seibel.lod.core.enums.LodDirection;
|
||||
import com.seibel.lod.core.objects.math.Mat4f;
|
||||
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.vector.Matrix4f;
|
||||
|
||||
/**
|
||||
* This class converts to and from Minecraft objects (Ex: Matrix4f)
|
||||
* and objects we created (Ex: Mat4f).
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 11-20-2021
|
||||
*/
|
||||
public class McObjectConverter
|
||||
{
|
||||
/** 4x4 float matrix converter */
|
||||
public static Mat4f Convert(Matrix4f mcMatrix)
|
||||
{
|
||||
FloatBuffer buffer = FloatBuffer.allocate(16);
|
||||
mcMatrix.store(buffer);
|
||||
Mat4f matrix = new Mat4f(buffer);
|
||||
matrix.transpose();
|
||||
return matrix;
|
||||
}
|
||||
|
||||
|
||||
public static Direction Convert(LodDirection lodDirection)
|
||||
{
|
||||
return Direction.byName(lodDirection.name());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,91 +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.forge.wrappers;
|
||||
|
||||
import com.seibel.lod.core.builders.lodBuilding.LodBuilder;
|
||||
import com.seibel.lod.core.objects.lod.LodDimension;
|
||||
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.world.IWorldWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.worldGeneration.AbstractWorldGeneratorWrapper;
|
||||
import com.seibel.lod.forge.wrappers.block.BlockPosWrapper;
|
||||
import com.seibel.lod.forge.wrappers.chunk.ChunkPosWrapper;
|
||||
import com.seibel.lod.forge.wrappers.worldGeneration.WorldGeneratorWrapper;
|
||||
|
||||
/**
|
||||
* This handles creating abstract wrapper objects.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 11-20-2021
|
||||
*/
|
||||
public class WrapperFactory implements IWrapperFactory
|
||||
{
|
||||
public static final WrapperFactory INSTANCE = new WrapperFactory();
|
||||
|
||||
|
||||
@Override
|
||||
public AbstractBlockPosWrapper createBlockPos()
|
||||
{
|
||||
return new BlockPosWrapper();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractBlockPosWrapper createBlockPos(int x, int y, int z)
|
||||
{
|
||||
return new BlockPosWrapper(x,y,z);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public AbstractChunkPosWrapper createChunkPos()
|
||||
{
|
||||
return new ChunkPosWrapper();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractChunkPosWrapper createChunkPos(int x, int z)
|
||||
{
|
||||
return new ChunkPosWrapper(x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractChunkPosWrapper createChunkPos(AbstractChunkPosWrapper newChunkPos)
|
||||
{
|
||||
return new ChunkPosWrapper(newChunkPos);
|
||||
}
|
||||
|
||||
@Override
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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.forge.wrappers.block;
|
||||
|
||||
import com.seibel.lod.core.wrapperInterfaces.block.IBlockColorSingletonWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.block.IBlockColorWrapper;
|
||||
|
||||
import net.minecraft.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,332 +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.forge.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.core.util.ColorUtil;
|
||||
import com.seibel.lod.core.wrapperInterfaces.block.IBlockColorWrapper;
|
||||
import com.seibel.lod.forge.wrappers.minecraft.MinecraftWrapper;
|
||||
|
||||
import net.minecraft.block.AbstractPlantBlock;
|
||||
import net.minecraft.block.AbstractTopPlantBlock;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.block.BushBlock;
|
||||
import net.minecraft.block.FlowerBlock;
|
||||
import net.minecraft.block.GrassBlock;
|
||||
import net.minecraft.block.IGrowable;
|
||||
import net.minecraft.block.LeavesBlock;
|
||||
import net.minecraft.block.TallGrassBlock;
|
||||
import net.minecraft.client.renderer.model.BakedQuad;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraftforge.client.model.data.ModelDataMap;
|
||||
|
||||
|
||||
/**
|
||||
* @author ??
|
||||
* @version 11-17-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 BlockPos blockPos = new BlockPos(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, dataMap);
|
||||
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, dataMap);
|
||||
if (!quads.isEmpty())
|
||||
break;
|
||||
}
|
||||
|
||||
//the quads list is not empty we extract the first one
|
||||
if (!quads.isEmpty())
|
||||
{
|
||||
isColored = true;
|
||||
texture = quads.get(0).getSprite();
|
||||
}
|
||||
else
|
||||
{
|
||||
isColored = true;
|
||||
texture = mc.getModelManager().getBlockModelShaper().getTexture(block.defaultBlockState(), mc.getClientWorld(), blockPosWrapper.getBlockPos());
|
||||
}
|
||||
|
||||
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++)
|
||||
{
|
||||
// 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 = texture.getPixelRGBA(frameIndex, u, v);
|
||||
|
||||
if (ColorUtil.getAlpha(texture.getPixelRGBA(frameIndex, u, v)) == 0)
|
||||
continue;
|
||||
|
||||
// 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 ((grassInstance() || leavesInstance() || waterIstance()) && (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;
|
||||
|
||||
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.VINE
|
||||
|| block == Blocks.SUGAR_CANE;
|
||||
}
|
||||
|
||||
/** determine if the given block should use the biome's foliage color */
|
||||
private boolean waterIstance()
|
||||
{
|
||||
return block == Blocks.WATER;
|
||||
}
|
||||
|
||||
//--------------//
|
||||
//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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,102 +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.forge.wrappers.block;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import com.seibel.lod.core.enums.LodDirection;
|
||||
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
|
||||
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
/**
|
||||
* @author James Seibel
|
||||
* @version 11-20-2021
|
||||
*/
|
||||
public class BlockPosWrapper extends AbstractBlockPosWrapper
|
||||
{
|
||||
private final BlockPos.Mutable blockPos;
|
||||
|
||||
|
||||
public BlockPosWrapper()
|
||||
{
|
||||
this.blockPos = new BlockPos.Mutable(0, 0, 0);
|
||||
}
|
||||
|
||||
public BlockPosWrapper(int x, int y, int z)
|
||||
{
|
||||
this.blockPos = new BlockPos.Mutable(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(int x, int y, int z)
|
||||
{
|
||||
blockPos.set(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getX()
|
||||
{
|
||||
return blockPos.getX();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getY()
|
||||
{
|
||||
return blockPos.getY();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getZ()
|
||||
{
|
||||
return blockPos.getZ();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get(LodDirection.Axis axis)
|
||||
{
|
||||
return axis.choose(getX(), getY(), getZ());
|
||||
}
|
||||
|
||||
public BlockPos.Mutable getBlockPos()
|
||||
{
|
||||
return blockPos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
return blockPos.equals(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return Objects.hash(blockPos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPosWrapper offset(int x, int y, int z)
|
||||
{
|
||||
blockPos.set(blockPos.getX() + x, blockPos.getY() + y, blockPos.getZ() + z);
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,179 +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.forge.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.forge.wrappers.chunk.ChunkWrapper;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.block.SixWayBlock;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.shapes.VoxelShape;
|
||||
import net.minecraft.world.IBlockReader;
|
||||
|
||||
|
||||
/**
|
||||
* @author ??
|
||||
* @version 11-18-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 boolean toAvoid;
|
||||
private boolean nonFull;
|
||||
private boolean noCollision;
|
||||
|
||||
/**Constructor only require for the block instance we are wrapping**/
|
||||
public BlockShapeWrapper(Block block, IChunkWrapper chunkWrapper, AbstractBlockPosWrapper blockPosWrapper)
|
||||
{
|
||||
this.block = block;
|
||||
this.nonFull = false;
|
||||
this.noCollision = false;
|
||||
this.toAvoid = ofBlockToAvoid();
|
||||
setupShapes((ChunkWrapper) chunkWrapper, (BlockPosWrapper) blockPosWrapper);
|
||||
//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, IChunkWrapper chunkWrapper, AbstractBlockPosWrapper blockPosWrapper)
|
||||
{
|
||||
//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, blockPosWrapper);
|
||||
blockShapeWrapperMap.put(block, blockWrapper);
|
||||
|
||||
//we return the newly created wrapper
|
||||
return blockWrapper;
|
||||
}
|
||||
|
||||
private void setupShapes(ChunkWrapper chunkWrapper, BlockPosWrapper blockPosWrapper)
|
||||
{
|
||||
IBlockReader chunk = chunkWrapper.getChunk();
|
||||
BlockPos blockPos = blockPosWrapper.getBlockPos();
|
||||
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())
|
||||
{
|
||||
AxisAlignedBB 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)
|
||||
|| block.equals(Blocks.VOID_AIR);
|
||||
}
|
||||
//-----------------//
|
||||
//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);
|
||||
}
|
||||
}
|
||||
@@ -1,135 +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.forge.wrappers.chunk;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.chunk.AbstractChunkPosWrapper;
|
||||
import com.seibel.lod.forge.wrappers.block.BlockPosWrapper;
|
||||
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
|
||||
|
||||
/**
|
||||
* @author James Seibel
|
||||
* @version 11-18-2021
|
||||
*/
|
||||
public class ChunkPosWrapper extends AbstractChunkPosWrapper
|
||||
{
|
||||
private final ChunkPos chunkPos;
|
||||
|
||||
public ChunkPosWrapper(ChunkPos newChunkPos)
|
||||
{
|
||||
this.chunkPos = newChunkPos;
|
||||
}
|
||||
|
||||
public ChunkPosWrapper(BlockPos blockPos)
|
||||
{
|
||||
this.chunkPos = new ChunkPos(blockPos);
|
||||
}
|
||||
|
||||
|
||||
public ChunkPosWrapper(AbstractChunkPosWrapper newChunkPos)
|
||||
{
|
||||
this.chunkPos = ((ChunkPosWrapper) newChunkPos).chunkPos;
|
||||
}
|
||||
|
||||
public ChunkPosWrapper(AbstractBlockPosWrapper blockPos)
|
||||
{
|
||||
this.chunkPos = new ChunkPos(((BlockPosWrapper) blockPos).getBlockPos());
|
||||
}
|
||||
|
||||
public ChunkPosWrapper(int chunkX, int chunkZ)
|
||||
{
|
||||
this.chunkPos = new ChunkPos(chunkX, chunkZ);
|
||||
}
|
||||
|
||||
public ChunkPosWrapper()
|
||||
{
|
||||
this.chunkPos = new ChunkPos(0, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public int getX()
|
||||
{
|
||||
return chunkPos.x;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getZ()
|
||||
{
|
||||
return chunkPos.z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinBlockX()
|
||||
{
|
||||
return chunkPos.getMinBlockX();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinBlockZ()
|
||||
{
|
||||
return chunkPos.getMinBlockZ();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRegionX()
|
||||
{
|
||||
return chunkPos.getRegionX();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRegionZ()
|
||||
{
|
||||
return chunkPos.getRegionZ();
|
||||
}
|
||||
|
||||
public ChunkPos getChunkPos()
|
||||
{
|
||||
return chunkPos;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
return chunkPos.equals(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return Objects.hash(chunkPos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPosWrapper getWorldPosition()
|
||||
{
|
||||
BlockPos blockPos = chunkPos.getWorldPosition();
|
||||
return new BlockPosWrapper(blockPos.getX(), blockPos.getY(), blockPos.getZ());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,125 +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.forge.wrappers.chunk;
|
||||
|
||||
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.block.IBlockColorWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.block.IBlockShapeWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||
import com.seibel.lod.forge.wrappers.WrapperUtil;
|
||||
import com.seibel.lod.forge.wrappers.block.BlockColorWrapper;
|
||||
import com.seibel.lod.forge.wrappers.block.BlockPosWrapper;
|
||||
import com.seibel.lod.forge.wrappers.block.BlockShapeWrapper;
|
||||
import com.seibel.lod.forge.wrappers.world.BiomeWrapper;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.ILiquidContainer;
|
||||
import net.minecraft.block.IWaterLoggable;
|
||||
import net.minecraft.state.properties.BlockStateProperties;
|
||||
import net.minecraft.world.chunk.IChunk;
|
||||
|
||||
/**
|
||||
* @author ??
|
||||
* @version 11-17-2021
|
||||
*/
|
||||
public class ChunkWrapper implements IChunkWrapper
|
||||
{
|
||||
private final IChunk chunk;
|
||||
private final ChunkPosWrapper chunkPos;
|
||||
|
||||
@Override
|
||||
public int getHeight()
|
||||
{
|
||||
return chunk.getMaxBuildHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPositionInWater(AbstractBlockPosWrapper blockPos)
|
||||
{
|
||||
BlockState blockState = chunk.getBlockState(((BlockPosWrapper) blockPos).getBlockPos());
|
||||
|
||||
//This type of block is always in water
|
||||
return ((blockState.getBlock() instanceof ILiquidContainer) && !(blockState.getBlock() instanceof IWaterLoggable))
|
||||
|| (blockState.hasProperty(BlockStateProperties.WATERLOGGED) && blockState.getValue(BlockStateProperties.WATERLOGGED));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHeightMapValue(int xRel, int zRel)
|
||||
{
|
||||
return chunk.getOrCreateHeightmapUnprimed(WrapperUtil.DEFAULT_HEIGHTMAP).getFirstAvailable(xRel, zRel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomeWrapper getBiome(int xRel, int yAbs, int zRel)
|
||||
{
|
||||
return BiomeWrapper.getBiomeWrapper(chunk.getBiomes().getNoiseBiome(xRel >> 2, yAbs >> 2, zRel >> 2));
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBlockColorWrapper getBlockColorWrapper(AbstractBlockPosWrapper blockPos)
|
||||
{
|
||||
return BlockColorWrapper.getBlockColorWrapper(chunk.getBlockState(((BlockPosWrapper) blockPos).getBlockPos()).getBlock());
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBlockShapeWrapper getBlockShapeWrapper(AbstractBlockPosWrapper blockPos)
|
||||
{
|
||||
return BlockShapeWrapper.getBlockShapeWrapper(chunk.getBlockState(((BlockPosWrapper) blockPos).getBlockPos()).getBlock(), this, blockPos);
|
||||
}
|
||||
|
||||
public ChunkWrapper(IChunk chunk)
|
||||
{
|
||||
this.chunk = chunk;
|
||||
this.chunkPos = new ChunkPosWrapper(chunk.getPos());
|
||||
}
|
||||
|
||||
public IChunk getChunk()
|
||||
{
|
||||
return chunk;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChunkPosWrapper getPos()
|
||||
{
|
||||
return chunkPos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLightCorrect()
|
||||
{
|
||||
return chunk.isLightCorrect();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWaterLogged(AbstractBlockPosWrapper blockPos)
|
||||
{
|
||||
BlockState blockState = chunk.getBlockState(((BlockPosWrapper)blockPos).getBlockPos());
|
||||
|
||||
//This type of block is always in water
|
||||
return ((blockState.getBlock() instanceof ILiquidContainer) && !(blockState.getBlock() instanceof IWaterLoggable))
|
||||
|| (blockState.hasProperty(BlockStateProperties.WATERLOGGED) && blockState.getValue(BlockStateProperties.WATERLOGGED));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEmittedBrightness(AbstractBlockPosWrapper blockPos)
|
||||
{
|
||||
return chunk.getLightEmission(((BlockPosWrapper)blockPos).getBlockPos());
|
||||
}
|
||||
}
|
||||
@@ -1,491 +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.forge.wrappers.config;
|
||||
|
||||
import com.seibel.lod.core.enums.config.BlocksToAvoid;
|
||||
import com.seibel.lod.core.enums.config.BufferRebuildTimes;
|
||||
import com.seibel.lod.core.enums.config.DistanceGenerationMode;
|
||||
import com.seibel.lod.core.enums.config.GenerationPriority;
|
||||
import com.seibel.lod.core.enums.config.GpuUploadMethod;
|
||||
import com.seibel.lod.core.enums.config.HorizontalQuality;
|
||||
import com.seibel.lod.core.enums.config.HorizontalResolution;
|
||||
import com.seibel.lod.core.enums.config.HorizontalScale;
|
||||
import com.seibel.lod.core.enums.config.LodTemplate;
|
||||
import com.seibel.lod.core.enums.config.VanillaOverdraw;
|
||||
import com.seibel.lod.core.enums.config.VerticalQuality;
|
||||
import com.seibel.lod.core.enums.rendering.DebugMode;
|
||||
import com.seibel.lod.core.enums.rendering.FogDistance;
|
||||
import com.seibel.lod.core.enums.rendering.FogDrawOverride;
|
||||
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
|
||||
import com.seibel.lod.forge.ForgeConfig;
|
||||
|
||||
/**
|
||||
* @author James Seibel
|
||||
* @version 11-16-2021
|
||||
*/
|
||||
public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
|
||||
{
|
||||
public static final LodConfigWrapperSingleton INSTANCE = new LodConfigWrapperSingleton();
|
||||
|
||||
|
||||
private static final Client client = new Client();
|
||||
@Override
|
||||
public IClient client()
|
||||
{
|
||||
return client;
|
||||
}
|
||||
|
||||
public static class Client implements IClient
|
||||
{
|
||||
public final IGraphics graphics;
|
||||
public final IWorldGenerator worldGenerator;
|
||||
public final IAdvanced advanced;
|
||||
|
||||
|
||||
@Override
|
||||
public IGraphics graphics()
|
||||
{
|
||||
return graphics;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IWorldGenerator worldGenerator()
|
||||
{
|
||||
return worldGenerator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IAdvanced advanced()
|
||||
{
|
||||
return advanced;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//================//
|
||||
// Client Configs //
|
||||
//================//
|
||||
public Client()
|
||||
{
|
||||
graphics = new Graphics();
|
||||
worldGenerator = new WorldGenerator();
|
||||
advanced = new Advanced();
|
||||
}
|
||||
|
||||
|
||||
//==================//
|
||||
// Graphics Configs //
|
||||
//==================//
|
||||
public static class Graphics implements IGraphics
|
||||
{
|
||||
public final IQuality quality;
|
||||
public final IFogQuality fogQuality;
|
||||
public final IAdvancedGraphics advancedGraphics;
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public IQuality quality()
|
||||
{
|
||||
return quality;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IFogQuality fogQuality()
|
||||
{
|
||||
return fogQuality;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IAdvancedGraphics advancedGraphics()
|
||||
{
|
||||
return advancedGraphics;
|
||||
}
|
||||
|
||||
|
||||
Graphics()
|
||||
{
|
||||
quality = new Quality();
|
||||
advancedGraphics = new AdvancedGraphics();
|
||||
fogQuality = new FogQuality();
|
||||
}
|
||||
|
||||
|
||||
public static class Quality implements IQuality
|
||||
{
|
||||
@Override
|
||||
public HorizontalResolution getDrawResolution()
|
||||
{
|
||||
return ForgeConfig.CLIENT.graphics.qualityOption.drawResolution.get();
|
||||
}
|
||||
@Override
|
||||
public void setDrawResolution(HorizontalResolution newHorizontalResolution)
|
||||
{
|
||||
ForgeConfig.CLIENT.graphics.qualityOption.drawResolution.set(newHorizontalResolution);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getLodChunkRenderDistance()
|
||||
{
|
||||
return ForgeConfig.CLIENT.graphics.qualityOption.lodChunkRenderDistance.get();
|
||||
}
|
||||
@Override
|
||||
public void setLodChunkRenderDistance(int newLodChunkRenderDistance)
|
||||
{
|
||||
ForgeConfig.CLIENT.graphics.qualityOption.lodChunkRenderDistance.set(newLodChunkRenderDistance);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public VerticalQuality getVerticalQuality()
|
||||
{
|
||||
return ForgeConfig.CLIENT.graphics.qualityOption.verticalQuality.get();
|
||||
}
|
||||
@Override
|
||||
public void setVerticalQuality(VerticalQuality newVerticalQuality)
|
||||
{
|
||||
ForgeConfig.CLIENT.graphics.qualityOption.verticalQuality.set(newVerticalQuality);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public HorizontalScale getHorizontalScale()
|
||||
{
|
||||
return ForgeConfig.CLIENT.graphics.qualityOption.horizontalScale.get();
|
||||
}
|
||||
@Override
|
||||
public void setHorizontalScale(HorizontalScale newHorizontalScale)
|
||||
{
|
||||
ForgeConfig.CLIENT.graphics.qualityOption.horizontalScale.set(newHorizontalScale);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public HorizontalQuality getHorizontalQuality()
|
||||
{
|
||||
return ForgeConfig.CLIENT.graphics.qualityOption.horizontalQuality.get();
|
||||
}
|
||||
@Override
|
||||
public void setHorizontalQuality(HorizontalQuality newHorizontalQuality)
|
||||
{
|
||||
ForgeConfig.CLIENT.graphics.qualityOption.horizontalQuality.set(newHorizontalQuality);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class FogQuality implements IFogQuality
|
||||
{
|
||||
@Override
|
||||
public FogDistance getFogDistance()
|
||||
{
|
||||
return ForgeConfig.CLIENT.graphics.fogQuality.fogDistance.get();
|
||||
}
|
||||
@Override
|
||||
public void setFogDistance(FogDistance newFogDistance)
|
||||
{
|
||||
ForgeConfig.CLIENT.graphics.fogQuality.fogDistance.set(newFogDistance);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public FogDrawOverride getFogDrawOverride()
|
||||
{
|
||||
return ForgeConfig.CLIENT.graphics.fogQuality.fogDrawOverride.get();
|
||||
}
|
||||
@Override
|
||||
public void setFogDrawOverride(FogDrawOverride newFogDrawOverride)
|
||||
{
|
||||
ForgeConfig.CLIENT.graphics.fogQuality.fogDrawOverride.set(newFogDrawOverride);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean getDisableVanillaFog()
|
||||
{
|
||||
return ForgeConfig.CLIENT.graphics.fogQuality.disableVanillaFog.get();
|
||||
}
|
||||
@Override
|
||||
public void setDisableVanillaFog(boolean newDisableVanillaFog)
|
||||
{
|
||||
ForgeConfig.CLIENT.graphics.fogQuality.disableVanillaFog.set(newDisableVanillaFog);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class AdvancedGraphics implements IAdvancedGraphics
|
||||
{
|
||||
@Override
|
||||
public LodTemplate getLodTemplate()
|
||||
{
|
||||
return ForgeConfig.CLIENT.graphics.advancedGraphicsOption.lodTemplate.get();
|
||||
}
|
||||
@Override
|
||||
public void setLodTemplate(LodTemplate newLodTemplate)
|
||||
{
|
||||
ForgeConfig.CLIENT.graphics.advancedGraphicsOption.lodTemplate.set(newLodTemplate);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean getDisableDirectionalCulling()
|
||||
{
|
||||
return ForgeConfig.CLIENT.graphics.advancedGraphicsOption.disableDirectionalCulling.get();
|
||||
}
|
||||
@Override
|
||||
public void setDisableDirectionalCulling(boolean newDisableDirectionalCulling)
|
||||
{
|
||||
ForgeConfig.CLIENT.graphics.advancedGraphicsOption.disableDirectionalCulling.set(newDisableDirectionalCulling);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean getAlwaysDrawAtMaxQuality()
|
||||
{
|
||||
return ForgeConfig.CLIENT.graphics.advancedGraphicsOption.alwaysDrawAtMaxQuality.get();
|
||||
}
|
||||
@Override
|
||||
public void setAlwaysDrawAtMaxQuality(boolean newAlwaysDrawAtMaxQuality)
|
||||
{
|
||||
ForgeConfig.CLIENT.graphics.advancedGraphicsOption.alwaysDrawAtMaxQuality.set(newAlwaysDrawAtMaxQuality);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public VanillaOverdraw getVanillaOverdraw()
|
||||
{
|
||||
return ForgeConfig.CLIENT.graphics.advancedGraphicsOption.vanillaOverdraw.get();
|
||||
}
|
||||
@Override
|
||||
public void setVanillaOverdraw(VanillaOverdraw newVanillaOverdraw)
|
||||
{
|
||||
ForgeConfig.CLIENT.graphics.advancedGraphicsOption.vanillaOverdraw.set(newVanillaOverdraw);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public GpuUploadMethod getGpuUploadMethod()
|
||||
{
|
||||
return ForgeConfig.CLIENT.graphics.advancedGraphicsOption.gpuUploadMethod.get();
|
||||
}
|
||||
@Override
|
||||
public void setGpuUploadMethod(GpuUploadMethod newDisableVanillaFog)
|
||||
{
|
||||
ForgeConfig.CLIENT.graphics.advancedGraphicsOption.gpuUploadMethod.set(newDisableVanillaFog);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean getUseExtendedNearClipPlane()
|
||||
{
|
||||
return ForgeConfig.CLIENT.graphics.advancedGraphicsOption.useExtendedNearClipPlane.get();
|
||||
}
|
||||
@Override
|
||||
public void setUseExtendedNearClipPlane(boolean newUseExtendedNearClipPlane)
|
||||
{
|
||||
ForgeConfig.CLIENT.graphics.advancedGraphicsOption.useExtendedNearClipPlane.set(newUseExtendedNearClipPlane);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//========================//
|
||||
// WorldGenerator Configs //
|
||||
//========================//
|
||||
public static class WorldGenerator implements IWorldGenerator
|
||||
{
|
||||
@Override
|
||||
public GenerationPriority getGenerationPriority()
|
||||
{
|
||||
return ForgeConfig.CLIENT.worldGenerator.generationPriority.get();
|
||||
}
|
||||
@Override
|
||||
public void setGenerationPriority(GenerationPriority newGenerationPriority)
|
||||
{
|
||||
ForgeConfig.CLIENT.worldGenerator.generationPriority.set(newGenerationPriority);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public DistanceGenerationMode getDistanceGenerationMode()
|
||||
{
|
||||
return ForgeConfig.CLIENT.worldGenerator.distanceGenerationMode.get();
|
||||
}
|
||||
@Override
|
||||
public void setDistanceGenerationMode(DistanceGenerationMode newDistanceGenerationMode)
|
||||
{
|
||||
ForgeConfig.CLIENT.worldGenerator.distanceGenerationMode.set(newDistanceGenerationMode);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean getAllowUnstableFeatureGeneration()
|
||||
{
|
||||
return ForgeConfig.CLIENT.worldGenerator.allowUnstableFeatureGeneration.get();
|
||||
}
|
||||
@Override
|
||||
public void setAllowUnstableFeatureGeneration(boolean newAllowUnstableFeatureGeneration)
|
||||
{
|
||||
ForgeConfig.CLIENT.worldGenerator.allowUnstableFeatureGeneration.set(newAllowUnstableFeatureGeneration);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public BlocksToAvoid getBlocksToAvoid()
|
||||
{
|
||||
return ForgeConfig.CLIENT.worldGenerator.blocksToAvoid.get();
|
||||
}
|
||||
@Override
|
||||
public void setBlockToAvoid(BlocksToAvoid newBlockToAvoid)
|
||||
{
|
||||
ForgeConfig.CLIENT.worldGenerator.blocksToAvoid.set(newBlockToAvoid);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//============================//
|
||||
// AdvancedModOptions Configs //
|
||||
//============================//
|
||||
public static class Advanced implements IAdvanced
|
||||
{
|
||||
public final IThreading threading;
|
||||
public final IDebugging debugging;
|
||||
public final IBuffers buffers;
|
||||
|
||||
|
||||
@Override
|
||||
public IThreading threading()
|
||||
{
|
||||
return threading;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public IDebugging debugging()
|
||||
{
|
||||
return debugging;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public IBuffers buffers()
|
||||
{
|
||||
return buffers;
|
||||
}
|
||||
|
||||
|
||||
public Advanced()
|
||||
{
|
||||
threading = new Threading();
|
||||
debugging = new Debugging();
|
||||
buffers = new Buffers();
|
||||
}
|
||||
|
||||
public static class Threading implements IThreading
|
||||
{
|
||||
@Override
|
||||
public int getNumberOfWorldGenerationThreads()
|
||||
{
|
||||
return ForgeConfig.CLIENT.advancedModOptions.threading.numberOfWorldGenerationThreads.get();
|
||||
}
|
||||
@Override
|
||||
public void setNumberOfWorldGenerationThreads(int newNumberOfWorldGenerationThreads)
|
||||
{
|
||||
ForgeConfig.CLIENT.advancedModOptions.threading.numberOfWorldGenerationThreads.set(newNumberOfWorldGenerationThreads);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getNumberOfBufferBuilderThreads()
|
||||
{
|
||||
return ForgeConfig.CLIENT.advancedModOptions.threading.numberOfBufferBuilderThreads.get();
|
||||
}
|
||||
@Override
|
||||
public void setNumberOfBufferBuilderThreads(int newNumberOfWorldBuilderThreads)
|
||||
{
|
||||
ForgeConfig.CLIENT.advancedModOptions.threading.numberOfBufferBuilderThreads.set(newNumberOfWorldBuilderThreads);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//===============//
|
||||
// Debug Options //
|
||||
//===============//
|
||||
public static class Debugging implements IDebugging
|
||||
{
|
||||
@Override
|
||||
public boolean getDrawLods()
|
||||
{
|
||||
return ForgeConfig.CLIENT.advancedModOptions.debugging.drawLods.get();
|
||||
}
|
||||
@Override
|
||||
public void setDrawLods(boolean newDrawLods)
|
||||
{
|
||||
ForgeConfig.CLIENT.advancedModOptions.debugging.drawLods.set(newDrawLods);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public DebugMode getDebugMode()
|
||||
{
|
||||
return ForgeConfig.CLIENT.advancedModOptions.debugging.debugMode.get();
|
||||
}
|
||||
@Override
|
||||
public void setDebugMode(DebugMode newDebugMode)
|
||||
{
|
||||
ForgeConfig.CLIENT.advancedModOptions.debugging.debugMode.set(newDebugMode);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean getDebugKeybindingsEnabled()
|
||||
{
|
||||
return ForgeConfig.CLIENT.advancedModOptions.debugging.enableDebugKeybindings.get();
|
||||
}
|
||||
@Override
|
||||
public void setDebugKeybindingsEnabled(boolean newEnableDebugKeybindings)
|
||||
{
|
||||
ForgeConfig.CLIENT.advancedModOptions.debugging.enableDebugKeybindings.set(newEnableDebugKeybindings);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class Buffers implements IBuffers
|
||||
{
|
||||
@Override
|
||||
public BufferRebuildTimes getRebuildTimes()
|
||||
{
|
||||
return ForgeConfig.CLIENT.advancedModOptions.buffers.rebuildTimes.get();
|
||||
}
|
||||
@Override
|
||||
public void setRebuildTimes(BufferRebuildTimes newBufferRebuildTimes)
|
||||
{
|
||||
ForgeConfig.CLIENT.advancedModOptions.buffers.rebuildTimes.set(newBufferRebuildTimes);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,139 +0,0 @@
|
||||
package com.seibel.lod.forge.wrappers.minecraft;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
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.block.AbstractBlockPosWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.chunk.AbstractChunkPosWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
import com.seibel.lod.forge.wrappers.McObjectConverter;
|
||||
import com.seibel.lod.forge.wrappers.block.BlockPosWrapper;
|
||||
import com.seibel.lod.forge.wrappers.chunk.ChunkPosWrapper;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.ActiveRenderInfo;
|
||||
import net.minecraft.client.renderer.GameRenderer;
|
||||
import net.minecraft.client.renderer.WorldRenderer;
|
||||
import net.minecraft.client.renderer.chunk.ChunkRenderDispatcher.CompiledChunk;
|
||||
import net.minecraft.potion.Effects;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.vector.Vector3d;
|
||||
import net.minecraft.util.math.vector.Vector3f;
|
||||
|
||||
/**
|
||||
* A singleton that contains everything
|
||||
* related to rendering in Minecraft.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 11-18-2021
|
||||
*/
|
||||
public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
|
||||
{
|
||||
public static final MinecraftRenderWrapper INSTANCE = new MinecraftRenderWrapper();
|
||||
|
||||
private final GameRenderer gameRenderer = Minecraft.getInstance().gameRenderer;
|
||||
private final static Minecraft mc = Minecraft.getInstance();
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public Vec3f getLookAtVector()
|
||||
{
|
||||
ActiveRenderInfo camera = gameRenderer.getMainCamera();
|
||||
Vector3f cameraDir = camera.getLookVector();
|
||||
return new Vec3f(cameraDir.x(), cameraDir.y(), cameraDir.z());
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractBlockPosWrapper getCameraBlockPosition()
|
||||
{
|
||||
ActiveRenderInfo camera = gameRenderer.getMainCamera();
|
||||
BlockPos blockPos = camera.getBlockPosition();
|
||||
return new BlockPosWrapper(blockPos.getX(), blockPos.getY(), blockPos.getZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playerHasBlindnessEffect()
|
||||
{
|
||||
return mc.player.getActiveEffectsMap().get(Effects.BLINDNESS) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vec3d getCameraExactPosition()
|
||||
{
|
||||
ActiveRenderInfo camera = gameRenderer.getMainCamera();
|
||||
Vector3d projectedView = camera.getPosition();
|
||||
|
||||
return new Vec3d(projectedView.x, projectedView.y, projectedView.z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mat4f getDefaultProjectionMatrix(float partialTicks)
|
||||
{
|
||||
return McObjectConverter.Convert(gameRenderer.getProjectionMatrix(gameRenderer.getMainCamera(), partialTicks, true));
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getGamma()
|
||||
{
|
||||
return mc.options.gamma;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getFov(float partialTicks)
|
||||
{
|
||||
return gameRenderer.getFov(gameRenderer.getMainCamera(), partialTicks, true);
|
||||
}
|
||||
|
||||
/** Measured in chunks */
|
||||
@Override
|
||||
public int getRenderDistance()
|
||||
{
|
||||
return mc.options.renderDistance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getScreenWidth()
|
||||
{
|
||||
return mc.getWindow().getWidth();
|
||||
}
|
||||
@Override
|
||||
public int getScreenHeight()
|
||||
{
|
||||
return mc.getWindow().getHeight();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns the ChunkPos of all chunks that Minecraft
|
||||
* is going to render this frame. <br><br>
|
||||
* <p>
|
||||
* Note: This isn't perfect. It will return some chunks that are outside
|
||||
* the clipping plane. (For example, if you are high above the ground some chunks
|
||||
* will be incorrectly added, even though they are outside render range).
|
||||
*/
|
||||
@Override
|
||||
public HashSet<AbstractChunkPosWrapper> getRenderedChunks()
|
||||
{
|
||||
HashSet<AbstractChunkPosWrapper> loadedPos = new HashSet<>();
|
||||
|
||||
// Wow, those are some long names!
|
||||
|
||||
// go through every RenderInfo to get the compiled chunks
|
||||
WorldRenderer renderer = mc.levelRenderer;
|
||||
for (WorldRenderer.LocalRenderInformationContainer worldRenderer$LocalRenderInformationContainer : renderer.renderChunks)
|
||||
{
|
||||
CompiledChunk compiledChunk = worldRenderer$LocalRenderInformationContainer.chunk.getCompiledChunk();
|
||||
if (!compiledChunk.hasNoRenderableLayers())
|
||||
{
|
||||
// add the ChunkPos for every rendered chunk
|
||||
BlockPos bpos = worldRenderer$LocalRenderInformationContainer.chunk.getOrigin();
|
||||
|
||||
loadedPos.add(new ChunkPosWrapper(bpos));
|
||||
}
|
||||
}
|
||||
|
||||
return loadedPos;
|
||||
}
|
||||
}
|
||||
@@ -1,394 +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.forge.wrappers.minecraft;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.seibel.lod.core.ModInfo;
|
||||
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.IProfilerWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.misc.ILightMapWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.world.IDimensionTypeWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
|
||||
import com.seibel.lod.forge.wrappers.McObjectConverter;
|
||||
import com.seibel.lod.forge.wrappers.block.BlockPosWrapper;
|
||||
import com.seibel.lod.forge.wrappers.chunk.ChunkPosWrapper;
|
||||
import com.seibel.lod.forge.wrappers.misc.LightMapWrapper;
|
||||
import com.seibel.lod.forge.wrappers.world.DimensionTypeWrapper;
|
||||
import com.seibel.lod.forge.wrappers.world.WorldWrapper;
|
||||
|
||||
import net.minecraft.client.GameSettings;
|
||||
import net.minecraft.client.MainWindow;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.entity.player.ClientPlayerEntity;
|
||||
import net.minecraft.client.multiplayer.ServerData;
|
||||
import net.minecraft.client.network.play.ClientPlayNetHandler;
|
||||
import net.minecraft.client.renderer.GameRenderer;
|
||||
import net.minecraft.client.renderer.LightTexture;
|
||||
import net.minecraft.client.renderer.WorldRenderer;
|
||||
import net.minecraft.client.renderer.model.ModelManager;
|
||||
import net.minecraft.client.renderer.texture.NativeImage;
|
||||
import net.minecraft.client.world.ClientWorld;
|
||||
import net.minecraft.crash.CrashReport;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.server.integrated.IntegratedServer;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.text.StringTextComponent;
|
||||
import net.minecraft.world.DimensionType;
|
||||
import net.minecraft.world.server.ServerWorld;
|
||||
|
||||
/**
|
||||
* A singleton that wraps the Minecraft class
|
||||
* to allow for easier movement between Minecraft versions.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 9-16-2021
|
||||
*/
|
||||
public class MinecraftWrapper implements IMinecraftWrapper
|
||||
{
|
||||
public static final MinecraftWrapper INSTANCE = new MinecraftWrapper();
|
||||
|
||||
private final Minecraft mc = Minecraft.getInstance();
|
||||
|
||||
/**
|
||||
* The lightmap for the current:
|
||||
* Time, dimension, brightness setting, etc.
|
||||
*/
|
||||
private NativeImage lightMap = null;
|
||||
|
||||
private ProfilerWrapper profilerWrapper;
|
||||
|
||||
|
||||
private MinecraftWrapper()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//================//
|
||||
// helper methods //
|
||||
//================//
|
||||
|
||||
/**
|
||||
* This should be called at the beginning of every frame to
|
||||
* clear any Minecraft data that becomes out of date after a frame. <br> <br>
|
||||
* <p>
|
||||
* LightMaps and other time sensitive objects fall in this category. <br> <br>
|
||||
* <p>
|
||||
* This doesn't affect OpenGL objects in any way.
|
||||
*/
|
||||
@Override
|
||||
public void clearFrameObjectCache()
|
||||
{
|
||||
lightMap = null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=================//
|
||||
// method wrappers //
|
||||
//=================//
|
||||
|
||||
@Override
|
||||
public float getShade(LodDirection lodDirection)
|
||||
{
|
||||
Direction mcDir = McObjectConverter.Convert(lodDirection);
|
||||
return mc.level.getShade(mcDir, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSinglePlayerServer()
|
||||
{
|
||||
return mc.hasSingleplayerServer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCurrentServerName()
|
||||
{
|
||||
return mc.getCurrentServer().name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCurrentServerIp()
|
||||
{
|
||||
return mc.getCurrentServer().ip;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCurrentServerVersion()
|
||||
{
|
||||
return mc.getCurrentServer().version.getString();
|
||||
}
|
||||
|
||||
/** Returns the dimension the player is currently in */
|
||||
@Override
|
||||
public IDimensionTypeWrapper getCurrentDimension()
|
||||
{
|
||||
return DimensionTypeWrapper.getDimensionTypeWrapper(mc.player.level.dimensionType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCurrentDimensionId()
|
||||
{
|
||||
return LodUtil.getDimensionIDFromWorld(WorldWrapper.getWorldWrapper(mc.level));
|
||||
}
|
||||
|
||||
/** This texture changes every frame */
|
||||
@Override
|
||||
public ILightMapWrapper getCurrentLightMap()
|
||||
{
|
||||
// get the current lightMap if the cache is empty
|
||||
if (lightMap == null)
|
||||
{
|
||||
LightTexture tex = mc.gameRenderer.lightTexture();
|
||||
lightMap = tex.lightPixels;
|
||||
}
|
||||
return new LightMapWrapper(lightMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the color int at the given pixel coordinates
|
||||
* from the current lightmap.
|
||||
* @param u x location in texture space
|
||||
* @param v z location in texture space
|
||||
*/
|
||||
@Override
|
||||
public int getColorIntFromLightMap(int u, int v)
|
||||
{
|
||||
if (lightMap == null)
|
||||
{
|
||||
// make sure the lightMap is up-to-date
|
||||
getCurrentLightMap();
|
||||
}
|
||||
|
||||
return lightMap.getPixelRGBA(u, v);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Color at the given pixel coordinates
|
||||
* from the current lightmap.
|
||||
* @param u x location in texture space
|
||||
* @param v z location in texture space
|
||||
*/
|
||||
@Override
|
||||
public Color getColorFromLightMap(int u, int v)
|
||||
{
|
||||
return LodUtil.intToColor(lightMap.getPixelRGBA(u, v));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// Simple gets //
|
||||
//=============//
|
||||
|
||||
public ClientPlayerEntity getPlayer()
|
||||
{
|
||||
return mc.player;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playerExists()
|
||||
{
|
||||
return mc.player != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPosWrapper getPlayerBlockPos()
|
||||
{
|
||||
BlockPos playerPos = getPlayer().blockPosition();
|
||||
return new BlockPosWrapper(playerPos.getX(), playerPos.getY(), playerPos.getZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChunkPosWrapper getPlayerChunkPos()
|
||||
{
|
||||
return new ChunkPosWrapper(getPlayer().xChunk, getPlayer().zChunk);
|
||||
}
|
||||
|
||||
public GameSettings getOptions()
|
||||
{
|
||||
return mc.options;
|
||||
}
|
||||
|
||||
public ModelManager getModelManager()
|
||||
{
|
||||
return mc.getModelManager();
|
||||
}
|
||||
|
||||
public ClientWorld getClientWorld()
|
||||
{
|
||||
return mc.level;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to get the ServerWorld for the dimension
|
||||
* the user is currently in.
|
||||
* @returns null if no ServerWorld is available
|
||||
*/
|
||||
@Override
|
||||
public IWorldWrapper getWrappedServerWorld()
|
||||
{
|
||||
if (mc.level == null)
|
||||
return null;
|
||||
|
||||
DimensionType dimension = mc.level.dimensionType();
|
||||
IntegratedServer server = mc.getSingleplayerServer();
|
||||
|
||||
if (server == null)
|
||||
return null;
|
||||
|
||||
ServerWorld serverWorld = null;
|
||||
Iterable<ServerWorld> worlds = server.getAllLevels();
|
||||
for (ServerWorld world : worlds)
|
||||
{
|
||||
if (world.dimensionType() == dimension)
|
||||
{
|
||||
serverWorld = world;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return WorldWrapper.getWorldWrapper(serverWorld);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IWorldWrapper getWrappedClientWorld()
|
||||
{
|
||||
return WorldWrapper.getWorldWrapper(mc.level);
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getGameDirectory()
|
||||
{
|
||||
return mc.gameDirectory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IProfilerWrapper getProfiler()
|
||||
{
|
||||
if (profilerWrapper == null)
|
||||
profilerWrapper = new ProfilerWrapper(mc.getProfiler());
|
||||
else if (mc.getProfiler() != profilerWrapper.profiler)
|
||||
profilerWrapper.profiler = mc.getProfiler();
|
||||
|
||||
return profilerWrapper;
|
||||
}
|
||||
|
||||
public ClientPlayNetHandler getConnection()
|
||||
{
|
||||
return mc.getConnection();
|
||||
}
|
||||
|
||||
public GameRenderer getGameRenderer()
|
||||
{
|
||||
return mc.gameRenderer;
|
||||
}
|
||||
|
||||
public Entity getCameraEntity()
|
||||
{
|
||||
return mc.cameraEntity;
|
||||
}
|
||||
|
||||
public MainWindow getWindow()
|
||||
{
|
||||
return mc.getWindow();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getSkyDarken(float partialTicks)
|
||||
{
|
||||
return mc.level.getSkyDarken(partialTicks);
|
||||
}
|
||||
|
||||
public IntegratedServer getSinglePlayerServer()
|
||||
{
|
||||
return mc.getSingleplayerServer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean connectedToServer()
|
||||
{
|
||||
return mc.getCurrentServer() != null;
|
||||
}
|
||||
|
||||
public ServerData getCurrentServer()
|
||||
{
|
||||
return mc.getCurrentServer();
|
||||
}
|
||||
|
||||
public WorldRenderer getLevelRenderer()
|
||||
{
|
||||
return mc.levelRenderer;
|
||||
}
|
||||
|
||||
/** Returns all worlds available to the server */
|
||||
@Override
|
||||
public ArrayList<IWorldWrapper> getAllServerWorlds()
|
||||
{
|
||||
ArrayList<IWorldWrapper> worlds = new ArrayList<IWorldWrapper>();
|
||||
|
||||
Iterable<ServerWorld> serverWorlds = mc.getSingleplayerServer().getAllLevels();
|
||||
for (ServerWorld world : serverWorlds)
|
||||
{
|
||||
worlds.add(WorldWrapper.getWorldWrapper(world));
|
||||
}
|
||||
|
||||
return worlds;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void sendChatMessage(String string)
|
||||
{
|
||||
getPlayer().sendMessage(new StringTextComponent(string), getPlayer().getUUID());
|
||||
}
|
||||
|
||||
/**
|
||||
* Crashes Minecraft, displaying the given errorMessage <br> <br>
|
||||
* In the following format: <br>
|
||||
*
|
||||
* The game crashed whilst <strong>errorMessage</strong> <br>
|
||||
* Error: <strong>ExceptionClass: exceptionErrorMessage</strong> <br>
|
||||
* Exit Code: -1 <br>
|
||||
*/
|
||||
@Override
|
||||
public void crashMinecraft(String errorMessage, Throwable exception)
|
||||
{
|
||||
ClientApi.LOGGER.error(ModInfo.READABLE_NAME + " had the following error: [" + errorMessage + "]. Crashing Minecraft...");
|
||||
CrashReport report = new CrashReport(errorMessage, exception);
|
||||
Minecraft.crash(report);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
package com.seibel.lod.forge.wrappers.minecraft;
|
||||
|
||||
import com.seibel.lod.core.wrapperInterfaces.minecraft.IProfilerWrapper;
|
||||
|
||||
import net.minecraft.profiler.IProfiler;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 11-20-2021
|
||||
*/
|
||||
public class ProfilerWrapper implements IProfilerWrapper
|
||||
{
|
||||
public IProfiler profiler;
|
||||
|
||||
public ProfilerWrapper(IProfiler newProfiler)
|
||||
{
|
||||
profiler = newProfiler;
|
||||
}
|
||||
|
||||
|
||||
/** starts a new section inside the currently running section */
|
||||
@Override
|
||||
public void push(String newSection)
|
||||
{
|
||||
profiler.push(newSection);
|
||||
}
|
||||
|
||||
/** ends the currently running section and starts a new one */
|
||||
@Override
|
||||
public void popPush(String newSection)
|
||||
{
|
||||
profiler.popPush(newSection);
|
||||
}
|
||||
|
||||
/** ends the currently running section */
|
||||
@Override
|
||||
public void pop()
|
||||
{
|
||||
profiler.pop();
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
package com.seibel.lod.forge.wrappers.misc;
|
||||
|
||||
import com.seibel.lod.core.wrapperInterfaces.misc.ILightMapWrapper;
|
||||
|
||||
import net.minecraft.client.renderer.texture.NativeImage;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Leonardo Amato
|
||||
* @version 11-13-2021
|
||||
*/
|
||||
public class LightMapWrapper implements ILightMapWrapper
|
||||
{
|
||||
private NativeImage lightMap = null;
|
||||
|
||||
public LightMapWrapper(NativeImage newlightMap)
|
||||
{
|
||||
lightMap = newlightMap;
|
||||
}
|
||||
|
||||
public void setLightMap(NativeImage newlightMap)
|
||||
{
|
||||
lightMap = newlightMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLightValue(int skyLight, int blockLight)
|
||||
{
|
||||
return lightMap.getPixelRGBA(skyLight, blockLight);
|
||||
}
|
||||
}
|
||||
@@ -1,60 +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.forge.wrappers.world;
|
||||
|
||||
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.world.IBiomeColorWrapperSingleton;
|
||||
import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
|
||||
import com.seibel.lod.forge.wrappers.block.BlockPosWrapper;
|
||||
|
||||
import net.minecraft.world.biome.BiomeColors;
|
||||
|
||||
|
||||
/**
|
||||
* @author Cola?
|
||||
* @version 11-15-2021
|
||||
*/
|
||||
public class BiomeColorWrapperSingleton implements IBiomeColorWrapperSingleton
|
||||
{
|
||||
private static final BiomeColorWrapperSingleton instance = new BiomeColorWrapperSingleton();
|
||||
|
||||
@Override
|
||||
public IBiomeColorWrapperSingleton getInstance()
|
||||
{
|
||||
return instance;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getGrassColor(IWorldWrapper world, AbstractBlockPosWrapper blockPos)
|
||||
{
|
||||
return BiomeColors.getAverageGrassColor(((WorldWrapper)world).getWorld(), ((BlockPosWrapper) blockPos).getBlockPos());
|
||||
}
|
||||
@Override
|
||||
public int getWaterColor(IWorldWrapper world, AbstractBlockPosWrapper blockPos)
|
||||
{
|
||||
return BiomeColors.getAverageWaterColor(((WorldWrapper)world).getWorld(), ((BlockPosWrapper) blockPos).getBlockPos());
|
||||
}
|
||||
@Override
|
||||
public int getFoliageColor(IWorldWrapper world, AbstractBlockPosWrapper blockPos)
|
||||
{
|
||||
return BiomeColors.getAverageFoliageColor(((WorldWrapper)world).getWorld(), ((BlockPosWrapper) blockPos).getBlockPos());
|
||||
}
|
||||
}
|
||||
@@ -1,157 +0,0 @@
|
||||
package com.seibel.lod.forge.wrappers.world;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
import com.seibel.lod.core.util.ColorUtil;
|
||||
import com.seibel.lod.core.wrapperInterfaces.world.IBiomeWrapper;
|
||||
import com.seibel.lod.forge.wrappers.block.BlockColorSingletonWrapper;
|
||||
import com.seibel.lod.forge.wrappers.block.BlockColorWrapper;
|
||||
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.world.biome.Biome;
|
||||
|
||||
|
||||
/**
|
||||
* @author James Seibel
|
||||
* @version 11-15-2021
|
||||
*/
|
||||
public class BiomeWrapper implements IBiomeWrapper
|
||||
{
|
||||
public static final ConcurrentMap<Biome, BiomeWrapper> biomeWrapperMap = new ConcurrentHashMap<>();
|
||||
private final Biome biome;
|
||||
|
||||
public BiomeWrapper(Biome biome)
|
||||
{
|
||||
this.biome = biome;
|
||||
}
|
||||
|
||||
static public BiomeWrapper getBiomeWrapper(Biome biome)
|
||||
{
|
||||
//first we check if the biome has already been wrapped
|
||||
if(biomeWrapperMap.containsKey(biome) && biomeWrapperMap.get(biome) != null)
|
||||
return biomeWrapperMap.get(biome);
|
||||
|
||||
|
||||
//if it hasn't been created yet, we create it and save it in the map
|
||||
BiomeWrapper biomeWrapper = new BiomeWrapper(biome);
|
||||
biomeWrapperMap.put(biome, biomeWrapper);
|
||||
|
||||
//we return the newly created wrapper
|
||||
return biomeWrapper;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** Returns a color int for the given biome. */
|
||||
@Override
|
||||
public int getColorForBiome(int x, int z)
|
||||
{
|
||||
int colorInt;
|
||||
int tintValue = 0;
|
||||
|
||||
switch (biome.getBiomeCategory())
|
||||
{
|
||||
|
||||
case NETHER:
|
||||
colorInt = BlockColorWrapper.getBlockColorWrapper(Blocks.NETHERRACK).getColor();
|
||||
break;
|
||||
|
||||
case THEEND:
|
||||
colorInt = BlockColorWrapper.getBlockColorWrapper(Blocks.END_STONE).getColor();
|
||||
break;
|
||||
|
||||
case BEACH:
|
||||
case DESERT:
|
||||
colorInt = BlockColorWrapper.getBlockColorWrapper(Blocks.SAND).getColor();
|
||||
break;
|
||||
|
||||
case EXTREME_HILLS:
|
||||
colorInt = BlockColorWrapper.getBlockColorWrapper(Blocks.STONE).getColor();
|
||||
break;
|
||||
|
||||
case MUSHROOM:
|
||||
colorInt = BlockColorWrapper.getBlockColorWrapper(Blocks.MYCELIUM).getColor();
|
||||
break;
|
||||
|
||||
case ICY:
|
||||
colorInt = BlockColorWrapper.getBlockColorWrapper(Blocks.SNOW).getColor();
|
||||
break;
|
||||
|
||||
case MESA:
|
||||
colorInt = BlockColorWrapper.getBlockColorWrapper(Blocks.RED_SAND).getColor();
|
||||
break;
|
||||
|
||||
case OCEAN:
|
||||
case RIVER:
|
||||
colorInt = BlockColorSingletonWrapper.INSTANCE.getWaterColor().getColor();
|
||||
tintValue = biome.getWaterColor();
|
||||
break;
|
||||
|
||||
case PLAINS:
|
||||
case SAVANNA:
|
||||
colorInt = BlockColorWrapper.getBlockColorWrapper(Blocks.GRASS_BLOCK).getColor();
|
||||
tintValue = biome.getGrassColor(x, z);
|
||||
colorInt = ColorUtil.multiplyRGBcolors(colorInt,tintValue);
|
||||
break;
|
||||
|
||||
case TAIGA:
|
||||
colorInt = BlockColorWrapper.getBlockColorWrapper(Blocks.SPRUCE_LEAVES).getColor();
|
||||
tintValue = biome.getFoliageColor();
|
||||
colorInt = ColorUtil.multiplyRGBcolors(colorInt,tintValue);
|
||||
break;
|
||||
case JUNGLE:
|
||||
colorInt = BlockColorWrapper.getBlockColorWrapper(Blocks.JUNGLE_LEAVES).getColor();
|
||||
tintValue = biome.getFoliageColor();
|
||||
colorInt = ColorUtil.multiplyRGBcolors(colorInt,tintValue);
|
||||
break;
|
||||
|
||||
case NONE:
|
||||
default:
|
||||
case SWAMP:
|
||||
case FOREST:
|
||||
colorInt = BlockColorWrapper.getBlockColorWrapper(Blocks.OAK_LEAVES).getColor();
|
||||
tintValue = biome.getFoliageColor();
|
||||
colorInt = ColorUtil.multiplyRGBcolors(colorInt,tintValue);
|
||||
break;
|
||||
}
|
||||
|
||||
return colorInt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getGrassTint(int x, int z)
|
||||
{
|
||||
return biome.getGrassColor(x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFolliageTint()
|
||||
{
|
||||
return biome.getFoliageColor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWaterTint()
|
||||
{
|
||||
return biome.getWaterColor();
|
||||
}
|
||||
|
||||
|
||||
@Override public boolean equals(Object o)
|
||||
{
|
||||
if (this == o)
|
||||
return true;
|
||||
if (!(o instanceof BiomeWrapper))
|
||||
return false;
|
||||
BiomeWrapper that = (BiomeWrapper) o;
|
||||
return Objects.equals(biome, that.biome);
|
||||
}
|
||||
|
||||
@Override public int hashCode()
|
||||
{
|
||||
return Objects.hash(biome);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
package com.seibel.lod.forge.wrappers.world;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
import com.seibel.lod.core.wrapperInterfaces.world.IDimensionTypeWrapper;
|
||||
|
||||
import net.minecraft.world.DimensionType;
|
||||
|
||||
/**
|
||||
* @author ??
|
||||
* @version 11-15-2021
|
||||
*/
|
||||
public class DimensionTypeWrapper implements IDimensionTypeWrapper
|
||||
{
|
||||
private static final ConcurrentMap<DimensionType, DimensionTypeWrapper> dimensionTypeWrapperMap = new ConcurrentHashMap<>();
|
||||
private final DimensionType dimensionType;
|
||||
|
||||
public DimensionTypeWrapper(DimensionType dimensionType)
|
||||
{
|
||||
this.dimensionType = dimensionType;
|
||||
}
|
||||
|
||||
public static DimensionTypeWrapper getDimensionTypeWrapper(DimensionType dimensionType)
|
||||
{
|
||||
//first we check if the biome has already been wrapped
|
||||
if(dimensionTypeWrapperMap.containsKey(dimensionType) && dimensionTypeWrapperMap.get(dimensionType) != null)
|
||||
return dimensionTypeWrapperMap.get(dimensionType);
|
||||
|
||||
|
||||
//if it hasn't been created yet, we create it and save it in the map
|
||||
DimensionTypeWrapper dimensionTypeWrapper = new DimensionTypeWrapper(dimensionType);
|
||||
dimensionTypeWrapperMap.put(dimensionType, dimensionTypeWrapper);
|
||||
|
||||
//we return the newly created wrapper
|
||||
return dimensionTypeWrapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDimensionName()
|
||||
{
|
||||
return dimensionType.effectsLocation().getPath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasCeiling()
|
||||
{
|
||||
return dimensionType.hasCeiling();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSkyLight()
|
||||
{
|
||||
return dimensionType.hasSkyLight();
|
||||
}
|
||||
}
|
||||
@@ -1,151 +0,0 @@
|
||||
package com.seibel.lod.forge.wrappers.world;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
import com.seibel.lod.core.enums.WorldType;
|
||||
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
|
||||
import com.seibel.lod.forge.wrappers.block.BlockPosWrapper;
|
||||
|
||||
import net.minecraft.client.world.ClientWorld;
|
||||
import net.minecraft.world.IWorld;
|
||||
import net.minecraft.world.server.ServerChunkProvider;
|
||||
import net.minecraft.world.server.ServerWorld;
|
||||
|
||||
/**
|
||||
* @author James Seibel
|
||||
* @author ??
|
||||
* @version 11-20-2021
|
||||
*/
|
||||
public class WorldWrapper implements IWorldWrapper
|
||||
{
|
||||
private static final ConcurrentMap<IWorld, WorldWrapper> worldWrapperMap = new ConcurrentHashMap<>();
|
||||
private final IWorld world;
|
||||
public final WorldType worldType;
|
||||
|
||||
|
||||
public WorldWrapper(IWorld newWorld)
|
||||
{
|
||||
world = newWorld;
|
||||
|
||||
if (world.getClass() == ServerWorld.class)
|
||||
worldType = WorldType.ServerWorld;
|
||||
else if (world.getClass() == ClientWorld.class)
|
||||
worldType = WorldType.ClientWorld;
|
||||
else
|
||||
worldType = WorldType.Unknown;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static WorldWrapper getWorldWrapper(IWorld world)
|
||||
{
|
||||
//first we check if the biome has already been wrapped
|
||||
if(worldWrapperMap.containsKey(world) && worldWrapperMap.get(world) != null)
|
||||
return worldWrapperMap.get(world);
|
||||
|
||||
|
||||
//if it hasn't been created yet, we create it and save it in the map
|
||||
WorldWrapper worldWrapper = new WorldWrapper(world);
|
||||
worldWrapperMap.put(world, worldWrapper);
|
||||
|
||||
//we return the newly created wrapper
|
||||
return worldWrapper;
|
||||
}
|
||||
|
||||
public static void clearMap()
|
||||
{
|
||||
worldWrapperMap.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldType getWorldType()
|
||||
{
|
||||
return worldType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DimensionTypeWrapper getDimensionType()
|
||||
{
|
||||
return DimensionTypeWrapper.getDimensionTypeWrapper(world.dimensionType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBlockLight(AbstractBlockPosWrapper blockPos)
|
||||
{
|
||||
return world.getLightEngine().blockEngine.getLightValue(((BlockPosWrapper) blockPos).getBlockPos());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSkyLight(AbstractBlockPosWrapper blockPos)
|
||||
{
|
||||
return world.getLightEngine().skyEngine.getLightValue(((BlockPosWrapper) blockPos).getBlockPos());
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomeWrapper getBiome(AbstractBlockPosWrapper blockPos)
|
||||
{
|
||||
return BiomeWrapper.getBiomeWrapper(world.getBiome(((BlockPosWrapper) blockPos).getBlockPos()));
|
||||
}
|
||||
|
||||
public IWorld getWorld()
|
||||
{
|
||||
return world;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasCeiling()
|
||||
{
|
||||
return world.dimensionType().hasCeiling();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSkyLight()
|
||||
{
|
||||
return world.dimensionType().hasSkyLight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty()
|
||||
{
|
||||
return world == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHeight()
|
||||
{
|
||||
return world.getHeight();
|
||||
}
|
||||
|
||||
/** @throws UnsupportedOperationException if the WorldWrapper isn't for a ServerWorld */
|
||||
@Override
|
||||
public File getSaveFolder() throws UnsupportedOperationException
|
||||
{
|
||||
if (worldType != WorldType.ServerWorld)
|
||||
throw new UnsupportedOperationException("getSaveFolder can only be called for ServerWorlds.");
|
||||
|
||||
ServerChunkProvider chunkSource = ((ServerWorld) world).getChunkSource();
|
||||
return chunkSource.dataStorage.dataFolder;
|
||||
}
|
||||
|
||||
|
||||
/** @throws UnsupportedOperationException if the WorldWrapper isn't for a ServerWorld */
|
||||
public ServerWorld getServerWorld() throws UnsupportedOperationException
|
||||
{
|
||||
if (worldType != WorldType.ServerWorld)
|
||||
throw new UnsupportedOperationException("getSaveFolder can only be called for ServerWorlds.");
|
||||
|
||||
return (ServerWorld) world;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSeaLevel()
|
||||
{
|
||||
// TODO this is depreciated, what should we use instead?
|
||||
return world.getSeaLevel();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,332 +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.forge.wrappers.worldGeneration;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import com.seibel.lod.core.util.LodUtil;
|
||||
import com.seibel.lod.forge.wrappers.WrapperUtil;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.fluid.Fluid;
|
||||
import net.minecraft.fluid.FluidState;
|
||||
import net.minecraft.particles.IParticleData;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.SoundCategory;
|
||||
import net.minecraft.util.SoundEvent;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.SectionPos;
|
||||
import net.minecraft.util.registry.DynamicRegistries;
|
||||
import net.minecraft.world.DifficultyInstance;
|
||||
import net.minecraft.world.DimensionType;
|
||||
import net.minecraft.world.EmptyTickList;
|
||||
import net.minecraft.world.ISeedReader;
|
||||
import net.minecraft.world.ITickList;
|
||||
import net.minecraft.world.biome.Biome;
|
||||
import net.minecraft.world.biome.BiomeManager;
|
||||
import net.minecraft.world.border.WorldBorder;
|
||||
import net.minecraft.world.chunk.AbstractChunkProvider;
|
||||
import net.minecraft.world.chunk.ChunkStatus;
|
||||
import net.minecraft.world.chunk.IChunk;
|
||||
import net.minecraft.world.gen.Heightmap;
|
||||
import net.minecraft.world.gen.feature.structure.Structure;
|
||||
import net.minecraft.world.gen.feature.structure.StructureStart;
|
||||
import net.minecraft.world.lighting.WorldLightManager;
|
||||
import net.minecraft.world.server.ServerWorld;
|
||||
import net.minecraft.world.storage.IWorldInfo;
|
||||
|
||||
|
||||
/**
|
||||
* This is a fake ServerWorld used when generating features.
|
||||
* It allows us to keep each LodChunk generation independent
|
||||
* of the actual ServerWorld, allowing
|
||||
* multithread generation.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 7-26-2021
|
||||
*/
|
||||
public class LodServerWorld implements ISeedReader
|
||||
{
|
||||
|
||||
public HashMap<Heightmap.Type, Heightmap> heightmaps = new HashMap<>();
|
||||
|
||||
public final IChunk chunk;
|
||||
|
||||
public final ServerWorld serverWorld;
|
||||
|
||||
public LodServerWorld(ServerWorld newServerWorld, IChunk newChunk)
|
||||
{
|
||||
chunk = newChunk;
|
||||
serverWorld = newServerWorld;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getHeight(Heightmap.Type heightmapType, int x, int z)
|
||||
{
|
||||
// make sure the block position is set relative to the chunk
|
||||
x = x % LodUtil.CHUNK_WIDTH;
|
||||
x = (x < 0) ? x + 16 : x;
|
||||
|
||||
z = z % LodUtil.CHUNK_WIDTH;
|
||||
z = (z < 0) ? z + 16 : z;
|
||||
|
||||
return chunk.getOrCreateHeightmapUnprimed(WrapperUtil.DEFAULT_HEIGHTMAP).getFirstAvailable(x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Biome getBiome(BlockPos pos)
|
||||
{
|
||||
return chunk.getBiomes().getNoiseBiome(pos.getX() >> 2, pos.getY() >> 2, pos.getZ() >> 2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBlock(BlockPos pos, BlockState state, int flags, int recursionLeft)
|
||||
{
|
||||
return chunk.setBlockState(pos, state, false) == state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getBlockState(BlockPos pos)
|
||||
{
|
||||
return chunk.getBlockState(pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FluidState getFluidState(BlockPos pos)
|
||||
{
|
||||
return chunk.getFluidState(pos);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isStateAtPosition(BlockPos pos, Predicate<BlockState> state)
|
||||
{
|
||||
return state.test(chunk.getBlockState(pos));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ITickList<Block> getBlockTicks()
|
||||
{
|
||||
return EmptyTickList.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IChunk getChunk(int x, int z, ChunkStatus requiredStatus, boolean nonnull)
|
||||
{
|
||||
return chunk;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<? extends StructureStart<?>> startsForFeature(SectionPos p_241827_1_, Structure<?> p_241827_2_)
|
||||
{
|
||||
return serverWorld.startsForFeature(p_241827_1_, p_241827_2_);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ITickList<Fluid> getLiquidTicks()
|
||||
{
|
||||
return EmptyTickList.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldLightManager getLightEngine()
|
||||
{
|
||||
return new WorldLightManager(null, false, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSeed()
|
||||
{
|
||||
return serverWorld.getSeed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DynamicRegistries registryAccess()
|
||||
{
|
||||
return serverWorld.registryAccess();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* All methods below shouldn't be needed
|
||||
* and thus have been left unimplemented.
|
||||
*/
|
||||
|
||||
|
||||
@Override
|
||||
public Random getRandom()
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playSound(PlayerEntity player, BlockPos pos, SoundEvent soundIn, SoundCategory category, float volume,
|
||||
float pitch)
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addParticle(IParticleData particleData, double x, double y, double z, double xSpeed, double ySpeed,
|
||||
double zSpeed)
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomeManager getBiomeManager()
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSeaLevel()
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getShade(Direction p_230487_1_, boolean p_230487_2_)
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldBorder getWorldBorder()
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeBlock(BlockPos pos, boolean isMoving)
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean destroyBlock(BlockPos pos, boolean dropBlock, Entity entity, int recursionLeft)
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ServerWorld getLevel()
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public AbstractChunkProvider getChunkSource()
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public DifficultyInstance getCurrentDifficultyAt(BlockPos arg0)
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public IWorldInfo getLevelData()
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void levelEvent(PlayerEntity arg0, int arg1, BlockPos arg2, int arg3)
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<Entity> getEntities(Entity arg0, AxisAlignedBB arg1, Predicate<? super Entity> arg2)
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public <T extends Entity> List<T> getEntitiesOfClass(Class<? extends T> arg0, AxisAlignedBB arg1,
|
||||
Predicate<? super T> arg2)
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<? extends PlayerEntity> players()
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getSkyDarken()
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Biome getUncachedNoiseBiome(int p_225604_1_, int p_225604_2_, int p_225604_3_)
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isClientSide()
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public DimensionType dimensionType()
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public TileEntity getBlockEntity(BlockPos p_175625_1_)
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
}
|
||||
-389
@@ -1,389 +0,0 @@
|
||||
package com.seibel.lod.forge.wrappers.worldGeneration;
|
||||
|
||||
import java.util.ConcurrentModificationException;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
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.LodUtil;
|
||||
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.forge.wrappers.WrapperUtil;
|
||||
import com.seibel.lod.forge.wrappers.chunk.ChunkPosWrapper;
|
||||
import com.seibel.lod.forge.wrappers.chunk.ChunkWrapper;
|
||||
import com.seibel.lod.forge.wrappers.world.WorldWrapper;
|
||||
|
||||
import net.minecraft.util.palette.UpgradeData;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
import net.minecraft.world.biome.Biome;
|
||||
import net.minecraft.world.chunk.ChunkPrimer;
|
||||
import net.minecraft.world.chunk.ChunkStatus;
|
||||
import net.minecraft.world.chunk.IChunk;
|
||||
import net.minecraft.world.gen.ChunkGenerator;
|
||||
import net.minecraft.world.gen.Heightmap;
|
||||
import net.minecraft.world.gen.feature.ConfiguredFeature;
|
||||
import net.minecraft.world.gen.feature.IceAndSnowFeature;
|
||||
import net.minecraft.world.gen.feature.NoFeatureConfig;
|
||||
import net.minecraft.world.gen.feature.template.TemplateManager;
|
||||
import net.minecraft.world.server.ServerChunkProvider;
|
||||
import net.minecraft.world.server.ServerWorld;
|
||||
import net.minecraft.world.server.ServerWorldLightManager;
|
||||
|
||||
/**
|
||||
* @author James Seibel
|
||||
* @version 11-13-2021
|
||||
*/
|
||||
public class WorldGeneratorWrapper extends AbstractWorldGeneratorWrapper
|
||||
{
|
||||
private static final ILodConfigWrapperSingleton CONFIG = SingletonHandler.get(ILodConfigWrapperSingleton.class);
|
||||
|
||||
/**
|
||||
* If a configured feature fails for whatever reason,
|
||||
* add it to this list. This will hopefully remove any
|
||||
* features that could cause issues down the line.
|
||||
*/
|
||||
private static final ConcurrentHashMap<Integer, ConfiguredFeature<?, ?>> FEATURES_TO_AVOID = new ConcurrentHashMap<>();
|
||||
|
||||
|
||||
public final ServerWorld 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)
|
||||
{
|
||||
List<IChunk> chunkList = new LinkedList<>();
|
||||
ChunkPrimer chunk = new ChunkPrimer(((ChunkPosWrapper) pos).getChunkPos(), UpgradeData.EMPTY);
|
||||
chunkList.add(chunk);
|
||||
|
||||
ServerChunkProvider chunkSource = serverWorld.getChunkSource();
|
||||
ChunkGenerator chunkGen = chunkSource.generator;
|
||||
|
||||
// generate the terrain (this is thread safe)
|
||||
ChunkStatus.EMPTY.generate(serverWorld, chunkGen, serverWorld.getStructureManager(), (ServerWorldLightManager) serverWorld.getLightEngine(), null, chunkList);
|
||||
// override the chunk status, so we can run the next generator stage
|
||||
chunk.setStatus(ChunkStatus.STRUCTURE_REFERENCES);
|
||||
chunkGen.createBiomes(serverWorld.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), chunk);
|
||||
chunk.setStatus(ChunkStatus.STRUCTURE_REFERENCES);
|
||||
|
||||
|
||||
|
||||
|
||||
// generate fake height data for this LOD
|
||||
int seaLevel = serverWorld.getSeaLevel();
|
||||
|
||||
boolean simulateHeight = generationMode == DistanceGenerationMode.BIOME_ONLY_SIMULATE_HEIGHT;
|
||||
boolean inTheEnd = false;
|
||||
|
||||
// add fake heightmap data so our LODs aren't at height 0
|
||||
Heightmap heightmap = new Heightmap(chunk, WrapperUtil.DEFAULT_HEIGHTMAP);
|
||||
for (int x = 0; x < LodUtil.CHUNK_WIDTH && !inTheEnd; x++)
|
||||
{
|
||||
for (int z = 0; z < LodUtil.CHUNK_WIDTH && !inTheEnd; z++)
|
||||
{
|
||||
if (simulateHeight)
|
||||
{
|
||||
// these heights are of course aren't super accurate,
|
||||
// they are just to simulate height data where there isn't any
|
||||
switch (chunk.getBiomes().getNoiseBiome(x >> 2, seaLevel >> 2, z >> 2).getBiomeCategory())
|
||||
{
|
||||
case NETHER:
|
||||
heightmap.setHeight(x, z, serverWorld.getHeight() / 2);
|
||||
break;
|
||||
|
||||
case EXTREME_HILLS:
|
||||
heightmap.setHeight(x, z, seaLevel + 30);
|
||||
break;
|
||||
case MESA:
|
||||
case JUNGLE:
|
||||
heightmap.setHeight(x, z, seaLevel + 20);
|
||||
break;
|
||||
case BEACH:
|
||||
heightmap.setHeight(x, z, seaLevel + 5);
|
||||
break;
|
||||
case NONE:
|
||||
heightmap.setHeight(x, z, 0);
|
||||
break;
|
||||
|
||||
case OCEAN:
|
||||
case RIVER:
|
||||
heightmap.setHeight(x, z, seaLevel);
|
||||
break;
|
||||
|
||||
case THEEND:
|
||||
inTheEnd = true;
|
||||
break;
|
||||
|
||||
// DESERT
|
||||
// FOREST
|
||||
// ICY
|
||||
// MUSHROOM
|
||||
// SAVANNA
|
||||
// SWAMP
|
||||
// TAIGA
|
||||
// PLAINS
|
||||
default:
|
||||
heightmap.setHeight(x, z, seaLevel + 10);
|
||||
break;
|
||||
}// heightmap switch
|
||||
}
|
||||
else
|
||||
{
|
||||
// we aren't simulating height
|
||||
// always use sea level
|
||||
heightmap.setHeight(x, z, seaLevel);
|
||||
}
|
||||
}// z
|
||||
}// x
|
||||
|
||||
chunk.setHeightmap(WrapperUtil.DEFAULT_HEIGHTMAP, heightmap.getRawData());
|
||||
|
||||
|
||||
if (!inTheEnd)
|
||||
{
|
||||
lodBuilder.generateLodNodeFromChunk(lodDim, new ChunkWrapper(chunk), new LodBuilderConfig(true, true, false));
|
||||
}
|
||||
else
|
||||
{
|
||||
// if we are in the end, don't generate any chunks.
|
||||
// Since we don't know where the islands are, everything
|
||||
// generates the same, and it looks awful.
|
||||
//TODO it appears that 'if' can be collapsed, but comment says that it should not be a case
|
||||
lodBuilder.generateLodNodeFromChunk(lodDim, new ChunkWrapper(chunk), new LodBuilderConfig(true, true, false));
|
||||
}
|
||||
|
||||
|
||||
// long startTime = System.currentTimeMillis();
|
||||
// long endTime = System.currentTimeMillis();
|
||||
// System.out.println(endTime - startTime);
|
||||
}
|
||||
|
||||
|
||||
/** takes about 10 - 20 ms */
|
||||
@Override
|
||||
public void generateSurface(AbstractChunkPosWrapper pos)
|
||||
{
|
||||
List<IChunk> chunkList = new LinkedList<>();
|
||||
ChunkPrimer chunk = new ChunkPrimer(((ChunkPosWrapper) pos).getChunkPos(), UpgradeData.EMPTY);
|
||||
chunkList.add(chunk);
|
||||
LodServerWorld lodServerWorld = new LodServerWorld(serverWorld, chunk);
|
||||
|
||||
ServerChunkProvider chunkSource = serverWorld.getChunkSource();
|
||||
ServerWorldLightManager lightEngine = (ServerWorldLightManager) serverWorld.getLightEngine();
|
||||
TemplateManager templateManager = serverWorld.getStructureManager();
|
||||
ChunkGenerator chunkGen = chunkSource.generator;
|
||||
|
||||
|
||||
// generate the terrain (this is thread safe)
|
||||
ChunkStatus.EMPTY.generate(serverWorld, chunkGen, templateManager, lightEngine, null, chunkList);
|
||||
// override the chunk status, so we can run the next generator stage
|
||||
chunk.setStatus(ChunkStatus.STRUCTURE_REFERENCES);
|
||||
chunkGen.createBiomes(serverWorld.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), chunk);
|
||||
ChunkStatus.NOISE.generate(serverWorld, chunkGen, templateManager, lightEngine, null, chunkList);
|
||||
ChunkStatus.SURFACE.generate(serverWorld, chunkGen, templateManager, lightEngine, null, chunkList);
|
||||
|
||||
// this feature has been proven to be thread safe,
|
||||
// so we will add it
|
||||
IceAndSnowFeature snowFeature = new IceAndSnowFeature(NoFeatureConfig.CODEC);
|
||||
snowFeature.place(lodServerWorld, chunkGen, serverWorld.random, chunk.getPos().getWorldPosition(), null);
|
||||
|
||||
|
||||
lodBuilder.generateLodNodeFromChunk(lodDim, new ChunkWrapper(chunk), new LodBuilderConfig(DistanceGenerationMode.SURFACE));
|
||||
|
||||
/*TODO if we want to use Biome utils and terrain utils for overworld
|
||||
* lodBuilder.generateLodNodeFromChunk(lodDim, pos ,detailLevel, serverWorld.getSeed());*/
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* takes about 15 - 20 ms
|
||||
* <p>
|
||||
* Causes concurrentModification Exceptions,
|
||||
* which could cause instability or world generation bugs
|
||||
*/
|
||||
@Override
|
||||
public void generateFeatures(AbstractChunkPosWrapper pos)
|
||||
{
|
||||
List<IChunk> chunkList = new LinkedList<>();
|
||||
ChunkPrimer chunk = new ChunkPrimer(((ChunkPosWrapper) pos).getChunkPos(), UpgradeData.EMPTY);
|
||||
chunkList.add(chunk);
|
||||
LodServerWorld lodServerWorld = new LodServerWorld(serverWorld, chunk);
|
||||
|
||||
ServerChunkProvider chunkSource = serverWorld.getChunkSource();
|
||||
ServerWorldLightManager lightEngine = (ServerWorldLightManager) serverWorld.getLightEngine();
|
||||
TemplateManager templateManager = serverWorld.getStructureManager();
|
||||
ChunkGenerator chunkGen = chunkSource.generator;
|
||||
|
||||
|
||||
// generate the terrain (this is thread safe)
|
||||
ChunkStatus.EMPTY.generate(serverWorld, chunkGen, templateManager, lightEngine, null, chunkList);
|
||||
// override the chunk status, so we can run the next generator stage
|
||||
chunk.setStatus(ChunkStatus.STRUCTURE_REFERENCES);
|
||||
chunkGen.createBiomes(serverWorld.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), chunk);
|
||||
ChunkStatus.NOISE.generate(serverWorld, chunkGen, templateManager, lightEngine, null, chunkList);
|
||||
ChunkStatus.SURFACE.generate(serverWorld, chunkGen, templateManager, lightEngine, null, chunkList);
|
||||
|
||||
|
||||
// get all the biomes in the chunk
|
||||
HashSet<Biome> biomes = new HashSet<>();
|
||||
for (int x = 0; x < LodUtil.CHUNK_WIDTH; x++)
|
||||
{
|
||||
for (int z = 0; z < LodUtil.CHUNK_WIDTH; z++)
|
||||
{
|
||||
Biome biome = chunk.getBiomes().getNoiseBiome(x >> 2, serverWorld.getSeaLevel() >> 2, z >> 2);
|
||||
|
||||
// Issue #35
|
||||
// For some reason Jungle biomes cause incredible lag
|
||||
// the features here must be interacting with each other
|
||||
// in unpredictable ways (specifically tree feature generation).
|
||||
// When generating Features my CPU usage generally hovers around 30 - 40%
|
||||
// when generating Jungles it spikes to 100%.
|
||||
if (biome.getBiomeCategory() != Biome.Category.JUNGLE)
|
||||
{
|
||||
// should probably use the heightmap here instead of seaLevel,
|
||||
// but this seems to get the job done well enough
|
||||
biomes.add(biome);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean allowUnstableFeatures = CONFIG.client().worldGenerator().getAllowUnstableFeatureGeneration();
|
||||
|
||||
// generate all the features related to this chunk.
|
||||
// this may or may not be thread safe
|
||||
for (Biome biome : biomes)
|
||||
{
|
||||
List<List<Supplier<ConfiguredFeature<?, ?>>>> featuresForState = biome.generationSettings.features();
|
||||
|
||||
for (List<Supplier<ConfiguredFeature<?, ?>>> suppliers : featuresForState)
|
||||
{
|
||||
for (Supplier<ConfiguredFeature<?, ?>> featureSupplier : suppliers)
|
||||
{
|
||||
ConfiguredFeature<?, ?> configuredFeature = featureSupplier.get();
|
||||
|
||||
if (!allowUnstableFeatures &&
|
||||
FEATURES_TO_AVOID.containsKey(configuredFeature.hashCode()))
|
||||
continue;
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
configuredFeature.place(lodServerWorld, chunkGen, serverWorld.random, chunk.getPos().getWorldPosition());
|
||||
}
|
||||
catch (ConcurrentModificationException | UnsupportedOperationException e)
|
||||
{
|
||||
// This will happen. I'm not sure what to do about it
|
||||
// except pray that it doesn't affect the normal world generation
|
||||
// in any harmful way.
|
||||
// Update: this can cause crashes and high CPU usage.
|
||||
|
||||
// Issue #35
|
||||
// I tried cloning the config for each feature, but that
|
||||
// path was blocked since I can't clone lambda methods.
|
||||
// I tried using a deep cloning library and discovered
|
||||
// the problem there.
|
||||
// ( https://github.com/kostaskougios/cloning
|
||||
// and
|
||||
// https://github.com/EsotericSoftware/kryo )
|
||||
|
||||
if (!allowUnstableFeatures)
|
||||
FEATURES_TO_AVOID.put(configuredFeature.hashCode(), configuredFeature);
|
||||
// ClientProxy.LOGGER.info(configuredFeaturesToAvoid.mappingCount());
|
||||
}
|
||||
// This will happen when the LodServerWorld
|
||||
// isn't able to return something that a feature
|
||||
// generator needs
|
||||
catch (Exception e)
|
||||
{
|
||||
// I'm not sure what happened, print to the log
|
||||
|
||||
e.printStackTrace();
|
||||
|
||||
if (!allowUnstableFeatures)
|
||||
FEATURES_TO_AVOID.put(configuredFeature.hashCode(), configuredFeature);
|
||||
// ClientProxy.LOGGER.info(configuredFeaturesToAvoid.mappingCount());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// generate a Lod like normal
|
||||
lodBuilder.generateLodNodeFromChunk(lodDim, new ChunkWrapper(chunk), new LodBuilderConfig(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)
|
||||
{
|
||||
lodBuilder.generateLodNodeFromChunk(lodDim, new ChunkWrapper(serverWorld.getChunk(pos.getX(), pos.getZ(), ChunkStatus.FEATURES)), new LodBuilderConfig(DistanceGenerationMode.FULL));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* 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,72 +0,0 @@
|
||||
# Note: to update code in eclipse run the "eclipse" command in graldew
|
||||
|
||||
|
||||
# used when creating the projection matrix
|
||||
public net.minecraft.client.renderer.GameRenderer func_215311_a(Lnet/minecraft/client/renderer/ActiveRenderInfo;FZ)D # getFOVModifier
|
||||
public net.minecraft.client.renderer.GameRenderer field_78529_t # rendererUpdateCount
|
||||
public net.minecraft.client.renderer.GameRenderer func_228380_a_(Lcom/mojang/blaze3d/matrix/MatrixStack;F)V # hurtCameraEffect
|
||||
public net.minecraft.client.renderer.GameRenderer func_228383_b_(Lcom/mojang/blaze3d/matrix/MatrixStack;F)V # applyBobbing
|
||||
|
||||
# used when accessing built byteBuffers
|
||||
public net.minecraft.client.renderer.BufferBuilder field_179001_a # byteBuffer
|
||||
|
||||
# used when determining where to save files too
|
||||
public net.minecraft.world.storage.DimensionSavedDataManager field_215759_d # folder
|
||||
|
||||
# used when generating LodChunks
|
||||
public net.minecraft.block.AbstractBlock$AbstractBlockState field_235704_h_ # materialColor
|
||||
|
||||
# used when determining which chunks Vanilla Minecraft is going to render
|
||||
public net.minecraft.client.renderer.WorldRenderer$LocalRenderInformationContainer
|
||||
public net.minecraft.client.renderer.WorldRenderer field_72755_R # renderInfos
|
||||
public net.minecraft.client.renderer.WorldRenderer$LocalRenderInformationContainer field_178036_a # renderChunk
|
||||
|
||||
# used in world generation
|
||||
public net.minecraft.world.server.ServerWorld field_241106_P_ # structuremanager
|
||||
public net.minecraft.world.gen.Heightmap func_202267_b(II)I # getDataArrayIndex
|
||||
public net.minecraft.world.gen.Heightmap func_202272_a(III)V # set
|
||||
public net.minecraft.world.chunk.Chunk field_76634_f # heightMap
|
||||
public net.minecraft.world.chunk.Chunk field_76652_q # sections
|
||||
public net.minecraft.world.chunk.ChunkPrimer field_201661_i # sections
|
||||
public net.minecraft.world.server.ChunkManager field_219269_w # templateManager
|
||||
public net.minecraft.world.server.ChunkManager field_219256_j # lightManager
|
||||
public net.minecraft.world.gen.feature.template.TemplateManager field_186240_a # templates
|
||||
public net.minecraft.world.biome.Biome field_242424_k # biomeGenerationSettings
|
||||
public net.minecraft.world.gen.blockstateprovider.WeightedBlockStateProvider field_227406_b_ # weightedStates
|
||||
public net.minecraft.world.gen.placement.ConfiguredPlacement field_215096_a # decorator
|
||||
public net.minecraft.world.gen.placement.ConfiguredPlacement field_215097_b # config
|
||||
public net.minecraft.util.WeightedList field_220658_a # weightedEntries
|
||||
public net.minecraft.world.gen.feature.FeatureSpread field_242250_b # base
|
||||
public net.minecraft.world.gen.feature.FeatureSpread field_242251_c # spread
|
||||
public net.minecraft.world.gen.feature.ConfiguredFeature func_242765_a(Lnet/minecraft/world/ISeedReader;Lnet/minecraft/world/gen/ChunkGenerator;Ljava/util/Random;Lnet/minecraft/util/math/BlockPos;)Z # place
|
||||
public net.minecraft.world.server.ServerChunkProvider field_217244_j # dataStorage
|
||||
public net.minecraft.world.lighting.WorldLightManager field_215576_a # blockEngine
|
||||
public net.minecraft.world.lighting.WorldLightManager field_215577_b # skyEngine
|
||||
public net.minecraft.world.gen.feature.Feature field_236290_a_ # configuredCodec
|
||||
|
||||
# used for uploading vertex buffers off the render thread
|
||||
public net.minecraft.client.renderer.vertex.VertexBuffer field_177365_a # id
|
||||
public net.minecraft.client.renderer.vertex.VertexBuffer field_177363_b # format
|
||||
public net.minecraft.client.renderer.vertex.VertexBuffer field_177364_c # vertexCount
|
||||
|
||||
# used for accessing the lightmap
|
||||
public net.minecraft.client.renderer.LightTexture field_205111_b # lightPixels
|
||||
|
||||
|
||||
#=====================#
|
||||
# Examples from Forge #
|
||||
#=====================#
|
||||
|
||||
# Makes public the IScreenFactory class in ScreenManager
|
||||
public net.minecraft.client.gui.ScreenManager$IScreenFactory
|
||||
|
||||
# Makes protected and removes the final modifier from 'random' in MinecraftServer
|
||||
protected-f net.minecraft.server.MinecraftServer field_147146_q #random
|
||||
|
||||
# Makes public the 'createNamedService' method in Util,
|
||||
# accepting a String and returns an ExecutorService
|
||||
public net.minecraft.util.Util func_240979_a_(Ljava/lang/String;)Ljava/util/concurrent/ExecutorService; #createNamedService
|
||||
|
||||
# Makes public the 'func_239776_a_' method in UUIDCodec,
|
||||
# accepting two longs and returning an int[]
|
||||
public net.minecraft.util.UUIDCodec func_239776_a_(JJ)[I #func_239776_a_
|
||||
@@ -1,51 +0,0 @@
|
||||
#// This is an example mods.toml file. It contains the data relating to the loading mods.
|
||||
#// There are several mandatory fields (#mandatory), and many more that are optional (#optional).
|
||||
#// The overall format is standard TOML format, v0.5.0.
|
||||
#// Note that there are a couple of TOML lists in this file.
|
||||
#// Find more information on toml format here: https://github.com/toml-lang/toml
|
||||
#// The name of the mod loader type to load - for regular FML @Mod mods it should be javafml
|
||||
modLoader="javafml" #mandatory
|
||||
|
||||
#// A version range to match for said mod loader - for regular FML @Mod it will be the forge version
|
||||
loaderVersion="[36,)" #mandatory This is typically bumped every Minecraft version by Forge. See our download page for lists of versions.
|
||||
|
||||
#// The license for you mod. This is mandatory metadata and allows for easier comprehension of your redistributive properties.
|
||||
#// Review your options at https://choosealicense.com/. All rights reserved is the default copyright stance, and is thus the default here.
|
||||
license="GNU GPLv3"
|
||||
|
||||
#// A URL to refer people to when problems occur with this mod
|
||||
issueTrackerURL="https://gitlab.com/jeseibel/minecraft-lod-mod/-/issues" #optional
|
||||
#// A list of mods - how many allowed here is determined by the individual mod loader
|
||||
[[mods]] #mandatory
|
||||
|
||||
#// The modid of the mod
|
||||
modId="lod" #mandatory
|
||||
|
||||
#// The version number of the mod - there's a few well known ${} variables useable here or just hardcode it
|
||||
#//${file.jarVersion} will substitute the value of the Implementation-Version as read from the mod's JAR file metadata
|
||||
#// see the associated build.gradle script for how to populate this completely automatically during a build
|
||||
version="a1.5.3" #mandatory
|
||||
|
||||
#// A display name for the mod
|
||||
displayName="Distant Horizons" #mandatory
|
||||
|
||||
#// A URL to query for updates for this mod. See the JSON update specification https://mcforge.readthedocs.io/en/latest/gettingstarted/autoupdate/
|
||||
#//updateJSONURL="https://change.me.example.invalid/updates.json" #optional
|
||||
|
||||
#// A URL for the "homepage" for this mod, displayed in the mod UI
|
||||
displayURL="https://www.curseforge.com/minecraft/mc-mods/lod-level-of-detail" #optional
|
||||
|
||||
#// A file name (in the root of the mod JAR) containing a logo for display
|
||||
logoFile="logo.png" #optional
|
||||
|
||||
#// A file name (in the root of the mod JAR) containing a icon for display by catalogue
|
||||
catalogueImageIcon="icon.png"
|
||||
|
||||
#// A text field displayed in the mod UI
|
||||
credits="TechnoVision, Vike, and Darkhax for their modding tutorials." #optional
|
||||
|
||||
#// A text field displayed in the mod UI
|
||||
authors="James Seibel, Leonardo Amato, and Cola" #optional
|
||||
|
||||
#// The description text for the mod (multi line!) (#mandatory)
|
||||
description='''This mod generates and renders simplified terrain beyond the normal view distance, at a low performance cost.'''
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 11 KiB |
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user