Compare commits
131 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 865923b0dc | |||
| b9b023691a | |||
| 5c7dfc5905 | |||
| b70fc86516 | |||
| 9c3ecc6deb | |||
| d688a53d74 | |||
| 2cf4b42c5c | |||
| c726a49c82 | |||
| 0b0a69aabe | |||
| 96ac022cbf | |||
| fa325b2eb8 | |||
| c87233eb10 | |||
| 88497593c4 | |||
| 9817dcf022 | |||
| 898eda7355 | |||
| 7363231361 | |||
| 40fbca33f4 | |||
| 62712cfab4 | |||
| 8d94988be1 | |||
| 99ce73feee | |||
| b7e3db12d9 | |||
| e0a7010abf | |||
| f1b8616329 | |||
| b6a84a454b | |||
| b8aabc59cd | |||
| 66f169bd78 | |||
| e038861b7a | |||
| c41fd1ab5b | |||
| a12a55a953 | |||
| 42068fc152 | |||
| 791d2c881a | |||
| 9fff802baf | |||
| d5c0f714fa | |||
| 09914af897 | |||
| 7dd57345a4 | |||
| aff52ce926 | |||
| 98ed33e2bf | |||
| d4f4e7e24d | |||
| cfc5f4cede | |||
| e3611b00e1 | |||
| 8f6fb9cecc | |||
| ba3f1fd0d0 | |||
| 932f3ca19a | |||
| 7eb4339a1b | |||
| 21fd19d8d8 | |||
| cfbca82905 | |||
| 11989b310e | |||
| c75f50a29a | |||
| 3a0deb5111 | |||
| c2462846db | |||
| 66c183ba4f | |||
| 3966c668d9 | |||
| d1cc7740d3 | |||
| 9586cfe90d | |||
| 5a8194fc0d | |||
| 15a7678da2 | |||
| 59f7a8571f | |||
| e878954763 | |||
| a07282dd36 | |||
| df5923ea8e | |||
| 19350cc5d4 | |||
| 1fd639a3f7 | |||
| 69efd93ec3 | |||
| c7575887ea | |||
| 7902d483ec | |||
| 2bd74d379c | |||
| 1db8d3599b | |||
| e80ccd38fe | |||
| 12b7723017 | |||
| 51341f14a3 | |||
| f07783deb1 | |||
| c7e41973d3 | |||
| f90276d8a1 | |||
| 384fe016cd | |||
| 06301a42d6 | |||
| b13626689b | |||
| ae820320de | |||
| 4da96d094e | |||
| d8196c2069 | |||
| c5e0f35a63 | |||
| 8a76887386 | |||
| 2d495b981f | |||
| 95b5d94596 | |||
| b4de7cbd0b | |||
| 27b4cde1dc | |||
| ed2b28aa30 | |||
| b43a29a98d | |||
| 3c3474e66b | |||
| 2aee802ca2 | |||
| 5cd338392c | |||
| fff510f315 | |||
| fbf418e31d | |||
| e0ac46290c | |||
| 77c21785d1 | |||
| 5bcb1fdca3 | |||
| 1e6167204a | |||
| 8c64a33537 | |||
| f3188bfa1f | |||
| efdceddd7b | |||
| be0255ed9e | |||
| a2abf0e210 | |||
| ed41a7e449 | |||
| 56e74a15ba | |||
| e7f9c01292 | |||
| ca997b8341 | |||
| 3bc6caba26 | |||
| a533ffc4c9 | |||
| 1c9c091a21 | |||
| b334a173f9 | |||
| 60c56d5507 | |||
| ce51dbfc3a | |||
| ccdf57eb3f | |||
| 15f0325343 | |||
| 157a21568c | |||
| c02abcb4ba | |||
| 55f636b2d5 | |||
| 580d17bb24 | |||
| f2dd9d7264 | |||
| 1a22f00c01 | |||
| 5c44967174 | |||
| 88b967780e | |||
| 5650a85c70 | |||
| cf03cb4576 | |||
| 6334c58fa6 | |||
| 297f53beaf | |||
| 34256540f0 | |||
| 2c2a9e05c9 | |||
| 69b2b1725b | |||
| 5dec52e493 | |||
| 56faf3fdb6 | |||
| d2a9edfd2c |
+11
-32
@@ -3,8 +3,7 @@ image: gradle:eclipse-temurin
|
||||
|
||||
# all stages need to be defined here
|
||||
stages:
|
||||
- build_18_1
|
||||
- build_18_2
|
||||
- build_17_1
|
||||
|
||||
variables:
|
||||
# Pull core when building
|
||||
@@ -17,39 +16,19 @@ before_script:
|
||||
- echo GE_JOB_ID=$CI_JOB_ID >> generate_jars.env
|
||||
|
||||
|
||||
# 1.18.1 build
|
||||
build_18_1:
|
||||
stage: build_18_1
|
||||
script:
|
||||
- ./gradlew deleteMerged --gradle-user-home cache/; # make sure any previously merged jars are removed before running this job
|
||||
- ./gradlew build -PmcVer=1.18.1 --gradle-user-home cache/;
|
||||
- ./gradlew merge --gradle-user-home cache/;
|
||||
# build using Java 17
|
||||
image: eclipse-temurin:17
|
||||
artifacts:
|
||||
name: "Merged_NightlyBuild_1_18_1-${CI_COMMIT_SHORT_SHA}-${CI_COMMIT_TIMESTAMP}"
|
||||
paths:
|
||||
# relative to the root directory
|
||||
- Merged
|
||||
expire_in: 1 day
|
||||
cache:
|
||||
key: "gradleCache"
|
||||
policy: pull-push
|
||||
paths:
|
||||
- .gradle
|
||||
- cache/
|
||||
|
||||
# 1.18.2 build
|
||||
build_18_2:
|
||||
stage: build_18_2
|
||||
# 1.17.1 build
|
||||
build_17_1:
|
||||
stage: build_17_1
|
||||
script:
|
||||
- ./gradlew deleteMerged --gradle-user-home cache/;
|
||||
- ./gradlew build -PmcVer=1.18.2 --gradle-user-home cache/;
|
||||
- ./gradlew deleteMerged --gradle-user-home cache/; # make sure any previously merged jars are removed before running this job
|
||||
- ./gradlew build -PmcVer=1.17.1 --gradle-user-home cache/;
|
||||
- ./gradlew merge --gradle-user-home cache/;
|
||||
image: eclipse-temurin:17
|
||||
# build using Java 16
|
||||
image: eclipse-temurin:16
|
||||
artifacts:
|
||||
name: "Merged_NightlyBuild_1_18_2-${CI_COMMIT_SHORT_SHA}-${CI_COMMIT_TIMESTAMP}"
|
||||
name: "Merged_NightlyBuild_1_17_1-${CI_COMMIT_SHORT_SHA}-${CI_COMMIT_TIMESTAMP}"
|
||||
paths:
|
||||
# relative to the root directory
|
||||
- Merged
|
||||
expire_in: 1 day
|
||||
cache:
|
||||
@@ -82,5 +61,5 @@ build_18_2:
|
||||
# - name: 'Fabric Jars'
|
||||
# url: 'https://gitlab.com/jeseibel/minecraft-lod-mod/cw/-/jobs/${GE_JOB_ID}/artifacts/file/fabric/build/libs'
|
||||
# - name: 'Forge Jars'
|
||||
# url: 'https://gitlab.com/jeseibel/minecraft-lod-mod/cw/-/jobs/${GE_JOB_ID}/artifacts/file/forge/build/libs'
|
||||
# url: 'https://gitlab.com/jeseibel/minecraft-lod-mod/cw/-/jobs/${GE_JOB_ID}/artifacts/file/forge/build/libs'
|
||||
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
[submodule "core"]
|
||||
path = core
|
||||
url = https://gitlab.com/jeseibel/distant-horizons-core.git
|
||||
branch = main
|
||||
branch = main
|
||||
@@ -0,0 +1,36 @@
|
||||
org.gradle.jvmargs=-Xmx2048M
|
||||
|
||||
minecraft_version=1.17.1
|
||||
java_version=16
|
||||
|
||||
# Fabric loader
|
||||
fabric_loader_version=0.13.2
|
||||
fabric_api_version=0.46.1+1.17
|
||||
# Fabric mod versions
|
||||
modmenu_version=2.0.14
|
||||
starlight_version_fabric=3442770
|
||||
lithium_version=mc1.17.1-0.7.5
|
||||
sodium_version=3605275
|
||||
iris_version=1.17.x-v1.1.4
|
||||
immersive_portals_version = 0.14-1.17
|
||||
|
||||
# Fabric mod run
|
||||
# 0 = Dont enable and dont run
|
||||
# 1 = Can be refranced in code but dosnt run
|
||||
# 2 = Can be refranced in code and runs in client
|
||||
enable_starlight=0
|
||||
enable_lithium=0
|
||||
enable_sodium=1
|
||||
enable_iris=0
|
||||
|
||||
|
||||
# Forge loader
|
||||
forge_version=37.1.1
|
||||
# Forge mod versions
|
||||
starlight_version_forge=3457784
|
||||
|
||||
# Forge mod run
|
||||
# 0 = Dont enable and dont run
|
||||
# 1 = Can be refranced in code but dosnt run
|
||||
# 2 = Can be refranced in code and runs in client
|
||||
enable_starlight_forge=0
|
||||
@@ -1,39 +0,0 @@
|
||||
# 1.18.1 version based stuff
|
||||
|
||||
minecraft_version=1.18.1
|
||||
java_version = 17
|
||||
|
||||
# Fabric loader
|
||||
fabric_loader_version=0.13.3
|
||||
fabric_api_version=0.46.6+1.18
|
||||
# Fabric mod versions
|
||||
modmenu_version=3.0.1
|
||||
starlight_version_fabric=3554912
|
||||
phosphor_version_fabric=3573395
|
||||
lithium_version=mc1.18.1-0.7.7
|
||||
sodium_version=3605309
|
||||
iris_version=1.18.x-v1.1.4
|
||||
bclib_version=1.2.5
|
||||
immersive_portals_version = v1.0.4-1.18
|
||||
|
||||
# Fabric mod run
|
||||
# 0 = Don't enable and don't run
|
||||
# 1 = Can be referenced in code but doesn't run
|
||||
# 2 = Can be referenced in code and runs in client
|
||||
enable_starlight=0
|
||||
enable_phosphor=0
|
||||
enable_sodium=1
|
||||
enable_lithium=0
|
||||
enable_iris=0
|
||||
enable_bclib=0
|
||||
|
||||
# Forge loader
|
||||
forge_version=39.1.2
|
||||
# Forge mod versions
|
||||
starlight_version_forge=3559934
|
||||
|
||||
# Forge mod run
|
||||
# 0 = Dont enable and don't run
|
||||
# 1 = Can be referenced in code but doesn't run
|
||||
# 2 = Can be referenced in code and runs in client
|
||||
enable_starlight_forge=0
|
||||
@@ -1,40 +0,0 @@
|
||||
# 1.18.2 version based stuff
|
||||
# architectury_plugin_version = 3.4-SNAPSHOT
|
||||
# dev_architectury_loom_version = 0.10.0-SNAPSHOT
|
||||
minecraft_version=1.18.2
|
||||
java_version = 17
|
||||
|
||||
# Fabric loader
|
||||
fabric_loader_version=0.13.3
|
||||
fabric_api_version=0.48.0+1.18.2
|
||||
# Fabric mod versions
|
||||
modmenu_version=3.1.0
|
||||
starlight_version_fabric=3667443
|
||||
phosphor_version_fabric=3573395
|
||||
lithium_version=mc1.18.2-0.7.9
|
||||
sodium_version=3669187
|
||||
iris_version=1.18.x-v1.2.2
|
||||
immersive_portals_version = v1.0.4-1.18
|
||||
bclib_version=0
|
||||
|
||||
# Fabric mod run
|
||||
# 0 = Don't enable and don't run
|
||||
# 1 = Can be referenced in code but doesn't run
|
||||
# 2 = Can be referenced in code and runs in client
|
||||
enable_starlight=0
|
||||
enable_phosphor=0
|
||||
enable_sodium=1
|
||||
enable_lithium=0
|
||||
enable_iris=0
|
||||
enable_bclib=0
|
||||
|
||||
# Forge loader
|
||||
forge_version=40.0.18
|
||||
# Forge mod versions
|
||||
starlight_version_forge=0
|
||||
|
||||
# Forge mod run
|
||||
# 0 = Don't enable and don't run
|
||||
# 1 = Can be referenced in code but doesn't run
|
||||
# 2 = Can be referenced in code and runs in client
|
||||
enable_starlight_forge=0
|
||||
@@ -21,22 +21,11 @@ If you want to see a quick demo, check out a video covering the mod here:
|
||||
Architectury version: 3.4-SNAPSHOT\
|
||||
Java Compiler plugin: Manifold Preprocessor
|
||||
|
||||
#### 1.18.2 mods
|
||||
Forge version: 40.0.18\
|
||||
Fabric version: 0.13.3\
|
||||
Fabric API version: 0.48.0+1.18.2\
|
||||
Modmenu version: 3.1.0
|
||||
|
||||
#### 1.18.1 mods
|
||||
Forge version: 39.1.2\
|
||||
Fabric version: 0.13.3\
|
||||
Fabric API version: 0.46.6+1.18\
|
||||
Modmenu version: 3.0.1
|
||||
|
||||
|
||||
Notes:\
|
||||
This version has been confirmed to work in IDE and Retail Minecraft.\
|
||||
(Retail running forge version 1.18.1-39.0.5 and fabric version 1.18-0.12.12 and 1.18.1-0.13.2)
|
||||
#### 1.17.1 mods
|
||||
Forge version: 37.1.1\
|
||||
Fabric version: 0.13.2\
|
||||
Fabric API version: 0.46.1+1.17\
|
||||
Modmenu version: 2.0.14
|
||||
|
||||
|
||||
## Source Code Installation
|
||||
@@ -62,15 +51,14 @@ https://fabricmc.net/wiki/tutorial:setup
|
||||
4. Import the project into eclipse
|
||||
|
||||
## Switching Versions
|
||||
This branch support 2 built versions:
|
||||
- 1.18.2
|
||||
- 1.18.1 (which also runs on 1.18)
|
||||
This branch support 1 built versions:
|
||||
- 1.17.1 (which also runs on 1.17)
|
||||
|
||||
To switch between active versions, change `mcVer=1.18.?` in `gradle.properties` file.
|
||||
To switch between active versions, change `mcVer=1.17.?` in `gradle.properties` file.
|
||||
|
||||
If running on IDE, to ensure IDE pickup the changed versions, you will need to run a gradle command again to allow gradle to update all the libs. (In IntellJ you will also need to do a gradle sync again if it didn't start it automatically.)
|
||||
>Note: There may be a `java.nio.file.FileSystemException` thrown on running the command after switching versions. To fix it, either restart your IDE (as your IDE is locking up a file) or use tools like LockHunter to unlock the linked file. (Often a lib file under `common\build\lib` or `forge\build\lib` or `fabric\build\lib`). If anyone knows how to solve this issue please comment to this issue: https://gitlab.com/jeseibel/minecraft-lod-mod/-/issues/233
|
||||
|
||||
|
||||
## Compiling
|
||||
|
||||
**Using GUI**
|
||||
@@ -82,12 +70,12 @@ If running on IDE, to ensure IDE pickup the changed versions, you will need to r
|
||||
6. The compiled jar file will be in the folder `Merged`
|
||||
|
||||
**If in terminal:**
|
||||
1. `git clone -b 1.18.X --recurse-submodules https://gitlab.com/jeseibel/minecraft-lod-mod.git`
|
||||
1. `git clone -b preprocessor_test --recurse-submodules https://gitlab.com/jeseibel/minecraft-lod-mod.git`
|
||||
2. `cd minecraft-lod-mod`
|
||||
3. `./gradlew assemble`
|
||||
4. `./gradlew mergeJars`
|
||||
5. The compiled jar file will be in the folder `Merged`
|
||||
>Note: You can add the arg: `-PmcVer=1.18.?` to tell gradle to build a selected MC version instead of having to manually modify the `gradle.properties` file.
|
||||
>Note: You can add the arg: `-PmcVer=1.17.?` to tell gradle to build a selected MC version instead of having to manually modify the `gradle.properties` file.
|
||||
|
||||
|
||||
## Other commands
|
||||
|
||||
+36
-52
@@ -9,7 +9,7 @@ buildscript {
|
||||
|
||||
plugins {
|
||||
id "architectury-plugin" version "3.4-SNAPSHOT"
|
||||
id "dev.architectury.loom" version "0.10.0-SNAPSHOT" apply false
|
||||
id "dev.architectury.loom" version "0.10.0.195" apply false
|
||||
}
|
||||
|
||||
def writeBuildGradlePredefine() {
|
||||
@@ -18,20 +18,20 @@ def writeBuildGradlePredefine() {
|
||||
}
|
||||
|
||||
def loadProperties() {
|
||||
def defaultMcVersion = '1.18.2'
|
||||
def defaultMcVersion = '1.17.1'
|
||||
if (!project.hasProperty("mcVer")) {
|
||||
println "No mcVer set! Defaulting to ${defaultMcVersion}."
|
||||
println "Tip: Use -PmcVer='${defaultMcVersion}' in cmd arg to set mcVer."
|
||||
}
|
||||
def mcVersion = project.hasProperty("mcVer") ? mcVer : defaultMcVersion
|
||||
def mcVersion = project.hasProperty("mcVer") ? mcVer : defaultMcVersion
|
||||
|
||||
println "Loading properties file at " + mcVersion + ".properties"
|
||||
def props = new Properties()
|
||||
props.load(new FileInputStream("$rootProject.rootDir/"+"$mcVersion"+".properties"))
|
||||
|
||||
println "Loading properties file at " + mcVersion + ".properties"
|
||||
def props = new Properties()
|
||||
props.load(new FileInputStream("$rootProject.rootDir/"+"$mcVersion"+".properties"))
|
||||
|
||||
props.each { prop ->
|
||||
rootProject.ext.set(prop.key, prop.value)
|
||||
// println "Added prop [key:" + prop.key + ", value:" + prop.value + "]"
|
||||
rootProject.ext.set(prop.key, prop.value)
|
||||
// println "Added prop [key:" + prop.key + ", value:" + prop.value + "]"
|
||||
}
|
||||
writeBuildGradlePredefine()
|
||||
}
|
||||
@@ -60,9 +60,9 @@ subprojects { p ->
|
||||
minecraft "com.mojang:minecraft:${rootProject.minecraft_version}"
|
||||
// The following line declares the mojmap mappings
|
||||
mappings loom.officialMojangMappings()
|
||||
|
||||
//Manifold
|
||||
annotationProcessor "systems.manifold:manifold-preprocessor:${rootProject.manifold_version}"
|
||||
|
||||
//Manifold
|
||||
annotationProcessor "systems.manifold:manifold-preprocessor:${rootProject.manifold_version}"
|
||||
|
||||
// Toml
|
||||
implementation("com.electronwill.night-config:toml:${rootProject.toml_version}")
|
||||
@@ -73,6 +73,7 @@ subprojects { p ->
|
||||
modImplementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}"
|
||||
}
|
||||
|
||||
|
||||
if (p != project(":core")) {
|
||||
common(project(":core")) { transitive false }
|
||||
shadowMe(project(":core")) { transitive false }
|
||||
@@ -88,7 +89,7 @@ subprojects { p ->
|
||||
}
|
||||
}
|
||||
|
||||
allprojects { p ->
|
||||
allprojects {
|
||||
apply plugin: "java"
|
||||
apply plugin: "architectury-plugin"
|
||||
apply plugin: "maven-publish"
|
||||
@@ -101,9 +102,9 @@ allprojects { p ->
|
||||
mavenCentral()
|
||||
// used to download and compile dependencies from git repos
|
||||
maven { url 'https://jitpack.io' }
|
||||
|
||||
// For Manifold Preprocessor
|
||||
maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }
|
||||
|
||||
// For Manifold Preprocessor
|
||||
maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }
|
||||
|
||||
// Required for importing Modrinth mods
|
||||
maven {
|
||||
@@ -137,7 +138,6 @@ allprojects { p ->
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Put stuff from gradle.properties into the mod info
|
||||
processResources {
|
||||
def resourceTargets = ["fabric.mod.json", "META-INF/mods.toml"] // Location of where to put
|
||||
@@ -174,52 +174,36 @@ allprojects { p ->
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
tasks.withType(JavaCompile) {
|
||||
// Add Manifold Preprocessor
|
||||
// def excapedMCVersion = rootProject.minecraft_version.replace(".", "_")
|
||||
// options.compilerArgs += ['-Xplugin:Manifold', "-AMC_VERSION_${excapedMCVersion}"]
|
||||
// // Add Manifold Preprocessor
|
||||
//// def excapedMCVersion = rootProject.minecraft_version.replace(".", "_")
|
||||
//// options.compilerArgs += ['-Xplugin:Manifold', "-AMC_VERSION_${excapedMCVersion}"]
|
||||
////
|
||||
// //options.compilerArgs += ['-deprecation']
|
||||
// //options.compilerArgs += ['-verbose']
|
||||
// //options.compilerArgs += ['-Xlint:unchecked']
|
||||
// //options.compilerArgs += ['-Xdiags:verbose']
|
||||
// //options.compilerArgs += ['-Xprint']
|
||||
// //options.compilerArgs += ['-XprintProcessorInfo']
|
||||
// //options.compilerArgs += ['-XprintRounds']
|
||||
//
|
||||
//options.compilerArgs += ['-deprecation']
|
||||
//options.compilerArgs += ['-verbose']
|
||||
//options.compilerArgs += ['-Xlint:unchecked']
|
||||
//options.compilerArgs += ['-Xdiags:verbose']
|
||||
//options.compilerArgs += ['-Xprint']
|
||||
//options.compilerArgs += ['-XprintProcessorInfo']
|
||||
//options.compilerArgs += ['-XprintRounds']
|
||||
|
||||
// println options.compilerArgs
|
||||
if (p != project(":core")) {
|
||||
options.compilerArgs += ['-Xplugin:Manifold']
|
||||
options.release = rootProject.java_version as Integer
|
||||
}
|
||||
// // println options.compilerArgs
|
||||
// if (p != project(":core")) {
|
||||
// options.compilerArgs += ['-Xplugin:Manifold']
|
||||
// options.release = rootProject.java_version as Integer
|
||||
// }
|
||||
options.encoding = "UTF-8"
|
||||
options.release = 16
|
||||
}
|
||||
|
||||
java {
|
||||
withSourcesJar()
|
||||
}
|
||||
|
||||
if (p == project(":core") || p == project(":common")) {
|
||||
runClient.enabled = false
|
||||
runServer.enabled = false
|
||||
}
|
||||
|
||||
|
||||
// this is necessary for running the fabric build
|
||||
if (p == project(":common")) {
|
||||
println "Coping [common/src/main/resources/lod.accesswidner] to [fabric/build/resources/main]."
|
||||
|
||||
copy {
|
||||
from "$rootProject.rootDir/common/src/main/resources"
|
||||
into "$rootProject.rootDir/fabric/build/resources/main"
|
||||
include "*.accesswidener"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// this deletes the merged folder so we don't carry over
|
||||
// the previous merges to each new build job in the CI/CD pipeline
|
||||
task deleteMerged(type: Delete) {
|
||||
delete files("./Merged")
|
||||
delete files("./Merged")
|
||||
}
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
package com.seibel.lod.common;
|
||||
|
||||
import com.seibel.lod.common.wrappers.config.ConfigGui;
|
||||
import com.seibel.lod.core.config.*;
|
||||
import com.seibel.lod.core.enums.config.*;
|
||||
import com.seibel.lod.core.enums.rendering.*;
|
||||
@@ -32,14 +33,12 @@ import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton.I
|
||||
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton.IClient.IAdvanced;
|
||||
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton.IClient.IAdvanced.IDebugging.*;
|
||||
|
||||
|
||||
/**
|
||||
* This handles any configuration the user has access to.
|
||||
* @author coolGi2007
|
||||
* @version 12-12-2021
|
||||
*/
|
||||
|
||||
public class Config
|
||||
public class Config extends ConfigGui
|
||||
//public class Config extends TinyConfig
|
||||
{
|
||||
// CONFIG STRUCTURE
|
||||
@@ -56,12 +55,12 @@ public class Config
|
||||
// |-> Threads
|
||||
// |-> Buffers
|
||||
// |-> Debugging
|
||||
|
||||
|
||||
// Since the original config system uses forge stuff, that means we have to rewrite the whole config system
|
||||
|
||||
|
||||
@ConfigAnnotations.ScreenEntry
|
||||
public static Client client;
|
||||
|
||||
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _optionsButton = ILodConfigWrapperSingleton.IClient.OPTIONS_BUTTON_DESC;
|
||||
// I know this option should be in Client
|
||||
@@ -69,61 +68,58 @@ public class Config
|
||||
// Tough it is in client in the wrapper singleton
|
||||
@ConfigAnnotations.Entry
|
||||
public static boolean optionsButton = true;
|
||||
|
||||
public static class Client
|
||||
{
|
||||
|
||||
public static class Client {
|
||||
@ConfigAnnotations.ScreenEntry
|
||||
public static Graphics graphics;
|
||||
|
||||
|
||||
@ConfigAnnotations.ScreenEntry
|
||||
public static WorldGenerator worldGenerator;
|
||||
|
||||
|
||||
@ConfigAnnotations.ScreenEntry
|
||||
public static Multiplayer multiplayer;
|
||||
|
||||
|
||||
@ConfigAnnotations.ScreenEntry
|
||||
public static Advanced advanced;
|
||||
|
||||
|
||||
public static class Graphics
|
||||
{
|
||||
|
||||
|
||||
public static class Graphics {
|
||||
@ConfigAnnotations.ScreenEntry
|
||||
public static Quality quality;
|
||||
|
||||
|
||||
@ConfigAnnotations.ScreenEntry
|
||||
public static FogQuality fogQuality;
|
||||
|
||||
|
||||
@ConfigAnnotations.ScreenEntry
|
||||
public static AdvancedGraphics advancedGraphics;
|
||||
|
||||
|
||||
public static class Quality
|
||||
{
|
||||
|
||||
|
||||
public static class Quality {
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _drawResolution = IQuality.DRAW_RESOLUTION_DESC;
|
||||
@ConfigAnnotations.Entry
|
||||
public static HorizontalResolution drawResolution = IQuality.DRAW_RESOLUTION_DEFAULT;
|
||||
|
||||
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _lodChunkRenderDistance = IQuality.LOD_CHUNK_RENDER_DISTANCE_DESC;
|
||||
@ConfigAnnotations.Entry(minValue = 16, maxValue = 2048)
|
||||
public static int lodChunkRenderDistance = IQuality.LOD_CHUNK_RENDER_DISTANCE_MIN_DEFAULT_MAX.defaultValue;
|
||||
|
||||
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _verticalQuality = IQuality.VERTICAL_QUALITY_DESC;
|
||||
@ConfigAnnotations.Entry
|
||||
public static VerticalQuality verticalQuality = IQuality.VERTICAL_QUALITY_DEFAULT;
|
||||
|
||||
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _horizontalScale = IQuality.HORIZONTAL_SCALE_DESC;
|
||||
@ConfigAnnotations.Entry(minValue = 2, maxValue = 32)
|
||||
public static int horizontalScale = IQuality.HORIZONTAL_SCALE_MIN_DEFAULT_MAX.defaultValue;
|
||||
|
||||
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _horizontalQuality = IQuality.HORIZONTAL_SCALE_DESC;
|
||||
@ConfigAnnotations.Entry
|
||||
public static HorizontalQuality horizontalQuality = IQuality.HORIZONTAL_QUALITY_DEFAULT;
|
||||
|
||||
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _dropoffQuality = IQuality.DROPOFF_QUALITY_DESC;
|
||||
@ConfigAnnotations.Entry
|
||||
@@ -134,71 +130,70 @@ public class Config
|
||||
@ConfigAnnotations.Entry(minValue = 0, maxValue = 7)
|
||||
public static int lodBiomeBlending = IQuality.LOD_BIOME_BLENDING_MIN_DEFAULT_MAX.defaultValue;
|
||||
}
|
||||
|
||||
|
||||
public static class FogQuality
|
||||
{
|
||||
|
||||
|
||||
public static class FogQuality {
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _fogDistance = IFogQuality.FOG_DISTANCE_DESC;
|
||||
@ConfigAnnotations.Entry
|
||||
public static FogDistance fogDistance = IFogQuality.FOG_DISTANCE_DEFAULT;
|
||||
|
||||
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _fogDrawMode = IFogQuality.FOG_DRAW_MODE_DESC;
|
||||
@ConfigAnnotations.Entry
|
||||
public static FogDrawMode fogDrawMode = IFogQuality.FOG_DRAW_MODE_DEFAULT;
|
||||
|
||||
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _fogColorMode = IFogQuality.FOG_COLOR_MODE_DESC;
|
||||
@ConfigAnnotations.Entry
|
||||
public static FogColorMode fogColorMode = IFogQuality.FOG_COLOR_MODE_DEFAULT;
|
||||
|
||||
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _disableVanillaFog = IFogQuality.DISABLE_VANILLA_FOG_DESC;
|
||||
@ConfigAnnotations.Entry
|
||||
public static boolean disableVanillaFog = IFogQuality.DISABLE_VANILLA_FOG_DEFAULT;
|
||||
|
||||
|
||||
@ConfigAnnotations.ScreenEntry
|
||||
public static AdvancedFog advancedFog;
|
||||
|
||||
|
||||
public static class AdvancedFog {
|
||||
static final double SQRT2 = 1.4142135623730951;
|
||||
|
||||
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _farFogStart = IAdvancedFog.FAR_FOG_START_DESC;
|
||||
@ConfigAnnotations.Entry(minValue = 0.0, maxValue = SQRT2)
|
||||
public static double farFogStart = IAdvancedFog.FAR_FOG_START_MIN_DEFAULT_MAX.defaultValue;
|
||||
|
||||
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _farFogEnd = IAdvancedFog.FAR_FOG_END_DESC;
|
||||
@ConfigAnnotations.Entry(minValue = 0.0, maxValue = SQRT2)
|
||||
public static double farFogEnd = IAdvancedFog.FAR_FOG_END_MIN_DEFAULT_MAX.defaultValue;
|
||||
|
||||
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _farFogMin = IAdvancedFog.FAR_FOG_MIN_DESC;
|
||||
@ConfigAnnotations.Entry(minValue = -5.0, maxValue = SQRT2)
|
||||
public static double farFogMin = IAdvancedFog.FAR_FOG_MIN_MIN_DEFAULT_MAX.defaultValue;
|
||||
|
||||
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _farFogMax = IAdvancedFog.FAR_FOG_MAX_DESC;
|
||||
@ConfigAnnotations.Entry(minValue = 0.0, maxValue = 5.0)
|
||||
public static double farFogMax = IAdvancedFog.FAR_FOG_MAX_MIN_DEFAULT_MAX.defaultValue;
|
||||
|
||||
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _farFogType = IAdvancedFog.FAR_FOG_TYPE_DESC;
|
||||
@ConfigAnnotations.Entry
|
||||
public static FogSetting.FogType farFogType = IAdvancedFog.FAR_FOG_TYPE_DEFAULT;
|
||||
|
||||
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _farFogDensity = IAdvancedFog.FAR_FOG_DENSITY_DESC;
|
||||
@ConfigAnnotations.Entry(minValue = 0.01, maxValue = 50.0)
|
||||
public static double farFogDensity = IAdvancedFog.FAR_FOG_DENSITY_MIN_DEFAULT_MAX.defaultValue;
|
||||
|
||||
|
||||
@ConfigAnnotations.ScreenEntry
|
||||
public static HeightFog heightFog;
|
||||
|
||||
|
||||
public static class HeightFog {
|
||||
|
||||
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _heightFogMixMode = IHeightFog.HEIGHT_FOG_MIX_MODE_DESC;
|
||||
@ConfigAnnotations.Entry
|
||||
@@ -207,54 +202,52 @@ public class Config
|
||||
public static String _heightFogMode = IHeightFog.HEIGHT_FOG_MODE_DESC;
|
||||
@ConfigAnnotations.Entry
|
||||
public static HeightFogMode heightFogMode = IHeightFog.HEIGHT_FOG_MODE_DEFAULT;
|
||||
|
||||
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _heightFogHeight = IHeightFog.HEIGHT_FOG_HEIGHT_DESC;
|
||||
@ConfigAnnotations.Entry(minValue = -4096.0, maxValue = 4096.0)
|
||||
public static double heightFogHeight = IHeightFog.HEIGHT_FOG_HEIGHT_MIN_DEFAULT_MAX.defaultValue;
|
||||
|
||||
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _heightFogStart = IHeightFog.HEIGHT_FOG_START_DESC;
|
||||
@ConfigAnnotations.Entry(minValue = 0.0, maxValue = SQRT2)
|
||||
public static double heightFogStart = IHeightFog.HEIGHT_FOG_START_MIN_DEFAULT_MAX.defaultValue;
|
||||
|
||||
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _heightFogEnd = IHeightFog.HEIGHT_FOG_END_DESC;
|
||||
@ConfigAnnotations.Entry(minValue = 0.0, maxValue = SQRT2)
|
||||
public static double heightFogEnd = IHeightFog.HEIGHT_FOG_END_MIN_DEFAULT_MAX.defaultValue;
|
||||
|
||||
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _heightFogMin = IHeightFog.HEIGHT_FOG_MIN_DESC;
|
||||
@ConfigAnnotations.Entry(minValue = -5.0, maxValue = SQRT2)
|
||||
public static double heightFogMin = IHeightFog.HEIGHT_FOG_MIN_MIN_DEFAULT_MAX.defaultValue;
|
||||
|
||||
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _heightFogMax = IHeightFog.HEIGHT_FOG_MAX_DESC;
|
||||
@ConfigAnnotations.Entry(minValue = 0.0, maxValue = 5.0)
|
||||
public static double heightFogMax = IHeightFog.HEIGHT_FOG_MAX_MIN_DEFAULT_MAX.defaultValue;
|
||||
|
||||
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _heightFogType = IHeightFog.HEIGHT_FOG_TYPE_DESC;
|
||||
@ConfigAnnotations.Entry
|
||||
public static FogSetting.FogType heightFogType = IHeightFog.HEIGHT_FOG_TYPE_DEFAULT;
|
||||
|
||||
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _heightFogDensity = IHeightFog.HEIGHT_FOG_DENSITY_DESC;
|
||||
@ConfigAnnotations.Entry(minValue = 0.01, maxValue = 50.0)
|
||||
public static double heightFogDensity = IHeightFog.HEIGHT_FOG_DENSITY_MIN_DEFAULT_MAX.defaultValue;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class AdvancedGraphics
|
||||
{
|
||||
|
||||
|
||||
public static class AdvancedGraphics {
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _disableDirectionalCulling = IAdvancedGraphics.DISABLE_DIRECTIONAL_CULLING_DESC;
|
||||
@ConfigAnnotations.Entry
|
||||
public static boolean disableDirectionalCulling = IAdvancedGraphics.DISABLE_DIRECTIONAL_CULLING_DEFAULT;
|
||||
|
||||
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _vanillaOverdraw = IAdvancedGraphics.VANILLA_OVERDRAW_DESC;
|
||||
@ConfigAnnotations.Entry
|
||||
@@ -269,12 +262,12 @@ public class Config
|
||||
public static String _useExtendedNearClipPlane = IAdvancedGraphics.USE_EXTENDED_NEAR_CLIP_PLANE_DESC;
|
||||
@ConfigAnnotations.Entry
|
||||
public static boolean useExtendedNearClipPlane = IAdvancedGraphics.USE_EXTENDED_NEAR_CLIP_PLANE_DEFAULT;
|
||||
|
||||
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _brightnessMultiplier = IAdvancedGraphics.BRIGHTNESS_MULTIPLIER_DESC;
|
||||
@ConfigAnnotations.Entry
|
||||
public static double brightnessMultiplier = IAdvancedGraphics.BRIGHTNESS_MULTIPLIER_DEFAULT;
|
||||
|
||||
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _saturationMultiplier = IAdvancedGraphics.SATURATION_MULTIPLIER_DESC;
|
||||
@ConfigAnnotations.Entry
|
||||
@@ -288,7 +281,7 @@ public class Config
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _caveCullingHeight = IAdvancedGraphics.CAVE_CULLING_HEIGHT_DESC;
|
||||
@ConfigAnnotations.Entry(minValue = -4096, maxValue = 4096)
|
||||
public static int caveCullingHeight = IAdvancedGraphics.CAVE_CULLING_HEIGHT_MIN_DEFAULT_MAX.defaultValue;
|
||||
public static int caveCullingHeight = IAdvancedGraphics.CAVE_CULLING_HEIGHT_MIN_DEFAULT_MAX.defaultValue;
|
||||
|
||||
/*
|
||||
@ConfigAnnotations.FileComment
|
||||
@@ -298,25 +291,24 @@ public class Config
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class WorldGenerator
|
||||
{
|
||||
|
||||
|
||||
public static class WorldGenerator {
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _enableDistantGeneration = IWorldGenerator.ENABLE_DISTANT_GENERATION_DESC;
|
||||
@ConfigAnnotations.Entry
|
||||
public static boolean enableDistantGeneration = IWorldGenerator.ENABLE_DISTANT_GENERATION_DEFAULT;
|
||||
|
||||
|
||||
// @ConfigAnnotations.FileComment
|
||||
// public static String _distanceGenerationMode = IWorldGenerator.getDistanceGenerationModeDesc();
|
||||
@ConfigAnnotations.Entry
|
||||
public static DistanceGenerationMode distanceGenerationMode = IWorldGenerator.DISTANCE_GENERATION_MODE_DEFAULT;
|
||||
|
||||
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _lightGenerationMode = IWorldGenerator.LIGHT_GENERATION_MODE_DESC;
|
||||
@ConfigAnnotations.Entry
|
||||
public static LightGenerationMode lightGenerationMode = IWorldGenerator.LIGHT_GENERATION_MODE_DEFAULT;
|
||||
|
||||
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _generationPriority = IWorldGenerator.GENERATION_PRIORITY_DESC;
|
||||
@ConfigAnnotations.Entry
|
||||
@@ -329,37 +321,34 @@ public class Config
|
||||
@ConfigAnnotations.Entry
|
||||
public static boolean allowUnstableFeatureGeneration = true;//IWorldGenerator.ALLOW_UNSTABLE_FEATURE_GENERATION_DEFAULT;
|
||||
*/
|
||||
|
||||
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _blocksToAvoid = IWorldGenerator.BLOCKS_TO_AVOID_DESC;
|
||||
@ConfigAnnotations.Entry
|
||||
public static BlocksToAvoid blocksToAvoid = IWorldGenerator.BLOCKS_TO_AVOID_DEFAULT;
|
||||
}
|
||||
|
||||
|
||||
public static class Multiplayer
|
||||
{
|
||||
|
||||
|
||||
public static class Multiplayer {
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _serverFolderNameMode = IMultiplayer.SERVER_FOLDER_NAME_MODE_DESC;
|
||||
@ConfigAnnotations.Entry
|
||||
public static ServerFolderNameMode serverFolderNameMode = IMultiplayer.SERVER_FOLDER_NAME_MODE_DEFAULT;
|
||||
|
||||
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _multiDimensionRequiredSimilarity = IMultiplayer.MULTI_DIMENSION_REQUIRED_SIMILARITY_DESC;
|
||||
@ConfigAnnotations.Entry(minValue = 0.0, maxValue = 1.0)
|
||||
public static double multiDimensionRequiredSimilarity = IMultiplayer.MULTI_DIMENSION_REQUIRED_SIMILARITY_MIN_DEFAULT_MAX.defaultValue;
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static class Advanced
|
||||
{
|
||||
|
||||
|
||||
public static class Advanced {
|
||||
@ConfigAnnotations.ScreenEntry
|
||||
public static Threading threading;
|
||||
|
||||
|
||||
@ConfigAnnotations.ScreenEntry
|
||||
public static Debugging debugging;
|
||||
|
||||
|
||||
@ConfigAnnotations.ScreenEntry
|
||||
public static Buffers buffers;
|
||||
|
||||
@@ -369,112 +358,110 @@ public class Config
|
||||
public static boolean lodOnlyMode = IAdvanced.LOD_ONLY_MODE_DEFAULT;
|
||||
|
||||
|
||||
public static class Threading
|
||||
{
|
||||
public static class Threading {
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _numberOfWorldGenerationThreads = IThreading.NUMBER_OF_WORLD_GENERATION_THREADS_DESC;
|
||||
@ConfigAnnotations.Entry(minValue = 1, maxValue = 50)
|
||||
public static int numberOfWorldGenerationThreads = IThreading.NUMBER_OF_WORLD_GENERATION_THREADS_DEFAULT.defaultValue;
|
||||
|
||||
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _numberOfBufferBuilderThreads = IThreading.NUMBER_OF_BUFFER_BUILDER_THREADS_DESC;
|
||||
@ConfigAnnotations.Entry(minValue = 1, maxValue = 50)
|
||||
public static int numberOfBufferBuilderThreads = IThreading.NUMBER_OF_BUFFER_BUILDER_THREADS_MIN_DEFAULT_MAX.defaultValue;
|
||||
}
|
||||
|
||||
|
||||
public static class Debugging
|
||||
{
|
||||
|
||||
|
||||
public static class Debugging {
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _rendererType = IDebugging.RENDERER_TYPE_DESC;
|
||||
@ConfigAnnotations.Entry
|
||||
public static RendererType rendererType = IDebugging.RENDERER_TYPE_DEFAULT;
|
||||
|
||||
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _debugMode = IDebugging.DEBUG_MODE_DESC;
|
||||
@ConfigAnnotations.Entry
|
||||
public static DebugMode debugMode = IDebugging.DEBUG_MODE_DEFAULT;
|
||||
|
||||
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _enableDebugKeybindings = IDebugging.DEBUG_KEYBINDINGS_ENABLED_DESC;
|
||||
@ConfigAnnotations.Entry
|
||||
public static boolean enableDebugKeybindings = IDebugging.DEBUG_KEYBINDINGS_ENABLED_DEFAULT;
|
||||
|
||||
@ConfigAnnotations.ScreenEntry
|
||||
public static DebugSwitch debugSwitch;
|
||||
|
||||
public static class DebugSwitch {
|
||||
/* The logging switches available:
|
||||
* WorldGenEvent
|
||||
* WorldGenPerformance
|
||||
* WorldGenLoadEvent
|
||||
* LodBuilderEvent
|
||||
* RendererBufferEvent
|
||||
* RendererGLEvent
|
||||
* FileReadWriteEvent
|
||||
* FileSubDimEvent
|
||||
* NetworkEvent //NOT IMPL YET
|
||||
*/
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _logWorldGenEvent = IDebugSwitch.LOG_WORLDGEN_EVENT_DESC;
|
||||
@ConfigAnnotations.Entry
|
||||
public static LoggerMode logWorldGenEvent = IDebugSwitch.LOG_WORLDGEN_EVENT_DEFAULT;
|
||||
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _logWorldGenPerformance = IDebugSwitch.LOG_WORLDGEN_PERFORMANCE_DESC;
|
||||
@ConfigAnnotations.Entry
|
||||
public static LoggerMode logWorldGenPerformance = IDebugSwitch.LOG_WORLDGEN_PERFORMANCE_DEFAULT;
|
||||
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _logWorldGenLoadEvent = IDebugSwitch.LOG_WORLDGEN_LOAD_EVENT_DESC;
|
||||
@ConfigAnnotations.Entry
|
||||
public static LoggerMode logWorldGenLoadEvent = IDebugSwitch.LOG_WORLDGEN_LOAD_EVENT_DEFAULT;
|
||||
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _logLodBuilderEvent = IDebugSwitch.LOG_LODBUILDER_EVENT_DESC;
|
||||
@ConfigAnnotations.Entry
|
||||
public static LoggerMode logLodBuilderEvent = IDebugSwitch.LOG_LODBUILDER_EVENT_DEFAULT;
|
||||
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _logRendererBufferEvent = IDebugSwitch.LOG_RENDERER_BUFFER_EVENT_DESC;
|
||||
@ConfigAnnotations.Entry
|
||||
public static LoggerMode logRendererBufferEvent = IDebugSwitch.LOG_RENDERER_BUFFER_EVENT_DEFAULT;
|
||||
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _logRendererGLEvent = IDebugSwitch.LOG_RENDERER_GL_EVENT_DESC;
|
||||
@ConfigAnnotations.Entry
|
||||
public static LoggerMode logRendererGLEvent = IDebugSwitch.LOG_RENDERER_GL_EVENT_DEFAULT;
|
||||
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _logFileReadWriteEvent = IDebugSwitch.LOG_FILE_READWRITE_EVENT_DESC;
|
||||
@ConfigAnnotations.Entry
|
||||
public static LoggerMode logFileReadWriteEvent = IDebugSwitch.LOG_FILE_READWRITE_EVENT_DEFAULT;
|
||||
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _logFileSubDimEvent = IDebugSwitch.LOG_FILE_SUB_DIM_EVENT_DESC;
|
||||
@ConfigAnnotations.Entry
|
||||
public static LoggerMode logFileSubDimEvent = IDebugSwitch.LOG_FILE_SUB_DIM_EVENT_DEFAULT;
|
||||
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _logNetworkEvent = IDebugSwitch.LOG_NETWORK_EVENT_DESC;
|
||||
@ConfigAnnotations.Entry
|
||||
public static LoggerMode logNetworkEvent = IDebugSwitch.LOG_NETWORK_EVENT_DEFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class Buffers
|
||||
{
|
||||
|
||||
|
||||
@ConfigAnnotations.ScreenEntry
|
||||
public static DebugSwitch debugSwitch;
|
||||
|
||||
public static class DebugSwitch {
|
||||
/* The logging switches available:
|
||||
* WorldGenEvent
|
||||
* WorldGenPerformance
|
||||
* WorldGenLoadEvent
|
||||
* LodBuilderEvent
|
||||
* RendererBufferEvent
|
||||
* RendererGLEvent
|
||||
* FileReadWriteEvent
|
||||
* FileSubDimEvent
|
||||
* NetworkEvent //NOT IMPL YET
|
||||
*/
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _logWorldGenEvent = IDebugSwitch.LOG_WORLDGEN_EVENT_DESC;
|
||||
@ConfigAnnotations.Entry
|
||||
public static LoggerMode logWorldGenEvent = IDebugSwitch.LOG_WORLDGEN_EVENT_DEFAULT;
|
||||
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _logWorldGenPerformance = IDebugSwitch.LOG_WORLDGEN_PERFORMANCE_DESC;
|
||||
@ConfigAnnotations.Entry
|
||||
public static LoggerMode logWorldGenPerformance = IDebugSwitch.LOG_WORLDGEN_PERFORMANCE_DEFAULT;
|
||||
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _logWorldGenLoadEvent = IDebugSwitch.LOG_WORLDGEN_LOAD_EVENT_DESC;
|
||||
@ConfigAnnotations.Entry
|
||||
public static LoggerMode logWorldGenLoadEvent = IDebugSwitch.LOG_WORLDGEN_LOAD_EVENT_DEFAULT;
|
||||
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _logLodBuilderEvent = IDebugSwitch.LOG_LODBUILDER_EVENT_DESC;
|
||||
@ConfigAnnotations.Entry
|
||||
public static LoggerMode logLodBuilderEvent = IDebugSwitch.LOG_LODBUILDER_EVENT_DEFAULT;
|
||||
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _logRendererBufferEvent = IDebugSwitch.LOG_RENDERER_BUFFER_EVENT_DESC;
|
||||
@ConfigAnnotations.Entry
|
||||
public static LoggerMode logRendererBufferEvent = IDebugSwitch.LOG_RENDERER_BUFFER_EVENT_DEFAULT;
|
||||
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _logRendererGLEvent = IDebugSwitch.LOG_RENDERER_GL_EVENT_DESC;
|
||||
@ConfigAnnotations.Entry
|
||||
public static LoggerMode logRendererGLEvent = IDebugSwitch.LOG_RENDERER_GL_EVENT_DEFAULT;
|
||||
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _logFileReadWriteEvent = IDebugSwitch.LOG_FILE_READWRITE_EVENT_DESC;
|
||||
@ConfigAnnotations.Entry
|
||||
public static LoggerMode logFileReadWriteEvent = IDebugSwitch.LOG_FILE_READWRITE_EVENT_DEFAULT;
|
||||
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _logFileSubDimEvent = IDebugSwitch.LOG_FILE_SUB_DIM_EVENT_DESC;
|
||||
@ConfigAnnotations.Entry
|
||||
public static LoggerMode logFileSubDimEvent = IDebugSwitch.LOG_FILE_SUB_DIM_EVENT_DEFAULT;
|
||||
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _logNetworkEvent = IDebugSwitch.LOG_NETWORK_EVENT_DESC;
|
||||
@ConfigAnnotations.Entry
|
||||
public static LoggerMode logNetworkEvent = IDebugSwitch.LOG_NETWORK_EVENT_DEFAULT;
|
||||
}
|
||||
|
||||
|
||||
public static class Buffers {
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _gpuUploadMethod = IBuffers.GPU_UPLOAD_METHOD_DESC;
|
||||
@ConfigAnnotations.Entry
|
||||
public static GpuUploadMethod gpuUploadMethod = IBuffers.GPU_UPLOAD_METHOD_DEFAULT;
|
||||
|
||||
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _gpuUploadPerMegabyteInMilliseconds = IBuffers.GPU_UPLOAD_PER_MEGABYTE_IN_MILLISECONDS_DESC;
|
||||
@ConfigAnnotations.Entry(minValue = 0, maxValue = 50)
|
||||
@ConfigAnnotations.Entry(minValue = 0, maxValue = 5000)
|
||||
public static int gpuUploadPerMegabyteInMilliseconds = IBuffers.GPU_UPLOAD_PER_MEGABYTE_IN_MILLISECONDS_DEFAULT.defaultValue;
|
||||
|
||||
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _rebuildTimes = IBuffers.REBUILD_TIMES_DESC;
|
||||
@ConfigAnnotations.Entry
|
||||
|
||||
@@ -15,7 +15,7 @@ public class LodCommonMain {
|
||||
public static LodForgeMethodCaller forgeMethodCaller;
|
||||
public static NetworkInterface networkInterface;
|
||||
|
||||
public static void startup(LodForgeMethodCaller caller, boolean serverSided, NetworkInterface networkInterface) {
|
||||
public static void startup(LodForgeMethodCaller caller, boolean serverSided) {
|
||||
LodCommonMain.serverSided = serverSided;
|
||||
if (caller != null) {
|
||||
LodCommonMain.forge = true;
|
||||
@@ -23,17 +23,13 @@ public class LodCommonMain {
|
||||
}
|
||||
|
||||
DependencySetup.createInitialBindings();
|
||||
|
||||
LodCommonMain.networkInterface = networkInterface;
|
||||
if (!serverSided) {
|
||||
networkInterface.register_Client();
|
||||
} else {
|
||||
networkInterface.register_Server();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void initConfig() {
|
||||
ConfigGui.init(Config.class);
|
||||
}
|
||||
|
||||
public static void registerNetworking(NetworkInterface networkInterface) {
|
||||
LodCommonMain.networkInterface = networkInterface;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.seibel.lod.common.forge;
|
||||
|
||||
import com.seibel.lod.common.wrappers.minecraft.MinecraftClientWrapper;
|
||||
import net.minecraft.client.renderer.block.model.BakedQuad;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
@@ -16,4 +17,5 @@ import java.util.Random;
|
||||
*/
|
||||
public interface LodForgeMethodCaller {
|
||||
List<BakedQuad> getQuads(MinecraftClientWrapper mc, Block block, BlockState blockState, Direction direction, Random random);
|
||||
int getPixelRGBA(TextureAtlasSprite sprite, int frameIndex, int x, int y);
|
||||
}
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
package com.seibel.lod.common.networking;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.ClientPacketListener;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.server.network.ServerGamePacketListenerImpl;
|
||||
|
||||
/**
|
||||
* This is packet handler for our mod
|
||||
* It basically handles the packets sent from the server & client
|
||||
*
|
||||
* @author Ran
|
||||
*/
|
||||
public class NetworkHandler {
|
||||
// If you need the response sender then tell me
|
||||
// I'll add extra code to get the response sender
|
||||
public static void receivePacketClient(Minecraft client, ClientPacketListener handler, FriendlyByteBuf buf) {
|
||||
// TODO: Server sided stuff here
|
||||
// You can make client execute something by using client.execute(Runnable)
|
||||
// In the fabric docs it says that client.execute is ran on the render thread?
|
||||
}
|
||||
|
||||
// If you need the response sender then tell me
|
||||
// I'll add extra code to get the response sender
|
||||
public static void receivePacketServer(MinecraftServer server, ServerPlayer client, ServerGamePacketListenerImpl handler, FriendlyByteBuf buf) {
|
||||
// TODO: Server sided stuff here
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,12 @@
|
||||
package com.seibel.lod.common.networking;
|
||||
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
|
||||
/**
|
||||
* @author Ran
|
||||
*/
|
||||
public interface NetworkInterface {
|
||||
void register_Client();
|
||||
void register_Server();
|
||||
void send(FriendlyByteBuf packetByteBuf);
|
||||
|
||||
FriendlyByteBuf receive();
|
||||
}
|
||||
|
||||
@@ -1,100 +1,20 @@
|
||||
package com.seibel.lod.common.networking;
|
||||
|
||||
import com.seibel.lod.core.ModInfo;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.network.protocol.Packet;
|
||||
import net.minecraft.network.protocol.game.ClientboundCustomPayloadPacket;
|
||||
import net.minecraft.network.protocol.game.ServerboundCustomPayloadPacket;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* This class holds most of the networking code for the mod.
|
||||
* @author Ran
|
||||
*/
|
||||
public class Networking {
|
||||
public static final ResourceLocation resourceLocation_meow = new ResourceLocation("lod", "meow");
|
||||
// public void example(int packetId) {
|
||||
// FriendlyByteBuf packetByteBuf = Networking.createNew();
|
||||
// packetByteBuf.writeInt(packetId);
|
||||
// LodCommonMain.networkInterface.send(packetByteBuf);
|
||||
// }
|
||||
|
||||
public static FriendlyByteBuf createNew() {
|
||||
// TODO: Probably replace the Unpooled.buffer()
|
||||
FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.buffer());
|
||||
buf.writeInt(ModInfo.PROTOCOL_VERSION);
|
||||
return buf;
|
||||
return new FriendlyByteBuf(Unpooled.buffer());
|
||||
}
|
||||
|
||||
/*
|
||||
* All code below is from the fabric api and might have been modified to work with Distant Horizons
|
||||
* Which is licensed under the Apache License 2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* Sends a packet to a player.
|
||||
*
|
||||
* @param player the player to send the packet to
|
||||
* @param buf the payload of the packet.
|
||||
*/
|
||||
public static void send(ServerPlayer player, FriendlyByteBuf buf) {
|
||||
Objects.requireNonNull(player, "Server player entity cannot be null");
|
||||
Objects.requireNonNull(resourceLocation_meow, "Channel name cannot be null");
|
||||
Objects.requireNonNull(buf, "Packet byte buf cannot be null");
|
||||
|
||||
player.connection.send(createS2CPacket(resourceLocation_meow, buf));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a packet to the connected server.
|
||||
*
|
||||
* @param buf the payload of the packet
|
||||
* @throws IllegalStateException if the client is not connected to a server
|
||||
*/
|
||||
public static void send(FriendlyByteBuf buf) throws IllegalStateException {
|
||||
// You cant send without a client player, so this is fine
|
||||
if (Minecraft.getInstance().getConnection() != null) {
|
||||
Minecraft.getInstance().getConnection().send(createC2SPacket(resourceLocation_meow, buf));
|
||||
return;
|
||||
}
|
||||
|
||||
throw new IllegalStateException("Cannot send packets when not in game!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a packet which may be sent to the connected client.
|
||||
*
|
||||
* @param channelName the channel name
|
||||
* @param buf the packet byte buf which represents the payload of the packet
|
||||
* @return a new packet
|
||||
*/
|
||||
public static Packet<?> createS2CPacket(ResourceLocation channelName, FriendlyByteBuf buf) {
|
||||
Objects.requireNonNull(channelName, "Channel cannot be null");
|
||||
Objects.requireNonNull(buf, "Buf cannot be null");
|
||||
|
||||
return createPlayS2CPacket(channelName, buf);
|
||||
}
|
||||
|
||||
public static Packet<?> createPlayS2CPacket(ResourceLocation channel, FriendlyByteBuf buf) {
|
||||
return new ClientboundCustomPayloadPacket(channel, buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a packet which may be sent to a the connected server.
|
||||
*
|
||||
* @param channelName the channel name
|
||||
* @param buf the packet byte buf which represents the payload of the packet
|
||||
* @return a new packet
|
||||
*/
|
||||
public static Packet<?> createC2SPacket(ResourceLocation channelName, FriendlyByteBuf buf) {
|
||||
Objects.requireNonNull(channelName, "Channel name cannot be null");
|
||||
Objects.requireNonNull(buf, "Buf cannot be null");
|
||||
|
||||
return createPlayC2SPacket(channelName, buf);
|
||||
}
|
||||
|
||||
public static Packet<?> createPlayC2SPacket(ResourceLocation channelName, FriendlyByteBuf buf) {
|
||||
return new ServerboundCustomPayloadPacket(channelName, buf);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
package com.seibel.lod.common.wrappers;
|
||||
|
||||
import com.seibel.lod.common.LodCommonMain;
|
||||
import com.seibel.lod.common.wrappers.minecraft.MinecraftClientWrapper;
|
||||
import com.seibel.lod.common.wrappers.minecraft.MinecraftRenderWrapper;
|
||||
import com.seibel.lod.common.wrappers.minecraft.MinecraftClientWrapper;
|
||||
import com.seibel.lod.core.handlers.IReflectionHandler;
|
||||
import com.seibel.lod.core.handlers.ReflectionHandler;
|
||||
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
|
||||
import com.seibel.lod.core.wrapperInterfaces.IVersionConstants;
|
||||
import com.seibel.lod.core.wrapperInterfaces.IWrapperFactory;
|
||||
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||
|
||||
/**
|
||||
* Binds all necessary dependencies, so we
|
||||
@@ -22,16 +22,13 @@ import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
* @version 12-1-2021
|
||||
*/
|
||||
public class DependencySetup {
|
||||
public static void createInitialBindings()
|
||||
{
|
||||
public static void createInitialBindings() {
|
||||
SingletonHandler.bind(IVersionConstants.class, VersionConstants.INSTANCE);
|
||||
if (!LodCommonMain.serverSided)
|
||||
{
|
||||
if (!LodCommonMain.serverSided) {
|
||||
SingletonHandler.bind(IMinecraftClientWrapper.class, MinecraftClientWrapper.INSTANCE);
|
||||
SingletonHandler.bind(IMinecraftRenderWrapper.class, MinecraftRenderWrapper.INSTANCE);
|
||||
SingletonHandler.bind(IReflectionHandler.class, ReflectionHandler.createSingleton(MinecraftClientWrapper.INSTANCE.getOptions().getClass().getDeclaredFields(), MinecraftClientWrapper.INSTANCE.getOptions()));
|
||||
}
|
||||
|
||||
SingletonHandler.bind(IWrapperFactory.class, WrapperFactory.INSTANCE);
|
||||
DependencySetupDoneCheck.isDone = true;
|
||||
}
|
||||
|
||||
@@ -2,9 +2,7 @@ package com.seibel.lod.common.wrappers;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class DependencySetupDoneCheck
|
||||
{
|
||||
public class DependencySetupDoneCheck {
|
||||
public static boolean isDone = false;
|
||||
public static Supplier<Boolean> getIsCurrentThreadDistantGeneratorThread = (() -> {return false;});
|
||||
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ package com.seibel.lod.common.wrappers;
|
||||
import java.nio.FloatBuffer;
|
||||
|
||||
import com.mojang.math.Matrix4f;
|
||||
import com.seibel.lod.common.wrappers.block.BlockPosWrapper;
|
||||
import com.seibel.lod.core.enums.LodDirection;
|
||||
import com.seibel.lod.core.objects.math.Mat4f;
|
||||
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
|
||||
@@ -53,21 +52,20 @@ public class McObjectConverter
|
||||
static final Direction[] directions;
|
||||
static final LodDirection[] lodDirections;
|
||||
static {
|
||||
LodDirection[] lodDirs = LodDirection.values();
|
||||
directions = new Direction[lodDirs.length];
|
||||
lodDirections = new LodDirection[lodDirs.length];
|
||||
for (LodDirection lodDir : lodDirs) {
|
||||
Direction dir = Direction.byName(lodDir.name());
|
||||
directions[lodDir.ordinal()] = dir;
|
||||
lodDirections[dir.ordinal()] = lodDir;
|
||||
}
|
||||
LodDirection[] lodDirs = LodDirection.values();
|
||||
directions = new Direction[lodDirs.length];
|
||||
lodDirections = new LodDirection[lodDirs.length];
|
||||
for (LodDirection lodDir : lodDirs) {
|
||||
Direction dir = Direction.byName(lodDir.name());
|
||||
directions[lodDir.ordinal()] = dir;
|
||||
lodDirections[dir.ordinal()] = lodDir;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static BlockPos Convert(AbstractBlockPosWrapper wrappedPos) {
|
||||
return new BlockPos(wrappedPos.getX(),wrappedPos.getY(), wrappedPos.getZ());
|
||||
return new BlockPos(wrappedPos.getX(),wrappedPos.getY(), wrappedPos.getZ());
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static Direction Convert(LodDirection lodDirection)
|
||||
{
|
||||
return directions[lodDirection.ordinal()];
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package com.seibel.lod.common.wrappers;
|
||||
|
||||
import com.seibel.lod.core.enums.config.DistanceGenerationMode;
|
||||
@@ -6,30 +5,26 @@ import com.seibel.lod.core.wrapperInterfaces.IVersionConstants;
|
||||
|
||||
/**
|
||||
* @author James Seibel
|
||||
* @version 12-11-2021
|
||||
* @version 3-3-2022
|
||||
*/
|
||||
public class VersionConstants implements IVersionConstants
|
||||
{
|
||||
public static final VersionConstants INSTANCE = new VersionConstants();
|
||||
|
||||
|
||||
private VersionConstants()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getMinimumWorldHeight()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
public class VersionConstants implements IVersionConstants {
|
||||
public static final VersionConstants INSTANCE = new VersionConstants();
|
||||
|
||||
@Override
|
||||
public int getWorldGenerationCountPerThread()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
private VersionConstants() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getMinimumWorldHeight() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWorldGenerationCountPerThread() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVanillaRenderedChunkSquare()
|
||||
|
||||
@@ -36,59 +36,48 @@ import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment
|
||||
* @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(long xAndZPositionCombined)
|
||||
{
|
||||
return new ChunkPosWrapper(xAndZPositionCombined);
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
|
||||
public AbstractBatchGenerationEnvionmentWrapper createBatchGenerator(LodBuilder newLodBuilder,
|
||||
LodDimension newLodDimension, IWorldWrapper worldWrapper)
|
||||
{
|
||||
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(long xAndZPositionCombined) {
|
||||
return new ChunkPosWrapper(xAndZPositionCombined);
|
||||
}
|
||||
|
||||
@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 AbstractBatchGenerationEnvionmentWrapper createBatchGenerator(LodBuilder newLodBuilder,
|
||||
LodDimension newLodDimension, IWorldWrapper worldWrapper) {
|
||||
return new BatchGenerationEnvironment(worldWrapper, newLodBuilder, newLodDimension);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,27 +1,26 @@
|
||||
package com.seibel.lod.common.wrappers.block;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.level.LevelReader;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class BlockDetailMap
|
||||
{
|
||||
|
||||
private static ConcurrentHashMap<BlockState, BlockDetailWrapper> map = new ConcurrentHashMap<BlockState, BlockDetailWrapper>();
|
||||
|
||||
private BlockDetailMap() {}
|
||||
|
||||
public static BlockDetailWrapper getOrMakeBlockDetailCache(BlockState bs, BlockPos pos, LevelReader getter) {
|
||||
BlockDetailWrapper cache = map.get(bs);
|
||||
if (cache != null) return cache;
|
||||
if (bs.getFluidState().isEmpty()) {
|
||||
cache = BlockDetailWrapper.make(bs, pos, getter);
|
||||
} else {
|
||||
cache = BlockDetailWrapper.make(bs.getFluidState().createLegacyBlock(), pos, getter);
|
||||
}
|
||||
BlockDetailWrapper cacheCAS = map.putIfAbsent(bs, cache);
|
||||
return cacheCAS==null ? cache : cacheCAS;
|
||||
}
|
||||
private static ConcurrentHashMap<BlockState, BlockDetailWrapper> map = new ConcurrentHashMap<BlockState, BlockDetailWrapper>();
|
||||
|
||||
private BlockDetailMap() {}
|
||||
|
||||
public static BlockDetailWrapper getOrMakeBlockDetailCache(BlockState bs, BlockPos pos, LevelReader getter) {
|
||||
BlockDetailWrapper cache = map.get(bs);
|
||||
if (cache != null) return cache;
|
||||
if (bs.getFluidState().isEmpty()) {
|
||||
cache = BlockDetailWrapper.make(bs, pos, getter);
|
||||
} else {
|
||||
cache = BlockDetailWrapper.make(bs.getFluidState().createLegacyBlock(), pos, getter);
|
||||
}
|
||||
BlockDetailWrapper cacheCAS = map.putIfAbsent(bs, cache);
|
||||
return cacheCAS==null ? cache : cacheCAS;
|
||||
}
|
||||
}
|
||||
|
||||
+251
-251
@@ -52,275 +52,275 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class BlockDetailWrapper extends IBlockDetailWrapper
|
||||
{
|
||||
private static final ILodConfigWrapperSingleton CONFIG = SingletonHandler.get(ILodConfigWrapperSingleton.class);
|
||||
private static final ILodConfigWrapperSingleton CONFIG = SingletonHandler.get(ILodConfigWrapperSingleton.class);
|
||||
|
||||
public static final int FLOWER_COLOR_SCALE = 5;
|
||||
public static final int FLOWER_COLOR_SCALE = 5;
|
||||
|
||||
public static final Random random = new Random(0);
|
||||
public static final Random random = new Random(0);
|
||||
|
||||
enum ColorMode {
|
||||
Default,
|
||||
Flower,
|
||||
Leaves;
|
||||
static ColorMode getColorMode(Block b) {
|
||||
if (b instanceof LeavesBlock) return Leaves;
|
||||
if (b instanceof FlowerBlock) return Flower;
|
||||
return Default;
|
||||
}
|
||||
}
|
||||
//TODO: Perhaps make this not just use the first frame?
|
||||
private static int calculateColorFromTexture(TextureAtlasSprite texture, ColorMode colorMode) {
|
||||
|
||||
int count = 0;
|
||||
double alpha = 0;
|
||||
double red = 0;
|
||||
double green = 0;
|
||||
double blue = 0;
|
||||
int tempColor;
|
||||
|
||||
{
|
||||
// textures normally use u and v instead of x and y
|
||||
for (int u = 0; u < texture.getWidth(); u++)
|
||||
{
|
||||
for (int v = 0; v < texture.getHeight(); v++)
|
||||
{
|
||||
//note: Minecraft color format is: 0xAA BB GG RR
|
||||
//________ DH mod color format is: 0xAA RR GG BB
|
||||
//OpenGL RGBA format native order: 0xRR GG BB AA
|
||||
//_ OpenGL RGBA format Java Order: 0xAA BB GG RR
|
||||
tempColor = TextureAtlasSpriteWrapper.getPixelRGBA(texture, 0, u, v);
|
||||
|
||||
double r = ((tempColor & 0x000000FF) )/255.;
|
||||
double g = ((tempColor & 0x0000FF00) >>> 8)/255.;
|
||||
double b = ((tempColor & 0x00FF0000) >>> 16)/255.;
|
||||
double a = ((tempColor & 0xFF000000) >>> 24)/255.;
|
||||
int scale = 1;
|
||||
|
||||
if (colorMode == ColorMode.Leaves) {
|
||||
r *= a;
|
||||
g *= a;
|
||||
b *= a;
|
||||
a = 1.;
|
||||
} else if (a==0.) {
|
||||
continue;
|
||||
} else if (colorMode == ColorMode.Flower && (g+0.1<b || g+0.1<r)) {
|
||||
scale = FLOWER_COLOR_SCALE;
|
||||
}
|
||||
|
||||
count += scale;
|
||||
alpha += a*a*scale;
|
||||
red += r*r*scale;
|
||||
green += g*g*scale;
|
||||
blue += b*b*scale;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (count == 0)
|
||||
// this block is entirely transparent
|
||||
tempColor = ColorUtil.rgbToInt(255,255,0,255);
|
||||
else
|
||||
{
|
||||
// determine the average color
|
||||
tempColor = ColorUtil.rgbToInt(
|
||||
(int) (Math.sqrt(alpha/count)*255.),
|
||||
(int) (Math.sqrt(red / count)*255.),
|
||||
(int) (Math.sqrt(green / count)*255.),
|
||||
(int) (Math.sqrt(blue / count)*255.));
|
||||
}
|
||||
// TODO: Remove this when transparency is added!
|
||||
double colorAlpha = ColorUtil.getAlpha(tempColor)/255.;
|
||||
tempColor = ColorUtil.rgbToInt(
|
||||
ColorUtil.getAlpha(tempColor),
|
||||
(int)(ColorUtil.getRed(tempColor) * colorAlpha),
|
||||
(int)(ColorUtil.getGreen(tempColor) * colorAlpha),
|
||||
(int)(ColorUtil.getBlue(tempColor) * colorAlpha)
|
||||
);
|
||||
return tempColor;
|
||||
}
|
||||
enum ColorMode {
|
||||
Default,
|
||||
Flower,
|
||||
Leaves;
|
||||
static ColorMode getColorMode(Block b) {
|
||||
if (b instanceof LeavesBlock) return Leaves;
|
||||
if (b instanceof FlowerBlock) return Flower;
|
||||
return Default;
|
||||
}
|
||||
}
|
||||
//TODO: Perhaps make this not just use the first frame?
|
||||
private static int calculateColorFromTexture(TextureAtlasSprite texture, ColorMode colorMode) {
|
||||
|
||||
int count = 0;
|
||||
double alpha = 0;
|
||||
double red = 0;
|
||||
double green = 0;
|
||||
double blue = 0;
|
||||
int tempColor;
|
||||
|
||||
{
|
||||
// textures normally use u and v instead of x and y
|
||||
for (int u = 0; u < texture.getWidth(); u++)
|
||||
{
|
||||
for (int v = 0; v < texture.getHeight(); v++)
|
||||
{
|
||||
//note: Minecraft color format is: 0xAA BB GG RR
|
||||
//________ DH mod color format is: 0xAA RR GG BB
|
||||
//OpenGL RGBA format native order: 0xRR GG BB AA
|
||||
//_ OpenGL RGBA format Java Order: 0xAA BB GG RR
|
||||
tempColor = TextureAtlasSpriteWrapper.getPixelRGBA(texture, 0, u, v);
|
||||
|
||||
double r = ((tempColor & 0x000000FF) )/255.;
|
||||
double g = ((tempColor & 0x0000FF00) >>> 8)/255.;
|
||||
double b = ((tempColor & 0x00FF0000) >>> 16)/255.;
|
||||
double a = ((tempColor & 0xFF000000) >>> 24)/255.;
|
||||
int scale = 1;
|
||||
|
||||
if (colorMode == ColorMode.Leaves) {
|
||||
r *= a;
|
||||
g *= a;
|
||||
b *= a;
|
||||
a = 1.;
|
||||
} else if (a==0.) {
|
||||
continue;
|
||||
} else if (colorMode == ColorMode.Flower && (g+0.1<b || g+0.1<r)) {
|
||||
scale = FLOWER_COLOR_SCALE;
|
||||
}
|
||||
|
||||
count += scale;
|
||||
alpha += a*a*scale;
|
||||
red += r*r*scale;
|
||||
green += g*g*scale;
|
||||
blue += b*b*scale;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (count == 0)
|
||||
// this block is entirely transparent
|
||||
tempColor = ColorUtil.rgbToInt(255,255,0,255);
|
||||
else
|
||||
{
|
||||
// determine the average color
|
||||
tempColor = ColorUtil.rgbToInt(
|
||||
(int) (Math.sqrt(alpha/count)*255.),
|
||||
(int) (Math.sqrt(red / count)*255.),
|
||||
(int) (Math.sqrt(green / count)*255.),
|
||||
(int) (Math.sqrt(blue / count)*255.));
|
||||
}
|
||||
// TODO: Remove this when transparency is added!
|
||||
double colorAlpha = ColorUtil.getAlpha(tempColor)/255.;
|
||||
tempColor = ColorUtil.rgbToInt(
|
||||
ColorUtil.getAlpha(tempColor),
|
||||
(int)(ColorUtil.getRed(tempColor) * colorAlpha),
|
||||
(int)(ColorUtil.getGreen(tempColor) * colorAlpha),
|
||||
(int)(ColorUtil.getBlue(tempColor) * colorAlpha)
|
||||
);
|
||||
return tempColor;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private static final Block[] BLOCK_TO_AVOID = {Blocks.AIR, Blocks.CAVE_AIR, Blocks.BARRIER};
|
||||
|
||||
private static final Direction[] DIRECTION_ORDER = {Direction.UP, Direction.NORTH, Direction.EAST, Direction.WEST, Direction.SOUTH, Direction.DOWN};
|
||||
|
||||
private static boolean isBlockToBeAvoid(Block b) {
|
||||
for (Block bta : BLOCK_TO_AVOID)
|
||||
if (bta==b) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
final BlockState state;
|
||||
final BlockPos samplePos;
|
||||
final LevelReader sampleGetter;
|
||||
|
||||
boolean isShapeResolved = false;
|
||||
boolean[] dontOccludeFaces = null;
|
||||
boolean noCollision = false;
|
||||
boolean noFullFace = false;
|
||||
|
||||
boolean isColorResolved = false;
|
||||
int baseColor = 0; //TODO: Impl per-face color
|
||||
boolean needShade = true;
|
||||
boolean needPostTinting = false;
|
||||
int tintIndex = 0;
|
||||
|
||||
public static BlockDetailWrapper NULL_BLOCK_DETAIL = new BlockDetailWrapper();
|
||||
|
||||
public BlockDetailWrapper(BlockState state, BlockPos pos, LevelReader getter) {
|
||||
this.state = state;
|
||||
this.samplePos = pos;
|
||||
this.sampleGetter = getter;
|
||||
}
|
||||
|
||||
private BlockDetailWrapper() {
|
||||
this.state = null;
|
||||
this.samplePos = null;
|
||||
this.sampleGetter = null;
|
||||
}
|
||||
|
||||
static BlockDetailWrapper make(BlockState bs, BlockPos pos, LevelReader getter) {
|
||||
if(!bs.getFluidState().isEmpty()) { // Is a fluidBlock
|
||||
if (isBlockToBeAvoid(bs.getBlock())) return NULL_BLOCK_DETAIL;
|
||||
if (bs.isAir()) return NULL_BLOCK_DETAIL;
|
||||
return new BlockDetailWrapper(bs, pos, getter);
|
||||
} else {
|
||||
if (bs.getRenderShape() != RenderShape.MODEL) return NULL_BLOCK_DETAIL;
|
||||
if (isBlockToBeAvoid(bs.getBlock())) return NULL_BLOCK_DETAIL;
|
||||
return new BlockDetailWrapper(bs, pos, getter);
|
||||
}
|
||||
}
|
||||
|
||||
private void resolveShapes() {
|
||||
if (isShapeResolved) return;
|
||||
if (state.getFluidState().isEmpty()) {
|
||||
noCollision = state.getCollisionShape(sampleGetter, samplePos).isEmpty();
|
||||
dontOccludeFaces = new boolean[6];
|
||||
if (state.canOcclude()) {
|
||||
|
||||
private static final Block[] BLOCK_TO_AVOID = {Blocks.AIR, Blocks.CAVE_AIR, Blocks.BARRIER};
|
||||
|
||||
private static final Direction[] DIRECTION_ORDER = {Direction.UP, Direction.NORTH, Direction.EAST, Direction.WEST, Direction.SOUTH, Direction.DOWN};
|
||||
|
||||
private static boolean isBlockToBeAvoid(Block b) {
|
||||
for (Block bta : BLOCK_TO_AVOID)
|
||||
if (bta==b) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
final BlockState state;
|
||||
final BlockPos samplePos;
|
||||
final LevelReader sampleGetter;
|
||||
|
||||
boolean isShapeResolved = false;
|
||||
boolean[] dontOccludeFaces = null;
|
||||
boolean noCollision = false;
|
||||
boolean noFullFace = false;
|
||||
|
||||
boolean isColorResolved = false;
|
||||
int baseColor = 0; //TODO: Impl per-face color
|
||||
boolean needShade = true;
|
||||
boolean needPostTinting = false;
|
||||
int tintIndex = 0;
|
||||
|
||||
public static BlockDetailWrapper NULL_BLOCK_DETAIL = new BlockDetailWrapper();
|
||||
|
||||
public BlockDetailWrapper(BlockState state, BlockPos pos, LevelReader getter) {
|
||||
this.state = state;
|
||||
this.samplePos = pos;
|
||||
this.sampleGetter = getter;
|
||||
}
|
||||
|
||||
private BlockDetailWrapper() {
|
||||
this.state = null;
|
||||
this.samplePos = null;
|
||||
this.sampleGetter = null;
|
||||
}
|
||||
|
||||
static BlockDetailWrapper make(BlockState bs, BlockPos pos, LevelReader getter) {
|
||||
if(!bs.getFluidState().isEmpty()) { // Is a fluidBlock
|
||||
if (isBlockToBeAvoid(bs.getBlock())) return NULL_BLOCK_DETAIL;
|
||||
if (bs.isAir()) return NULL_BLOCK_DETAIL;
|
||||
return new BlockDetailWrapper(bs, pos, getter);
|
||||
} else {
|
||||
if (bs.getRenderShape() != RenderShape.MODEL) return NULL_BLOCK_DETAIL;
|
||||
if (isBlockToBeAvoid(bs.getBlock())) return NULL_BLOCK_DETAIL;
|
||||
return new BlockDetailWrapper(bs, pos, getter);
|
||||
}
|
||||
}
|
||||
|
||||
private void resolveShapes() {
|
||||
if (isShapeResolved) return;
|
||||
if (state.getFluidState().isEmpty()) {
|
||||
noCollision = state.getCollisionShape(sampleGetter, samplePos).isEmpty();
|
||||
dontOccludeFaces = new boolean[6];
|
||||
if (state.canOcclude()) {
|
||||
/* FIXME: Figure out how or if needed to impl per-face culling?
|
||||
for (Direction dir : Direction.values()) {
|
||||
dontOccludeFaces[McObjectConverter.Convert(dir).ordinal()]
|
||||
= state.getFaceOcclusionShape(sampleGetter, samplePos, dir).isEmpty();
|
||||
}*/
|
||||
} else {
|
||||
Arrays.fill(dontOccludeFaces, true);
|
||||
}
|
||||
|
||||
VoxelShape voxelShape = state.getShape(sampleGetter, samplePos);
|
||||
if (voxelShape.isEmpty()) {
|
||||
noFullFace = true;
|
||||
} else {
|
||||
AABB bbox = voxelShape.bounds();
|
||||
double xWidth = (bbox.maxX - bbox.minX);
|
||||
double yWidth = (bbox.maxY - bbox.minY);
|
||||
double zWidth = (bbox.maxZ - bbox.minZ);
|
||||
noFullFace = xWidth < 1 && zWidth < 1 && yWidth < 1;
|
||||
Arrays.fill(dontOccludeFaces, true);
|
||||
}
|
||||
} else { // Liquid Block
|
||||
dontOccludeFaces = new boolean[6];
|
||||
}
|
||||
isShapeResolved = true;
|
||||
}
|
||||
|
||||
private void resolveColors() {
|
||||
if (isColorResolved) return;
|
||||
if (state.getFluidState().isEmpty()) {
|
||||
List<BakedQuad> quads = null;
|
||||
for (Direction direction : DIRECTION_ORDER)
|
||||
{
|
||||
quads = Minecraft.getInstance().getModelManager().getBlockModelShaper().
|
||||
getBlockModel(state).getQuads(state, direction, random);
|
||||
if (!quads.isEmpty() &&
|
||||
!(state.getBlock() instanceof RotatedPillarBlock && direction == Direction.UP))
|
||||
break;
|
||||
};
|
||||
if (quads == null || quads.isEmpty()) {
|
||||
quads = Minecraft.getInstance().getModelManager().getBlockModelShaper().
|
||||
getBlockModel(state).getQuads(state, null, random);
|
||||
}
|
||||
|
||||
if (quads != null && !quads.isEmpty()) {
|
||||
needPostTinting = quads.get(0).isTinted();
|
||||
needShade = quads.get(0).isShade();
|
||||
tintIndex = quads.get(0).getTintIndex();
|
||||
baseColor = calculateColorFromTexture(quads.get(0).getSprite(),
|
||||
ColorMode.getColorMode(state.getBlock()));
|
||||
} else { // Backup method.
|
||||
needPostTinting = false;
|
||||
needShade = false;
|
||||
tintIndex = 0;
|
||||
baseColor = calculateColorFromTexture(Minecraft.getInstance().getModelManager().getBlockModelShaper().getParticleIcon(state),
|
||||
ColorMode.getColorMode(state.getBlock()));
|
||||
}
|
||||
} else { // Liquid Block
|
||||
|
||||
needPostTinting = true;
|
||||
needShade = false;
|
||||
tintIndex = 0;
|
||||
baseColor = calculateColorFromTexture(Minecraft.getInstance().getModelManager().getBlockModelShaper().getParticleIcon(state),
|
||||
ColorMode.getColorMode(state.getBlock()));
|
||||
|
||||
}
|
||||
isColorResolved = true;
|
||||
}
|
||||
|
||||
private BlockAndTintGetter wrapColorResolver(LevelReader level) {
|
||||
int blendDistance = CONFIG.client().graphics().quality().getLodBiomeBlending();
|
||||
if (blendDistance == 0) {
|
||||
return new TintGetterOverrideFast(level);
|
||||
} else {
|
||||
return new TintGetterOverrideSmooth(level, blendDistance);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAndResolveFaceColor(LodDirection dir, IChunkWrapper chunk, AbstractBlockPosWrapper blockPos)
|
||||
{
|
||||
// FIXME: impl per-face colors
|
||||
resolveColors();
|
||||
if (!needPostTinting) return baseColor;
|
||||
int tintColor = Minecraft.getInstance().getBlockColors()
|
||||
.getColor(state, wrapColorResolver(((ChunkWrapper)chunk).getColorResolver()),
|
||||
McObjectConverter.Convert(blockPos), tintIndex);
|
||||
if (tintColor == -1) return baseColor;
|
||||
return ColorUtil.multiplyARGBwithRGB(baseColor, tintColor);
|
||||
}
|
||||
VoxelShape voxelShape = state.getShape(sampleGetter, samplePos);
|
||||
if (voxelShape.isEmpty()) {
|
||||
noFullFace = true;
|
||||
} else {
|
||||
AABB bbox = voxelShape.bounds();
|
||||
double xWidth = (bbox.maxX - bbox.minX);
|
||||
double yWidth = (bbox.maxY - bbox.minY);
|
||||
double zWidth = (bbox.maxZ - bbox.minZ);
|
||||
noFullFace = xWidth < 1 && zWidth < 1 && yWidth < 1;
|
||||
}
|
||||
} else { // Liquid Block
|
||||
dontOccludeFaces = new boolean[6];
|
||||
}
|
||||
isShapeResolved = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasFaceCullingFor(LodDirection dir)
|
||||
{
|
||||
resolveShapes();
|
||||
return !dontOccludeFaces[dir.ordinal()];
|
||||
}
|
||||
private void resolveColors() {
|
||||
if (isColorResolved) return;
|
||||
if (state.getFluidState().isEmpty()) {
|
||||
List<BakedQuad> quads = null;
|
||||
for (Direction direction : DIRECTION_ORDER)
|
||||
{
|
||||
quads = Minecraft.getInstance().getModelManager().getBlockModelShaper().
|
||||
getBlockModel(state).getQuads(state, direction, random);
|
||||
if (!quads.isEmpty() &&
|
||||
!(state.getBlock() instanceof RotatedPillarBlock && direction == Direction.UP))
|
||||
break;
|
||||
};
|
||||
if (quads == null || quads.isEmpty()) {
|
||||
quads = Minecraft.getInstance().getModelManager().getBlockModelShaper().
|
||||
getBlockModel(state).getQuads(state, null, random);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNoCollision()
|
||||
{
|
||||
resolveShapes();
|
||||
return noCollision;
|
||||
}
|
||||
if (quads != null && !quads.isEmpty()) {
|
||||
needPostTinting = quads.get(0).isTinted();
|
||||
needShade = quads.get(0).isShade();
|
||||
tintIndex = quads.get(0).getTintIndex();
|
||||
baseColor = calculateColorFromTexture(quads.get(0).getSprite(),
|
||||
ColorMode.getColorMode(state.getBlock()));
|
||||
} else { // Backup method.
|
||||
needPostTinting = false;
|
||||
needShade = false;
|
||||
tintIndex = 0;
|
||||
baseColor = calculateColorFromTexture(Minecraft.getInstance().getModelManager().getBlockModelShaper().getParticleIcon(state),
|
||||
ColorMode.getColorMode(state.getBlock()));
|
||||
}
|
||||
} else { // Liquid Block
|
||||
|
||||
@Override
|
||||
public boolean noFaceIsFullFace()
|
||||
{
|
||||
resolveShapes();
|
||||
return noFullFace;
|
||||
}
|
||||
needPostTinting = true;
|
||||
needShade = false;
|
||||
tintIndex = 0;
|
||||
baseColor = calculateColorFromTexture(Minecraft.getInstance().getModelManager().getBlockModelShaper().getParticleIcon(state),
|
||||
ColorMode.getColorMode(state.getBlock()));
|
||||
|
||||
@Override
|
||||
public String serialize()
|
||||
{
|
||||
// FIXME: Impl this for the blockState Storage stuff
|
||||
return null;
|
||||
}
|
||||
}
|
||||
isColorResolved = true;
|
||||
}
|
||||
|
||||
private BlockAndTintGetter wrapColorResolver(LevelReader level) {
|
||||
int blendDistance = CONFIG.client().graphics().quality().getLodBiomeBlending();
|
||||
if (blendDistance == 0) {
|
||||
return new TintGetterOverrideFast(level);
|
||||
} else {
|
||||
return new TintGetterOverrideSmooth(level, blendDistance);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAndResolveFaceColor(LodDirection dir, IChunkWrapper chunk, AbstractBlockPosWrapper blockPos)
|
||||
{
|
||||
// FIXME: impl per-face colors
|
||||
resolveColors();
|
||||
if (!needPostTinting) return baseColor;
|
||||
int tintColor = Minecraft.getInstance().getBlockColors()
|
||||
.getColor(state, wrapColorResolver(((ChunkWrapper)chunk).getColorResolver()),
|
||||
McObjectConverter.Convert(blockPos), tintIndex);
|
||||
if (tintColor == -1) return baseColor;
|
||||
return ColorUtil.multiplyARGBwithRGB(baseColor, tintColor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasFaceCullingFor(LodDirection dir)
|
||||
{
|
||||
resolveShapes();
|
||||
return !dontOccludeFaces[dir.ordinal()];
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNoCollision()
|
||||
{
|
||||
resolveShapes();
|
||||
return noCollision;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean noFaceIsFullFace()
|
||||
{
|
||||
resolveShapes();
|
||||
return noFullFace;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String serialize()
|
||||
{
|
||||
// FIXME: Impl this for the blockState Storage stuff
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isSame(IBlockDetailWrapper iBlockDetail)
|
||||
{
|
||||
return ((BlockDetailWrapper)iBlockDetail).state.getBlock().equals(state.getBlock());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isSame(IBlockDetailWrapper iBlockDetail)
|
||||
{
|
||||
return ((BlockDetailWrapper)iBlockDetail).state.getBlock().equals(state.getBlock());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ import net.minecraft.core.BlockPos;
|
||||
*/
|
||||
public class BlockPosWrapper extends AbstractBlockPosWrapper
|
||||
{
|
||||
private final BlockPos.MutableBlockPos blockPos;
|
||||
private BlockPos.MutableBlockPos blockPos;
|
||||
|
||||
|
||||
public BlockPosWrapper()
|
||||
|
||||
+8
-6
@@ -27,23 +27,25 @@ import java.util.stream.Stream;
|
||||
|
||||
public class TintGetterOverrideFast implements BlockAndTintGetter {
|
||||
LevelReader parent;
|
||||
private final Object2ObjectArrayMap<ColorResolver, ConcurrentHashMap<Biome, Integer>> tintCaches;
|
||||
|
||||
public TintGetterOverrideFast(LevelReader parent) {
|
||||
this.parent = parent;
|
||||
this.tintCaches = Util.make(new Object2ObjectArrayMap(3), object2ObjectArrayMap -> {
|
||||
object2ObjectArrayMap.put(BiomeColors.GRASS_COLOR_RESOLVER, new ConcurrentHashMap<Biome, Integer>());
|
||||
object2ObjectArrayMap.put(BiomeColors.FOLIAGE_COLOR_RESOLVER, new ConcurrentHashMap<Biome, Integer>());
|
||||
object2ObjectArrayMap.put(BiomeColors.WATER_COLOR_RESOLVER, new ConcurrentHashMap<Biome, Integer>());
|
||||
});
|
||||
}
|
||||
|
||||
private Biome _getBiome(BlockPos pos) {
|
||||
#if MC_VERSION_1_18_2
|
||||
return parent.getBiome(pos).value();
|
||||
#elif MC_VERSION_1_18_1
|
||||
return parent.getBiome(pos);
|
||||
#endif
|
||||
return parent.getBiome(pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBlockTint(BlockPos blockPos, ColorResolver colorResolver) {
|
||||
Biome b = _getBiome(blockPos);
|
||||
return colorResolver.getColor(b, blockPos.getX(), blockPos.getZ());
|
||||
return tintCaches.get(colorResolver).computeIfAbsent(b, (key) -> colorResolver.getColor(b, blockPos.getX(), blockPos.getZ()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+9
-6
@@ -26,19 +26,21 @@ import java.util.stream.Stream;
|
||||
|
||||
public class TintGetterOverrideSmooth implements BlockAndTintGetter {
|
||||
LevelReader parent;
|
||||
private final Object2ObjectArrayMap<ColorResolver, BlockTintCache> tintCaches;
|
||||
public int smoothingRange;
|
||||
|
||||
public TintGetterOverrideSmooth(LevelReader parent, int smoothingRange) {
|
||||
this.parent = parent;
|
||||
this.smoothingRange = smoothingRange;
|
||||
this.tintCaches = Util.make(new Object2ObjectArrayMap<>(3), object2ObjectArrayMap -> {
|
||||
object2ObjectArrayMap.put(BiomeColors.GRASS_COLOR_RESOLVER, new BlockTintCache((pos) -> calculateBlockTint(pos, BiomeColors.GRASS_COLOR_RESOLVER)));
|
||||
object2ObjectArrayMap.put(BiomeColors.FOLIAGE_COLOR_RESOLVER, new BlockTintCache((pos) -> calculateBlockTint(pos, BiomeColors.FOLIAGE_COLOR_RESOLVER)));
|
||||
object2ObjectArrayMap.put(BiomeColors.WATER_COLOR_RESOLVER, new BlockTintCache((pos) -> calculateBlockTint(pos, BiomeColors.WATER_COLOR_RESOLVER)));
|
||||
});
|
||||
}
|
||||
|
||||
private Biome _getBiome(BlockPos pos) {
|
||||
#if MC_VERSION_1_18_2
|
||||
return parent.getBiome(pos).value();
|
||||
#elif MC_VERSION_1_18_1
|
||||
return parent.getBiome(pos);
|
||||
#endif
|
||||
return parent.getBiome(pos);
|
||||
}
|
||||
|
||||
public int calculateBlockTint(BlockPos blockPos, ColorResolver colorResolver)
|
||||
@@ -65,7 +67,8 @@ public class TintGetterOverrideSmooth implements BlockAndTintGetter {
|
||||
|
||||
@Override
|
||||
public int getBlockTint(BlockPos blockPos, ColorResolver colorResolver) {
|
||||
return calculateBlockTint(blockPos, colorResolver);
|
||||
BlockTintCache blockTintCache = this.tintCaches.get(colorResolver);
|
||||
return blockTintCache.getColor(blockPos, null); //FIXME
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -18,7 +18,7 @@ import net.minecraft.world.level.ChunkPos;
|
||||
*/
|
||||
public class ChunkPosWrapper extends AbstractChunkPosWrapper
|
||||
{
|
||||
private final net.minecraft.world.level.ChunkPos chunkPos;
|
||||
private net.minecraft.world.level.ChunkPos chunkPos;
|
||||
|
||||
public ChunkPosWrapper()
|
||||
{
|
||||
@@ -45,8 +45,9 @@ public class ChunkPosWrapper extends AbstractChunkPosWrapper
|
||||
this.chunkPos = new ChunkPos(chunkX, chunkZ);
|
||||
}
|
||||
|
||||
public ChunkPosWrapper(long l) {
|
||||
this.chunkPos = new ChunkPos(l);
|
||||
public ChunkPosWrapper(long l)
|
||||
{
|
||||
this.chunkPos = new ChunkPos(l);
|
||||
}
|
||||
|
||||
|
||||
@@ -93,21 +94,21 @@ public class ChunkPosWrapper extends AbstractChunkPosWrapper
|
||||
{
|
||||
return LevelPosUtil.convert(LodUtil.CHUNK_DETAIL_LEVEL, chunkPos.z, LodUtil.REGION_DETAIL_LEVEL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLong() {
|
||||
return chunkPos.toLong();
|
||||
}
|
||||
|
||||
public ChunkPos getChunkPos()
|
||||
{
|
||||
return chunkPos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLong() {
|
||||
return chunkPos.toLong();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
// If the object is compared with itself then return true
|
||||
// If the object is compared with itself then return true
|
||||
if (o == this) {
|
||||
return true;
|
||||
}
|
||||
@@ -133,4 +134,5 @@ public class ChunkPosWrapper extends AbstractChunkPosWrapper
|
||||
return new BlockPosWrapper(blockPos.getX(), blockPos.getY(), blockPos.getZ());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -33,57 +33,52 @@ import net.minecraft.world.level.levelgen.Heightmap;
|
||||
*/
|
||||
public class ChunkWrapper implements IChunkWrapper
|
||||
{
|
||||
private final ChunkAccess chunk;
|
||||
private final LevelReader lightSource;
|
||||
|
||||
|
||||
public ChunkWrapper(ChunkAccess chunk, LevelReader lightSource)
|
||||
{
|
||||
this.chunk = chunk;
|
||||
this.lightSource = lightSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHeight(){
|
||||
return chunk.getHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinBuildHeight()
|
||||
{
|
||||
return chunk.getMinBuildHeight();
|
||||
}
|
||||
@Override
|
||||
public int getMaxBuildHeight()
|
||||
{
|
||||
return chunk.getMaxBuildHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHeightMapValue(int xRel, int zRel)
|
||||
{
|
||||
return chunk.getOrCreateHeightmapUnprimed(WrapperUtil.DEFAULT_HEIGHTMAP).getFirstAvailable(xRel, zRel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBiomeWrapper getBiome(int x, int y, int z)
|
||||
{
|
||||
#if MC_VERSION_1_18_2
|
||||
return BiomeWrapper.getBiomeWrapper(chunk.getNoiseBiome(
|
||||
QuartPos.fromBlock(x), QuartPos.fromBlock(y), QuartPos.fromBlock(z)).value());
|
||||
#elif MC_VERSION_1_18_1
|
||||
return BiomeWrapper.getBiomeWrapper(chunk.getNoiseBiome(
|
||||
QuartPos.fromBlock(x), QuartPos.fromBlock(y), QuartPos.fromBlock(z)));
|
||||
#endif
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBlockDetailWrapper getBlockDetail(int x, int y, int z) {
|
||||
BlockPos pos = new BlockPos(x,y,z);
|
||||
BlockState blockState = chunk.getBlockState(pos);
|
||||
IBlockDetailWrapper blockDetail = BlockDetailMap.getOrMakeBlockDetailCache(blockState, pos, lightSource);
|
||||
return blockDetail == BlockDetailWrapper.NULL_BLOCK_DETAIL ? null : blockDetail;
|
||||
}
|
||||
private final ChunkAccess chunk;
|
||||
private final LevelReader lightSource;
|
||||
|
||||
|
||||
public ChunkWrapper(ChunkAccess chunk, LevelReader lightSource)
|
||||
{
|
||||
this.chunk = chunk;
|
||||
this.lightSource = lightSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHeight(){
|
||||
return chunk.getHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinBuildHeight()
|
||||
{
|
||||
return chunk.getMinBuildHeight();
|
||||
}
|
||||
@Override
|
||||
public int getMaxBuildHeight()
|
||||
{
|
||||
return chunk.getMaxBuildHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHeightMapValue(int xRel, int zRel)
|
||||
{
|
||||
return chunk.getOrCreateHeightmapUnprimed(WrapperUtil.DEFAULT_HEIGHTMAP).getFirstAvailable(xRel, zRel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBiomeWrapper getBiome(int x, int y, int z)
|
||||
{
|
||||
return BiomeWrapper.getBiomeWrapper(chunk.getBiomes().getNoiseBiome(
|
||||
QuartPos.fromBlock(x), QuartPos.fromBlock(y), QuartPos.fromBlock(z)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBlockDetailWrapper getBlockDetail(int x, int y, int z) {
|
||||
BlockPos pos = new BlockPos(x,y,z);
|
||||
BlockState blockState = chunk.getBlockState(pos);
|
||||
IBlockDetailWrapper blockDetail = BlockDetailMap.getOrMakeBlockDetailCache(blockState, pos, lightSource);
|
||||
return blockDetail == BlockDetailWrapper.NULL_BLOCK_DETAIL ? null : blockDetail;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBlockDetailWrapper getBlockDetailAtFace(int x, int y, int z, LodDirection dir) {
|
||||
@@ -97,112 +92,113 @@ public class ChunkWrapper implements IChunkWrapper
|
||||
blockState = lightSource.getBlockState(pos);
|
||||
}
|
||||
if (blockState == null || blockState.isAir()) return null;
|
||||
IBlockDetailWrapper blockDetail = BlockDetailMap.getOrMakeBlockDetailCache(blockState, pos, lightSource);
|
||||
IBlockDetailWrapper blockDetail = BlockDetailMap.getOrMakeBlockDetailCache(blockState, pos, lightSource);
|
||||
return blockDetail == BlockDetailWrapper.NULL_BLOCK_DETAIL ? null : blockDetail;
|
||||
}
|
||||
|
||||
public ChunkAccess getChunk() {
|
||||
return chunk;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getChunkPosX(){
|
||||
return chunk.getPos().x;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getChunkPosZ(){
|
||||
return chunk.getPos().z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRegionPosX(){
|
||||
return LevelPosUtil.convert(LodUtil.CHUNK_DETAIL_LEVEL, chunk.getPos().x, LodUtil.REGION_DETAIL_LEVEL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRegionPosZ(){
|
||||
return LevelPosUtil.convert(LodUtil.CHUNK_DETAIL_LEVEL, chunk.getPos().z, LodUtil.REGION_DETAIL_LEVEL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxY(int x, int z) {
|
||||
return chunk.getHeight(Heightmap.Types.MOTION_BLOCKING, Math.floorMod(x, 16), Math.floorMod(z, 16));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxX(){
|
||||
return chunk.getPos().getMaxBlockX();
|
||||
}
|
||||
@Override
|
||||
public int getMaxZ(){
|
||||
return chunk.getPos().getMaxBlockZ();
|
||||
}
|
||||
@Override
|
||||
public int getMinX(){
|
||||
return chunk.getPos().getMinBlockX();
|
||||
}
|
||||
@Override
|
||||
public int getMinZ() {
|
||||
return chunk.getPos().getMinBlockZ();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLongChunkPos() {
|
||||
return chunk.getPos().toLong();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLightCorrect(){
|
||||
//return true;
|
||||
if (chunk instanceof LevelChunk) {
|
||||
return ((LevelChunk) chunk).isClientLightReady();
|
||||
}
|
||||
return chunk.isLightCorrect();
|
||||
}
|
||||
|
||||
public boolean isWaterLogged(int x, int y, int z)
|
||||
{
|
||||
BlockState blockState = chunk.getBlockState(new BlockPos(x,y,z));
|
||||
|
||||
//This type of block is always in water
|
||||
return (!(blockState.getBlock() instanceof LiquidBlockContainer) && (blockState.getBlock() instanceof SimpleWaterloggedBlock))
|
||||
&& (blockState.hasProperty(BlockStateProperties.WATERLOGGED) && blockState.getValue(BlockStateProperties.WATERLOGGED));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEmittedBrightness(int x, int y, int z)
|
||||
{
|
||||
return chunk.getLightEmission(new BlockPos(x,y,z));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBlockLight(int x, int y, int z) {
|
||||
if (lightSource == null) return -1;
|
||||
return lightSource.getBrightness(LightLayer.BLOCK, new BlockPos(x,y,z));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSkyLight(int x, int y, int z) {
|
||||
if (lightSource == null) return -1;
|
||||
return lightSource.getBrightness(LightLayer.SKY, new BlockPos(x,y,z));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean doesNearbyChunksExist() {
|
||||
if (lightSource instanceof LightedWorldGenRegion) return true;
|
||||
for (int dx = -1; dx <= 1; dx++) {
|
||||
for (int dz = -1; dz <= 1; dz++) {
|
||||
if (dx==0 && dz==0) continue;
|
||||
if (lightSource.getChunk(dx+getChunkPosX(), dz+getChunkPosZ(), ChunkStatus.BIOMES, false) == null) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public LevelReader getColorResolver()
|
||||
{
|
||||
return lightSource;
|
||||
}
|
||||
|
||||
|
||||
public ChunkAccess getChunk() {
|
||||
return chunk;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getChunkPosX(){
|
||||
return chunk.getPos().x;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getChunkPosZ(){
|
||||
return chunk.getPos().z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRegionPosX(){
|
||||
return LevelPosUtil.convert(LodUtil.CHUNK_DETAIL_LEVEL, chunk.getPos().x, LodUtil.REGION_DETAIL_LEVEL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRegionPosZ(){
|
||||
return LevelPosUtil.convert(LodUtil.CHUNK_DETAIL_LEVEL, chunk.getPos().z, LodUtil.REGION_DETAIL_LEVEL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxY(int x, int z) {
|
||||
return chunk.getHeight(Heightmap.Types.MOTION_BLOCKING, Math.floorMod(x, 16), Math.floorMod(z, 16));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxX(){
|
||||
return chunk.getPos().getMaxBlockX();
|
||||
}
|
||||
@Override
|
||||
public int getMaxZ(){
|
||||
return chunk.getPos().getMaxBlockZ();
|
||||
}
|
||||
@Override
|
||||
public int getMinX(){
|
||||
return chunk.getPos().getMinBlockX();
|
||||
}
|
||||
@Override
|
||||
public int getMinZ() {
|
||||
return chunk.getPos().getMinBlockZ();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLongChunkPos() {
|
||||
return chunk.getPos().toLong();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLightCorrect(){
|
||||
return true;
|
||||
// TODO
|
||||
// if (chunk instanceof LevelChunk) {
|
||||
// return ((LevelChunk) chunk).isClientLightReady();
|
||||
// }
|
||||
// return chunk.isLightCorrect();
|
||||
}
|
||||
|
||||
public boolean isWaterLogged(int x, int y, int z)
|
||||
{
|
||||
BlockState blockState = chunk.getBlockState(new BlockPos(x,y,z));
|
||||
|
||||
//This type of block is always in water
|
||||
return (!(blockState.getBlock() instanceof LiquidBlockContainer) && (blockState.getBlock() instanceof SimpleWaterloggedBlock))
|
||||
&& (blockState.hasProperty(BlockStateProperties.WATERLOGGED) && blockState.getValue(BlockStateProperties.WATERLOGGED));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEmittedBrightness(int x, int y, int z)
|
||||
{
|
||||
return chunk.getLightEmission(new BlockPos(x,y,z));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBlockLight(int x, int y, int z) {
|
||||
if (lightSource == null) return -1;
|
||||
return lightSource.getBrightness(LightLayer.BLOCK, new BlockPos(x,y,z));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSkyLight(int x, int y, int z) {
|
||||
if (lightSource == null) return -1;
|
||||
return lightSource.getBrightness(LightLayer.SKY, new BlockPos(x,y,z));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean doesNearbyChunksExist() {
|
||||
if (lightSource instanceof LightedWorldGenRegion) return true;
|
||||
for (int dx = -1; dx <= 1; dx++) {
|
||||
for (int dz = -1; dz <= 1; dz++) {
|
||||
if (dx==0 && dz==0) continue;
|
||||
if (lightSource.getChunk(dx+getChunkPosX(), dz+getChunkPosZ(), ChunkStatus.BIOMES, false) == null) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public LevelReader getColorResolver()
|
||||
{
|
||||
return lightSource;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -379,7 +379,7 @@ public abstract class ConfigGui
|
||||
// Just put this here for the future
|
||||
config.setComment("_Version", " DONT TOUCH THIS, IF YOU DO THEN CONFIG FILE WOULD BREAK");
|
||||
config.set("_Versions", ModInfo.VERSION);
|
||||
|
||||
|
||||
|
||||
// Puts everything into its variable
|
||||
for (EntryInfo info : entries) {
|
||||
@@ -753,10 +753,10 @@ public abstract class ConfigGui
|
||||
|
||||
// Only for 1.17 and over
|
||||
// Remove in 1.16 and below
|
||||
@Override
|
||||
public List<? extends NarratableEntry> narratables()
|
||||
{
|
||||
return children;
|
||||
}
|
||||
@Override
|
||||
public List<? extends NarratableEntry> narratables()
|
||||
{
|
||||
return children;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+89
-89
@@ -15,47 +15,47 @@ import com.seibel.lod.common.Config;
|
||||
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 IMultiplayer multiplayer;
|
||||
public final IAdvanced advanced;
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public IGraphics graphics()
|
||||
{
|
||||
return graphics;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public IWorldGenerator worldGenerator()
|
||||
{
|
||||
return worldGenerator;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public IMultiplayer multiplayer() {
|
||||
return multiplayer;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public IAdvanced advanced()
|
||||
{
|
||||
return advanced;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean getOptionsButton()
|
||||
{
|
||||
@@ -67,8 +67,8 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
|
||||
ConfigGui.editSingleOption.getEntry("optionsButton").value = newOptionsButton;
|
||||
ConfigGui.editSingleOption.saveOption("optionsButton");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//================//
|
||||
// Client Configs //
|
||||
//================//
|
||||
@@ -79,8 +79,8 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
|
||||
multiplayer = new Multiplayer();
|
||||
advanced = new Advanced();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//==================//
|
||||
// Graphics Configs //
|
||||
//==================//
|
||||
@@ -89,36 +89,36 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
|
||||
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();
|
||||
fogQuality = new FogQuality();
|
||||
advancedGraphics = new AdvancedGraphics();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public static class Quality implements IQuality
|
||||
{
|
||||
@Override
|
||||
@@ -132,8 +132,8 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
|
||||
ConfigGui.editSingleOption.getEntry("client.graphics.quality.drawResolution").value = newHorizontalResolution;
|
||||
ConfigGui.editSingleOption.saveOption("client.graphics.quality.drawResolution");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public int getLodChunkRenderDistance()
|
||||
{
|
||||
@@ -145,8 +145,8 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
|
||||
ConfigGui.editSingleOption.getEntry("client.graphics.quality.lodChunkRenderDistance").value = newLodChunkRenderDistance;
|
||||
ConfigGui.editSingleOption.saveOption("client.graphics.quality.lodChunkRenderDistance");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public VerticalQuality getVerticalQuality()
|
||||
{
|
||||
@@ -158,8 +158,8 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
|
||||
ConfigGui.editSingleOption.getEntry("client.graphics.quality.verticalQuality").value = newVerticalQuality;
|
||||
ConfigGui.editSingleOption.saveOption("client.graphics.quality.verticalQuality");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public int getHorizontalScale()
|
||||
{
|
||||
@@ -171,8 +171,8 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
|
||||
ConfigGui.editSingleOption.getEntry("client.graphics.quality.horizontalScale").value = newHorizontalScale;
|
||||
ConfigGui.editSingleOption.saveOption("client.graphics.quality.horizontalScale");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public HorizontalQuality getHorizontalQuality()
|
||||
{
|
||||
@@ -184,7 +184,7 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
|
||||
ConfigGui.editSingleOption.getEntry("client.graphics.quality.horizontalQuality").value = newHorizontalQuality;
|
||||
ConfigGui.editSingleOption.saveOption("client.graphics.quality.horizontalQuality");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public DropoffQuality getDropoffQuality() {
|
||||
return Config.Client.Graphics.Quality.dropoffQuality;
|
||||
@@ -206,8 +206,8 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
|
||||
ConfigGui.editSingleOption.saveOption("client.graphics.quality.lodBiomeBlending");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public static class FogQuality implements IFogQuality
|
||||
{
|
||||
public final IAdvancedFog advancedFog;
|
||||
@@ -228,36 +228,36 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
|
||||
ConfigGui.editSingleOption.getEntry("client.graphics.fogQuality.fogDistance").value = newFogDistance;
|
||||
ConfigGui.editSingleOption.saveOption("client.graphics.fogQuality.fogDistance");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public FogDrawMode getFogDrawMode()
|
||||
{
|
||||
return Config.Client.Graphics.FogQuality.fogDrawMode;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setFogDrawMode(FogDrawMode setFogDrawMode)
|
||||
{
|
||||
ConfigGui.editSingleOption.getEntry("client.graphics.fogQuality.fogDrawMode").value = setFogDrawMode;
|
||||
ConfigGui.editSingleOption.saveOption("client.graphics.fogQuality.fogDrawMode");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public FogColorMode getFogColorMode()
|
||||
{
|
||||
return Config.Client.Graphics.FogQuality.fogColorMode;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setFogColorMode(FogColorMode newFogColorMode)
|
||||
{
|
||||
ConfigGui.editSingleOption.getEntry("client.graphics.fogQuality.fogColorMode").value = newFogColorMode;
|
||||
ConfigGui.editSingleOption.saveOption("client.graphics.fogQuality.fogColorMode");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean getDisableVanillaFog()
|
||||
{
|
||||
@@ -342,7 +342,7 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
|
||||
public IHeightFog heightFog() {
|
||||
return heightFog;
|
||||
}
|
||||
|
||||
|
||||
public static class HeightFog implements IHeightFog {
|
||||
|
||||
@Override
|
||||
@@ -431,8 +431,8 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public static class AdvancedGraphics implements IAdvancedGraphics
|
||||
{
|
||||
@Override
|
||||
@@ -446,8 +446,8 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
|
||||
ConfigGui.editSingleOption.getEntry("client.graphics.advancedGraphics.disableDirectionalCulling").value = newDisableDirectionalCulling;
|
||||
ConfigGui.editSingleOption.saveOption("client.graphics.advancedGraphics.disableDirectionalCulling");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public VanillaOverdraw getVanillaOverdraw()
|
||||
{
|
||||
@@ -482,7 +482,7 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
|
||||
ConfigGui.editSingleOption.getEntry("client.graphics.advancedGraphics.backsideCullingRange").value = newBacksideCullingRange;
|
||||
ConfigGui.editSingleOption.saveOption("client.graphics.advancedGraphics.backsideCullingRange");
|
||||
}*/
|
||||
|
||||
|
||||
@Override
|
||||
public boolean getUseExtendedNearClipPlane()
|
||||
{
|
||||
@@ -494,7 +494,7 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
|
||||
ConfigGui.editSingleOption.getEntry("client.graphics.advancedGraphics.useExtendedNearClipPlane").value = newUseExtendedNearClipPlane;
|
||||
ConfigGui.editSingleOption.saveOption("client.graphics.advancedGraphics.useExtendedNearClipPlane");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public double getBrightnessMultiplier()
|
||||
{
|
||||
@@ -506,7 +506,7 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
|
||||
ConfigGui.editSingleOption.getEntry("client.graphics.advancedGraphics.brightnessMultiplier").value = newBrightnessMultiplier;
|
||||
ConfigGui.editSingleOption.saveOption("client.graphics.advancedGraphics.brightnessMultiplier");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public double getSaturationMultiplier()
|
||||
{
|
||||
@@ -544,10 +544,10 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//========================//
|
||||
// WorldGenerator Configs //
|
||||
//========================//
|
||||
@@ -564,8 +564,8 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
|
||||
ConfigGui.editSingleOption.getEntry("client.worldGenerator.generationPriority").value = newGenerationPriority;
|
||||
ConfigGui.editSingleOption.saveOption("client.worldGenerator.generationPriority");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public DistanceGenerationMode getDistanceGenerationMode()
|
||||
{
|
||||
@@ -590,8 +590,8 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
|
||||
ConfigGui.editSingleOption.getEntry("client.worldGenerator.allowUnstableFeatureGeneration").value = newAllowUnstableFeatureGeneration;
|
||||
ConfigGui.editSingleOption.saveOption("client.worldGenerator.allowUnstableFeatureGeneration");
|
||||
}*/
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public BlocksToAvoid getBlocksToAvoid()
|
||||
{
|
||||
@@ -626,9 +626,9 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
|
||||
ConfigGui.editSingleOption.saveOption("client.worldGenerator.lightGenerationMode");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//=====================//
|
||||
// Multiplayer Configs //
|
||||
//=====================//
|
||||
@@ -645,13 +645,13 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
|
||||
ConfigGui.editSingleOption.getEntry("client.multiplayer.serverFolderNameMode").value = newServerFolderNameMode;
|
||||
ConfigGui.editSingleOption.saveOption("client.multiplayer.serverFolderNameMode");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public double getMultiDimensionRequiredSimilarity()
|
||||
{
|
||||
return Config.Client.Multiplayer.multiDimensionRequiredSimilarity;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setMultiDimensionRequiredSimilarity(double newMultiDimensionMinimumSimilarityPercent)
|
||||
{
|
||||
@@ -659,9 +659,9 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
|
||||
ConfigGui.editSingleOption.saveOption("client.multiplayer.multiDimensionMinimumSimilarityPercent");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//============================//
|
||||
// AdvancedModOptions Configs //
|
||||
//============================//
|
||||
@@ -670,22 +670,22 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
|
||||
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()
|
||||
{
|
||||
@@ -699,7 +699,7 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
|
||||
debugging = new Debugging();
|
||||
buffers = new Buffers();
|
||||
}
|
||||
|
||||
|
||||
public static class Threading implements IThreading
|
||||
{
|
||||
@Override
|
||||
@@ -713,8 +713,8 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
|
||||
ConfigGui.editSingleOption.getEntry("client.advanced.threading.numberOfWorldGenerationThreads").value = newNumberOfWorldGenerationThreads;
|
||||
ConfigGui.editSingleOption.saveOption("client.advanced.threading.numberOfWorldGenerationThreads");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public int getNumberOfBufferBuilderThreads()
|
||||
{
|
||||
@@ -727,10 +727,10 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
|
||||
ConfigGui.editSingleOption.saveOption("client.advanced.threading.numberOfBufferBuilderThreads");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//===============//
|
||||
// Debug Options //
|
||||
//===============//
|
||||
@@ -758,7 +758,7 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
|
||||
ConfigGui.editSingleOption.getEntry("client.advanced.debugging.rendererType").value = newRenderType;
|
||||
ConfigGui.editSingleOption.saveOption("client.advanced.debugging.rendererType");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public DebugMode getDebugMode()
|
||||
{
|
||||
@@ -770,8 +770,8 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
|
||||
ConfigGui.editSingleOption.getEntry("client.advanced.debugging.debugMode").value = newDebugMode;
|
||||
ConfigGui.editSingleOption.saveOption("client.advanced.debugging.debugMode");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean getDebugKeybindingsEnabled()
|
||||
{
|
||||
@@ -894,11 +894,11 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public static class Buffers implements IBuffers
|
||||
{
|
||||
|
||||
|
||||
@Override
|
||||
public GpuUploadMethod getGpuUploadMethod()
|
||||
{
|
||||
@@ -910,8 +910,8 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
|
||||
ConfigGui.editSingleOption.getEntry("client.advanced.buffers.gpuUploadMethod").value = newDisableVanillaFog;
|
||||
ConfigGui.editSingleOption.saveOption("client.advanced.buffers.gpuUploadMethod");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public int getGpuUploadPerMegabyteInMilliseconds()
|
||||
{
|
||||
@@ -922,8 +922,8 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
|
||||
ConfigGui.editSingleOption.getEntry("client.advanced.buffers.gpuUploadPerMegabyteInMilliseconds").value = newMilliseconds;
|
||||
ConfigGui.editSingleOption.saveOption("client.advanced.buffers.gpuUploadPerMegabyteInMilliseconds");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public BufferRebuildTimes getRebuildTimes()
|
||||
{
|
||||
|
||||
+5
-2
@@ -27,6 +27,7 @@ import com.mojang.blaze3d.platform.NativeImage;
|
||||
import com.mojang.blaze3d.platform.Window;
|
||||
import com.seibel.lod.core.ModInfo;
|
||||
import com.seibel.lod.core.api.ApiShared;
|
||||
import com.seibel.lod.core.api.ClientApi;
|
||||
import com.seibel.lod.core.enums.LodDirection;
|
||||
import com.seibel.lod.core.util.LodUtil;
|
||||
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||
@@ -63,10 +64,11 @@ import net.minecraft.world.level.dimension.DimensionType;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* A singleton that wraps the Minecraft object.
|
||||
* A singleton that wraps the Minecraft class
|
||||
* to allow for easier movement between Minecraft versions.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 3-5-2022
|
||||
* @version 9-16-2021
|
||||
*/
|
||||
public class MinecraftClientWrapper implements IMinecraftClientWrapper
|
||||
{
|
||||
@@ -197,6 +199,7 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper
|
||||
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// Simple gets //
|
||||
//=============//
|
||||
|
||||
+233
-245
@@ -10,9 +10,12 @@ import com.mojang.blaze3d.platform.NativeImage;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.seibel.lod.common.wrappers.misc.LightMapWrapper;
|
||||
import com.seibel.lod.core.api.ApiShared;
|
||||
import com.seibel.lod.core.api.ClientApi;
|
||||
import com.seibel.lod.core.handlers.dependencyInjection.ModAccessorHandler;
|
||||
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
|
||||
import com.seibel.lod.core.util.LodUtil;
|
||||
|
||||
import com.seibel.lod.core.wrapperInterfaces.misc.ILightMapWrapper;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||
import net.minecraft.client.renderer.LightTexture;
|
||||
|
||||
import com.mojang.math.Vector3f;
|
||||
@@ -52,96 +55,96 @@ import net.minecraft.world.phys.Vec3;
|
||||
*/
|
||||
public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
|
||||
{
|
||||
public static final MinecraftRenderWrapper INSTANCE = new MinecraftRenderWrapper();
|
||||
|
||||
private static final Minecraft MC = Minecraft.getInstance();
|
||||
private static final GameRenderer GAME_RENDERER = MC.gameRenderer;
|
||||
private static final IWrapperFactory FACTORY = WrapperFactory.INSTANCE;
|
||||
|
||||
@Override
|
||||
public Vec3f getLookAtVector()
|
||||
{
|
||||
Camera camera = GAME_RENDERER.getMainCamera();
|
||||
Vector3f cameraDir = camera.getLookVector();
|
||||
return new Vec3f(cameraDir.x(), cameraDir.y(), cameraDir.z());
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractBlockPosWrapper getCameraBlockPosition()
|
||||
{
|
||||
Camera camera = GAME_RENDERER.getMainCamera();
|
||||
BlockPos blockPos = camera.getBlockPosition();
|
||||
return new BlockPosWrapper(blockPos.getX(), blockPos.getY(), blockPos.getZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playerHasBlindnessEffect()
|
||||
{
|
||||
return MC.player.getActiveEffectsMap().get(MobEffects.BLINDNESS) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vec3d getCameraExactPosition()
|
||||
{
|
||||
Camera camera = GAME_RENDERER.getMainCamera();
|
||||
Vec3 projectedView = camera.getPosition();
|
||||
|
||||
return new Vec3d(projectedView.x, projectedView.y, projectedView.z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mat4f getDefaultProjectionMatrix(float partialTicks)
|
||||
{
|
||||
return McObjectConverter.Convert(GAME_RENDERER.getProjectionMatrix(GAME_RENDERER.getFov(GAME_RENDERER.getMainCamera(), partialTicks, true)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getGamma()
|
||||
{
|
||||
return MC.options.gamma;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Color getFogColor(float partialTicks) {
|
||||
FogRenderer.setupColor(GAME_RENDERER.getMainCamera(), partialTicks, MC.level, 1, GAME_RENDERER.getDarkenWorldAmount(partialTicks));
|
||||
float[] colorValues = RenderSystem.getShaderFogColor();
|
||||
return new Color(colorValues[0], colorValues[1], colorValues[2], colorValues[3]);
|
||||
}
|
||||
// getSpecialFogColor() is the same as getFogColor()
|
||||
|
||||
@Override
|
||||
public Color getSkyColor() {
|
||||
if (MC.level.dimensionType().hasSkyLight()) {
|
||||
Vec3 colorValues = MC.level.getSkyColor(MC.gameRenderer.getMainCamera().getPosition(), MC.getFrameTime());
|
||||
return new Color((float) colorValues.x, (float) colorValues.y, (float) colorValues.z);
|
||||
} else
|
||||
return new Color(0, 0, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getFov(float partialTicks)
|
||||
{
|
||||
return GAME_RENDERER.getFov(GAME_RENDERER.getMainCamera(), partialTicks, true);
|
||||
}
|
||||
|
||||
/** Measured in chunks */
|
||||
@Override
|
||||
public int getRenderDistance()
|
||||
{
|
||||
return MC.options.getEffectiveRenderDistance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getScreenWidth()
|
||||
{
|
||||
return MC.getWindow().getWidth();
|
||||
}
|
||||
@Override
|
||||
public int getScreenHeight()
|
||||
{
|
||||
return MC.getWindow().getHeight();
|
||||
}
|
||||
|
||||
public static final MinecraftRenderWrapper INSTANCE = new MinecraftRenderWrapper();
|
||||
|
||||
private static final Minecraft MC = Minecraft.getInstance();
|
||||
private static final GameRenderer GAME_RENDERER = MC.gameRenderer;
|
||||
private static final IWrapperFactory FACTORY = WrapperFactory.INSTANCE;
|
||||
|
||||
@Override
|
||||
public Vec3f getLookAtVector()
|
||||
{
|
||||
Camera camera = GAME_RENDERER.getMainCamera();
|
||||
Vector3f cameraDir = camera.getLookVector();
|
||||
return new Vec3f(cameraDir.x(), cameraDir.y(), cameraDir.z());
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractBlockPosWrapper getCameraBlockPosition()
|
||||
{
|
||||
Camera camera = GAME_RENDERER.getMainCamera();
|
||||
BlockPos blockPos = camera.getBlockPosition();
|
||||
return new BlockPosWrapper(blockPos.getX(), blockPos.getY(), blockPos.getZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playerHasBlindnessEffect()
|
||||
{
|
||||
return MC.player.getActiveEffectsMap().get(MobEffects.BLINDNESS) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vec3d getCameraExactPosition()
|
||||
{
|
||||
Camera camera = GAME_RENDERER.getMainCamera();
|
||||
Vec3 projectedView = camera.getPosition();
|
||||
|
||||
return new Vec3d(projectedView.x, projectedView.y, projectedView.z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mat4f getDefaultProjectionMatrix(float partialTicks)
|
||||
{
|
||||
return McObjectConverter.Convert(GAME_RENDERER.getProjectionMatrix(GAME_RENDERER.getFov(GAME_RENDERER.getMainCamera(), partialTicks, true)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getGamma()
|
||||
{
|
||||
return MC.options.gamma;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Color getFogColor(float partialTicks) {
|
||||
FogRenderer.setupColor(GAME_RENDERER.getMainCamera(), partialTicks, MC.level, 1, GAME_RENDERER.getDarkenWorldAmount(partialTicks));
|
||||
float[] colorValues = RenderSystem.getShaderFogColor();
|
||||
return new Color(colorValues[0], colorValues[1], colorValues[2], colorValues[3]);
|
||||
}
|
||||
// getSpecialFogColor() is the same as getFogColor()
|
||||
|
||||
@Override
|
||||
public Color getSkyColor() {
|
||||
if (MC.level.dimensionType().hasSkyLight()) {
|
||||
Vec3 colorValues = MC.level.getSkyColor(MC.gameRenderer.getMainCamera().getPosition(), MC.getFrameTime());
|
||||
return new Color((float) colorValues.x, (float) colorValues.y, (float) colorValues.z);
|
||||
} else
|
||||
return new Color(0, 0, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getFov(float partialTicks)
|
||||
{
|
||||
return GAME_RENDERER.getFov(GAME_RENDERER.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();
|
||||
}
|
||||
|
||||
private RenderTarget getRenderTarget() {
|
||||
RenderTarget r = null; //MC.levelRenderer.getCloudsTarget();
|
||||
return r!=null ? r : MC.getMainRenderTarget();
|
||||
@@ -162,81 +165,76 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
|
||||
return getRenderTarget().viewHeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns the ChunkPos of all chunks that Minecraft
|
||||
* is going to render this frame. <br><br>
|
||||
* <p>
|
||||
*/
|
||||
|
||||
public boolean usingBackupGetVanillaRenderedChunks = false;
|
||||
@Override
|
||||
public HashSet<AbstractChunkPosWrapper> getVanillaRenderedChunks()
|
||||
{
|
||||
ISodiumAccessor sodium = ModAccessorHandler.get(ISodiumAccessor.class);
|
||||
if (sodium != null)
|
||||
{
|
||||
return sodium.getNormalRenderedChunks();
|
||||
}
|
||||
IOptifineAccessor optifine = ModAccessorHandler.get(IOptifineAccessor.class);
|
||||
if (optifine != null)
|
||||
{
|
||||
HashSet<AbstractChunkPosWrapper> pos = optifine.getNormalRenderedChunks();
|
||||
if (pos == null)
|
||||
pos = getMaximumRenderedChunks();
|
||||
return pos;
|
||||
}
|
||||
if (!usingBackupGetVanillaRenderedChunks) {
|
||||
try {
|
||||
LevelRenderer levelRenderer = MC.levelRenderer;
|
||||
LinkedHashSet<LevelRenderer.RenderChunkInfo> chunks = levelRenderer.renderChunkStorage.get().renderChunks;
|
||||
return (chunks.stream().map((chunk) -> {
|
||||
#if MC_VERSION_1_18_2
|
||||
AABB chunkBoundingBox = chunk.chunk.getBoundingBox();
|
||||
#elif MC_VERSION_1_18_1
|
||||
AABB chunkBoundingBox = chunk.chunk.bb;
|
||||
#endif
|
||||
return FACTORY.createChunkPos(Math.floorDiv((int) chunkBoundingBox.minX, 16),
|
||||
Math.floorDiv((int) chunkBoundingBox.minZ, 16));
|
||||
}).collect(Collectors.toCollection(HashSet::new)));
|
||||
} catch (LinkageError e) {
|
||||
try {
|
||||
MinecraftClientWrapper.INSTANCE.sendChatMessage(
|
||||
"\u00A7e\u00A7l\u00A7uWARNING: Distant Horizons: getVanillaRenderedChunks method failed."
|
||||
+ " Using Backup Method.");
|
||||
MinecraftClientWrapper.INSTANCE.sendChatMessage(
|
||||
"\u00A7eOverdraw prevention will be worse than normal.");
|
||||
} catch (Exception e2) {}
|
||||
ApiShared.LOGGER.error("getVanillaRenderedChunks Error: ", e);
|
||||
usingBackupGetVanillaRenderedChunks = true;
|
||||
}
|
||||
}
|
||||
return getMaximumRenderedChunks();
|
||||
}
|
||||
/**
|
||||
* This method returns the ChunkPos of all chunks that Minecraft
|
||||
* is going to render this frame. <br><br>
|
||||
* <p>
|
||||
*/
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public int[] getLightmapPixels()
|
||||
{
|
||||
LightTexture tex = GAME_RENDERER.lightTexture();
|
||||
//tex.tick(); // This call makes no sense, but it fixes pause menu flicker bug
|
||||
NativeImage lightMapPixels = tex.lightTexture.getPixels();
|
||||
LightMapWrapper lightMap = new LightMapWrapper(lightMapPixels);
|
||||
|
||||
|
||||
int lightMapHeight = getLightmapTextureHeight();
|
||||
int lightMapWidth = getLightmapTextureWidth();
|
||||
|
||||
int[] pixels = new int[lightMapWidth * lightMapHeight];
|
||||
for (int u = 0; u < lightMapWidth; u++)
|
||||
{
|
||||
for (int v = 0; v < lightMapWidth; v++)
|
||||
{
|
||||
// this could probably be kept as a int, but
|
||||
// it is easier to test and see the colors when debugging this way.
|
||||
// When creating a new release this should be changed to the int version.
|
||||
int col = lightMap.getLightValue(u, v);
|
||||
|
||||
// these should both create a totally white image
|
||||
public boolean usingBackupGetVanillaRenderedChunks = false;
|
||||
@Override
|
||||
public HashSet<AbstractChunkPosWrapper> getVanillaRenderedChunks()
|
||||
{
|
||||
ISodiumAccessor sodium = ModAccessorHandler.get(ISodiumAccessor.class);
|
||||
if (sodium != null)
|
||||
{
|
||||
return sodium.getNormalRenderedChunks();
|
||||
}
|
||||
IOptifineAccessor optifine = ModAccessorHandler.get(IOptifineAccessor.class);
|
||||
if (optifine != null)
|
||||
{
|
||||
HashSet<AbstractChunkPosWrapper> pos = optifine.getNormalRenderedChunks();
|
||||
if (pos == null)
|
||||
pos = getMaximumRenderedChunks();
|
||||
return pos;
|
||||
}
|
||||
if (!usingBackupGetVanillaRenderedChunks) {
|
||||
try {
|
||||
LevelRenderer levelRenderer = MC.levelRenderer;
|
||||
ObjectArrayList<LevelRenderer.RenderChunkInfo> chunks = levelRenderer.renderChunks;
|
||||
return (chunks.stream().map((chunk) -> {
|
||||
AABB chunkBoundingBox = chunk.chunk.bb;
|
||||
return FACTORY.createChunkPos(Math.floorDiv((int) chunkBoundingBox.minX, 16),
|
||||
Math.floorDiv((int) chunkBoundingBox.minZ, 16));
|
||||
}).collect(Collectors.toCollection(HashSet::new)));
|
||||
} catch (LinkageError e) {
|
||||
try {
|
||||
MinecraftClientWrapper.INSTANCE.sendChatMessage(
|
||||
"\u00A7e\u00A7l\u00A7uWARNING: Distant Horizons: getVanillaRenderedChunks method failed."
|
||||
+ " Using Backup Method.");
|
||||
MinecraftClientWrapper.INSTANCE.sendChatMessage(
|
||||
"\u00A7eOverdraw prevention will be worse than normal.");
|
||||
} catch (Exception e2) {}
|
||||
ApiShared.LOGGER.error("getVanillaRenderedChunks Error: ", e);
|
||||
usingBackupGetVanillaRenderedChunks = true;
|
||||
}
|
||||
}
|
||||
return getMaximumRenderedChunks();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getLightmapPixels()
|
||||
{
|
||||
LightTexture tex = GAME_RENDERER.lightTexture();
|
||||
tex.tick(); // This call makes no sense, but it fixes pause menu flicker bug
|
||||
NativeImage lightMapPixels = tex.lightPixels;
|
||||
LightMapWrapper lightMap = new LightMapWrapper(lightMapPixels);
|
||||
|
||||
|
||||
int lightMapHeight = getLightmapTextureHeight();
|
||||
int lightMapWidth = getLightmapTextureWidth();
|
||||
|
||||
int[] pixels = new int[lightMapWidth * lightMapHeight];
|
||||
for (int u = 0; u < lightMapWidth; u++)
|
||||
{
|
||||
for (int v = 0; v < lightMapWidth; v++)
|
||||
{
|
||||
// this could probably be kept as a int, but
|
||||
// it is easier to test and see the colors when debugging this way.
|
||||
// When creating a new release this should be changed to the int version.
|
||||
int col = lightMap.getLightValue(u, v);
|
||||
|
||||
// these should both create a totally white image
|
||||
// int col =
|
||||
// Integer.MAX_VALUE;
|
||||
// int col =
|
||||
@@ -250,88 +248,78 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
|
||||
// ((c.getGreen() & 0xFF) << 8) | // green
|
||||
// ((c.getBlue() & 0xFF)) | // red
|
||||
// ((c.getAlpha() & 0xFF) << 24); // alpha
|
||||
|
||||
// 2D array stored in a 1D array.
|
||||
// Thank you Tim from College ;)
|
||||
pixels[u * lightMapWidth + v] = col;
|
||||
}
|
||||
}
|
||||
|
||||
return pixels;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ILightMapWrapper getLightmapWrapper() {
|
||||
return new LightMapWrapper(GAME_RENDERER.lightTexture());
|
||||
}
|
||||
// 2D array stored in a 1D array.
|
||||
// Thank you Tim from College ;)
|
||||
pixels[u * lightMapWidth + v] = col;
|
||||
}
|
||||
}
|
||||
|
||||
return pixels;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getLightmapTextureHeight()
|
||||
{
|
||||
int height = -1;
|
||||
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public int getLightmapTextureHeight()
|
||||
{
|
||||
int height = -1;
|
||||
|
||||
LightTexture lightTexture = GAME_RENDERER.lightTexture();
|
||||
if (lightTexture != null)
|
||||
{
|
||||
NativeImage tex = lightTexture.lightPixels;
|
||||
if (tex != null)
|
||||
{
|
||||
height = tex.getHeight();
|
||||
}
|
||||
}
|
||||
|
||||
return height;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public int getLightmapTextureWidth()
|
||||
{
|
||||
int width = -1;
|
||||
|
||||
LightTexture lightTexture = GAME_RENDERER.lightTexture();
|
||||
if (lightTexture != null)
|
||||
{
|
||||
NativeImage tex = lightTexture.lightPixels;
|
||||
if (tex != null)
|
||||
{
|
||||
width = tex.getWidth();
|
||||
}
|
||||
}
|
||||
|
||||
return width;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public int getLightmapGLFormat() {
|
||||
int glFormat = -1;
|
||||
|
||||
LightTexture lightTexture = GAME_RENDERER.lightTexture();
|
||||
if (lightTexture != null) {
|
||||
NativeImage tex = lightTexture.lightPixels;
|
||||
if (tex != null) {
|
||||
glFormat = tex.format().glFormat();
|
||||
}
|
||||
}
|
||||
|
||||
return glFormat;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFogStateSpecial() {
|
||||
Entity entity = GAME_RENDERER.getMainCamera().getEntity();
|
||||
boolean isBlind = (entity instanceof LivingEntity) && ((LivingEntity)entity).hasEffect(MobEffects.BLINDNESS);
|
||||
return GAME_RENDERER.getMainCamera().getFluidInCamera() != FogType.NONE || isBlind;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean tryDisableVanillaFog() {
|
||||
return true; // Handled via MixinFogRenderer in both forge and fabric
|
||||
}
|
||||
LightTexture lightTexture = GAME_RENDERER.lightTexture();
|
||||
if (lightTexture != null)
|
||||
{
|
||||
NativeImage tex = lightTexture.lightPixels;
|
||||
if (tex != null)
|
||||
{
|
||||
height = tex.getHeight();
|
||||
}
|
||||
}
|
||||
|
||||
return height;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLightmapTextureWidth()
|
||||
{
|
||||
int width = -1;
|
||||
|
||||
LightTexture lightTexture = GAME_RENDERER.lightTexture();
|
||||
if (lightTexture != null)
|
||||
{
|
||||
NativeImage tex = lightTexture.lightPixels;
|
||||
if (tex != null)
|
||||
{
|
||||
width = tex.getWidth();
|
||||
}
|
||||
}
|
||||
|
||||
return width;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getLightmapGLFormat() {
|
||||
int glFormat = -1;
|
||||
|
||||
LightTexture lightTexture = GAME_RENDERER.lightTexture();
|
||||
if (lightTexture != null) {
|
||||
NativeImage tex = lightTexture.lightPixels;
|
||||
if (tex != null) {
|
||||
glFormat = tex.format().glFormat();
|
||||
}
|
||||
}
|
||||
|
||||
return glFormat;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFogStateSpecial() {
|
||||
Entity entity = GAME_RENDERER.getMainCamera().getEntity();
|
||||
boolean isBlind = (entity instanceof LivingEntity) && ((LivingEntity)entity).hasEffect(MobEffects.BLINDNESS);
|
||||
return GAME_RENDERER.getMainCamera().getFluidInCamera() != FogType.NONE || isBlind;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean tryDisableVanillaFog() {
|
||||
return true; // Handled via MixinFogRenderer in both forge and fabric
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@ package com.seibel.lod.common.wrappers.misc;
|
||||
|
||||
import com.mojang.blaze3d.platform.NativeImage;
|
||||
import com.seibel.lod.core.wrapperInterfaces.misc.ILightMapWrapper;
|
||||
import net.minecraft.client.renderer.LightTexture;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
|
||||
/**
|
||||
* @author James Seibel
|
||||
@@ -13,17 +11,11 @@ public class LightMapWrapper implements ILightMapWrapper
|
||||
{
|
||||
static NativeImage lightMap = null;
|
||||
|
||||
private LightTexture tex;
|
||||
|
||||
public LightMapWrapper(NativeImage newLightMap)
|
||||
{
|
||||
lightMap = newLightMap;
|
||||
}
|
||||
|
||||
public LightMapWrapper(LightTexture lightTexture) {
|
||||
tex = lightTexture;
|
||||
}
|
||||
|
||||
public static void setLightMap(NativeImage newLightMap)
|
||||
{
|
||||
lightMap = newLightMap;
|
||||
@@ -34,14 +26,4 @@ public class LightMapWrapper implements ILightMapWrapper
|
||||
{
|
||||
return lightMap.getPixelRGBA(skyLight, blockLight);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bind() {
|
||||
GL32.glBindTexture(GL32.GL_TEXTURE_2D, tex.lightTexture.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unbind() {
|
||||
GL32.glBindTexture(GL32.GL_TEXTURE_2D, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ public class BiomeWrapper implements IBiomeWrapper
|
||||
{
|
||||
|
||||
public static final ConcurrentMap<Biome, BiomeWrapper> biomeWrapperMap = new ConcurrentHashMap<>();
|
||||
private final Biome biome;
|
||||
private Biome biome;
|
||||
|
||||
public BiomeWrapper(Biome biome)
|
||||
{
|
||||
@@ -121,12 +121,12 @@ public class BiomeWrapper implements IBiomeWrapper
|
||||
|
||||
return colorInt;
|
||||
}
|
||||
|
||||
@Override public String getName()
|
||||
{
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return biome.toString();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getGrassTint(int x, int z)
|
||||
{
|
||||
|
||||
@@ -34,7 +34,7 @@ import net.minecraft.world.level.dimension.DimensionType;
|
||||
public class DimensionTypeWrapper implements IDimensionTypeWrapper
|
||||
{
|
||||
private static final ConcurrentMap<DimensionType, DimensionTypeWrapper> dimensionTypeWrapperMap = new ConcurrentHashMap<>();
|
||||
private final DimensionType dimensionType;
|
||||
private DimensionType dimensionType;
|
||||
|
||||
public DimensionTypeWrapper(DimensionType dimensionType)
|
||||
{
|
||||
|
||||
@@ -51,12 +51,12 @@ public class WorldWrapper implements IWorldWrapper
|
||||
private static final ConcurrentMap<LevelAccessor, WorldWrapper> worldWrapperMap = new ConcurrentHashMap<>();
|
||||
private final LevelAccessor world;
|
||||
public final WorldType worldType;
|
||||
|
||||
|
||||
|
||||
|
||||
public WorldWrapper(LevelAccessor newWorld)
|
||||
{
|
||||
world = newWorld;
|
||||
|
||||
|
||||
if (world.getClass() == ServerLevel.class)
|
||||
worldType = WorldType.ServerWorld;
|
||||
else if (world.getClass() == ClientLevel.class)
|
||||
@@ -64,8 +64,8 @@ public class WorldWrapper implements IWorldWrapper
|
||||
else
|
||||
worldType = WorldType.Unknown;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Nullable
|
||||
public static WorldWrapper getWorldWrapper(LevelAccessor world)
|
||||
{
|
||||
@@ -73,109 +73,109 @@ public class WorldWrapper implements IWorldWrapper
|
||||
//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(int x, int y, int z)
|
||||
{
|
||||
return world.getBrightness(LightLayer.BLOCK, new BlockPos(x,y,z));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getSkyLight(int x, int y, int z)
|
||||
{
|
||||
return world.getBrightness(LightLayer.SKY, new BlockPos(x,y,z));
|
||||
}
|
||||
|
||||
|
||||
public LevelAccessor getWorld()
|
||||
{
|
||||
return world;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean hasCeiling()
|
||||
{
|
||||
return world.dimensionType().hasCeiling();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean hasSkyLight()
|
||||
{
|
||||
return world.dimensionType().hasSkyLight();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getHeight()
|
||||
{
|
||||
return world.getHeight();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public short getMinHeight()
|
||||
{
|
||||
return (short) world.getMinBuildHeight();
|
||||
}
|
||||
|
||||
|
||||
/** @throws UnsupportedOperationException if the WorldWrapper isn't for a ServerWorld */
|
||||
@Override
|
||||
public File getSaveFolder() throws UnsupportedOperationException
|
||||
{
|
||||
if (worldType != WorldType.ServerWorld)
|
||||
throw new UnsupportedOperationException("getSaveFolder can only be called for ServerWorlds.");
|
||||
|
||||
|
||||
ServerChunkCache chunkSource = ((ServerLevel) world).getChunkSource();
|
||||
return chunkSource.getDataStorage().dataFolder;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/** @throws UnsupportedOperationException if the WorldWrapper isn't for a ServerWorld */
|
||||
public ServerLevel getServerWorld() throws UnsupportedOperationException
|
||||
{
|
||||
if (worldType != WorldType.ServerWorld)
|
||||
throw new UnsupportedOperationException("getSaveFolder can only be called for ServerWorlds.");
|
||||
|
||||
|
||||
return (ServerLevel) world;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getSeaLevel()
|
||||
{
|
||||
// TODO this is depreciated, what should we use instead?
|
||||
return world.getSeaLevel();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public IChunkWrapper tryGetChunk(AbstractChunkPosWrapper pos) {
|
||||
ChunkAccess chunk = world.getChunk(pos.getX(), pos.getZ(), ChunkStatus.EMPTY, false);
|
||||
if (chunk == null) return null;
|
||||
return new ChunkWrapper(chunk, world);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean hasChunkLoaded(int chunkX, int chunkZ) {
|
||||
// world.hasChunk(chunkX, chunkZ); THIS DOES NOT WORK FOR CLIENT LEVEL CAUSE MOJANG ALWAYS RETURN TRUE FOR THAT!
|
||||
@@ -183,5 +183,5 @@ public class WorldWrapper implements IWorldWrapper
|
||||
return source.hasChunk(chunkX, chunkZ);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
+28
-38
@@ -19,21 +19,24 @@
|
||||
|
||||
package com.seibel.lod.common.wrappers.worldGeneration;
|
||||
|
||||
import com.seibel.lod.core.logging.ConfigBasedLogger;
|
||||
import com.seibel.lod.core.logging.ConfigBasedSpamLogger;
|
||||
import com.seibel.lod.core.api.ApiShared;
|
||||
import com.seibel.lod.core.api.ClientApi;
|
||||
import com.seibel.lod.core.builders.lodBuilding.LodBuilder;
|
||||
import com.seibel.lod.core.builders.lodBuilding.LodBuilderConfig;
|
||||
import com.seibel.lod.core.enums.config.DistanceGenerationMode;
|
||||
import com.seibel.lod.core.enums.config.LightGenerationMode;
|
||||
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
|
||||
import com.seibel.lod.core.logging.ConfigBasedLogger;
|
||||
import com.seibel.lod.core.logging.ConfigBasedSpamLogger;
|
||||
import com.seibel.lod.core.objects.lod.LodDimension;
|
||||
import com.seibel.lod.core.util.gridList.ArrayGridList;
|
||||
import com.seibel.lod.core.util.LodThreadFactory;
|
||||
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
|
||||
import com.seibel.lod.core.util.gridList.ArrayGridList;
|
||||
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
|
||||
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.worldGeneration.AbstractBatchGenerationEnvionmentWrapper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.Duration;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
@@ -68,7 +71,6 @@ import net.minecraft.world.level.chunk.UpgradeData;
|
||||
import net.minecraft.world.level.levelgen.DebugLevelSource;
|
||||
import net.minecraft.world.level.levelgen.FlatLevelSource;
|
||||
import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.world.level.lighting.LevelLightEngine;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
@@ -99,7 +101,6 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
||||
public static final ConfigBasedLogger LOAD_LOGGER =
|
||||
new ConfigBasedLogger(LogManager.getLogger("LodWorldGen"),
|
||||
() -> CONFIG.client().advanced().debugging().debugSwitch().getLogWorldGenLoadEvent());
|
||||
|
||||
//TODO: Make actual proper support for StarLight
|
||||
|
||||
public static class PrefEvent
|
||||
@@ -240,7 +241,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
||||
public static final int RANGE_TO_RANGE_EMPTY_EXTENSION = 1;
|
||||
public int unknownExceptionCount = 0;
|
||||
public long lastExceptionTriggerTime = 0;
|
||||
|
||||
|
||||
public static final LodThreadFactory threadFactory = new LodThreadFactory("Gen-Worker-Thread", Thread.MIN_PRIORITY);
|
||||
|
||||
public static ThreadLocal<Boolean> isDistantGeneratorThread = new ThreadLocal<>();
|
||||
@@ -255,7 +256,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
||||
|
||||
public ExecutorService executors = Executors.newFixedThreadPool(
|
||||
CONFIG.client().advanced().threading().getNumberOfWorldGenerationThreads(), threadFactory);
|
||||
|
||||
|
||||
public <T> T joinSync(CompletableFuture<T> f) {
|
||||
if (!unsafeThreadingRecorded && !f.isDone()) {
|
||||
EVENT_LOGGER.error("Unsafe Threading in Chunk Generator: ", new RuntimeException("Concurrent future"));
|
||||
@@ -264,7 +265,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
||||
}
|
||||
return f.join();
|
||||
}
|
||||
|
||||
|
||||
public void resizeThreadPool(int newThreadCount)
|
||||
{
|
||||
executors = Executors.newFixedThreadPool(newThreadCount,
|
||||
@@ -294,7 +295,6 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
||||
unknownExceptionCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Update all current out standing jobs
|
||||
Iterator<GenerationEvent> iter = events.iterator();
|
||||
while (iter.hasNext())
|
||||
@@ -350,10 +350,11 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
||||
generator instanceof FlatLevelSource)) {
|
||||
EVENT_LOGGER.warn("Unknown Chunk Generator detected: [{}], Distant Generation May Fail!", generator.getClass());
|
||||
EVENT_LOGGER.warn("If it does crash, set Distant Generation to OFF or Generation Mode to None.");
|
||||
ApiShared.LOGGER.warn("Unknown Chunk Generator detected: {}", generator.getClass());
|
||||
}
|
||||
params = new GlobalParameters((ServerLevel) ((WorldWrapper) serverlevel).getWorld(), lodBuilder, lodDim);
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("resource")
|
||||
public static ChunkAccess loadOrMakeChunk(ChunkPos chunkPos, ServerLevel level, LevelLightEngine lightEngine)
|
||||
{
|
||||
@@ -368,15 +369,15 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
||||
}
|
||||
if (chunkData == null)
|
||||
{
|
||||
return new ProtoChunk(chunkPos, UpgradeData.EMPTY, level, level.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), null);
|
||||
return new ProtoChunk(chunkPos, UpgradeData.EMPTY, level);
|
||||
}
|
||||
else
|
||||
{
|
||||
try {
|
||||
return ChunkLoader.read(level, lightEngine, chunkPos, chunkData);
|
||||
return ChunkLoader.read(level, lightEngine, chunkPos, chunkData);
|
||||
} catch (Exception e) {
|
||||
LOAD_LOGGER.error("DistantHorizons: Couldn't load chunk {}", chunkPos, e);
|
||||
return new ProtoChunk(chunkPos, UpgradeData.EMPTY, level, level.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), null);
|
||||
return new ProtoChunk(chunkPos, UpgradeData.EMPTY, level);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -395,6 +396,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
||||
int refRange = e.range + RANGE_TO_RANGE_EMPTY_EXTENSION;
|
||||
int refOffsetX = e.pos.x - refRange;
|
||||
int refOffsetZ = e.pos.z - refRange;
|
||||
|
||||
try
|
||||
{
|
||||
adaptor = new LightGetterAdaptor(params.level);
|
||||
@@ -414,8 +416,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
||||
// Continue...
|
||||
}
|
||||
if (target == null)
|
||||
target = new ProtoChunk(chunkPos, UpgradeData.EMPTY, params.level,
|
||||
params.biomes, null);
|
||||
target = new ProtoChunk(chunkPos, UpgradeData.EMPTY, params.level);
|
||||
return target;
|
||||
};
|
||||
|
||||
@@ -462,39 +463,31 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
for (int oy = 0; oy < genChunks.gridSize; oy++)
|
||||
{
|
||||
for (int ox = 0; ox < genChunks.gridSize; ox++)
|
||||
{
|
||||
ChunkAccess target = genChunks.get(ox, oy);
|
||||
ChunkWrapper wrappedChunk = new ChunkWrapper(target, region);
|
||||
if (!wrappedChunk.isLightCorrect()) {
|
||||
throw new RuntimeException("The generated chunk somehow has isLightCorrect() returning false");
|
||||
}
|
||||
|
||||
target.setLightCorrect(true);
|
||||
//if (target instanceof LevelChunk)
|
||||
// ((LevelChunk) target).setClientLightReady(true);
|
||||
boolean isFull = target.getStatus() == ChunkStatus.FULL || target instanceof LevelChunk;
|
||||
boolean isPartial = target.isOldNoiseGeneration();
|
||||
//boolean isPartial = target.isOldNoiseGeneration();
|
||||
if (isFull)
|
||||
{
|
||||
LOAD_LOGGER.info("Detected full existing chunk at {}", target.getPos());
|
||||
params.lodBuilder.generateLodNodeFromChunk(params.lodDim, wrappedChunk,
|
||||
params.lodBuilder.generateLodNodeFromChunk(params.lodDim, new ChunkWrapper(target, region),
|
||||
new LodBuilderConfig(DistanceGenerationMode.FULL), true, e.genAllDetails);
|
||||
}
|
||||
else if (isPartial)
|
||||
{
|
||||
LOAD_LOGGER.info("Detected old existing chunk at {}", target.getPos());
|
||||
params.lodBuilder.generateLodNodeFromChunk(params.lodDim, wrappedChunk,
|
||||
new LodBuilderConfig(generationMode), true, e.genAllDetails);
|
||||
}
|
||||
else if (target.getStatus() == ChunkStatus.EMPTY && generationMode == DistanceGenerationMode.NONE)
|
||||
{
|
||||
params.lodBuilder.generateLodNodeFromChunk(params.lodDim,wrappedChunk,
|
||||
params.lodBuilder.generateLodNodeFromChunk(params.lodDim, new ChunkWrapper(target, region),
|
||||
LodBuilderConfig.getFillVoidConfig(), true, e.genAllDetails);
|
||||
}
|
||||
else
|
||||
{
|
||||
params.lodBuilder.generateLodNodeFromChunk(params.lodDim, wrappedChunk,
|
||||
params.lodBuilder.generateLodNodeFromChunk(params.lodDim, new ChunkWrapper(target, region),
|
||||
new LodBuilderConfig(generationMode), true, e.genAllDetails);
|
||||
}
|
||||
if (e.lightMode == LightGenerationMode.FANCY || isFull)
|
||||
@@ -512,9 +505,9 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
||||
PREF_LOGGER.infoInc("{}", e.tParam.perf);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void generateDirect(GenerationEvent e, ArrayGridList<ChunkAccess> subRange, Steps step,
|
||||
LightedWorldGenRegion region)
|
||||
LightedWorldGenRegion region)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -558,6 +551,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
||||
stepFeatures.generateGroup(e.tParam, region, subRange);
|
||||
e.pEvent.featureNano = System.nanoTime();
|
||||
e.refreshTimeout();
|
||||
return;
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -571,10 +565,6 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
||||
{
|
||||
if (p instanceof ProtoChunk)
|
||||
((ProtoChunk) p).setLightCorrect(true);
|
||||
if (p instanceof LevelChunk) {
|
||||
((LevelChunk) p).setLightCorrect(true);
|
||||
((LevelChunk) p).setClientLightReady(true);
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
+2
-3
@@ -7,9 +7,9 @@ import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment.PrefEvent;
|
||||
import com.seibel.lod.core.api.ApiShared;
|
||||
import com.seibel.lod.core.api.ClientApi;
|
||||
import com.seibel.lod.core.enums.config.LightGenerationMode;
|
||||
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
|
||||
import com.seibel.lod.core.util.LodUtil;
|
||||
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
|
||||
import com.seibel.lod.core.wrapperInterfaces.worldGeneration.AbstractBatchGenerationEnvionmentWrapper.Steps;
|
||||
|
||||
@@ -70,9 +70,9 @@ public final class GenerationEvent
|
||||
|
||||
public boolean terminate()
|
||||
{
|
||||
future.cancel(true);
|
||||
ApiShared.LOGGER.info("======================DUMPING ALL THREADS FOR WORLD GEN=======================");
|
||||
BatchGenerationEnvironment.threadFactory.dumpAllThreadStacks();
|
||||
future.cancel(true);
|
||||
return future.isCancelled();
|
||||
}
|
||||
|
||||
@@ -100,7 +100,6 @@ public final class GenerationEvent
|
||||
public void refreshTimeout()
|
||||
{
|
||||
nanotime = System.nanoTime();
|
||||
LodUtil.checkInterruptsUnchecked();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+2
-6
@@ -11,9 +11,7 @@ import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ThreadedLevelLightEngine;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.biome.BiomeManager;
|
||||
import net.minecraft.world.level.chunk.ChunkGenerator;
|
||||
import net.minecraft.world.level.chunk.storage.ChunkScanAccess;
|
||||
import net.minecraft.world.level.levelgen.WorldGenSettings;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager;
|
||||
import net.minecraft.world.level.storage.WorldData;
|
||||
@@ -22,7 +20,7 @@ public final class GlobalParameters
|
||||
{
|
||||
public final ChunkGenerator generator;
|
||||
public final StructureManager structures;
|
||||
public final BiomeManager biomeManager;
|
||||
//public final BiomeManager biomeManager;
|
||||
public final WorldGenSettings worldGenSettings;
|
||||
public final ThreadedLevelLightEngine lightEngine;
|
||||
public final LodBuilder lodBuilder;
|
||||
@@ -30,7 +28,6 @@ public final class GlobalParameters
|
||||
public final Registry<Biome> biomes;
|
||||
public final RegistryAccess registry;
|
||||
public final long worldSeed;
|
||||
public final ChunkScanAccess chunkScanner;
|
||||
public final ServerLevel level; // TODO: Figure out a way to remove this. Maybe ClientLevel also works?
|
||||
public final DataFixer fixerUpper;
|
||||
|
||||
@@ -46,10 +43,9 @@ public final class GlobalParameters
|
||||
registry = server.registryAccess();
|
||||
biomes = registry.registryOrThrow(Registry.BIOME_REGISTRY);
|
||||
worldSeed = worldGenSettings.seed();
|
||||
biomeManager = new BiomeManager(level, BiomeManager.obfuscateSeed(worldSeed));
|
||||
//biomeManager = new BiomeManager(level, BiomeManager.obfuscateSeed(worldSeed));
|
||||
structures = server.getStructureManager();
|
||||
generator = level.getChunkSource().getGenerator();
|
||||
chunkScanner = level.getChunkSource().chunkScanner();
|
||||
fixerUpper = server.getFixerUpper();
|
||||
}
|
||||
}
|
||||
+3
-9
@@ -7,14 +7,12 @@ import com.seibel.lod.common.wrappers.worldGeneration.mimicObject.WorldGenStruct
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.level.WorldGenLevel;
|
||||
import net.minecraft.world.level.levelgen.WorldGenSettings;
|
||||
import net.minecraft.world.level.levelgen.structure.StructureCheck;
|
||||
|
||||
public final class ThreadedParameters
|
||||
{
|
||||
private static final ThreadLocal<ThreadedParameters> localParam = new ThreadLocal<ThreadedParameters>();
|
||||
final ServerLevel level;
|
||||
public WorldGenStructFeatManager structFeat = null;
|
||||
public final StructureCheck structCheck;
|
||||
boolean isValid = true;
|
||||
public final PerfCalculator perf = new PerfCalculator();
|
||||
|
||||
@@ -36,13 +34,9 @@ public final class ThreadedParameters
|
||||
private ThreadedParameters(GlobalParameters param)
|
||||
{
|
||||
level = param.level;
|
||||
structCheck = new StructureCheck(param.chunkScanner, param.registry, param.structures,
|
||||
param.level.dimension(), param.generator, level, param.generator.getBiomeSource(), param.worldSeed,
|
||||
param.fixerUpper);
|
||||
structFeat = new WorldGenStructFeatManager(level, param.worldGenSettings);
|
||||
}
|
||||
|
||||
public void makeStructFeat(WorldGenLevel genLevel, GlobalParameters param)
|
||||
{
|
||||
structFeat = new WorldGenStructFeatManager(param.worldGenSettings, genLevel, structCheck);
|
||||
public void makeStructFeat(WorldGenLevel genLevel, GlobalParameters param) {
|
||||
structFeat = new WorldGenStructFeatManager(param.worldGenSettings, genLevel);
|
||||
}
|
||||
}
|
||||
+96
-271
@@ -1,145 +1,74 @@
|
||||
|
||||
package com.seibel.lod.common.wrappers.worldGeneration.mimicObject;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.Dynamic;
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment;
|
||||
import com.seibel.lod.core.api.ApiShared;
|
||||
|
||||
import com.seibel.lod.core.logging.ConfigBasedLogger;
|
||||
import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
|
||||
import it.unimi.dsi.fastutil.longs.LongSet;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
#if MC_VERSION_1_18_2
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.RegistryAccess;
|
||||
import net.minecraft.world.level.levelgen.feature.ConfiguredStructureFeature;
|
||||
#endif
|
||||
|
||||
import com.seibel.lod.core.logging.ConfigBasedLogger;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.core.SectionPos;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.ListTag;
|
||||
import net.minecraft.nbt.NbtOps;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraft.world.level.ChunkTickList;
|
||||
import net.minecraft.world.level.LightLayer;
|
||||
import net.minecraft.world.level.TickList;
|
||||
import net.minecraft.world.level.WorldGenLevel;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.biome.Biomes;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.chunk.ChunkBiomeContainer;
|
||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||
import net.minecraft.world.level.chunk.DataLayer;
|
||||
import net.minecraft.world.level.chunk.LevelChunk;
|
||||
import net.minecraft.world.level.chunk.LevelChunkSection;
|
||||
import net.minecraft.world.level.chunk.PalettedContainer;
|
||||
import net.minecraft.world.level.chunk.ProtoTickList;
|
||||
import net.minecraft.world.level.chunk.UpgradeData;
|
||||
import net.minecraft.world.level.levelgen.Heightmap;
|
||||
import net.minecraft.world.level.levelgen.blending.BlendingData;
|
||||
import net.minecraft.world.level.levelgen.feature.StructureFeature;
|
||||
import net.minecraft.world.level.levelgen.structure.StructureStart;
|
||||
import net.minecraft.world.level.levelgen.structure.pieces.StructurePieceSerializationContext;
|
||||
import net.minecraft.world.level.lighting.LevelLightEngine;
|
||||
import net.minecraft.world.level.material.Fluid;
|
||||
import net.minecraft.world.ticks.LevelChunkTicks;
|
||||
import net.minecraft.world.level.material.Fluids;
|
||||
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
public class ChunkLoader
|
||||
{
|
||||
private static final Codec<PalettedContainer<BlockState>> BLOCK_STATE_CODEC = PalettedContainer.codec(Block.BLOCK_STATE_REGISTRY, BlockState.CODEC, PalettedContainer.Strategy.SECTION_STATES, Blocks.AIR.defaultBlockState());
|
||||
public class ChunkLoader {
|
||||
private static final ConfigBasedLogger LOGGER = BatchGenerationEnvironment.LOAD_LOGGER;
|
||||
private static final String TAG_UPGRADE_DATA = "UpgradeData";
|
||||
private static final String BLOCK_TICKS_TAG = "block_ticks";
|
||||
private static final String FLUID_TICKS_TAG = "fluid_ticks";
|
||||
|
||||
private static BlendingData readBlendingData(CompoundTag chunkData)
|
||||
{
|
||||
BlendingData blendingData = null;
|
||||
if (chunkData.contains("blending_data", 10))
|
||||
{
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
Dynamic<CompoundTag> blendingDataTag = new Dynamic(NbtOps.INSTANCE, chunkData.getCompound("blending_data"));
|
||||
blendingData = BlendingData.CODEC.parse(blendingDataTag).resultOrPartial(LOGGER::error).orElse(null);
|
||||
}
|
||||
return blendingData;
|
||||
}
|
||||
|
||||
private static LevelChunkSection[] readSections(LevelAccessor level, LevelLightEngine lightEngine, ChunkPos chunkPos, CompoundTag chunkData)
|
||||
{
|
||||
Registry<Biome> biomes = level.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY);
|
||||
#if MC_VERSION_1_18_1
|
||||
Codec<PalettedContainer<Biome>> biomeCodec = PalettedContainer.codec(
|
||||
biomes, biomes.byNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, biomes.getOrThrow(Biomes.PLAINS));
|
||||
#elif MC_VERSION_1_18_2
|
||||
Codec<PalettedContainer<Holder<Biome>>> biomeCodec = PalettedContainer.codec(
|
||||
biomes.asHolderIdMap(), biomes.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, biomes.getHolderOrThrow(Biomes.PLAINS));
|
||||
#endif
|
||||
|
||||
int i = level.getSectionsCount();
|
||||
LevelChunkSection[] chunkSections = new LevelChunkSection[i];
|
||||
|
||||
boolean isLightOn = chunkData.getBoolean("isLightOn");
|
||||
boolean hasSkyLight = level.dimensionType().hasSkyLight();
|
||||
ListTag tagSections = chunkData.getList("sections", 10);
|
||||
|
||||
for (int j = 0; j < tagSections.size(); ++j)
|
||||
{
|
||||
CompoundTag tagSection = tagSections.getCompound(j);
|
||||
byte sectionYPos = tagSection.getByte("Y");
|
||||
int sectionId = level.getSectionIndexFromSectionY(sectionYPos);
|
||||
if (sectionId >= 0 && sectionId < chunkSections.length)
|
||||
{
|
||||
PalettedContainer<BlockState> blockStateContainer;
|
||||
#if MC_VERSION_1_18_1
|
||||
PalettedContainer<Biome> biomeContainer;
|
||||
#elif MC_VERSION_1_18_2
|
||||
PalettedContainer<Holder<Biome>> biomeContainer;
|
||||
#endif
|
||||
|
||||
blockStateContainer = tagSection.contains("block_states", 10)
|
||||
? BLOCK_STATE_CODEC.parse(NbtOps.INSTANCE, tagSection.getCompound("block_states")).promotePartial(string -> logErrors(chunkPos, sectionYPos, string)).getOrThrow(false, LOGGER::error)
|
||||
: new PalettedContainer<BlockState>(Block.BLOCK_STATE_REGISTRY, Blocks.AIR.defaultBlockState(), PalettedContainer.Strategy.SECTION_STATES);
|
||||
|
||||
#if MC_VERSION_1_18_1
|
||||
biomeContainer = tagSection.contains("biomes", 10)
|
||||
? biomeCodec.parse(NbtOps.INSTANCE, tagSection.getCompound("biomes")).promotePartial(string -> logErrors(chunkPos, sectionYPos, string)).getOrThrow(false, LOGGER::error)
|
||||
: new PalettedContainer<Biome>(biomes, biomes.getOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES);
|
||||
#elif MC_VERSION_1_18_2
|
||||
biomeContainer = tagSection.contains("biomes", 10)
|
||||
? biomeCodec.parse(NbtOps.INSTANCE, tagSection.getCompound("biomes")).promotePartial(string -> logErrors(chunkPos, i, (String) string)).getOrThrow(false, LOGGER::error)
|
||||
: new PalettedContainer<Holder<Biome>>(biomes.asHolderIdMap(), biomes.getHolderOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES);
|
||||
#endif
|
||||
|
||||
|
||||
chunkSections[sectionId] = new LevelChunkSection(sectionYPos, blockStateContainer, biomeContainer);
|
||||
private static LevelChunkSection[] readSections(WorldGenLevel level, LevelLightEngine lightEngine,
|
||||
ChunkPos chunkPos, CompoundTag tagLevel) {
|
||||
boolean isLightOn = tagLevel.getBoolean("isLightOn");
|
||||
ListTag listTag = tagLevel.getList("Sections", 10);
|
||||
int i = level.getSectionsCount();
|
||||
LevelChunkSection[] levelChunkSections = new LevelChunkSection[i];
|
||||
boolean bl2 = level.getLevel().dimensionType().hasSkyLight();
|
||||
if (isLightOn)
|
||||
lightEngine.retainData(chunkPos, true);
|
||||
for (int j = 0; j < listTag.size(); j++) {
|
||||
CompoundTag compoundTag3 = listTag.getCompound(j);
|
||||
int k = compoundTag3.getByte("Y");
|
||||
if (compoundTag3.contains("Palette", 9) && compoundTag3.contains("BlockStates", 12)) {
|
||||
LevelChunkSection levelChunkSection = new LevelChunkSection(k << 4);
|
||||
levelChunkSection.getStates().read(compoundTag3.getList("Palette", 10),
|
||||
compoundTag3.getLongArray("BlockStates"));
|
||||
levelChunkSection.recalcBlockCounts();
|
||||
if (!levelChunkSection.isEmpty())
|
||||
levelChunkSections[level.getSectionIndexFromSectionY(k)] = levelChunkSection;
|
||||
}
|
||||
if (isLightOn) {
|
||||
if (compoundTag3.contains("BlockLight", 7))
|
||||
lightEngine.queueSectionData(LightLayer.BLOCK, SectionPos.of(chunkPos, k),
|
||||
new DataLayer(compoundTag3.getByteArray("BlockLight")), true);
|
||||
if (bl2 && compoundTag3.contains("SkyLight", 7))
|
||||
lightEngine.queueSectionData(LightLayer.SKY, SectionPos.of(chunkPos, k),
|
||||
new DataLayer(compoundTag3.getByteArray("SkyLight")), true);
|
||||
}
|
||||
|
||||
if (!isLightOn)
|
||||
continue;
|
||||
|
||||
if (tagSection.contains("BlockLight", 7))
|
||||
lightEngine.queueSectionData(LightLayer.BLOCK, SectionPos.of(chunkPos, sectionYPos), new DataLayer(tagSection.getByteArray("BlockLight")), true);
|
||||
if (hasSkyLight && tagSection.contains("SkyLight", 7))
|
||||
lightEngine.queueSectionData(LightLayer.SKY, SectionPos.of(chunkPos, sectionYPos), new DataLayer(tagSection.getByteArray("SkyLight")), true);
|
||||
}
|
||||
return chunkSections;
|
||||
return levelChunkSections;
|
||||
}
|
||||
|
||||
private static void readHeightmaps(LevelChunk chunk, CompoundTag chunkData)
|
||||
{
|
||||
|
||||
private static void readHeightmaps(LevelChunk chunk, CompoundTag chunkData) {
|
||||
CompoundTag tagHeightmaps = chunkData.getCompound("Heightmaps");
|
||||
for (Heightmap.Types type : ChunkStatus.FULL.heightmapsAfter())
|
||||
{
|
||||
for (Heightmap.Types type : ChunkStatus.FULL.heightmapsAfter()) {
|
||||
String heightmap = type.getSerializationKey();
|
||||
if (tagHeightmaps.contains(heightmap, 12))
|
||||
chunk.setHeightmap(type, tagHeightmaps.getLongArray(heightmap));
|
||||
@@ -147,178 +76,74 @@ public class ChunkLoader
|
||||
Heightmap.primeHeightmaps(chunk, ChunkStatus.FULL.heightmapsAfter());
|
||||
}
|
||||
|
||||
#if MC_VERSION_1_18_1
|
||||
private static Map<StructureFeature<?>, StructureStart<?>> unpackStructureStart(StructurePieceSerializationContext structurePieceSerializationContext, CompoundTag compoundTag, long l)
|
||||
{
|
||||
HashMap<StructureFeature<?>, StructureStart<?>> map = Maps.newHashMap();
|
||||
CompoundTag compoundTag2 = compoundTag.getCompound("starts");
|
||||
for (String string : compoundTag2.getAllKeys())
|
||||
{
|
||||
String string2 = string.toLowerCase(Locale.ROOT);
|
||||
StructureFeature<?> structureFeature = StructureFeature.STRUCTURES_REGISTRY.get(string2);
|
||||
if (structureFeature == null)
|
||||
{
|
||||
LOGGER.error("Unknown structure start: {}", (Object) string2);
|
||||
continue;
|
||||
}
|
||||
StructureStart<?> structureStart = StructureFeature.loadStaticStart(structurePieceSerializationContext, compoundTag2.getCompound(string), l);
|
||||
if (structureStart == null)
|
||||
continue;
|
||||
map.put(structureFeature, structureStart);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
private static Map<StructureFeature<?>, LongSet> unpackStructureReferences(ChunkPos chunkPos, CompoundTag compoundTag)
|
||||
{
|
||||
HashMap<StructureFeature<?>, LongSet> map = Maps.newHashMap();
|
||||
CompoundTag compoundTag2 = compoundTag.getCompound("References");
|
||||
for (String string : compoundTag2.getAllKeys())
|
||||
{
|
||||
String string2 = string.toLowerCase(Locale.ROOT);
|
||||
StructureFeature<?> structureFeature = StructureFeature.STRUCTURES_REGISTRY.get(string2);
|
||||
if (structureFeature == null)
|
||||
{
|
||||
LOGGER.warn("Found reference to unknown structure '{}' in chunk {}, discarding", (Object) string2, (Object) chunkPos);
|
||||
continue;
|
||||
}
|
||||
map.put(structureFeature, new LongOpenHashSet(Arrays.stream(compoundTag2.getLongArray(string)).filter(l ->
|
||||
{
|
||||
ChunkPos chunkPos2 = new ChunkPos(l);
|
||||
if (chunkPos2.getChessboardDistance(chunkPos) > 8)
|
||||
{
|
||||
LOGGER.warn("Found invalid structure reference [ {} @ {} ] for chunk {}.", (Object) string2, (Object) chunkPos2, (Object) chunkPos);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}).toArray()));
|
||||
}
|
||||
return map;
|
||||
}
|
||||
#elif MC_VERSION_1_18_2
|
||||
private static Map<ConfiguredStructureFeature<?, ?>, StructureStart> unpackStructureStart(StructurePieceSerializationContext structurePieceSerializationContext, CompoundTag compoundTag, long l) {
|
||||
Map<ConfiguredStructureFeature<?, ?>, StructureStart> map = Maps.newHashMap();
|
||||
Registry<ConfiguredStructureFeature<?, ?>> structStartRegistry = structurePieceSerializationContext.registryAccess().registryOrThrow(Registry.CONFIGURED_STRUCTURE_FEATURE_REGISTRY);
|
||||
CompoundTag compoundTag2 = compoundTag.getCompound("starts");
|
||||
for (String string : compoundTag2.getAllKeys()) {
|
||||
ResourceLocation resourceLocation = ResourceLocation.tryParse(string);
|
||||
ConfiguredStructureFeature<?, ?> structureFeature = structStartRegistry.get(resourceLocation);
|
||||
// String string2 = string.toLowerCase(Locale.ROOT);
|
||||
// ConfiguredStructureFeature<?, ?> structureFeature = StructureFeature.STRUCTURES_REGISTRY.get(string2);
|
||||
if (structureFeature == null) {
|
||||
LOGGER.error("Unknown structure start: {}", resourceLocation);
|
||||
continue;
|
||||
}
|
||||
StructureStart structureStart = StructureFeature.loadStaticStart(structurePieceSerializationContext, compoundTag2.getCompound(string), l);
|
||||
if (structureStart == null)
|
||||
continue;
|
||||
map.put(structureFeature, structureStart);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
private static Map<ConfiguredStructureFeature<?, ?>, LongSet> unpackStructureReferences(RegistryAccess registryAccess, ChunkPos chunkPos, CompoundTag compoundTag)
|
||||
{
|
||||
Map<ConfiguredStructureFeature<?, ?>, LongSet> map = Maps.newHashMap();
|
||||
Registry<ConfiguredStructureFeature<?, ?>> structRegistry = registryAccess.registryOrThrow(Registry.CONFIGURED_STRUCTURE_FEATURE_REGISTRY);
|
||||
CompoundTag compoundTag2 = compoundTag.getCompound("References");
|
||||
for (String string : compoundTag2.getAllKeys())
|
||||
{
|
||||
ResourceLocation resourceLocation = ResourceLocation.tryParse(string);
|
||||
ConfiguredStructureFeature<?, ?> structureFeature = structRegistry.get(resourceLocation);
|
||||
// String string2 = string.toLowerCase(Locale.ROOT);
|
||||
// ConfiguredStructureFeature<?, ?> structureFeature = StructureFeature.STRUCTURES_REGISTRY.get(string2);
|
||||
if (structureFeature == null)
|
||||
{
|
||||
LOGGER.warn("Found reference to unknown structure '{}' in chunk {}, discarding", resourceLocation, chunkPos);
|
||||
continue;
|
||||
}
|
||||
map.put(structureFeature, new LongOpenHashSet(Arrays.stream(compoundTag2.getLongArray(string)).filter(l ->
|
||||
{
|
||||
ChunkPos chunkPos2 = new ChunkPos(l);
|
||||
if (chunkPos2.getChessboardDistance(chunkPos) > 8)
|
||||
{
|
||||
LOGGER.warn("Found invalid structure reference [ {} @ {} ] for chunk {}.", resourceLocation, chunkPos2, chunkPos);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}).toArray()));
|
||||
}
|
||||
return map;
|
||||
}
|
||||
#endif
|
||||
|
||||
private static void readStructures(WorldGenLevel level, LevelChunk chunk, CompoundTag chunkData)
|
||||
{
|
||||
CompoundTag tagStructures = chunkData.getCompound("structures");
|
||||
chunk.setAllStarts(
|
||||
unpackStructureStart(StructurePieceSerializationContext.fromLevel(level.getLevel()), tagStructures, level.getSeed()));
|
||||
chunk.setAllReferences(unpackStructureReferences(#if MC_VERSION_1_18_2 level.registryAccess() ,#endif chunk.getPos(), tagStructures));
|
||||
}
|
||||
|
||||
private static void readPostPocessings(LevelChunk chunk, CompoundTag chunkData)
|
||||
{
|
||||
private static void readPostPocessings(LevelChunk chunk, CompoundTag chunkData) {
|
||||
ListTag tagPostProcessings = chunkData.getList("PostProcessing", 9);
|
||||
for (int n = 0; n < tagPostProcessings.size(); ++n)
|
||||
{
|
||||
for (int n = 0; n < tagPostProcessings.size(); ++n) {
|
||||
ListTag listTag3 = tagPostProcessings.getList(n);
|
||||
for (int o = 0; o < listTag3.size(); ++o)
|
||||
{
|
||||
for (int o = 0; o < listTag3.size(); ++o) {
|
||||
chunk.addPackedPostProcess(listTag3.getShort(o), n);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static ChunkStatus.ChunkType readChunkType(CompoundTag compoundTag)
|
||||
{
|
||||
return ChunkStatus.byName(compoundTag.getString("Status")).getChunkType();
|
||||
|
||||
public static ChunkStatus.ChunkType readChunkType(CompoundTag tagLevel) {
|
||||
ChunkStatus chunkStatus = ChunkStatus.byName(tagLevel.getString("Status"));
|
||||
if (chunkStatus != null) {
|
||||
return chunkStatus.getChunkType();
|
||||
}
|
||||
return ChunkStatus.ChunkType.PROTOCHUNK;
|
||||
}
|
||||
|
||||
public static LevelChunk read(WorldGenLevel level, LevelLightEngine lightEngine, ChunkPos chunkPos, CompoundTag chunkData)
|
||||
{
|
||||
|
||||
ChunkPos actualPos = new ChunkPos(chunkData.getInt("xPos"), chunkData.getInt("zPos"));
|
||||
if (!Objects.equals(chunkPos, actualPos))
|
||||
{
|
||||
|
||||
public static LevelChunk read(WorldGenLevel level, LevelLightEngine lightEngine, ChunkPos chunkPos,
|
||||
CompoundTag chunkData) {
|
||||
CompoundTag tagLevel = chunkData.getCompound("Level");
|
||||
|
||||
ChunkStatus.ChunkType chunkType = readChunkType(tagLevel);
|
||||
if (chunkType != ChunkStatus.ChunkType.LEVELCHUNK)
|
||||
return null;
|
||||
|
||||
ChunkPos actualPos = new ChunkPos(tagLevel.getInt("xPos"), tagLevel.getInt("zPos"));
|
||||
if (!Objects.equals(chunkPos, actualPos)) {
|
||||
LOGGER.error("Chunk file at {} is in the wrong location; Ignoring. (Expected {}, got {})", (Object) chunkPos, (Object) chunkPos, (Object) actualPos);
|
||||
return null;
|
||||
}
|
||||
|
||||
ChunkStatus.ChunkType chunkType = readChunkType(chunkData);
|
||||
BlendingData blendingData = readBlendingData(chunkData);
|
||||
if (chunkType == ChunkStatus.ChunkType.PROTOCHUNK && (blendingData == null || !blendingData.oldNoise()))
|
||||
return null;
|
||||
|
||||
// Prepare the light engine
|
||||
boolean isLightOn = chunkData.getBoolean("isLightOn");
|
||||
if (isLightOn)
|
||||
level.getLightEngine().retainData(chunkPos, true);
|
||||
|
||||
// Read params for making the LevelChunk
|
||||
UpgradeData upgradeData = chunkData.contains(TAG_UPGRADE_DATA, 10)
|
||||
? new UpgradeData(chunkData.getCompound(TAG_UPGRADE_DATA), level)
|
||||
|
||||
// ====================== Read params for making the LevelChunk
|
||||
// ============================
|
||||
ChunkBiomeContainer chunkBiomeContainer = new ChunkBiomeContainer(
|
||||
level.getLevel().registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), level, chunkPos,
|
||||
level.getLevel().getChunkSource().getGenerator().getBiomeSource(),
|
||||
tagLevel.contains("Biomes", 11) ? tagLevel.getIntArray("Biomes") : null);
|
||||
|
||||
UpgradeData upgradeData = tagLevel.contains("UpgradeData", 10)
|
||||
? new UpgradeData(tagLevel.getCompound("UpgradeData"), level)
|
||||
: UpgradeData.EMPTY;
|
||||
LevelChunkTicks<Block> blockTicks = LevelChunkTicks.load(chunkData.getList(BLOCK_TICKS_TAG, 10),
|
||||
string -> Registry.BLOCK.getOptional(ResourceLocation.tryParse(string)), chunkPos);
|
||||
LevelChunkTicks<Fluid> fluidTicks = LevelChunkTicks.load(chunkData.getList(FLUID_TICKS_TAG, 10),
|
||||
string -> Registry.FLUID.getOptional(ResourceLocation.tryParse(string)), chunkPos);
|
||||
long inhabitedTime = chunkData.getLong("InhabitedTime");
|
||||
LevelChunkSection[] chunkSections = readSections(level, lightEngine, actualPos, chunkData);
|
||||
|
||||
// Make chunk
|
||||
LevelChunk chunk = new LevelChunk((Level) level, chunkPos, upgradeData, blockTicks, fluidTicks, inhabitedTime, chunkSections, null, blendingData);
|
||||
|
||||
// Set some states after object creation
|
||||
chunk.setLightCorrect(isLightOn);
|
||||
readHeightmaps(chunk, chunkData);
|
||||
readStructures(level, chunk, chunkData);
|
||||
readPostPocessings(chunk, chunkData);
|
||||
|
||||
TickList<Block> blockTicks = tagLevel.contains("TileTicks", 9)
|
||||
? ChunkTickList.create(tagLevel.getList("TileTicks", 10), Registry.BLOCK::getKey, Registry.BLOCK::get)
|
||||
: new ProtoTickList<Block>(block -> (block == null || block.defaultBlockState().isAir()), chunkPos,
|
||||
tagLevel.getList("ToBeTicked", 9), level);
|
||||
|
||||
TickList<Fluid> liquidTicks = tagLevel.contains("LiquidTicks", 9)
|
||||
? ChunkTickList.create(tagLevel.getList("LiquidTicks", 10), Registry.FLUID::getKey, Registry.FLUID::get)
|
||||
: new ProtoTickList<Fluid>(fluid -> (fluid == null || fluid == Fluids.EMPTY), chunkPos,
|
||||
tagLevel.getList("LiquidsToBeTicked", 9), level);
|
||||
|
||||
long inhabitedTime = tagLevel.getLong("InhabitedTime");
|
||||
|
||||
LevelChunkSection[] levelChunkSections = readSections(level, lightEngine, chunkPos, tagLevel);
|
||||
|
||||
// ======================== Make the chunk
|
||||
// ===========================================
|
||||
LevelChunk chunk = new LevelChunk(level.getLevel(), chunkPos, chunkBiomeContainer, upgradeData, blockTicks,
|
||||
liquidTicks, inhabitedTime, levelChunkSections, null);
|
||||
|
||||
// ========================== Post setup some chunk data
|
||||
// ==============================
|
||||
chunk.setLightCorrect(tagLevel.getBoolean("isLightOn"));
|
||||
readHeightmaps(chunk, tagLevel);
|
||||
readPostPocessings(chunk, tagLevel);
|
||||
// ApiShared.LOGGER.info("Loaded chunk @ "+chunk.getPos());
|
||||
return chunk;
|
||||
}
|
||||
|
||||
private static void logErrors(ChunkPos chunkPos, int i, String string)
|
||||
{
|
||||
LOGGER.error("Distant Horizons: Recoverable errors when loading section [" + chunkPos.x + ", " + i + ", " + chunkPos.z + "]: " + string);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+22
-27
@@ -1,11 +1,14 @@
|
||||
package com.seibel.lod.common.wrappers.worldGeneration.mimicObject;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import com.seibel.lod.core.api.ApiShared;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment.EmptyChunkGenerator;
|
||||
import com.seibel.lod.core.api.ApiShared;
|
||||
import com.seibel.lod.core.api.ClientApi;
|
||||
import com.seibel.lod.core.enums.config.LightGenerationMode;
|
||||
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
|
||||
@@ -23,7 +26,6 @@ import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import net.minecraft.world.level.ColorResolver;
|
||||
import net.minecraft.world.level.LevelHeightAccessor;
|
||||
import net.minecraft.world.level.LightLayer;
|
||||
import net.minecraft.world.level.StructureFeatureManager;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
@@ -48,6 +50,13 @@ public class LightedWorldGenRegion extends WorldGenRegion {
|
||||
private final ChunkPos firstPos;
|
||||
private final List<ChunkAccess> cache;
|
||||
Long2ObjectOpenHashMap<ChunkAccess> chunkMap = new Long2ObjectOpenHashMap<ChunkAccess>();
|
||||
private ChunkPos overrideCenterPos = null;
|
||||
|
||||
public void setOverrideCenter(ChunkPos pos) {overrideCenterPos = pos;}
|
||||
@Override
|
||||
public ChunkPos getCenter() {
|
||||
return overrideCenterPos==null ? super.getCenter() : overrideCenterPos;
|
||||
}
|
||||
|
||||
public LightedWorldGenRegion(ServerLevel serverLevel, WorldGenLevelLightEngine lightEngine,
|
||||
List<ChunkAccess> list, ChunkStatus chunkStatus, int i,
|
||||
@@ -60,12 +69,12 @@ public class LightedWorldGenRegion extends WorldGenRegion {
|
||||
writeRadius = i;
|
||||
cache = list;
|
||||
size = Mth.floor(Math.sqrt(list.size()));
|
||||
|
||||
this.tintCaches = Util.make(new Object2ObjectArrayMap(3), object2ObjectArrayMap -> {
|
||||
object2ObjectArrayMap.put(BiomeColors.GRASS_COLOR_RESOLVER, new BlockTintCache((pos) -> {return calculateBlockTint(pos, BiomeColors.GRASS_COLOR_RESOLVER);}));
|
||||
object2ObjectArrayMap.put(BiomeColors.FOLIAGE_COLOR_RESOLVER, new BlockTintCache((pos) -> {return calculateBlockTint(pos, BiomeColors.FOLIAGE_COLOR_RESOLVER);}));
|
||||
object2ObjectArrayMap.put(BiomeColors.WATER_COLOR_RESOLVER, new BlockTintCache((pos) -> {return calculateBlockTint(pos, BiomeColors.WATER_COLOR_RESOLVER);}));
|
||||
});
|
||||
|
||||
this.tintCaches = Util.make(new Object2ObjectArrayMap(3), object2ObjectArrayMap -> {
|
||||
object2ObjectArrayMap.put(BiomeColors.GRASS_COLOR_RESOLVER, new BlockTintCache());
|
||||
object2ObjectArrayMap.put(BiomeColors.FOLIAGE_COLOR_RESOLVER, new BlockTintCache());
|
||||
object2ObjectArrayMap.put(BiomeColors.WATER_COLOR_RESOLVER, new BlockTintCache());
|
||||
});
|
||||
}
|
||||
|
||||
// Bypass BCLib mixin overrides.
|
||||
@@ -74,18 +83,11 @@ public class LightedWorldGenRegion extends WorldGenRegion {
|
||||
int i = SectionPos.blockToSectionCoord(blockPos.getX());
|
||||
int j = SectionPos.blockToSectionCoord(blockPos.getZ());
|
||||
ChunkPos chunkPos = this.getCenter();
|
||||
ChunkAccess center = this.getChunk(chunkPos.x, chunkPos.z);
|
||||
int k = Math.abs(chunkPos.x - i);
|
||||
int l = Math.abs(chunkPos.z - j);
|
||||
if (k > this.writeRadius || l > this.writeRadius) {
|
||||
return false;
|
||||
}
|
||||
if (center.isUpgrading()) {
|
||||
LevelHeightAccessor levelHeightAccessor = center.getHeightAccessorForGeneration();
|
||||
if (blockPos.getY() < levelHeightAccessor.getMinBuildHeight() || blockPos.getY() >= levelHeightAccessor.getMaxBuildHeight()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -172,7 +174,7 @@ public class LightedWorldGenRegion extends WorldGenRegion {
|
||||
public ChunkAccess getChunk(int i, int j, ChunkStatus chunkStatus, boolean bl) {
|
||||
ChunkAccess chunk = getChunkAccess(i, j, chunkStatus, bl);
|
||||
if (chunk instanceof LevelChunk) {
|
||||
chunk = new ImposterProtoChunk((LevelChunk) chunk, true);
|
||||
chunk = new ImposterProtoChunk((LevelChunk) chunk);
|
||||
}
|
||||
return chunk;
|
||||
}
|
||||
@@ -237,29 +239,23 @@ public class LightedWorldGenRegion extends WorldGenRegion {
|
||||
return (getBrightness(LightLayer.SKY, blockPos) >= getMaxLightLevel());
|
||||
}
|
||||
|
||||
|
||||
|
||||
private final Object2ObjectArrayMap<ColorResolver, BlockTintCache> tintCaches;
|
||||
|
||||
|
||||
public int getBlockTint(BlockPos blockPos, ColorResolver colorResolver)
|
||||
{
|
||||
BlockTintCache blockTintCache = (BlockTintCache) this.tintCaches.get(colorResolver);
|
||||
return blockTintCache.getColor(blockPos);
|
||||
return blockTintCache.getColor(blockPos, null); // FIXME[Generator]: Replace this null with something else
|
||||
}
|
||||
|
||||
private Biome _getBiome(BlockPos pos) {
|
||||
#if MC_VERSION_1_18_2
|
||||
return getBiome(pos).value();
|
||||
#elif MC_VERSION_1_18_1
|
||||
return getBiome(pos);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
public int calculateBlockTint(BlockPos blockPos, ColorResolver colorResolver)
|
||||
{
|
||||
int i = (Minecraft.getInstance()).options.biomeBlendRadius;
|
||||
if (i == 0)
|
||||
return colorResolver.getColor((Biome) _getBiome(blockPos), blockPos.getX(), blockPos.getZ());
|
||||
return colorResolver.getColor((Biome) getBiome(blockPos), blockPos.getX(), blockPos.getZ());
|
||||
int j = (i * 2 + 1) * (i * 2 + 1);
|
||||
int k = 0;
|
||||
int l = 0;
|
||||
@@ -269,12 +265,11 @@ public class LightedWorldGenRegion extends WorldGenRegion {
|
||||
while (cursor3D.advance())
|
||||
{
|
||||
mutableBlockPos.set(cursor3D.nextX(), cursor3D.nextY(), cursor3D.nextZ());
|
||||
int n = colorResolver.getColor((Biome) _getBiome((BlockPos) mutableBlockPos), mutableBlockPos.getX(), mutableBlockPos.getZ());
|
||||
int n = colorResolver.getColor((Biome) getBiome((BlockPos) mutableBlockPos), mutableBlockPos.getX(), mutableBlockPos.getZ());
|
||||
k += (n & 0xFF0000) >> 16;
|
||||
l += (n & 0xFF00) >> 8;
|
||||
m += n & 0xFF;
|
||||
}
|
||||
return (k / j & 0xFF) << 16 | (l / j & 0xFF) << 8 | m / j & 0xFF;
|
||||
}
|
||||
|
||||
}
|
||||
+4
-3
@@ -125,9 +125,10 @@ public class WorldGenLevelLightEngine extends LevelLightEngine {
|
||||
LevelChunkSection[] levelChunkSections = chunkAccess.getSections();
|
||||
for (int i = 0; i < chunkAccess.getSectionsCount(); ++i) {
|
||||
LevelChunkSection levelChunkSection = levelChunkSections[i];
|
||||
if (levelChunkSection.hasOnlyAir()) continue;
|
||||
int j = this.levelHeightAccessor.getSectionYFromSectionIndex(i);
|
||||
updateSectionStatus(SectionPos.of(chunkPos, j), false);
|
||||
if (!LevelChunkSection.isEmpty(levelChunkSection)) {
|
||||
int j = this.levelHeightAccessor.getSectionYFromSectionIndex(i);
|
||||
updateSectionStatus(SectionPos.of(chunkPos, j), false);
|
||||
}
|
||||
}
|
||||
enableLightSources(chunkPos, true);
|
||||
if (needLightBlockUpdate) {
|
||||
|
||||
+19
-97
@@ -1,17 +1,7 @@
|
||||
package com.seibel.lod.common.wrappers.worldGeneration.mimicObject;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import it.unimi.dsi.fastutil.longs.LongIterator;
|
||||
import it.unimi.dsi.fastutil.longs.LongSet;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.SectionPos;
|
||||
import net.minecraft.server.level.WorldGenRegion;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
@@ -21,18 +11,15 @@ import net.minecraft.world.level.WorldGenLevel;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||
import net.minecraft.world.level.levelgen.WorldGenSettings;
|
||||
import net.minecraft.world.level.levelgen.feature.ConfiguredStructureFeature;
|
||||
import net.minecraft.world.level.levelgen.feature.StructureFeature;
|
||||
import net.minecraft.world.level.levelgen.structure.StructureCheck;
|
||||
import net.minecraft.world.level.levelgen.structure.StructureStart;
|
||||
|
||||
public class WorldGenStructFeatManager extends StructureFeatureManager {
|
||||
final WorldGenLevel genLevel;
|
||||
WorldGenSettings worldGenSettings;
|
||||
StructureCheck structureCheck;
|
||||
public WorldGenStructFeatManager(WorldGenSettings worldGenSettings,
|
||||
WorldGenLevel genLevel, StructureCheck structureCheck) {
|
||||
super(genLevel, worldGenSettings, structureCheck);
|
||||
WorldGenLevel genLevel) {
|
||||
super(genLevel, worldGenSettings);
|
||||
this.genLevel = genLevel;
|
||||
this.worldGenSettings = worldGenSettings;
|
||||
}
|
||||
@@ -41,7 +28,7 @@ public class WorldGenStructFeatManager extends StructureFeatureManager {
|
||||
public WorldGenStructFeatManager forWorldGenRegion(WorldGenRegion worldGenRegion) {
|
||||
if (worldGenRegion == genLevel)
|
||||
return this;
|
||||
return new WorldGenStructFeatManager(worldGenSettings, worldGenRegion, structureCheck);
|
||||
return new WorldGenStructFeatManager(worldGenSettings, worldGenRegion);
|
||||
}
|
||||
|
||||
private ChunkAccess _getChunk(int x, int z, ChunkStatus status) {
|
||||
@@ -50,85 +37,20 @@ public class WorldGenStructFeatManager extends StructureFeatureManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasAnyStructureAt(BlockPos blockPos) {
|
||||
SectionPos sectionPos = SectionPos.of(blockPos);
|
||||
ChunkAccess chunk = _getChunk(sectionPos.x(), sectionPos.z(), ChunkStatus.STRUCTURE_REFERENCES);
|
||||
if (chunk == null) return false;
|
||||
return chunk.hasAnyStructureReferences();
|
||||
}
|
||||
|
||||
|
||||
|
||||
#if MC_VERSION_1_18_1
|
||||
@Override
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public List<? extends StructureStart<?>> startsForFeature(SectionPos sectionPos,
|
||||
StructureFeature<?> structureFeature) {
|
||||
|
||||
ChunkAccess chunk = _getChunk(sectionPos.x(), sectionPos.z(), ChunkStatus.STRUCTURE_REFERENCES);
|
||||
if (chunk == null) return List.of();
|
||||
|
||||
// Copied from StructureFeatureManager::startsForFeature(...) with slight tweaks
|
||||
LongSet longSet = chunk.getReferencesForFeature(structureFeature);
|
||||
ImmutableList.Builder builder = ImmutableList.builder();
|
||||
LongIterator longIterator = longSet.iterator();
|
||||
while (longIterator.hasNext()) {
|
||||
long l = (Long)longIterator.next();
|
||||
SectionPos sectPos = SectionPos.of(new ChunkPos(l), genLevel.getMinSection());
|
||||
ChunkAccess startChunk = _getChunk(sectPos.x(), sectPos.z(), ChunkStatus.STRUCTURE_STARTS);
|
||||
if (startChunk == null) continue;
|
||||
StructureStart<?> structureStart = this.getStartForFeature(sectPos, structureFeature, startChunk);
|
||||
if (structureStart == null || !structureStart.isValid()) continue;
|
||||
builder.add(structureStart);
|
||||
}
|
||||
return builder.build();
|
||||
public Stream<? extends StructureStart<?>> startsForFeature(SectionPos sectionPos2,
|
||||
StructureFeature<?> structureFeature) {
|
||||
if (genLevel == null)
|
||||
return Stream.empty();
|
||||
ChunkAccess chunk = genLevel.getChunk(sectionPos2.x(), sectionPos2.z(), ChunkStatus.STRUCTURE_REFERENCES,
|
||||
false);
|
||||
if (chunk == null)
|
||||
return Stream.empty();
|
||||
return chunk.getReferencesForFeature(structureFeature).stream().map(pos -> {
|
||||
SectionPos sectPos = SectionPos.of(ChunkPos.getX(pos), 0, ChunkPos.getZ(pos));
|
||||
ChunkAccess startChunk = genLevel.getChunk(sectPos.x(), sectPos.z(), ChunkStatus.STRUCTURE_STARTS, false);
|
||||
if (startChunk == null)
|
||||
return null;
|
||||
return this.getStartForFeature(sectPos, structureFeature, startChunk);
|
||||
}).filter(structureStart -> structureStart != null && structureStart.isValid());
|
||||
}
|
||||
#elif MC_VERSION_1_18_2
|
||||
|
||||
@Override
|
||||
public List<StructureStart> startsForFeature(SectionPos sectionPos, Predicate<ConfiguredStructureFeature<?, ?>> predicate) {
|
||||
ChunkAccess chunk = _getChunk(sectionPos.x(), sectionPos.z(), ChunkStatus.STRUCTURE_REFERENCES);
|
||||
if (chunk == null) return List.of();
|
||||
|
||||
// Copied from StructureFeatureManager::startsForFeature(...)
|
||||
Map<ConfiguredStructureFeature<?, ?>, LongSet> map = chunk.getAllReferences();
|
||||
|
||||
ImmutableList.Builder<StructureStart> builder = ImmutableList.builder();
|
||||
Iterator<Map.Entry<ConfiguredStructureFeature<?, ?>, LongSet>> var5 = map.entrySet().iterator();
|
||||
|
||||
while(var5.hasNext()) {
|
||||
Map.Entry<ConfiguredStructureFeature<?, ?>, LongSet> entry = var5.next();
|
||||
ConfiguredStructureFeature<?, ?> configuredStructureFeature = entry.getKey();
|
||||
if (predicate.test(configuredStructureFeature)) {
|
||||
LongSet var10002 = (LongSet)entry.getValue();
|
||||
Objects.requireNonNull(builder);
|
||||
this.fillStartsForFeature(configuredStructureFeature, var10002, builder::add);
|
||||
}
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<StructureStart> startsForFeature(SectionPos sectionPos, ConfiguredStructureFeature<?, ?> configuredStructureFeature) {
|
||||
ChunkAccess chunk = _getChunk(sectionPos.x(), sectionPos.z(), ChunkStatus.STRUCTURE_REFERENCES);
|
||||
if (chunk == null) return List.of();
|
||||
|
||||
// Copied from StructureFeatureManager::startsForFeature(...)
|
||||
LongSet longSet = chunk.getReferencesForFeature(configuredStructureFeature);
|
||||
ImmutableList.Builder<StructureStart> builder = ImmutableList.builder();
|
||||
Objects.requireNonNull(builder);
|
||||
this.fillStartsForFeature(configuredStructureFeature, longSet, builder::add);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<ConfiguredStructureFeature<?, ?>, LongSet> getAllStructuresAt(BlockPos blockPos) {
|
||||
SectionPos sectionPos = SectionPos.of(blockPos);
|
||||
ChunkAccess chunk = _getChunk(sectionPos.x(), sectionPos.z(), ChunkStatus.STRUCTURE_REFERENCES);
|
||||
if (chunk == null) return Map.of();
|
||||
return chunk.getAllReferences();
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
+12
-22
@@ -3,53 +3,43 @@ package com.seibel.lod.common.wrappers.worldGeneration.step;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment;
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.ThreadedParameters;
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment;
|
||||
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.server.level.WorldGenRegion;
|
||||
import net.minecraft.world.level.StructureFeatureManager;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
import net.minecraft.world.level.chunk.ChunkGenerator;
|
||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||
import net.minecraft.world.level.chunk.ProtoChunk;
|
||||
import net.minecraft.world.level.levelgen.DebugLevelSource;
|
||||
import net.minecraft.world.level.levelgen.FlatLevelSource;
|
||||
import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator;
|
||||
import net.minecraft.world.level.levelgen.blending.Blender;
|
||||
|
||||
public final class StepBiomes {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private final BatchGenerationEnvironment environment;
|
||||
private final BatchGenerationEnvironment envionment;
|
||||
|
||||
/**
|
||||
* @param batchGenerationEnvironment
|
||||
* @param worldGenerationEnvironment
|
||||
*/
|
||||
public StepBiomes(BatchGenerationEnvironment batchGenerationEnvironment)
|
||||
{
|
||||
environment = batchGenerationEnvironment;
|
||||
public StepBiomes(BatchGenerationEnvironment worldGenerationEnvironment) {
|
||||
envionment = worldGenerationEnvironment;
|
||||
}
|
||||
|
||||
public final ChunkStatus STATUS = ChunkStatus.BIOMES;
|
||||
|
||||
public void generateGroup(ThreadedParameters tParams, WorldGenRegion worldGenRegion,
|
||||
List<ChunkAccess> chunks) {
|
||||
|
||||
public void generateGroup(ThreadedParameters tParams, WorldGenRegion worldGenRegion, List<ChunkAccess> chunks) {
|
||||
|
||||
ArrayList<ChunkAccess> chunksToDo = new ArrayList<ChunkAccess>();
|
||||
|
||||
|
||||
for (ChunkAccess chunk : chunks) {
|
||||
if (chunk.getStatus().isOrAfter(STATUS)) continue;
|
||||
if (chunk.getStatus().isOrAfter(STATUS))
|
||||
continue;
|
||||
((ProtoChunk) chunk).setStatus(STATUS);
|
||||
chunksToDo.add(chunk);
|
||||
}
|
||||
|
||||
|
||||
for (ChunkAccess chunk : chunksToDo) {
|
||||
// System.out.println("StepBiomes: "+chunk.getPos());
|
||||
chunk = environment.joinSync(environment.params.generator.createBiomes(environment.params.biomes, Runnable::run, Blender.of(worldGenRegion),
|
||||
tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk));
|
||||
envionment.params.generator.createBiomes(envionment.params.biomes, chunk);
|
||||
}
|
||||
}
|
||||
}
|
||||
+16
-26
@@ -2,59 +2,49 @@ package com.seibel.lod.common.wrappers.worldGeneration.step;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment;
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.ThreadedParameters;
|
||||
import com.seibel.lod.core.util.gridList.ArrayGridList;
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.mimicObject.LightedWorldGenRegion;
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment;
|
||||
|
||||
import com.seibel.lod.core.util.gridList.ArrayGridList;
|
||||
import net.minecraft.ReportedException;
|
||||
import net.minecraft.server.level.WorldGenRegion;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||
import net.minecraft.world.level.chunk.ProtoChunk;
|
||||
import net.minecraft.world.level.levelgen.blending.Blender;
|
||||
|
||||
public final class StepFeatures {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private final BatchGenerationEnvironment environment;
|
||||
private final BatchGenerationEnvironment envionment;
|
||||
|
||||
/**
|
||||
* @param batchGenerationEnvironment
|
||||
* @param worldGenerationEnvironment
|
||||
*/
|
||||
public StepFeatures(BatchGenerationEnvironment batchGenerationEnvironment)
|
||||
{
|
||||
environment = batchGenerationEnvironment;
|
||||
public StepFeatures(BatchGenerationEnvironment worldGenerationEnvironment) {
|
||||
envionment = worldGenerationEnvironment;
|
||||
}
|
||||
|
||||
public final ChunkStatus STATUS = ChunkStatus.FEATURES;
|
||||
|
||||
public void generateGroup(ThreadedParameters tParams, WorldGenRegion worldGenRegion,
|
||||
ArrayGridList<ChunkAccess> chunks) {
|
||||
public void generateGroup(ThreadedParameters tParams, LightedWorldGenRegion worldGenRegion, ArrayGridList<ChunkAccess> chunks) {
|
||||
ArrayList<ChunkAccess> chunksToDo = new ArrayList<ChunkAccess>();
|
||||
|
||||
|
||||
for (ChunkAccess chunk : chunks) {
|
||||
if (chunk.getStatus().isOrAfter(STATUS)) continue;
|
||||
if (chunk.getStatus().isOrAfter(STATUS))
|
||||
continue;
|
||||
((ProtoChunk) chunk).setStatus(STATUS);
|
||||
chunksToDo.add(chunk);
|
||||
}
|
||||
|
||||
|
||||
for (ChunkAccess chunk : chunksToDo) {
|
||||
try {
|
||||
environment.params.generator.applyBiomeDecoration(worldGenRegion, chunk,
|
||||
tParams.structFeat.forWorldGenRegion(worldGenRegion));
|
||||
Blender.generateBorderTicks(worldGenRegion, chunk);
|
||||
worldGenRegion.setOverrideCenter(chunk.getPos());
|
||||
envionment.params.generator.applyBiomeDecoration(worldGenRegion, tParams.structFeat);
|
||||
} catch (ReportedException e) {
|
||||
e.printStackTrace();
|
||||
// FIXME: Features concurrent modification issue. Something about cocobeans just
|
||||
// aren't happy
|
||||
// For now just retry.
|
||||
}
|
||||
}/*
|
||||
for (ChunkAccess chunk : chunks) {
|
||||
Heightmap.primeHeightmaps(chunk,
|
||||
EnumSet.of(Heightmap.Types.MOTION_BLOCKING, Heightmap.Types.MOTION_BLOCKING_NO_LEAVES,
|
||||
Heightmap.Types.OCEAN_FLOOR, Heightmap.Types.WORLD_SURFACE));
|
||||
}*/
|
||||
}
|
||||
worldGenRegion.setOverrideCenter(null);
|
||||
}
|
||||
}
|
||||
+2
-3
@@ -2,8 +2,8 @@ package com.seibel.lod.common.wrappers.worldGeneration.step;
|
||||
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment;
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.mimicObject.WorldGenLevelLightEngine;
|
||||
import com.seibel.lod.core.util.gridList.ArrayGridList;
|
||||
|
||||
import com.seibel.lod.core.util.gridList.ArrayGridList;
|
||||
import net.minecraft.server.level.ThreadedLevelLightEngine;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||
@@ -28,7 +28,7 @@ public final class StepLight {
|
||||
public final ChunkStatus STATUS = ChunkStatus.LIGHT;
|
||||
|
||||
public void generateGroup(LightEventListener lightEngine,
|
||||
ArrayGridList<ChunkAccess> chunks) {
|
||||
ArrayGridList<ChunkAccess> chunks) {
|
||||
//ArrayList<ChunkAccess> chunksToDo = new ArrayList<ChunkAccess>();
|
||||
|
||||
for (ChunkAccess chunk : chunks) {
|
||||
@@ -52,7 +52,6 @@ public final class StepLight {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (chunk instanceof LevelChunk) ((LevelChunk)chunk).setClientLightReady(true);
|
||||
chunk.setLightCorrect(true);
|
||||
}
|
||||
lightEngine.runUpdates(Integer.MAX_VALUE, true, true);
|
||||
|
||||
+3
-5
@@ -3,15 +3,14 @@ package com.seibel.lod.common.wrappers.worldGeneration.step;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment;
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.ThreadedParameters;
|
||||
|
||||
import net.minecraft.core.QuartPos;
|
||||
import net.minecraft.server.level.WorldGenRegion;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.level.LevelHeightAccessor;
|
||||
import net.minecraft.world.level.StructureFeatureManager;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||
@@ -19,7 +18,6 @@ import net.minecraft.world.level.chunk.LevelChunkSection;
|
||||
import net.minecraft.world.level.chunk.ProtoChunk;
|
||||
import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator;
|
||||
import net.minecraft.world.level.levelgen.NoiseSettings;
|
||||
import net.minecraft.world.level.levelgen.blending.Blender;
|
||||
|
||||
public final class StepNoise {
|
||||
/**
|
||||
@@ -50,8 +48,8 @@ public final class StepNoise {
|
||||
|
||||
for (ChunkAccess chunk : chunksToDo) {
|
||||
// System.out.println("StepNoise: "+chunk.getPos());
|
||||
chunk = environment.joinSync(environment.params.generator.fillFromNoise(Runnable::run, Blender.of(worldGenRegion),
|
||||
tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk));
|
||||
chunk = environment.joinSync(environment.params.generator.fillFromNoise(Runnable::run,
|
||||
tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk));
|
||||
}
|
||||
}
|
||||
}
|
||||
-8
@@ -53,14 +53,6 @@ public final class StepStructureStart {
|
||||
// System.out.println("StepStructureStart: "+chunk.getPos());
|
||||
environment.params.generator.createStructures(environment.params.registry, tParams.structFeat, chunk, environment.params.structures,
|
||||
environment.params.worldSeed);
|
||||
try {
|
||||
tParams.structCheck.onStructureLoad(chunk.getPos(), chunk.getAllStarts());
|
||||
} catch (ArrayIndexOutOfBoundsException e) {
|
||||
// There's a rare issue with StructStart where it throws ArrayIndexOutOfBounds
|
||||
// This means the structFeat is corrupted (For some reason) and I need to reset it.
|
||||
// TODO: Figure out in the future why this happens even though I am using new structFeat
|
||||
throw new StepStructureStart.StructStartCorruptedException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-2
@@ -39,8 +39,7 @@ public final class StepSurface {
|
||||
|
||||
for (ChunkAccess chunk : chunksToDo) {
|
||||
// System.out.println("StepSurface: "+chunk.getPos());
|
||||
environment.params.generator.buildSurface(worldGenRegion, tParams.structFeat.forWorldGenRegion(worldGenRegion),
|
||||
chunk);
|
||||
environment.params.generator.buildSurfaceAndBedrock(worldGenRegion, chunk);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,15 +8,17 @@ accessible field com/mojang/blaze3d/vertex/VertexBuffer indexCount I
|
||||
accessible field com/mojang/blaze3d/vertex/VertexBuffer vertextBufferId I
|
||||
accessible method net/minecraft/client/renderer/GameRenderer getFov (Lnet/minecraft/client/Camera;FZ)D
|
||||
|
||||
# pre-render setup
|
||||
accessible field net/minecraft/client/renderer/LevelRenderer renderChunks Lit/unimi/dsi/fastutil/objects/ObjectArrayList;
|
||||
accessible class net/minecraft/client/renderer/LevelRenderer$RenderChunkInfo
|
||||
accessible field net/minecraft/client/renderer/LevelRenderer$RenderChunkInfo chunk Lnet/minecraft/client/renderer/chunk/ChunkRenderDispatcher$RenderChunk;
|
||||
|
||||
# used for grabbing vanilla rendered chunks
|
||||
accessible field net/minecraft/client/renderer/LevelRenderer renderChunkStorage Ljava/util/concurrent/atomic/AtomicReference;
|
||||
accessible class net/minecraft/client/renderer/LevelRenderer$RenderChunkStorage
|
||||
accessible class net/minecraft/client/renderer/LevelRenderer$RenderChunkInfo
|
||||
accessible field net/minecraft/client/renderer/LevelRenderer$RenderChunkInfo chunk Lnet/minecraft/client/renderer/chunk/ChunkRenderDispatcher$RenderChunk;
|
||||
|
||||
# lighting
|
||||
accessible field net/minecraft/client/renderer/LightTexture lightPixels Lcom/mojang/blaze3d/platform/NativeImage;
|
||||
accessible field net/minecraft/client/renderer/LightTexture lightTexture Lnet/minecraft/client/renderer/texture/DynamicTexture;
|
||||
accessible field net/minecraft/world/level/lighting/LevelLightEngine blockEngine Lnet/minecraft/world/level/lighting/LayerLightEngine;
|
||||
accessible field net/minecraft/world/level/lighting/LevelLightEngine skyEngine Lnet/minecraft/world/level/lighting/LayerLightEngine;
|
||||
|
||||
@@ -25,25 +27,26 @@ accessible method net/minecraft/world/level/levelgen/Heightmap setHeight (III)V
|
||||
accessible field net/minecraft/world/level/biome/Biome generationSettings Lnet/minecraft/world/level/biome/BiomeGenerationSettings;
|
||||
accessible field net/minecraft/world/level/biome/Biome biomeCategory Lnet/minecraft/world/level/biome/Biome$BiomeCategory;
|
||||
# accessible field net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator settings Lnet/minecraft/core/Holder;
|
||||
accessible method net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator doFill (Lnet/minecraft/world/level/levelgen/blending/Blender;Lnet/minecraft/world/level/StructureFeatureManager;Lnet/minecraft/world/level/chunk/ChunkAccess;II)Lnet/minecraft/world/level/chunk/ChunkAccess;
|
||||
accessible field net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator settings Ljava/util/function/Supplier;
|
||||
#accessible method net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator doCreateBiomes (Lnet/minecraft/core/Registry;Lnet/minecraft/world/level/levelgen/blending/Blender;Lnet/minecraft/world/level/StructureFeatureManager;Lnet/minecraft/world/level/chunk/ChunkAccess;)V
|
||||
accessible method net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator doFill (Lnet/minecraft/world/level/StructureFeatureManager;Lnet/minecraft/world/level/chunk/ChunkAccess;II)Lnet/minecraft/world/level/chunk/ChunkAccess;
|
||||
|
||||
accessible method net/minecraft/world/level/lighting/LayerLightEngine queueSectionData (JLnet/minecraft/world/level/chunk/DataLayer;Z)V
|
||||
accessible field net/minecraft/world/level/chunk/ChunkGenerator biomeSource Lnet/minecraft/world/level/biome/BiomeSource;
|
||||
|
||||
# lod generation from save file
|
||||
accessible field net/minecraft/server/level/ChunkMap mainThreadExecutor Lnet/minecraft/util/thread/BlockableEventLoop;
|
||||
accessible method net/minecraft/server/level/ChunkMap readChunk (Lnet/minecraft/world/level/ChunkPos;)Lnet/minecraft/nbt/CompoundTag;
|
||||
|
||||
|
||||
# grabbing textures
|
||||
accessible field net/minecraft/client/renderer/texture/TextureAtlasSprite animatedTexture Lnet/minecraft/client/renderer/texture/TextureAtlasSprite$AnimatedTexture;
|
||||
accessible field net/minecraft/client/renderer/texture/TextureAtlasSprite width I
|
||||
accessible field net/minecraft/client/renderer/texture/TextureAtlasSprite height I
|
||||
accessible field net/minecraft/client/renderer/texture/TextureAtlasSprite mainImage [Lcom/mojang/blaze3d/platform/NativeImage;
|
||||
accessible class net/minecraft/client/renderer/texture/TextureAtlasSprite$AnimatedTexture
|
||||
accessible method net/minecraft/client/renderer/texture/TextureAtlasSprite$AnimatedTexture getFrameX (I)I
|
||||
accessible method net/minecraft/client/renderer/texture/TextureAtlasSprite$AnimatedTexture getFrameY (I)I
|
||||
extendable class com/mojang/math/Matrix4f
|
||||
|
||||
# hacky stuff
|
||||
accessible field net/minecraft/util/ThreadingDetector lock Ljava/util/concurrent/Semaphore;
|
||||
mutable field net/minecraft/util/ThreadingDetector lock Ljava/util/concurrent/Semaphore;
|
||||
accessible field net/minecraft/world/level/chunk/PalettedContainer lock Ljava/util/concurrent/Semaphore;
|
||||
mutable field net/minecraft/world/level/chunk/PalettedContainer lock Ljava/util/concurrent/Semaphore;
|
||||
|
||||
+1
-1
Submodule core updated: 02b0637adc...4bac38c99f
+7
-16
@@ -1,5 +1,5 @@
|
||||
plugins {
|
||||
id "com.github.johnrengelman.shadow" version "7.1.0"
|
||||
id "com.github.johnrengelman.shadow" version "7.0.0"
|
||||
}
|
||||
|
||||
version = rootProject.mod_version+"-"+rootProject.minecraft_version+"-"+new Date().format("yyyy_MM_dd_HH_mm")
|
||||
@@ -45,29 +45,20 @@ dependencies {
|
||||
addModJar(fabricApi.module("fabric-networking-api-v1", rootProject.fabric_api_version))
|
||||
|
||||
// Mod Menu
|
||||
modImplementation("com.terraformersmc:modmenu:${rootProject.modmenu_version}")
|
||||
|
||||
// Starlight
|
||||
addMod("curse.maven:starlight-521783:${rootProject.starlight_version_fabric}", rootProject.enable_starlight)
|
||||
|
||||
// Phosphor
|
||||
addMod("curse.maven:phosphor-372124:${rootProject.phosphor_version_fabric}", rootProject.enable_phosphor)
|
||||
modImplementation("com.terraformersmc:modmenu:${rootProject.modmenu_version}") {
|
||||
exclude(group: "net.fabricmc.fabric-api")
|
||||
}
|
||||
|
||||
// Sodium
|
||||
addMod("curse.maven:sodium-394468:${rootProject.sodium_version}", rootProject.enable_sodium)
|
||||
implementation "org.joml:joml:1.10.2"
|
||||
modImplementation(fabricApi.module("fabric-rendering-data-attachment-v1", rootProject.fabric_api_version))
|
||||
modImplementation(fabricApi.module("fabric-rendering-fluids-v1", rootProject.fabric_api_version))
|
||||
|
||||
// Lithium
|
||||
|
||||
// Lithium
|
||||
addMod("maven.modrinth:lithium:${rootProject.lithium_version}", rootProject.enable_lithium)
|
||||
|
||||
// Iris
|
||||
addMod("maven.modrinth:iris:${rootProject.iris_version}", rootProject.enable_iris)
|
||||
|
||||
// BCLib
|
||||
addMod("com.github.paulevsGitch:BCLib:${rootProject.bclib_version}", rootProject.enable_bclib)
|
||||
|
||||
// Immersive Portals
|
||||
/*
|
||||
modImplementation("com.github.qouteall.ImmersivePortalsMod:build:${rootProject.immersive_portals_version}") {
|
||||
@@ -82,7 +73,7 @@ dependencies {
|
||||
exclude(group: "net.fabricmc.fabric-api")
|
||||
transitive(false)
|
||||
}
|
||||
*/
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -22,20 +22,19 @@ package com.seibel.lod.fabric;
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment;
|
||||
import com.seibel.lod.core.api.ClientApi;
|
||||
import com.seibel.lod.core.api.EventApi;
|
||||
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
|
||||
import com.mojang.blaze3d.platform.InputConstants;
|
||||
import com.seibel.lod.common.wrappers.chunk.ChunkWrapper;
|
||||
import com.seibel.lod.common.wrappers.world.DimensionTypeWrapper;
|
||||
import com.seibel.lod.common.wrappers.world.WorldWrapper;
|
||||
|
||||
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
|
||||
import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
|
||||
|
||||
import com.seibel.lod.fabric.mixins.MixinUtilBackgroudThread;
|
||||
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientChunkEvents;
|
||||
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
|
||||
import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
|
||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
|
||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerWorldEvents;
|
||||
import net.minecraft.client.KeyMapping;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
@@ -44,7 +43,6 @@ import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraft.world.level.chunk.LevelChunk;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
@@ -52,7 +50,7 @@ import org.lwjgl.glfw.GLFW;
|
||||
/**
|
||||
* This handles all events sent to the client,
|
||||
* and is the starting point for most of the mod.
|
||||
*
|
||||
*
|
||||
* @author coolGi2007
|
||||
* @author Ran
|
||||
* @version 11-23-2021
|
||||
@@ -69,6 +67,8 @@ public class ClientProxy
|
||||
* @author Ran
|
||||
*/
|
||||
public void registerEvents() {
|
||||
// TODO: Fix this if it's wrong
|
||||
|
||||
/* Registor the mod accessor*/
|
||||
|
||||
/* World Events */
|
||||
@@ -77,12 +77,12 @@ public class ClientProxy
|
||||
|
||||
/* World Events */
|
||||
//ServerChunkEvents.CHUNK_LOAD.register(this::chunkLoadEvent);
|
||||
//ClientChunkEvents.CHUNK_LOAD.register(this::chunkLoadEvent);
|
||||
ClientChunkEvents.CHUNK_LOAD.register(this::chunkLoadEvent);
|
||||
|
||||
/* World Events */
|
||||
ServerWorldEvents.LOAD.register((server, level) -> this.worldLoadEvent(level));
|
||||
ServerWorldEvents.UNLOAD.register((server, level) -> this.worldUnloadEvent(level));
|
||||
|
||||
|
||||
/* The Client World Events are in the mixins
|
||||
Client world load event is in MixinClientLevel
|
||||
Client world unload event is in MixinMinecraft */
|
||||
@@ -93,7 +93,6 @@ public class ClientProxy
|
||||
if (client.player != null) onKeyInput();
|
||||
});
|
||||
isGenerationThreadChecker = BatchGenerationEnvironment::isCurrentThreadDistantGeneratorThread;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -112,7 +111,7 @@ public class ClientProxy
|
||||
{
|
||||
eventApi.worldSaveEvent();
|
||||
}
|
||||
|
||||
|
||||
/** This is also called when a new dimension loads */
|
||||
public void worldLoadEvent(Level level)
|
||||
{
|
||||
@@ -155,8 +154,8 @@ public class ClientProxy
|
||||
// recreate the LOD where the blocks were changed
|
||||
eventApi.blockChangeEvent(chunk, dimType);
|
||||
}
|
||||
|
||||
private static final List<Integer> KEY_TO_CHECK_FOR = List.of(GLFW.GLFW_KEY_F6, GLFW.GLFW_KEY_F8);
|
||||
|
||||
private static final int[] KEY_TO_CHECK_FOR = {GLFW.GLFW_KEY_F6, GLFW.GLFW_KEY_F8};
|
||||
|
||||
HashSet<Integer> previousKeyDown = new HashSet<Integer>();
|
||||
|
||||
@@ -169,7 +168,7 @@ public class ClientProxy
|
||||
// Note: Minecraft's InputConstants is same as GLFW Key values
|
||||
//TODO: Use mixin to hook directly into the GLFW Keyboard event in minecraft KeyboardHandler
|
||||
// Check all keys we need
|
||||
for (int i = InputConstants.KEY_A; i <= InputConstants.KEY_Z; i++) {
|
||||
for (int i = GLFW.GLFW_KEY_A; i <= GLFW.GLFW_KEY_Z; i++) {
|
||||
if (InputConstants.isKeyDown(Minecraft.getInstance().getWindow().getWindow(), i)) {
|
||||
currectKeyDown.add(i);
|
||||
}
|
||||
|
||||
@@ -28,13 +28,10 @@ import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
|
||||
import com.seibel.lod.core.wrapperInterfaces.modAccessor.IModChecker;
|
||||
import com.seibel.lod.core.wrapperInterfaces.modAccessor.IOptifineAccessor;
|
||||
import com.seibel.lod.core.wrapperInterfaces.modAccessor.ISodiumAccessor;
|
||||
import com.seibel.lod.core.wrapperInterfaces.modAccessor.IStarlightAccessor;
|
||||
import com.seibel.lod.fabric.networking.NetworkHandler;
|
||||
import com.seibel.lod.fabric.wrappers.FabricDependencySetup;
|
||||
import com.seibel.lod.fabric.wrappers.modAccessor.ModChecker;
|
||||
import com.seibel.lod.fabric.wrappers.modAccessor.OptifineAccessor;
|
||||
import com.seibel.lod.fabric.wrappers.modAccessor.SodiumAccessor;
|
||||
import com.seibel.lod.fabric.wrappers.modAccessor.StarlightAccessor;
|
||||
import com.seibel.lod.fabric.wrappers.FabricDependencySetup;
|
||||
|
||||
import net.fabricmc.api.ClientModInitializer;
|
||||
|
||||
@@ -42,14 +39,14 @@ import net.fabricmc.api.ClientModInitializer;
|
||||
* Initialize and setup the Mod. <br>
|
||||
* If you are looking for the real start of the mod
|
||||
* check out the ClientProxy.
|
||||
*
|
||||
*
|
||||
* @author coolGi2007
|
||||
* @author Ran
|
||||
* @version 12-1-2021
|
||||
*/
|
||||
public class Main implements ClientModInitializer
|
||||
{
|
||||
// This is a client mod so it should implement ClientModInitializer and in fabric.mod.json it should have "environment": "client"
|
||||
// This is a client mod, so it should implement ClientModInitializer and in fabric.mod.json it should have "environment": "client"
|
||||
// Once it works on servers change the implement to ModInitializer and in fabric.mod.json it should be "environment": "*"
|
||||
|
||||
public static ClientProxy client_proxy;
|
||||
@@ -65,7 +62,7 @@ public class Main implements ClientModInitializer
|
||||
// This loads the mod after minecraft loads which doesn't causes a lot of issues
|
||||
public static void init() {
|
||||
LodCommonMain.initConfig();
|
||||
LodCommonMain.startup(null, false, new NetworkHandler());
|
||||
LodCommonMain.startup(null, false);
|
||||
FabricDependencySetup.createInitialBindings();
|
||||
FabricDependencySetup.finishBinding();
|
||||
ApiShared.LOGGER.info(ModInfo.READABLE_NAME + ", Version: " + ModInfo.VERSION);
|
||||
@@ -76,9 +73,6 @@ public class Main implements ClientModInitializer
|
||||
if (SingletonHandler.get(IModChecker.class).isModLoaded("sodium")) {
|
||||
ModAccessorHandler.bind(ISodiumAccessor.class, new SodiumAccessor());
|
||||
}
|
||||
if (SingletonHandler.get(IModChecker.class).isModLoaded("starlight")) {
|
||||
ModAccessorHandler.bind(IStarlightAccessor.class, new StarlightAccessor());
|
||||
}
|
||||
if (SingletonHandler.get(IModChecker.class).isModLoaded("optifine")) {
|
||||
ModAccessorHandler.bind(IOptifineAccessor.class, new OptifineAccessor());
|
||||
}
|
||||
@@ -88,7 +82,7 @@ public class Main implements ClientModInitializer
|
||||
|
||||
public static void initServer() {
|
||||
LodCommonMain.initConfig();
|
||||
LodCommonMain.startup(null, true, new NetworkHandler());
|
||||
LodCommonMain.startup(null, true);
|
||||
FabricDependencySetup.createInitialBindings();
|
||||
FabricDependencySetup.finishBinding();
|
||||
ApiShared.LOGGER.info(ModInfo.READABLE_NAME + ", Version: " + ModInfo.VERSION);
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.seibel.lod.fabric.mixins;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.server.level.WorldGenRegion;
|
||||
import net.minecraft.world.level.StructureFeatureManager;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.chunk.ChunkGenerator;
|
||||
import net.minecraft.world.level.levelgen.WorldgenRandom;
|
||||
|
||||
@Mixin(ChunkGenerator.class)
|
||||
public class MixinChunkGenerator {
|
||||
@Redirect(method = "applyBiomeDecoration", at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/world/level/biome/Biome;generate(Lnet/minecraft/world/level/StructureFeatureManager;"
|
||||
+ "Lnet/minecraft/world/level/chunk/ChunkGenerator;Lnet/minecraft/server/level/WorldGenRegion;J"
|
||||
+ "Lnet/minecraft/world/level/levelgen/WorldgenRandom;Lnet/minecraft/core/BlockPos;)V"
|
||||
|
||||
))
|
||||
private void wrapBiomeGenerateCall(Biome biome, StructureFeatureManager structFeatManager, ChunkGenerator generator,
|
||||
WorldGenRegion genRegion, long l, WorldgenRandom random, BlockPos pos) {
|
||||
synchronized((ChunkGenerator)(Object)this) {
|
||||
biome.generate(structFeatManager, (ChunkGenerator)(Object)this, genRegion, l, random, pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
package com.seibel.lod.fabric.mixins;
|
||||
|
||||
import com.seibel.lod.fabric.Main;
|
||||
import net.minecraft.server.dedicated.DedicatedServer;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
@Mixin(DedicatedServer.class)
|
||||
public class MixinDedicatedServer {
|
||||
@Inject(method = "initServer", at = @At("TAIL"))
|
||||
public void initServer(CallbackInfoReturnable<Boolean> cir) {
|
||||
Main.initServer();
|
||||
}
|
||||
}
|
||||
@@ -19,8 +19,8 @@ import net.minecraft.world.level.material.FogType;
|
||||
|
||||
@Mixin(FogRenderer.class)
|
||||
public class MixinFogRenderer {
|
||||
private static final ILodConfigWrapperSingleton CONFIG = SingletonHandler.get(ILodConfigWrapperSingleton.class);
|
||||
|
||||
private static final ILodConfigWrapperSingleton CONFIG = SingletonHandler.get(ILodConfigWrapperSingleton.class);
|
||||
|
||||
// Using this instead of Float.MAX_VALUE because Sodium don't like it.
|
||||
private static final float A_REALLY_REALLY_BIG_VALUE = 420694206942069.F;
|
||||
private static final float A_EVEN_LARGER_VALUE = 42069420694206942069.F;
|
||||
|
||||
@@ -22,7 +22,7 @@ import java.util.Objects;
|
||||
*
|
||||
* @author coolGi2007
|
||||
* @version 12-02-2021
|
||||
*/
|
||||
*/
|
||||
@Mixin(OptionsScreen.class)
|
||||
public class MixinOptionsScreen extends Screen {
|
||||
// Get the texture for the button
|
||||
@@ -35,18 +35,18 @@ public class MixinOptionsScreen extends Screen {
|
||||
private void lodconfig$init(CallbackInfo ci) {
|
||||
if (SingletonHandler.get(ILodConfigWrapperSingleton.class).client().getOptionsButton())
|
||||
this.addRenderableWidget(new TexturedButtonWidget(
|
||||
// Where the button is on the screen
|
||||
this.width / 2 - 180, this.height / 6 - 12,
|
||||
// Width and height of the button
|
||||
20, 20,
|
||||
// Offset
|
||||
0, 0,
|
||||
// Some textuary stuff
|
||||
20, ICON_TEXTURE, 20, 40,
|
||||
// Create the button and tell it where to go
|
||||
// For now it goes to the client option by default
|
||||
(buttonWidget) -> Objects.requireNonNull(minecraft).setScreen(ConfigGui.getScreen(this, "client")),
|
||||
// Add a title to the screen
|
||||
new TranslatableComponent("text.autoconfig." + ModInfo.ID + ".title")));
|
||||
// Where the button is on the screen
|
||||
this.width / 2 - 180, this.height / 6 - 12,
|
||||
// Width and height of the button
|
||||
20, 20,
|
||||
// Offset
|
||||
0, 0,
|
||||
// Some textuary stuff
|
||||
20, ICON_TEXTURE, 20, 40,
|
||||
// Create the button and tell it where to go
|
||||
// For now it goes to the client option by default
|
||||
(buttonWidget) -> Objects.requireNonNull(minecraft).setScreen(ConfigGui.getScreen(this, "client")),
|
||||
// Add a title to the screen
|
||||
new TranslatableComponent("text.autoconfig." + ModInfo.ID + ".title")));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.seibel.lod.fabric.mixins;
|
||||
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import com.seibel.lod.fabric.ClientProxy;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
@@ -9,13 +8,23 @@ import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import com.seibel.lod.core.util.DummyRunExecutorService;
|
||||
import com.seibel.lod.common.wrappers.DependencySetupDoneCheck;
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment;
|
||||
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
|
||||
import com.seibel.lod.core.wrapperInterfaces.IWrapperFactory;
|
||||
|
||||
import net.minecraft.Util;
|
||||
|
||||
@Mixin(Util.class)
|
||||
public class MixinUtilBackgroudThread
|
||||
{
|
||||
private static boolean doTriggerOverride() {
|
||||
try {
|
||||
return DependencySetupDoneCheck.getIsCurrentThreadDistantGeneratorThread.get();
|
||||
} catch (NullPointerException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "wrapThreadWithTaskName(Ljava/lang/String;Ljava/lang/Runnable;)Ljava/lang/Runnable;",
|
||||
at = @At("HEAD"), cancellable = true)
|
||||
@@ -23,28 +32,18 @@ public class MixinUtilBackgroudThread
|
||||
{
|
||||
if (ClientProxy.isGenerationThreadChecker != null && ClientProxy.isGenerationThreadChecker.get())
|
||||
{
|
||||
//ApiShared.LOGGER.info("util wrapThreadWithTaskName(Runnable) triggered");
|
||||
// ApiShared.LOGGER.info("util wrapThreadWithTaskName(Runnable) triggered");
|
||||
ci.setReturnValue(r);
|
||||
}
|
||||
}
|
||||
@Inject(method = "wrapThreadWithTaskName(Ljava/lang/String;Ljava/util/function/Supplier;)Ljava/util/function/Supplier;",
|
||||
at = @At("HEAD"), cancellable = true)
|
||||
private static void overrideUtil$wrapThreadWithTaskNameForSupplier(String string, Supplier<?> r, CallbackInfoReturnable<Supplier<?>> ci)
|
||||
{
|
||||
if (ClientProxy.isGenerationThreadChecker != null && ClientProxy.isGenerationThreadChecker.get())
|
||||
{
|
||||
//ApiShared.LOGGER.info("util wrapThreadWithTaskName(Supplier) triggered");
|
||||
ci.setReturnValue(r);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Inject(method = "backgroundExecutor", at = @At("HEAD"), cancellable = true)
|
||||
private static void overrideUtil$backgroundExecutor(CallbackInfoReturnable<ExecutorService> ci)
|
||||
private static void overrideUtil$backgroundExecutor(CallbackInfoReturnable<Executor> ci)
|
||||
{
|
||||
if (ClientProxy.isGenerationThreadChecker != null && ClientProxy.isGenerationThreadChecker.get())
|
||||
{
|
||||
//ApiShared.LOGGER.info("util backgroundExecutor triggered");
|
||||
ci.setReturnValue(new DummyRunExecutorService());
|
||||
// ApiShared.LOGGER.info("util backgroundExecutor triggered");
|
||||
ci.setReturnValue(Runnable::run);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,6 @@ import com.seibel.lod.common.Config;
|
||||
import com.seibel.lod.common.wrappers.McObjectConverter;
|
||||
import com.seibel.lod.core.api.ClientApi;
|
||||
import com.seibel.lod.core.objects.math.Mat4f;
|
||||
import net.minecraft.client.Camera;
|
||||
import net.minecraft.client.renderer.LevelRenderer;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
@@ -62,21 +61,6 @@ public class MixinWorldRenderer
|
||||
previousPartialTicks = tickDelta;
|
||||
}
|
||||
|
||||
/* Inject rendering at renderSky
|
||||
// HEAD or RETURN
|
||||
@Inject(at = @At("RETURN"),
|
||||
method = "renderSky",
|
||||
cancellable = true)
|
||||
private void renderLod(PoseStack modelViewMatrixStack, Matrix4f projectionMatrix, float f,
|
||||
#if MC_VERSION_1_18_2 Camera camera, boolean bl,#endif Runnable r, CallbackInfo callback) {
|
||||
|
||||
Mat4f mcModelViewMatrix = McObjectConverter.Convert(modelViewMatrixStack.last().pose());
|
||||
Mat4f mcProjectionMatrix = McObjectConverter.Convert(projectionMatrix);
|
||||
|
||||
ClientApi.INSTANCE.renderLods(mcModelViewMatrix, mcProjectionMatrix, previousPartialTicks);
|
||||
|
||||
}*/
|
||||
|
||||
// Inject rendering at first call to renderChunkLayer
|
||||
// HEAD or RETURN
|
||||
@Inject(at = @At("HEAD"),
|
||||
|
||||
@@ -18,10 +18,11 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
*/
|
||||
@Mixin(ClientboundBlockUpdatePacket.class)
|
||||
public abstract class MixinBlockUpdate {
|
||||
@Shadow public abstract BlockPos getPos();
|
||||
@Shadow
|
||||
public abstract BlockPos getPos();
|
||||
|
||||
@Inject(method = "handle(Lnet/minecraft/network/protocol/game/ClientGamePacketListener;)V", at = @At("TAIL"))
|
||||
private void onBlockUpdate(ClientGamePacketListener clientGamePacketListener, CallbackInfo ci) {
|
||||
Main.client_proxy.blockChangeEvent(Minecraft.getInstance().player.clientLevel, this.getPos());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,11 +4,9 @@ import com.seibel.lod.fabric.Main;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.client.multiplayer.ClientPacketListener;
|
||||
import net.minecraft.client.renderer.LevelRenderer;
|
||||
#if MC_VERSION_1_18_2
|
||||
import net.minecraft.core.Holder;
|
||||
#endif
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.world.level.chunk.LevelChunk;
|
||||
import net.minecraft.util.profiling.ProfilerFiller;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.dimension.DimensionType;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
@@ -21,26 +19,10 @@ import java.util.function.Supplier;
|
||||
* This class is used for world loading events
|
||||
* @author Ran
|
||||
*/
|
||||
|
||||
@Mixin(ClientLevel.class)
|
||||
public class MixinClientLevel {
|
||||
#if MC_VERSION_1_18_2
|
||||
@Inject(method = "<init>", at = @At("TAIL"))
|
||||
private void loadWorldEvent(ClientPacketListener clientPacketListener, ClientLevel.ClientLevelData clientLevelData, ResourceKey resourceKey, Holder holder, int i, int j, Supplier supplier, LevelRenderer levelRenderer, boolean bl, long l, CallbackInfo ci) {
|
||||
private void loadWorldEvent(ClientPacketListener clientPacketListener, ClientLevel.ClientLevelData clientLevelData, ResourceKey<Level> resourceKey, DimensionType dimensionType, int i, Supplier<ProfilerFiller> supplier, LevelRenderer levelRenderer, boolean bl, long l, CallbackInfo ci) {
|
||||
Main.client_proxy.worldLoadEvent((ClientLevel) (Object) this);
|
||||
}
|
||||
#elif MC_VERSION_1_18_1
|
||||
@Inject(method = "<init>", at = @At("TAIL"))
|
||||
private void loadWorldEvent(ClientPacketListener clientPacketListener, ClientLevel.ClientLevelData clientLevelData, ResourceKey resourceKey, DimensionType dimensionType, int i, int j, Supplier supplier, LevelRenderer levelRenderer, boolean bl, long l, CallbackInfo ci) {
|
||||
Main.client_proxy.worldLoadEvent((ClientLevel) (Object) this);
|
||||
}
|
||||
#endif
|
||||
|
||||
@Inject(method = "setLightReady", at = @At("HEAD"))
|
||||
private void onChunkLightReady(int x, int z, CallbackInfo ci) {
|
||||
ClientLevel l = (ClientLevel) (Object) this;
|
||||
LevelChunk chunk = l.getChunkSource().getChunk(x, z, false);
|
||||
if (chunk!=null && !chunk.isClientLightReady())
|
||||
Main.client_proxy.chunkLoadEvent(l, chunk);
|
||||
}
|
||||
}
|
||||
|
||||
+7
-6
@@ -1,9 +1,8 @@
|
||||
package com.seibel.lod.fabric.mixins.unsafe;
|
||||
|
||||
import net.minecraft.util.ThreadingDetector;
|
||||
import net.minecraft.world.level.chunk.PalettedContainer;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Mutable;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
@@ -11,12 +10,14 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import java.util.concurrent.Semaphore;
|
||||
|
||||
/**
|
||||
* Why does this exist? But okay! (Will be probably removed when the experimental generator is done)
|
||||
* NOTE: THIS IS NOT A FIX TO THE PROBLEM.
|
||||
* TODO: Do/Find an actual fix to this
|
||||
*
|
||||
* @author Ran
|
||||
*/
|
||||
@Mixin(ThreadingDetector.class)
|
||||
public class MixinThreadingDectector {
|
||||
@Mixin(PalettedContainer.class)
|
||||
public class MixinPalettedContainer {
|
||||
@Mutable
|
||||
@Shadow
|
||||
private Semaphore lock;
|
||||
|
||||
@Inject(method = "<init>", at = @At("RETURN"))
|
||||
@@ -1,25 +0,0 @@
|
||||
package com.seibel.lod.fabric.networking;
|
||||
|
||||
import com.seibel.lod.common.networking.NetworkInterface;
|
||||
import com.seibel.lod.common.networking.Networking;
|
||||
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
|
||||
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
|
||||
|
||||
/**
|
||||
* @author Ran
|
||||
*/
|
||||
public class NetworkHandler implements NetworkInterface {
|
||||
@Override
|
||||
public void register_Client() {
|
||||
ClientPlayNetworking.registerGlobalReceiver(Networking.resourceLocation_meow, (client, handler, buf, responseSender) -> {
|
||||
com.seibel.lod.common.networking.NetworkHandler.receivePacketClient(client, handler, buf);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register_Server() {
|
||||
ServerPlayNetworking.registerGlobalReceiver(Networking.resourceLocation_meow, (server, player, handler, buf, responseSender) -> {
|
||||
com.seibel.lod.common.networking.NetworkHandler.receivePacketServer(server, player, handler, buf);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@ import com.seibel.lod.fabric.wrappers.modAccessor.ModChecker;
|
||||
*
|
||||
* @author James Seibel
|
||||
* @author Ran
|
||||
* @version 3-5-2022
|
||||
* @version 12-1-2021
|
||||
*/
|
||||
public class FabricDependencySetup
|
||||
{
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
|
||||
package com.seibel.lod.fabric.wrappers.modAccessor;
|
||||
|
||||
import com.seibel.lod.core.wrapperInterfaces.modAccessor.IModChecker;
|
||||
|
||||
+12
-12
@@ -8,17 +8,17 @@ import com.seibel.lod.core.wrapperInterfaces.modAccessor.IOptifineAccessor;
|
||||
public class OptifineAccessor implements IOptifineAccessor
|
||||
{
|
||||
|
||||
@Override
|
||||
public String getModName()
|
||||
{
|
||||
return "Optifine-Fabric-1.18.X";
|
||||
}
|
||||
@Override
|
||||
public String getModName()
|
||||
{
|
||||
return "Optifine-Fabric-1.18.X";
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashSet<AbstractChunkPosWrapper> getNormalRenderedChunks()
|
||||
{
|
||||
// TODO: Impl proper methods here
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashSet<AbstractChunkPosWrapper> getNormalRenderedChunks()
|
||||
{
|
||||
// TODO: Impl proper methods here
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+14
-20
@@ -4,39 +4,33 @@ import java.util.HashSet;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
|
||||
import com.seibel.lod.core.wrapperInterfaces.IWrapperFactory;
|
||||
import com.seibel.lod.core.wrapperInterfaces.chunk.AbstractChunkPosWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.modAccessor.ISodiumAccessor;
|
||||
|
||||
|
||||
import me.jellysquid.mods.sodium.client.render.SodiumWorldRenderer;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.world.level.LevelHeightAccessor;
|
||||
|
||||
public class SodiumAccessor implements ISodiumAccessor {
|
||||
IWrapperFactory factory = SingletonHandler.get(IWrapperFactory.class);
|
||||
private final IMinecraftRenderWrapper MC_RENDER = SingletonHandler.get(IMinecraftRenderWrapper.class);
|
||||
|
||||
@Override
|
||||
public String getModName() {
|
||||
return "Sodium-Fabric-1.18.X";
|
||||
@Override
|
||||
public String getModName() {
|
||||
return "Sodium-Fabric-1.17.1";
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashSet<AbstractChunkPosWrapper> getNormalRenderedChunks() {
|
||||
SodiumWorldRenderer renderer = SodiumWorldRenderer.instance();
|
||||
LevelHeightAccessor height = Minecraft.getInstance().level;
|
||||
// 0b11 = Lighted chunk & loaded chunk
|
||||
return renderer.getChunkTracker().getChunks(0b00).filter(
|
||||
(long l) -> {
|
||||
return true;
|
||||
//for (int i = height.getMinSection(); i<height.getMaxSection(); i++) {
|
||||
// SectionPos p = SectionPos.of(new ChunkPos(l), i);
|
||||
// if (renderer.isBoxVisible(p.minBlockX()+1, p.minBlockY()+1, p.minBlockZ()+1,
|
||||
// p.maxBlockX()-1, p.maxBlockY()-1, p.maxBlockZ()-1)) return true;
|
||||
//}
|
||||
//return false;
|
||||
}).mapToObj((long l) -> {
|
||||
return (AbstractChunkPosWrapper)factory.createChunkPos(l);
|
||||
}).collect(Collectors.toCollection(HashSet::new));
|
||||
LevelHeightAccessor height = Minecraft.getInstance().level;
|
||||
|
||||
// TODO: Maybe use a mixin to make this more efficient
|
||||
return MC_RENDER.getMaximumRenderedChunks().stream().filter((AbstractChunkPosWrapper chunk) -> {
|
||||
return (renderer.isBoxVisible(
|
||||
chunk.getMinBlockX()+1, height.getMinBuildHeight()+1, chunk.getMinBlockZ()+1,
|
||||
chunk.getMinBlockX()+15, height.getMaxBuildHeight()-1, chunk.getMinBlockZ()+15));
|
||||
}).collect(Collectors.toCollection(HashSet::new));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
-16
@@ -1,16 +0,0 @@
|
||||
package com.seibel.lod.fabric.wrappers.modAccessor;
|
||||
|
||||
import com.seibel.lod.core.wrapperInterfaces.modAccessor.IStarlightAccessor;
|
||||
|
||||
|
||||
public class StarlightAccessor implements IStarlightAccessor {
|
||||
|
||||
@Override
|
||||
public String getModName() {
|
||||
return "Starlight-Fabric-1.18.X";
|
||||
}
|
||||
|
||||
public StarlightAccessor() {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -455,4 +455,4 @@ FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
@@ -2,11 +2,12 @@
|
||||
"required": true,
|
||||
"minVersion": "0.8",
|
||||
"package": "com.seibel.lod.fabric.mixins",
|
||||
"compatibilityLevel": "JAVA_17",
|
||||
"compatibilityLevel": "JAVA_16",
|
||||
"mixins": [
|
||||
"unsafe.MixinThreadingDectector",
|
||||
"MixinUtilBackgroudThread",
|
||||
"events.MixinServerLevel"
|
||||
"events.MixinServerLevel",
|
||||
"unsafe.MixinPalettedContainer",
|
||||
"MixinChunkGenerator",
|
||||
"MixinUtilBackgroudThread"
|
||||
],
|
||||
"client": [
|
||||
"MixinMinecraft",
|
||||
@@ -17,10 +18,8 @@
|
||||
"events.MixinMinecraft",
|
||||
"events.MixinBlockUpdate"
|
||||
],
|
||||
"server": [
|
||||
"MixinDedicatedServer"
|
||||
],
|
||||
"server": [],
|
||||
"injectors": {
|
||||
"defaultRequire": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
+10
-12
@@ -1,5 +1,5 @@
|
||||
plugins {
|
||||
id "com.github.johnrengelman.shadow" version "7.1.0"
|
||||
id "com.github.johnrengelman.shadow" version "7.0.0"
|
||||
}
|
||||
|
||||
version = rootProject.mod_version+"-"+rootProject.minecraft_version+"-"+new Date().format("yyyy_MM_dd_HH_mm")
|
||||
@@ -19,12 +19,6 @@ architectury {
|
||||
forge()
|
||||
}
|
||||
|
||||
configurations {
|
||||
compileClasspath.extendsFrom common
|
||||
runtimeClasspath.extendsFrom common
|
||||
developmentForge.extendsFrom common
|
||||
}
|
||||
|
||||
def addMod(path, enabled) {
|
||||
if (enabled == "2")
|
||||
dependencies { modImplementation(path) }
|
||||
@@ -32,24 +26,28 @@ def addMod(path, enabled) {
|
||||
dependencies { modCompileOnly(path) }
|
||||
}
|
||||
|
||||
configurations {
|
||||
compileClasspath.extendsFrom common
|
||||
runtimeClasspath.extendsFrom common
|
||||
developmentForge.extendsFrom common
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// Forge loader
|
||||
forge "net.minecraftforge:forge:${rootProject.minecraft_version}-${rootProject.forge_version}"
|
||||
|
||||
// Starlight
|
||||
addMod("curse.maven:starlight-forge-526854:${rootProject.starlight_version_forge}", rootProject.enable_starlight_forge)
|
||||
annotationProcessor "org.spongepowered:mixin:0.8.4:processor"
|
||||
|
||||
common(project(path: ":common", configuration: "namedElements")) { transitive false }
|
||||
shadowMe(project(path: ":common", configuration: "transformProductionForge")) { transitive = false }
|
||||
|
||||
// Starlight
|
||||
addMod("curse.maven:starlight-forge-526854:${rootProject.starlight_version_forge}", rootProject.enable_starlight_forge)
|
||||
|
||||
// forgeDependencies(project(":core")) { transitive false }
|
||||
|
||||
|
||||
// Toml
|
||||
shadowMe("com.electronwill.night-config:toml:${rootProject.toml_version}") {}
|
||||
|
||||
// Compression
|
||||
forgeDependencies('org.tukaani:xz:1.9')
|
||||
forgeDependencies('org.apache.commons:commons-compress:1.21')
|
||||
shadowMe 'org.tukaani:xz:1.9'
|
||||
|
||||
@@ -23,8 +23,6 @@ import com.seibel.lod.core.api.ClientApi;
|
||||
import com.seibel.lod.core.api.EventApi;
|
||||
import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
|
||||
import com.seibel.lod.common.wrappers.chunk.ChunkWrapper;
|
||||
@@ -42,7 +40,7 @@ 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
|
||||
*/
|
||||
@@ -50,28 +48,28 @@ public class ForgeClientProxy
|
||||
{
|
||||
private final EventApi eventApi = EventApi.INSTANCE;
|
||||
private final ClientApi clientApi = ClientApi.INSTANCE;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@SubscribeEvent
|
||||
public void serverTickEvent(TickEvent.ServerTickEvent event)
|
||||
{
|
||||
if (event.phase != TickEvent.Phase.START) return;
|
||||
eventApi.serverTickEvent();
|
||||
}
|
||||
|
||||
|
||||
@SubscribeEvent
|
||||
public void chunkLoadEvent(ChunkEvent.Load event)
|
||||
{
|
||||
clientApi.clientChunkLoadEvent(new ChunkWrapper(event.getChunk(), event.getWorld()), WorldWrapper.getWorldWrapper(event.getWorld()));
|
||||
}
|
||||
|
||||
|
||||
@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)
|
||||
@@ -80,13 +78,13 @@ public class ForgeClientProxy
|
||||
eventApi.worldLoadEvent(WorldWrapper.getWorldWrapper(event.getWorld()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@SubscribeEvent
|
||||
public void worldUnloadEvent(WorldEvent.Unload event)
|
||||
{
|
||||
eventApi.worldUnloadEvent(WorldWrapper.getWorldWrapper(event.getWorld()));
|
||||
}
|
||||
|
||||
|
||||
@SubscribeEvent
|
||||
public void blockChangeEvent(BlockEvent event)
|
||||
{
|
||||
@@ -99,12 +97,12 @@ public class ForgeClientProxy
|
||||
{
|
||||
IChunkWrapper chunk = new ChunkWrapper(event.getWorld().getChunk(event.getPos()), event.getWorld());
|
||||
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)
|
||||
{
|
||||
@@ -112,7 +110,5 @@ public class ForgeClientProxy
|
||||
if (event.getAction() != GLFW.GLFW_PRESS) return;
|
||||
clientApi.keyPressedEvent(event.getKey());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -25,20 +25,22 @@ import com.seibel.lod.common.wrappers.config.ConfigGui;
|
||||
import com.seibel.lod.common.wrappers.minecraft.MinecraftClientWrapper;
|
||||
import com.seibel.lod.core.ModInfo;
|
||||
import com.seibel.lod.core.api.ApiShared;
|
||||
import com.seibel.lod.core.handlers.ReflectionHandler;
|
||||
import com.seibel.lod.core.api.ClientApi;
|
||||
import com.seibel.lod.core.handlers.dependencyInjection.ModAccessorHandler;
|
||||
import com.seibel.lod.core.handlers.ReflectionHandler;
|
||||
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
|
||||
import com.seibel.lod.core.wrapperInterfaces.modAccessor.IModChecker;
|
||||
import com.seibel.lod.core.wrapperInterfaces.modAccessor.IOptifineAccessor;
|
||||
import com.seibel.lod.forge.networking.NetworkHandler;
|
||||
import com.seibel.lod.forge.wrappers.ForgeDependencySetup;
|
||||
|
||||
import com.seibel.lod.forge.wrappers.modAccessor.ModChecker;
|
||||
import com.seibel.lod.forge.wrappers.modAccessor.OptifineAccessor;
|
||||
|
||||
import net.minecraft.client.renderer.block.model.BakedQuad;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraftforge.client.model.data.ModelDataMap;
|
||||
import net.minecraftforge.client.ConfigGuiHandler;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.fml.ModLoadingContext;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
@@ -46,6 +48,7 @@ import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
|
||||
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
|
||||
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
|
||||
import net.minecraftforge.fml.loading.FMLLoader;
|
||||
import net.minecraftforge.fmlclient.ConfigGuiHandler;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
@@ -54,7 +57,7 @@ import java.util.Random;
|
||||
* 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-21-2021
|
||||
*/
|
||||
@@ -62,22 +65,25 @@ import java.util.Random;
|
||||
public class ForgeMain implements LodForgeMethodCaller
|
||||
{
|
||||
public static ForgeClientProxy forgeClientProxy;
|
||||
|
||||
|
||||
private void init(final FMLCommonSetupEvent event)
|
||||
{
|
||||
// make sure the dependencies are set up before the mod needs them
|
||||
LodCommonMain.initConfig();
|
||||
LodCommonMain.startup(this, !FMLLoader.getDist().isClient(), new NetworkHandler());
|
||||
LodCommonMain.startup(this, !FMLLoader.getDist().isClient());
|
||||
ForgeDependencySetup.createInitialBindings();
|
||||
ForgeDependencySetup.finishBinding();
|
||||
ApiShared.LOGGER.info("Distant Horizons initializing...");
|
||||
}
|
||||
|
||||
|
||||
|
||||
public ForgeMain()
|
||||
{
|
||||
// Register the methods for server and other game events we are interested in
|
||||
// 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)
|
||||
@@ -85,9 +91,9 @@ public class ForgeMain implements LodForgeMethodCaller
|
||||
if (ReflectionHandler.instance.optifinePresent()) {
|
||||
ModAccessorHandler.bind(IOptifineAccessor.class, new OptifineAccessor());
|
||||
}
|
||||
|
||||
|
||||
ModAccessorHandler.finishBinding();
|
||||
|
||||
|
||||
|
||||
ModAccessorHandler.finishBinding();
|
||||
|
||||
@@ -97,9 +103,15 @@ public class ForgeMain implements LodForgeMethodCaller
|
||||
MinecraftForge.EVENT_BUS.register(forgeClientProxy);
|
||||
}
|
||||
|
||||
private final ModelDataMap dataMap = new ModelDataMap.Builder().build();
|
||||
private ModelDataMap dataMap = new ModelDataMap.Builder().build();
|
||||
@Override
|
||||
public List<BakedQuad> getQuads(MinecraftClientWrapper mc, Block block, BlockState blockState, Direction direction, Random random) {
|
||||
return mc.getModelManager().getBlockModelShaper().getBlockModel(block.defaultBlockState()).getQuads(blockState, direction, random, dataMap);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getPixelRGBA(TextureAtlasSprite sprite, int frameIndex, int x, int y) {
|
||||
return sprite.getPixelRGBA(frameIndex, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
-72
@@ -1,72 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.forge.fabric.api.client.networking.v1;
|
||||
|
||||
import java.util.List;
|
||||
import com.seibel.lod.forge.fabric.api.event.Event;
|
||||
import com.seibel.lod.forge.fabric.api.event.EventFactory;
|
||||
import com.seibel.lod.forge.fabric.api.networking.v1.PacketSender;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.ClientPacketListener;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
/**
|
||||
* Offers access to events related to the indication of a connected server's ability to receive packets in certain channels.
|
||||
*/
|
||||
|
||||
public final class C2SPlayChannelEvents {
|
||||
/**
|
||||
* An event for the client play network handler receiving an update indicating the connected server's ability to receive packets in certain channels.
|
||||
* This event may be invoked at any time after login and up to disconnection.
|
||||
*/
|
||||
public static final Event<Register> REGISTER = EventFactory.createArrayBacked(Register.class, callbacks -> (handler, sender, client, channels) -> {
|
||||
for (Register callback : callbacks) {
|
||||
callback.onChannelRegister(handler, sender, client, channels);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* An event for the client play network handler receiving an update indicating the connected server's lack of ability to receive packets in certain channels.
|
||||
* This event may be invoked at any time after login and up to disconnection.
|
||||
*/
|
||||
public static final Event<Unregister> UNREGISTER = EventFactory.createArrayBacked(Unregister.class, callbacks -> (handler, sender, client, channels) -> {
|
||||
for (Unregister callback : callbacks) {
|
||||
callback.onChannelUnregister(handler, sender, client, channels);
|
||||
}
|
||||
});
|
||||
|
||||
private C2SPlayChannelEvents() {
|
||||
}
|
||||
|
||||
/**
|
||||
* @see C2SPlayChannelEvents#REGISTER
|
||||
*/
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Register {
|
||||
void onChannelRegister(ClientPacketListener handler, PacketSender sender, Minecraft client, List<ResourceLocation> channels);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see C2SPlayChannelEvents#UNREGISTER
|
||||
*/
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Unregister {
|
||||
void onChannelUnregister(ClientPacketListener handler, PacketSender sender, Minecraft client, List<ResourceLocation> channels);
|
||||
}
|
||||
}
|
||||
-103
@@ -1,103 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.forge.fabric.api.client.networking.v1;
|
||||
|
||||
import com.seibel.lod.forge.fabric.api.event.Event;
|
||||
import com.seibel.lod.forge.fabric.api.event.EventFactory;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.ClientHandshakePacketListenerImpl;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
/**
|
||||
* Offers access to events related to the connection to a server on the client while the server is processing the client's login request.
|
||||
*/
|
||||
|
||||
public final class ClientLoginConnectionEvents {
|
||||
/**
|
||||
* Event indicating a connection entered the LOGIN state, ready for registering query request handlers.
|
||||
* This event may be used by mods to prepare their client side state.
|
||||
* This event does not guarantee that a login attempt will be successful.
|
||||
*
|
||||
* @see ClientLoginNetworking#registerReceiver(ResourceLocation, ClientLoginNetworking.LoginQueryRequestHandler)
|
||||
*/
|
||||
public static final Event<Init> INIT = EventFactory.createArrayBacked(Init.class, callbacks -> (handler, client) -> {
|
||||
for (Init callback : callbacks) {
|
||||
callback.onLoginStart(handler, client);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* An event for when the client has started receiving login queries.
|
||||
* A client can only start receiving login queries when a server has sent the first login query.
|
||||
* Vanilla servers will typically never make the client enter this login phase, but it is not a guarantee that the
|
||||
* connected server is a vanilla server since a modded server or proxy may have no login queries to send to the client
|
||||
* and therefore bypass the login query phase.
|
||||
* If this event is fired then it is a sign that a server is not a vanilla server or the server is behind a proxy which
|
||||
* is capable of handling login queries.
|
||||
*
|
||||
* <p>This event may be used to {@link ClientLoginNetworking.LoginQueryRequestHandler register login query handlers}
|
||||
* which may be used to send a response to a server.
|
||||
*
|
||||
* <p>No packets should be sent when this event is invoked.
|
||||
*/
|
||||
public static final Event<QueryStart> QUERY_START = EventFactory.createArrayBacked(QueryStart.class, callbacks -> (handler, client) -> {
|
||||
for (QueryStart callback : callbacks) {
|
||||
callback.onLoginQueryStart(handler, client);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* An event for when the client's login process has ended due to disconnection.
|
||||
*
|
||||
* <p>No packets should be sent when this event is invoked.
|
||||
*/
|
||||
public static final Event<Disconnect> DISCONNECT = EventFactory.createArrayBacked(Disconnect.class, callbacks -> (handler, client) -> {
|
||||
for (Disconnect callback : callbacks) {
|
||||
callback.onLoginDisconnect(handler, client);
|
||||
}
|
||||
});
|
||||
|
||||
private ClientLoginConnectionEvents() {
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ClientLoginConnectionEvents#INIT
|
||||
*/
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Init {
|
||||
void onLoginStart(ClientHandshakePacketListenerImpl handler, Minecraft client);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ClientLoginConnectionEvents#QUERY_START
|
||||
*/
|
||||
|
||||
@FunctionalInterface
|
||||
public interface QueryStart {
|
||||
void onLoginQueryStart(ClientHandshakePacketListenerImpl handler, Minecraft client);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ClientLoginConnectionEvents#DISCONNECT
|
||||
*/
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Disconnect {
|
||||
void onLoginDisconnect(ClientHandshakePacketListenerImpl handler, Minecraft client);
|
||||
}
|
||||
}
|
||||
-161
@@ -1,161 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.forge.fabric.api.client.networking.v1;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import io.netty.util.concurrent.Future;
|
||||
import io.netty.util.concurrent.GenericFutureListener;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import com.seibel.lod.forge.fabric.api.networking.v1.ServerLoginNetworking;
|
||||
import com.seibel.lod.forge.fabric.impl.networking.client.ClientNetworkingImpl;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.ClientHandshakePacketListenerImpl;
|
||||
import net.minecraft.network.Connection;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.network.PacketListener;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
/**
|
||||
* Offers access to login stage client-side networking functionalities.
|
||||
*
|
||||
* <p>The Minecraft login protocol only allows the client to respond to a server's request, but not initiate one of its own.
|
||||
*
|
||||
* @see ClientPlayNetworking
|
||||
* @see ServerLoginNetworking
|
||||
*/
|
||||
|
||||
public final class ClientLoginNetworking {
|
||||
/**
|
||||
* Registers a handler to a query request channel.
|
||||
* A global receiver is registered to all connections, in the present and future.
|
||||
*
|
||||
* <p>If a handler is already registered to the {@code channel}, this method will return {@code false}, and no change will be made.
|
||||
* Use {@link #unregisterGlobalReceiver(ResourceLocation)} to unregister the existing handler.
|
||||
*
|
||||
* @param channelName the id of the channel
|
||||
* @param queryHandler the handler
|
||||
* @return false if a handler is already registered to the channel
|
||||
* @see ClientLoginNetworking#unregisterGlobalReceiver(ResourceLocation)
|
||||
* @see ClientLoginNetworking#registerReceiver(ResourceLocation, LoginQueryRequestHandler)
|
||||
*/
|
||||
public static boolean registerGlobalReceiver(ResourceLocation channelName, LoginQueryRequestHandler queryHandler) {
|
||||
return ClientNetworkingImpl.LOGIN.registerGlobalReceiver(channelName, queryHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the handler of a query request channel.
|
||||
* A global receiver is registered to all connections, in the present and future.
|
||||
*
|
||||
* <p>The {@code channel} is guaranteed not to have a handler after this call.
|
||||
*
|
||||
* @param channelName the id of the channel
|
||||
* @return the previous handler, or {@code null} if no handler was bound to the channel
|
||||
* @see ClientLoginNetworking#registerGlobalReceiver(ResourceLocation, LoginQueryRequestHandler)
|
||||
* @see ClientLoginNetworking#unregisterReceiver(ResourceLocation)
|
||||
*/
|
||||
@Nullable
|
||||
public static ClientLoginNetworking.LoginQueryRequestHandler unregisterGlobalReceiver(ResourceLocation channelName) {
|
||||
return ClientNetworkingImpl.LOGIN.unregisterGlobalReceiver(channelName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all query request channel names which global receivers are registered for.
|
||||
* A global receiver is registered to all connections, in the present and future.
|
||||
*
|
||||
* @return all channel names which global receivers are registered for.
|
||||
*/
|
||||
public static Set<ResourceLocation> getGlobalReceivers() {
|
||||
return ClientNetworkingImpl.LOGIN.getChannels();
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a handler to a query request channel.
|
||||
*
|
||||
* <p>If a handler is already registered to the {@code channelName}, this method will return {@code false}, and no change will be made.
|
||||
* Use {@link #unregisterReceiver(ResourceLocation)} to unregister the existing handler.
|
||||
*
|
||||
* @param channelName the id of the channel
|
||||
* @param queryHandler the handler
|
||||
* @return false if a handler is already registered to the channel name
|
||||
* @throws IllegalStateException if the client is not logging in
|
||||
*/
|
||||
public static boolean registerReceiver(ResourceLocation channelName, LoginQueryRequestHandler queryHandler) throws IllegalStateException {
|
||||
final Connection connection = ClientNetworkingImpl.getLoginConnection();
|
||||
|
||||
if (connection != null) {
|
||||
final PacketListener packetListener = connection.getPacketListener();
|
||||
|
||||
if (packetListener instanceof ClientHandshakePacketListenerImpl) {
|
||||
return ClientNetworkingImpl.getAddon(((ClientHandshakePacketListenerImpl) packetListener)).registerChannel(channelName, queryHandler);
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalStateException("Cannot register receiver while client is not logging in!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the handler of a query request channel.
|
||||
*
|
||||
* <p>The {@code channelName} is guaranteed not to have a handler after this call.
|
||||
*
|
||||
* @param channelName the id of the channel
|
||||
* @return the previous handler, or {@code null} if no handler was bound to the channel name
|
||||
* @throws IllegalStateException if the client is not logging in
|
||||
*/
|
||||
@Nullable
|
||||
public static LoginQueryRequestHandler unregisterReceiver(ResourceLocation channelName) throws IllegalStateException {
|
||||
final Connection connection = ClientNetworkingImpl.getLoginConnection();
|
||||
|
||||
if (connection != null) {
|
||||
final PacketListener packetListener = connection.getPacketListener();
|
||||
|
||||
if (packetListener instanceof ClientHandshakePacketListenerImpl) {
|
||||
return ClientNetworkingImpl.getAddon(((ClientHandshakePacketListenerImpl) packetListener)).unregisterChannel(channelName);
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalStateException("Cannot unregister receiver while client is not logging in!");
|
||||
}
|
||||
|
||||
private ClientLoginNetworking() {
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface LoginQueryRequestHandler {
|
||||
/**
|
||||
* Handles an incoming query request from a server.
|
||||
*
|
||||
* <p>This method is executed on {@linkplain io.netty.channel.EventLoop netty's event loops}.
|
||||
* Modification to the game should be {@linkplain net.minecraft.util.thread.BlockableEventLoop#submit(Runnable) scheduled} using the provided Minecraft client instance.
|
||||
*
|
||||
* <p>The return value of this method is a completable future that may be used to delay the login process to the server until a task {@link CompletableFuture#isDone() is done}.
|
||||
* The future should complete in reasonably time to prevent disconnection by the server.
|
||||
* If your request processes instantly, you may use {@link CompletableFuture#completedFuture(Object)} to wrap your response for immediate sending.
|
||||
*
|
||||
* @param client the client
|
||||
* @param handler the network handler that received this packet
|
||||
* @param buf the payload of the packet
|
||||
* @param listenerAdder listeners to be called when the response packet is sent to the server
|
||||
* @return a completable future which contains the payload to respond to the server with.
|
||||
* If the future contains {@code null}, then the server will be notified that the client did not understand the query.
|
||||
*/
|
||||
CompletableFuture<@Nullable FriendlyByteBuf> receive(Minecraft client, ClientHandshakePacketListenerImpl handler, FriendlyByteBuf buf, Consumer<GenericFutureListener<? extends Future<? super Void>>> listenerAdder);
|
||||
}
|
||||
}
|
||||
-85
@@ -1,85 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.forge.fabric.api.client.networking.v1;
|
||||
|
||||
import com.seibel.lod.forge.fabric.api.event.Event;
|
||||
import com.seibel.lod.forge.fabric.api.event.EventFactory;
|
||||
import com.seibel.lod.forge.fabric.api.networking.v1.PacketSender;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.ClientPacketListener;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
/**
|
||||
* Offers access to events related to the connection to a server on a logical client.
|
||||
*/
|
||||
|
||||
public final class ClientPlayConnectionEvents {
|
||||
/**
|
||||
* Event indicating a connection entered the PLAY state, ready for registering channel handlers.
|
||||
*
|
||||
* @see ClientPlayNetworking#registerReceiver(ResourceLocation, ClientPlayNetworking.PlayChannelHandler)
|
||||
*/
|
||||
public static final Event<Init> INIT = EventFactory.createArrayBacked(Init.class, callbacks -> (handler, client) -> {
|
||||
for (Init callback : callbacks) {
|
||||
callback.onPlayInit(handler, client);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* An event for notification when the client play network handler is ready to send packets to the server.
|
||||
*
|
||||
* <p>At this stage, the network handler is ready to send packets to the server.
|
||||
* Since the client's local state has been setup.
|
||||
*/
|
||||
public static final Event<Join> JOIN = EventFactory.createArrayBacked(Join.class, callbacks -> (handler, sender, client) -> {
|
||||
for (Join callback : callbacks) {
|
||||
callback.onPlayReady(handler, sender, client);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* An event for the disconnection of the client play network handler.
|
||||
*
|
||||
* <p>No packets should be sent when this event is invoked.
|
||||
*/
|
||||
public static final Event<Disconnect> DISCONNECT = EventFactory.createArrayBacked(Disconnect.class, callbacks -> (handler, client) -> {
|
||||
for (Disconnect callback : callbacks) {
|
||||
callback.onPlayDisconnect(handler, client);
|
||||
}
|
||||
});
|
||||
|
||||
private ClientPlayConnectionEvents() {
|
||||
}
|
||||
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Init {
|
||||
void onPlayInit(ClientPacketListener handler, Minecraft client);
|
||||
}
|
||||
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Join {
|
||||
void onPlayReady(ClientPacketListener handler, PacketSender sender, Minecraft client);
|
||||
}
|
||||
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Disconnect {
|
||||
void onPlayDisconnect(ClientPacketListener handler, Minecraft client);
|
||||
}
|
||||
}
|
||||
-256
@@ -1,256 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.forge.fabric.api.client.networking.v1;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import com.seibel.lod.forge.fabric.api.networking.v1.PacketSender;
|
||||
import com.seibel.lod.forge.fabric.api.networking.v1.ServerPlayNetworking;
|
||||
import com.seibel.lod.forge.fabric.impl.networking.client.ClientNetworkingImpl;
|
||||
import com.seibel.lod.forge.fabric.impl.networking.client.ClientPlayNetworkAddon;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.ClientPacketListener;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.network.protocol.Packet;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
/**
|
||||
* Offers access to play stage client-side networking functionalities.
|
||||
*
|
||||
* <p>Client-side networking functionalities include receiving clientbound packets,
|
||||
* sending serverbound packets, and events related to client-side network handlers.
|
||||
*
|
||||
* <p>This class should be only used on the physical client and for the logical client.
|
||||
*
|
||||
* @see ClientLoginNetworking
|
||||
* @see ServerPlayNetworking
|
||||
*/
|
||||
|
||||
public final class ClientPlayNetworking {
|
||||
/**
|
||||
* Registers a handler to a channel.
|
||||
* A global receiver is registered to all connections, in the present and future.
|
||||
*
|
||||
* <p>If a handler is already registered to the {@code channel}, this method will return {@code false}, and no change will be made.
|
||||
* Use {@link #unregisterGlobalReceiver(ResourceLocation)} to unregister the existing handler.
|
||||
*
|
||||
* @param channelName the id of the channel
|
||||
* @param channelHandler the handler
|
||||
* @return false if a handler is already registered to the channel
|
||||
* @see ClientPlayNetworking#unregisterGlobalReceiver(ResourceLocation)
|
||||
* @see ClientPlayNetworking#registerReceiver(ResourceLocation, PlayChannelHandler)
|
||||
*/
|
||||
public static boolean registerGlobalReceiver(ResourceLocation channelName, PlayChannelHandler channelHandler) {
|
||||
return ClientNetworkingImpl.PLAY.registerGlobalReceiver(channelName, channelHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the handler of a channel.
|
||||
* A global receiver is registered to all connections, in the present and future.
|
||||
*
|
||||
* <p>The {@code channel} is guaranteed not to have a handler after this call.
|
||||
*
|
||||
* @param channelName the id of the channel
|
||||
* @return the previous handler, or {@code null} if no handler was bound to the channel
|
||||
* @see ClientPlayNetworking#registerGlobalReceiver(ResourceLocation, PlayChannelHandler)
|
||||
* @see ClientPlayNetworking#unregisterReceiver(ResourceLocation)
|
||||
*/
|
||||
@Nullable
|
||||
public static PlayChannelHandler unregisterGlobalReceiver(ResourceLocation channelName) {
|
||||
return ClientNetworkingImpl.PLAY.unregisterGlobalReceiver(channelName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all channel names which global receivers are registered for.
|
||||
* A global receiver is registered to all connections, in the present and future.
|
||||
*
|
||||
* @return all channel names which global receivers are registered for.
|
||||
*/
|
||||
public static Set<ResourceLocation> getGlobalReceivers() {
|
||||
return ClientNetworkingImpl.PLAY.getChannels();
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a handler to a channel.
|
||||
*
|
||||
* <p>If a handler is already registered to the {@code channel}, this method will return {@code false}, and no change will be made.
|
||||
* Use {@link #unregisterReceiver(ResourceLocation)} to unregister the existing handler.
|
||||
*
|
||||
* <p>For example, if you only register a receiver using this method when a {@linkplain ClientLoginNetworking#registerGlobalReceiver(ResourceLocation, ClientLoginNetworking.LoginQueryRequestHandler)}
|
||||
* login query has been received, you should use {@link ClientPlayConnectionEvents#INIT} to register the channel handler.
|
||||
*
|
||||
* @param channelName the id of the channel
|
||||
* @return false if a handler is already registered to the channel
|
||||
* @throws IllegalStateException if the client is not connected to a server
|
||||
* @see ClientPlayConnectionEvents#INIT
|
||||
*/
|
||||
public static boolean registerReceiver(ResourceLocation channelName, PlayChannelHandler channelHandler) {
|
||||
final ClientPlayNetworkAddon addon = ClientNetworkingImpl.getClientPlayAddon();
|
||||
|
||||
if (addon != null) {
|
||||
return addon.registerChannel(channelName, channelHandler);
|
||||
}
|
||||
|
||||
throw new IllegalStateException("Cannot register receiver while not in game!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the handler of a channel.
|
||||
*
|
||||
* <p>The {@code channelName} is guaranteed not to have a handler after this call.
|
||||
*
|
||||
* @param channelName the id of the channel
|
||||
* @return the previous handler, or {@code null} if no handler was bound to the channel
|
||||
* @throws IllegalStateException if the client is not connected to a server
|
||||
*/
|
||||
@Nullable
|
||||
public static PlayChannelHandler unregisterReceiver(ResourceLocation channelName) throws IllegalStateException {
|
||||
final ClientPlayNetworkAddon addon = ClientNetworkingImpl.getClientPlayAddon();
|
||||
|
||||
if (addon != null) {
|
||||
return addon.unregisterChannel(channelName);
|
||||
}
|
||||
|
||||
throw new IllegalStateException("Cannot unregister receiver while not in game!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all the channel names that the client can receive packets on.
|
||||
*
|
||||
* @return All the channel names that the client can receive packets on
|
||||
* @throws IllegalStateException if the client is not connected to a server
|
||||
*/
|
||||
public static Set<ResourceLocation> getReceived() throws IllegalStateException {
|
||||
final ClientPlayNetworkAddon addon = ClientNetworkingImpl.getClientPlayAddon();
|
||||
|
||||
if (addon != null) {
|
||||
return addon.getReceivableChannels();
|
||||
}
|
||||
|
||||
throw new IllegalStateException("Cannot get a list of channels the client can receive packets on while not in game!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all channel names that the connected server declared the ability to receive a packets on.
|
||||
*
|
||||
* @return All the channel names the connected server declared the ability to receive a packets on
|
||||
* @throws IllegalStateException if the client is not connected to a server
|
||||
*/
|
||||
public static Set<ResourceLocation> getSendable() throws IllegalStateException {
|
||||
final ClientPlayNetworkAddon addon = ClientNetworkingImpl.getClientPlayAddon();
|
||||
|
||||
if (addon != null) {
|
||||
return addon.getSendableChannels();
|
||||
}
|
||||
|
||||
throw new IllegalStateException("Cannot get a list of channels the server can receive packets on while not in game!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the connected server declared the ability to receive a packet on a specified channel name.
|
||||
*
|
||||
* @param channelName the channel name
|
||||
* @return True if the connected server has declared the ability to receive a packet on the specified channel.
|
||||
* False if the client is not in game.
|
||||
*/
|
||||
public static boolean canSend(ResourceLocation channelName) throws IllegalArgumentException {
|
||||
// You cant send without a client player, so this is fine
|
||||
if (Minecraft.getInstance().getConnection() != null) {
|
||||
return ClientNetworkingImpl.getAddon(Minecraft.getInstance().getConnection()).getSendableChannels().contains(channelName);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a packet which may be sent to a the connected server.
|
||||
*
|
||||
* @param channelName the channel name
|
||||
* @param buf the packet byte buf which represents the payload of the packet
|
||||
* @return a new packet
|
||||
*/
|
||||
public static Packet<?> createC2SPacket(ResourceLocation channelName, FriendlyByteBuf buf) {
|
||||
Objects.requireNonNull(channelName, "Channel name cannot be null");
|
||||
Objects.requireNonNull(buf, "Buf cannot be null");
|
||||
|
||||
return ClientNetworkingImpl.createPlayC2SPacket(channelName, buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the packet sender which sends packets to the connected server.
|
||||
*
|
||||
* @return the client's packet sender
|
||||
* @throws IllegalStateException if the client is not connected to a server
|
||||
*/
|
||||
public static PacketSender getSender() throws IllegalStateException {
|
||||
// You cant send without a client player, so this is fine
|
||||
if (Minecraft.getInstance().getConnection() != null) {
|
||||
return ClientNetworkingImpl.getAddon(Minecraft.getInstance().getConnection());
|
||||
}
|
||||
|
||||
throw new IllegalStateException("Cannot get packet sender when not in game!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a packet to the connected server.
|
||||
*
|
||||
* @param channelName the channel of the packet
|
||||
* @param buf the payload of the packet
|
||||
* @throws IllegalStateException if the client is not connected to a server
|
||||
*/
|
||||
public static void send(ResourceLocation channelName, FriendlyByteBuf buf) throws IllegalStateException {
|
||||
// You cant send without a client player, so this is fine
|
||||
if (Minecraft.getInstance().getConnection() != null) {
|
||||
Minecraft.getInstance().getConnection().send(createC2SPacket(channelName, buf));
|
||||
return;
|
||||
}
|
||||
|
||||
throw new IllegalStateException("Cannot send packets when not in game!");
|
||||
}
|
||||
|
||||
private ClientPlayNetworking() {
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface PlayChannelHandler {
|
||||
/**
|
||||
* Handles an incoming packet.
|
||||
*
|
||||
* <p>This method is executed on {@linkplain io.netty.channel.EventLoop netty's event loops}.
|
||||
* Modification to the game should be {@linkplain net.minecraft.util.thread.BlockableEventLoop#submit(Runnable) scheduled} using the provided Minecraft client instance.
|
||||
*
|
||||
* <p>An example usage of this is to display an overlay message:
|
||||
* <pre>{@code
|
||||
* ClientPlayNetworking.registerReceiver(new Identifier("mymod", "overlay"), (client, handler, buf, responseSender) -&rt; {
|
||||
* String message = buf.readString(32767);
|
||||
*
|
||||
* // All operations on the server or world must be executed on the server thread
|
||||
* client.execute(() -&rt; {
|
||||
* client.inGameHud.setOverlayMessage(message, true);
|
||||
* });
|
||||
* });
|
||||
* }</pre>
|
||||
* @param client the client
|
||||
* @param handler the network handler that received this packet
|
||||
* @param buf the payload of the packet
|
||||
* @param responseSender the packet sender
|
||||
*/
|
||||
void receive(Minecraft client, ClientPacketListener handler, FriendlyByteBuf buf, PacketSender responseSender);
|
||||
}
|
||||
}
|
||||
-29
@@ -1,29 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The Networking API (client side), version 1.
|
||||
*
|
||||
* <p>For login stage networking see {@link net.fabricmc.fabric.api.client.networking.v1.ClientLoginNetworking}.
|
||||
* For play stage networking see {@link net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking}.
|
||||
*
|
||||
* <p>For events related to connection to a server see {@link net.fabricmc.fabric.api.client.networking.v1.ClientLoginConnectionEvents} for login stage
|
||||
* or {@link net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents} for play stage.
|
||||
*
|
||||
* <p>For events related to the ability of a server to receive packets on a channel of a specific name see {@link net.fabricmc.fabric.api.client.networking.v1.C2SPlayChannelEvents}.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.forge.fabric.api.client.networking.v1;
|
||||
@@ -1,55 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.forge.fabric.api.event;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Indicates that this {@link Event} is auto-invoking:
|
||||
* it calls the event callback implemented by a context parameter type automatically and without registration.
|
||||
*
|
||||
* <p>This means that this event can be listened to in two ways:
|
||||
* <ul>
|
||||
* <li>If the consumer is the context parameter and it implements the callback, it will be automatically invoked, don't register manually.
|
||||
* <li>Otherwise, there is no invocation and the listener needs manual registration as usual.
|
||||
* </ul>
|
||||
*
|
||||
* <p>Do note that there may be more than one context parameter.
|
||||
*
|
||||
* <p>A typical use case is feature augmentation, for example to expose raw clicks to slots.
|
||||
* The event callback has a slot parameter - the context parameter - and the event itself is carrying this annotation.
|
||||
* All the slot needs to receive slot clicks is to implement {@code SlotClickCallback} on itself.
|
||||
* It shouldn't do any explicit event registration like {@code SLOT_CLICK_EVENT.register(this::onSlotClick)},
|
||||
* otherwise it will see extraneous callback invocations.
|
||||
*
|
||||
* <p>In general, an auto-invoking event bridges the gap between the flexibility of an event with global reach,
|
||||
* and the convenience of implementing an interface that gets detected automatically.
|
||||
*
|
||||
* <p>This is a documentation-only annotation, the event factory has to implement the functionality explicitly by checking the parameter type and invoking it.
|
||||
* On top of adding this annotation, the event field or method should document which parameters are context parameters,
|
||||
* and under which circumstances they are invoked.
|
||||
*/
|
||||
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ ElementType.FIELD, ElementType.METHOD })
|
||||
public @interface AutoInvokingEvent {
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.forge.fabric.api.event;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
/**
|
||||
* Base class for Fabric's event implementations.
|
||||
*
|
||||
* @param <T> The listener type.
|
||||
* @see EventFactory
|
||||
*/
|
||||
@ApiStatus.NonExtendable // Should only be extended by fabric API.
|
||||
public abstract class Event<T> {
|
||||
/**
|
||||
* The invoker field. This should be updated by the implementation to
|
||||
* always refer to an instance containing all code that should be
|
||||
* executed upon event emission.
|
||||
*/
|
||||
protected volatile T invoker;
|
||||
|
||||
/**
|
||||
* Returns the invoker instance.
|
||||
*
|
||||
* <p>An "invoker" is an object which hides multiple registered
|
||||
* listeners of type T under one instance of type T, executing
|
||||
* them and leaving early as necessary.
|
||||
*
|
||||
* @return The invoker instance.
|
||||
*/
|
||||
public final T invoker() {
|
||||
return invoker;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a listener to the event, in the default phase.
|
||||
* Have a look at {@link #addPhaseOrdering} for an explanation of event phases.
|
||||
*
|
||||
* @param listener The desired listener.
|
||||
*/
|
||||
public abstract void register(T listener);
|
||||
|
||||
/**
|
||||
* The ResourceLocation of the default phase.
|
||||
* Have a look at {@link EventFactory#createWithPhases} for an explanation of event phases.
|
||||
*/
|
||||
public static final ResourceLocation DEFAULT_PHASE = new ResourceLocation("fabric", "default");
|
||||
|
||||
/**
|
||||
* Register a listener to the event for the specified phase.
|
||||
* Have a look at {@link EventFactory#createWithPhases} for an explanation of event phases.
|
||||
*
|
||||
* @param phase ResourceLocation of the phase this listener should be registered for. It will be created if it didn't exist yet.
|
||||
* @param listener The desired listener.
|
||||
*/
|
||||
public void register(ResourceLocation phase, T listener) {
|
||||
// This is done to keep compatibility with existing Event subclasses, but they should really not be subclassing Event.
|
||||
register(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Request that listeners registered for one phase be executed before listeners registered for another phase.
|
||||
* Relying on the default phases supplied to {@link EventFactory#createWithPhases} should be preferred over manually
|
||||
* registering phase ordering dependencies.
|
||||
*
|
||||
* <p>Incompatible ordering constraints such as cycles will lead to inconsistent behavior:
|
||||
* some constraints will be respected and some will be ignored. If this happens, a warning will be logged.
|
||||
*
|
||||
* @param firstPhase The ResourceLocation of the phase that should run before the other. It will be created if it didn't exist yet.
|
||||
* @param secondPhase The ResourceLocation of the phase that should run after the other. It will be created if it didn't exist yet.
|
||||
*/
|
||||
public void addPhaseOrdering(ResourceLocation firstPhase, ResourceLocation secondPhase) {
|
||||
// This is not abstract to avoid breaking existing Event subclasses, but they should really not be subclassing Event.
|
||||
}
|
||||
}
|
||||
@@ -1,141 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.forge.fabric.api.event;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
import com.seibel.lod.forge.fabric.impl.base.event.EventFactoryImpl;
|
||||
|
||||
/**
|
||||
* Helper for creating {@link Event} classes.
|
||||
*/
|
||||
public final class EventFactory {
|
||||
private static boolean profilingEnabled = true;
|
||||
|
||||
private EventFactory() { }
|
||||
|
||||
/**
|
||||
* @return True if events are supposed to be profiled.
|
||||
*/
|
||||
public static boolean isProfilingEnabled() {
|
||||
return profilingEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate and re-create all existing "invoker" instances across
|
||||
* events created by this EventFactory. Use this if, for instance,
|
||||
* the profilingEnabled field changes.
|
||||
*/
|
||||
// TODO: Turn this into an event?
|
||||
public static void invalidate() {
|
||||
EventFactoryImpl.invalidate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an "array-backed" Event instance.
|
||||
*
|
||||
* <p>If your factory simply delegates to the listeners without adding custom behavior,
|
||||
* consider using {@linkplain #createArrayBacked(Class, Object, Function) the other overload}
|
||||
* if performance of this event is critical.
|
||||
*
|
||||
* @param type The listener class type.
|
||||
* @param invokerFactory The invoker factory, combining multiple listeners into one instance.
|
||||
* @param <T> The listener type.
|
||||
* @return The Event instance.
|
||||
*/
|
||||
public static <T> Event<T> createArrayBacked(Class<? super T> type, Function<T[], T> invokerFactory) {
|
||||
return EventFactoryImpl.createArrayBacked(type, invokerFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an "array-backed" Event instance with a custom empty invoker,
|
||||
* for an event whose {@code invokerFactory} only delegates to the listeners.
|
||||
* <ul>
|
||||
* <li>If there is no listener, the custom empty invoker will be used.</li>
|
||||
* <li><b>If there is only one listener, that one will be used as the invoker
|
||||
* and the factory will not be called.</b></li>
|
||||
* <li>Only when there are at least two listeners will the factory be used.</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>Having a custom empty invoker (of type (...) -> {}) increases performance
|
||||
* relative to iterating over an empty array; however, it only really matters
|
||||
* if the event is executed thousands of times a second.
|
||||
*
|
||||
* @param type The listener class type.
|
||||
* @param emptyInvoker The custom empty invoker.
|
||||
* @param invokerFactory The invoker factory, combining multiple listeners into one instance.
|
||||
* @param <T> The listener type.
|
||||
* @return The Event instance.
|
||||
*/
|
||||
public static <T> Event<T> createArrayBacked(Class<T> type, T emptyInvoker, Function<T[], T> invokerFactory) {
|
||||
return createArrayBacked(type, listeners -> {
|
||||
if (listeners.length == 0) {
|
||||
return emptyInvoker;
|
||||
} else if (listeners.length == 1) {
|
||||
return listeners[0];
|
||||
} else {
|
||||
return invokerFactory.apply(listeners);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an array-backed event with a list of default phases that get invoked in order.
|
||||
* Exposing the ResourceLocations of the default phases as {@code public static final} constants is encouraged.
|
||||
*
|
||||
* <p>An event phase is a named group of listeners, which may be ordered before or after other groups of listeners.
|
||||
* This allows some listeners to take priority over other listeners.
|
||||
* Adding separate events should be considered before making use of multiple event phases.
|
||||
*
|
||||
* <p>Phases may be freely added to events created with any of the factory functions,
|
||||
* however using this function is preferred for widely used event phases.
|
||||
* If more phases are necessary, discussion with the author of the Event is encouraged.
|
||||
*
|
||||
* <p>Refer to {@link Event#addPhaseOrdering} for an explanation of event phases.
|
||||
*
|
||||
* @param type The listener class type.
|
||||
* @param invokerFactory The invoker factory, combining multiple listeners into one instance.
|
||||
* @param defaultPhases The default phases of this event, in the correct order. Must contain {@link Event#DEFAULT_PHASE}.
|
||||
* @param <T> The listener type.
|
||||
* @return The Event instance.
|
||||
*/
|
||||
public static <T> Event<T> createWithPhases(Class<? super T> type, Function<T[], T> invokerFactory, ResourceLocation... defaultPhases) {
|
||||
EventFactoryImpl.ensureContainsDefault(defaultPhases);
|
||||
EventFactoryImpl.ensureNoDuplicates(defaultPhases);
|
||||
|
||||
Event<T> event = createArrayBacked(type, invokerFactory);
|
||||
|
||||
for (int i = 1; i < defaultPhases.length; ++i) {
|
||||
event.addPhaseOrdering(defaultPhases[i-1], defaultPhases[i]);
|
||||
}
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the listener object name. This can be used in debugging/profiling
|
||||
* scenarios.
|
||||
*
|
||||
* @param handler The listener object.
|
||||
* @return The listener name.
|
||||
*/
|
||||
public static String getHandlerName(Object handler) {
|
||||
return handler.getClass().getName();
|
||||
}
|
||||
}
|
||||
-74
@@ -1,74 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.forge.fabric.api.networking.v1;
|
||||
|
||||
import com.seibel.lod.forge.fabric.api.event.Event;
|
||||
import com.seibel.lod.forge.fabric.api.event.EventFactory;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
|
||||
/**
|
||||
* Events related to a tracking entities within a player's view distance.
|
||||
*/
|
||||
public final class EntityTrackingEvents {
|
||||
/**
|
||||
* An event that is called before player starts tracking an entity.
|
||||
* Typically this occurs when an entity enters a client's view distance.
|
||||
* This event is called before the player's client is sent the entity's {@link Entity#getAddEntityPacket() spawn packet}.
|
||||
*/
|
||||
public static final Event<StartTracking> START_TRACKING = EventFactory.createArrayBacked(StartTracking.class, callbacks -> (trackedEntity, player) -> {
|
||||
for (StartTracking callback : callbacks) {
|
||||
callback.onStartTracking(trackedEntity, player);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* An event that is called after a player has stopped tracking an entity.
|
||||
* The client at this point was sent a packet to {@link net.minecraft.network.protocol.game.ClientboundRemoveEntitiesPacket destroy} the entity on the client.
|
||||
* The entity still exists on the server.
|
||||
*/
|
||||
public static final Event<StopTracking> STOP_TRACKING = EventFactory.createArrayBacked(StopTracking.class, callbacks -> (trackedEntity, player) -> {
|
||||
for (StopTracking callback : callbacks) {
|
||||
callback.onStopTracking(trackedEntity, player);
|
||||
}
|
||||
});
|
||||
|
||||
@FunctionalInterface
|
||||
public interface StartTracking {
|
||||
/**
|
||||
* Called before an entity starts getting tracked by a player.
|
||||
*
|
||||
* @param trackedEntity the entity that will be tracked
|
||||
* @param player the player that will track the entity
|
||||
*/
|
||||
void onStartTracking(Entity trackedEntity, ServerPlayer player);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface StopTracking {
|
||||
/**
|
||||
* Called after an entity stops getting tracked by a player.
|
||||
*
|
||||
* @param trackedEntity the entity that is no longer being tracked
|
||||
* @param player the player that is no longer tracking the entity
|
||||
*/
|
||||
void onStopTracking(Entity trackedEntity, ServerPlayer player);
|
||||
}
|
||||
|
||||
private EntityTrackingEvents() {
|
||||
}
|
||||
}
|
||||
-94
@@ -1,94 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.forge.fabric.api.networking.v1;
|
||||
|
||||
import java.util.Objects;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelFutureListener;
|
||||
import io.netty.channel.local.LocalChannel;
|
||||
import io.netty.channel.local.LocalServerChannel;
|
||||
import io.netty.util.concurrent.Future;
|
||||
import io.netty.util.concurrent.FutureListener;
|
||||
import io.netty.util.concurrent.GenericFutureListener;
|
||||
|
||||
/**
|
||||
* Utilities for working with netty's future listeners.
|
||||
* @see FutureListener
|
||||
* @see ChannelFutureListener
|
||||
*/
|
||||
public final class FutureListeners {
|
||||
/**
|
||||
* Returns a future listener that releases a packet byte buf when the buffer has been sent to a remote connection.
|
||||
*
|
||||
* @param buf the buffer
|
||||
* @return the future listener
|
||||
*/
|
||||
public static ChannelFutureListener free(FriendlyByteBuf buf) {
|
||||
Objects.requireNonNull(buf, "PacketByteBuf cannot be null");
|
||||
|
||||
return (future) -> {
|
||||
if (!isLocalChannel(future.channel())) {
|
||||
buf.release();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether a netty channel performs local transportation, or if the message objects in the channel are directly passed than written to and read from a byte buf.
|
||||
*
|
||||
* @param channel the channel to check
|
||||
* @return whether the channel is local
|
||||
*/
|
||||
public static boolean isLocalChannel(Channel channel) {
|
||||
return channel instanceof LocalServerChannel || channel instanceof LocalChannel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines two future listeners.
|
||||
*
|
||||
* @param first the first future listener
|
||||
* @param second the second future listener
|
||||
* @param <A> the future type of the first listener, used for casting
|
||||
* @param <B> the future type of the second listener, used for casting
|
||||
* @return the combined future listener.
|
||||
*/
|
||||
// A, B exist just to allow casting
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <A extends Future<? super Void>, B extends Future<? super Void>> GenericFutureListener<? extends Future<? super Void>> union(GenericFutureListener<A> first, GenericFutureListener<B> second) {
|
||||
// Return an empty future listener in the case of both parameters somehow being null
|
||||
if (first == null && second == null) {
|
||||
return future -> { };
|
||||
}
|
||||
|
||||
if (first == null) {
|
||||
return second;
|
||||
}
|
||||
|
||||
if (second == null) {
|
||||
return first;
|
||||
}
|
||||
|
||||
return future -> {
|
||||
first.operationComplete((A) future);
|
||||
second.operationComplete((B) future);
|
||||
};
|
||||
}
|
||||
|
||||
private FutureListeners() {
|
||||
}
|
||||
}
|
||||
-204
@@ -1,204 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.forge.fabric.api.networking.v1;
|
||||
|
||||
import java.util.Objects;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
|
||||
/**
|
||||
* Helper methods for working with and creating {@link FriendlyByteBuf}s.
|
||||
*/
|
||||
public final class PacketByteBufs {
|
||||
private static final FriendlyByteBuf EMPTY_PACKET_BYTE_BUF = new FriendlyByteBuf(Unpooled.EMPTY_BUFFER);
|
||||
|
||||
/**
|
||||
* Returns an empty instance of packet byte buf.
|
||||
*
|
||||
* @return an empty buf
|
||||
*/
|
||||
public static FriendlyByteBuf empty() {
|
||||
return EMPTY_PACKET_BYTE_BUF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new heap memory-backed instance of packet byte buf.
|
||||
*
|
||||
* @return a new buf
|
||||
*/
|
||||
public static FriendlyByteBuf create() {
|
||||
return new FriendlyByteBuf(Unpooled.buffer());
|
||||
}
|
||||
|
||||
// Convenience methods for byte buf methods that return a new byte buf
|
||||
|
||||
/**
|
||||
* Wraps the newly created buf from {@code buf.readBytes} in a packet byte buf.
|
||||
*
|
||||
* @param buf the original buf
|
||||
* @param length the number of bytes to transfer
|
||||
* @return the transferred bytes
|
||||
* @see ByteBuf#readBytes(int)
|
||||
*/
|
||||
public static FriendlyByteBuf readBytes(ByteBuf buf, int length) {
|
||||
Objects.requireNonNull(buf, "ByteBuf cannot be null");
|
||||
|
||||
return new FriendlyByteBuf(buf.readBytes(length));
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps the newly created buf from {@code buf.readSlice} in a packet byte buf.
|
||||
*
|
||||
* @param buf the original buf
|
||||
* @param length the size of the new slice
|
||||
* @return the newly created slice
|
||||
* @see ByteBuf#readSlice(int)
|
||||
*/
|
||||
public static FriendlyByteBuf readSlice(ByteBuf buf, int length) {
|
||||
Objects.requireNonNull(buf, "ByteBuf cannot be null");
|
||||
|
||||
return new FriendlyByteBuf(buf.readSlice(length));
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps the newly created buf from {@code buf.readRetainedSlice} in a packet byte buf.
|
||||
*
|
||||
* @param buf the original buf
|
||||
* @param length the size of the new slice
|
||||
* @return the newly created slice
|
||||
* @see ByteBuf#readRetainedSlice(int)
|
||||
*/
|
||||
public static FriendlyByteBuf readRetainedSlice(ByteBuf buf, int length) {
|
||||
Objects.requireNonNull(buf, "ByteBuf cannot be null");
|
||||
|
||||
return new FriendlyByteBuf(buf.readRetainedSlice(length));
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps the newly created buf from {@code buf.copy} in a packet byte buf.
|
||||
*
|
||||
* @param buf the original buf
|
||||
* @return a copy of the buf
|
||||
* @see ByteBuf#copy()
|
||||
*/
|
||||
public static FriendlyByteBuf copy(ByteBuf buf) {
|
||||
Objects.requireNonNull(buf, "ByteBuf cannot be null");
|
||||
|
||||
return new FriendlyByteBuf(buf.copy());
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps the newly created buf from {@code buf.copy} in a packet byte buf.
|
||||
*
|
||||
* @param buf the original buf
|
||||
* @param index the starting index
|
||||
* @param length the size of the copy
|
||||
* @return a copy of the buf
|
||||
* @see ByteBuf#copy(int, int)
|
||||
*/
|
||||
public static FriendlyByteBuf copy(ByteBuf buf, int index, int length) {
|
||||
Objects.requireNonNull(buf, "ByteBuf cannot be null");
|
||||
|
||||
return new FriendlyByteBuf(buf.copy(index, length));
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps the newly created buf from {@code buf.slice} in a packet byte buf.
|
||||
*
|
||||
* @param buf the original buf
|
||||
* @return a slice of the buf
|
||||
* @see ByteBuf#slice()
|
||||
*/
|
||||
public static FriendlyByteBuf slice(ByteBuf buf) {
|
||||
Objects.requireNonNull(buf, "ByteBuf cannot be null");
|
||||
|
||||
return new FriendlyByteBuf(buf.slice());
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps the newly created buf from {@code buf.retainedSlice} in a packet byte buf.
|
||||
*
|
||||
* @param buf the original buf
|
||||
* @return a slice of the buf
|
||||
* @see ByteBuf#retainedSlice()
|
||||
*/
|
||||
public static FriendlyByteBuf retainedSlice(ByteBuf buf) {
|
||||
Objects.requireNonNull(buf, "ByteBuf cannot be null");
|
||||
|
||||
return new FriendlyByteBuf(buf.retainedSlice());
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps the newly created buf from {@code buf.slice} in a packet byte buf.
|
||||
*
|
||||
* @param buf the original buf
|
||||
* @param index the starting index
|
||||
* @param length the size of the copy
|
||||
* @return a slice of the buf
|
||||
* @see ByteBuf#slice(int, int)
|
||||
*/
|
||||
public static FriendlyByteBuf slice(ByteBuf buf, int index, int length) {
|
||||
Objects.requireNonNull(buf, "ByteBuf cannot be null");
|
||||
|
||||
return new FriendlyByteBuf(buf.slice(index, length));
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps the newly created buf from {@code buf.retainedSlice} in a packet byte buf.
|
||||
*
|
||||
* @param buf the original buf
|
||||
* @param index the starting index
|
||||
* @param length the size of the copy
|
||||
* @return a slice of the buf
|
||||
* @see ByteBuf#retainedSlice(int, int)
|
||||
*/
|
||||
public static FriendlyByteBuf retainedSlice(ByteBuf buf, int index, int length) {
|
||||
Objects.requireNonNull(buf, "ByteBuf cannot be null");
|
||||
|
||||
return new FriendlyByteBuf(buf.retainedSlice(index, length));
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps the newly created buf from {@code buf.duplicate} in a packet byte buf.
|
||||
*
|
||||
* @param buf the original buf
|
||||
* @return a duplicate of the buf
|
||||
* @see ByteBuf#duplicate()
|
||||
*/
|
||||
public static FriendlyByteBuf duplicate(ByteBuf buf) {
|
||||
Objects.requireNonNull(buf, "ByteBuf cannot be null");
|
||||
|
||||
return new FriendlyByteBuf(buf.duplicate());
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps the newly created buf from {@code buf.retainedDuplicate} in a packet byte buf.
|
||||
*
|
||||
* @param buf the original buf
|
||||
* @return a duplicate of the buf
|
||||
* @see ByteBuf#retainedDuplicate()
|
||||
*/
|
||||
public static FriendlyByteBuf retainedDuplicate(ByteBuf buf) {
|
||||
Objects.requireNonNull(buf, "ByteBuf cannot be null");
|
||||
|
||||
return new FriendlyByteBuf(buf.retainedDuplicate());
|
||||
}
|
||||
|
||||
private PacketByteBufs() {
|
||||
}
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.forge.fabric.api.networking.v1;
|
||||
|
||||
import java.util.Objects;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.network.protocol.Packet;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import io.netty.channel.ChannelFutureListener;
|
||||
import io.netty.util.concurrent.Future;
|
||||
import io.netty.util.concurrent.GenericFutureListener;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Represents something that supports sending packets to channels.
|
||||
* @see PacketByteBufs
|
||||
*/
|
||||
public interface PacketSender {
|
||||
/**
|
||||
* Makes a packet for a channel.
|
||||
*
|
||||
* @param channelName the id of the channel
|
||||
* @param buf the content of the packet
|
||||
*/
|
||||
Packet<?> createPacket(ResourceLocation channelName, FriendlyByteBuf buf);
|
||||
|
||||
/**
|
||||
* Sends a packet.
|
||||
*
|
||||
* @param packet the packet
|
||||
*/
|
||||
void sendPacket(Packet<?> packet);
|
||||
|
||||
/**
|
||||
* Sends a packet.
|
||||
*
|
||||
* @param packet the packet
|
||||
* @param callback an optional callback to execute after the packet is sent, may be {@code null}. The callback may also accept a {@link ChannelFutureListener}.
|
||||
*/
|
||||
void sendPacket(Packet<?> packet, @Nullable GenericFutureListener<? extends Future<? super Void>> callback);
|
||||
|
||||
/**
|
||||
* Sends a packet to a channel.
|
||||
*
|
||||
* @param channel the id of the channel
|
||||
* @param buf the content of the packet
|
||||
*/
|
||||
default void sendPacket(ResourceLocation channel, FriendlyByteBuf buf) {
|
||||
Objects.requireNonNull(channel, "Channel cannot be null");
|
||||
Objects.requireNonNull(buf, "Payload cannot be null");
|
||||
|
||||
this.sendPacket(this.createPacket(channel, buf));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a packet to a channel.
|
||||
*
|
||||
* @param channel the id of the channel
|
||||
* @param buf the content of the packet
|
||||
* @param callback an optional callback to execute after the packet is sent, may be {@code null}
|
||||
*/
|
||||
// the generic future listener can accept ChannelFutureListener
|
||||
default void sendPacket(ResourceLocation channel, FriendlyByteBuf buf, @Nullable GenericFutureListener<? extends Future<? super Void>> callback) {
|
||||
Objects.requireNonNull(channel, "Channel cannot be null");
|
||||
Objects.requireNonNull(buf, "Payload cannot be null");
|
||||
|
||||
this.sendPacket(this.createPacket(channel, buf), callback);
|
||||
}
|
||||
}
|
||||
@@ -1,199 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.forge.fabric.api.networking.v1;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Vec3i;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ChunkMap;
|
||||
import net.minecraft.server.level.ServerChunkCache;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.server.network.ServerPlayerConnection;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.chunk.ChunkSource;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import com.seibel.lod.forge.mixins.fabric.mixin.networking.accessor.EntityTrackerAccessor;
|
||||
import com.seibel.lod.forge.mixins.fabric.mixin.networking.accessor.ThreadedAnvilChunkStorageAccessor;
|
||||
|
||||
/**
|
||||
* For example, a block entity may use the methods in this class to send a packet to all clients which can see the block entity in order notify clients about a change.
|
||||
*
|
||||
* <p>The word "tracking" means that an entity/chunk on the server is known to a player's client (within in view distance) and the (block) entity should notify tracking clients of changes.
|
||||
*
|
||||
* <p>These methods should only be called on the server thread and only be used on logical a server.
|
||||
*/
|
||||
public final class PlayerLookup {
|
||||
/**
|
||||
* Gets all the players on the minecraft server.
|
||||
*
|
||||
* <p>The returned collection is immutable.
|
||||
*
|
||||
* @param server the server
|
||||
* @return all players on the server
|
||||
*/
|
||||
public static Collection<ServerPlayer> all(MinecraftServer server) {
|
||||
Objects.requireNonNull(server, "The server cannot be null");
|
||||
|
||||
// return an immutable collection to guard against accidental removals.
|
||||
if (server.getPlayerList() != null) {
|
||||
return Collections.unmodifiableCollection(server.getPlayerList().getPlayers());
|
||||
}
|
||||
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all the players in a server world.
|
||||
*
|
||||
* <p>The returned collection is immutable.
|
||||
*
|
||||
* @param world the server world
|
||||
* @return the players in the server world
|
||||
*/
|
||||
public static Collection<ServerPlayer> world(ServerLevel world) {
|
||||
Objects.requireNonNull(world, "The world cannot be null");
|
||||
|
||||
// return an immutable collection to guard against accidental removals.
|
||||
return Collections.unmodifiableCollection(world.players());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all players tracking a chunk in a server world.
|
||||
*
|
||||
* @param world the server world
|
||||
* @param pos the chunk in question
|
||||
* @return the players tracking the chunk
|
||||
*/
|
||||
public static Collection<ServerPlayer> tracking(ServerLevel world, ChunkPos pos) {
|
||||
Objects.requireNonNull(world, "The world cannot be null");
|
||||
Objects.requireNonNull(pos, "The chunk pos cannot be null");
|
||||
|
||||
return world.getChunkSource().chunkMap.getPlayers(pos, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all players tracking an entity in a server world.
|
||||
*
|
||||
* <p>The returned collection is immutable.
|
||||
*
|
||||
* <p><b>Warning</b>: If the provided entity is a player, it is not
|
||||
* guaranteed by the contract that said player is included in the
|
||||
* resulting stream.
|
||||
*
|
||||
* @param entity the entity being tracked
|
||||
* @return the players tracking the entity
|
||||
* @throws IllegalArgumentException if the entity is not in a server world
|
||||
*/
|
||||
public static Collection<ServerPlayer> tracking(Entity entity) {
|
||||
Objects.requireNonNull(entity, "Entity cannot be null");
|
||||
ChunkSource manager = entity.level.getChunkSource();
|
||||
|
||||
if (manager instanceof ServerChunkCache) {
|
||||
ChunkMap storage = ((ServerChunkCache) manager).chunkMap;
|
||||
EntityTrackerAccessor tracker = ((ThreadedAnvilChunkStorageAccessor) storage).getEntityMap().get(entity.getId());
|
||||
|
||||
// return an immutable collection to guard against accidental removals.
|
||||
if (tracker != null) {
|
||||
return Collections.unmodifiableCollection(tracker.getPlayersTracking()
|
||||
.stream().map(ServerPlayerConnection::getPlayer).collect(Collectors.toSet()));
|
||||
}
|
||||
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Only supported on server worlds!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all players tracking a block entity in a server world.
|
||||
*
|
||||
* @param blockEntity the block entity
|
||||
* @return the players tracking the block position
|
||||
* @throws IllegalArgumentException if the block entity is not in a server world
|
||||
*/
|
||||
public static Collection<ServerPlayer> tracking(BlockEntity blockEntity) {
|
||||
Objects.requireNonNull(blockEntity, "BlockEntity cannot be null");
|
||||
|
||||
//noinspection ConstantConditions - IJ intrinsics don't know hasWorld == true will result in no null
|
||||
if (!blockEntity.hasLevel() || blockEntity.getLevel().isClientSide()) {
|
||||
throw new IllegalArgumentException("Only supported on server worlds!");
|
||||
}
|
||||
|
||||
return tracking((ServerLevel) blockEntity.getLevel(), blockEntity.getBlockPos());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all players tracking a block position in a server world.
|
||||
*
|
||||
* @param world the server world
|
||||
* @param pos the block position
|
||||
* @return the players tracking the block position
|
||||
*/
|
||||
public static Collection<ServerPlayer> tracking(ServerLevel world, BlockPos pos) {
|
||||
Objects.requireNonNull(pos, "BlockPos cannot be null");
|
||||
|
||||
return tracking(world, new ChunkPos(pos));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all players around a position in a world.
|
||||
*
|
||||
* <p>The distance check is done in the three-dimensional space instead of in the horizontal plane.
|
||||
*
|
||||
* @param world the world
|
||||
* @param pos the position
|
||||
* @param radius the maximum distance from the position in blocks
|
||||
* @return the players around the position
|
||||
*/
|
||||
public static Collection<ServerPlayer> around(ServerLevel world, Vec3 pos, double radius) {
|
||||
double radiusSq = radius * radius;
|
||||
|
||||
return world(world)
|
||||
.stream()
|
||||
.filter((p) -> p.distanceToSqr(pos) <= radiusSq)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all players around a position in a world.
|
||||
*
|
||||
* <p>The distance check is done in the three-dimensional space instead of in the horizontal plane.
|
||||
*
|
||||
* @param world the world
|
||||
* @param pos the position (can be a block pos)
|
||||
* @param radius the maximum distance from the position in blocks
|
||||
* @return the players around the position
|
||||
*/
|
||||
public static Collection<ServerPlayer> around(ServerLevel world, Vec3i pos, double radius) {
|
||||
double radiusSq = radius * radius;
|
||||
|
||||
return world(world)
|
||||
.stream()
|
||||
.filter((p) -> p.distanceToSqr(pos.getX(), pos.getY(), pos.getZ()) <= radiusSq)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private PlayerLookup() {
|
||||
}
|
||||
}
|
||||
-68
@@ -1,68 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.forge.fabric.api.networking.v1;
|
||||
|
||||
import java.util.List;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.network.ServerGamePacketListenerImpl;
|
||||
import com.seibel.lod.forge.fabric.api.event.Event;
|
||||
import com.seibel.lod.forge.fabric.api.event.EventFactory;
|
||||
|
||||
/**
|
||||
* Offers access to events related to the indication of a connected client's ability to receive packets in certain channels.
|
||||
*/
|
||||
public final class S2CPlayChannelEvents {
|
||||
/**
|
||||
* An event for the server play network handler receiving an update indicating the connected client's ability to receive packets in certain channels.
|
||||
* This event may be invoked at any time after login and up to disconnection.
|
||||
*/
|
||||
public static final Event<Register> REGISTER = EventFactory.createArrayBacked(Register.class, callbacks -> (handler, sender, server, channels) -> {
|
||||
for (Register callback : callbacks) {
|
||||
callback.onChannelRegister(handler, sender, server, channels);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* An event for the server play network handler receiving an update indicating the connected client's lack of ability to receive packets in certain channels.
|
||||
* This event may be invoked at any time after login and up to disconnection.
|
||||
*/
|
||||
public static final Event<Unregister> UNREGISTER = EventFactory.createArrayBacked(Unregister.class, callbacks -> (handler, sender, server, channels) -> {
|
||||
for (Unregister callback : callbacks) {
|
||||
callback.onChannelUnregister(handler, sender, server, channels);
|
||||
}
|
||||
});
|
||||
|
||||
private S2CPlayChannelEvents() {
|
||||
}
|
||||
|
||||
/**
|
||||
* @see S2CPlayChannelEvents#REGISTER
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface Register {
|
||||
void onChannelRegister(ServerGamePacketListenerImpl handler, PacketSender sender, MinecraftServer server, List<ResourceLocation> channels);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see S2CPlayChannelEvents#UNREGISTER
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface Unregister {
|
||||
void onChannelUnregister(ServerGamePacketListenerImpl handler, PacketSender sender, MinecraftServer server, List<ResourceLocation> channels);
|
||||
}
|
||||
}
|
||||
-91
@@ -1,91 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.forge.fabric.api.networking.v1;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.network.ServerLoginPacketListenerImpl;
|
||||
import com.seibel.lod.forge.fabric.api.event.Event;
|
||||
import com.seibel.lod.forge.fabric.api.event.EventFactory;
|
||||
|
||||
/**
|
||||
* Offers access to events related to the connection to a client on a logical server while a client is logging in.
|
||||
*/
|
||||
public final class ServerLoginConnectionEvents {
|
||||
/**
|
||||
* Event indicating a connection entered the LOGIN state, ready for registering query response handlers.
|
||||
*
|
||||
* @see ServerLoginNetworking#registerReceiver(ServerLoginPacketListenerImpl, ResourceLocation, ServerLoginNetworking.LoginQueryResponseHandler)
|
||||
*/
|
||||
public static final Event<Init> INIT = EventFactory.createArrayBacked(Init.class, callbacks -> (handler, server) -> {
|
||||
for (Init callback : callbacks) {
|
||||
callback.onLoginInit(handler, server);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* An event for the start of login queries of the server login network handler.
|
||||
* This event may be used to register {@link ServerLoginNetworking.LoginQueryResponseHandler login query response handlers}
|
||||
* using {@link ServerLoginNetworking#registerReceiver(ServerLoginPacketListenerImpl, ResourceLocation, ServerLoginNetworking.LoginQueryResponseHandler)}
|
||||
* since this event is fired just before the first login query response is processed.
|
||||
*
|
||||
* <p>You may send login queries to the connected client using the provided {@link PacketSender}.
|
||||
*/
|
||||
public static final Event<QueryStart> QUERY_START = EventFactory.createArrayBacked(QueryStart.class, callbacks -> (handler, server, sender, synchronizer) -> {
|
||||
for (QueryStart callback : callbacks) {
|
||||
callback.onLoginStart(handler, server, sender, synchronizer);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* An event for the disconnection of the server login network handler.
|
||||
*
|
||||
* <p>No packets should be sent when this event is invoked.
|
||||
*/
|
||||
public static final Event<Disconnect> DISCONNECT = EventFactory.createArrayBacked(Disconnect.class, callbacks -> (handler, server) -> {
|
||||
for (Disconnect callback : callbacks) {
|
||||
callback.onLoginDisconnect(handler, server);
|
||||
}
|
||||
});
|
||||
|
||||
private ServerLoginConnectionEvents() {
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ServerLoginConnectionEvents#INIT
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface Init {
|
||||
void onLoginInit(ServerLoginPacketListenerImpl handler, MinecraftServer server);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ServerLoginConnectionEvents#QUERY_START
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface QueryStart {
|
||||
void onLoginStart(ServerLoginPacketListenerImpl handler, MinecraftServer server, PacketSender sender, ServerLoginNetworking.LoginSynchronizer synchronizer);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ServerLoginConnectionEvents#DISCONNECT
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface Disconnect {
|
||||
void onLoginDisconnect(ServerLoginPacketListenerImpl handler, MinecraftServer server);
|
||||
}
|
||||
}
|
||||
-196
@@ -1,196 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.forge.fabric.api.networking.v1;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.network.ServerLoginPacketListenerImpl;
|
||||
import com.seibel.lod.forge.fabric.api.client.networking.v1.ClientLoginNetworking;
|
||||
import com.seibel.lod.forge.fabric.impl.networking.server.ServerNetworkingImpl;
|
||||
import com.seibel.lod.forge.mixins.fabric.mixin.networking.accessor.ServerLoginNetworkHandlerAccessor;
|
||||
|
||||
/**
|
||||
* Offers access to login stage server-side networking functionalities.
|
||||
*
|
||||
* <p>Server-side networking functionalities include receiving serverbound query responses and sending clientbound query requests.
|
||||
*
|
||||
* @see ServerPlayNetworking
|
||||
* @see ClientLoginNetworking
|
||||
*/
|
||||
public final class ServerLoginNetworking {
|
||||
/**
|
||||
* Registers a handler to a query response channel.
|
||||
* A global receiver is registered to all connections, in the present and future.
|
||||
*
|
||||
* <p>If a handler is already registered to the {@code channel}, this method will return {@code false}, and no change will be made.
|
||||
* Use {@link #unregisterGlobalReceiver(ResourceLocation)} to unregister the existing handler.
|
||||
*
|
||||
* @param channelName the id of the channel
|
||||
* @param channelHandler the handler
|
||||
* @return false if a handler is already registered to the channel
|
||||
* @see ServerLoginNetworking#unregisterGlobalReceiver(ResourceLocation)
|
||||
* @see ServerLoginNetworking#registerReceiver(ServerLoginPacketListenerImpl, ResourceLocation, LoginQueryResponseHandler)
|
||||
*/
|
||||
public static boolean registerGlobalReceiver(ResourceLocation channelName, LoginQueryResponseHandler channelHandler) {
|
||||
return ServerNetworkingImpl.LOGIN.registerGlobalReceiver(channelName, channelHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the handler of a query response channel.
|
||||
* A global receiver is registered to all connections, in the present and future.
|
||||
*
|
||||
* <p>The {@code channel} is guaranteed not to have a handler after this call.
|
||||
*
|
||||
* @param channelName the id of the channel
|
||||
* @return the previous handler, or {@code null} if no handler was bound to the channel
|
||||
* @see ServerLoginNetworking#registerGlobalReceiver(ResourceLocation, LoginQueryResponseHandler)
|
||||
* @see ServerLoginNetworking#unregisterReceiver(ServerLoginPacketListenerImpl, ResourceLocation)
|
||||
*/
|
||||
@Nullable
|
||||
public static ServerLoginNetworking.LoginQueryResponseHandler unregisterGlobalReceiver(ResourceLocation channelName) {
|
||||
return ServerNetworkingImpl.LOGIN.unregisterGlobalReceiver(channelName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all channel names which global receivers are registered for.
|
||||
* A global receiver is registered to all connections, in the present and future.
|
||||
*
|
||||
* @return all channel names which global receivers are registered for.
|
||||
*/
|
||||
public static Set<ResourceLocation> getGlobalReceivers() {
|
||||
return ServerNetworkingImpl.LOGIN.getChannels();
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a handler to a query response channel.
|
||||
*
|
||||
* <p>If a handler is already registered to the {@code channelName}, this method will return {@code false}, and no change will be made.
|
||||
* Use {@link #unregisterReceiver(ServerLoginPacketListenerImpl, ResourceLocation)} to unregister the existing handler.
|
||||
*
|
||||
* @param networkHandler the handler
|
||||
* @param channelName the id of the channel
|
||||
* @param responseHandler the handler
|
||||
* @return false if a handler is already registered to the channel name
|
||||
*/
|
||||
public static boolean registerReceiver(ServerLoginPacketListenerImpl networkHandler, ResourceLocation channelName, LoginQueryResponseHandler responseHandler) {
|
||||
Objects.requireNonNull(networkHandler, "Network handler cannot be null");
|
||||
|
||||
return ServerNetworkingImpl.getAddon(networkHandler).registerChannel(channelName, responseHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the handler of a query response channel.
|
||||
*
|
||||
* <p>The {@code channelName} is guaranteed not to have a handler after this call.
|
||||
*
|
||||
* @param channelName the id of the channel
|
||||
* @return the previous handler, or {@code null} if no handler was bound to the channel name
|
||||
*/
|
||||
@Nullable
|
||||
public static ServerLoginNetworking.LoginQueryResponseHandler unregisterReceiver(ServerLoginPacketListenerImpl networkHandler, ResourceLocation channelName) {
|
||||
Objects.requireNonNull(networkHandler, "Network handler cannot be null");
|
||||
|
||||
return ServerNetworkingImpl.getAddon(networkHandler).unregisterChannel(channelName);
|
||||
}
|
||||
|
||||
// Helper methods
|
||||
|
||||
/**
|
||||
* Returns the <i>Minecraft</i> Server of a server login network handler.
|
||||
*
|
||||
* @param handler the server login network handler
|
||||
*/
|
||||
public static MinecraftServer getServer(ServerLoginPacketListenerImpl handler) {
|
||||
Objects.requireNonNull(handler, "Network handler cannot be null");
|
||||
|
||||
return ((ServerLoginNetworkHandlerAccessor) handler).getServer();
|
||||
}
|
||||
|
||||
private ServerLoginNetworking() {
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface LoginQueryResponseHandler {
|
||||
/**
|
||||
* Handles an incoming query response from a client.
|
||||
*
|
||||
* <p>This method is executed on {@linkplain io.netty.channel.EventLoop netty's event loops}.
|
||||
* Modification to the game should be {@linkplain net.minecraft.util.thread.BlockableEventLoop#submit(Runnable) scheduled} using the provided Minecraft client instance.
|
||||
*
|
||||
* <p><b>Whether the client understood the query should be checked before reading from the payload of the packet.</b>
|
||||
* @param server the server
|
||||
* @param handler the network handler that received this packet, representing the player/client who sent the response
|
||||
* @param understood whether the client understood the packet
|
||||
* @param buf the payload of the packet
|
||||
* @param synchronizer the synchronizer which may be used to delay log-in till a {@link Future} is completed.
|
||||
* @param responseSender the packet sender
|
||||
*/
|
||||
void receive(MinecraftServer server, ServerLoginPacketListenerImpl handler, boolean understood, FriendlyByteBuf buf, LoginSynchronizer synchronizer, PacketSender responseSender);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows blocking client log-in until all all futures passed into {@link LoginSynchronizer#waitFor(Future)} are completed.
|
||||
*
|
||||
* @apiNote this interface is not intended to be implemented by users of api.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface LoginSynchronizer {
|
||||
/**
|
||||
* Allows blocking client log-in until the {@code future} is {@link Future#isDone() done}.
|
||||
*
|
||||
* <p>Since packet reception happens on netty's event loops, this allows handlers to
|
||||
* perform logic on the Server Thread, etc. For instance, a handler can prepare an
|
||||
* upcoming query request or check necessary login data on the server thread.</p>
|
||||
*
|
||||
* <p>Here is an example where the player log-in is blocked so that a credential check and
|
||||
* building of a followup query request can be performed properly on the logical server
|
||||
* thread before the player successfully logs in:
|
||||
* <pre>{@code
|
||||
* ServerLoginNetworking.registerGlobalReceiver(CHECK_CHANNEL, (server, handler, understood, buf, synchronizer, responseSender) -> {
|
||||
* if (!understood) {
|
||||
* handler.disconnect(new LiteralText("Only accept clients that can check!"));
|
||||
* return;
|
||||
* }
|
||||
*
|
||||
* String checkMessage = buf.readString(32767);
|
||||
*
|
||||
* // Just send the CompletableFuture returned by the server's submit method
|
||||
* synchronizer.waitFor(server.submit(() -> {
|
||||
* LoginInfoChecker checker = LoginInfoChecker.get(server);
|
||||
*
|
||||
* if (!checker.check(handler.getConnectionInfo(), checkMessage)) {
|
||||
* handler.disconnect(new LiteralText("Invalid credentials!"));
|
||||
* return;
|
||||
* }
|
||||
*
|
||||
* responseSender.send(UPCOMING_CHECK, checker.buildSecondQueryPacket(handler, checkMessage));
|
||||
* }));
|
||||
* });
|
||||
* }</pre>
|
||||
* Usually it is enough to pass the return value for {@link net.minecraft.util.thread.BlockableEventLoop#submit(Runnable)} for {@code future}.</p>
|
||||
*
|
||||
* @param future the future that must be done before the player can log in
|
||||
*/
|
||||
void waitFor(Future<?> future);
|
||||
}
|
||||
}
|
||||
-79
@@ -1,79 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.forge.fabric.api.networking.v1;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.network.ServerGamePacketListenerImpl;
|
||||
import com.seibel.lod.forge.fabric.api.event.Event;
|
||||
import com.seibel.lod.forge.fabric.api.event.EventFactory;
|
||||
|
||||
/**
|
||||
* Offers access to events related to the connection to a client on a logical server while a client is in game.
|
||||
*/
|
||||
public final class ServerPlayConnectionEvents {
|
||||
/**
|
||||
* Event indicating a connection entered the PLAY state, ready for registering channel handlers.
|
||||
*
|
||||
* @see ServerPlayNetworking#registerReceiver(ServerGamePacketListenerImpl, ResourceLocation, ServerPlayNetworking.PlayChannelHandler)
|
||||
*/
|
||||
public static final Event<Init> INIT = EventFactory.createArrayBacked(Init.class, callbacks -> (handler, server) -> {
|
||||
for (Init callback : callbacks) {
|
||||
callback.onPlayInit(handler, server);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* An event for notification when the server play network handler is ready to send packets to the client.
|
||||
*
|
||||
* <p>At this stage, the network handler is ready to send packets to the client.
|
||||
*/
|
||||
public static final Event<Join> JOIN = EventFactory.createArrayBacked(Join.class, callbacks -> (handler, sender, server) -> {
|
||||
for (Join callback : callbacks) {
|
||||
callback.onPlayReady(handler, sender, server);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* An event for the disconnection of the server play network handler.
|
||||
*
|
||||
* <p>No packets should be sent when this event is invoked.
|
||||
*/
|
||||
public static final Event<Disconnect> DISCONNECT = EventFactory.createArrayBacked(Disconnect.class, callbacks -> (handler, server) -> {
|
||||
for (Disconnect callback : callbacks) {
|
||||
callback.onPlayDisconnect(handler, server);
|
||||
}
|
||||
});
|
||||
|
||||
private ServerPlayConnectionEvents() {
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Init {
|
||||
void onPlayInit(ServerGamePacketListenerImpl handler, MinecraftServer server);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Join {
|
||||
void onPlayReady(ServerGamePacketListenerImpl handler, PacketSender sender, MinecraftServer server);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Disconnect {
|
||||
void onPlayDisconnect(ServerGamePacketListenerImpl handler, MinecraftServer server);
|
||||
}
|
||||
}
|
||||
-295
@@ -1,295 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.forge.fabric.api.networking.v1;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.network.protocol.Packet;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.server.network.ServerGamePacketListenerImpl;
|
||||
import com.seibel.lod.forge.fabric.api.client.networking.v1.ClientPlayNetworking;
|
||||
import com.seibel.lod.forge.fabric.impl.networking.server.ServerNetworkingImpl;
|
||||
|
||||
/**
|
||||
* Offers access to play stage server-side networking functionalities.
|
||||
*
|
||||
* <p>Server-side networking functionalities include receiving serverbound packets, sending clientbound packets, and events related to server-side network handlers.
|
||||
*
|
||||
* <p>This class should be only used for the logical server.
|
||||
*
|
||||
* @see ServerLoginNetworking
|
||||
* @see ClientPlayNetworking
|
||||
*/
|
||||
public final class ServerPlayNetworking {
|
||||
/**
|
||||
* Registers a handler to a channel.
|
||||
* A global receiver is registered to all connections, in the present and future.
|
||||
*
|
||||
* <p>If a handler is already registered to the {@code channel}, this method will return {@code false}, and no change will be made.
|
||||
* Use {@link #unregisterReceiver(ServerGamePacketListenerImpl, ResourceLocation)} to unregister the existing handler.
|
||||
*
|
||||
* @param channelName the id of the channel
|
||||
* @param channelHandler the handler
|
||||
* @return false if a handler is already registered to the channel
|
||||
* @see ServerPlayNetworking#unregisterGlobalReceiver(ResourceLocation)
|
||||
* @see ServerPlayNetworking#registerReceiver(ServerGamePacketListenerImpl, ResourceLocation, PlayChannelHandler)
|
||||
*/
|
||||
public static boolean registerGlobalReceiver(ResourceLocation channelName, PlayChannelHandler channelHandler) {
|
||||
return ServerNetworkingImpl.PLAY.registerGlobalReceiver(channelName, channelHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the handler of a channel.
|
||||
* A global receiver is registered to all connections, in the present and future.
|
||||
*
|
||||
* <p>The {@code channel} is guaranteed not to have a handler after this call.
|
||||
*
|
||||
* @param channelName the id of the channel
|
||||
* @return the previous handler, or {@code null} if no handler was bound to the channel
|
||||
* @see ServerPlayNetworking#registerGlobalReceiver(ResourceLocation, PlayChannelHandler)
|
||||
* @see ServerPlayNetworking#unregisterReceiver(ServerGamePacketListenerImpl, ResourceLocation)
|
||||
*/
|
||||
@Nullable
|
||||
public static PlayChannelHandler unregisterGlobalReceiver(ResourceLocation channelName) {
|
||||
return ServerNetworkingImpl.PLAY.unregisterGlobalReceiver(channelName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all channel names which global receivers are registered for.
|
||||
* A global receiver is registered to all connections, in the present and future.
|
||||
*
|
||||
* @return all channel names which global receivers are registered for.
|
||||
*/
|
||||
public static Set<ResourceLocation> getGlobalReceivers() {
|
||||
return ServerNetworkingImpl.PLAY.getChannels();
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a handler to a channel.
|
||||
* This method differs from {@link ServerPlayNetworking#registerGlobalReceiver(ResourceLocation, PlayChannelHandler)} since
|
||||
* the channel handler will only be applied to the player represented by the {@link ServerGamePacketListenerImpl}.
|
||||
*
|
||||
* <p>For example, if you only register a receiver using this method when a {@linkplain ServerLoginNetworking#registerGlobalReceiver(ResourceLocation, ServerLoginNetworking.LoginQueryResponseHandler)}
|
||||
* login response has been received, you should use {@link ServerPlayConnectionEvents#INIT} to register the channel handler.
|
||||
*
|
||||
* <p>If a handler is already registered to the {@code channelName}, this method will return {@code false}, and no change will be made.
|
||||
* Use {@link #unregisterReceiver(ServerGamePacketListenerImpl, ResourceLocation)} to unregister the existing handler.
|
||||
*
|
||||
* @param networkHandler the handler
|
||||
* @param channelName the id of the channel
|
||||
* @param channelHandler the handler
|
||||
* @return false if a handler is already registered to the channel name
|
||||
* @see ServerPlayConnectionEvents#INIT
|
||||
*/
|
||||
public static boolean registerReceiver(ServerGamePacketListenerImpl networkHandler, ResourceLocation channelName, PlayChannelHandler channelHandler) {
|
||||
Objects.requireNonNull(networkHandler, "Network handler cannot be null");
|
||||
|
||||
return ServerNetworkingImpl.getAddon(networkHandler).registerChannel(channelName, channelHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the handler of a channel.
|
||||
*
|
||||
* <p>The {@code channelName} is guaranteed not to have a handler after this call.
|
||||
*
|
||||
* @param channelName the id of the channel
|
||||
* @return the previous handler, or {@code null} if no handler was bound to the channel name
|
||||
*/
|
||||
@Nullable
|
||||
public static PlayChannelHandler unregisterReceiver(ServerGamePacketListenerImpl networkHandler, ResourceLocation channelName) {
|
||||
Objects.requireNonNull(networkHandler, "Network handler cannot be null");
|
||||
|
||||
return ServerNetworkingImpl.getAddon(networkHandler).unregisterChannel(channelName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all the channel names that the server can receive packets on.
|
||||
*
|
||||
* @param player the player
|
||||
* @return All the channel names that the server can receive packets on
|
||||
*/
|
||||
public static Set<ResourceLocation> getReceived(ServerPlayer player) {
|
||||
Objects.requireNonNull(player, "Server player entity cannot be null");
|
||||
|
||||
return getReceived(player.connection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all the channel names that the server can receive packets on.
|
||||
*
|
||||
* @param handler the network handler
|
||||
* @return All the channel names that the server can receive packets on
|
||||
*/
|
||||
public static Set<ResourceLocation> getReceived(ServerGamePacketListenerImpl handler) {
|
||||
Objects.requireNonNull(handler, "Server play network handler cannot be null");
|
||||
|
||||
return ServerNetworkingImpl.getAddon(handler).getReceivableChannels();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all channel names that the connected client declared the ability to receive a packets on.
|
||||
*
|
||||
* @param player the player
|
||||
* @return All the channel names the connected client declared the ability to receive a packets on
|
||||
*/
|
||||
public static Set<ResourceLocation> getSendable(ServerPlayer player) {
|
||||
Objects.requireNonNull(player, "Server player entity cannot be null");
|
||||
|
||||
return getSendable(player.connection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all channel names that a the connected client declared the ability to receive a packets on.
|
||||
*
|
||||
* @param handler the network handler
|
||||
* @return True if the connected client has declared the ability to receive a packet on the specified channel
|
||||
*/
|
||||
public static Set<ResourceLocation> getSendable(ServerGamePacketListenerImpl handler) {
|
||||
Objects.requireNonNull(handler, "Server play network handler cannot be null");
|
||||
|
||||
return ServerNetworkingImpl.getAddon(handler).getSendableChannels();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the connected client declared the ability to receive a packet on a specified channel name.
|
||||
*
|
||||
* @param player the player
|
||||
* @param channelName the channel name
|
||||
* @return True if the connected client has declared the ability to receive a packet on the specified channel
|
||||
*/
|
||||
public static boolean canSend(ServerPlayer player, ResourceLocation channelName) {
|
||||
Objects.requireNonNull(player, "Server player entity cannot be null");
|
||||
|
||||
return canSend(player.connection, channelName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the connected client declared the ability to receive a packet on a specified channel name.
|
||||
*
|
||||
* @param handler the network handler
|
||||
* @param channelName the channel name
|
||||
* @return True if the connected client has declared the ability to receive a packet on the specified channel
|
||||
*/
|
||||
public static boolean canSend(ServerGamePacketListenerImpl handler, ResourceLocation channelName) {
|
||||
Objects.requireNonNull(handler, "Server play network handler cannot be null");
|
||||
Objects.requireNonNull(channelName, "Channel name cannot be null");
|
||||
|
||||
return ServerNetworkingImpl.getAddon(handler).getSendableChannels().contains(channelName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a packet which may be sent to a the connected client.
|
||||
*
|
||||
* @param channelName the channel name
|
||||
* @param buf the packet byte buf which represents the payload of the packet
|
||||
* @return a new packet
|
||||
*/
|
||||
public static Packet<?> createS2CPacket(ResourceLocation channelName, FriendlyByteBuf buf) {
|
||||
Objects.requireNonNull(channelName, "Channel cannot be null");
|
||||
Objects.requireNonNull(buf, "Buf cannot be null");
|
||||
|
||||
return ServerNetworkingImpl.createPlayC2SPacket(channelName, buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the packet sender which sends packets to the connected client.
|
||||
*
|
||||
* @param player the player
|
||||
* @return the packet sender
|
||||
*/
|
||||
public static PacketSender getSender(ServerPlayer player) {
|
||||
Objects.requireNonNull(player, "Server player entity cannot be null");
|
||||
|
||||
return getSender(player.connection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the packet sender which sends packets to the connected client.
|
||||
*
|
||||
* @param handler the network handler, representing the connection to the player/client
|
||||
* @return the packet sender
|
||||
*/
|
||||
public static PacketSender getSender(ServerGamePacketListenerImpl handler) {
|
||||
Objects.requireNonNull(handler, "Server play network handler cannot be null");
|
||||
|
||||
return ServerNetworkingImpl.getAddon(handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a packet to a player.
|
||||
*
|
||||
* @param player the player to send the packet to
|
||||
* @param channelName the channel of the packet
|
||||
* @param buf the payload of the packet.
|
||||
*/
|
||||
public static void send(ServerPlayer player, ResourceLocation channelName, FriendlyByteBuf buf) {
|
||||
Objects.requireNonNull(player, "Server player entity cannot be null");
|
||||
Objects.requireNonNull(channelName, "Channel name cannot be null");
|
||||
Objects.requireNonNull(buf, "Packet byte buf cannot be null");
|
||||
|
||||
player.connection.send(createS2CPacket(channelName, buf));
|
||||
}
|
||||
|
||||
// Helper methods
|
||||
|
||||
/**
|
||||
* Returns the <i>Minecraft</i> Server of a server play network handler.
|
||||
*
|
||||
* @param handler the server play network handler
|
||||
*/
|
||||
public static MinecraftServer getServer(ServerGamePacketListenerImpl handler) {
|
||||
Objects.requireNonNull(handler, "Network handler cannot be null");
|
||||
|
||||
return handler.player.server;
|
||||
}
|
||||
|
||||
private ServerPlayNetworking() {
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface PlayChannelHandler {
|
||||
/**
|
||||
* Handles an incoming packet.
|
||||
*
|
||||
* <p>This method is executed on {@linkplain io.netty.channel.EventLoop netty's event loops}.
|
||||
* Modification to the game should be {@linkplain net.minecraft.util.thread.BlockableEventLoop#submit(Runnable) scheduled} using the provided Minecraft server instance.
|
||||
*
|
||||
* <p>An example usage of this is to create an explosion where the player is looking:
|
||||
* <pre>{@code
|
||||
* ServerPlayNetworking.registerReceiver(new Identifier("mymod", "boom"), (server, player, handler, buf, responseSender) -&rt; {
|
||||
* boolean fire = buf.readBoolean();
|
||||
*
|
||||
* // All operations on the server or world must be executed on the server thread
|
||||
* server.execute(() -&rt; {
|
||||
* ModPacketHandler.createExplosion(player, fire);
|
||||
* });
|
||||
* });
|
||||
* }</pre>
|
||||
* @param server the server
|
||||
* @param player the player
|
||||
* @param handler the network handler that received this packet, representing the player/client who sent the packet
|
||||
* @param buf the payload of the packet
|
||||
* @param responseSender the packet sender
|
||||
*/
|
||||
void receive(MinecraftServer server, ServerPlayer player, ServerGamePacketListenerImpl handler, FriendlyByteBuf buf, PacketSender responseSender);
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The Networking API, version 1.
|
||||
*
|
||||
* <p>For login stage networking see {@link net.fabricmc.fabric.api.networking.v1.ServerLoginNetworking}.
|
||||
* For play stage networking see {@link net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking}.
|
||||
*
|
||||
* <p>For events related to the connection to a client see {@link net.fabricmc.fabric.api.networking.v1.ServerLoginConnectionEvents} for login stage
|
||||
* or {@link net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents} for play stage.
|
||||
*
|
||||
* <p>For events related to the ability of a client to receive packets on a channel of a specific name see {@link net.fabricmc.fabric.api.networking.v1.S2CPlayChannelEvents}.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.forge.fabric.api.networking.v1;
|
||||
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.forge.fabric.api.util;
|
||||
|
||||
/**
|
||||
* Represents a function that accepts an boolean-valued argument and produces a result.
|
||||
*
|
||||
* <p>This is the {@code boolean}-consuming primitive specialization for {@link java.util.function.Function}.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface BooleanFunction<R> {
|
||||
/**
|
||||
* Applies this function to the given argument.
|
||||
*
|
||||
* @param value the function argument
|
||||
* @return the function result
|
||||
*/
|
||||
R apply(boolean value);
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.forge.fabric.api.util;
|
||||
|
||||
/**
|
||||
* NBT type ID constants. Useful for filtering by value type in a few cases.
|
||||
*
|
||||
* <p>For the current list of types, check with {@link NbtElement#TYPES}.
|
||||
*
|
||||
* @see NbtCompound#contains(String, int)
|
||||
* @see net.minecraft.nbt.NbtTypes#byId(int)
|
||||
*/
|
||||
public final class NbtType {
|
||||
public static final int END = 0;
|
||||
public static final int BYTE = 1;
|
||||
public static final int SHORT = 2;
|
||||
public static final int INT = 3;
|
||||
public static final int LONG = 4;
|
||||
public static final int FLOAT = 5;
|
||||
public static final int DOUBLE = 6;
|
||||
public static final int BYTE_ARRAY = 7;
|
||||
public static final int STRING = 8;
|
||||
public static final int LIST = 9;
|
||||
public static final int COMPOUND = 10;
|
||||
public static final int INT_ARRAY = 11;
|
||||
public static final int LONG_ARRAY = 12;
|
||||
|
||||
/**
|
||||
* Any numeric value: byte, short, int, long, float, double.
|
||||
*
|
||||
* @see NbtCompound#contains(String, int)
|
||||
*/
|
||||
public static final int NUMBER = 99;
|
||||
|
||||
private NbtType() { }
|
||||
}
|
||||
@@ -1,139 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.forge.fabric.api.util;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.function.BooleanSupplier;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Represents a boolean value which can be true, false or refer to a default value.
|
||||
*/
|
||||
public enum TriState {
|
||||
/**
|
||||
* Represents the boolean value of {@code false}.
|
||||
*/
|
||||
FALSE,
|
||||
/**
|
||||
* Represents a value that refers to a "default" value, often as a fallback.
|
||||
*/
|
||||
DEFAULT,
|
||||
/**
|
||||
* Represents the boolean value of {@code true}.
|
||||
*/
|
||||
TRUE;
|
||||
|
||||
/**
|
||||
* Gets the corresponding tri-state from a boolean value.
|
||||
*
|
||||
* @param bool the boolean value
|
||||
* @return {@link TriState#TRUE} or {@link TriState#FALSE} depending on the value of the boolean.
|
||||
*/
|
||||
public static TriState of(boolean bool) {
|
||||
return bool ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a tri-state from a nullable boxed boolean.
|
||||
*
|
||||
* @param bool the boolean value
|
||||
* @return {@link TriState#DEFAULT} if {@code null}.
|
||||
* Otherwise {@link TriState#TRUE} or {@link TriState#FALSE} depending on the value of the boolean.
|
||||
*/
|
||||
public static TriState of(@Nullable Boolean bool) {
|
||||
return bool == null ? DEFAULT : of(bool.booleanValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the tri-state.
|
||||
*
|
||||
* @return true if the tri-state is {@link TriState#TRUE}.
|
||||
* Otherwise false.
|
||||
*/
|
||||
public boolean get() {
|
||||
return this == TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the tri-state as a boxed, nullable boolean.
|
||||
*
|
||||
* @return {@code null} if {@link TriState#DEFAULT}.
|
||||
* Otherwise {@code true} if {@link TriState#TRUE} or {@code false} if {@link TriState#FALSE}.
|
||||
*/
|
||||
@Nullable
|
||||
public Boolean getBoxed() {
|
||||
return this == DEFAULT ? null : this.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of this tri-state.
|
||||
* If the value is {@link TriState#DEFAULT} then use the supplied value.
|
||||
*
|
||||
* @param value the value to fallback to
|
||||
* @return the value of the tri-state or the supplied value if {@link TriState#DEFAULT}.
|
||||
*/
|
||||
public boolean orElse(boolean value) {
|
||||
return this == DEFAULT ? value : this.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of this tri-state.
|
||||
* If the value is {@link TriState#DEFAULT} then use the supplied value.
|
||||
*
|
||||
* @param supplier the supplier used to get the value to fallback to
|
||||
* @return the value of the tri-state or the value of the supplier if the tri-state is {@link TriState#DEFAULT}.
|
||||
*/
|
||||
public boolean orElseGet(BooleanSupplier supplier) {
|
||||
return this == DEFAULT ? supplier.getAsBoolean() : this.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps the boolean value of this tri-state if it is {@link TriState#TRUE} or {@link TriState#FALSE}.
|
||||
*
|
||||
* @param mapper the mapper to use
|
||||
* @param <T> the type of object being supplier by the mapper
|
||||
* @return an optional containing the mapped value; {@link Optional#empty()} if the tri-state is {@link TriState#DEFAULT} or the value provided by the mapper is {@code null}.
|
||||
*/
|
||||
public <T> Optional<T> map(BooleanFunction<@Nullable ? extends T> mapper) {
|
||||
Objects.requireNonNull(mapper, "Mapper function cannot be null");
|
||||
|
||||
if (this == DEFAULT) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
return Optional.ofNullable(mapper.apply(this.get()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of this tri-state, or throws an exception if this tri-state's value is {@link TriState#DEFAULT}.
|
||||
*
|
||||
* @param exceptionSupplier the supplying function that produces an exception to be thrown
|
||||
* @param <X> Type of the exception to be thrown
|
||||
* @return the value
|
||||
* @throws X if the value is {@link TriState#DEFAULT}
|
||||
*/
|
||||
public <X extends Throwable> boolean orElseThrow(Supplier<X> exceptionSupplier) throws X {
|
||||
if (this != DEFAULT) {
|
||||
return this.get();
|
||||
}
|
||||
|
||||
throw exceptionSupplier.get();
|
||||
}
|
||||
}
|
||||
-130
@@ -1,130 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.forge.fabric.impl.base.event;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
import com.seibel.lod.forge.fabric.api.event.Event;
|
||||
|
||||
class ArrayBackedEvent<T> extends Event<T> {
|
||||
static final Logger LOGGER = LoggerFactory.getLogger("fabric-api-base");
|
||||
|
||||
private final Function<T[], T> invokerFactory;
|
||||
private final Object lock = new Object();
|
||||
private T[] handlers;
|
||||
/**
|
||||
* Registered event phases.
|
||||
*/
|
||||
private final Map<ResourceLocation, EventPhaseData<T>> phases = new LinkedHashMap<>();
|
||||
/**
|
||||
* Phases sorted in the correct dependency order.
|
||||
*/
|
||||
private final List<EventPhaseData<T>> sortedPhases = new ArrayList<>();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
ArrayBackedEvent(Class<? super T> type, Function<T[], T> invokerFactory) {
|
||||
this.invokerFactory = invokerFactory;
|
||||
this.handlers = (T[]) Array.newInstance(type, 0);
|
||||
update();
|
||||
}
|
||||
|
||||
void update() {
|
||||
this.invoker = invokerFactory.apply(handlers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(T listener) {
|
||||
register(DEFAULT_PHASE, listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(ResourceLocation phaseResourceLocation, T listener) {
|
||||
Objects.requireNonNull(phaseResourceLocation, "Tried to register a listener for a null phase!");
|
||||
Objects.requireNonNull(listener, "Tried to register a null listener!");
|
||||
|
||||
synchronized (lock) {
|
||||
getOrCreatePhase(phaseResourceLocation, true).addListener(listener);
|
||||
rebuildInvoker(handlers.length + 1);
|
||||
}
|
||||
}
|
||||
|
||||
private EventPhaseData<T> getOrCreatePhase(ResourceLocation id, boolean sortIfCreate) {
|
||||
EventPhaseData<T> phase = phases.get(id);
|
||||
|
||||
if (phase == null) {
|
||||
phase = new EventPhaseData<>(id, handlers.getClass().getComponentType());
|
||||
phases.put(id, phase);
|
||||
sortedPhases.add(phase);
|
||||
|
||||
if (sortIfCreate) {
|
||||
PhaseSorting.sortPhases(sortedPhases);
|
||||
}
|
||||
}
|
||||
|
||||
return phase;
|
||||
}
|
||||
|
||||
private void rebuildInvoker(int newLength) {
|
||||
// Rebuild handlers.
|
||||
if (sortedPhases.size() == 1) {
|
||||
// Special case with a single phase: use the array of the phase directly.
|
||||
handlers = sortedPhases.get(0).listeners;
|
||||
} else {
|
||||
@SuppressWarnings("unchecked")
|
||||
T[] newHandlers = (T[]) Array.newInstance(handlers.getClass().getComponentType(), newLength);
|
||||
int newHandlersIndex = 0;
|
||||
|
||||
for (EventPhaseData<T> existingPhase : sortedPhases) {
|
||||
int length = existingPhase.listeners.length;
|
||||
System.arraycopy(existingPhase.listeners, 0, newHandlers, newHandlersIndex, length);
|
||||
newHandlersIndex += length;
|
||||
}
|
||||
|
||||
handlers = newHandlers;
|
||||
}
|
||||
|
||||
// Rebuild invoker.
|
||||
update();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addPhaseOrdering(ResourceLocation firstPhase, ResourceLocation secondPhase) {
|
||||
Objects.requireNonNull(firstPhase, "Tried to add an ordering for a null phase.");
|
||||
Objects.requireNonNull(secondPhase, "Tried to add an ordering for a null phase.");
|
||||
if (firstPhase.equals(secondPhase)) throw new IllegalArgumentException("Tried to add a phase that depends on itself.");
|
||||
|
||||
synchronized (lock) {
|
||||
EventPhaseData<T> first = getOrCreatePhase(firstPhase, false);
|
||||
EventPhaseData<T> second = getOrCreatePhase(secondPhase, false);
|
||||
first.subsequentPhases.add(second);
|
||||
second.previousPhases.add(first);
|
||||
PhaseSorting.sortPhases(this.sortedPhases);
|
||||
rebuildInvoker(handlers.length);
|
||||
}
|
||||
}
|
||||
}
|
||||
-122
@@ -1,122 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.forge.fabric.impl.base.event;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
import com.seibel.lod.forge.fabric.api.event.Event;
|
||||
|
||||
public final class EventFactoryImpl {
|
||||
private static final List<ArrayBackedEvent<?>> ARRAY_BACKED_EVENTS = new ArrayList<>();
|
||||
|
||||
private EventFactoryImpl() { }
|
||||
|
||||
public static void invalidate() {
|
||||
ARRAY_BACKED_EVENTS.forEach(ArrayBackedEvent::update);
|
||||
}
|
||||
|
||||
public static <T> Event<T> createArrayBacked(Class<? super T> type, Function<T[], T> invokerFactory) {
|
||||
ArrayBackedEvent<T> event = new ArrayBackedEvent<>(type, invokerFactory);
|
||||
ARRAY_BACKED_EVENTS.add(event);
|
||||
return event;
|
||||
}
|
||||
|
||||
public static void ensureContainsDefault(ResourceLocation[] defaultPhases) {
|
||||
for (ResourceLocation id : defaultPhases) {
|
||||
if (id.equals(Event.DEFAULT_PHASE)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("The event phases must contain Event.DEFAULT_PHASE.");
|
||||
}
|
||||
|
||||
public static void ensureNoDuplicates(ResourceLocation[] defaultPhases) {
|
||||
for (int i = 0; i < defaultPhases.length; ++i) {
|
||||
for (int j = i+1; j < defaultPhases.length; ++j) {
|
||||
if (defaultPhases[i].equals(defaultPhases[j])) {
|
||||
throw new IllegalArgumentException("Duplicate event phase: " + defaultPhases[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Code originally by sfPlayer1.
|
||||
// Unfortunately, it's slightly slower than just passing an empty array in the first place.
|
||||
private static <T> T buildEmptyInvoker(Class<T> handlerClass, Function<T[], T> invokerSetup) {
|
||||
// find the functional interface method
|
||||
Method funcIfMethod = null;
|
||||
|
||||
for (Method m : handlerClass.getMethods()) {
|
||||
if ((m.getModifiers() & (Modifier.STRICT | Modifier.PRIVATE)) == 0) {
|
||||
if (funcIfMethod != null) {
|
||||
throw new IllegalStateException("Multiple virtual methods in " + handlerClass + "; cannot build empty invoker!");
|
||||
}
|
||||
|
||||
funcIfMethod = m;
|
||||
}
|
||||
}
|
||||
|
||||
if (funcIfMethod == null) {
|
||||
throw new IllegalStateException("No virtual methods in " + handlerClass + "; cannot build empty invoker!");
|
||||
}
|
||||
|
||||
Object defValue = null;
|
||||
|
||||
try {
|
||||
// concert to mh, determine its type without the "this" reference
|
||||
MethodHandle target = MethodHandles.lookup().unreflect(funcIfMethod);
|
||||
MethodType type = target.type().dropParameterTypes(0, 1);
|
||||
|
||||
if (type.returnType() != void.class) {
|
||||
// determine default return value by invoking invokerSetup.apply(T[0]) with all-jvm-default args (null for refs, false for boolean, etc.)
|
||||
// explicitCastArguments is being used to cast Object=null to the jvm default value for the correct type
|
||||
|
||||
// construct method desc (TLjava/lang/Object;Ljava/lang/Object;...)R where T = invoker ref ("this"), R = invoker ret type and args 1+ are Object for each non-"this" invoker arg
|
||||
MethodType objTargetType = MethodType.genericMethodType(type.parameterCount()).changeReturnType(type.returnType()).insertParameterTypes(0, target.type().parameterType(0));
|
||||
// explicit cast to translate to the invoker args from Object to their real type, inferring jvm default values
|
||||
MethodHandle objTarget = MethodHandles.explicitCastArguments(target, objTargetType);
|
||||
|
||||
// build invocation args with 0 = "this", 1+ = null
|
||||
Object[] args = new Object[target.type().parameterCount()];
|
||||
//noinspection unchecked
|
||||
args[0] = invokerSetup.apply((T[]) Array.newInstance(handlerClass, 0));
|
||||
|
||||
// retrieve default by invoking invokerSetup.apply(T[0]).targetName(def,def,...)
|
||||
defValue = objTarget.invokeWithArguments(args);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
throw new RuntimeException(t);
|
||||
}
|
||||
|
||||
final Object returnValue = defValue;
|
||||
//noinspection unchecked
|
||||
return (T) Proxy.newProxyInstance(EventFactoryImpl.class.getClassLoader(), new Class[]{handlerClass},
|
||||
(proxy, method, args) -> returnValue);
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.forge.fabric.impl.base.event;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
/**
|
||||
* Data of an {@link ArrayBackedEvent} phase.
|
||||
*/
|
||||
class EventPhaseData<T> {
|
||||
final ResourceLocation id;
|
||||
T[] listeners;
|
||||
final List<EventPhaseData<T>> subsequentPhases = new ArrayList<>();
|
||||
final List<EventPhaseData<T>> previousPhases = new ArrayList<>();
|
||||
int visitStatus = 0; // 0: not visited, 1: visiting, 2: visited
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
EventPhaseData(ResourceLocation id, Class<?> listenerClass) {
|
||||
this.id = id;
|
||||
this.listeners = (T[]) Array.newInstance(listenerClass, 0);
|
||||
}
|
||||
|
||||
void addListener(T listener) {
|
||||
int oldLength = listeners.length;
|
||||
listeners = Arrays.copyOf(listeners, oldLength + 1);
|
||||
listeners[oldLength] = listener;
|
||||
}
|
||||
}
|
||||
@@ -1,164 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.forge.fabric.impl.base.event;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.PriorityQueue;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
/**
|
||||
* Contains phase-sorting logic for {@link ArrayBackedEvent}.
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
public class PhaseSorting {
|
||||
@VisibleForTesting
|
||||
public static boolean ENABLE_CYCLE_WARNING = true;
|
||||
|
||||
/**
|
||||
* Deterministically sort a list of phases.
|
||||
* 1) Compute phase SCCs (i.e. cycles).
|
||||
* 2) Sort phases by id within SCCs.
|
||||
* 3) Sort SCCs with respect to each other by respecting constraints, and by id in case of a tie.
|
||||
*/
|
||||
static <T> void sortPhases(List<EventPhaseData<T>> sortedPhases) {
|
||||
// FIRST KOSARAJU SCC VISIT
|
||||
List<EventPhaseData<T>> toposort = new ArrayList<>(sortedPhases.size());
|
||||
|
||||
for (EventPhaseData<T> phase : sortedPhases) {
|
||||
forwardVisit(phase, null, toposort);
|
||||
}
|
||||
|
||||
clearStatus(toposort);
|
||||
Collections.reverse(toposort);
|
||||
|
||||
// SECOND KOSARAJU SCC VISIT
|
||||
Map<EventPhaseData<T>, PhaseScc<T>> phaseToScc = new IdentityHashMap<>();
|
||||
|
||||
for (EventPhaseData<T> phase : toposort) {
|
||||
if (phase.visitStatus == 0) {
|
||||
List<EventPhaseData<T>> sccPhases = new ArrayList<>();
|
||||
// Collect phases in SCC.
|
||||
backwardVisit(phase, sccPhases);
|
||||
// Sort phases by id.
|
||||
sccPhases.sort(Comparator.comparing(p -> p.id));
|
||||
// Mark phases as belonging to this SCC.
|
||||
PhaseScc<T> scc = new PhaseScc<>(sccPhases);
|
||||
|
||||
for (EventPhaseData<T> phaseInScc : sccPhases) {
|
||||
phaseToScc.put(phaseInScc, scc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
clearStatus(toposort);
|
||||
|
||||
// Build SCC graph
|
||||
for (PhaseScc<T> scc : phaseToScc.values()) {
|
||||
for (EventPhaseData<T> phase : scc.phases) {
|
||||
for (EventPhaseData<T> subsequentPhase : phase.subsequentPhases) {
|
||||
PhaseScc<T> subsequentScc = phaseToScc.get(subsequentPhase);
|
||||
|
||||
if (subsequentScc != scc) {
|
||||
scc.subsequentSccs.add(subsequentScc);
|
||||
subsequentScc.inDegree++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Order SCCs according to priorities. When there is a choice, use the SCC with the lowest id.
|
||||
// The priority queue contains all SCCs that currently have 0 in-degree.
|
||||
PriorityQueue<PhaseScc<T>> pq = new PriorityQueue<>(Comparator.comparing(scc -> scc.phases.get(0).id));
|
||||
sortedPhases.clear();
|
||||
|
||||
for (PhaseScc<T> scc : phaseToScc.values()) {
|
||||
if (scc.inDegree == 0) {
|
||||
pq.add(scc);
|
||||
// Prevent adding the same SCC multiple times, as phaseToScc may contain the same value multiple times.
|
||||
scc.inDegree = -1;
|
||||
}
|
||||
}
|
||||
|
||||
while (!pq.isEmpty()) {
|
||||
PhaseScc<T> scc = pq.poll();
|
||||
sortedPhases.addAll(scc.phases);
|
||||
|
||||
for (PhaseScc<T> subsequentScc : scc.subsequentSccs) {
|
||||
subsequentScc.inDegree--;
|
||||
|
||||
if (subsequentScc.inDegree == 0) {
|
||||
pq.add(subsequentScc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static <T> void forwardVisit(EventPhaseData<T> phase, EventPhaseData<T> parent, List<EventPhaseData<T>> toposort) {
|
||||
if (phase.visitStatus == 0) {
|
||||
// Not yet visited.
|
||||
phase.visitStatus = 1;
|
||||
|
||||
for (EventPhaseData<T> data : phase.subsequentPhases) {
|
||||
forwardVisit(data, phase, toposort);
|
||||
}
|
||||
|
||||
toposort.add(phase);
|
||||
phase.visitStatus = 2;
|
||||
} else if (phase.visitStatus == 1 && ENABLE_CYCLE_WARNING) {
|
||||
// Already visiting, so we have found a cycle.
|
||||
ArrayBackedEvent.LOGGER.warn(String.format(
|
||||
"Event phase ordering conflict detected.%nEvent phase %s is ordered both before and after event phase %s.",
|
||||
phase.id,
|
||||
parent.id
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
private static <T> void clearStatus(List<EventPhaseData<T>> phases) {
|
||||
for (EventPhaseData<T> phase : phases) {
|
||||
phase.visitStatus = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private static <T> void backwardVisit(EventPhaseData<T> phase, List<EventPhaseData<T>> sccPhases) {
|
||||
if (phase.visitStatus == 0) {
|
||||
phase.visitStatus = 1;
|
||||
sccPhases.add(phase);
|
||||
|
||||
for (EventPhaseData<T> data : phase.previousPhases) {
|
||||
backwardVisit(data, sccPhases);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class PhaseScc<T> {
|
||||
final List<EventPhaseData<T>> phases;
|
||||
final List<PhaseScc<T>> subsequentSccs = new ArrayList<>();
|
||||
int inDegree = 0;
|
||||
|
||||
private PhaseScc(List<EventPhaseData<T>> phases) {
|
||||
this.phases = phases;
|
||||
}
|
||||
}
|
||||
}
|
||||
-205
@@ -1,205 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.forge.fabric.impl.networking;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import io.netty.util.AsciiString;
|
||||
import io.netty.util.concurrent.Future;
|
||||
import io.netty.util.concurrent.GenericFutureListener;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import com.seibel.lod.forge.fabric.api.networking.v1.PacketByteBufs;
|
||||
import com.seibel.lod.forge.fabric.api.networking.v1.PacketSender;
|
||||
import net.minecraft.ResourceLocationException;
|
||||
import net.minecraft.network.Connection;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.network.protocol.Packet;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
/**
|
||||
* A network addon which is aware of the channels the other side may receive.
|
||||
*
|
||||
* @param <H> the channel handler type
|
||||
*/
|
||||
public abstract class AbstractChanneledNetworkAddon<H> extends AbstractNetworkAddon<H> implements PacketSender {
|
||||
protected final Connection connection;
|
||||
protected final GlobalReceiverRegistry<H> receiver;
|
||||
protected final Set<ResourceLocation> sendableChannels;
|
||||
protected final Set<ResourceLocation> sendableChannelsView;
|
||||
|
||||
protected AbstractChanneledNetworkAddon(GlobalReceiverRegistry<H> receiver, Connection connection, String description) {
|
||||
this(receiver, connection, new HashSet<>(), description);
|
||||
}
|
||||
|
||||
protected AbstractChanneledNetworkAddon(GlobalReceiverRegistry<H> receiver, Connection connection, Set<ResourceLocation> sendableChannels, String description) {
|
||||
super(receiver, description);
|
||||
this.connection = connection;
|
||||
this.receiver = receiver;
|
||||
this.sendableChannels = sendableChannels;
|
||||
this.sendableChannelsView = Collections.unmodifiableSet(sendableChannels);
|
||||
}
|
||||
|
||||
public abstract void lateInit();
|
||||
|
||||
protected void registerPendingChannels(ChannelInfoHolder holder) {
|
||||
final Collection<ResourceLocation> pending = holder.getPendingChannelsNames();
|
||||
|
||||
if (!pending.isEmpty()) {
|
||||
register(new ArrayList<>(pending));
|
||||
pending.clear();
|
||||
}
|
||||
}
|
||||
|
||||
// always supposed to handle async!
|
||||
protected boolean handle(ResourceLocation channelName, FriendlyByteBuf originalBuf) {
|
||||
this.logger.debug("Handling inbound packet from channel with name \"{}\"", channelName);
|
||||
|
||||
// Handle reserved packets
|
||||
if (NetworkingImpl.REGISTER_CHANNEL.equals(channelName)) {
|
||||
this.receiveRegistration(true, PacketByteBufs.slice(originalBuf));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (NetworkingImpl.UNREGISTER_CHANNEL.equals(channelName)) {
|
||||
this.receiveRegistration(false, PacketByteBufs.slice(originalBuf));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable H handler = this.getHandler(channelName);
|
||||
|
||||
if (handler == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
FriendlyByteBuf buf = PacketByteBufs.slice(originalBuf);
|
||||
|
||||
try {
|
||||
this.receive(handler, buf);
|
||||
} catch (Throwable ex) {
|
||||
this.logger.error("Encountered exception while handling in channel with name \"{}\"", channelName, ex);
|
||||
throw ex;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected abstract void receive(H handler, FriendlyByteBuf buf);
|
||||
|
||||
protected void sendInitialChannelRegistrationPacket() {
|
||||
final FriendlyByteBuf buf = this.createRegistrationPacket(this.getReceivableChannels());
|
||||
|
||||
if (buf != null) {
|
||||
this.sendPacket(NetworkingImpl.REGISTER_CHANNEL, buf);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected FriendlyByteBuf createRegistrationPacket(Collection<ResourceLocation> channels) {
|
||||
if (channels.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
FriendlyByteBuf buf = PacketByteBufs.create();
|
||||
boolean first = true;
|
||||
|
||||
for (ResourceLocation channel : channels) {
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
buf.writeByte(0);
|
||||
}
|
||||
|
||||
buf.writeBytes(channel.toString().getBytes(StandardCharsets.US_ASCII));
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
// wrap in try with res (buf)
|
||||
protected void receiveRegistration(boolean register, FriendlyByteBuf buf) {
|
||||
List<ResourceLocation> ids = new ArrayList<>();
|
||||
StringBuilder active = new StringBuilder();
|
||||
|
||||
while (buf.isReadable()) {
|
||||
byte b = buf.readByte();
|
||||
|
||||
if (b != 0) {
|
||||
active.append(AsciiString.b2c(b));
|
||||
} else {
|
||||
this.addId(ids, active);
|
||||
active = new StringBuilder();
|
||||
}
|
||||
}
|
||||
|
||||
this.addId(ids, active);
|
||||
this.schedule(register ? () -> register(ids) : () -> unregister(ids));
|
||||
}
|
||||
|
||||
void register(List<ResourceLocation> ids) {
|
||||
this.sendableChannels.addAll(ids);
|
||||
this.invokeRegisterEvent(ids);
|
||||
}
|
||||
|
||||
void unregister(List<ResourceLocation> ids) {
|
||||
this.sendableChannels.removeAll(ids);
|
||||
this.invokeUnregisterEvent(ids);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendPacket(Packet<?> packet) {
|
||||
Objects.requireNonNull(packet, "Packet cannot be null");
|
||||
|
||||
this.connection.send(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendPacket(Packet<?> packet, GenericFutureListener<? extends Future<? super Void>> callback) {
|
||||
Objects.requireNonNull(packet, "Packet cannot be null");
|
||||
|
||||
this.connection.send(packet, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedules a task to run on the main thread.
|
||||
*/
|
||||
protected abstract void schedule(Runnable task);
|
||||
|
||||
protected abstract void invokeRegisterEvent(List<ResourceLocation> ids);
|
||||
|
||||
protected abstract void invokeUnregisterEvent(List<ResourceLocation> ids);
|
||||
|
||||
private void addId(List<ResourceLocation> ids, StringBuilder sb) {
|
||||
String literal = sb.toString();
|
||||
|
||||
try {
|
||||
ids.add(new ResourceLocation(literal));
|
||||
} catch (ResourceLocationException ex) {
|
||||
this.logger.warn("Received invalid channel identifier \"{}\" from connection {}", literal, this.connection);
|
||||
}
|
||||
}
|
||||
|
||||
public Set<ResourceLocation> getSendableChannels() {
|
||||
return this.sendableChannelsView;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user