Compare commits
76 Commits
section-oc
...
v0.2.0-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6ec14ff755 | ||
|
|
18e872ad12 | ||
|
|
13c6499854 | ||
|
|
b70443edd5 | ||
|
|
38bab21ddf | ||
|
|
f7d98327e0 | ||
|
|
271a58d2af | ||
|
|
a4f5ef1abd | ||
|
|
d87df61412 | ||
|
|
e917272d3a | ||
|
|
bff8caea54 | ||
|
|
97a865c532 | ||
|
|
f6541b0d91 | ||
|
|
6b4139a5ab | ||
|
|
43164acf5e | ||
|
|
73d73c935a | ||
|
|
7863c556f9 | ||
|
|
c0b02ea709 | ||
|
|
9004f12be6 | ||
|
|
b2144a55aa | ||
|
|
882d733203 | ||
|
|
9b6982bf65 | ||
|
|
5635373cff | ||
|
|
76d2c36481 | ||
|
|
ca791ddc74 | ||
|
|
7f08c11a11 | ||
|
|
93b908350e | ||
|
|
4bd7eb8b72 | ||
|
|
a6cf977c5f | ||
|
|
8ed23bc8f3 | ||
|
|
7034995878 | ||
|
|
ca3d776562 | ||
|
|
1a077389c2 | ||
|
|
49bcc60cf5 | ||
|
|
8b1f31ade8 | ||
|
|
4d88e04e3c | ||
|
|
33889c3850 | ||
|
|
37ac3003cb | ||
|
|
28128d06c1 | ||
|
|
6f9620787b | ||
|
|
cbf6c118dc | ||
|
|
d44fa1f8aa | ||
|
|
3d9ae3f018 | ||
|
|
d24f6c2874 | ||
|
|
f190cdd8cb | ||
|
|
e7510eda16 | ||
|
|
d9442c1492 | ||
|
|
93eb2786f2 | ||
|
|
1bef6823c5 | ||
|
|
01152eec95 | ||
|
|
1e39f5370a | ||
|
|
ea50ba38ea | ||
|
|
c00b9fcd7b | ||
|
|
bad5cae4d8 | ||
|
|
e3b1502bb6 | ||
|
|
54fc964987 | ||
|
|
0cbc9aa1a1 | ||
|
|
19e2136ae1 | ||
|
|
126cc03747 | ||
|
|
ceb4936d9d | ||
|
|
3cb888e894 | ||
|
|
7bedc1a7de | ||
|
|
718f6e1369 | ||
|
|
da9ab708a6 | ||
|
|
f22335f0b6 | ||
|
|
a3f2328000 | ||
|
|
529b9a44bb | ||
|
|
1e9a6504a1 | ||
|
|
9c46dcbb94 | ||
|
|
9a1e04389a | ||
|
|
29084d8e3f | ||
|
|
41790ecf1a | ||
|
|
8af7bccdfd | ||
|
|
5f9b3571f8 | ||
|
|
9adfb2514d | ||
|
|
bf2cd1c571 |
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@@ -31,8 +31,6 @@ jobs:
|
|||||||
key: ${{ runner.os }}-project-local-gradle-caches-${{ hashFiles('**/libs.versions.toml', '**/*.gradle*', '**/gradle-wrapper.properties') }}
|
key: ${{ runner.os }}-project-local-gradle-caches-${{ hashFiles('**/libs.versions.toml', '**/*.gradle*', '**/gradle-wrapper.properties') }}
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
${{ runner.os }}-project-local-gradle-caches-
|
${{ runner.os }}-project-local-gradle-caches-
|
||||||
- name: "setup concurrentutil"
|
|
||||||
run: ./installConcurrentUtil.sh
|
|
||||||
- name: "execute gradle build"
|
- name: "execute gradle build"
|
||||||
run: ./gradlew build
|
run: ./gradlew build
|
||||||
- name: Determine Snapshot Status
|
- name: Determine Snapshot Status
|
||||||
|
|||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -116,3 +116,6 @@ run/
|
|||||||
|
|
||||||
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
|
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
|
||||||
!gradle-wrapper.jar
|
!gradle-wrapper.jar
|
||||||
|
|
||||||
|
ConcurrentUtil/
|
||||||
|
YamlConfig/
|
||||||
|
|||||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -1,3 +0,0 @@
|
|||||||
[submodule "ConcurrentUtil"]
|
|
||||||
path = ConcurrentUtil
|
|
||||||
url = https://github.com/Spottedleaf/ConcurrentUtil.git
|
|
||||||
|
|||||||
Submodule ConcurrentUtil deleted from 08d3ca3241
@@ -12,19 +12,19 @@ Fabric/NeoForge mod for optimising performance of the integrated (singleplayer/L
|
|||||||
Moonrise aims to optimise the game *without changing Vanilla behavior*. If you find that there are changes to Vanilla behavior,
|
Moonrise aims to optimise the game *without changing Vanilla behavior*. If you find that there are changes to Vanilla behavior,
|
||||||
please open an issue.
|
please open an issue.
|
||||||
|
|
||||||
Moonrise ports several important [Paper](https://github.com/PaperMC/Paper/)
|
Moonrise is an official port of several important [Paper](https://github.com/PaperMC/Paper/)
|
||||||
patches. Listed below are notable patches:
|
patches. Listed below are notable patches:
|
||||||
|
- [Starlight](https://github.com/PaperMC/Starlight/)
|
||||||
- Chunk system rewrite
|
- Chunk system rewrite
|
||||||
- Collision optimisations
|
- Collision optimisations
|
||||||
- Entity tracker optimisations
|
- Entity tracker optimisations
|
||||||
- Random ticking optimisations
|
- Random ticking optimisations
|
||||||
- [Starlight](https://github.com/PaperMC/Starlight/)
|
|
||||||
|
|
||||||
## Known Compatibility Issues
|
## Known Compatibility Issues
|
||||||
| Mod | Status |
|
| Mod | Status |
|
||||||
|-------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|-------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
| Lithium | <details><summary>✅ compatible</summary>Lithium optimises many of the same parts of the game as Moonrise, for example the chunk system. Moonrise will automatically disable conflicting parts of Lithium. This mechanism needs to be manually validated for each Moonrise and Lithium release.</details> |
|
| Lithium | <details><summary>✅ compatible</summary>Lithium optimises many of the same parts of the game as Moonrise, for example the chunk system. Moonrise will automatically disable conflicting parts of Lithium. This mechanism needs to be manually validated for each Moonrise and Lithium release.</details> |
|
||||||
| FerriteCore | <details><summary>📝 requires config changes</summary>In `config/ferritecore-mixin.toml`:<br/>Set `replaceNeighborLookup` and `replacePropertyMap` to `false`</details> |
|
| FerriteCore | <details><summary>✅ compatible</summary>FerriteCore optimises some of the same parts of the game as Moonrise. Moonrise will automatically disable conflicting parts of FerriteCore. This mechanism needs to be manually validated for each Moonrise and FerriteCore release.</details> |
|
||||||
| C2ME | <details><summary>❌ incompatible</summary>C2ME is based around modifications to the chunk system, which Moonrise replaces wholesale. This makes them fundamentally incompatible.</details> |
|
| C2ME | <details><summary>❌ incompatible</summary>C2ME is based around modifications to the chunk system, which Moonrise replaces wholesale. This makes them fundamentally incompatible.</details> |
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|||||||
121
build.gradle
121
build.gradle
@@ -1,40 +1,53 @@
|
|||||||
import me.modmuss50.mpp.ReleaseType
|
import me.modmuss50.mpp.ReleaseType
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("xyz.jpenilla.quiet-architectury-loom")
|
id("java-library")
|
||||||
id("me.modmuss50.mod-publish-plugin") version "0.7.2" apply false
|
id("net.neoforged.moddev")
|
||||||
|
id("me.modmuss50.mod-publish-plugin") version "0.8.4" apply false
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
extensions.create("runConfigCommon", RunConfigCommon.class)
|
||||||
* Gets the version name from the latest Git tag
|
|
||||||
*/
|
def getGitCommit = providers.exec {
|
||||||
// https://stackoverflow.com/questions/28498688/gradle-script-to-autoversion-and-include-the-commit-hash-in-android
|
commandLine 'git', 'rev-parse', '--short', 'HEAD'
|
||||||
def getGitCommit = { ->
|
}.standardOutput.getAsText().map { it.trim() }
|
||||||
def stdout = new ByteArrayOutputStream()
|
|
||||||
exec {
|
def aw2at = Aw2AtTask.configureDefault(
|
||||||
commandLine 'git', 'rev-parse', '--short', 'HEAD'
|
getProject(),
|
||||||
standardOutput = stdout
|
layout.projectDirectory.file("src/main/resources/moonrise.accesswidener").getAsFile(),
|
||||||
}
|
sourceSets.main
|
||||||
return stdout.toString().trim()
|
)
|
||||||
|
|
||||||
|
neoForge {
|
||||||
|
neoFormVersion = neoform_version
|
||||||
|
validateAccessTransformers = true
|
||||||
|
accessTransformers.files.setFrom(aw2at.flatMap { t -> t.getOutputFile() })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
runConfigCommon {
|
||||||
|
systemProperties.put "mixin.debug", "true"
|
||||||
|
systemProperties.put "Moonrise.MaxViewDistance", "128"
|
||||||
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
|
compileOnly "net.fabricmc:sponge-mixin:0.15.4+mixin.0.8.7"
|
||||||
|
compileOnly "io.github.llamalad7:mixinextras-common:0.4.1"
|
||||||
|
// work around minecraft (MDG) forcing ASM 9.3 which is incompatible with the above deps...
|
||||||
|
components.withModule("net.neoforged:minecraft-dependencies", RemoveAsmConstraint.class)
|
||||||
|
|
||||||
api("ca.spottedleaf:concurrentutil:${rootProject.concurrentutil_version}")
|
api("ca.spottedleaf:concurrentutil:${rootProject.concurrentutil_version}") { setTransitive(false) }
|
||||||
|
api("ca.spottedleaf:yamlconfig:${rootProject.yamlconfig_version}") { setTransitive(false) }
|
||||||
api("org.yaml:snakeyaml:${rootProject.snakeyaml_version}")
|
api("org.yaml:snakeyaml:${rootProject.snakeyaml_version}")
|
||||||
|
|
||||||
modImplementation "me.shedaniel.cloth:cloth-config:${rootProject.cloth_version}"
|
// todo: does cloth publish a platform-agnostic jar in mojang mappings?
|
||||||
|
compileOnly "me.shedaniel.cloth:cloth-config-neoforge:${rootProject.cloth_version}"
|
||||||
}
|
}
|
||||||
|
|
||||||
File awFile = file("src/main/resources/moonrise.accesswidener")
|
|
||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
group = rootProject.maven_group
|
group = rootProject.maven_group
|
||||||
version = rootProject.mod_version + "+" + getGitCommit()
|
version = rootProject.mod_version + "+" + getGitCommit.get()
|
||||||
|
|
||||||
plugins.apply("xyz.jpenilla.quiet-architectury-loom")
|
plugins.apply("java-library")
|
||||||
|
|
||||||
java {
|
java {
|
||||||
withSourcesJar()
|
withSourcesJar()
|
||||||
@@ -44,10 +57,20 @@ allprojects {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
testImplementation "org.junit.jupiter:junit-jupiter:${rootProject.junit_version}"
|
||||||
|
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.test {
|
||||||
|
useJUnitPlatform()
|
||||||
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenLocal {
|
maven {
|
||||||
|
url "https://repo.papermc.io/repository/maven-public/"
|
||||||
mavenContent {
|
mavenContent {
|
||||||
includeModule("ca.spottedleaf", "concurrentutil")
|
includeGroup("ca.spottedleaf")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
maven {
|
maven {
|
||||||
@@ -60,11 +83,6 @@ allprojects {
|
|||||||
maven { url "https://maven.terraformersmc.com/releases/" }
|
maven { url "https://maven.terraformersmc.com/releases/" }
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
|
||||||
minecraft "com.mojang:minecraft:${project.minecraft_version}"
|
|
||||||
mappings loom.officialMojangMappings()
|
|
||||||
}
|
|
||||||
|
|
||||||
// make build reproducible
|
// make build reproducible
|
||||||
tasks.withType(AbstractArchiveTask).configureEach {
|
tasks.withType(AbstractArchiveTask).configureEach {
|
||||||
preserveFileTimestamps = false
|
preserveFileTimestamps = false
|
||||||
@@ -80,32 +98,22 @@ allprojects {
|
|||||||
rename { "${it}_${rootProject.base.archivesName.get()}"}
|
rename { "${it}_${rootProject.base.archivesName.get()}"}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
loom {
|
|
||||||
accessWidenerPath = awFile
|
|
||||||
mixin {
|
|
||||||
useLegacyMixinAp = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
subprojects {
|
subprojects {
|
||||||
loom.mods {
|
|
||||||
main {
|
|
||||||
sourceSet("main")
|
|
||||||
sourceSet("main", project.rootProject)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
loom.runs.all {
|
|
||||||
ideConfigGenerated true
|
|
||||||
property "mixin.debug", "true"
|
|
||||||
property "Moonrise.MaxViewDistance", "128"
|
|
||||||
}
|
|
||||||
|
|
||||||
plugins.apply("me.modmuss50.mod-publish-plugin")
|
plugins.apply("me.modmuss50.mod-publish-plugin")
|
||||||
|
plugins.apply 'java-library'
|
||||||
|
plugins.apply 'com.gradleup.shadow'
|
||||||
|
|
||||||
|
configurations.create("libs")
|
||||||
|
configurations.shadow {
|
||||||
|
extendsFrom(configurations.libs)
|
||||||
|
}
|
||||||
|
configurations.implementation {
|
||||||
|
extendsFrom(configurations.libs)
|
||||||
|
}
|
||||||
|
|
||||||
publishMods {
|
publishMods {
|
||||||
file = remapJar.archiveFile
|
|
||||||
if (project.version.contains("-beta.")) {
|
if (project.version.contains("-beta.")) {
|
||||||
type = ReleaseType.BETA
|
type = ReleaseType.BETA
|
||||||
} else {
|
} else {
|
||||||
@@ -129,20 +137,7 @@ subprojects {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Setup a run with lithium for compatibility testing
|
// Setup a run with lithium for compatibility testing
|
||||||
sourceSets.create("lithium")
|
|
||||||
configurations.create("lithium")
|
configurations.create("lithium")
|
||||||
loom {
|
|
||||||
createRemapConfigurations(sourceSets.lithium)
|
|
||||||
runs {
|
|
||||||
register("lithiumClient") {
|
|
||||||
client()
|
|
||||||
property "mixin.debug", "true"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tasks.named("runLithiumClient", net.fabricmc.loom.task.RunGameTask.class) {
|
|
||||||
getClasspath().from(configurations.modRuntimeClasspathLithiumMapped)
|
|
||||||
}
|
|
||||||
dependencies {
|
dependencies {
|
||||||
String coordinates = "maven.modrinth:lithium:"
|
String coordinates = "maven.modrinth:lithium:"
|
||||||
if (getProject().name == "Moonrise-NeoForge") {
|
if (getProject().name == "Moonrise-NeoForge") {
|
||||||
@@ -150,10 +145,6 @@ subprojects {
|
|||||||
} else {
|
} else {
|
||||||
coordinates += rootProject.fabric_lithium_version
|
coordinates += rootProject.fabric_lithium_version
|
||||||
}
|
}
|
||||||
modLithiumRuntimeOnly coordinates
|
lithium coordinates
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
loom.runs.all {
|
|
||||||
ideConfigGenerated false
|
|
||||||
}
|
|
||||||
|
|||||||
11
buildSrc/build.gradle.kts
Normal file
11
buildSrc/build.gradle.kts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
repositories {
|
||||||
|
gradlePluginPortal()
|
||||||
|
mavenCentral()
|
||||||
|
maven("https://maven.fabricmc.net/")
|
||||||
|
maven("https://maven.architectury.dev/")
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation("net.fabricmc:access-widener:2.1.0")
|
||||||
|
implementation("dev.architectury:at:1.0.1")
|
||||||
|
}
|
||||||
130
buildSrc/src/main/java/Aw2AtTask.java
Normal file
130
buildSrc/src/main/java/Aw2AtTask.java
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
import dev.architectury.at.AccessChange;
|
||||||
|
import dev.architectury.at.AccessTransform;
|
||||||
|
import dev.architectury.at.AccessTransformSet;
|
||||||
|
import dev.architectury.at.ModifierChange;
|
||||||
|
import dev.architectury.at.io.AccessTransformFormats;
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import net.fabricmc.accesswidener.AccessWidenerReader;
|
||||||
|
import net.fabricmc.accesswidener.AccessWidenerVisitor;
|
||||||
|
import org.cadixdev.bombe.type.signature.MethodSignature;
|
||||||
|
import org.gradle.api.DefaultTask;
|
||||||
|
import org.gradle.api.Project;
|
||||||
|
import org.gradle.api.file.ProjectLayout;
|
||||||
|
import org.gradle.api.file.RegularFileProperty;
|
||||||
|
import org.gradle.api.tasks.CacheableTask;
|
||||||
|
import org.gradle.api.tasks.InputFile;
|
||||||
|
import org.gradle.api.tasks.OutputFile;
|
||||||
|
import org.gradle.api.tasks.PathSensitive;
|
||||||
|
import org.gradle.api.tasks.PathSensitivity;
|
||||||
|
import org.gradle.api.tasks.SourceSet;
|
||||||
|
import org.gradle.api.tasks.TaskAction;
|
||||||
|
import org.gradle.api.tasks.TaskProvider;
|
||||||
|
|
||||||
|
@CacheableTask
|
||||||
|
public abstract class Aw2AtTask extends DefaultTask {
|
||||||
|
|
||||||
|
@InputFile
|
||||||
|
@PathSensitive(PathSensitivity.NONE)
|
||||||
|
public abstract RegularFileProperty getInputFile();
|
||||||
|
|
||||||
|
@OutputFile
|
||||||
|
public abstract RegularFileProperty getOutputFile();
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public abstract ProjectLayout getLayout();
|
||||||
|
|
||||||
|
public static TaskProvider<Aw2AtTask> configureDefault(
|
||||||
|
final Project project,
|
||||||
|
final File awFile,
|
||||||
|
final SourceSet sourceSet
|
||||||
|
) {
|
||||||
|
final TaskProvider<Aw2AtTask> aw2at = project.getTasks().register("aw2at", Aw2AtTask.class, task -> {
|
||||||
|
task.getOutputFile().set(project.getLayout().getBuildDirectory().file("aw2at/files/accesstransformer.cfg"));
|
||||||
|
task.getInputFile().set(awFile);
|
||||||
|
});
|
||||||
|
|
||||||
|
final TaskProvider<CopyTask> copyTask = project.getTasks().register("copyAt", CopyTask.class, copy -> {
|
||||||
|
copy.getInputFile().set(aw2at.flatMap(Aw2AtTask::getOutputFile));
|
||||||
|
copy.getOutputDirectory().set(project.getLayout().getBuildDirectory().dir("aw2at/dir"));
|
||||||
|
copy.getDestination().set("META-INF/accesstransformer.cfg");
|
||||||
|
});
|
||||||
|
|
||||||
|
sourceSet.resources(resources -> {
|
||||||
|
resources.srcDir(copyTask.flatMap(CopyTask::getOutputDirectory));
|
||||||
|
});
|
||||||
|
|
||||||
|
return aw2at;
|
||||||
|
}
|
||||||
|
|
||||||
|
@TaskAction
|
||||||
|
public void run() {
|
||||||
|
try (final BufferedReader reader = Files.newBufferedReader(this.getInputFile().get().getAsFile().toPath())) {
|
||||||
|
final AccessTransformSet accessTransformSet = toAccessTransformSet(reader);
|
||||||
|
Files.deleteIfExists(this.getOutputFile().get().getAsFile().toPath());
|
||||||
|
Files.createDirectories(this.getOutputFile().get().getAsFile().toPath().getParent());
|
||||||
|
AccessTransformFormats.FML.write(this.getOutputFile().get().getAsFile().toPath(), accessTransformSet);
|
||||||
|
} catch (final IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Below methods are heavily based on architectury-loom Aw2At class (MIT licensed)
|
||||||
|
/*
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2016 FabricMC
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public static AccessTransformSet toAccessTransformSet(final BufferedReader reader) throws IOException {
|
||||||
|
// TODO: Remove copied classes once https://github.com/architectury/at/pull/1 is released
|
||||||
|
AccessTransformSet atSet = new at.AccessTransformSetImpl();
|
||||||
|
|
||||||
|
new AccessWidenerReader(new AccessWidenerVisitor() {
|
||||||
|
@Override
|
||||||
|
public void visitClass(final String name, final AccessWidenerReader.AccessType access, final boolean transitive) {
|
||||||
|
atSet.getOrCreateClass(name).merge(toAt(access));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitMethod(final String owner, final String name, final String descriptor, final AccessWidenerReader.AccessType access, final boolean transitive) {
|
||||||
|
atSet.getOrCreateClass(owner).mergeMethod(MethodSignature.of(name, descriptor), toAt(access));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitField(final String owner, final String name, final String descriptor, final AccessWidenerReader.AccessType access, final boolean transitive) {
|
||||||
|
atSet.getOrCreateClass(owner).mergeField(name, toAt(access));
|
||||||
|
}
|
||||||
|
}).read(reader);
|
||||||
|
|
||||||
|
return atSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AccessTransform toAt(final AccessWidenerReader.AccessType access) {
|
||||||
|
return switch (access) {
|
||||||
|
case ACCESSIBLE -> AccessTransform.of(AccessChange.PUBLIC);
|
||||||
|
case EXTENDABLE, MUTABLE -> AccessTransform.of(AccessChange.PUBLIC, ModifierChange.REMOVE);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
44
buildSrc/src/main/java/CopyTask.java
Normal file
44
buildSrc/src/main/java/CopyTask.java
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
import org.gradle.api.DefaultTask;
|
||||||
|
import org.gradle.api.file.DirectoryProperty;
|
||||||
|
import org.gradle.api.file.RegularFileProperty;
|
||||||
|
import org.gradle.api.provider.Property;
|
||||||
|
import org.gradle.api.tasks.Input;
|
||||||
|
import org.gradle.api.tasks.InputFile;
|
||||||
|
import org.gradle.api.tasks.OutputDirectory;
|
||||||
|
import org.gradle.api.tasks.TaskAction;
|
||||||
|
|
||||||
|
public abstract class CopyTask extends DefaultTask {
|
||||||
|
|
||||||
|
@InputFile
|
||||||
|
public abstract RegularFileProperty getInputFile();
|
||||||
|
|
||||||
|
@Input
|
||||||
|
public abstract Property<String> getDestination();
|
||||||
|
|
||||||
|
@OutputDirectory
|
||||||
|
public abstract DirectoryProperty getOutputDirectory();
|
||||||
|
|
||||||
|
@TaskAction
|
||||||
|
public void run() {
|
||||||
|
final Path outputDirPath = this.getOutputDirectory().get().getAsFile().toPath();
|
||||||
|
try {
|
||||||
|
try (final Stream<Path> walk = Files.walk(outputDirPath)) {
|
||||||
|
for (final Path path : walk.sorted(Comparator.reverseOrder()).toList()) {
|
||||||
|
Files.delete(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final Path destFile = outputDirPath.resolve(this.getDestination().get());
|
||||||
|
Files.createDirectories(destFile.getParent());
|
||||||
|
|
||||||
|
Files.copy(this.getInputFile().get().getAsFile().toPath(), destFile);
|
||||||
|
} catch (final IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
24
buildSrc/src/main/java/RemoveAsmConstraint.java
Normal file
24
buildSrc/src/main/java/RemoveAsmConstraint.java
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
import java.util.Objects;
|
||||||
|
import org.gradle.api.artifacts.CacheableRule;
|
||||||
|
import org.gradle.api.artifacts.ComponentMetadataContext;
|
||||||
|
import org.gradle.api.artifacts.ComponentMetadataRule;
|
||||||
|
|
||||||
|
@CacheableRule
|
||||||
|
public abstract class RemoveAsmConstraint implements ComponentMetadataRule {
|
||||||
|
@Override
|
||||||
|
public void execute(final ComponentMetadataContext ctx) {
|
||||||
|
ctx.getDetails().allVariants(variants -> {
|
||||||
|
variants.withDependencies(deps -> {
|
||||||
|
deps.forEach(dep -> {
|
||||||
|
if (Objects.equals(dep.getGroup(), "org.ow2.asm")) {
|
||||||
|
if (dep.getVersionConstraint().getStrictVersion() != null) {
|
||||||
|
dep.version(v -> {
|
||||||
|
v.require(v.getStrictVersion());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
5
buildSrc/src/main/java/RunConfigCommon.java
Normal file
5
buildSrc/src/main/java/RunConfigCommon.java
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import org.gradle.api.provider.MapProperty;
|
||||||
|
|
||||||
|
public abstract class RunConfigCommon {
|
||||||
|
public abstract MapProperty<String, String> getSystemProperties();
|
||||||
|
}
|
||||||
97
buildSrc/src/main/java/at/AccessTransformSetImpl.java
Normal file
97
buildSrc/src/main/java/at/AccessTransformSetImpl.java
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
/*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2023 Architectury
|
||||||
|
* Copyright (c) 2018 Minecrell (https://github.com/Minecrell)
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package at;
|
||||||
|
|
||||||
|
import dev.architectury.at.AccessTransformSet;
|
||||||
|
import net.fabricmc.mappingio.tree.MappingTreeView;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public class AccessTransformSetImpl implements AccessTransformSet {
|
||||||
|
|
||||||
|
private final Map<String, Class> classes = new LinkedHashMap<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, Class> getClasses() {
|
||||||
|
return Collections.unmodifiableMap(this.classes);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<Class> getClass(String name) {
|
||||||
|
Objects.requireNonNull(name, "name");
|
||||||
|
return Optional.ofNullable(this.classes.get(name.replace('.', '/')));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class getOrCreateClass(String name) {
|
||||||
|
Objects.requireNonNull(name, "name");
|
||||||
|
return this.classes.computeIfAbsent(name.replace('.', '/'), n -> new ClassAccessTransformSetImpl(this, n));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<Class> removeClass(String name) {
|
||||||
|
Objects.requireNonNull(name, "name");
|
||||||
|
return Optional.ofNullable(this.classes.remove(name.replace('.', '/')));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AccessTransformSet remap(MappingTreeView mappings, String from, String to) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void merge(AccessTransformSet other) {
|
||||||
|
other.getClasses().forEach((name, classSet) -> getOrCreateClass(name).merge(classSet));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!(o instanceof AccessTransformSetImpl)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
AccessTransformSetImpl that = (AccessTransformSetImpl) o;
|
||||||
|
return this.classes.equals(that.classes);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return this.classes.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "AccessTransformSet{" + classes + '}';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
256
buildSrc/src/main/java/at/ClassAccessTransformSetImpl.java
Normal file
256
buildSrc/src/main/java/at/ClassAccessTransformSetImpl.java
Normal file
@@ -0,0 +1,256 @@
|
|||||||
|
/*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2023 Architectury
|
||||||
|
* Copyright (c) 2018 Minecrell (https://github.com/Minecrell)
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package at;
|
||||||
|
|
||||||
|
import dev.architectury.at.AccessTransform;
|
||||||
|
import dev.architectury.at.AccessTransformSet;
|
||||||
|
import org.cadixdev.bombe.analysis.InheritanceProvider;
|
||||||
|
import org.cadixdev.bombe.type.signature.MethodSignature;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.StringJoiner;
|
||||||
|
|
||||||
|
class ClassAccessTransformSetImpl implements AccessTransformSet.Class {
|
||||||
|
|
||||||
|
private final AccessTransformSet parent;
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
private AccessTransform classTransform = AccessTransform.EMPTY;
|
||||||
|
private AccessTransform allFields = AccessTransform.EMPTY;
|
||||||
|
private AccessTransform allMethods = AccessTransform.EMPTY;
|
||||||
|
|
||||||
|
private final Map<String, AccessTransform> fields = new LinkedHashMap<>();
|
||||||
|
private final Map<MethodSignature, AccessTransform> methods = new LinkedHashMap<>();
|
||||||
|
|
||||||
|
private boolean complete;
|
||||||
|
|
||||||
|
ClassAccessTransformSetImpl(AccessTransformSet parent, String name) {
|
||||||
|
this.parent = parent;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AccessTransformSet getParent() {
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AccessTransform get() {
|
||||||
|
return this.classTransform;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AccessTransform merge(AccessTransform transform) {
|
||||||
|
return this.classTransform = this.classTransform.merge(transform);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AccessTransform replace(AccessTransform transform) {
|
||||||
|
return this.classTransform = Objects.requireNonNull(transform, "transform");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AccessTransform allFields() {
|
||||||
|
return this.allFields;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AccessTransform mergeAllFields(AccessTransform transform) {
|
||||||
|
return this.allFields = this.allFields.merge(transform);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AccessTransform replaceAllFields(AccessTransform transform) {
|
||||||
|
return this.allFields = Objects.requireNonNull(transform, "transform");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AccessTransform allMethods() {
|
||||||
|
return this.allMethods;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AccessTransform mergeAllMethods(AccessTransform transform) {
|
||||||
|
return this.allMethods = this.allMethods.merge(transform);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AccessTransform replaceAllMethods(AccessTransform transform) {
|
||||||
|
return this.allMethods = Objects.requireNonNull(transform, "transform");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, AccessTransform> getFields() {
|
||||||
|
return Collections.unmodifiableMap(this.fields);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AccessTransform getField(String name) {
|
||||||
|
return this.fields.getOrDefault(Objects.requireNonNull(name, "name"), this.allFields);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AccessTransform mergeField(String name, AccessTransform transform) {
|
||||||
|
Objects.requireNonNull(name, "name");
|
||||||
|
Objects.requireNonNull(transform, "transform");
|
||||||
|
|
||||||
|
if (transform.isEmpty()) {
|
||||||
|
return this.fields.getOrDefault(name, AccessTransform.EMPTY);
|
||||||
|
}
|
||||||
|
return this.fields.merge(name, transform, AccessTransform::merge);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AccessTransform replaceField(String name, AccessTransform transform) {
|
||||||
|
Objects.requireNonNull(name, "name");
|
||||||
|
Objects.requireNonNull(transform, "transform");
|
||||||
|
|
||||||
|
if (transform.isEmpty()) {
|
||||||
|
return this.fields.remove(name);
|
||||||
|
}
|
||||||
|
return this.fields.put(name, transform);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<MethodSignature, AccessTransform> getMethods() {
|
||||||
|
return Collections.unmodifiableMap(this.methods);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AccessTransform getMethod(MethodSignature signature) {
|
||||||
|
return this.methods.getOrDefault(Objects.requireNonNull(signature, "signature"), this.allMethods);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AccessTransform mergeMethod(MethodSignature signature, AccessTransform transform) {
|
||||||
|
Objects.requireNonNull(signature, "signature");
|
||||||
|
Objects.requireNonNull(transform, "transform");
|
||||||
|
|
||||||
|
if (transform.isEmpty()) {
|
||||||
|
return this.methods.getOrDefault(signature, AccessTransform.EMPTY);
|
||||||
|
}
|
||||||
|
return this.methods.merge(signature, transform, AccessTransform::merge);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AccessTransform replaceMethod(MethodSignature signature, AccessTransform transform) {
|
||||||
|
Objects.requireNonNull(signature, "signature");
|
||||||
|
Objects.requireNonNull(transform, "transform");
|
||||||
|
|
||||||
|
if (transform.isEmpty()) {
|
||||||
|
return this.methods.remove(signature);
|
||||||
|
}
|
||||||
|
return this.methods.put(signature, transform);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void merge(AccessTransformSet.Class other) {
|
||||||
|
Objects.requireNonNull(other, "other");
|
||||||
|
|
||||||
|
merge(other.get());
|
||||||
|
mergeAllFields(other.allFields());
|
||||||
|
mergeAllMethods(other.allMethods());
|
||||||
|
|
||||||
|
other.getFields().forEach(this::mergeField);
|
||||||
|
other.getMethods().forEach(this::mergeMethod);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isComplete() {
|
||||||
|
return this.complete;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void complete(InheritanceProvider provider, InheritanceProvider.ClassInfo info) {
|
||||||
|
if (this.complete) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (InheritanceProvider.ClassInfo parent : info.provideParents(provider)) {
|
||||||
|
AccessTransformSet.Class parentAts = getParent().getOrCreateClass(parent.getName());
|
||||||
|
parentAts.complete(provider, parent);
|
||||||
|
|
||||||
|
parentAts.getMethods().forEach((signature, transform) -> {
|
||||||
|
if (info.overrides(signature, parent)) {
|
||||||
|
mergeMethod(signature, transform);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.complete = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!(o instanceof ClassAccessTransformSetImpl)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassAccessTransformSetImpl that = (ClassAccessTransformSetImpl) o;
|
||||||
|
return this.classTransform.equals(that.classTransform) &&
|
||||||
|
this.allFields.equals(that.allFields) &&
|
||||||
|
this.allMethods.equals(that.allMethods) &&
|
||||||
|
this.fields.equals(that.fields) &&
|
||||||
|
this.methods.equals(that.methods);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(this.classTransform, this.allFields, this.allMethods, this.fields, this.methods);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringJoiner joiner = new StringJoiner(", ", "AccessTransformSet.Class{", "}");
|
||||||
|
if (!this.classTransform.isEmpty()) {
|
||||||
|
joiner.add(this.classTransform.toString());
|
||||||
|
}
|
||||||
|
if (!this.allFields.isEmpty()) {
|
||||||
|
joiner.add("allFields=" + this.allFields);
|
||||||
|
}
|
||||||
|
if (!this.allMethods.isEmpty()) {
|
||||||
|
joiner.add("allMethods=" + this.allMethods);
|
||||||
|
}
|
||||||
|
if (!this.fields.isEmpty()) {
|
||||||
|
joiner.add("fields=" + this.fields);
|
||||||
|
}
|
||||||
|
if (!this.methods.isEmpty()) {
|
||||||
|
joiner.add("method=" + this.methods);
|
||||||
|
}
|
||||||
|
return joiner.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,51 +1,60 @@
|
|||||||
plugins {
|
import java.util.stream.Collectors
|
||||||
id("xyz.jpenilla.quiet-architectury-loom")
|
import net.fabricmc.loom.util.gradle.SourceSetHelper
|
||||||
id 'maven-publish'
|
|
||||||
id 'com.gradleup.shadow'
|
|
||||||
}
|
|
||||||
|
|
||||||
configurations.create("libs")
|
plugins {
|
||||||
configurations.shadow {
|
id("quiet-fabric-loom")
|
||||||
extendsFrom(configurations.libs)
|
id 'maven-publish'
|
||||||
}
|
|
||||||
configurations.implementation {
|
|
||||||
extendsFrom(configurations.libs)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
add('shadow', project([path: ":", configuration: "namedElements"]))
|
minecraft "com.mojang:minecraft:${project.minecraft_version}"
|
||||||
runtimeOnly(project(":").sourceSets.main.output)
|
mappings loom.officialMojangMappings()
|
||||||
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
|
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
|
||||||
|
testImplementation "net.fabricmc:fabric-loader-junit:${project.loader_version}"
|
||||||
|
|
||||||
libs("ca.spottedleaf:concurrentutil:${rootProject.concurrentutil_version}")
|
runtimeOnly(project(":").sourceSets.main.output)
|
||||||
|
shadow(project(":"))
|
||||||
|
compileOnly(project(":"))
|
||||||
|
|
||||||
|
libs("ca.spottedleaf:concurrentutil:${rootProject.concurrentutil_version}") { setTransitive(false) }
|
||||||
|
libs("ca.spottedleaf:yamlconfig:${rootProject.yamlconfig_version}") { setTransitive(false) }
|
||||||
libs("org.yaml:snakeyaml:${rootProject.snakeyaml_version}")
|
libs("org.yaml:snakeyaml:${rootProject.snakeyaml_version}")
|
||||||
|
|
||||||
modImplementation "me.shedaniel.cloth:cloth-config-fabric:${rootProject.cloth_version}"
|
modImplementation "me.shedaniel.cloth:cloth-config-fabric:${rootProject.cloth_version}"
|
||||||
include "me.shedaniel.cloth:cloth-config-fabric:${rootProject.cloth_version}"
|
include "me.shedaniel.cloth:cloth-config-fabric:${rootProject.cloth_version}"
|
||||||
modImplementation "com.terraformersmc:modmenu:${rootProject.modmenu_version}"
|
modImplementation "com.terraformersmc:modmenu:${rootProject.modmenu_version}"
|
||||||
|
|
||||||
modImplementation fabricApiLibs.fabric.api
|
modImplementation platform(fabricApiLibs.bom)
|
||||||
|
modImplementation fabricApiLibs.command.api.v2
|
||||||
|
modImplementation fabricApiLibs.lifecycle.events.v1
|
||||||
include fabricApiLibs.command.api.v2
|
include fabricApiLibs.command.api.v2
|
||||||
include fabricApiLibs.base
|
include fabricApiLibs.base
|
||||||
}
|
}
|
||||||
|
|
||||||
processResources {
|
tasks.processResources {
|
||||||
inputs.property "version", project.version
|
def properties = [
|
||||||
|
"version": project.version,
|
||||||
|
"minecraft_version": minecraft_version,
|
||||||
|
"loader_version": loader_version,
|
||||||
|
"mod_version": mod_version
|
||||||
|
]
|
||||||
|
inputs.properties(properties)
|
||||||
filesMatching("fabric.mod.json") {
|
filesMatching("fabric.mod.json") {
|
||||||
expand "version": project.version, "minecraft_version": minecraft_version, "loader_version": loader_version, "mod_version": mod_version
|
expand properties
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
shadowJar {
|
tasks.shadowJar {
|
||||||
archiveClassifier = "dev-all"
|
archiveClassifier = "dev-all"
|
||||||
destinationDirectory = layout.buildDirectory.dir("libs")
|
destinationDirectory = layout.buildDirectory.dir("libs")
|
||||||
configurations = [project.configurations.shadow]
|
configurations = [project.configurations.shadow]
|
||||||
relocate 'ca.spottedleaf.concurrentutil', 'ca.spottedleaf.moonrise.libs.ca.spottedleaf.concurrentutil'
|
relocate 'ca.spottedleaf.concurrentutil', 'ca.spottedleaf.moonrise.libs.ca.spottedleaf.concurrentutil'
|
||||||
|
relocate 'ca.spottedleaf.yamlconfig', 'ca.spottedleaf.moonrise.libs.ca.spottedleaf.yamlconfig'
|
||||||
relocate 'org.yaml.snakeyaml', 'ca.spottedleaf.moonrise.libs.org.yaml.snakeyaml'
|
relocate 'org.yaml.snakeyaml', 'ca.spottedleaf.moonrise.libs.org.yaml.snakeyaml'
|
||||||
}
|
}
|
||||||
|
|
||||||
publishMods {
|
publishMods {
|
||||||
|
file = remapJar.archiveFile
|
||||||
modLoaders = ["fabric"]
|
modLoaders = ["fabric"]
|
||||||
|
|
||||||
modrinth {
|
modrinth {
|
||||||
@@ -59,7 +68,56 @@ publishMods {
|
|||||||
incompatible(
|
incompatible(
|
||||||
"not-enough-crashes",
|
"not-enough-crashes",
|
||||||
"starlight",
|
"starlight",
|
||||||
"c2me-fabric"
|
"c2me"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
loom {
|
||||||
|
accessWidenerPath.set(getRootProject().file("src/main/resources/moonrise.accesswidener"))
|
||||||
|
mixin {
|
||||||
|
useLegacyMixinAp = false
|
||||||
|
}
|
||||||
|
runs.configureEach {
|
||||||
|
ideConfigGenerated true
|
||||||
|
}
|
||||||
|
mods {
|
||||||
|
main {
|
||||||
|
sourceSet("main")
|
||||||
|
sourceSet("main", project.rootProject)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.test {
|
||||||
|
def classPathGroups = SourceSetHelper.getClasspath(loom.mods.main, getProject()).stream()
|
||||||
|
.map(File.&getAbsolutePath)
|
||||||
|
.collect(Collectors.joining(File.pathSeparator))
|
||||||
|
|
||||||
|
systemProperty("fabric.classPathGroups", classPathGroups)
|
||||||
|
}
|
||||||
|
|
||||||
|
afterEvaluate {
|
||||||
|
loom.runs.configureEach { cfg ->
|
||||||
|
runConfigCommon.systemProperties.get().each {
|
||||||
|
cfg.property it.key, it.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup a run with lithium for compatibility testing
|
||||||
|
sourceSets.create("lithium")
|
||||||
|
loom {
|
||||||
|
createRemapConfigurations(sourceSets.lithium)
|
||||||
|
runs {
|
||||||
|
register("lithiumClient") {
|
||||||
|
client()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
configurations.modLithiumRuntimeOnly {
|
||||||
|
extendsFrom configurations.lithium
|
||||||
|
}
|
||||||
|
tasks.named("runLithiumClient", net.fabricmc.loom.task.RunGameTask.class) {
|
||||||
|
getClasspath().from(configurations.modRuntimeClasspathLithiumMapped)
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,32 +1,41 @@
|
|||||||
package ca.spottedleaf.moonrise.fabric;
|
package ca.spottedleaf.moonrise.fabric;
|
||||||
|
|
||||||
|
import ca.spottedleaf.moonrise.common.util.BaseChunkSystemHooks;
|
||||||
import ca.spottedleaf.moonrise.common.PlatformHooks;
|
import ca.spottedleaf.moonrise.common.PlatformHooks;
|
||||||
import ca.spottedleaf.moonrise.common.util.ConfigHolder;
|
import ca.spottedleaf.moonrise.common.util.ConfigHolder;
|
||||||
import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.NewChunkHolder;
|
import com.mojang.datafixers.DSL;
|
||||||
import com.mojang.datafixers.DataFixer;
|
import com.mojang.datafixers.DataFixer;
|
||||||
|
import com.mojang.serialization.Dynamic;
|
||||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerChunkEvents;
|
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerChunkEvents;
|
||||||
|
import net.fabricmc.loader.api.FabricLoader;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
import net.minecraft.nbt.NbtOps;
|
||||||
|
import net.minecraft.server.level.ChunkHolder;
|
||||||
import net.minecraft.server.level.GenerationChunkHolder;
|
import net.minecraft.server.level.GenerationChunkHolder;
|
||||||
import net.minecraft.server.level.ServerLevel;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import net.minecraft.server.level.ServerPlayer;
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
import net.minecraft.util.datafix.DataFixTypes;
|
|
||||||
import net.minecraft.world.entity.Entity;
|
import net.minecraft.world.entity.Entity;
|
||||||
|
import net.minecraft.world.entity.boss.EnderDragonPart;
|
||||||
import net.minecraft.world.level.BlockGetter;
|
import net.minecraft.world.level.BlockGetter;
|
||||||
import net.minecraft.world.level.ChunkPos;
|
import net.minecraft.world.level.ChunkPos;
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||||
|
import net.minecraft.world.level.chunk.ImposterProtoChunk;
|
||||||
import net.minecraft.world.level.chunk.LevelChunk;
|
import net.minecraft.world.level.chunk.LevelChunk;
|
||||||
import net.minecraft.world.level.chunk.ProtoChunk;
|
import net.minecraft.world.level.chunk.ProtoChunk;
|
||||||
import net.minecraft.world.level.chunk.status.ChunkStatusTasks;
|
import net.minecraft.world.level.chunk.status.ChunkStatusTasks;
|
||||||
import net.minecraft.world.level.chunk.storage.SerializableChunkData;
|
import net.minecraft.world.level.chunk.storage.SerializableChunkData;
|
||||||
import net.minecraft.world.level.entity.EntityTypeTest;
|
import net.minecraft.world.level.entity.EntityTypeTest;
|
||||||
import net.minecraft.world.phys.AABB;
|
import net.minecraft.world.phys.AABB;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
public final class FabricHooks implements PlatformHooks {
|
public final class FabricHooks extends BaseChunkSystemHooks implements PlatformHooks {
|
||||||
|
|
||||||
|
private static final boolean HAS_FABRIC_LIFECYCLE_EVENTS = FabricLoader.getInstance().isModLoaded("fabric-lifecycle-events-v1");
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getBrand() {
|
public String getBrand() {
|
||||||
@@ -62,7 +71,12 @@ public final class FabricHooks implements PlatformHooks {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void chunkFullStatusComplete(final LevelChunk newChunk, final ProtoChunk original) {
|
public void chunkFullStatusComplete(final LevelChunk newChunk, final ProtoChunk original) {
|
||||||
ServerChunkEvents.CHUNK_LOAD.invoker().onChunkLoad((ServerLevel)newChunk.getLevel(), newChunk);
|
if (HAS_FABRIC_LIFECYCLE_EVENTS) {
|
||||||
|
ServerChunkEvents.CHUNK_LOAD.invoker().onChunkLoad((ServerLevel)newChunk.getLevel(), newChunk);
|
||||||
|
if (!(original instanceof ImposterProtoChunk)) {
|
||||||
|
ServerChunkEvents.CHUNK_GENERATE.invoker().onChunkGenerate((ServerLevel)newChunk.getLevel(), newChunk);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -71,13 +85,15 @@ public final class FabricHooks implements PlatformHooks {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onChunkHolderTicketChange(final ServerLevel world, final NewChunkHolder holder, final int oldLevel, final int newLevel) {
|
public void onChunkHolderTicketChange(final ServerLevel world, final ChunkHolder holder, final int oldLevel, final int newLevel) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void chunkUnloadFromWorld(final LevelChunk chunk) {
|
public void chunkUnloadFromWorld(final LevelChunk chunk) {
|
||||||
ServerChunkEvents.CHUNK_UNLOAD.invoker().onChunkUnload((ServerLevel)chunk.getLevel(), chunk);
|
if (HAS_FABRIC_LIFECYCLE_EVENTS) {
|
||||||
|
ServerChunkEvents.CHUNK_UNLOAD.invoker().onChunkUnload((ServerLevel)chunk.getLevel(), chunk);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -98,13 +114,43 @@ public final class FabricHooks implements PlatformHooks {
|
|||||||
@Override
|
@Override
|
||||||
public void addToGetEntities(final Level world, final Entity entity, final AABB boundingBox, final Predicate<? super Entity> predicate,
|
public void addToGetEntities(final Level world, final Entity entity, final AABB boundingBox, final Predicate<? super Entity> predicate,
|
||||||
final List<Entity> into) {
|
final List<Entity> into) {
|
||||||
|
final Collection<EnderDragonPart> parts = world.dragonParts();
|
||||||
|
if (parts.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (final EnderDragonPart part : parts) {
|
||||||
|
if (part != entity && part.getBoundingBox().intersects(boundingBox) && (predicate == null || predicate.test(part))) {
|
||||||
|
into.add(part);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T extends Entity> void addToGetEntities(final Level world, final EntityTypeTest<Entity, T> entityTypeTest, final AABB boundingBox,
|
public <T extends Entity> void addToGetEntities(final Level world, final EntityTypeTest<Entity, T> entityTypeTest, final AABB boundingBox,
|
||||||
final Predicate<? super T> predicate, final List<? super T> into, final int maxCount) {
|
final Predicate<? super T> predicate, final List<? super T> into, final int maxCount) {
|
||||||
|
if (into.size() >= maxCount) {
|
||||||
|
// fix neoforge issue: do not add if list is already full
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Collection<EnderDragonPart> parts = world.dragonParts();
|
||||||
|
if (parts.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (final EnderDragonPart part : parts) {
|
||||||
|
if (!part.getBoundingBox().intersects(boundingBox)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
final T casted = (T)entityTypeTest.tryCast(part);
|
||||||
|
if (casted != null && (predicate == null || predicate.test(casted))) {
|
||||||
|
into.add(casted);
|
||||||
|
if (into.size() >= maxCount) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -153,12 +199,12 @@ public final class FabricHooks implements PlatformHooks {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long configAutoSaveInterval() {
|
public long configAutoSaveInterval(final ServerLevel world) {
|
||||||
return ConfigHolder.getConfig().chunkSaving.autoSaveInterval.getTimeTicks();
|
return ConfigHolder.getConfig().chunkSaving.autoSaveInterval.getTimeTicks();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int configMaxAutoSavePerTick() {
|
public int configMaxAutoSavePerTick(final ServerLevel world) {
|
||||||
return ConfigHolder.getConfig().chunkSaving.maxAutoSaveChunksPerTick;
|
return ConfigHolder.getConfig().chunkSaving.maxAutoSaveChunksPerTick;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,9 +219,11 @@ public final class FabricHooks implements PlatformHooks {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompoundTag convertNBT(final DataFixTypes type, final DataFixer dataFixer, final CompoundTag nbt,
|
public CompoundTag convertNBT(final DSL.TypeReference type, final DataFixer dataFixer, final CompoundTag nbt,
|
||||||
final int fromVersion, final int toVersion) {
|
final int fromVersion, final int toVersion) {
|
||||||
return type.update(dataFixer, nbt, fromVersion, toVersion);
|
return (CompoundTag)dataFixer.update(
|
||||||
|
type, new Dynamic<>(NbtOps.INSTANCE, nbt), fromVersion, toVersion
|
||||||
|
).getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -36,13 +36,12 @@
|
|||||||
"accessWidener": "moonrise.accesswidener",
|
"accessWidener": "moonrise.accesswidener",
|
||||||
"depends": {
|
"depends": {
|
||||||
"fabricloader": ">=${loader_version}",
|
"fabricloader": ">=${loader_version}",
|
||||||
"minecraft": ">1.21.1 <1.21.4",
|
"minecraft": ">1.21.3 <1.21.5",
|
||||||
"fabric-command-api-v2": "*"
|
"fabric-command-api-v2": "*"
|
||||||
},
|
},
|
||||||
"custom": {
|
"custom": {
|
||||||
"lithium:options": {
|
"lithium:options": {
|
||||||
"mixin.ai.poi": false,
|
"mixin.ai.poi": false,
|
||||||
"mixin.alloc.chunk_ticking": false,
|
|
||||||
"mixin.alloc.deep_passengers": false,
|
"mixin.alloc.deep_passengers": false,
|
||||||
"mixin.alloc.entity_tracker": false,
|
"mixin.alloc.entity_tracker": false,
|
||||||
"mixin.block.flatten_states": false,
|
"mixin.block.flatten_states": false,
|
||||||
@@ -66,9 +65,12 @@
|
|||||||
"mixin.world.block_entity_ticking": false,
|
"mixin.world.block_entity_ticking": false,
|
||||||
"mixin.world.chunk_access": false,
|
"mixin.world.chunk_access": false,
|
||||||
"mixin.world.explosions.block_raycast": false,
|
"mixin.world.explosions.block_raycast": false,
|
||||||
"mixin.world.explosions.cache_exposure": false,
|
|
||||||
"mixin.world.temperature_cache": false,
|
"mixin.world.temperature_cache": false,
|
||||||
"mixin.world.tick_scheduler": false
|
"mixin.world.tick_scheduler": false
|
||||||
}
|
},
|
||||||
|
"ferritecore:disabled_options": [
|
||||||
|
"replaceNeighborLookup",
|
||||||
|
"replacePropertyMap"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package ca.spottedleaf.moonrise.fabric;
|
||||||
|
|
||||||
|
import net.minecraft.SharedConstants;
|
||||||
|
import net.minecraft.server.Bootstrap;
|
||||||
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.spongepowered.asm.mixin.MixinEnvironment;
|
||||||
|
|
||||||
|
class MixinAuditTest {
|
||||||
|
@BeforeAll
|
||||||
|
static void beforeAll() {
|
||||||
|
SharedConstants.tryDetectVersion();
|
||||||
|
Bootstrap.bootStrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void auditMixins() {
|
||||||
|
MixinEnvironment.getCurrentEnvironment().audit();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,21 +1,25 @@
|
|||||||
# Done to increase the memory available to gradle.
|
# Done to increase the memory available to gradle.
|
||||||
org.gradle.jvmargs=-Xmx2G
|
org.gradle.jvmargs=-Xmx2G
|
||||||
org.gradle.daemon=false
|
org.gradle.parallel=true
|
||||||
|
org.gradle.caching=true
|
||||||
# Fabric Properties
|
# Fabric Properties
|
||||||
# check these on https://modmuss50.me/fabric.html
|
# check these on https://modmuss50.me/fabric.html
|
||||||
minecraft_version=1.21.3
|
minecraft_version=1.21.4
|
||||||
loader_version=0.16.7
|
loader_version=0.16.9
|
||||||
supported_minecraft_versions=1.21.3
|
supported_minecraft_versions=1.21.4
|
||||||
neoforge_version=21.3.0-beta
|
neoforge_version=21.4.33-beta
|
||||||
fabric_api_version=0.106.1+1.21.3
|
neoform_version=1.21.4-20241203.161809
|
||||||
snakeyaml_version=2.2
|
fabric_api_version=0.110.5+1.21.4
|
||||||
concurrentutil_version=0.0.2-SNAPSHOT
|
snakeyaml_version=2.3
|
||||||
cloth_version=16.0.141
|
concurrentutil_version=0.0.2
|
||||||
modmenu_version=12.0.0-beta.1
|
yamlconfig_version=1.0.2
|
||||||
|
cloth_version=17.0.144
|
||||||
|
modmenu_version=13.0.0-beta.1
|
||||||
|
junit_version=5.11.3
|
||||||
# version ids from modrinth
|
# version ids from modrinth
|
||||||
fabric_lithium_version=mc1.21.1-0.14.0-beta.1
|
fabric_lithium_version=t1FlWYl9
|
||||||
neo_lithium_version=BrMIoIMv
|
neo_lithium_version=iDqQi66g
|
||||||
# Mod Properties
|
# Mod Properties
|
||||||
mod_version=0.2.0-SNAPSHOT
|
mod_version=0.2.0-beta.7
|
||||||
maven_group=ca.spottedleaf.moonrise
|
maven_group=ca.spottedleaf.moonrise
|
||||||
archives_base_name=moonrise
|
archives_base_name=moonrise
|
||||||
|
|||||||
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,6 +1,6 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-all.zip
|
||||||
networkTimeout=10000
|
networkTimeout=10000
|
||||||
validateDistributionUrl=true
|
validateDistributionUrl=true
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
|||||||
3
gradlew
vendored
3
gradlew
vendored
@@ -86,8 +86,7 @@ done
|
|||||||
# shellcheck disable=SC2034
|
# shellcheck disable=SC2034
|
||||||
APP_BASE_NAME=${0##*/}
|
APP_BASE_NAME=${0##*/}
|
||||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||||
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
|
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
|
||||||
' "$PWD" ) || exit
|
|
||||||
|
|
||||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
MAX_FD=maximum
|
MAX_FD=maximum
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -eou pipefail
|
|
||||||
|
|
||||||
git submodule update --init --recursive
|
|
||||||
cd ConcurrentUtil
|
|
||||||
mvn install
|
|
||||||
@@ -1,9 +1,10 @@
|
|||||||
import net.fabricmc.loom.util.aw2at.Aw2At
|
import java.nio.file.Files
|
||||||
|
import java.nio.file.StandardCopyOption
|
||||||
|
import net.neoforged.moddevgradle.internal.RunGameTask
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("xyz.jpenilla.quiet-architectury-loom")
|
id("net.neoforged.moddev")
|
||||||
id 'maven-publish'
|
id 'maven-publish'
|
||||||
id 'com.gradleup.shadow'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
@@ -13,41 +14,88 @@ repositories {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
configurations.implementation {
|
def aw2at = Aw2AtTask.configureDefault(
|
||||||
extendsFrom(configurations.shadow)
|
getProject(),
|
||||||
}
|
rootProject.layout.projectDirectory.file("src/main/resources/moonrise.accesswidener").getAsFile(),
|
||||||
|
sourceSets.main
|
||||||
|
)
|
||||||
|
|
||||||
dependencies {
|
neoForge {
|
||||||
add('shadow', project([path: ":", configuration: "namedElements"]))
|
version = rootProject.neoforge_version
|
||||||
neoForge "net.neoforged:neoforge:${rootProject.neoforge_version}"
|
validateAccessTransformers = true
|
||||||
|
accessTransformers.files.setFrom(aw2at.flatMap { t -> t.getOutputFile() })
|
||||||
shadow("ca.spottedleaf:concurrentutil:${rootProject.concurrentutil_version}")
|
mods {
|
||||||
shadow("org.yaml:snakeyaml:${rootProject.snakeyaml_version}")
|
moonrise {
|
||||||
forgeExtra("org.yaml:snakeyaml:${rootProject.snakeyaml_version}")
|
sourceSet sourceSets.main
|
||||||
|
sourceSet rootProject.sourceSets.main
|
||||||
modImplementation "me.shedaniel.cloth:cloth-config-neoforge:${rootProject.cloth_version}"
|
}
|
||||||
include "me.shedaniel.cloth:cloth-config-neoforge:${rootProject.cloth_version}"
|
}
|
||||||
}
|
runs {
|
||||||
|
client {
|
||||||
processResources {
|
client()
|
||||||
inputs.property "version", project.version
|
}
|
||||||
|
server {
|
||||||
filesMatching("META-INF/neoforge.mods.toml") {
|
server()
|
||||||
expand "version": project.version, "minecraft_version": minecraft_version, "loader_version": loader_version, "mod_version": mod_version
|
}
|
||||||
|
}
|
||||||
|
unitTest {
|
||||||
|
enable()
|
||||||
|
testedMod = mods.moonrise
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
shadowJar {
|
dependencies {
|
||||||
|
runtimeOnly(project(":").sourceSets.main.output)
|
||||||
|
shadow(project(":"))
|
||||||
|
compileOnly(project(":"))
|
||||||
|
|
||||||
|
libs("ca.spottedleaf:concurrentutil:${rootProject.concurrentutil_version}") { setTransitive(false) }
|
||||||
|
libs("ca.spottedleaf:yamlconfig:${rootProject.yamlconfig_version}") { setTransitive(false) }
|
||||||
|
additionalRuntimeClasspath libs("org.yaml:snakeyaml:${rootProject.snakeyaml_version}")
|
||||||
|
|
||||||
|
implementation "me.shedaniel.cloth:cloth-config-neoforge:${rootProject.cloth_version}"
|
||||||
|
jarJar "me.shedaniel.cloth:cloth-config-neoforge:${rootProject.cloth_version}"
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.processResources {
|
||||||
|
def properties = [
|
||||||
|
"version": project.version,
|
||||||
|
"minecraft_version": minecraft_version,
|
||||||
|
"mod_version": mod_version
|
||||||
|
]
|
||||||
|
inputs.properties(properties)
|
||||||
|
filesMatching("META-INF/neoforge.mods.toml") {
|
||||||
|
expand properties
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.jar {
|
||||||
|
archiveClassifier = "dev"
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.shadowJar {
|
||||||
archiveClassifier = "dev-all"
|
archiveClassifier = "dev-all"
|
||||||
destinationDirectory = layout.buildDirectory.dir("libs")
|
destinationDirectory = layout.buildDirectory.dir("libs")
|
||||||
configurations = [project.configurations.shadow]
|
configurations = [project.configurations.shadow]
|
||||||
relocate 'ca.spottedleaf.concurrentutil', 'ca.spottedleaf.moonrise.libs.ca.spottedleaf.concurrentutil'
|
relocate 'ca.spottedleaf.concurrentutil', 'ca.spottedleaf.moonrise.libs.ca.spottedleaf.concurrentutil'
|
||||||
|
relocate 'ca.spottedleaf.yamlconfig', 'ca.spottedleaf.moonrise.libs.ca.spottedleaf.yamlconfig'
|
||||||
relocate 'org.yaml.snakeyaml', 'ca.spottedleaf.moonrise.libs.org.yaml.snakeyaml'
|
relocate 'org.yaml.snakeyaml', 'ca.spottedleaf.moonrise.libs.org.yaml.snakeyaml'
|
||||||
}
|
}
|
||||||
|
|
||||||
Aw2At.setup(getProject(), tasks.remapJar)
|
tasks.register("productionJar", Zip.class) {
|
||||||
|
archiveClassifier = ""
|
||||||
|
archiveExtension = "jar"
|
||||||
|
destinationDirectory = layout.buildDirectory.dir("libs")
|
||||||
|
from(tasks.jarJar)
|
||||||
|
from(zipTree(tasks.shadowJar.archiveFile))
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.assemble {
|
||||||
|
dependsOn tasks.productionJar
|
||||||
|
}
|
||||||
|
|
||||||
publishMods {
|
publishMods {
|
||||||
|
file = productionJar.archiveFile
|
||||||
modLoaders = ["neoforge"]
|
modLoaders = ["neoforge"]
|
||||||
|
|
||||||
modrinth {
|
modrinth {
|
||||||
@@ -65,3 +113,42 @@ publishMods {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
afterEvaluate {
|
||||||
|
neoForge.runs.configureEach { cfg ->
|
||||||
|
runConfigCommon.systemProperties.get().each {
|
||||||
|
cfg.systemProperties.put it.key, it.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup a run with lithium for compatibility testing
|
||||||
|
neoForge {
|
||||||
|
runs {
|
||||||
|
lithiumClient {
|
||||||
|
client()
|
||||||
|
disableIdeRun()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tasks.withType(RunGameTask).configureEach {
|
||||||
|
if (name == "runLithiumClient") {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
def out = gameDirectory.get().getAsFile().toPath().resolve("mods/lithium-tmp.jar")
|
||||||
|
doFirst {
|
||||||
|
Files.deleteIfExists(out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
def lithium = configurations.lithium
|
||||||
|
tasks.runLithiumClient {
|
||||||
|
def out = gameDirectory.get().getAsFile().toPath().resolve("mods/lithium-tmp.jar")
|
||||||
|
doFirst {
|
||||||
|
for (File file in lithium) {
|
||||||
|
Files.copy(file.toPath(), out, StandardCopyOption.REPLACE_EXISTING)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
doLast {
|
||||||
|
Files.deleteIfExists(out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
loom.platform=neoforge
|
|
||||||
@@ -1,16 +1,19 @@
|
|||||||
package ca.spottedleaf.moonrise.neoforge;
|
package ca.spottedleaf.moonrise.neoforge;
|
||||||
|
|
||||||
|
import ca.spottedleaf.moonrise.common.util.BaseChunkSystemHooks;
|
||||||
import ca.spottedleaf.moonrise.common.PlatformHooks;
|
import ca.spottedleaf.moonrise.common.PlatformHooks;
|
||||||
import ca.spottedleaf.moonrise.common.util.ConfigHolder;
|
import ca.spottedleaf.moonrise.common.util.ConfigHolder;
|
||||||
import ca.spottedleaf.moonrise.common.util.CoordinateUtils;
|
import ca.spottedleaf.moonrise.common.util.CoordinateUtils;
|
||||||
import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.NewChunkHolder;
|
import com.mojang.datafixers.DSL;
|
||||||
import com.mojang.datafixers.DataFixer;
|
import com.mojang.datafixers.DataFixer;
|
||||||
|
import com.mojang.serialization.Dynamic;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
import net.minecraft.nbt.NbtOps;
|
||||||
|
import net.minecraft.server.level.ChunkHolder;
|
||||||
import net.minecraft.server.level.GenerationChunkHolder;
|
import net.minecraft.server.level.GenerationChunkHolder;
|
||||||
import net.minecraft.server.level.ServerLevel;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import net.minecraft.server.level.ServerPlayer;
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
import net.minecraft.util.datafix.DataFixTypes;
|
|
||||||
import net.minecraft.world.entity.Entity;
|
import net.minecraft.world.entity.Entity;
|
||||||
import net.minecraft.world.level.BlockGetter;
|
import net.minecraft.world.level.BlockGetter;
|
||||||
import net.minecraft.world.level.ChunkPos;
|
import net.minecraft.world.level.ChunkPos;
|
||||||
@@ -32,10 +35,11 @@ import net.neoforged.neoforge.event.EventHooks;
|
|||||||
import net.neoforged.neoforge.event.entity.EntityJoinLevelEvent;
|
import net.neoforged.neoforge.event.entity.EntityJoinLevelEvent;
|
||||||
import net.neoforged.neoforge.event.level.ChunkDataEvent;
|
import net.neoforged.neoforge.event.level.ChunkDataEvent;
|
||||||
import net.neoforged.neoforge.event.level.ChunkEvent;
|
import net.neoforged.neoforge.event.level.ChunkEvent;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
public final class NeoForgeHooks implements PlatformHooks {
|
public final class NeoForgeHooks extends BaseChunkSystemHooks implements PlatformHooks {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getBrand() {
|
public String getBrand() {
|
||||||
@@ -80,10 +84,12 @@ public final class NeoForgeHooks implements PlatformHooks {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onChunkHolderTicketChange(final ServerLevel world, final NewChunkHolder holder, final int oldLevel, final int newLevel) {
|
public void onChunkHolderTicketChange(final ServerLevel world, final ChunkHolder holder, final int oldLevel, final int newLevel) {
|
||||||
|
final ChunkPos pos = holder.getPos();
|
||||||
|
|
||||||
EventHooks.fireChunkTicketLevelUpdated(
|
EventHooks.fireChunkTicketLevelUpdated(
|
||||||
world, CoordinateUtils.getChunkKey(holder.chunkX, holder.chunkZ),
|
world, CoordinateUtils.getChunkKey(pos.x, pos.z),
|
||||||
oldLevel, newLevel, holder.vanillaChunkHolder
|
oldLevel, newLevel, holder
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,7 +116,12 @@ public final class NeoForgeHooks implements PlatformHooks {
|
|||||||
@Override
|
@Override
|
||||||
public void addToGetEntities(final Level world, final Entity entity, final AABB boundingBox, final Predicate<? super Entity> predicate,
|
public void addToGetEntities(final Level world, final Entity entity, final AABB boundingBox, final Predicate<? super Entity> predicate,
|
||||||
final List<Entity> into) {
|
final List<Entity> into) {
|
||||||
for (final PartEntity<?> part : world.getPartEntities()) {
|
final Collection<PartEntity<?>> parts = world.dragonParts();
|
||||||
|
if (parts.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (final PartEntity<?> part : parts) {
|
||||||
if (part != entity && part.getBoundingBox().intersects(boundingBox) && (predicate == null || predicate.test(part))) {
|
if (part != entity && part.getBoundingBox().intersects(boundingBox) && (predicate == null || predicate.test(part))) {
|
||||||
into.add(part);
|
into.add(part);
|
||||||
}
|
}
|
||||||
@@ -125,9 +136,18 @@ public final class NeoForgeHooks implements PlatformHooks {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (final PartEntity<?> part : world.getPartEntities()) {
|
final Collection<PartEntity<?>> parts = world.dragonParts();
|
||||||
|
if (parts.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (final PartEntity<?> part : parts) {
|
||||||
|
if (!part.getBoundingBox().intersects(boundingBox)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
final T casted = (T)entityTypeTest.tryCast(part);
|
final T casted = (T)entityTypeTest.tryCast(part);
|
||||||
if (casted != null && casted.getBoundingBox().intersects(boundingBox) && (predicate == null || predicate.test(casted))) {
|
if (casted != null && (predicate == null || predicate.test(casted))) {
|
||||||
into.add(casted);
|
into.add(casted);
|
||||||
if (into.size() >= maxCount) {
|
if (into.size() >= maxCount) {
|
||||||
break;
|
break;
|
||||||
@@ -185,12 +205,12 @@ public final class NeoForgeHooks implements PlatformHooks {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long configAutoSaveInterval() {
|
public long configAutoSaveInterval(final ServerLevel world) {
|
||||||
return ConfigHolder.getConfig().chunkSaving.autoSaveInterval.getTimeTicks();
|
return ConfigHolder.getConfig().chunkSaving.autoSaveInterval.getTimeTicks();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int configMaxAutoSavePerTick() {
|
public int configMaxAutoSavePerTick(final ServerLevel world) {
|
||||||
return ConfigHolder.getConfig().chunkSaving.maxAutoSaveChunksPerTick;
|
return ConfigHolder.getConfig().chunkSaving.maxAutoSaveChunksPerTick;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,9 +225,11 @@ public final class NeoForgeHooks implements PlatformHooks {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompoundTag convertNBT(final DataFixTypes type, final DataFixer dataFixer, final CompoundTag nbt,
|
public CompoundTag convertNBT(final DSL.TypeReference type, final DataFixer dataFixer, final CompoundTag nbt,
|
||||||
final int fromVersion, final int toVersion) {
|
final int fromVersion, final int toVersion) {
|
||||||
return type.update(dataFixer, nbt, fromVersion, toVersion);
|
return (CompoundTag)dataFixer.update(
|
||||||
|
type, new Dynamic<>(NbtOps.INSTANCE, nbt), fromVersion, toVersion
|
||||||
|
).getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -13,6 +13,10 @@ displayURL = "https://github.com/Tuinity/Moonrise"
|
|||||||
authors = "Spottedleaf"
|
authors = "Spottedleaf"
|
||||||
description = "Optimisation mod for the dedicated and integrated server."
|
description = "Optimisation mod for the dedicated and integrated server."
|
||||||
displayTest = "IGNORE_ALL_VERSION"
|
displayTest = "IGNORE_ALL_VERSION"
|
||||||
|
"ferritecore:disabled_options" = [
|
||||||
|
"replaceNeighborLookup",
|
||||||
|
"replacePropertyMap"
|
||||||
|
]
|
||||||
|
|
||||||
[[dependencies.moonrise]]
|
[[dependencies.moonrise]]
|
||||||
modId = "neoforge"
|
modId = "neoforge"
|
||||||
@@ -24,7 +28,7 @@ side = "BOTH"
|
|||||||
[[dependencies.moonrise]]
|
[[dependencies.moonrise]]
|
||||||
modId = "minecraft"
|
modId = "minecraft"
|
||||||
type = "required"
|
type = "required"
|
||||||
versionRange = "(1.21.1,1.21.4)"
|
versionRange = "(1.21.3,1.21.5)"
|
||||||
ordering = "NONE"
|
ordering = "NONE"
|
||||||
side = "BOTH"
|
side = "BOTH"
|
||||||
|
|
||||||
@@ -51,9 +55,8 @@ config = "moonrise.mixins.json"
|
|||||||
[[mixins]]
|
[[mixins]]
|
||||||
config = "moonrise-neoforge.mixins.json"
|
config = "moonrise-neoforge.mixins.json"
|
||||||
|
|
||||||
[mods."lithium:options"]
|
["lithium:options"]
|
||||||
"mixin.ai.poi" = false
|
"mixin.ai.poi" = false
|
||||||
"mixin.alloc.chunk_ticking" = false
|
|
||||||
"mixin.alloc.deep_passengers" = false
|
"mixin.alloc.deep_passengers" = false
|
||||||
"mixin.alloc.entity_tracker" = false
|
"mixin.alloc.entity_tracker" = false
|
||||||
"mixin.block.flatten_states" = false
|
"mixin.block.flatten_states" = false
|
||||||
@@ -77,6 +80,5 @@ config = "moonrise-neoforge.mixins.json"
|
|||||||
"mixin.world.block_entity_ticking" = false
|
"mixin.world.block_entity_ticking" = false
|
||||||
"mixin.world.chunk_access" = false
|
"mixin.world.chunk_access" = false
|
||||||
"mixin.world.explosions.block_raycast" = false
|
"mixin.world.explosions.block_raycast" = false
|
||||||
"mixin.world.explosions.cache_exposure" = false
|
|
||||||
"mixin.world.temperature_cache" = false
|
"mixin.world.temperature_cache" = false
|
||||||
"mixin.world.tick_scheduler" = false
|
"mixin.world.tick_scheduler" = false
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package ca.spottedleaf.moonrise.neoforge;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.spongepowered.asm.mixin.MixinEnvironment;
|
||||||
|
|
||||||
|
class MixinAuditTest {
|
||||||
|
@Test
|
||||||
|
void auditMixins() {
|
||||||
|
final ClassLoader old = Thread.currentThread().getContextClassLoader();
|
||||||
|
try {
|
||||||
|
Thread.currentThread().setContextClassLoader(MixinAuditTest.class.getClassLoader());
|
||||||
|
MixinEnvironment.getCurrentEnvironment().audit();
|
||||||
|
} finally {
|
||||||
|
Thread.currentThread().setContextClassLoader(old);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,7 +13,6 @@ pluginManagement {
|
|||||||
maven {
|
maven {
|
||||||
name = 'jmp'
|
name = 'jmp'
|
||||||
url = 'https://repo.jpenilla.xyz/snapshots'
|
url = 'https://repo.jpenilla.xyz/snapshots'
|
||||||
mavenContent { snapshotsOnly() }
|
|
||||||
}
|
}
|
||||||
maven {
|
maven {
|
||||||
name = 'architectury'
|
name = 'architectury'
|
||||||
@@ -23,9 +22,10 @@ pluginManagement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0"
|
id("org.gradle.toolchains.foojay-resolver-convention") version "0.9.0"
|
||||||
id("xyz.jpenilla.quiet-architectury-loom") version "1.7.297" apply false
|
id("quiet-fabric-loom") version "1.9.312" apply false
|
||||||
id 'com.gradleup.shadow' version '8.3.0' apply false
|
id("net.neoforged.moddev") version "2.0.61-beta" apply false
|
||||||
|
id 'com.gradleup.shadow' version '8.3.5' apply false
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencyResolutionManagement {
|
dependencyResolutionManagement {
|
||||||
@@ -48,3 +48,6 @@ include("fabric")
|
|||||||
findProject(":fabric").name = "Moonrise-Fabric"
|
findProject(":fabric").name = "Moonrise-Fabric"
|
||||||
include("neoforge")
|
include("neoforge")
|
||||||
findProject(":neoforge").name = "Moonrise-NeoForge"
|
findProject(":neoforge").name = "Moonrise-NeoForge"
|
||||||
|
|
||||||
|
// includeBuild("../YamlConfig") // Uncomment to use local YamlConfig
|
||||||
|
// includeBuild("../ConcurrentUtil") // Uncomment to use local ConcurrentUtil
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
package ca.spottedleaf.moonrise.common;
|
package ca.spottedleaf.moonrise.common;
|
||||||
|
|
||||||
import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.NewChunkHolder;
|
import ca.spottedleaf.moonrise.common.util.ChunkSystemHooks;
|
||||||
|
import com.mojang.datafixers.DSL;
|
||||||
import com.mojang.datafixers.DataFixer;
|
import com.mojang.datafixers.DataFixer;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
import net.minecraft.server.level.ChunkHolder;
|
||||||
import net.minecraft.server.level.GenerationChunkHolder;
|
import net.minecraft.server.level.GenerationChunkHolder;
|
||||||
import net.minecraft.server.level.ServerLevel;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import net.minecraft.server.level.ServerPlayer;
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
import net.minecraft.util.datafix.DataFixTypes;
|
|
||||||
import net.minecraft.world.entity.Entity;
|
import net.minecraft.world.entity.Entity;
|
||||||
import net.minecraft.world.level.BlockGetter;
|
import net.minecraft.world.level.BlockGetter;
|
||||||
import net.minecraft.world.level.ChunkPos;
|
import net.minecraft.world.level.ChunkPos;
|
||||||
@@ -23,7 +24,7 @@ import java.util.List;
|
|||||||
import java.util.ServiceLoader;
|
import java.util.ServiceLoader;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
public interface PlatformHooks {
|
public interface PlatformHooks extends ChunkSystemHooks {
|
||||||
public static PlatformHooks get() {
|
public static PlatformHooks get() {
|
||||||
return Holder.INSTANCE;
|
return Holder.INSTANCE;
|
||||||
}
|
}
|
||||||
@@ -44,7 +45,7 @@ public interface PlatformHooks {
|
|||||||
|
|
||||||
public boolean allowAsyncTicketUpdates();
|
public boolean allowAsyncTicketUpdates();
|
||||||
|
|
||||||
public void onChunkHolderTicketChange(final ServerLevel world, final NewChunkHolder holder, final int oldLevel, final int newLevel);
|
public void onChunkHolderTicketChange(final ServerLevel world, final ChunkHolder holder, final int oldLevel, final int newLevel);
|
||||||
|
|
||||||
public void chunkUnloadFromWorld(final LevelChunk chunk);
|
public void chunkUnloadFromWorld(final LevelChunk chunk);
|
||||||
|
|
||||||
@@ -63,8 +64,6 @@ public interface PlatformHooks {
|
|||||||
|
|
||||||
public void entityMove(final Entity entity, final long oldSection, final long newSection);
|
public void entityMove(final Entity entity, final long oldSection, final long newSection);
|
||||||
|
|
||||||
public boolean screenEntity(final ServerLevel world, final Entity entity, final boolean fromDisk, final boolean event);
|
|
||||||
|
|
||||||
public boolean configFixMC224294();
|
public boolean configFixMC224294();
|
||||||
|
|
||||||
public boolean configAutoConfigSendDistance();
|
public boolean configAutoConfigSendDistance();
|
||||||
@@ -79,16 +78,16 @@ public interface PlatformHooks {
|
|||||||
|
|
||||||
public int configPlayerMaxConcurrentGens();
|
public int configPlayerMaxConcurrentGens();
|
||||||
|
|
||||||
public long configAutoSaveInterval();
|
public long configAutoSaveInterval(final ServerLevel world);
|
||||||
|
|
||||||
public int configMaxAutoSavePerTick();
|
public int configMaxAutoSavePerTick(final ServerLevel world);
|
||||||
|
|
||||||
public boolean configFixMC159283();
|
public boolean configFixMC159283();
|
||||||
|
|
||||||
// support for CB chunk mustNotSave
|
// support for CB chunk mustNotSave
|
||||||
public boolean forceNoSave(final ChunkAccess chunk);
|
public boolean forceNoSave(final ChunkAccess chunk);
|
||||||
|
|
||||||
public CompoundTag convertNBT(final DataFixTypes type, final DataFixer dataFixer, final CompoundTag nbt,
|
public CompoundTag convertNBT(final DSL.TypeReference type, final DataFixer dataFixer, final CompoundTag nbt,
|
||||||
final int fromVersion, final int toVersion);
|
final int fromVersion, final int toVersion);
|
||||||
|
|
||||||
public boolean hasMainChunkLoadHook();
|
public boolean hasMainChunkLoadHook();
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
package ca.spottedleaf.moonrise.common.config;
|
|
||||||
|
|
||||||
public interface InitialiseHook {
|
|
||||||
|
|
||||||
public void initialise();
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
package ca.spottedleaf.moonrise.common.config.adapter;
|
|
||||||
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
|
|
||||||
public abstract class TypeAdapter<T, S> {
|
|
||||||
|
|
||||||
public abstract T deserialize(final TypeAdapterRegistry registry, final Object input, final Type type);
|
|
||||||
|
|
||||||
public abstract S serialize(final TypeAdapterRegistry registry, final T value, final Type type);
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,307 +0,0 @@
|
|||||||
package ca.spottedleaf.moonrise.common.config.adapter;
|
|
||||||
|
|
||||||
import ca.spottedleaf.moonrise.common.config.InitialiseHook;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.collection.CollectionTypeAdapter;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.collection.ListTypeAdapter;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.collection.SortedMapTypeAdapter;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.primitive.BooleanTypeAdapter;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.primitive.ByteTypeAdapter;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.primitive.DoubleTypeAdapter;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.primitive.FloatTypeAdapter;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.primitive.IntegerTypeAdapter;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.primitive.LongTypeAdapter;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.primitive.ShortTypeAdapter;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.primitive.StringTypeAdapter;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.type.BigDecimalTypeAdapter;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.type.BigIntegerTypeAdapter;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.type.DurationTypeAdapter;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.annotation.Adaptable;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.annotation.Serializable;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.type.Duration;
|
|
||||||
import java.lang.annotation.Annotation;
|
|
||||||
import java.lang.reflect.Constructor;
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.lang.reflect.ParameterizedType;
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.math.BigInteger;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public final class TypeAdapterRegistry {
|
|
||||||
|
|
||||||
private final Map<Class<?>, TypeAdapter<?, ?>> adapters = new HashMap<>();
|
|
||||||
{
|
|
||||||
this.adapters.put(boolean.class, BooleanTypeAdapter.INSTANCE);
|
|
||||||
this.adapters.put(byte.class, ByteTypeAdapter.INSTANCE);
|
|
||||||
this.adapters.put(short.class, ShortTypeAdapter.INSTANCE);
|
|
||||||
this.adapters.put(int.class, IntegerTypeAdapter.INSTANCE);
|
|
||||||
this.adapters.put(long.class, LongTypeAdapter.INSTANCE);
|
|
||||||
this.adapters.put(float.class, FloatTypeAdapter.INSTANCE);
|
|
||||||
this.adapters.put(double.class, DoubleTypeAdapter.INSTANCE);
|
|
||||||
|
|
||||||
this.adapters.put(Boolean.class, BooleanTypeAdapter.INSTANCE);
|
|
||||||
this.adapters.put(Byte.class, ByteTypeAdapter.INSTANCE);
|
|
||||||
this.adapters.put(Short.class, ShortTypeAdapter.INSTANCE);
|
|
||||||
this.adapters.put(Integer.class, IntegerTypeAdapter.INSTANCE);
|
|
||||||
this.adapters.put(Long.class, LongTypeAdapter.INSTANCE);
|
|
||||||
this.adapters.put(Float.class, FloatTypeAdapter.INSTANCE);
|
|
||||||
this.adapters.put(Double.class, DoubleTypeAdapter.INSTANCE);
|
|
||||||
|
|
||||||
this.adapters.put(String.class, StringTypeAdapter.INSTANCE);
|
|
||||||
|
|
||||||
this.adapters.put(Collection.class, CollectionTypeAdapter.INSTANCE);
|
|
||||||
this.adapters.put(List.class, ListTypeAdapter.INSTANCE);
|
|
||||||
this.adapters.put(Map.class, SortedMapTypeAdapter.SORTED_CASE_INSENSITIVE);
|
|
||||||
this.adapters.put(LinkedHashMap.class, SortedMapTypeAdapter.SORTED_CASE_INSENSITIVE);
|
|
||||||
|
|
||||||
this.adapters.put(BigInteger.class, BigIntegerTypeAdapter.INSTANCE);
|
|
||||||
this.adapters.put(BigDecimal.class, BigDecimalTypeAdapter.INSTANCE);
|
|
||||||
this.adapters.put(Duration.class, DurationTypeAdapter.INSTANCE);
|
|
||||||
}
|
|
||||||
|
|
||||||
public TypeAdapter<?, ?> putAdapter(final Class<?> clazz, final TypeAdapter<?, ?> adapter) {
|
|
||||||
return this.adapters.put(clazz, adapter);
|
|
||||||
}
|
|
||||||
|
|
||||||
public TypeAdapter<?, ?> getAdapter(final Class<?> clazz) {
|
|
||||||
return this.adapters.get(clazz);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object deserialize(final Object input, final Type type) {
|
|
||||||
TypeAdapter<?, ?> adapter = null;
|
|
||||||
if (type instanceof Class<?> clazz) {
|
|
||||||
adapter = this.adapters.get(clazz);
|
|
||||||
}
|
|
||||||
if (adapter == null && (type instanceof ParameterizedType parameterizedType)) {
|
|
||||||
adapter = this.adapters.get((Class<?>)parameterizedType.getRawType());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (adapter == null) {
|
|
||||||
throw new IllegalArgumentException("No adapter for " + input.getClass() + " with type " + type);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ((TypeAdapter)adapter).deserialize(this, input, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object serialize(final Object input, final Type type) {
|
|
||||||
TypeAdapter<?, ?> adapter = null;
|
|
||||||
if (type instanceof Class<?> clazz) {
|
|
||||||
adapter = this.adapters.get(clazz);
|
|
||||||
}
|
|
||||||
if (adapter == null && (type instanceof ParameterizedType parameterizedType)) {
|
|
||||||
adapter = this.adapters.get((Class<?>)parameterizedType.getRawType());
|
|
||||||
}
|
|
||||||
if (adapter == null) {
|
|
||||||
adapter = this.adapters.get(input.getClass());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (adapter == null) {
|
|
||||||
throw new IllegalArgumentException("No adapter for " + input.getClass() + " with type " + type);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ((TypeAdapter)adapter).serialize(this, input, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
public <T> TypeAdapter<T, Map<Object, Object>> makeAdapter(final Class<? extends T> clazz) throws Exception {
|
|
||||||
final TypeAdapter<T, Map<Object, Object>> ret = new AutoTypeAdapter<>(this, clazz);
|
|
||||||
|
|
||||||
this.putAdapter(clazz, ret);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
public <T> void callInitialisers(final T object) {
|
|
||||||
if (object == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final TypeAdapter<?, ?> adapter = this.getAdapter(object.getClass());
|
|
||||||
|
|
||||||
if (!(adapter instanceof AutoTypeAdapter<?> autoTypeAdapter)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
((AutoTypeAdapter<T>)autoTypeAdapter).callInitialisers(object);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final class AutoTypeAdapter<T> extends TypeAdapter<T, Map<Object, Object>> {
|
|
||||||
|
|
||||||
private final TypeAdapterRegistry registry;
|
|
||||||
private final Constructor<? extends T> constructor;
|
|
||||||
private final SerializableField[] fields;
|
|
||||||
|
|
||||||
public AutoTypeAdapter(final TypeAdapterRegistry registry, final Class<? extends T> clazz) throws Exception {
|
|
||||||
this.registry = registry;
|
|
||||||
this.constructor = clazz.getConstructor();
|
|
||||||
this.fields = findSerializableFields(registry, clazz);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static TypeAdapter<?, ?> findOrMakeAdapter(final TypeAdapterRegistry registry, final Class<?> clazz) throws Exception {
|
|
||||||
final TypeAdapter<?, ?> ret = registry.getAdapter(clazz);
|
|
||||||
if (ret != null) {
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (final Annotation annotation : clazz.getAnnotations()) {
|
|
||||||
if (annotation instanceof Adaptable adaptable) {
|
|
||||||
return registry.makeAdapter(clazz);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new IllegalArgumentException("No type adapter for " + clazz + " (Forgot @Adaptable?)");
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String makeSerializedKey(final String input) {
|
|
||||||
final StringBuilder ret = new StringBuilder();
|
|
||||||
|
|
||||||
for (final char c : input.toCharArray()) {
|
|
||||||
if (!Character.isUpperCase(c)) {
|
|
||||||
ret.append(c);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
ret.append('-');
|
|
||||||
ret.append(Character.toLowerCase(c));
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static record SerializableField(
|
|
||||||
Field field,
|
|
||||||
boolean required,
|
|
||||||
String comment,
|
|
||||||
TypeAdapter<?, ?> adapter,
|
|
||||||
boolean serialize,
|
|
||||||
String serializedKey
|
|
||||||
) {}
|
|
||||||
|
|
||||||
private static SerializableField[] findSerializableFields(final TypeAdapterRegistry registry, Class<?> clazz) throws Exception {
|
|
||||||
final List<SerializableField> ret = new ArrayList<>();
|
|
||||||
do {
|
|
||||||
for (final Field field : clazz.getDeclaredFields()) {
|
|
||||||
field.setAccessible(true);
|
|
||||||
|
|
||||||
for (final Annotation annotation : field.getAnnotations()) {
|
|
||||||
if (!(annotation instanceof Serializable serializable)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
final TypeAdapter<?, ?> adapter;
|
|
||||||
|
|
||||||
if (serializable.adapter() != TypeAdapter.class) {
|
|
||||||
adapter = serializable.adapter().getConstructor().newInstance();
|
|
||||||
} else {
|
|
||||||
adapter = findOrMakeAdapter(registry, field.getType());
|
|
||||||
}
|
|
||||||
|
|
||||||
String serializedKey = serializable.serializedKey();
|
|
||||||
if (serializedKey.isEmpty()) {
|
|
||||||
serializedKey = makeSerializedKey(field.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
ret.add(new SerializableField(
|
|
||||||
field, serializable.required(), serializable.comment(), adapter,
|
|
||||||
serializable.serialize(), serializedKey
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} while ((clazz = clazz.getSuperclass()) != Object.class);
|
|
||||||
|
|
||||||
ret.sort((final SerializableField c1, final SerializableField c2) -> {
|
|
||||||
return c1.serializedKey.compareTo(c2.serializedKey);
|
|
||||||
});
|
|
||||||
|
|
||||||
return ret.toArray(new SerializableField[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public T deserialize(final TypeAdapterRegistry registry, final Object input, final Type type) {
|
|
||||||
if (!(input instanceof Map<?,?> inputMap)) {
|
|
||||||
throw new IllegalArgumentException("Not a map type: " + input.getClass());
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
final T ret = this.constructor.newInstance();
|
|
||||||
|
|
||||||
for (final SerializableField field : this.fields) {
|
|
||||||
final Object fieldValue = inputMap.get(field.serializedKey);
|
|
||||||
|
|
||||||
if (fieldValue == null) {
|
|
||||||
if (field.required) {
|
|
||||||
throw new IllegalArgumentException("Missing required field '" + field.serializedKey + "' in " + this.constructor.getDeclaringClass());
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
field.field.set(ret, field.adapter.deserialize(registry, fieldValue, field.field.getGenericType()));
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
} catch (final Exception ex) {
|
|
||||||
throw new RuntimeException(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<Object, Object> serialize(final TypeAdapterRegistry registry, final T value, final Type type) {
|
|
||||||
final LinkedHashMap<Object, Object> ret = new LinkedHashMap<>();
|
|
||||||
|
|
||||||
for (final SerializableField field : this.fields) {
|
|
||||||
if (!field.serialize) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
final Object fieldValue;
|
|
||||||
try {
|
|
||||||
fieldValue = field.field.get(value);
|
|
||||||
} catch (final Exception ex) {
|
|
||||||
throw new RuntimeException(ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fieldValue != null) {
|
|
||||||
ret.put(
|
|
||||||
field.comment.isBlank() ? field.serializedKey : new CommentedData(field.comment, field.serializedKey),
|
|
||||||
((TypeAdapter)field.adapter).serialize(
|
|
||||||
registry, fieldValue, field.field.getGenericType()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void callInitialisers(final T value) {
|
|
||||||
for (final SerializableField field : this.fields) {
|
|
||||||
final Object fieldValue;
|
|
||||||
try {
|
|
||||||
fieldValue = field.field.get(value);
|
|
||||||
} catch (final Exception ex) {
|
|
||||||
throw new RuntimeException(ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fieldValue instanceof InitialiseHook initialiseHook) {
|
|
||||||
initialiseHook.initialise();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.registry.callInitialisers(fieldValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final class CommentedData {
|
|
||||||
|
|
||||||
public final String comment;
|
|
||||||
public final Object data;
|
|
||||||
|
|
||||||
public CommentedData(final String comment, final Object data) {
|
|
||||||
this.comment = comment;
|
|
||||||
this.data = data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
package ca.spottedleaf.moonrise.common.config.adapter.collection;
|
|
||||||
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapter;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapterRegistry;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.primitive.StringTypeAdapter;
|
|
||||||
import java.lang.reflect.ParameterizedType;
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public final class CollectionTypeAdapter extends TypeAdapter<Collection<Object>, List<Object>> {
|
|
||||||
|
|
||||||
public static final CollectionTypeAdapter INSTANCE = new CollectionTypeAdapter();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Collection<Object> deserialize(final TypeAdapterRegistry registry, final Object input, final Type type) {
|
|
||||||
if (!(type instanceof ParameterizedType parameterizedType)) {
|
|
||||||
throw new IllegalArgumentException("Collection field must specify generic type");
|
|
||||||
}
|
|
||||||
final Type elementType = parameterizedType.getActualTypeArguments()[0];
|
|
||||||
if (input instanceof Collection<?> collection) {
|
|
||||||
final List<Object> ret = new ArrayList<>(collection.size());
|
|
||||||
|
|
||||||
for (final Object v : collection) {
|
|
||||||
ret.add(registry.deserialize(v, elementType));
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
throw new IllegalArgumentException("Not a collection type: " + input.getClass());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<Object> serialize(final TypeAdapterRegistry registry, final Collection<Object> value, final Type type) {
|
|
||||||
final List<Object> ret = new ArrayList<>(value.size());
|
|
||||||
|
|
||||||
final Type elementType = type instanceof ParameterizedType parameterizedType ? parameterizedType.getActualTypeArguments()[0] : null;
|
|
||||||
|
|
||||||
for (final Object v : value) {
|
|
||||||
ret.add(registry.serialize(v, elementType == null ? v.getClass() : elementType));
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
package ca.spottedleaf.moonrise.common.config.adapter.collection;
|
|
||||||
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapter;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapterRegistry;
|
|
||||||
import java.lang.reflect.ParameterizedType;
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public final class ListTypeAdapter extends TypeAdapter<List<Object>, List<Object>> {
|
|
||||||
|
|
||||||
public static final ListTypeAdapter INSTANCE = new ListTypeAdapter();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<Object> deserialize(final TypeAdapterRegistry registry, final Object input, final Type type) {
|
|
||||||
if (!(type instanceof ParameterizedType parameterizedType)) {
|
|
||||||
throw new IllegalArgumentException("Collection field must specify generic type");
|
|
||||||
}
|
|
||||||
final Type elementType = parameterizedType.getActualTypeArguments()[0];
|
|
||||||
if (input instanceof Collection<?> collection) {
|
|
||||||
final List<Object> ret = new ArrayList<>(collection.size());
|
|
||||||
|
|
||||||
for (final Object v : collection) {
|
|
||||||
ret.add(registry.deserialize(v, elementType));
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
throw new IllegalArgumentException("Not a collection type: " + input.getClass());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<Object> serialize(final TypeAdapterRegistry registry, final List<Object> value, final Type type) {
|
|
||||||
final List<Object> ret = new ArrayList<>(value.size());
|
|
||||||
|
|
||||||
final Type elementType = type instanceof ParameterizedType parameterizedType ? parameterizedType.getActualTypeArguments()[0] : null;
|
|
||||||
|
|
||||||
for (final Object v : value) {
|
|
||||||
ret.add(registry.serialize(v, elementType));
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
package ca.spottedleaf.moonrise.common.config.adapter.collection;
|
|
||||||
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapter;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapterRegistry;
|
|
||||||
import java.lang.reflect.ParameterizedType;
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.TreeMap;
|
|
||||||
|
|
||||||
public final class SortedMapTypeAdapter extends TypeAdapter<Map<String, Object>, Map<String, Object>> {
|
|
||||||
|
|
||||||
public static final SortedMapTypeAdapter SORTED_CASE_INSENSITIVE = new SortedMapTypeAdapter(String.CASE_INSENSITIVE_ORDER);
|
|
||||||
public static final SortedMapTypeAdapter SORTED_CASE_SENSITIVE = new SortedMapTypeAdapter(null);
|
|
||||||
|
|
||||||
private final Comparator<String> keyComparator;
|
|
||||||
|
|
||||||
public SortedMapTypeAdapter(final Comparator<String> keyComparator) {
|
|
||||||
this.keyComparator = keyComparator;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String, Object> deserialize(final TypeAdapterRegistry registry, final Object input, final Type type) {
|
|
||||||
if (!(type instanceof ParameterizedType parameterizedType)) {
|
|
||||||
throw new IllegalArgumentException("Collection field must specify generic type");
|
|
||||||
}
|
|
||||||
final Type valueType = parameterizedType.getActualTypeArguments()[1];
|
|
||||||
if (input instanceof Map<?,?> inputMap) {
|
|
||||||
final Map<String, Object> castedInput = (Map<String, Object>)inputMap;
|
|
||||||
|
|
||||||
final TreeMap<String, Object> ret = new TreeMap<>(this.keyComparator);
|
|
||||||
|
|
||||||
for (final Map.Entry<String, Object> entry : castedInput.entrySet()) {
|
|
||||||
ret.put(entry.getKey(), registry.deserialize(entry.getValue(), valueType));
|
|
||||||
}
|
|
||||||
|
|
||||||
// transform to linked so that get() is O(1)
|
|
||||||
return new LinkedHashMap<>(ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new IllegalArgumentException("Not a map type: " + input.getClass());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String, Object> serialize(final TypeAdapterRegistry registry, final Map<String, Object> value, final Type type) {
|
|
||||||
final TreeMap<String, Object> ret = new TreeMap<>(this.keyComparator);
|
|
||||||
|
|
||||||
final Type valueType = type instanceof ParameterizedType parameterizedType ? parameterizedType.getActualTypeArguments()[1] : null;
|
|
||||||
|
|
||||||
for (final Map.Entry<String, Object> entry : value.entrySet()) {
|
|
||||||
ret.put(entry.getKey(), registry.serialize(entry.getValue(), valueType));
|
|
||||||
}
|
|
||||||
|
|
||||||
// transform to linked so that get() is O(1)
|
|
||||||
return new LinkedHashMap<>(ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
package ca.spottedleaf.moonrise.common.config.adapter.collection;
|
|
||||||
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapter;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapterRegistry;
|
|
||||||
import java.lang.reflect.ParameterizedType;
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public final class UnsortedMapTypeAdapter extends TypeAdapter<Map<String, Object>, Map<String, Object>> {
|
|
||||||
|
|
||||||
public static final UnsortedMapTypeAdapter INSTANCE = new UnsortedMapTypeAdapter();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String, Object> deserialize(final TypeAdapterRegistry registry, final Object input, final Type type) {
|
|
||||||
if (!(type instanceof ParameterizedType parameterizedType)) {
|
|
||||||
throw new IllegalArgumentException("Collection field must specify generic type");
|
|
||||||
}
|
|
||||||
final Type valueType = parameterizedType.getActualTypeArguments()[1];
|
|
||||||
if (input instanceof Map<?,?> inputMap) {
|
|
||||||
final Map<String, Object> castedInput = (Map<String, Object>)inputMap;
|
|
||||||
|
|
||||||
final LinkedHashMap<String, Object> ret = new LinkedHashMap<>();
|
|
||||||
|
|
||||||
for (final Map.Entry<String, Object> entry : castedInput.entrySet()) {
|
|
||||||
ret.put(entry.getKey(), registry.deserialize(entry.getValue(), valueType));
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new IllegalArgumentException("Not a map type: " + input.getClass());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String, Object> serialize(final TypeAdapterRegistry registry, final Map<String, Object> value, final Type type) {
|
|
||||||
final LinkedHashMap<String, Object> ret = new LinkedHashMap<>();
|
|
||||||
|
|
||||||
final Type valueType = type instanceof ParameterizedType parameterizedType ? parameterizedType.getActualTypeArguments()[1] : null;
|
|
||||||
|
|
||||||
for (final Map.Entry<String, Object> entry : value.entrySet()) {
|
|
||||||
ret.put(entry.getKey(), registry.serialize(entry.getValue(), valueType));
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
package ca.spottedleaf.moonrise.common.config.adapter.primitive;
|
|
||||||
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapter;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapterRegistry;
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
|
|
||||||
public final class BooleanTypeAdapter extends TypeAdapter<Boolean, Boolean> {
|
|
||||||
|
|
||||||
public static final BooleanTypeAdapter INSTANCE = new BooleanTypeAdapter();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Boolean deserialize(final TypeAdapterRegistry registry, final Object input, final Type type) {
|
|
||||||
if (input instanceof Boolean ret) {
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
if (input instanceof String str) {
|
|
||||||
if (str.equalsIgnoreCase("false")) {
|
|
||||||
return Boolean.FALSE;
|
|
||||||
}
|
|
||||||
if (str.equalsIgnoreCase("true")) {
|
|
||||||
return Boolean.TRUE;
|
|
||||||
}
|
|
||||||
throw new IllegalArgumentException("Not a boolean: " + str);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new IllegalArgumentException("Not a boolean type: " + input.getClass());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Boolean serialize(final TypeAdapterRegistry registry, final Boolean value, final Type type) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
package ca.spottedleaf.moonrise.common.config.adapter.primitive;
|
|
||||||
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapter;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapterRegistry;
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
import java.math.BigInteger;
|
|
||||||
|
|
||||||
public final class ByteTypeAdapter extends TypeAdapter<Byte, Byte> {
|
|
||||||
|
|
||||||
public static final ByteTypeAdapter INSTANCE = new ByteTypeAdapter();
|
|
||||||
|
|
||||||
private static Byte cast(final Object original, final long value) {
|
|
||||||
if (value < (long)Byte.MIN_VALUE || value > (long)Byte.MAX_VALUE) {
|
|
||||||
throw new IllegalArgumentException("Byte value is out of range: " + original.toString());
|
|
||||||
}
|
|
||||||
return Byte.valueOf((byte)value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Byte deserialize(final TypeAdapterRegistry registry, final Object input, final Type type) {
|
|
||||||
if (input instanceof Number number) {
|
|
||||||
// note: silently discard floating point significand
|
|
||||||
return cast(input, number instanceof BigInteger bigInteger ? bigInteger.longValueExact() : number.longValue());
|
|
||||||
}
|
|
||||||
if (input instanceof String string) {
|
|
||||||
return cast(input, (long)Double.parseDouble(string));
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new IllegalArgumentException("Not a byte type: " + input.getClass());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Byte serialize(final TypeAdapterRegistry registry, final Byte value, final Type type) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
package ca.spottedleaf.moonrise.common.config.adapter.primitive;
|
|
||||||
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapter;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapterRegistry;
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
|
|
||||||
public final class DoubleTypeAdapter extends TypeAdapter<Double, Double> {
|
|
||||||
|
|
||||||
public static final DoubleTypeAdapter INSTANCE = new DoubleTypeAdapter();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Double deserialize(final TypeAdapterRegistry registry, final Object input, final Type type) {
|
|
||||||
if (input instanceof Number number) {
|
|
||||||
return Double.valueOf(number.doubleValue());
|
|
||||||
}
|
|
||||||
if (input instanceof String string) {
|
|
||||||
return Double.valueOf(Double.parseDouble(string));
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new IllegalArgumentException("Not a byte type: " + input.getClass());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Double serialize(final TypeAdapterRegistry registry, final Double value, final Type type) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
package ca.spottedleaf.moonrise.common.config.adapter.primitive;
|
|
||||||
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapter;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapterRegistry;
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
|
|
||||||
public final class FloatTypeAdapter extends TypeAdapter<Float, Float> {
|
|
||||||
|
|
||||||
public static final FloatTypeAdapter INSTANCE = new FloatTypeAdapter();
|
|
||||||
|
|
||||||
private static Float cast(final Object original, final double value) {
|
|
||||||
if (value < -(double)Float.MAX_VALUE || value > (double)Float.MAX_VALUE) {
|
|
||||||
throw new IllegalArgumentException("Byte value is out of range: " + original.toString());
|
|
||||||
}
|
|
||||||
// note: silently ignore precision loss
|
|
||||||
return Float.valueOf((float)value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Float deserialize(final TypeAdapterRegistry registry, final Object input, final Type type) {
|
|
||||||
if (input instanceof Number number) {
|
|
||||||
return cast(input, number.doubleValue());
|
|
||||||
}
|
|
||||||
if (input instanceof String string) {
|
|
||||||
return cast(input, Double.parseDouble(string));
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new IllegalArgumentException("Not a byte type: " + input.getClass());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Float serialize(final TypeAdapterRegistry registry, final Float value, final Type type) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
package ca.spottedleaf.moonrise.common.config.adapter.primitive;
|
|
||||||
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapter;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapterRegistry;
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
import java.math.BigInteger;
|
|
||||||
|
|
||||||
public final class IntegerTypeAdapter extends TypeAdapter<Integer, Integer> {
|
|
||||||
|
|
||||||
public static final IntegerTypeAdapter INSTANCE = new IntegerTypeAdapter();
|
|
||||||
|
|
||||||
private static Integer cast(final Object original, final long value) {
|
|
||||||
if (value < (long)Integer.MIN_VALUE || value > (long)Integer.MAX_VALUE) {
|
|
||||||
throw new IllegalArgumentException("Integer value is out of range: " + original.toString());
|
|
||||||
}
|
|
||||||
return Integer.valueOf((int)value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Integer deserialize(final TypeAdapterRegistry registry, final Object input, final Type type) {
|
|
||||||
if (input instanceof Number number) {
|
|
||||||
// note: silently discard floating point significand
|
|
||||||
return cast(input, number instanceof BigInteger bigInteger ? bigInteger.longValueExact() : number.longValue());
|
|
||||||
}
|
|
||||||
if (input instanceof String string) {
|
|
||||||
return cast(input, (long)Double.parseDouble(string));
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new IllegalArgumentException("Not an integer type: " + input.getClass());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Integer serialize(final TypeAdapterRegistry registry, final Integer value, final Type type) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
package ca.spottedleaf.moonrise.common.config.adapter.primitive;
|
|
||||||
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapter;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapterRegistry;
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
import java.math.BigInteger;
|
|
||||||
|
|
||||||
public final class LongTypeAdapter extends TypeAdapter<Long, Long> {
|
|
||||||
|
|
||||||
public static final LongTypeAdapter INSTANCE = new LongTypeAdapter();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Long deserialize(final TypeAdapterRegistry registry, final Object input, final Type type) {
|
|
||||||
if (input instanceof Number number) {
|
|
||||||
// note: silently discard floating point significand
|
|
||||||
return number instanceof BigInteger bigInteger ? bigInteger.longValueExact() : number.longValue();
|
|
||||||
}
|
|
||||||
if (input instanceof String string) {
|
|
||||||
try {
|
|
||||||
return Long.valueOf(Long.parseLong(string));
|
|
||||||
} catch (final NumberFormatException ex) {
|
|
||||||
return Long.valueOf((long)Double.parseDouble(string));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new IllegalArgumentException("Not a long type: " + input.getClass());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Long serialize(final TypeAdapterRegistry registry, final Long value, final Type type) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
package ca.spottedleaf.moonrise.common.config.adapter.primitive;
|
|
||||||
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapter;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapterRegistry;
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
import java.math.BigInteger;
|
|
||||||
|
|
||||||
public final class ShortTypeAdapter extends TypeAdapter<Short, Short> {
|
|
||||||
|
|
||||||
public static final ShortTypeAdapter INSTANCE = new ShortTypeAdapter();
|
|
||||||
|
|
||||||
private static Short cast(final Object original, final long value) {
|
|
||||||
if (value < (long)Short.MIN_VALUE || value > (long)Short.MAX_VALUE) {
|
|
||||||
throw new IllegalArgumentException("Short value is out of range: " + original.toString());
|
|
||||||
}
|
|
||||||
return Short.valueOf((short)value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Short deserialize(final TypeAdapterRegistry registry, final Object input, final Type type) {
|
|
||||||
if (input instanceof Number number) {
|
|
||||||
// note: silently discard floating point significand
|
|
||||||
return cast(input, number instanceof BigInteger bigInteger ? bigInteger.longValueExact() : number.longValue());
|
|
||||||
}
|
|
||||||
if (input instanceof String string) {
|
|
||||||
return cast(input, (long)Double.parseDouble(string));
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new IllegalArgumentException("Not a short type: " + input.getClass());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Short serialize(final TypeAdapterRegistry registry, final Short value, final Type type) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
package ca.spottedleaf.moonrise.common.config.adapter.primitive;
|
|
||||||
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapter;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapterRegistry;
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
|
|
||||||
public final class StringTypeAdapter extends TypeAdapter<String, String> {
|
|
||||||
|
|
||||||
public static final StringTypeAdapter INSTANCE = new StringTypeAdapter();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String deserialize(final TypeAdapterRegistry registry, final Object input, final Type type) {
|
|
||||||
if (input instanceof Boolean bool) {
|
|
||||||
return String.valueOf(bool.booleanValue());
|
|
||||||
}
|
|
||||||
if (input instanceof Number number) {
|
|
||||||
return number.toString();
|
|
||||||
}
|
|
||||||
if (input instanceof String string) {
|
|
||||||
return string;
|
|
||||||
}
|
|
||||||
throw new IllegalArgumentException("Not a string type: " + input.getClass());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String serialize(final TypeAdapterRegistry registry, final String value, final Type type) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
package ca.spottedleaf.moonrise.common.config.adapter.type;
|
|
||||||
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapter;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapterRegistry;
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.math.BigInteger;
|
|
||||||
|
|
||||||
public final class BigDecimalTypeAdapter extends TypeAdapter<BigDecimal, String> {
|
|
||||||
|
|
||||||
public static final BigDecimalTypeAdapter INSTANCE = new BigDecimalTypeAdapter();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BigDecimal deserialize(final TypeAdapterRegistry registry, final Object input, final Type type) {
|
|
||||||
if (input instanceof Number number) {
|
|
||||||
// safest to catch all number impls is to use toString
|
|
||||||
return new BigDecimal(number.toString());
|
|
||||||
}
|
|
||||||
if (input instanceof String string) {
|
|
||||||
return new BigDecimal(string);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new IllegalArgumentException("Not an BigDecimal type: " + input.getClass());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String serialize(final TypeAdapterRegistry registry, final BigDecimal value, final Type type) {
|
|
||||||
return value.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
package ca.spottedleaf.moonrise.common.config.adapter.type;
|
|
||||||
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapter;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapterRegistry;
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.math.BigInteger;
|
|
||||||
|
|
||||||
public final class BigIntegerTypeAdapter extends TypeAdapter<BigInteger, String> {
|
|
||||||
|
|
||||||
public static final BigIntegerTypeAdapter INSTANCE = new BigIntegerTypeAdapter();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BigInteger deserialize(final TypeAdapterRegistry registry, final Object input, final Type type) {
|
|
||||||
if (input instanceof Number number) {
|
|
||||||
if (number instanceof BigInteger bigInteger) {
|
|
||||||
return bigInteger;
|
|
||||||
}
|
|
||||||
// note: silently discard floating point significand
|
|
||||||
if (number instanceof BigDecimal bigDecimal) {
|
|
||||||
return bigDecimal.toBigInteger();
|
|
||||||
}
|
|
||||||
|
|
||||||
return BigInteger.valueOf(number.longValue());
|
|
||||||
}
|
|
||||||
if (input instanceof String string) {
|
|
||||||
return new BigDecimal(string).toBigInteger();
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new IllegalArgumentException("Not an BigInteger type: " + input.getClass());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String serialize(final TypeAdapterRegistry registry, final BigInteger value, final Type type) {
|
|
||||||
return value.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
package ca.spottedleaf.moonrise.common.config.adapter.type;
|
|
||||||
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapter;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapterRegistry;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.type.Duration;
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
|
|
||||||
public final class DurationTypeAdapter extends TypeAdapter<Duration, String> {
|
|
||||||
|
|
||||||
public static final DurationTypeAdapter INSTANCE = new DurationTypeAdapter();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Duration deserialize(final TypeAdapterRegistry registry, final Object input, final Type type) {
|
|
||||||
if (!(input instanceof String string)) {
|
|
||||||
throw new IllegalArgumentException("Not a string: " + input.getClass());
|
|
||||||
}
|
|
||||||
return Duration.parse(string);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String serialize(final TypeAdapterRegistry registry, final Duration value, final Type type) {
|
|
||||||
return value.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
package ca.spottedleaf.moonrise.common.config.annotation;
|
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
|
||||||
import java.lang.annotation.Retention;
|
|
||||||
import java.lang.annotation.RetentionPolicy;
|
|
||||||
import java.lang.annotation.Target;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Annotation used on a class to indicate that its type adapter may automatically be generated. The class must have
|
|
||||||
* a public no-args constructor.
|
|
||||||
*/
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
@Target(ElementType.TYPE)
|
|
||||||
public @interface Adaptable {
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
package ca.spottedleaf.moonrise.common.config.annotation;
|
|
||||||
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapter;
|
|
||||||
import java.lang.annotation.ElementType;
|
|
||||||
import java.lang.annotation.Retention;
|
|
||||||
import java.lang.annotation.RetentionPolicy;
|
|
||||||
import java.lang.annotation.Target;
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Annotation indicating that a field should be deserialized or serialized from the config.
|
|
||||||
* By default, this annotation is not assumed.
|
|
||||||
*/
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
@Target(ElementType.FIELD)
|
|
||||||
public @interface Serializable {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Indicates whether this field is required to be present in the config. If the field is not present,
|
|
||||||
* and {@code required = true}, then an exception will be thrown during deserialization. If {@code required = false}
|
|
||||||
* and the field is not present, then the field value will remain unmodified.
|
|
||||||
*/
|
|
||||||
public boolean required() default false;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The comment to apply before the element when serializing.
|
|
||||||
*/
|
|
||||||
public String comment() default "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adapter override class. The class must have a public no-args constructor.
|
|
||||||
*/
|
|
||||||
public Class<? extends TypeAdapter> adapter() default TypeAdapter.class;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether to serialize the value to the config.
|
|
||||||
*/
|
|
||||||
public boolean serialize() default true;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* When not empty, this value overrides the auto generated serialized key in the config.
|
|
||||||
*/
|
|
||||||
public String serializedKey() default "";
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,178 +0,0 @@
|
|||||||
package ca.spottedleaf.moonrise.common.config.config;
|
|
||||||
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapterRegistry;
|
|
||||||
import org.yaml.snakeyaml.DumperOptions;
|
|
||||||
import org.yaml.snakeyaml.LoaderOptions;
|
|
||||||
import org.yaml.snakeyaml.Yaml;
|
|
||||||
import org.yaml.snakeyaml.comments.CommentLine;
|
|
||||||
import org.yaml.snakeyaml.comments.CommentType;
|
|
||||||
import org.yaml.snakeyaml.constructor.Constructor;
|
|
||||||
import org.yaml.snakeyaml.nodes.Node;
|
|
||||||
import org.yaml.snakeyaml.representer.Represent;
|
|
||||||
import org.yaml.snakeyaml.representer.Representer;
|
|
||||||
import java.io.BufferedInputStream;
|
|
||||||
import java.io.BufferedOutputStream;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.io.StringReader;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.nio.file.AtomicMoveNotSupportedException;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.StandardCopyOption;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.TreeMap;
|
|
||||||
|
|
||||||
public final class YamlConfig<T> {
|
|
||||||
|
|
||||||
public final TypeAdapterRegistry typeAdapters;
|
|
||||||
|
|
||||||
private final Class<? extends T> clazz;
|
|
||||||
|
|
||||||
public volatile T config;
|
|
||||||
|
|
||||||
private final Yaml yaml;
|
|
||||||
private final LoaderOptions loaderOptions;
|
|
||||||
private final DumperOptions dumperOptions;
|
|
||||||
|
|
||||||
public YamlConfig(final Class<? extends T> clazz, final T dfl) throws Exception {
|
|
||||||
this(clazz, dfl, new TypeAdapterRegistry());
|
|
||||||
}
|
|
||||||
|
|
||||||
public YamlConfig(final Class<? extends T> clazz, final T dfl, final TypeAdapterRegistry registry) throws Exception {
|
|
||||||
this.clazz = clazz;
|
|
||||||
this.config = dfl;
|
|
||||||
this.typeAdapters = registry;
|
|
||||||
this.typeAdapters.makeAdapter(clazz);
|
|
||||||
|
|
||||||
final LoaderOptions loaderOptions = new LoaderOptions();
|
|
||||||
loaderOptions.setProcessComments(true);
|
|
||||||
|
|
||||||
final DumperOptions dumperOptions = new DumperOptions();
|
|
||||||
dumperOptions.setProcessComments(true);
|
|
||||||
dumperOptions.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
|
|
||||||
|
|
||||||
this.loaderOptions = loaderOptions;
|
|
||||||
this.dumperOptions = dumperOptions;
|
|
||||||
this.yaml = new Yaml(new YamlConstructor(loaderOptions), new YamlRepresenter(dumperOptions), dumperOptions, loaderOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void load(final File file) throws IOException {
|
|
||||||
try (final InputStream is = new BufferedInputStream(new FileInputStream(file))) {
|
|
||||||
this.load(is);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void load(final InputStream is) throws IOException {
|
|
||||||
final Object serialized = this.yaml.load(new InputStreamReader(is, StandardCharsets.UTF_8));
|
|
||||||
|
|
||||||
this.config = (T)this.typeAdapters.deserialize(serialized, this.clazz);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void save(final File file) throws IOException {
|
|
||||||
this.save(file, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void save(final File file, final String header) throws IOException {
|
|
||||||
if (file.isDirectory()) {
|
|
||||||
throw new IOException("File is a directory");
|
|
||||||
}
|
|
||||||
|
|
||||||
final File parent = file.getParentFile();
|
|
||||||
if (parent != null) {
|
|
||||||
parent.mkdirs();
|
|
||||||
}
|
|
||||||
|
|
||||||
final File tmp = new File(parent, file.getName() + ".tmp");
|
|
||||||
tmp.delete();
|
|
||||||
tmp.createNewFile();
|
|
||||||
try {
|
|
||||||
try (final OutputStream os = new BufferedOutputStream(new FileOutputStream(tmp))) {
|
|
||||||
this.save(os, header);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
Files.move(tmp.toPath(), file.toPath(), StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.ATOMIC_MOVE);
|
|
||||||
} catch (final AtomicMoveNotSupportedException ex) {
|
|
||||||
Files.move(tmp.toPath(), file.toPath(), StandardCopyOption.REPLACE_EXISTING);
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
tmp.delete();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void save(final OutputStream os) throws IOException {
|
|
||||||
os.write(this.saveToString().getBytes(StandardCharsets.UTF_8));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void save(final OutputStream os, final String header) throws IOException {
|
|
||||||
os.write(this.saveToString(header).getBytes(StandardCharsets.UTF_8));
|
|
||||||
}
|
|
||||||
|
|
||||||
public String saveToString() {
|
|
||||||
return this.yaml.dump(this.typeAdapters.serialize(this.config, this.clazz));
|
|
||||||
}
|
|
||||||
|
|
||||||
public String saveToString(final String header) {
|
|
||||||
if (header.isBlank()) {
|
|
||||||
return this.saveToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
final StringBuilder ret = new StringBuilder();
|
|
||||||
final String lineBreak = this.dumperOptions.getLineBreak().getString();
|
|
||||||
|
|
||||||
for (final String line : header.split("\n")) {
|
|
||||||
ret.append("# ").append(line.trim()).append(lineBreak);
|
|
||||||
}
|
|
||||||
|
|
||||||
ret.append(lineBreak);
|
|
||||||
|
|
||||||
return ret.append(this.saveToString()).toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void callInitialisers() {
|
|
||||||
this.typeAdapters.callInitialisers(this.config);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final class YamlConstructor extends Constructor {
|
|
||||||
|
|
||||||
public YamlConstructor(final LoaderOptions loadingConfig) {
|
|
||||||
super(loadingConfig);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final class YamlRepresenter extends Representer {
|
|
||||||
|
|
||||||
public YamlRepresenter(final DumperOptions options) {
|
|
||||||
super(options);
|
|
||||||
|
|
||||||
this.representers.put(TypeAdapterRegistry.CommentedData.class, new CommentedDataRepresenter());
|
|
||||||
}
|
|
||||||
|
|
||||||
private final class CommentedDataRepresenter implements Represent {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Node representData(final Object data0) {
|
|
||||||
final TypeAdapterRegistry.CommentedData commentedData = (TypeAdapterRegistry.CommentedData)data0;
|
|
||||||
|
|
||||||
final Node node = YamlRepresenter.this.representData(commentedData.data);
|
|
||||||
|
|
||||||
final List<CommentLine> comments = new ArrayList<>();
|
|
||||||
|
|
||||||
for (final String line : commentedData.comment.split("\n")) {
|
|
||||||
comments.add(new CommentLine(null, null, " ".concat(line.trim()), CommentType.BLOCK));
|
|
||||||
}
|
|
||||||
|
|
||||||
node.setBlockComments(comments);
|
|
||||||
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
package ca.spottedleaf.moonrise.common.config.moonrise;
|
package ca.spottedleaf.moonrise.common.config.moonrise;
|
||||||
|
|
||||||
import ca.spottedleaf.moonrise.common.config.InitialiseHook;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.annotation.Adaptable;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.ui.ClothConfig;
|
import ca.spottedleaf.moonrise.common.config.ui.ClothConfig;
|
||||||
import ca.spottedleaf.moonrise.common.config.annotation.Serializable;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.type.Duration;
|
|
||||||
import ca.spottedleaf.moonrise.common.util.MoonriseCommon;
|
import ca.spottedleaf.moonrise.common.util.MoonriseCommon;
|
||||||
import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkTaskScheduler;
|
import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkTaskScheduler;
|
||||||
|
import ca.spottedleaf.yamlconfig.InitialiseHook;
|
||||||
|
import ca.spottedleaf.yamlconfig.annotation.Adaptable;
|
||||||
|
import ca.spottedleaf.yamlconfig.annotation.Serializable;
|
||||||
|
import ca.spottedleaf.yamlconfig.type.Duration;
|
||||||
|
|
||||||
@Adaptable
|
@Adaptable
|
||||||
public final class MoonriseConfig {
|
public final class MoonriseConfig {
|
||||||
@@ -251,4 +251,21 @@ public final class MoonriseConfig {
|
|||||||
)
|
)
|
||||||
public boolean fixMC159283 = false;
|
public boolean fixMC159283 = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
public Misc misc = new Misc();
|
||||||
|
|
||||||
|
@Adaptable
|
||||||
|
public static final class Misc {
|
||||||
|
|
||||||
|
@Serializable(
|
||||||
|
serializedKey = "immediately-close-loading-screen",
|
||||||
|
comment = """
|
||||||
|
Whether the loading screen should be closed immediately when joining servers/SP worlds.
|
||||||
|
This will let you in game faster, but may result in getting in game before enough chunks are
|
||||||
|
loaded for rendering.
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
public boolean immediatelyCloseLoadingScreen = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,38 +0,0 @@
|
|||||||
package ca.spottedleaf.moonrise.common.config.moonrise.adapter;
|
|
||||||
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapter;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapterRegistry;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.moonrise.type.DefaultedValue;
|
|
||||||
import java.lang.reflect.ParameterizedType;
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
|
|
||||||
public final class DefaultedTypeAdapter extends TypeAdapter<DefaultedValue<?>, Object> {
|
|
||||||
|
|
||||||
private static final String DEFAULT_STRING = "default";
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DefaultedValue<?> deserialize(final TypeAdapterRegistry registry, final Object input, final Type type) {
|
|
||||||
if (input instanceof String string && string.equalsIgnoreCase(DEFAULT_STRING)) {
|
|
||||||
return new DefaultedValue<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(type instanceof ParameterizedType parameterizedType)) {
|
|
||||||
throw new IllegalArgumentException("DefaultedValue field must specify generic type");
|
|
||||||
}
|
|
||||||
final Type valueType = parameterizedType.getActualTypeArguments()[0];
|
|
||||||
|
|
||||||
return new DefaultedValue<>(registry.deserialize(input, valueType));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object serialize(final TypeAdapterRegistry registry, final DefaultedValue<?> value, final Type type) {
|
|
||||||
final Object raw = value.getValueRaw();
|
|
||||||
if (raw == null) {
|
|
||||||
return DEFAULT_STRING;
|
|
||||||
}
|
|
||||||
|
|
||||||
final Type valueType = type instanceof ParameterizedType parameterizedType ? parameterizedType.getActualTypeArguments()[0] : null;
|
|
||||||
|
|
||||||
return registry.serialize(raw, valueType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
package ca.spottedleaf.moonrise.common.config.moonrise.type;
|
|
||||||
|
|
||||||
public final class DefaultedValue<T> {
|
|
||||||
|
|
||||||
private final T value;
|
|
||||||
|
|
||||||
public DefaultedValue() {
|
|
||||||
this(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DefaultedValue(final T value) {
|
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public T getValueRaw() {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public T getOrDefault(final T dfl) {
|
|
||||||
return this.value != null ? this.value : dfl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
package ca.spottedleaf.moonrise.common.config.type;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
|
|
||||||
public final class Duration {
|
|
||||||
|
|
||||||
private final String string;
|
|
||||||
private final long timeNS;
|
|
||||||
|
|
||||||
private Duration(final String string, final long timeNS) {
|
|
||||||
this.string = string;
|
|
||||||
this.timeNS = timeNS;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Duration parse(final String value) {
|
|
||||||
if (value.length() < 2) {
|
|
||||||
throw new IllegalArgumentException("Invalid duration: " + value);
|
|
||||||
}
|
|
||||||
|
|
||||||
final char last = value.charAt(value.length() - 1);
|
|
||||||
|
|
||||||
final long multiplier;
|
|
||||||
|
|
||||||
switch (last) {
|
|
||||||
case 's': {
|
|
||||||
multiplier = (1000L * 1000L * 1000L) * 1L;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 't': {
|
|
||||||
multiplier = (1000L * 1000L * 1000L) / 20L;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'm': {
|
|
||||||
multiplier = (1000L * 1000L * 1000L) * 60L;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'h': {
|
|
||||||
multiplier = (1000L * 1000L * 1000L) * 60L * 60L;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'd': {
|
|
||||||
multiplier = (1000L * 1000L * 1000L) * 24L * 60L * 60L;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
throw new IllegalArgumentException("Duration must end with one of: [s, t, m, h, d]");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final BigDecimal parsed = new BigDecimal(value.substring(0, value.length() - 1))
|
|
||||||
.multiply(new BigDecimal(multiplier));
|
|
||||||
|
|
||||||
return new Duration(value, parsed.toBigInteger().longValueExact());
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getTimeNS() {
|
|
||||||
return this.timeNS;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getTimeMS() {
|
|
||||||
return this.timeNS / (1000L * 1000L);
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getTimeS() {
|
|
||||||
return this.timeNS / (1000L * 1000L * 1000L);
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getTimeTicks() {
|
|
||||||
return this.timeNS / ((1000L * 1000L * 1000L) / (20L));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return this.string;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
package ca.spottedleaf.moonrise.common.misc;
|
package ca.spottedleaf.moonrise.common.misc;
|
||||||
|
|
||||||
|
import ca.spottedleaf.moonrise.common.PlatformHooks;
|
||||||
import ca.spottedleaf.moonrise.common.list.ReferenceList;
|
import ca.spottedleaf.moonrise.common.list.ReferenceList;
|
||||||
import ca.spottedleaf.moonrise.common.util.CoordinateUtils;
|
import ca.spottedleaf.moonrise.common.util.CoordinateUtils;
|
||||||
import ca.spottedleaf.moonrise.common.util.MoonriseConstants;
|
import ca.spottedleaf.moonrise.common.util.MoonriseConstants;
|
||||||
import ca.spottedleaf.moonrise.common.util.ChunkSystem;
|
|
||||||
import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemLevel;
|
import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemLevel;
|
||||||
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkData;
|
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkData;
|
||||||
import ca.spottedleaf.moonrise.patches.chunk_tick_iteration.ChunkTickConstants;
|
import ca.spottedleaf.moonrise.patches.chunk_tick_iteration.ChunkTickConstants;
|
||||||
@@ -121,8 +121,8 @@ public final class NearbyPlayers {
|
|||||||
players[NearbyMapType.GENERAL.ordinal()].update(chunk.x, chunk.z, GENERAL_AREA_VIEW_DISTANCE);
|
players[NearbyMapType.GENERAL.ordinal()].update(chunk.x, chunk.z, GENERAL_AREA_VIEW_DISTANCE);
|
||||||
players[NearbyMapType.GENERAL_SMALL.ordinal()].update(chunk.x, chunk.z, GENERAL_SMALL_VIEW_DISTANCE);
|
players[NearbyMapType.GENERAL_SMALL.ordinal()].update(chunk.x, chunk.z, GENERAL_SMALL_VIEW_DISTANCE);
|
||||||
players[NearbyMapType.GENERAL_REALLY_SMALL.ordinal()].update(chunk.x, chunk.z, GENERAL_REALLY_SMALL_VIEW_DISTANCE);
|
players[NearbyMapType.GENERAL_REALLY_SMALL.ordinal()].update(chunk.x, chunk.z, GENERAL_REALLY_SMALL_VIEW_DISTANCE);
|
||||||
players[NearbyMapType.TICK_VIEW_DISTANCE.ordinal()].update(chunk.x, chunk.z, ChunkSystem.getTickViewDistance(player));
|
players[NearbyMapType.TICK_VIEW_DISTANCE.ordinal()].update(chunk.x, chunk.z, PlatformHooks.get().getTickViewDistance(player));
|
||||||
players[NearbyMapType.VIEW_DISTANCE.ordinal()].update(chunk.x, chunk.z, ChunkSystem.getLoadViewDistance(player));
|
players[NearbyMapType.VIEW_DISTANCE.ordinal()].update(chunk.x, chunk.z, PlatformHooks.get().getViewDistance(player));
|
||||||
players[NearbyMapType.SPAWN_RANGE.ordinal()].update(chunk.x, chunk.z, ChunkTickConstants.PLAYER_SPAWN_TRACK_RANGE); // Moonrise - chunk tick iteration
|
players[NearbyMapType.SPAWN_RANGE.ordinal()].update(chunk.x, chunk.z, ChunkTickConstants.PLAYER_SPAWN_TRACK_RANGE); // Moonrise - chunk tick iteration
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package ca.spottedleaf.moonrise.common.misc;
|
|||||||
|
|
||||||
import ca.spottedleaf.concurrentutil.util.IntPairUtil;
|
import ca.spottedleaf.concurrentutil.util.IntPairUtil;
|
||||||
import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap;
|
import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap;
|
||||||
|
import it.unimi.dsi.fastutil.longs.LongSet;
|
||||||
import it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap;
|
import it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap;
|
||||||
import it.unimi.dsi.fastutil.objects.ReferenceSet;
|
import it.unimi.dsi.fastutil.objects.ReferenceSet;
|
||||||
|
|
||||||
@@ -14,6 +15,10 @@ public final class PositionCountingAreaMap<T> {
|
|||||||
return this.counters.keySet();
|
return this.counters.keySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public LongSet getPositions() {
|
||||||
|
return this.positions.keySet();
|
||||||
|
}
|
||||||
|
|
||||||
public int getTotalPositions() {
|
public int getTotalPositions() {
|
||||||
return this.positions.size();
|
return this.positions.size();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,121 +1,125 @@
|
|||||||
package ca.spottedleaf.moonrise.common.util;
|
package ca.spottedleaf.moonrise.common.util;
|
||||||
|
|
||||||
import ca.spottedleaf.concurrentutil.util.Priority;
|
import ca.spottedleaf.concurrentutil.util.Priority;
|
||||||
import ca.spottedleaf.moonrise.common.PlatformHooks;
|
|
||||||
import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel;
|
import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel;
|
||||||
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkSystemLevelChunk;
|
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkSystemLevelChunk;
|
||||||
import ca.spottedleaf.moonrise.patches.chunk_system.player.RegionizedPlayerChunkLoader;
|
import ca.spottedleaf.moonrise.patches.chunk_system.player.RegionizedPlayerChunkLoader;
|
||||||
import ca.spottedleaf.moonrise.patches.chunk_system.world.ChunkSystemServerChunkCache;
|
import ca.spottedleaf.moonrise.patches.chunk_system.world.ChunkSystemServerChunkCache;
|
||||||
import ca.spottedleaf.moonrise.patches.chunk_tick_iteration.ChunkTickServerLevel;
|
import ca.spottedleaf.moonrise.patches.chunk_tick_iteration.ChunkTickServerLevel;
|
||||||
import com.mojang.logging.LogUtils;
|
|
||||||
import net.minecraft.server.level.ChunkHolder;
|
import net.minecraft.server.level.ChunkHolder;
|
||||||
import net.minecraft.server.level.FullChunkStatus;
|
import net.minecraft.server.level.FullChunkStatus;
|
||||||
import net.minecraft.server.level.ServerLevel;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import net.minecraft.server.level.ServerPlayer;
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
import net.minecraft.server.level.progress.ChunkProgressListener;
|
import net.minecraft.server.level.progress.ChunkProgressListener;
|
||||||
import net.minecraft.world.entity.Entity;
|
|
||||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||||
import net.minecraft.world.level.chunk.LevelChunk;
|
import net.minecraft.world.level.chunk.LevelChunk;
|
||||||
import net.minecraft.world.level.chunk.status.ChunkStatus;
|
import net.minecraft.world.level.chunk.status.ChunkStatus;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
public final class ChunkSystem {
|
public abstract class BaseChunkSystemHooks implements ChunkSystemHooks {
|
||||||
|
|
||||||
private static final Logger LOGGER = LogUtils.getLogger();
|
@Override
|
||||||
|
public void scheduleChunkTask(final ServerLevel level, final int chunkX, final int chunkZ, final Runnable run) {
|
||||||
public static void scheduleChunkTask(final ServerLevel level, final int chunkX, final int chunkZ, final Runnable run) {
|
|
||||||
scheduleChunkTask(level, chunkX, chunkZ, run, Priority.NORMAL);
|
scheduleChunkTask(level, chunkX, chunkZ, run, Priority.NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void scheduleChunkTask(final ServerLevel level, final int chunkX, final int chunkZ, final Runnable run, final Priority priority) {
|
@Override
|
||||||
|
public void scheduleChunkTask(final ServerLevel level, final int chunkX, final int chunkZ, final Runnable run, final Priority priority) {
|
||||||
((ChunkSystemServerLevel)level).moonrise$getChunkTaskScheduler().scheduleChunkTask(chunkX, chunkZ, run, priority);
|
((ChunkSystemServerLevel)level).moonrise$getChunkTaskScheduler().scheduleChunkTask(chunkX, chunkZ, run, priority);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void scheduleChunkLoad(final ServerLevel level, final int chunkX, final int chunkZ, final boolean gen,
|
@Override
|
||||||
final ChunkStatus toStatus, final boolean addTicket, final Priority priority,
|
public void scheduleChunkLoad(final ServerLevel level, final int chunkX, final int chunkZ, final boolean gen,
|
||||||
final Consumer<ChunkAccess> onComplete) {
|
final ChunkStatus toStatus, final boolean addTicket, final Priority priority,
|
||||||
|
final Consumer<ChunkAccess> onComplete) {
|
||||||
((ChunkSystemServerLevel)level).moonrise$getChunkTaskScheduler().scheduleChunkLoad(chunkX, chunkZ, gen, toStatus, addTicket, priority, onComplete);
|
((ChunkSystemServerLevel)level).moonrise$getChunkTaskScheduler().scheduleChunkLoad(chunkX, chunkZ, gen, toStatus, addTicket, priority, onComplete);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void scheduleChunkLoad(final ServerLevel level, final int chunkX, final int chunkZ, final ChunkStatus toStatus,
|
@Override
|
||||||
final boolean addTicket, final Priority priority, final Consumer<ChunkAccess> onComplete) {
|
public void scheduleChunkLoad(final ServerLevel level, final int chunkX, final int chunkZ, final ChunkStatus toStatus,
|
||||||
|
final boolean addTicket, final Priority priority, final Consumer<ChunkAccess> onComplete) {
|
||||||
((ChunkSystemServerLevel)level).moonrise$getChunkTaskScheduler().scheduleChunkLoad(chunkX, chunkZ, toStatus, addTicket, priority, onComplete);
|
((ChunkSystemServerLevel)level).moonrise$getChunkTaskScheduler().scheduleChunkLoad(chunkX, chunkZ, toStatus, addTicket, priority, onComplete);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void scheduleTickingState(final ServerLevel level, final int chunkX, final int chunkZ,
|
@Override
|
||||||
final FullChunkStatus toStatus, final boolean addTicket,
|
public void scheduleTickingState(final ServerLevel level, final int chunkX, final int chunkZ,
|
||||||
final Priority priority, final Consumer<LevelChunk> onComplete) {
|
final FullChunkStatus toStatus, final boolean addTicket,
|
||||||
|
final Priority priority, final Consumer<LevelChunk> onComplete) {
|
||||||
((ChunkSystemServerLevel)level).moonrise$getChunkTaskScheduler().scheduleTickingState(chunkX, chunkZ, toStatus, addTicket, priority, onComplete);
|
((ChunkSystemServerLevel)level).moonrise$getChunkTaskScheduler().scheduleTickingState(chunkX, chunkZ, toStatus, addTicket, priority, onComplete);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<ChunkHolder> getVisibleChunkHolders(final ServerLevel level) {
|
@Override
|
||||||
|
public List<ChunkHolder> getVisibleChunkHolders(final ServerLevel level) {
|
||||||
return ((ChunkSystemServerLevel)level).moonrise$getChunkTaskScheduler().chunkHolderManager.getOldChunkHolders();
|
return ((ChunkSystemServerLevel)level).moonrise$getChunkTaskScheduler().chunkHolderManager.getOldChunkHolders();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<ChunkHolder> getUpdatingChunkHolders(final ServerLevel level) {
|
@Override
|
||||||
|
public List<ChunkHolder> getUpdatingChunkHolders(final ServerLevel level) {
|
||||||
return ((ChunkSystemServerLevel)level).moonrise$getChunkTaskScheduler().chunkHolderManager.getOldChunkHolders();
|
return ((ChunkSystemServerLevel)level).moonrise$getChunkTaskScheduler().chunkHolderManager.getOldChunkHolders();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getVisibleChunkHolderCount(final ServerLevel level) {
|
@Override
|
||||||
|
public int getVisibleChunkHolderCount(final ServerLevel level) {
|
||||||
return ((ChunkSystemServerLevel)level).moonrise$getChunkTaskScheduler().chunkHolderManager.size();
|
return ((ChunkSystemServerLevel)level).moonrise$getChunkTaskScheduler().chunkHolderManager.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getUpdatingChunkHolderCount(final ServerLevel level) {
|
@Override
|
||||||
|
public int getUpdatingChunkHolderCount(final ServerLevel level) {
|
||||||
return ((ChunkSystemServerLevel)level).moonrise$getChunkTaskScheduler().chunkHolderManager.size();
|
return ((ChunkSystemServerLevel)level).moonrise$getChunkTaskScheduler().chunkHolderManager.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean hasAnyChunkHolders(final ServerLevel level) {
|
@Override
|
||||||
|
public boolean hasAnyChunkHolders(final ServerLevel level) {
|
||||||
return getUpdatingChunkHolderCount(level) != 0;
|
return getUpdatingChunkHolderCount(level) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean screenEntity(final ServerLevel level, final Entity entity, final boolean fromDisk, final boolean event) {
|
@Override
|
||||||
if (!PlatformHooks.get().screenEntity(level, entity, fromDisk, event)) {
|
public void onChunkHolderCreate(final ServerLevel level, final ChunkHolder holder) {
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void onChunkHolderCreate(final ServerLevel level, final ChunkHolder holder) {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void onChunkHolderDelete(final ServerLevel level, final ChunkHolder holder) {
|
@Override
|
||||||
|
public void onChunkHolderDelete(final ServerLevel level, final ChunkHolder holder) {
|
||||||
// Update progress listener for LevelLoadingScreen
|
// Update progress listener for LevelLoadingScreen
|
||||||
final ChunkProgressListener progressListener = level.getChunkSource().chunkMap.progressListener;
|
final ChunkProgressListener progressListener = level.getChunkSource().chunkMap.progressListener;
|
||||||
if (progressListener != null) {
|
if (progressListener != null) {
|
||||||
ChunkSystem.scheduleChunkTask(level, holder.getPos().x, holder.getPos().z, () -> {
|
this.scheduleChunkTask(level, holder.getPos().x, holder.getPos().z, () -> {
|
||||||
progressListener.onStatusChange(holder.getPos(), null);
|
progressListener.onStatusChange(holder.getPos(), null);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void onChunkPreBorder(final LevelChunk chunk, final ChunkHolder holder) {
|
@Override
|
||||||
|
public void onChunkPreBorder(final LevelChunk chunk, final ChunkHolder holder) {
|
||||||
((ChunkSystemServerChunkCache)((ServerLevel)chunk.getLevel()).getChunkSource())
|
((ChunkSystemServerChunkCache)((ServerLevel)chunk.getLevel()).getChunkSource())
|
||||||
.moonrise$setFullChunk(chunk.getPos().x, chunk.getPos().z, chunk);
|
.moonrise$setFullChunk(chunk.getPos().x, chunk.getPos().z, chunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void onChunkBorder(final LevelChunk chunk, final ChunkHolder holder) {
|
@Override
|
||||||
|
public void onChunkBorder(final LevelChunk chunk, final ChunkHolder holder) {
|
||||||
((ChunkSystemServerLevel)((ServerLevel)chunk.getLevel())).moonrise$getLoadedChunks().add(
|
((ChunkSystemServerLevel)((ServerLevel)chunk.getLevel())).moonrise$getLoadedChunks().add(
|
||||||
((ChunkSystemLevelChunk)chunk).moonrise$getChunkAndHolder()
|
((ChunkSystemLevelChunk)chunk).moonrise$getChunkAndHolder()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void onChunkNotBorder(final LevelChunk chunk, final ChunkHolder holder) {
|
@Override
|
||||||
|
public void onChunkNotBorder(final LevelChunk chunk, final ChunkHolder holder) {
|
||||||
((ChunkSystemServerLevel)((ServerLevel)chunk.getLevel())).moonrise$getLoadedChunks().remove(
|
((ChunkSystemServerLevel)((ServerLevel)chunk.getLevel())).moonrise$getLoadedChunks().remove(
|
||||||
((ChunkSystemLevelChunk)chunk).moonrise$getChunkAndHolder()
|
((ChunkSystemLevelChunk)chunk).moonrise$getChunkAndHolder()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void onChunkPostNotBorder(final LevelChunk chunk, final ChunkHolder holder) {
|
@Override
|
||||||
|
public void onChunkPostNotBorder(final LevelChunk chunk, final ChunkHolder holder) {
|
||||||
((ChunkSystemServerChunkCache)((ServerLevel)chunk.getLevel()).getChunkSource())
|
((ChunkSystemServerChunkCache)((ServerLevel)chunk.getLevel()).getChunkSource())
|
||||||
.moonrise$setFullChunk(chunk.getPos().x, chunk.getPos().z, null);
|
.moonrise$setFullChunk(chunk.getPos().x, chunk.getPos().z, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void onChunkTicking(final LevelChunk chunk, final ChunkHolder holder) {
|
@Override
|
||||||
|
public void onChunkTicking(final LevelChunk chunk, final ChunkHolder holder) {
|
||||||
((ChunkSystemServerLevel)((ServerLevel)chunk.getLevel())).moonrise$getTickingChunks().add(
|
((ChunkSystemServerLevel)((ServerLevel)chunk.getLevel())).moonrise$getTickingChunks().add(
|
||||||
((ChunkSystemLevelChunk)chunk).moonrise$getChunkAndHolder()
|
((ChunkSystemLevelChunk)chunk).moonrise$getChunkAndHolder()
|
||||||
);
|
);
|
||||||
if (!((ChunkSystemLevelChunk)chunk).moonrise$isPostProcessingDone()) {
|
if (!((ChunkSystemLevelChunk)chunk).moonrise$isPostProcessingDone()) {
|
||||||
chunk.postProcessGeneration((ServerLevel)chunk.getLevel());
|
chunk.postProcessGeneration((ServerLevel)chunk.getLevel());
|
||||||
@@ -125,52 +129,60 @@ public final class ChunkSystem {
|
|||||||
((ChunkTickServerLevel)(ServerLevel)chunk.getLevel()).moonrise$markChunkForPlayerTicking(chunk); // Moonrise - chunk tick iteration
|
((ChunkTickServerLevel)(ServerLevel)chunk.getLevel()).moonrise$markChunkForPlayerTicking(chunk); // Moonrise - chunk tick iteration
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void onChunkNotTicking(final LevelChunk chunk, final ChunkHolder holder) {
|
@Override
|
||||||
|
public void onChunkNotTicking(final LevelChunk chunk, final ChunkHolder holder) {
|
||||||
((ChunkSystemServerLevel)((ServerLevel)chunk.getLevel())).moonrise$getTickingChunks().remove(
|
((ChunkSystemServerLevel)((ServerLevel)chunk.getLevel())).moonrise$getTickingChunks().remove(
|
||||||
((ChunkSystemLevelChunk)chunk).moonrise$getChunkAndHolder()
|
((ChunkSystemLevelChunk)chunk).moonrise$getChunkAndHolder()
|
||||||
);
|
);
|
||||||
((ChunkTickServerLevel)(ServerLevel)chunk.getLevel()).moonrise$removeChunkForPlayerTicking(chunk); // Moonrise - chunk tick iteration
|
((ChunkTickServerLevel)(ServerLevel)chunk.getLevel()).moonrise$removeChunkForPlayerTicking(chunk); // Moonrise - chunk tick iteration
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void onChunkEntityTicking(final LevelChunk chunk, final ChunkHolder holder) {
|
@Override
|
||||||
|
public void onChunkEntityTicking(final LevelChunk chunk, final ChunkHolder holder) {
|
||||||
((ChunkSystemServerLevel)((ServerLevel)chunk.getLevel())).moonrise$getEntityTickingChunks().add(
|
((ChunkSystemServerLevel)((ServerLevel)chunk.getLevel())).moonrise$getEntityTickingChunks().add(
|
||||||
((ChunkSystemLevelChunk)chunk).moonrise$getChunkAndHolder()
|
((ChunkSystemLevelChunk)chunk).moonrise$getChunkAndHolder()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void onChunkNotEntityTicking(final LevelChunk chunk, final ChunkHolder holder) {
|
@Override
|
||||||
|
public void onChunkNotEntityTicking(final LevelChunk chunk, final ChunkHolder holder) {
|
||||||
((ChunkSystemServerLevel)((ServerLevel)chunk.getLevel())).moonrise$getEntityTickingChunks().remove(
|
((ChunkSystemServerLevel)((ServerLevel)chunk.getLevel())).moonrise$getEntityTickingChunks().remove(
|
||||||
((ChunkSystemLevelChunk)chunk).moonrise$getChunkAndHolder()
|
((ChunkSystemLevelChunk)chunk).moonrise$getChunkAndHolder()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ChunkHolder getUnloadingChunkHolder(final ServerLevel level, final int chunkX, final int chunkZ) {
|
@Override
|
||||||
|
public ChunkHolder getUnloadingChunkHolder(final ServerLevel level, final int chunkX, final int chunkZ) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getSendViewDistance(final ServerPlayer player) {
|
@Override
|
||||||
|
public int getSendViewDistance(final ServerPlayer player) {
|
||||||
return RegionizedPlayerChunkLoader.getAPISendViewDistance(player);
|
return RegionizedPlayerChunkLoader.getAPISendViewDistance(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getLoadViewDistance(final ServerPlayer player) {
|
@Override
|
||||||
return RegionizedPlayerChunkLoader.getLoadViewDistance(player);
|
public int getViewDistance(final ServerPlayer player) {
|
||||||
|
return RegionizedPlayerChunkLoader.getAPIViewDistance(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getTickViewDistance(final ServerPlayer player) {
|
@Override
|
||||||
|
public int getTickViewDistance(final ServerPlayer player) {
|
||||||
return RegionizedPlayerChunkLoader.getAPITickViewDistance(player);
|
return RegionizedPlayerChunkLoader.getAPITickViewDistance(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void addPlayerToDistanceMaps(final ServerLevel world, final ServerPlayer player) {
|
@Override
|
||||||
|
public void addPlayerToDistanceMaps(final ServerLevel world, final ServerPlayer player) {
|
||||||
((ChunkSystemServerLevel)world).moonrise$getPlayerChunkLoader().addPlayer(player);
|
((ChunkSystemServerLevel)world).moonrise$getPlayerChunkLoader().addPlayer(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void removePlayerFromDistanceMaps(final ServerLevel world, final ServerPlayer player) {
|
@Override
|
||||||
|
public void removePlayerFromDistanceMaps(final ServerLevel world, final ServerPlayer player) {
|
||||||
((ChunkSystemServerLevel)world).moonrise$getPlayerChunkLoader().removePlayer(player);
|
((ChunkSystemServerLevel)world).moonrise$getPlayerChunkLoader().removePlayer(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void updateMaps(final ServerLevel world, final ServerPlayer player) {
|
@Override
|
||||||
|
public void updateMaps(final ServerLevel world, final ServerPlayer player) {
|
||||||
((ChunkSystemServerLevel)world).moonrise$getPlayerChunkLoader().updatePlayer(player);
|
((ChunkSystemServerLevel)world).moonrise$getPlayerChunkLoader().updatePlayer(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ChunkSystem() {}
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
package ca.spottedleaf.moonrise.common.util;
|
||||||
|
|
||||||
|
import ca.spottedleaf.concurrentutil.util.Priority;
|
||||||
|
import net.minecraft.server.level.ChunkHolder;
|
||||||
|
import net.minecraft.server.level.FullChunkStatus;
|
||||||
|
import net.minecraft.server.level.ServerLevel;
|
||||||
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
|
import net.minecraft.world.entity.Entity;
|
||||||
|
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||||
|
import net.minecraft.world.level.chunk.LevelChunk;
|
||||||
|
import net.minecraft.world.level.chunk.status.ChunkStatus;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
public interface ChunkSystemHooks {
|
||||||
|
|
||||||
|
public void scheduleChunkTask(final ServerLevel level, final int chunkX, final int chunkZ, final Runnable run);
|
||||||
|
|
||||||
|
public void scheduleChunkTask(final ServerLevel level, final int chunkX, final int chunkZ, final Runnable run, final Priority priority);
|
||||||
|
|
||||||
|
public void scheduleChunkLoad(final ServerLevel level, final int chunkX, final int chunkZ, final boolean gen,
|
||||||
|
final ChunkStatus toStatus, final boolean addTicket, final Priority priority,
|
||||||
|
final Consumer<ChunkAccess> onComplete);
|
||||||
|
|
||||||
|
public void scheduleChunkLoad(final ServerLevel level, final int chunkX, final int chunkZ, final ChunkStatus toStatus,
|
||||||
|
final boolean addTicket, final Priority priority, final Consumer<ChunkAccess> onComplete);
|
||||||
|
|
||||||
|
public void scheduleTickingState(final ServerLevel level, final int chunkX, final int chunkZ,
|
||||||
|
final FullChunkStatus toStatus, final boolean addTicket,
|
||||||
|
final Priority priority, final Consumer<LevelChunk> onComplete);
|
||||||
|
|
||||||
|
public List<ChunkHolder> getVisibleChunkHolders(final ServerLevel level);
|
||||||
|
|
||||||
|
public List<ChunkHolder> getUpdatingChunkHolders(final ServerLevel level);
|
||||||
|
|
||||||
|
public int getVisibleChunkHolderCount(final ServerLevel level);
|
||||||
|
|
||||||
|
public int getUpdatingChunkHolderCount(final ServerLevel level);
|
||||||
|
|
||||||
|
public boolean hasAnyChunkHolders(final ServerLevel level);
|
||||||
|
|
||||||
|
public boolean screenEntity(final ServerLevel level, final Entity entity, final boolean fromDisk, final boolean event);
|
||||||
|
|
||||||
|
public void onChunkHolderCreate(final ServerLevel level, final ChunkHolder holder);
|
||||||
|
|
||||||
|
public void onChunkHolderDelete(final ServerLevel level, final ChunkHolder holder);
|
||||||
|
|
||||||
|
public void onChunkPreBorder(final LevelChunk chunk, final ChunkHolder holder);
|
||||||
|
|
||||||
|
public void onChunkBorder(final LevelChunk chunk, final ChunkHolder holder);
|
||||||
|
|
||||||
|
public void onChunkNotBorder(final LevelChunk chunk, final ChunkHolder holder);
|
||||||
|
|
||||||
|
public void onChunkPostNotBorder(final LevelChunk chunk, final ChunkHolder holder);
|
||||||
|
|
||||||
|
public void onChunkTicking(final LevelChunk chunk, final ChunkHolder holder);
|
||||||
|
|
||||||
|
public void onChunkNotTicking(final LevelChunk chunk, final ChunkHolder holder);
|
||||||
|
|
||||||
|
public void onChunkEntityTicking(final LevelChunk chunk, final ChunkHolder holder);
|
||||||
|
|
||||||
|
public void onChunkNotEntityTicking(final LevelChunk chunk, final ChunkHolder holder);
|
||||||
|
|
||||||
|
public ChunkHolder getUnloadingChunkHolder(final ServerLevel level, final int chunkX, final int chunkZ);
|
||||||
|
|
||||||
|
public int getSendViewDistance(final ServerPlayer player);
|
||||||
|
|
||||||
|
public int getViewDistance(final ServerPlayer player);
|
||||||
|
|
||||||
|
public int getTickViewDistance(final ServerPlayer player);
|
||||||
|
|
||||||
|
public void addPlayerToDistanceMaps(final ServerLevel world, final ServerPlayer player);
|
||||||
|
|
||||||
|
public void removePlayerFromDistanceMaps(final ServerLevel world, final ServerPlayer player);
|
||||||
|
|
||||||
|
public void updateMaps(final ServerLevel world, final ServerPlayer player);
|
||||||
|
}
|
||||||
@@ -1,11 +1,9 @@
|
|||||||
package ca.spottedleaf.moonrise.common.util;
|
package ca.spottedleaf.moonrise.common.util;
|
||||||
|
|
||||||
import ca.spottedleaf.moonrise.common.PlatformHooks;
|
import ca.spottedleaf.moonrise.common.PlatformHooks;
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapterRegistry;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.config.YamlConfig;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.moonrise.MoonriseConfig;
|
import ca.spottedleaf.moonrise.common.config.moonrise.MoonriseConfig;
|
||||||
import ca.spottedleaf.moonrise.common.config.moonrise.adapter.DefaultedTypeAdapter;
|
import ca.spottedleaf.yamlconfig.adapter.TypeAdapterRegistry;
|
||||||
import ca.spottedleaf.moonrise.common.config.moonrise.type.DefaultedValue;
|
import ca.spottedleaf.yamlconfig.config.YamlConfig;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@@ -18,8 +16,6 @@ public final class ConfigHolder {
|
|||||||
private static final TypeAdapterRegistry CONFIG_ADAPTERS = new TypeAdapterRegistry();
|
private static final TypeAdapterRegistry CONFIG_ADAPTERS = new TypeAdapterRegistry();
|
||||||
private static final YamlConfig<MoonriseConfig> CONFIG;
|
private static final YamlConfig<MoonriseConfig> CONFIG;
|
||||||
static {
|
static {
|
||||||
CONFIG_ADAPTERS.putAdapter(DefaultedValue.class, new DefaultedTypeAdapter());
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
CONFIG = new YamlConfig<>(MoonriseConfig.class, new MoonriseConfig(), CONFIG_ADAPTERS);
|
CONFIG = new YamlConfig<>(MoonriseConfig.class, new MoonriseConfig(), CONFIG_ADAPTERS);
|
||||||
} catch (final Exception ex) {
|
} catch (final Exception ex) {
|
||||||
@@ -52,14 +48,6 @@ public final class ConfigHolder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static boolean reloadConfig() {
|
public static boolean reloadConfig() {
|
||||||
final boolean ret = reloadConfig0();
|
|
||||||
|
|
||||||
CONFIG.callInitialisers();
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean reloadConfig0() {
|
|
||||||
synchronized (CONFIG) {
|
synchronized (CONFIG) {
|
||||||
if (CONFIG_FILE.exists()) {
|
if (CONFIG_FILE.exists()) {
|
||||||
try {
|
try {
|
||||||
@@ -70,6 +58,8 @@ public final class ConfigHolder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CONFIG.callInitialisers();
|
||||||
|
|
||||||
// write back any changes, or create if needed
|
// write back any changes, or create if needed
|
||||||
return saveConfig();
|
return saveConfig();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package ca.spottedleaf.moonrise.common.util;
|
package ca.spottedleaf.moonrise.common.util;
|
||||||
|
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.Strictness;
|
||||||
import com.google.gson.internal.Streams;
|
import com.google.gson.internal.Streams;
|
||||||
import com.google.gson.stream.JsonWriter;
|
import com.google.gson.stream.JsonWriter;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@@ -16,7 +17,7 @@ public final class JsonUtil {
|
|||||||
final StringWriter stringWriter = new StringWriter();
|
final StringWriter stringWriter = new StringWriter();
|
||||||
final JsonWriter jsonWriter = new JsonWriter(stringWriter);
|
final JsonWriter jsonWriter = new JsonWriter(stringWriter);
|
||||||
jsonWriter.setIndent(" ");
|
jsonWriter.setIndent(" ");
|
||||||
jsonWriter.setLenient(false);
|
jsonWriter.setStrictness(Strictness.LENIENT);
|
||||||
Streams.write(element, jsonWriter);
|
Streams.write(element, jsonWriter);
|
||||||
|
|
||||||
final String jsonString = stringWriter.toString();
|
final String jsonString = stringWriter.toString();
|
||||||
|
|||||||
@@ -1,52 +0,0 @@
|
|||||||
package ca.spottedleaf.moonrise.common.util;
|
|
||||||
|
|
||||||
import net.minecraft.world.level.levelgen.LegacyRandomSource;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Avoid costly CAS of superclass
|
|
||||||
*/
|
|
||||||
public final class SimpleRandom extends LegacyRandomSource {
|
|
||||||
|
|
||||||
private static final long MULTIPLIER = 25214903917L;
|
|
||||||
private static final long ADDEND = 11L;
|
|
||||||
private static final int BITS = 48;
|
|
||||||
private static final long MASK = (1L << BITS) - 1;
|
|
||||||
|
|
||||||
private long value;
|
|
||||||
|
|
||||||
public SimpleRandom(final long seed) {
|
|
||||||
super(0L);
|
|
||||||
this.value = seed;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setSeed(final long seed) {
|
|
||||||
this.value = (seed ^ MULTIPLIER) & MASK;
|
|
||||||
}
|
|
||||||
|
|
||||||
private long advanceSeed() {
|
|
||||||
return this.value = ((this.value * MULTIPLIER) + ADDEND) & MASK;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int next(final int bits) {
|
|
||||||
return (int)(this.advanceSeed() >>> (BITS - bits));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int nextInt() {
|
|
||||||
final long seed = this.advanceSeed();
|
|
||||||
return (int)(seed >>> (BITS - Integer.SIZE));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int nextInt(final int bound) {
|
|
||||||
if (bound <= 0) {
|
|
||||||
throw new IllegalArgumentException();
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/
|
|
||||||
final long value = this.advanceSeed() >>> (BITS - Integer.SIZE);
|
|
||||||
return (int)((value * (long)bound) >>> Integer.SIZE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
package ca.spottedleaf.moonrise.common.util;
|
||||||
|
|
||||||
|
import net.minecraft.util.Mth;
|
||||||
|
import net.minecraft.util.RandomSource;
|
||||||
|
import net.minecraft.world.level.levelgen.BitRandomSource;
|
||||||
|
import net.minecraft.world.level.levelgen.MarsagliaPolarGaussian;
|
||||||
|
import net.minecraft.world.level.levelgen.PositionalRandomFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Avoid costly CAS of superclass + division in nextInt
|
||||||
|
*/
|
||||||
|
public final class SimpleThreadUnsafeRandom implements BitRandomSource {
|
||||||
|
|
||||||
|
private static final long MULTIPLIER = 25214903917L;
|
||||||
|
private static final long ADDEND = 11L;
|
||||||
|
private static final int BITS = 48;
|
||||||
|
private static final long MASK = (1L << BITS) - 1L;
|
||||||
|
|
||||||
|
private long value;
|
||||||
|
private final MarsagliaPolarGaussian gaussianSource = new MarsagliaPolarGaussian(this);
|
||||||
|
|
||||||
|
public SimpleThreadUnsafeRandom(final long seed) {
|
||||||
|
this.setSeed(seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSeed(final long seed) {
|
||||||
|
this.value = (seed ^ MULTIPLIER) & MASK;
|
||||||
|
this.gaussianSource.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
private long advanceSeed() {
|
||||||
|
return this.value = ((this.value * MULTIPLIER) + ADDEND) & MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int next(final int bits) {
|
||||||
|
return (int)(this.advanceSeed() >>> (BITS - bits));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int nextInt() {
|
||||||
|
final long seed = this.advanceSeed();
|
||||||
|
return (int)(seed >>> (BITS - Integer.SIZE));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int nextInt(final int bound) {
|
||||||
|
if (bound <= 0) {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/
|
||||||
|
final long value = this.advanceSeed() >>> (BITS - Integer.SIZE);
|
||||||
|
return (int)((value * (long)bound) >>> Integer.SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double nextGaussian() {
|
||||||
|
return this.gaussianSource.nextGaussian();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RandomSource fork() {
|
||||||
|
return new SimpleThreadUnsafeRandom(this.nextLong());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PositionalRandomFactory forkPositional() {
|
||||||
|
return new SimpleRandomPositionalFactory(this.nextLong());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class SimpleRandomPositionalFactory implements PositionalRandomFactory {
|
||||||
|
|
||||||
|
private final long seed;
|
||||||
|
|
||||||
|
public SimpleRandomPositionalFactory(final long seed) {
|
||||||
|
this.seed = seed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getSeed() {
|
||||||
|
return this.seed;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RandomSource fromHashOf(final String string) {
|
||||||
|
return new SimpleThreadUnsafeRandom((long)string.hashCode() ^ this.seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RandomSource fromSeed(final long seed) {
|
||||||
|
return new SimpleThreadUnsafeRandom(seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RandomSource at(final int x, final int y, final int z) {
|
||||||
|
return new SimpleThreadUnsafeRandom(Mth.getSeed(x, y, z) ^ this.seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void parityConfigString(final StringBuilder stringBuilder) {
|
||||||
|
stringBuilder.append("SimpleRandomPositionalFactory{").append(this.seed).append('}');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
package ca.spottedleaf.moonrise.common.util;
|
||||||
|
|
||||||
|
import net.minecraft.util.Mth;
|
||||||
|
import net.minecraft.util.RandomSource;
|
||||||
|
import net.minecraft.world.level.levelgen.BitRandomSource;
|
||||||
|
import net.minecraft.world.level.levelgen.MarsagliaPolarGaussian;
|
||||||
|
import net.minecraft.world.level.levelgen.PositionalRandomFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Avoid costly CAS of superclass
|
||||||
|
*/
|
||||||
|
public final class ThreadUnsafeRandom implements BitRandomSource {
|
||||||
|
|
||||||
|
private static final long MULTIPLIER = 25214903917L;
|
||||||
|
private static final long ADDEND = 11L;
|
||||||
|
private static final int BITS = 48;
|
||||||
|
private static final long MASK = (1L << BITS) - 1L;
|
||||||
|
|
||||||
|
private long value;
|
||||||
|
private final MarsagliaPolarGaussian gaussianSource = new MarsagliaPolarGaussian(this);
|
||||||
|
|
||||||
|
public ThreadUnsafeRandom(final long seed) {
|
||||||
|
this.setSeed(seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSeed(final long seed) {
|
||||||
|
this.value = (seed ^ MULTIPLIER) & MASK;
|
||||||
|
this.gaussianSource.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
private long advanceSeed() {
|
||||||
|
return this.value = ((this.value * MULTIPLIER) + ADDEND) & MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int next(final int bits) {
|
||||||
|
return (int)(this.advanceSeed() >>> (BITS - bits));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int nextInt() {
|
||||||
|
final long seed = this.advanceSeed();
|
||||||
|
return (int)(seed >>> (BITS - Integer.SIZE));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double nextGaussian() {
|
||||||
|
return this.gaussianSource.nextGaussian();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RandomSource fork() {
|
||||||
|
return new ThreadUnsafeRandom(this.nextLong());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PositionalRandomFactory forkPositional() {
|
||||||
|
return new ThreadUnsafeRandomPositionalFactory(this.nextLong());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class ThreadUnsafeRandomPositionalFactory implements PositionalRandomFactory {
|
||||||
|
|
||||||
|
private final long seed;
|
||||||
|
|
||||||
|
public ThreadUnsafeRandomPositionalFactory(final long seed) {
|
||||||
|
this.seed = seed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getSeed() {
|
||||||
|
return this.seed;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RandomSource fromHashOf(final String string) {
|
||||||
|
return new ThreadUnsafeRandom((long)string.hashCode() ^ this.seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RandomSource fromSeed(final long seed) {
|
||||||
|
return new ThreadUnsafeRandom(seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RandomSource at(final int x, final int y, final int z) {
|
||||||
|
return new ThreadUnsafeRandom(Mth.getSeed(x, y, z) ^ this.seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void parityConfigString(final StringBuilder stringBuilder) {
|
||||||
|
stringBuilder.append("ThreadUnsafeRandomPositionalFactory{").append(this.seed).append('}');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
package ca.spottedleaf.moonrise.mixin.chunk_system;
|
package ca.spottedleaf.moonrise.mixin.chunk_system;
|
||||||
|
|
||||||
|
import ca.spottedleaf.moonrise.common.PlatformHooks;
|
||||||
import ca.spottedleaf.moonrise.common.util.MoonriseConstants;
|
import ca.spottedleaf.moonrise.common.util.MoonriseConstants;
|
||||||
import ca.spottedleaf.moonrise.common.util.ChunkSystem;
|
|
||||||
import ca.spottedleaf.moonrise.patches.chunk_system.io.MoonriseRegionFileIO;
|
import ca.spottedleaf.moonrise.patches.chunk_system.io.MoonriseRegionFileIO;
|
||||||
import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemChunkMap;
|
import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemChunkMap;
|
||||||
import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel;
|
import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel;
|
||||||
@@ -499,7 +499,7 @@ abstract class ChunkMapMixin extends ChunkStorage implements ChunkSystemChunkMap
|
|||||||
*/
|
*/
|
||||||
@Overwrite
|
@Overwrite
|
||||||
public int getPlayerViewDistance(final ServerPlayer player) {
|
public int getPlayerViewDistance(final ServerPlayer player) {
|
||||||
return ChunkSystem.getSendViewDistance(player);
|
return PlatformHooks.get().getSendViewDistance(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -538,6 +538,21 @@ abstract class ChunkMapMixin extends ChunkStorage implements ChunkSystemChunkMap
|
|||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @reason Route to new chunk system
|
||||||
|
* @author Spottedleaf
|
||||||
|
*/
|
||||||
|
@Redirect(
|
||||||
|
method = "forEachSpawnCandidateChunk",
|
||||||
|
at = @At(
|
||||||
|
value = "INVOKE",
|
||||||
|
target = "Lit/unimi/dsi/fastutil/longs/Long2ObjectLinkedOpenHashMap;get(J)Ljava/lang/Object;"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
private <V> V redirectChunkHolderGet(final Long2ObjectLinkedOpenHashMap<V> instance, final long key) {
|
||||||
|
return (V)this.getVisibleChunkIfPresent(key);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<Optional<CompoundTag>> read(final ChunkPos pos) {
|
public CompletableFuture<Optional<CompoundTag>> read(final ChunkPos pos) {
|
||||||
final CompletableFuture<Optional<CompoundTag>> ret = new CompletableFuture<>();
|
final CompletableFuture<Optional<CompoundTag>> ret = new CompletableFuture<>();
|
||||||
@@ -582,7 +597,7 @@ abstract class ChunkMapMixin extends ChunkStorage implements ChunkSystemChunkMap
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
private void avoidUpdateChunkTrackingInUpdate(final ChunkMap instance, final ServerPlayer serverPlayer) {
|
private void avoidUpdateChunkTrackingInUpdate(final ChunkMap instance, final ServerPlayer serverPlayer) {
|
||||||
ChunkSystem.addPlayerToDistanceMaps(this.level, serverPlayer);
|
PlatformHooks.get().addPlayerToDistanceMaps(this.level, serverPlayer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -612,7 +627,7 @@ abstract class ChunkMapMixin extends ChunkStorage implements ChunkSystemChunkMap
|
|||||||
)
|
)
|
||||||
private void avoidApplyChunkTrackingViewInUpdate(final ChunkMap instance, final ServerPlayer serverPlayer,
|
private void avoidApplyChunkTrackingViewInUpdate(final ChunkMap instance, final ServerPlayer serverPlayer,
|
||||||
final ChunkTrackingView chunkTrackingView) {
|
final ChunkTrackingView chunkTrackingView) {
|
||||||
ChunkSystem.removePlayerFromDistanceMaps(this.level, serverPlayer);
|
PlatformHooks.get().removePlayerFromDistanceMaps(this.level, serverPlayer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -626,7 +641,7 @@ abstract class ChunkMapMixin extends ChunkStorage implements ChunkSystemChunkMap
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
private void updateMapsHook(final ServerPlayer player, final CallbackInfo ci) {
|
private void updateMapsHook(final ServerPlayer player, final CallbackInfo ci) {
|
||||||
ChunkSystem.updateMaps(this.level, player);
|
PlatformHooks.get().updateMaps(this.level, player);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package ca.spottedleaf.moonrise.mixin.chunk_system;
|
package ca.spottedleaf.moonrise.mixin.chunk_system;
|
||||||
|
|
||||||
|
import ca.spottedleaf.moonrise.common.util.MoonriseConstants;
|
||||||
import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel;
|
import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel;
|
||||||
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkSystemDistanceManager;
|
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkSystemDistanceManager;
|
||||||
import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkHolderManager;
|
import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkHolderManager;
|
||||||
@@ -13,6 +14,7 @@ import net.minecraft.server.level.ThrottlingChunkTaskDispatcher;
|
|||||||
import net.minecraft.server.level.Ticket;
|
import net.minecraft.server.level.Ticket;
|
||||||
import net.minecraft.server.level.TicketType;
|
import net.minecraft.server.level.TicketType;
|
||||||
import net.minecraft.server.level.TickingTracker;
|
import net.minecraft.server.level.TickingTracker;
|
||||||
|
import net.minecraft.util.Mth;
|
||||||
import net.minecraft.util.SortedArraySet;
|
import net.minecraft.util.SortedArraySet;
|
||||||
import net.minecraft.world.level.ChunkPos;
|
import net.minecraft.world.level.ChunkPos;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
@@ -285,7 +287,10 @@ abstract class DistanceManagerMixin implements ChunkSystemDistanceManager {
|
|||||||
*/
|
*/
|
||||||
@Overwrite
|
@Overwrite
|
||||||
public void updateSimulationDistance(final int simulationDistance) {
|
public void updateSimulationDistance(final int simulationDistance) {
|
||||||
((ChunkSystemServerLevel)this.moonrise$getChunkMap().level).moonrise$getPlayerChunkLoader().setTickDistance(simulationDistance);
|
// note: vanilla does not clamp to 0, but we do simply because we need a min of 0
|
||||||
|
final int clamped = Mth.clamp(simulationDistance, 0, MoonriseConstants.MAX_VIEW_DISTANCE);
|
||||||
|
|
||||||
|
((ChunkSystemServerLevel)this.moonrise$getChunkMap().level).moonrise$getPlayerChunkLoader().setTickDistance(clamped);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -315,6 +320,15 @@ abstract class DistanceManagerMixin implements ChunkSystemDistanceManager {
|
|||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @reason Remove old chunk system hooks
|
||||||
|
* @author Spottedleaf
|
||||||
|
*/
|
||||||
|
@Overwrite
|
||||||
|
public LongSet getTickingChunks() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @reason This hack is not required anymore, see {@link MinecraftServerMixin}
|
* @reason This hack is not required anymore, see {@link MinecraftServerMixin}
|
||||||
* @author Spottedleaf
|
* @author Spottedleaf
|
||||||
|
|||||||
@@ -43,4 +43,17 @@ abstract class PlayerListMixin {
|
|||||||
)
|
)
|
||||||
private void doNotAdjustVD(final PlayerList instance, final Packet<?> packet) {}
|
private void doNotAdjustVD(final PlayerList instance, final Packet<?> packet) {}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @reason The RegionizedPlayerChunkLoader will handle the SD packet
|
||||||
|
* @author Spottedleaf
|
||||||
|
*/
|
||||||
|
@Redirect(
|
||||||
|
method = "setSimulationDistance",
|
||||||
|
at = @At(
|
||||||
|
value = "INVOKE",
|
||||||
|
target = "Lnet/minecraft/server/players/PlayerList;broadcastAll(Lnet/minecraft/network/protocol/Packet;)V"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
private void doNotAdjustSD(final PlayerList instance, final Packet<?> packet) {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -266,20 +266,4 @@ public abstract class PoiManagerMixin extends SectionStorage<Object, Object> imp
|
|||||||
private <T> Stream<T> skipLoadedSet(final Stream<T> instance, final Predicate<? super T> predicate) {
|
private <T> Stream<T> skipLoadedSet(final Stream<T> instance, final Predicate<? super T> predicate) {
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void moonrise$close() throws IOException {}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final CompoundTag moonrise$read(final int chunkX, final int chunkZ) throws IOException {
|
|
||||||
return MoonriseRegionFileIO.loadData(
|
|
||||||
this.world, chunkX, chunkZ, MoonriseRegionFileIO.RegionFileType.POI_DATA,
|
|
||||||
MoonriseRegionFileIO.getIOBlockingPriorityForCurrentThread()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void moonrise$write(final int chunkX, final int chunkZ, final CompoundTag data) throws IOException {
|
|
||||||
MoonriseRegionFileIO.scheduleSave(this.world, chunkX, chunkZ, data, MoonriseRegionFileIO.RegionFileType.POI_DATA);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,10 +26,6 @@ abstract class SectionStorageMixin<R, P> implements ChunkSystemSectionStorage, A
|
|||||||
@Shadow
|
@Shadow
|
||||||
private SimpleRegionStorage simpleRegionStorage;
|
private SimpleRegionStorage simpleRegionStorage;
|
||||||
|
|
||||||
@Shadow
|
|
||||||
@Final
|
|
||||||
static Logger LOGGER;
|
|
||||||
|
|
||||||
|
|
||||||
@Unique
|
@Unique
|
||||||
private RegionFileStorage storage;
|
private RegionFileStorage storage;
|
||||||
@@ -39,6 +35,9 @@ abstract class SectionStorageMixin<R, P> implements ChunkSystemSectionStorage, A
|
|||||||
return this.storage;
|
return this.storage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void moonrise$close() throws IOException {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @reason Retrieve storage from IOWorker, and then nuke it
|
* @reason Retrieve storage from IOWorker, and then nuke it
|
||||||
* @author Spottedleaf
|
* @author Spottedleaf
|
||||||
@@ -59,12 +58,8 @@ abstract class SectionStorageMixin<R, P> implements ChunkSystemSectionStorage, A
|
|||||||
* @author Spottedleaf
|
* @author Spottedleaf
|
||||||
*/
|
*/
|
||||||
@Overwrite
|
@Overwrite
|
||||||
public final CompletableFuture<Optional<CompoundTag>> tryRead(final ChunkPos pos) {
|
public final CompletableFuture<Optional<SectionStorage.PackedChunk<P>>> tryRead(final ChunkPos pos) {
|
||||||
try {
|
throw new IllegalStateException("Only chunk system can write state, offending class:" + this.getClass().getName());
|
||||||
return CompletableFuture.completedFuture(Optional.ofNullable(this.moonrise$read(pos.x, pos.z)));
|
|
||||||
} catch (final Throwable thr) {
|
|
||||||
return CompletableFuture.failedFuture(thr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -77,24 +72,12 @@ abstract class SectionStorageMixin<R, P> implements ChunkSystemSectionStorage, A
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @reason Route to new chunk system hook
|
* @reason Destroy old chunk system hook
|
||||||
* @author Spottedleaf
|
* @author Spottedleaf
|
||||||
*/
|
*/
|
||||||
@Redirect(
|
@Overwrite
|
||||||
method = "writeChunk(Lnet/minecraft/world/level/ChunkPos;)V",
|
private void writeChunk(final ChunkPos chunkPos) {
|
||||||
at = @At(
|
throw new IllegalStateException("Only chunk system can write state, offending class:" + this.getClass().getName());
|
||||||
value = "INVOKE",
|
|
||||||
target = "Lnet/minecraft/world/level/chunk/storage/SimpleRegionStorage;write(Lnet/minecraft/world/level/ChunkPos;Lnet/minecraft/nbt/CompoundTag;)Ljava/util/concurrent/CompletableFuture;"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
private CompletableFuture<Void> redirectWrite(final SimpleRegionStorage instance, final ChunkPos pos,
|
|
||||||
final CompoundTag tag) {
|
|
||||||
try {
|
|
||||||
this.moonrise$write(pos.x, pos.z, tag);
|
|
||||||
} catch (final IOException ex) {
|
|
||||||
LOGGER.error("Error writing poi chunk data to disk for chunk " + pos, ex);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import net.minecraft.world.level.chunk.ChunkSource;
|
|||||||
import net.minecraft.world.level.chunk.LevelChunk;
|
import net.minecraft.world.level.chunk.LevelChunk;
|
||||||
import net.minecraft.world.level.chunk.LightChunk;
|
import net.minecraft.world.level.chunk.LightChunk;
|
||||||
import net.minecraft.world.level.chunk.status.ChunkStatus;
|
import net.minecraft.world.level.chunk.status.ChunkStatus;
|
||||||
|
import net.minecraft.world.level.storage.DimensionDataStorage;
|
||||||
import org.spongepowered.asm.mixin.Final;
|
import org.spongepowered.asm.mixin.Final;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Overwrite;
|
import org.spongepowered.asm.mixin.Overwrite;
|
||||||
@@ -51,6 +52,10 @@ abstract class ServerChunkCacheMixin extends ChunkSource implements ChunkSystemS
|
|||||||
@Final
|
@Final
|
||||||
public ServerLevel level;
|
public ServerLevel level;
|
||||||
|
|
||||||
|
@Shadow
|
||||||
|
@Final
|
||||||
|
private DimensionDataStorage dataStorage;
|
||||||
|
|
||||||
@Unique
|
@Unique
|
||||||
private final ConcurrentLong2ReferenceChainedHashTable<LevelChunk> fullChunks = new ConcurrentLong2ReferenceChainedHashTable<>();
|
private final ConcurrentLong2ReferenceChainedHashTable<LevelChunk> fullChunks = new ConcurrentLong2ReferenceChainedHashTable<>();
|
||||||
|
|
||||||
@@ -81,6 +86,13 @@ abstract class ServerChunkCacheMixin extends ChunkSource implements ChunkSystemS
|
|||||||
completable::complete
|
completable::complete
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (!completable.isDone() && chunkTaskScheduler.hasShutdown()) {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"Chunk system has shut down, cannot process chunk requests in world '" + ca.spottedleaf.moonrise.common.util.WorldUtil.getWorldName(this.level) + "' at "
|
||||||
|
+ "(" + chunkX + "," + chunkZ + ") status: " + toStatus
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (TickThread.isTickThreadFor(this.level, chunkX, chunkZ)) {
|
if (TickThread.isTickThreadFor(this.level, chunkX, chunkZ)) {
|
||||||
ChunkTaskScheduler.pushChunkWait(this.level, chunkX, chunkZ);
|
ChunkTaskScheduler.pushChunkWait(this.level, chunkX, chunkZ);
|
||||||
this.mainThreadProcessor.managedBlock(completable::isDone);
|
this.mainThreadProcessor.managedBlock(completable::isDone);
|
||||||
@@ -261,6 +273,7 @@ abstract class ServerChunkCacheMixin extends ChunkSource implements ChunkSystemS
|
|||||||
@Override
|
@Override
|
||||||
@Overwrite
|
@Overwrite
|
||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
|
this.dataStorage.close();
|
||||||
((ChunkSystemServerLevel)this.level).moonrise$getChunkTaskScheduler().chunkHolderManager.close(true, true);
|
((ChunkSystemServerLevel)this.level).moonrise$getChunkTaskScheduler().chunkHolderManager.close(true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -309,6 +322,22 @@ abstract class ServerChunkCacheMixin extends ChunkSource implements ChunkSystemS
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @reason We need to use {@link ChunkHolder#getChunkToSend()} as the new chunk system will not bring every chunk
|
||||||
|
* sent to players up to block ticking.
|
||||||
|
* @author Spottedleaf
|
||||||
|
*/
|
||||||
|
@Redirect(
|
||||||
|
method = "broadcastChangedChunks",
|
||||||
|
at = @At(
|
||||||
|
value = "INVOKE",
|
||||||
|
target = "Lnet/minecraft/server/level/ChunkHolder;getTickingChunk()Lnet/minecraft/world/level/chunk/LevelChunk;")
|
||||||
|
)
|
||||||
|
private LevelChunk redirectTickingChunk(final ChunkHolder instance) {
|
||||||
|
return instance.getChunkToSend();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @reason Perform mid-tick chunk task processing during chunk tick
|
* @reason Perform mid-tick chunk task processing during chunk tick
|
||||||
* @author Spottedleaf
|
* @author Spottedleaf
|
||||||
|
|||||||
@@ -85,11 +85,20 @@ abstract class ChunkMapMixin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @reason Use nearby players to avoid iterating over all online players
|
* @reason Avoid checking first if there are nearby players, as we make internal perform this implicitly.
|
||||||
* @author Spottedleaf
|
* @author Spottedleaf
|
||||||
*/
|
*/
|
||||||
@Overwrite
|
@Overwrite
|
||||||
public boolean anyPlayerCloseEnoughForSpawning(final ChunkPos pos) {
|
public boolean anyPlayerCloseEnoughForSpawning(final ChunkPos pos) {
|
||||||
|
return this.anyPlayerCloseEnoughForSpawningInternal(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @reason Use nearby players to avoid iterating over all online players
|
||||||
|
* @author Spottedleaf
|
||||||
|
*/
|
||||||
|
@Overwrite
|
||||||
|
public boolean anyPlayerCloseEnoughForSpawningInternal(final ChunkPos pos) {
|
||||||
final ReferenceList<ServerPlayer> players = ((ChunkSystemServerLevel)this.level).moonrise$getNearbyPlayers().getPlayers(
|
final ReferenceList<ServerPlayer> players = ((ChunkSystemServerLevel)this.level).moonrise$getNearbyPlayers().getPlayers(
|
||||||
pos, NearbyPlayers.NearbyMapType.SPAWN_RANGE
|
pos, NearbyPlayers.NearbyMapType.SPAWN_RANGE
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import ca.spottedleaf.moonrise.common.misc.PositionCountingAreaMap;
|
|||||||
import ca.spottedleaf.moonrise.common.util.CoordinateUtils;
|
import ca.spottedleaf.moonrise.common.util.CoordinateUtils;
|
||||||
import ca.spottedleaf.moonrise.patches.chunk_tick_iteration.ChunkTickConstants;
|
import ca.spottedleaf.moonrise.patches.chunk_tick_iteration.ChunkTickConstants;
|
||||||
import ca.spottedleaf.moonrise.patches.chunk_tick_iteration.ChunkTickDistanceManager;
|
import ca.spottedleaf.moonrise.patches.chunk_tick_iteration.ChunkTickDistanceManager;
|
||||||
|
import it.unimi.dsi.fastutil.longs.LongIterator;
|
||||||
import net.minecraft.core.SectionPos;
|
import net.minecraft.core.SectionPos;
|
||||||
import net.minecraft.server.level.DistanceManager;
|
import net.minecraft.server.level.DistanceManager;
|
||||||
import net.minecraft.server.level.ServerPlayer;
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
@@ -106,4 +107,13 @@ abstract class DistanceManagerMixin implements ChunkTickDistanceManager {
|
|||||||
public boolean hasPlayersNearby(final long pos) {
|
public boolean hasPlayersNearby(final long pos) {
|
||||||
return this.spawnChunkTracker.hasObjectsNear(CoordinateUtils.getChunkX(pos), CoordinateUtils.getChunkZ(pos));
|
return this.spawnChunkTracker.hasObjectsNear(CoordinateUtils.getChunkX(pos), CoordinateUtils.getChunkZ(pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @reason Use spawnChunkTracker instead
|
||||||
|
* @author Spottedleaf
|
||||||
|
*/
|
||||||
|
@Overwrite
|
||||||
|
public LongIterator getSpawnCandidateChunks() {
|
||||||
|
return this.spawnChunkTracker.getPositions().iterator();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package ca.spottedleaf.moonrise.mixin.chunk_tick_iteration;
|
|||||||
|
|
||||||
import ca.spottedleaf.moonrise.common.list.ReferenceList;
|
import ca.spottedleaf.moonrise.common.list.ReferenceList;
|
||||||
import ca.spottedleaf.moonrise.common.misc.NearbyPlayers;
|
import ca.spottedleaf.moonrise.common.misc.NearbyPlayers;
|
||||||
import ca.spottedleaf.moonrise.common.util.SimpleRandom;
|
import ca.spottedleaf.moonrise.common.util.SimpleThreadUnsafeRandom;
|
||||||
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkData;
|
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkData;
|
||||||
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkSystemChunkHolder;
|
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkSystemChunkHolder;
|
||||||
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkSystemLevelChunk;
|
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkSystemLevelChunk;
|
||||||
@@ -39,7 +39,7 @@ abstract class ServerChunkCacheMixin extends ChunkSource {
|
|||||||
|
|
||||||
|
|
||||||
@Unique
|
@Unique
|
||||||
private final SimpleRandom shuffleRandom = new SimpleRandom(0L);
|
private final SimpleThreadUnsafeRandom shuffleRandom = new SimpleThreadUnsafeRandom(0L);
|
||||||
|
|
||||||
@Unique
|
@Unique
|
||||||
private boolean isChunkNearPlayer(final ChunkMap chunkMap, final ChunkPos chunkPos, final LevelChunk levelChunk) {
|
private boolean isChunkNearPlayer(final ChunkMap chunkMap, final ChunkPos chunkPos, final LevelChunk levelChunk) {
|
||||||
|
|||||||
@@ -5,16 +5,12 @@ import ca.spottedleaf.moonrise.patches.collisions.shape.CollisionVoxelShape;
|
|||||||
import com.mojang.serialization.MapCodec;
|
import com.mojang.serialization.MapCodec;
|
||||||
import it.unimi.dsi.fastutil.HashCommon;
|
import it.unimi.dsi.fastutil.HashCommon;
|
||||||
import it.unimi.dsi.fastutil.objects.Reference2ObjectArrayMap;
|
import it.unimi.dsi.fastutil.objects.Reference2ObjectArrayMap;
|
||||||
import net.minecraft.core.BlockPos;
|
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
import net.minecraft.world.level.BlockGetter;
|
|
||||||
import net.minecraft.world.level.block.Block;
|
import net.minecraft.world.level.block.Block;
|
||||||
import net.minecraft.world.level.block.state.BlockBehaviour;
|
import net.minecraft.world.level.block.state.BlockBehaviour;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
import net.minecraft.world.level.block.state.StateHolder;
|
import net.minecraft.world.level.block.state.StateHolder;
|
||||||
import net.minecraft.world.level.block.state.properties.Property;
|
import net.minecraft.world.level.block.state.properties.Property;
|
||||||
import net.minecraft.world.phys.AABB;
|
|
||||||
import net.minecraft.world.phys.shapes.CollisionContext;
|
|
||||||
import net.minecraft.world.phys.shapes.Shapes;
|
import net.minecraft.world.phys.shapes.Shapes;
|
||||||
import net.minecraft.world.phys.shapes.VoxelShape;
|
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
@@ -32,7 +28,7 @@ abstract class BlockStateBaseMixin extends StateHolder<Block, BlockState> implem
|
|||||||
protected BlockBehaviour.BlockStateBase.Cache cache;
|
protected BlockBehaviour.BlockStateBase.Cache cache;
|
||||||
|
|
||||||
@Shadow
|
@Shadow
|
||||||
public abstract VoxelShape getCollisionShape(BlockGetter blockGetter, BlockPos blockPos, CollisionContext collisionContext);
|
public abstract boolean isAir();
|
||||||
|
|
||||||
@Shadow
|
@Shadow
|
||||||
public VoxelShape[] occlusionShapesByFace;
|
public VoxelShape[] occlusionShapesByFace;
|
||||||
@@ -99,10 +95,9 @@ abstract class BlockStateBaseMixin extends StateHolder<Block, BlockState> implem
|
|||||||
private void initCollisionState(final CallbackInfo ci) {
|
private void initCollisionState(final CallbackInfo ci) {
|
||||||
if (this.cache != null) {
|
if (this.cache != null) {
|
||||||
final VoxelShape collisionShape = this.cache.collisionShape;
|
final VoxelShape collisionShape = this.cache.collisionShape;
|
||||||
try {
|
if (this.isAir()) {
|
||||||
this.constantCollisionShape = this.getCollisionShape(null, null, null);
|
this.constantCollisionShape = Shapes.empty();
|
||||||
} catch (final Throwable throwable) {
|
} else {
|
||||||
// :(
|
|
||||||
this.constantCollisionShape = null;
|
this.constantCollisionShape = null;
|
||||||
}
|
}
|
||||||
this.occludesFullBlock = ((CollisionVoxelShape)collisionShape).moonrise$occludesFullBlock();
|
this.occludesFullBlock = ((CollisionVoxelShape)collisionShape).moonrise$occludesFullBlock();
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ import net.minecraft.world.entity.Entity;
|
|||||||
import net.minecraft.world.level.ChunkPos;
|
import net.minecraft.world.level.ChunkPos;
|
||||||
import net.minecraft.world.level.Explosion;
|
import net.minecraft.world.level.Explosion;
|
||||||
import net.minecraft.world.level.ExplosionDamageCalculator;
|
import net.minecraft.world.level.ExplosionDamageCalculator;
|
||||||
import net.minecraft.world.level.Level;
|
|
||||||
import net.minecraft.world.level.ServerExplosion;
|
import net.minecraft.world.level.ServerExplosion;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
import net.minecraft.world.level.chunk.LevelChunk;
|
import net.minecraft.world.level.chunk.LevelChunk;
|
||||||
@@ -440,7 +439,10 @@ abstract class ServerExplosionMixin {
|
|||||||
* @author Spottedleaf
|
* @author Spottedleaf
|
||||||
*/
|
*/
|
||||||
@Redirect(
|
@Redirect(
|
||||||
method = "hurtEntities",
|
method = {
|
||||||
|
"hurtEntities()V",
|
||||||
|
"hurtEntities(Ljava/util/List;)V" // Neo moves logic into this new method
|
||||||
|
},
|
||||||
at = @At(
|
at = @At(
|
||||||
value = "INVOKE",
|
value = "INVOKE",
|
||||||
target = "Lnet/minecraft/world/level/ServerExplosion;getSeenPercent(Lnet/minecraft/world/phys/Vec3;Lnet/minecraft/world/entity/Entity;)F"
|
target = "Lnet/minecraft/world/level/ServerExplosion;getSeenPercent(Lnet/minecraft/world/phys/Vec3;Lnet/minecraft/world/entity/Entity;)F"
|
||||||
|
|||||||
@@ -378,19 +378,19 @@ abstract class VoxelShapeMixin implements CollisionVoxelShape {
|
|||||||
case X: {
|
case X: {
|
||||||
final double[] values = this.rootCoordinatesX;
|
final double[] values = this.rootCoordinatesX;
|
||||||
return CollisionUtil.findFloor(
|
return CollisionUtil.findFloor(
|
||||||
values, value - this.offsetX, 0, values.length - 1
|
values, this.offsetX, value, 0, values.length - 1
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
case Y: {
|
case Y: {
|
||||||
final double[] values = this.rootCoordinatesY;
|
final double[] values = this.rootCoordinatesY;
|
||||||
return CollisionUtil.findFloor(
|
return CollisionUtil.findFloor(
|
||||||
values, value - this.offsetY, 0, values.length - 1
|
values, this.offsetY, value, 0, values.length - 1
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
case Z: {
|
case Z: {
|
||||||
final double[] values = this.rootCoordinatesZ;
|
final double[] values = this.rootCoordinatesZ;
|
||||||
return CollisionUtil.findFloor(
|
return CollisionUtil.findFloor(
|
||||||
values, value - this.offsetZ, 0, values.length - 1
|
values, this.offsetZ, value, 0, values.length - 1
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
@@ -411,7 +411,7 @@ abstract class VoxelShapeMixin implements CollisionVoxelShape {
|
|||||||
|
|
||||||
// see findIndex
|
// see findIndex
|
||||||
final int index = CollisionUtil.findFloor(
|
final int index = CollisionUtil.findFloor(
|
||||||
coords, (positiveDir ? (1.0 - CollisionUtil.COLLISION_EPSILON) : (0.0 + CollisionUtil.COLLISION_EPSILON)) - offset,
|
coords, offset, (positiveDir ? (1.0 - CollisionUtil.COLLISION_EPSILON) : (0.0 + CollisionUtil.COLLISION_EPSILON)),
|
||||||
0, coords.length - 1
|
0, coords.length - 1
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -146,7 +146,7 @@ abstract class TrackedEntityMixin implements EntityTrackerTrackedEntity {
|
|||||||
@Overwrite
|
@Overwrite
|
||||||
public int getEffectiveRange() {
|
public int getEffectiveRange() {
|
||||||
final Entity entity = this.entity;
|
final Entity entity = this.entity;
|
||||||
int range = PlatformHooks.get().modifyEntityTrackingRange(entity, this.range);
|
int range = this.range;
|
||||||
|
|
||||||
if (entity.getPassengers() == ImmutableList.<Entity>of()) {
|
if (entity.getPassengers() == ImmutableList.<Entity>of()) {
|
||||||
return this.scaledRange(range);
|
return this.scaledRange(range);
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package ca.spottedleaf.moonrise.mixin.loading_screen;
|
package ca.spottedleaf.moonrise.mixin.loading_screen;
|
||||||
|
|
||||||
|
import ca.spottedleaf.moonrise.common.util.ConfigHolder;
|
||||||
import net.minecraft.client.multiplayer.LevelLoadStatusManager;
|
import net.minecraft.client.multiplayer.LevelLoadStatusManager;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
@@ -25,6 +26,9 @@ abstract class LevelLoadStatusManagerMixin {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
private void immediatelyClose(final CallbackInfo ci) {
|
private void immediatelyClose(final CallbackInfo ci) {
|
||||||
|
if (!ConfigHolder.getConfig().misc.immediatelyCloseLoadingScreen) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (this.status == LevelLoadStatusManager.Status.WAITING_FOR_SERVER) {
|
if (this.status == LevelLoadStatusManager.Status.WAITING_FOR_SERVER) {
|
||||||
this.status = LevelLoadStatusManager.Status.LEVEL_READY;
|
this.status = LevelLoadStatusManager.Status.LEVEL_READY;
|
||||||
ci.cancel();
|
ci.cancel();
|
||||||
|
|||||||
@@ -24,8 +24,8 @@ abstract class AcquirePoiMixin {
|
|||||||
*/
|
*/
|
||||||
@Redirect(
|
@Redirect(
|
||||||
method = {
|
method = {
|
||||||
"method_46885",
|
"lambda$create$8",
|
||||||
"*(ZLorg/apache/commons/lang3/mutable/MutableLong;Lit/unimi/dsi/fastutil/longs/Long2ObjectMap;Ljava/util/function/Predicate;Lnet/minecraft/world/entity/ai/behavior/declarative/MemoryAccessor;Ljava/util/Optional;Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/entity/PathfinderMob;J)Z"
|
"method_46885"
|
||||||
},
|
},
|
||||||
at = @At(
|
at = @At(
|
||||||
target = "Lnet/minecraft/world/entity/ai/village/poi/PoiManager;findAllClosestFirstWithType(Ljava/util/function/Predicate;Ljava/util/function/Predicate;Lnet/minecraft/core/BlockPos;ILnet/minecraft/world/entity/ai/village/poi/PoiManager$Occupancy;)Ljava/util/stream/Stream;",
|
target = "Lnet/minecraft/world/entity/ai/village/poi/PoiManager;findAllClosestFirstWithType(Ljava/util/function/Predicate;Ljava/util/function/Predicate;Lnet/minecraft/core/BlockPos;ILnet/minecraft/world/entity/ai/village/poi/PoiManager$Occupancy;)Ljava/util/stream/Stream;",
|
||||||
@@ -33,9 +33,9 @@ abstract class AcquirePoiMixin {
|
|||||||
ordinal = 0
|
ordinal = 0
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
private static Stream<Pair<Holder<PoiType>, BlockPos>> aaa(PoiManager poiManager, Predicate<Holder<PoiType>> predicate,
|
private static Stream<Pair<Holder<PoiType>, BlockPos>> useLimitedSearch(PoiManager poiManager, Predicate<Holder<PoiType>> predicate,
|
||||||
Predicate<BlockPos> predicate2, BlockPos blockPos, int i,
|
Predicate<BlockPos> predicate2, BlockPos blockPos, int i,
|
||||||
PoiManager.Occupancy occup) {
|
PoiManager.Occupancy occup) {
|
||||||
final List<Pair<Holder<PoiType>, BlockPos>> ret = new ArrayList<>();
|
final List<Pair<Holder<PoiType>, BlockPos>> ret = new ArrayList<>();
|
||||||
|
|
||||||
PoiAccess.findNearestPoiPositions(
|
PoiAccess.findNearestPoiPositions(
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package ca.spottedleaf.moonrise.mixin.random;
|
||||||
|
|
||||||
|
import ca.spottedleaf.moonrise.common.util.ThreadUnsafeRandom;
|
||||||
|
import net.minecraft.util.RandomSource;
|
||||||
|
import net.minecraft.world.entity.Entity;
|
||||||
|
import net.minecraft.world.level.levelgen.RandomSupport;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||||
|
|
||||||
|
@Mixin(Entity.class)
|
||||||
|
abstract class EntityMixin {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @reason Changes Entity#random to use ThreadUnsafeRandom, skipping the thread checks and CAS logic
|
||||||
|
* @author Spottedleadf
|
||||||
|
*/
|
||||||
|
@Redirect(
|
||||||
|
method = "<init>",
|
||||||
|
at = @At(
|
||||||
|
value = "INVOKE",
|
||||||
|
target = "Lnet/minecraft/util/RandomSource;create()Lnet/minecraft/util/RandomSource;"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
private RandomSource redirectEntityRandom() {
|
||||||
|
return new ThreadUnsafeRandom(RandomSupport.generateUniqueSeed());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package ca.spottedleaf.moonrise.mixin.random;
|
||||||
|
|
||||||
|
import ca.spottedleaf.moonrise.common.util.ThreadUnsafeRandom;
|
||||||
|
import net.minecraft.util.RandomSource;
|
||||||
|
import net.minecraft.world.level.Level;
|
||||||
|
import net.minecraft.world.level.levelgen.RandomSupport;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||||
|
|
||||||
|
@Mixin(Level.class)
|
||||||
|
abstract class LevelMixin {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @reason Changes Level#random to use ThreadUnsafeRandom, skipping the thread checks and CAS logic
|
||||||
|
* @author Spottedleadf
|
||||||
|
*/
|
||||||
|
@Redirect(
|
||||||
|
method = "<init>",
|
||||||
|
at = @At(
|
||||||
|
value = "INVOKE",
|
||||||
|
target = "Lnet/minecraft/util/RandomSource;create()Lnet/minecraft/util/RandomSource;"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
private RandomSource redirectLevelRandom() {
|
||||||
|
return new ThreadUnsafeRandom(RandomSupport.generateUniqueSeed());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@ package ca.spottedleaf.moonrise.mixin.random_ticking;
|
|||||||
|
|
||||||
import ca.spottedleaf.moonrise.common.PlatformHooks;
|
import ca.spottedleaf.moonrise.common.PlatformHooks;
|
||||||
import ca.spottedleaf.moonrise.common.list.ShortList;
|
import ca.spottedleaf.moonrise.common.list.ShortList;
|
||||||
import ca.spottedleaf.moonrise.common.util.SimpleRandom;
|
import ca.spottedleaf.moonrise.common.util.SimpleThreadUnsafeRandom;
|
||||||
import ca.spottedleaf.moonrise.common.util.WorldUtil;
|
import ca.spottedleaf.moonrise.common.util.WorldUtil;
|
||||||
import ca.spottedleaf.moonrise.patches.block_counting.BlockCountingChunkSection;
|
import ca.spottedleaf.moonrise.patches.block_counting.BlockCountingChunkSection;
|
||||||
import com.llamalad7.mixinextras.sugar.Local;
|
import com.llamalad7.mixinextras.sugar.Local;
|
||||||
@@ -20,6 +20,7 @@ import net.minecraft.world.level.chunk.LevelChunk;
|
|||||||
import net.minecraft.world.level.chunk.LevelChunkSection;
|
import net.minecraft.world.level.chunk.LevelChunkSection;
|
||||||
import net.minecraft.world.level.chunk.PalettedContainer;
|
import net.minecraft.world.level.chunk.PalettedContainer;
|
||||||
import net.minecraft.world.level.dimension.DimensionType;
|
import net.minecraft.world.level.dimension.DimensionType;
|
||||||
|
import net.minecraft.world.level.levelgen.RandomSupport;
|
||||||
import net.minecraft.world.level.material.FluidState;
|
import net.minecraft.world.level.material.FluidState;
|
||||||
import net.minecraft.world.level.storage.WritableLevelData;
|
import net.minecraft.world.level.storage.WritableLevelData;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
@@ -38,7 +39,7 @@ abstract class ServerLevelMixin extends Level implements WorldGenLevel {
|
|||||||
private static final LevelChunkSection[] EMPTY_SECTION_ARRAY = new LevelChunkSection[0];
|
private static final LevelChunkSection[] EMPTY_SECTION_ARRAY = new LevelChunkSection[0];
|
||||||
|
|
||||||
@Unique
|
@Unique
|
||||||
private final SimpleRandom simpleRandom = new SimpleRandom(0L);
|
private final SimpleThreadUnsafeRandom simpleRandom = new SimpleThreadUnsafeRandom(RandomSupport.generateUniqueSeed());
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @reason Use faster random
|
* @reason Use faster random
|
||||||
@@ -72,7 +73,7 @@ abstract class ServerLevelMixin extends Level implements WorldGenLevel {
|
|||||||
@Local(ordinal = 0, argsOnly = true) final int tickSpeed) {
|
@Local(ordinal = 0, argsOnly = true) final int tickSpeed) {
|
||||||
final LevelChunkSection[] sections = chunk.getSections();
|
final LevelChunkSection[] sections = chunk.getSections();
|
||||||
final int minSection = WorldUtil.getMinSection((ServerLevel)(Object)this);
|
final int minSection = WorldUtil.getMinSection((ServerLevel)(Object)this);
|
||||||
final SimpleRandom simpleRandom = this.simpleRandom;
|
final SimpleThreadUnsafeRandom simpleRandom = this.simpleRandom;
|
||||||
final boolean doubleTickFluids = !PlatformHooks.get().configFixMC224294();
|
final boolean doubleTickFluids = !PlatformHooks.get().configFixMC224294();
|
||||||
|
|
||||||
final ChunkPos cpos = chunk.getPos();
|
final ChunkPos cpos = chunk.getPos();
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import net.minecraft.world.level.chunk.status.ChunkStatus;
|
|||||||
import net.minecraft.world.level.chunk.storage.RegionStorageInfo;
|
import net.minecraft.world.level.chunk.storage.RegionStorageInfo;
|
||||||
import net.minecraft.world.level.chunk.storage.SerializableChunkData;
|
import net.minecraft.world.level.chunk.storage.SerializableChunkData;
|
||||||
import net.minecraft.world.level.lighting.LevelLightEngine;
|
import net.minecraft.world.level.lighting.LevelLightEngine;
|
||||||
|
import org.slf4j.Logger;
|
||||||
import org.spongepowered.asm.mixin.Final;
|
import org.spongepowered.asm.mixin.Final;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
@@ -46,6 +47,10 @@ abstract class SerializableChunkDataMixin {
|
|||||||
@Final
|
@Final
|
||||||
private List<SerializableChunkData.SectionData> sectionData;
|
private List<SerializableChunkData.SectionData> sectionData;
|
||||||
|
|
||||||
|
@Shadow
|
||||||
|
@Final
|
||||||
|
private static Logger LOGGER;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @reason Replace light correctness check with our own
|
* @reason Replace light correctness check with our own
|
||||||
* Our light check is versioned in case we change the light format OR fix a bug
|
* Our light check is versioned in case we change the light format OR fix a bug
|
||||||
@@ -116,33 +121,45 @@ abstract class SerializableChunkDataMixin {
|
|||||||
final SWMRNibbleArray[] blockNibbles = StarLightEngine.getFilledEmptyLight(world);
|
final SWMRNibbleArray[] blockNibbles = StarLightEngine.getFilledEmptyLight(world);
|
||||||
final SWMRNibbleArray[] skyNibbles = StarLightEngine.getFilledEmptyLight(world);
|
final SWMRNibbleArray[] skyNibbles = StarLightEngine.getFilledEmptyLight(world);
|
||||||
|
|
||||||
for (final SerializableChunkData.SectionData sectionData : this.sectionData) {
|
if (!this.lightCorrect) {
|
||||||
final int y = sectionData.y();
|
((StarlightChunk)ret).starlight$setBlockNibbles(blockNibbles);
|
||||||
final DataLayer blockLight = sectionData.blockLight();
|
((StarlightChunk)ret).starlight$setSkyNibbles(skyNibbles);
|
||||||
final DataLayer skyLight = sectionData.skyLight();
|
return;
|
||||||
|
|
||||||
final int blockState = ((StarlightSectionData)(Object)sectionData).starlight$getBlockLightState();
|
|
||||||
final int skyState = ((StarlightSectionData)(Object)sectionData).starlight$getSkyLightState();
|
|
||||||
|
|
||||||
if (blockState >= 0) {
|
|
||||||
if (blockLight != null) {
|
|
||||||
blockNibbles[y - minSection] = new SWMRNibbleArray(MixinWorkarounds.clone(blockLight.getData()), blockState); // clone for data safety
|
|
||||||
} else {
|
|
||||||
blockNibbles[y - minSection] = new SWMRNibbleArray(null, blockState);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (skyState >= 0 && hasSkyLight) {
|
|
||||||
if (skyLight != null) {
|
|
||||||
skyNibbles[y - minSection] = new SWMRNibbleArray(MixinWorkarounds.clone(skyLight.getData()), skyState); // clone for data safety
|
|
||||||
} else {
|
|
||||||
skyNibbles[y - minSection] = new SWMRNibbleArray(null, skyState);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
((StarlightChunk)ret).starlight$setBlockNibbles(blockNibbles);
|
try {
|
||||||
((StarlightChunk)ret).starlight$setSkyNibbles(skyNibbles);
|
for (final SerializableChunkData.SectionData sectionData : this.sectionData) {
|
||||||
|
final int y = sectionData.y();
|
||||||
|
final DataLayer blockLight = sectionData.blockLight();
|
||||||
|
final DataLayer skyLight = sectionData.skyLight();
|
||||||
|
|
||||||
|
final int blockState = ((StarlightSectionData)(Object)sectionData).starlight$getBlockLightState();
|
||||||
|
final int skyState = ((StarlightSectionData)(Object)sectionData).starlight$getSkyLightState();
|
||||||
|
|
||||||
|
if (blockState >= 0) {
|
||||||
|
if (blockLight != null) {
|
||||||
|
blockNibbles[y - minSection] = new SWMRNibbleArray(MixinWorkarounds.clone(blockLight.getData()), blockState); // clone for data safety
|
||||||
|
} else {
|
||||||
|
blockNibbles[y - minSection] = new SWMRNibbleArray(null, blockState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (skyState >= 0 && hasSkyLight) {
|
||||||
|
if (skyLight != null) {
|
||||||
|
skyNibbles[y - minSection] = new SWMRNibbleArray(MixinWorkarounds.clone(skyLight.getData()), skyState); // clone for data safety
|
||||||
|
} else {
|
||||||
|
skyNibbles[y - minSection] = new SWMRNibbleArray(null, skyState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
((StarlightChunk)ret).starlight$setBlockNibbles(blockNibbles);
|
||||||
|
((StarlightChunk)ret).starlight$setSkyNibbles(skyNibbles);
|
||||||
|
} catch (final Throwable thr) {
|
||||||
|
ret.setLightCorrect(false);
|
||||||
|
|
||||||
|
LOGGER.error("Failed to parse light data for chunk " + ret.getPos() + " in world '" + WorldUtil.getWorldName(world) + "'", thr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import it.unimi.dsi.fastutil.objects.AbstractReference2ObjectMap;
|
|||||||
import it.unimi.dsi.fastutil.objects.ObjectIterator;
|
import it.unimi.dsi.fastutil.objects.ObjectIterator;
|
||||||
import it.unimi.dsi.fastutil.objects.ObjectSet;
|
import it.unimi.dsi.fastutil.objects.ObjectSet;
|
||||||
import it.unimi.dsi.fastutil.objects.Reference2ObjectMap;
|
import it.unimi.dsi.fastutil.objects.Reference2ObjectMap;
|
||||||
import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet;
|
import it.unimi.dsi.fastutil.objects.ReferenceArrayList;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@@ -27,7 +27,7 @@ public final class ZeroCollidingReferenceStateTable<O, S> {
|
|||||||
|
|
||||||
public ZeroCollidingReferenceStateTable(final Collection<Property<?>> properties) {
|
public ZeroCollidingReferenceStateTable(final Collection<Property<?>> properties) {
|
||||||
this.propertyToIndexer = new Int2ObjectOpenHashMap<>(properties.size());
|
this.propertyToIndexer = new Int2ObjectOpenHashMap<>(properties.size());
|
||||||
this.properties = new ReferenceOpenHashSet<>(properties);
|
this.properties = new ReferenceArrayList<>(properties);
|
||||||
|
|
||||||
final List<Property<?>> sortedProperties = new ArrayList<>(properties);
|
final List<Property<?>> sortedProperties = new ArrayList<>(properties);
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import net.minecraft.SharedConstants;
|
|||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.nbt.Tag;
|
import net.minecraft.nbt.Tag;
|
||||||
import net.minecraft.server.level.ServerLevel;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import net.minecraft.util.datafix.DataFixTypes;
|
import net.minecraft.util.datafix.fixes.References;
|
||||||
|
|
||||||
public final class ChunkSystemConverters {
|
public final class ChunkSystemConverters {
|
||||||
|
|
||||||
@@ -26,13 +26,13 @@ public final class ChunkSystemConverters {
|
|||||||
public static CompoundTag convertPoiCompoundTag(final CompoundTag data, final ServerLevel world) {
|
public static CompoundTag convertPoiCompoundTag(final CompoundTag data, final ServerLevel world) {
|
||||||
final int dataVersion = getDataVersion(data, DEFAULT_POI_DATA_VERSION);
|
final int dataVersion = getDataVersion(data, DEFAULT_POI_DATA_VERSION);
|
||||||
|
|
||||||
return PlatformHooks.get().convertNBT(DataFixTypes.POI_CHUNK, world.getServer().getFixerUpper(), data, dataVersion, getCurrentVersion());
|
return PlatformHooks.get().convertNBT(References.POI_CHUNK, world.getServer().getFixerUpper(), data, dataVersion, getCurrentVersion());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CompoundTag convertEntityChunkCompoundTag(final CompoundTag data, final ServerLevel world) {
|
public static CompoundTag convertEntityChunkCompoundTag(final CompoundTag data, final ServerLevel world) {
|
||||||
final int dataVersion = getDataVersion(data, DEFAULT_ENTITY_CHUNK_DATA_VERSION);
|
final int dataVersion = getDataVersion(data, DEFAULT_ENTITY_CHUNK_DATA_VERSION);
|
||||||
|
|
||||||
return PlatformHooks.get().convertNBT(DataFixTypes.ENTITY_CHUNK, world.getServer().getFixerUpper(), data, dataVersion, getCurrentVersion());
|
return PlatformHooks.get().convertNBT(References.ENTITY_CHUNK, world.getServer().getFixerUpper(), data, dataVersion, getCurrentVersion());
|
||||||
}
|
}
|
||||||
|
|
||||||
private ChunkSystemConverters() {}
|
private ChunkSystemConverters() {}
|
||||||
|
|||||||
@@ -1214,15 +1214,8 @@ public final class MoonriseRegionFileIO {
|
|||||||
try {
|
try {
|
||||||
writeData = this.regionDataController.startWrite(this.chunkX, this.chunkZ, write);
|
writeData = this.regionDataController.startWrite(this.chunkX, this.chunkZ, write);
|
||||||
} catch (final Throwable thr) {
|
} catch (final Throwable thr) {
|
||||||
// TODO implement this?
|
failedWrite = thr instanceof IOException;
|
||||||
/*if (thr instanceof RegionFileStorage.RegionFileSizeException) {
|
LOGGER.error("Failed to write chunk data for task: " + this.toString(), thr);
|
||||||
final int maxSize = RegionFile.MAX_CHUNK_SIZE / (1024 * 1024);
|
|
||||||
LOGGER.error("Chunk at (" + this.chunkX + "," + this.chunkZ + ") in '" + WorldUtil.getWorldName(this.world) + "' exceeds max size of " + maxSize + "MiB, it has been deleted from disk.");
|
|
||||||
} else */
|
|
||||||
{
|
|
||||||
failedWrite = thr instanceof IOException;
|
|
||||||
LOGGER.error("Failed to write chunk data for task: " + this.toString(), thr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (writeData == null) {
|
if (writeData == null) {
|
||||||
|
|||||||
@@ -165,7 +165,7 @@ public final class ChunkEntitySlices {
|
|||||||
return this.entities.size() != 0;
|
return this.entities.size() != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Entity> getAllEntities() {
|
public List<Entity> getAllEntities() {
|
||||||
final int len = this.entities.size();
|
final int len = this.entities.size();
|
||||||
if (len == 0) {
|
if (len == 0) {
|
||||||
return new ArrayList<>();
|
return new ArrayList<>();
|
||||||
@@ -291,21 +291,12 @@ public final class ChunkEntitySlices {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void getEntities(final Entity except, final AABB box, final List<Entity> into, final Predicate<? super Entity> predicate) {
|
public void getEntities(final Entity except, final AABB box, final List<Entity> into, final Predicate<? super Entity> predicate) {
|
||||||
this.allEntities.getEntitiesWithEnderDragonParts(except, box, into, predicate);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void getEntitiesWithoutDragonParts(final Entity except, final AABB box, final List<Entity> into, final Predicate<? super Entity> predicate) {
|
|
||||||
this.allEntities.getEntities(except, box, into, predicate);
|
this.allEntities.getEntities(except, box, into, predicate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public boolean getEntities(final Entity except, final AABB box, final List<Entity> into, final Predicate<? super Entity> predicate,
|
public boolean getEntities(final Entity except, final AABB box, final List<Entity> into, final Predicate<? super Entity> predicate,
|
||||||
final int maxCount) {
|
final int maxCount) {
|
||||||
return this.allEntities.getEntitiesWithEnderDragonPartsLimited(except, box, into, predicate, maxCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean getEntitiesWithoutDragonParts(final Entity except, final AABB box, final List<Entity> into, final Predicate<? super Entity> predicate,
|
|
||||||
final int maxCount) {
|
|
||||||
return this.allEntities.getEntitiesLimited(except, box, into, predicate, maxCount);
|
return this.allEntities.getEntitiesLimited(except, box, into, predicate, maxCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -319,7 +310,7 @@ public final class ChunkEntitySlices {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public <T extends Entity> boolean getEntities(final EntityType<?> type, final AABB box, final List<? super T> into,
|
public <T extends Entity> boolean getEntities(final EntityType<?> type, final AABB box, final List<? super T> into,
|
||||||
final Predicate<? super T> predicate, final int maxCount) {
|
final Predicate<? super T> predicate, final int maxCount) {
|
||||||
final EntityCollectionBySection byType = this.entitiesByType.get(type);
|
final EntityCollectionBySection byType = this.entitiesByType.get(type);
|
||||||
|
|
||||||
if (byType != null) {
|
if (byType != null) {
|
||||||
@@ -356,21 +347,21 @@ public final class ChunkEntitySlices {
|
|||||||
final Predicate<? super T> predicate) {
|
final Predicate<? super T> predicate) {
|
||||||
EntityCollectionBySection collection = this.entitiesByClass.get(clazz);
|
EntityCollectionBySection collection = this.entitiesByClass.get(clazz);
|
||||||
if (collection != null) {
|
if (collection != null) {
|
||||||
collection.getEntitiesWithEnderDragonParts(except, clazz, box, (List)into, (Predicate)predicate);
|
collection.getEntities(except, box, (List)into, (Predicate)predicate);
|
||||||
} else {
|
} else {
|
||||||
this.entitiesByClass.put(clazz, collection = this.initClass(clazz));
|
this.entitiesByClass.put(clazz, collection = this.initClass(clazz));
|
||||||
collection.getEntitiesWithEnderDragonParts(except, clazz, box, (List)into, (Predicate)predicate);
|
collection.getEntities(except, box, (List)into, (Predicate)predicate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T extends Entity> boolean getEntities(final Class<? extends T> clazz, final Entity except, final AABB box, final List<? super T> into,
|
public <T extends Entity> boolean getEntities(final Class<? extends T> clazz, final Entity except, final AABB box, final List<? super T> into,
|
||||||
final Predicate<? super T> predicate, final int maxCount) {
|
final Predicate<? super T> predicate, final int maxCount) {
|
||||||
EntityCollectionBySection collection = this.entitiesByClass.get(clazz);
|
EntityCollectionBySection collection = this.entitiesByClass.get(clazz);
|
||||||
if (collection != null) {
|
if (collection != null) {
|
||||||
return collection.getEntitiesWithEnderDragonPartsLimited(except, clazz, box, (List)into, (Predicate)predicate, maxCount);
|
return collection.getEntitiesLimited(except, box, (List)into, (Predicate)predicate, maxCount);
|
||||||
} else {
|
} else {
|
||||||
this.entitiesByClass.put(clazz, collection = this.initClass(clazz));
|
this.entitiesByClass.put(clazz, collection = this.initClass(clazz));
|
||||||
return collection.getEntitiesWithEnderDragonPartsLimited(except, clazz, box, (List)into, (Predicate)predicate, maxCount);
|
return collection.getEntitiesLimited(except, box, (List)into, (Predicate)predicate, maxCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -574,225 +565,5 @@ public final class ChunkEntitySlices {
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void getEntitiesWithEnderDragonParts(final Entity except, final AABB box, final List<Entity> into,
|
|
||||||
final Predicate<? super Entity> predicate) {
|
|
||||||
if (this.count == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final int minSection = this.slices.minSection;
|
|
||||||
final int maxSection = this.slices.maxSection;
|
|
||||||
|
|
||||||
final int min = Mth.clamp(Mth.floor(box.minY - 2.0) >> 4, minSection, maxSection);
|
|
||||||
final int max = Mth.clamp(Mth.floor(box.maxY + 2.0) >> 4, minSection, maxSection);
|
|
||||||
|
|
||||||
final BasicEntityList<Entity>[] entitiesBySection = this.entitiesBySection;
|
|
||||||
|
|
||||||
for (int section = min; section <= max; ++section) {
|
|
||||||
final BasicEntityList<Entity> list = entitiesBySection[section - minSection];
|
|
||||||
|
|
||||||
if (list == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
final Entity[] storage = list.storage;
|
|
||||||
|
|
||||||
for (int i = 0, len = Math.min(storage.length, list.size()); i < len; ++i) {
|
|
||||||
final Entity entity = storage[i];
|
|
||||||
|
|
||||||
if (entity == null || entity == except || !entity.getBoundingBox().intersects(box)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (predicate == null || predicate.test(entity)) {
|
|
||||||
into.add(entity);
|
|
||||||
} // else: continue to test the ender dragon parts
|
|
||||||
|
|
||||||
if (entity instanceof EnderDragon) {
|
|
||||||
for (final EnderDragonPart part : ((EnderDragon)entity).getSubEntities()) {
|
|
||||||
if (part == except || !part.getBoundingBox().intersects(box)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (predicate != null && !predicate.test(part)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
into.add(part);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean getEntitiesWithEnderDragonPartsLimited(final Entity except, final AABB box, final List<Entity> into,
|
|
||||||
final Predicate<? super Entity> predicate, final int maxCount) {
|
|
||||||
if (this.count == 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
final int minSection = this.slices.minSection;
|
|
||||||
final int maxSection = this.slices.maxSection;
|
|
||||||
|
|
||||||
final int min = Mth.clamp(Mth.floor(box.minY - 2.0) >> 4, minSection, maxSection);
|
|
||||||
final int max = Mth.clamp(Mth.floor(box.maxY + 2.0) >> 4, minSection, maxSection);
|
|
||||||
|
|
||||||
final BasicEntityList<Entity>[] entitiesBySection = this.entitiesBySection;
|
|
||||||
|
|
||||||
for (int section = min; section <= max; ++section) {
|
|
||||||
final BasicEntityList<Entity> list = entitiesBySection[section - minSection];
|
|
||||||
|
|
||||||
if (list == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
final Entity[] storage = list.storage;
|
|
||||||
|
|
||||||
for (int i = 0, len = Math.min(storage.length, list.size()); i < len; ++i) {
|
|
||||||
final Entity entity = storage[i];
|
|
||||||
|
|
||||||
if (entity == null || entity == except || !entity.getBoundingBox().intersects(box)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (predicate == null || predicate.test(entity)) {
|
|
||||||
into.add(entity);
|
|
||||||
if (into.size() >= maxCount) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} // else: continue to test the ender dragon parts
|
|
||||||
|
|
||||||
if (entity instanceof EnderDragon) {
|
|
||||||
for (final EnderDragonPart part : ((EnderDragon)entity).getSubEntities()) {
|
|
||||||
if (part == except || !part.getBoundingBox().intersects(box)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (predicate != null && !predicate.test(part)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
into.add(part);
|
|
||||||
if (into.size() >= maxCount) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void getEntitiesWithEnderDragonParts(final Entity except, final Class<?> clazz, final AABB box, final List<Entity> into,
|
|
||||||
final Predicate<? super Entity> predicate) {
|
|
||||||
if (this.count == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final int minSection = this.slices.minSection;
|
|
||||||
final int maxSection = this.slices.maxSection;
|
|
||||||
|
|
||||||
final int min = Mth.clamp(Mth.floor(box.minY - 2.0) >> 4, minSection, maxSection);
|
|
||||||
final int max = Mth.clamp(Mth.floor(box.maxY + 2.0) >> 4, minSection, maxSection);
|
|
||||||
|
|
||||||
final BasicEntityList<Entity>[] entitiesBySection = this.entitiesBySection;
|
|
||||||
|
|
||||||
for (int section = min; section <= max; ++section) {
|
|
||||||
final BasicEntityList<Entity> list = entitiesBySection[section - minSection];
|
|
||||||
|
|
||||||
if (list == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
final Entity[] storage = list.storage;
|
|
||||||
|
|
||||||
for (int i = 0, len = Math.min(storage.length, list.size()); i < len; ++i) {
|
|
||||||
final Entity entity = storage[i];
|
|
||||||
|
|
||||||
if (entity == null || entity == except || !entity.getBoundingBox().intersects(box)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (predicate == null || predicate.test(entity)) {
|
|
||||||
into.add(entity);
|
|
||||||
} // else: continue to test the ender dragon parts
|
|
||||||
|
|
||||||
if (entity instanceof EnderDragon) {
|
|
||||||
for (final EnderDragonPart part : ((EnderDragon)entity).getSubEntities()) {
|
|
||||||
if (part == except || !part.getBoundingBox().intersects(box) || !clazz.isInstance(part)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (predicate != null && !predicate.test(part)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
into.add(part);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean getEntitiesWithEnderDragonPartsLimited(final Entity except, final Class<?> clazz, final AABB box, final List<Entity> into,
|
|
||||||
final Predicate<? super Entity> predicate, final int maxCount) {
|
|
||||||
if (this.count == 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
final int minSection = this.slices.minSection;
|
|
||||||
final int maxSection = this.slices.maxSection;
|
|
||||||
|
|
||||||
final int min = Mth.clamp(Mth.floor(box.minY - 2.0) >> 4, minSection, maxSection);
|
|
||||||
final int max = Mth.clamp(Mth.floor(box.maxY + 2.0) >> 4, minSection, maxSection);
|
|
||||||
|
|
||||||
final BasicEntityList<Entity>[] entitiesBySection = this.entitiesBySection;
|
|
||||||
|
|
||||||
for (int section = min; section <= max; ++section) {
|
|
||||||
final BasicEntityList<Entity> list = entitiesBySection[section - minSection];
|
|
||||||
|
|
||||||
if (list == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
final Entity[] storage = list.storage;
|
|
||||||
|
|
||||||
for (int i = 0, len = Math.min(storage.length, list.size()); i < len; ++i) {
|
|
||||||
final Entity entity = storage[i];
|
|
||||||
|
|
||||||
if (entity == null || entity == except || !entity.getBoundingBox().intersects(box)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (predicate == null || predicate.test(entity)) {
|
|
||||||
into.add(entity);
|
|
||||||
if (into.size() >= maxCount) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} // else: continue to test the ender dragon parts
|
|
||||||
|
|
||||||
if (entity instanceof EnderDragon) {
|
|
||||||
for (final EnderDragonPart part : ((EnderDragon)entity).getSubEntities()) {
|
|
||||||
if (part == except || !part.getBoundingBox().intersects(box) || !clazz.isInstance(part)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (predicate != null && !predicate.test(part)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
into.add(part);
|
|
||||||
if (into.size() >= maxCount) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -209,7 +209,7 @@ public abstract class EntityLookup implements LevelEntityGetter<Entity> {
|
|||||||
@Override
|
@Override
|
||||||
public void get(final AABB box, final Consumer<Entity> action) {
|
public void get(final AABB box, final Consumer<Entity> action) {
|
||||||
List<Entity> entities = new ArrayList<>();
|
List<Entity> entities = new ArrayList<>();
|
||||||
this.getEntitiesWithoutDragonParts(null, box, entities, null);
|
this.getEntities((Entity)null, box, entities, null);
|
||||||
for (int i = 0, len = entities.size(); i < len; ++i) {
|
for (int i = 0, len = entities.size(); i < len; ++i) {
|
||||||
action.accept(entities.get(i));
|
action.accept(entities.get(i));
|
||||||
}
|
}
|
||||||
@@ -218,7 +218,7 @@ public abstract class EntityLookup implements LevelEntityGetter<Entity> {
|
|||||||
@Override
|
@Override
|
||||||
public <U extends Entity> void get(final EntityTypeTest<Entity, U> filter, final AABB box, final AbortableIterationConsumer<U> action) {
|
public <U extends Entity> void get(final EntityTypeTest<Entity, U> filter, final AABB box, final AbortableIterationConsumer<U> action) {
|
||||||
List<Entity> entities = new ArrayList<>();
|
List<Entity> entities = new ArrayList<>();
|
||||||
this.getEntitiesWithoutDragonParts(null, box, entities, null);
|
this.getEntities((Entity)null, box, entities, null);
|
||||||
for (int i = 0, len = entities.size(); i < len; ++i) {
|
for (int i = 0, len = entities.size(); i < len; ++i) {
|
||||||
final U casted = filter.tryCast(entities.get(i));
|
final U casted = filter.tryCast(entities.get(i));
|
||||||
if (casted != null && action.accept(casted).shouldAbort()) {
|
if (casted != null && action.accept(casted).shouldAbort()) {
|
||||||
@@ -560,45 +560,6 @@ public abstract class EntityLookup implements LevelEntityGetter<Entity> {
|
|||||||
return slices;
|
return slices;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void getEntitiesWithoutDragonParts(final Entity except, final AABB box, final List<Entity> into, final Predicate<? super Entity> predicate) {
|
|
||||||
final int minChunkX = (Mth.floor(box.minX) - 2) >> 4;
|
|
||||||
final int minChunkZ = (Mth.floor(box.minZ) - 2) >> 4;
|
|
||||||
final int maxChunkX = (Mth.floor(box.maxX) + 2) >> 4;
|
|
||||||
final int maxChunkZ = (Mth.floor(box.maxZ) + 2) >> 4;
|
|
||||||
|
|
||||||
final int minRegionX = minChunkX >> REGION_SHIFT;
|
|
||||||
final int minRegionZ = minChunkZ >> REGION_SHIFT;
|
|
||||||
final int maxRegionX = maxChunkX >> REGION_SHIFT;
|
|
||||||
final int maxRegionZ = maxChunkZ >> REGION_SHIFT;
|
|
||||||
|
|
||||||
for (int currRegionZ = minRegionZ; currRegionZ <= maxRegionZ; ++currRegionZ) {
|
|
||||||
final int minZ = currRegionZ == minRegionZ ? minChunkZ & REGION_MASK : 0;
|
|
||||||
final int maxZ = currRegionZ == maxRegionZ ? maxChunkZ & REGION_MASK : REGION_MASK;
|
|
||||||
|
|
||||||
for (int currRegionX = minRegionX; currRegionX <= maxRegionX; ++currRegionX) {
|
|
||||||
final ChunkSlicesRegion region = this.getRegion(currRegionX, currRegionZ);
|
|
||||||
|
|
||||||
if (region == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
final int minX = currRegionX == minRegionX ? minChunkX & REGION_MASK : 0;
|
|
||||||
final int maxX = currRegionX == maxRegionX ? maxChunkX & REGION_MASK : REGION_MASK;
|
|
||||||
|
|
||||||
for (int currZ = minZ; currZ <= maxZ; ++currZ) {
|
|
||||||
for (int currX = minX; currX <= maxX; ++currX) {
|
|
||||||
final ChunkEntitySlices chunk = region.get(currX | (currZ << REGION_SHIFT));
|
|
||||||
if (chunk == null || !chunk.status.isOrAfter(FullChunkStatus.FULL)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
chunk.getEntitiesWithoutDragonParts(except, box, into, predicate);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void getEntities(final Entity except, final AABB box, final List<Entity> into, final Predicate<? super Entity> predicate) {
|
public void getEntities(final Entity except, final AABB box, final List<Entity> into, final Predicate<? super Entity> predicate) {
|
||||||
final int minChunkX = (Mth.floor(box.minX) - 2) >> 4;
|
final int minChunkX = (Mth.floor(box.minX) - 2) >> 4;
|
||||||
final int minChunkZ = (Mth.floor(box.minZ) - 2) >> 4;
|
final int minChunkZ = (Mth.floor(box.minZ) - 2) >> 4;
|
||||||
@@ -759,48 +720,6 @@ public abstract class EntityLookup implements LevelEntityGetter<Entity> {
|
|||||||
|
|
||||||
//////// Limited ////////
|
//////// Limited ////////
|
||||||
|
|
||||||
public void getEntitiesWithoutDragonParts(final Entity except, final AABB box, final List<Entity> into, final Predicate<? super Entity> predicate,
|
|
||||||
final int maxCount) {
|
|
||||||
final int minChunkX = (Mth.floor(box.minX) - 2) >> 4;
|
|
||||||
final int minChunkZ = (Mth.floor(box.minZ) - 2) >> 4;
|
|
||||||
final int maxChunkX = (Mth.floor(box.maxX) + 2) >> 4;
|
|
||||||
final int maxChunkZ = (Mth.floor(box.maxZ) + 2) >> 4;
|
|
||||||
|
|
||||||
final int minRegionX = minChunkX >> REGION_SHIFT;
|
|
||||||
final int minRegionZ = minChunkZ >> REGION_SHIFT;
|
|
||||||
final int maxRegionX = maxChunkX >> REGION_SHIFT;
|
|
||||||
final int maxRegionZ = maxChunkZ >> REGION_SHIFT;
|
|
||||||
|
|
||||||
for (int currRegionZ = minRegionZ; currRegionZ <= maxRegionZ; ++currRegionZ) {
|
|
||||||
final int minZ = currRegionZ == minRegionZ ? minChunkZ & REGION_MASK : 0;
|
|
||||||
final int maxZ = currRegionZ == maxRegionZ ? maxChunkZ & REGION_MASK : REGION_MASK;
|
|
||||||
|
|
||||||
for (int currRegionX = minRegionX; currRegionX <= maxRegionX; ++currRegionX) {
|
|
||||||
final ChunkSlicesRegion region = this.getRegion(currRegionX, currRegionZ);
|
|
||||||
|
|
||||||
if (region == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
final int minX = currRegionX == minRegionX ? minChunkX & REGION_MASK : 0;
|
|
||||||
final int maxX = currRegionX == maxRegionX ? maxChunkX & REGION_MASK : REGION_MASK;
|
|
||||||
|
|
||||||
for (int currZ = minZ; currZ <= maxZ; ++currZ) {
|
|
||||||
for (int currX = minX; currX <= maxX; ++currX) {
|
|
||||||
final ChunkEntitySlices chunk = region.get(currX | (currZ << REGION_SHIFT));
|
|
||||||
if (chunk == null || !chunk.status.isOrAfter(FullChunkStatus.FULL)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (chunk.getEntitiesWithoutDragonParts(except, box, into, predicate, maxCount)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void getEntities(final Entity except, final AABB box, final List<Entity> into, final Predicate<? super Entity> predicate,
|
public void getEntities(final Entity except, final AABB box, final List<Entity> into, final Predicate<? super Entity> predicate,
|
||||||
final int maxCount) {
|
final int maxCount) {
|
||||||
final int minChunkX = (Mth.floor(box.minX) - 2) >> 4;
|
final int minChunkX = (Mth.floor(box.minX) - 2) >> 4;
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import ca.spottedleaf.moonrise.common.PlatformHooks;
|
|||||||
import ca.spottedleaf.moonrise.common.list.ReferenceList;
|
import ca.spottedleaf.moonrise.common.list.ReferenceList;
|
||||||
import ca.spottedleaf.moonrise.common.util.CoordinateUtils;
|
import ca.spottedleaf.moonrise.common.util.CoordinateUtils;
|
||||||
import ca.spottedleaf.moonrise.common.util.TickThread;
|
import ca.spottedleaf.moonrise.common.util.TickThread;
|
||||||
import ca.spottedleaf.moonrise.common.util.ChunkSystem;
|
|
||||||
import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel;
|
import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel;
|
||||||
import ca.spottedleaf.moonrise.patches.chunk_system.level.entity.ChunkEntitySlices;
|
import ca.spottedleaf.moonrise.patches.chunk_system.level.entity.ChunkEntitySlices;
|
||||||
import ca.spottedleaf.moonrise.patches.chunk_system.level.entity.EntityLookup;
|
import ca.spottedleaf.moonrise.patches.chunk_system.level.entity.EntityLookup;
|
||||||
@@ -111,6 +110,6 @@ public final class ServerEntityLookup extends EntityLookup {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean screenEntity(final Entity entity, final boolean fromDisk, final boolean event) {
|
protected boolean screenEntity(final Entity entity, final boolean fromDisk, final boolean event) {
|
||||||
return ChunkSystem.screenEntity(this.serverWorld, entity, fromDisk, event);
|
return PlatformHooks.get().screenEntity(this.serverWorld, entity, fromDisk, event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,10 @@
|
|||||||
package ca.spottedleaf.moonrise.patches.chunk_system.level.storage;
|
package ca.spottedleaf.moonrise.patches.chunk_system.level.storage;
|
||||||
|
|
||||||
import net.minecraft.nbt.CompoundTag;
|
|
||||||
import net.minecraft.world.level.chunk.storage.RegionFileStorage;
|
import net.minecraft.world.level.chunk.storage.RegionFileStorage;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
public interface ChunkSystemSectionStorage {
|
public interface ChunkSystemSectionStorage {
|
||||||
|
|
||||||
public CompoundTag moonrise$read(final int chunkX, final int chunkZ) throws IOException;
|
|
||||||
|
|
||||||
public void moonrise$write(final int chunkX, final int chunkZ, final CompoundTag data) throws IOException;
|
|
||||||
|
|
||||||
public RegionFileStorage moonrise$getRegionStorage();
|
public RegionFileStorage moonrise$getRegionStorage();
|
||||||
|
|
||||||
public void moonrise$close() throws IOException;
|
public void moonrise$close() throws IOException;
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import ca.spottedleaf.moonrise.common.PlatformHooks;
|
|||||||
import ca.spottedleaf.moonrise.common.misc.AllocatingRateLimiter;
|
import ca.spottedleaf.moonrise.common.misc.AllocatingRateLimiter;
|
||||||
import ca.spottedleaf.moonrise.common.misc.SingleUserAreaMap;
|
import ca.spottedleaf.moonrise.common.misc.SingleUserAreaMap;
|
||||||
import ca.spottedleaf.moonrise.common.util.CoordinateUtils;
|
import ca.spottedleaf.moonrise.common.util.CoordinateUtils;
|
||||||
|
import ca.spottedleaf.moonrise.common.util.MoonriseConstants;
|
||||||
import ca.spottedleaf.moonrise.common.util.TickThread;
|
import ca.spottedleaf.moonrise.common.util.TickThread;
|
||||||
import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemLevel;
|
import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemLevel;
|
||||||
import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel;
|
import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel;
|
||||||
@@ -114,14 +115,25 @@ public final class RegionizedPlayerChunkLoader {
|
|||||||
int sendViewDistance
|
int sendViewDistance
|
||||||
) {
|
) {
|
||||||
public ViewDistances setTickViewDistance(final int distance) {
|
public ViewDistances setTickViewDistance(final int distance) {
|
||||||
|
if (distance != -1 && (distance < (0) || distance > (MoonriseConstants.MAX_VIEW_DISTANCE))) {
|
||||||
|
throw new IllegalArgumentException(Integer.toString(distance));
|
||||||
|
}
|
||||||
return new ViewDistances(distance, this.loadViewDistance, this.sendViewDistance);
|
return new ViewDistances(distance, this.loadViewDistance, this.sendViewDistance);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ViewDistances setLoadViewDistance(final int distance) {
|
public ViewDistances setLoadViewDistance(final int distance) {
|
||||||
|
// note: load view distance = api view distance + 1
|
||||||
|
if (distance != -1 && (distance < (2 + 1) || distance > (MoonriseConstants.MAX_VIEW_DISTANCE + 1))) {
|
||||||
|
throw new IllegalArgumentException(Integer.toString(distance));
|
||||||
|
}
|
||||||
return new ViewDistances(this.tickViewDistance, distance, this.sendViewDistance);
|
return new ViewDistances(this.tickViewDistance, distance, this.sendViewDistance);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ViewDistances setSendViewDistance(final int distance) {
|
public ViewDistances setSendViewDistance(final int distance) {
|
||||||
|
// note: send view distance <= load view distance - 1
|
||||||
|
if (distance != -1 && (distance < (0) || distance > (MoonriseConstants.MAX_VIEW_DISTANCE))) {
|
||||||
|
throw new IllegalArgumentException(Integer.toString(distance));
|
||||||
|
}
|
||||||
return new ViewDistances(this.tickViewDistance, this.loadViewDistance, distance);
|
return new ViewDistances(this.tickViewDistance, this.loadViewDistance, distance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,16 +167,6 @@ public final class RegionizedPlayerChunkLoader {
|
|||||||
return data.lastLoadDistance - 1;
|
return data.lastLoadDistance - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getLoadViewDistance(final ServerPlayer player) {
|
|
||||||
final ServerLevel level = player.serverLevel();
|
|
||||||
final PlayerChunkLoaderData data = ((ChunkSystemServerPlayer)player).moonrise$getChunkLoader();
|
|
||||||
if (data == null) {
|
|
||||||
return ((ChunkSystemServerLevel)level).moonrise$getPlayerChunkLoader().getAPIViewDistance();
|
|
||||||
}
|
|
||||||
// view distance = load distance + 1
|
|
||||||
return data.lastLoadDistance - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int getAPISendViewDistance(final ServerPlayer player) {
|
public static int getAPISendViewDistance(final ServerPlayer player) {
|
||||||
final ServerLevel level = player.serverLevel();
|
final ServerLevel level = player.serverLevel();
|
||||||
final PlayerChunkLoaderData data = ((ChunkSystemServerPlayer)player).moonrise$getChunkLoader();
|
final PlayerChunkLoaderData data = ((ChunkSystemServerPlayer)player).moonrise$getChunkLoader();
|
||||||
@@ -516,7 +518,7 @@ public final class RegionizedPlayerChunkLoader {
|
|||||||
final int playerLoadViewDistance, final int worldLoadViewDistance) {
|
final int playerLoadViewDistance, final int worldLoadViewDistance) {
|
||||||
return Math.min(
|
return Math.min(
|
||||||
playerTickViewDistance < 0 ? worldTickViewDistance : playerTickViewDistance,
|
playerTickViewDistance < 0 ? worldTickViewDistance : playerTickViewDistance,
|
||||||
playerLoadViewDistance < 0 ? worldLoadViewDistance : playerLoadViewDistance
|
playerLoadViewDistance < 0 ? (worldLoadViewDistance - 1) : (playerLoadViewDistance - 1)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import ca.spottedleaf.moonrise.common.PlatformHooks;
|
|||||||
import ca.spottedleaf.moonrise.common.util.CoordinateUtils;
|
import ca.spottedleaf.moonrise.common.util.CoordinateUtils;
|
||||||
import ca.spottedleaf.moonrise.common.util.TickThread;
|
import ca.spottedleaf.moonrise.common.util.TickThread;
|
||||||
import ca.spottedleaf.moonrise.common.util.WorldUtil;
|
import ca.spottedleaf.moonrise.common.util.WorldUtil;
|
||||||
import ca.spottedleaf.moonrise.common.util.ChunkSystem;
|
|
||||||
import ca.spottedleaf.moonrise.patches.chunk_system.io.MoonriseRegionFileIO;
|
import ca.spottedleaf.moonrise.patches.chunk_system.io.MoonriseRegionFileIO;
|
||||||
import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel;
|
import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel;
|
||||||
import ca.spottedleaf.moonrise.patches.chunk_system.level.entity.ChunkEntitySlices;
|
import ca.spottedleaf.moonrise.patches.chunk_system.level.entity.ChunkEntitySlices;
|
||||||
@@ -219,6 +218,8 @@ public final class ChunkHolderManager {
|
|||||||
LOGGER.error("Failed to close '" + type.name() + "' regionfile cache for world '" + WorldUtil.getWorldName(this.world) + "'", ex);
|
LOGGER.error("Failed to close '" + type.name() + "' regionfile cache for world '" + WorldUtil.getWorldName(this.world) + "'", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.taskScheduler.setShutdown(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ensureInAutosave(final NewChunkHolder holder) {
|
void ensureInAutosave(final NewChunkHolder holder) {
|
||||||
@@ -231,8 +232,8 @@ public final class ChunkHolderManager {
|
|||||||
public void autoSave() {
|
public void autoSave() {
|
||||||
final List<NewChunkHolder> reschedule = new ArrayList<>();
|
final List<NewChunkHolder> reschedule = new ArrayList<>();
|
||||||
final long currentTick = this.currentTick;
|
final long currentTick = this.currentTick;
|
||||||
final long maxSaveTime = currentTick - Math.max(1L, PlatformHooks.get().configAutoSaveInterval());
|
final long maxSaveTime = currentTick - Math.max(1L, PlatformHooks.get().configAutoSaveInterval(this.world));
|
||||||
final int maxToSave = PlatformHooks.get().configMaxAutoSavePerTick();
|
final int maxToSave = PlatformHooks.get().configMaxAutoSavePerTick(this.world);
|
||||||
for (int autoSaved = 0; autoSaved < maxToSave && !this.autoSaveQueue.isEmpty();) {
|
for (int autoSaved = 0; autoSaved < maxToSave && !this.autoSaveQueue.isEmpty();) {
|
||||||
final NewChunkHolder holder = this.autoSaveQueue.first();
|
final NewChunkHolder holder = this.autoSaveQueue.first();
|
||||||
|
|
||||||
@@ -816,7 +817,7 @@ public final class ChunkHolderManager {
|
|||||||
private NewChunkHolder createChunkHolder(final long position) {
|
private NewChunkHolder createChunkHolder(final long position) {
|
||||||
final NewChunkHolder ret = new NewChunkHolder(this.world, CoordinateUtils.getChunkX(position), CoordinateUtils.getChunkZ(position), this.taskScheduler);
|
final NewChunkHolder ret = new NewChunkHolder(this.world, CoordinateUtils.getChunkX(position), CoordinateUtils.getChunkZ(position), this.taskScheduler);
|
||||||
|
|
||||||
ChunkSystem.onChunkHolderCreate(this.world, ret.vanillaChunkHolder);
|
PlatformHooks.get().onChunkHolderCreate(this.world, ret.vanillaChunkHolder);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -1024,7 +1025,7 @@ public final class ChunkHolderManager {
|
|||||||
private void removeChunkHolder(final NewChunkHolder holder) {
|
private void removeChunkHolder(final NewChunkHolder holder) {
|
||||||
holder.onUnload();
|
holder.onUnload();
|
||||||
this.autoSaveQueue.remove(holder);
|
this.autoSaveQueue.remove(holder);
|
||||||
ChunkSystem.onChunkHolderDelete(this.world, holder.vanillaChunkHolder);
|
PlatformHooks.get().onChunkHolderDelete(this.world, holder.vanillaChunkHolder);
|
||||||
this.chunkHolders.remove(CoordinateUtils.getChunkKey(holder.chunkX, holder.chunkZ));
|
this.chunkHolders.remove(CoordinateUtils.getChunkKey(holder.chunkX, holder.chunkZ));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import ca.spottedleaf.concurrentutil.executor.thread.PrioritisedThreadPool;
|
|||||||
import ca.spottedleaf.concurrentutil.lock.ReentrantAreaLock;
|
import ca.spottedleaf.concurrentutil.lock.ReentrantAreaLock;
|
||||||
import ca.spottedleaf.concurrentutil.util.ConcurrentUtil;
|
import ca.spottedleaf.concurrentutil.util.ConcurrentUtil;
|
||||||
import ca.spottedleaf.concurrentutil.util.Priority;
|
import ca.spottedleaf.concurrentutil.util.Priority;
|
||||||
import ca.spottedleaf.moonrise.common.config.moonrise.MoonriseConfig;
|
|
||||||
import ca.spottedleaf.moonrise.common.util.CoordinateUtils;
|
import ca.spottedleaf.moonrise.common.util.CoordinateUtils;
|
||||||
import ca.spottedleaf.moonrise.common.util.JsonUtil;
|
import ca.spottedleaf.moonrise.common.util.JsonUtil;
|
||||||
import ca.spottedleaf.moonrise.common.util.MoonriseCommon;
|
import ca.spottedleaf.moonrise.common.util.MoonriseCommon;
|
||||||
@@ -272,6 +271,16 @@ public final class ChunkTaskScheduler {
|
|||||||
return this.lockShift;
|
return this.lockShift;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private volatile boolean shutdown;
|
||||||
|
|
||||||
|
public boolean hasShutdown() {
|
||||||
|
return this.shutdown;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setShutdown(final boolean shutdown) {
|
||||||
|
this.shutdown = shutdown;
|
||||||
|
}
|
||||||
|
|
||||||
public ChunkTaskScheduler(final ServerLevel world) {
|
public ChunkTaskScheduler(final ServerLevel world) {
|
||||||
this.world = world;
|
this.world = world;
|
||||||
// must be >= region shift (in paper, doesn't exist) and must be >= ticket propagator section shift
|
// must be >= region shift (in paper, doesn't exist) and must be >= ticket propagator section shift
|
||||||
@@ -526,6 +535,13 @@ public final class ChunkTaskScheduler {
|
|||||||
return loaded;
|
return loaded;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.hasShutdown()) {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"Chunk system has shut down, cannot process chunk requests in world '" + ca.spottedleaf.moonrise.common.util.WorldUtil.getWorldName(this.world) + "' at "
|
||||||
|
+ "(" + chunkX + "," + chunkZ + ") status: " + status
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
final Long ticketId = getNextNonFullLoadId();
|
final Long ticketId = getNextNonFullLoadId();
|
||||||
final int ticketLevel = getTicketLevel(status);
|
final int ticketLevel = getTicketLevel(status);
|
||||||
this.chunkHolderManager.addTicketAtLevel(NON_FULL_CHUNK_LOAD, chunkX, chunkZ, ticketLevel, ticketId);
|
this.chunkHolderManager.addTicketAtLevel(NON_FULL_CHUNK_LOAD, chunkX, chunkZ, ticketLevel, ticketId);
|
||||||
@@ -580,7 +596,7 @@ public final class ChunkTaskScheduler {
|
|||||||
this.chunkHolderManager.processTicketUpdates();
|
this.chunkHolderManager.processTicketUpdates();
|
||||||
}
|
}
|
||||||
|
|
||||||
final Consumer<ChunkAccess> loadCallback = (final ChunkAccess chunk) -> {
|
final Consumer<ChunkAccess> loadCallback = onComplete == null && !addTicket ? null : (final ChunkAccess chunk) -> {
|
||||||
try {
|
try {
|
||||||
if (onComplete != null) {
|
if (onComplete != null) {
|
||||||
onComplete.accept(chunk);
|
onComplete.accept(chunk);
|
||||||
@@ -617,7 +633,9 @@ public final class ChunkTaskScheduler {
|
|||||||
if (!chunkHolder.upgradeGenTarget(toStatus)) {
|
if (!chunkHolder.upgradeGenTarget(toStatus)) {
|
||||||
this.schedule(chunkX, chunkZ, toStatus, chunkHolder, tasks);
|
this.schedule(chunkX, chunkZ, toStatus, chunkHolder, tasks);
|
||||||
}
|
}
|
||||||
chunkHolder.addStatusConsumer(toStatus, loadCallback);
|
if (loadCallback != null) {
|
||||||
|
chunkHolder.addStatusConsumer(toStatus, loadCallback);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
@@ -631,7 +649,7 @@ public final class ChunkTaskScheduler {
|
|||||||
tasks.get(i).schedule();
|
tasks.get(i).schedule();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!scheduled) {
|
if (loadCallback != null && !scheduled) {
|
||||||
// couldn't schedule
|
// couldn't schedule
|
||||||
try {
|
try {
|
||||||
loadCallback.accept(chunk);
|
loadCallback.accept(chunk);
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import ca.spottedleaf.moonrise.common.misc.LazyRunnable;
|
|||||||
import ca.spottedleaf.moonrise.common.util.CoordinateUtils;
|
import ca.spottedleaf.moonrise.common.util.CoordinateUtils;
|
||||||
import ca.spottedleaf.moonrise.common.util.TickThread;
|
import ca.spottedleaf.moonrise.common.util.TickThread;
|
||||||
import ca.spottedleaf.moonrise.common.util.WorldUtil;
|
import ca.spottedleaf.moonrise.common.util.WorldUtil;
|
||||||
import ca.spottedleaf.moonrise.common.util.ChunkSystem;
|
|
||||||
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkData;
|
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkData;
|
||||||
import ca.spottedleaf.moonrise.patches.chunk_system.io.MoonriseRegionFileIO;
|
import ca.spottedleaf.moonrise.patches.chunk_system.io.MoonriseRegionFileIO;
|
||||||
import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemLevel;
|
import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemLevel;
|
||||||
@@ -1078,7 +1077,7 @@ public final class NewChunkHolder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Don't really have a choice but to place this hook here
|
// Don't really have a choice but to place this hook here
|
||||||
PlatformHooks.get().onChunkHolderTicketChange(this.world, this, oldLevel, newLevel);
|
PlatformHooks.get().onChunkHolderTicketChange(this.world, this.vanillaChunkHolder, oldLevel, newLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
static final int NEIGHBOUR_RADIUS = 2;
|
static final int NEIGHBOUR_RADIUS = 2;
|
||||||
@@ -1270,10 +1269,10 @@ public final class NewChunkHolder {
|
|||||||
// state upgrade
|
// state upgrade
|
||||||
if (!current.isOrAfter(FullChunkStatus.FULL) && pending.isOrAfter(FullChunkStatus.FULL)) {
|
if (!current.isOrAfter(FullChunkStatus.FULL) && pending.isOrAfter(FullChunkStatus.FULL)) {
|
||||||
this.updateCurrentState(FullChunkStatus.FULL);
|
this.updateCurrentState(FullChunkStatus.FULL);
|
||||||
ChunkSystem.onChunkPreBorder(chunk, this.vanillaChunkHolder);
|
PlatformHooks.get().onChunkPreBorder(chunk, this.vanillaChunkHolder);
|
||||||
this.scheduler.chunkHolderManager.ensureInAutosave(this);
|
this.scheduler.chunkHolderManager.ensureInAutosave(this);
|
||||||
this.changeEntityChunkStatus(FullChunkStatus.FULL);
|
this.changeEntityChunkStatus(FullChunkStatus.FULL);
|
||||||
ChunkSystem.onChunkBorder(chunk, this.vanillaChunkHolder);
|
PlatformHooks.get().onChunkBorder(chunk, this.vanillaChunkHolder);
|
||||||
this.onFullChunkLoadChange(true, changedFullStatus);
|
this.onFullChunkLoadChange(true, changedFullStatus);
|
||||||
this.completeFullStatusConsumers(FullChunkStatus.FULL, chunk);
|
this.completeFullStatusConsumers(FullChunkStatus.FULL, chunk);
|
||||||
}
|
}
|
||||||
@@ -1281,34 +1280,34 @@ public final class NewChunkHolder {
|
|||||||
if (!current.isOrAfter(FullChunkStatus.BLOCK_TICKING) && pending.isOrAfter(FullChunkStatus.BLOCK_TICKING)) {
|
if (!current.isOrAfter(FullChunkStatus.BLOCK_TICKING) && pending.isOrAfter(FullChunkStatus.BLOCK_TICKING)) {
|
||||||
this.updateCurrentState(FullChunkStatus.BLOCK_TICKING);
|
this.updateCurrentState(FullChunkStatus.BLOCK_TICKING);
|
||||||
this.changeEntityChunkStatus(FullChunkStatus.BLOCK_TICKING);
|
this.changeEntityChunkStatus(FullChunkStatus.BLOCK_TICKING);
|
||||||
ChunkSystem.onChunkTicking(chunk, this.vanillaChunkHolder);
|
PlatformHooks.get().onChunkTicking(chunk, this.vanillaChunkHolder);
|
||||||
this.completeFullStatusConsumers(FullChunkStatus.BLOCK_TICKING, chunk);
|
this.completeFullStatusConsumers(FullChunkStatus.BLOCK_TICKING, chunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!current.isOrAfter(FullChunkStatus.ENTITY_TICKING) && pending.isOrAfter(FullChunkStatus.ENTITY_TICKING)) {
|
if (!current.isOrAfter(FullChunkStatus.ENTITY_TICKING) && pending.isOrAfter(FullChunkStatus.ENTITY_TICKING)) {
|
||||||
this.updateCurrentState(FullChunkStatus.ENTITY_TICKING);
|
this.updateCurrentState(FullChunkStatus.ENTITY_TICKING);
|
||||||
this.changeEntityChunkStatus(FullChunkStatus.ENTITY_TICKING);
|
this.changeEntityChunkStatus(FullChunkStatus.ENTITY_TICKING);
|
||||||
ChunkSystem.onChunkEntityTicking(chunk, this.vanillaChunkHolder);
|
PlatformHooks.get().onChunkEntityTicking(chunk, this.vanillaChunkHolder);
|
||||||
this.completeFullStatusConsumers(FullChunkStatus.ENTITY_TICKING, chunk);
|
this.completeFullStatusConsumers(FullChunkStatus.ENTITY_TICKING, chunk);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (current.isOrAfter(FullChunkStatus.ENTITY_TICKING) && !pending.isOrAfter(FullChunkStatus.ENTITY_TICKING)) {
|
if (current.isOrAfter(FullChunkStatus.ENTITY_TICKING) && !pending.isOrAfter(FullChunkStatus.ENTITY_TICKING)) {
|
||||||
this.changeEntityChunkStatus(FullChunkStatus.BLOCK_TICKING);
|
this.changeEntityChunkStatus(FullChunkStatus.BLOCK_TICKING);
|
||||||
ChunkSystem.onChunkNotEntityTicking(chunk, this.vanillaChunkHolder);
|
PlatformHooks.get().onChunkNotEntityTicking(chunk, this.vanillaChunkHolder);
|
||||||
this.updateCurrentState(FullChunkStatus.BLOCK_TICKING);
|
this.updateCurrentState(FullChunkStatus.BLOCK_TICKING);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (current.isOrAfter(FullChunkStatus.BLOCK_TICKING) && !pending.isOrAfter(FullChunkStatus.BLOCK_TICKING)) {
|
if (current.isOrAfter(FullChunkStatus.BLOCK_TICKING) && !pending.isOrAfter(FullChunkStatus.BLOCK_TICKING)) {
|
||||||
this.changeEntityChunkStatus(FullChunkStatus.FULL);
|
this.changeEntityChunkStatus(FullChunkStatus.FULL);
|
||||||
ChunkSystem.onChunkNotTicking(chunk, this.vanillaChunkHolder);
|
PlatformHooks.get().onChunkNotTicking(chunk, this.vanillaChunkHolder);
|
||||||
this.updateCurrentState(FullChunkStatus.FULL);
|
this.updateCurrentState(FullChunkStatus.FULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (current.isOrAfter(FullChunkStatus.FULL) && !pending.isOrAfter(FullChunkStatus.FULL)) {
|
if (current.isOrAfter(FullChunkStatus.FULL) && !pending.isOrAfter(FullChunkStatus.FULL)) {
|
||||||
this.onFullChunkLoadChange(false, changedFullStatus);
|
this.onFullChunkLoadChange(false, changedFullStatus);
|
||||||
this.changeEntityChunkStatus(FullChunkStatus.INACCESSIBLE);
|
this.changeEntityChunkStatus(FullChunkStatus.INACCESSIBLE);
|
||||||
ChunkSystem.onChunkNotBorder(chunk, this.vanillaChunkHolder);
|
PlatformHooks.get().onChunkNotBorder(chunk, this.vanillaChunkHolder);
|
||||||
ChunkSystem.onChunkPostNotBorder(chunk, this.vanillaChunkHolder);
|
PlatformHooks.get().onChunkPostNotBorder(chunk, this.vanillaChunkHolder);
|
||||||
this.updateCurrentState(FullChunkStatus.INACCESSIBLE);
|
this.updateCurrentState(FullChunkStatus.INACCESSIBLE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,9 @@ import net.minecraft.core.BlockPos;
|
|||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
import net.minecraft.util.Mth;
|
import net.minecraft.util.Mth;
|
||||||
import net.minecraft.world.entity.Entity;
|
import net.minecraft.world.entity.Entity;
|
||||||
|
import net.minecraft.world.entity.vehicle.AbstractMinecart;
|
||||||
import net.minecraft.world.item.Item;
|
import net.minecraft.world.item.Item;
|
||||||
|
import net.minecraft.world.level.CollisionGetter;
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
import net.minecraft.world.level.block.Blocks;
|
import net.minecraft.world.level.block.Blocks;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
@@ -164,11 +166,11 @@ public final class CollisionUtil {
|
|||||||
|
|
||||||
// startIndex and endIndex inclusive
|
// startIndex and endIndex inclusive
|
||||||
// assumes indices are in range of array
|
// assumes indices are in range of array
|
||||||
public static int findFloor(final double[] values, final double value, int startIndex, int endIndex) {
|
public static int findFloor(final double[] values, final double offset, final double value, int startIndex, int endIndex) {
|
||||||
Objects.checkFromToIndex(startIndex, endIndex + 1, values.length);
|
Objects.checkFromToIndex(startIndex, endIndex + 1, values.length);
|
||||||
do {
|
do {
|
||||||
final int middle = (startIndex + endIndex) >>> 1;
|
final int middle = (startIndex + endIndex) >>> 1;
|
||||||
final double middleVal = values[middle];
|
final double middleVal = (values[middle] + offset);
|
||||||
|
|
||||||
if (value < middleVal) {
|
if (value < middleVal) {
|
||||||
endIndex = middle - 1;
|
endIndex = middle - 1;
|
||||||
@@ -417,8 +419,6 @@ public final class CollisionUtil {
|
|||||||
// an AABB(coords_x[x], coords_y[y], coords_z[z], coords_x[x + 1], coords_y[y + 1], coords_z[z + 1])
|
// an AABB(coords_x[x], coords_y[y], coords_z[z], coords_x[x + 1], coords_y[y + 1], coords_z[z + 1])
|
||||||
// is collidable. this is the fundamental principle of operation for the voxel collision operation
|
// is collidable. this is the fundamental principle of operation for the voxel collision operation
|
||||||
|
|
||||||
// note: we should be offsetting coords, but we can also just subtract from source as well - which is
|
|
||||||
// a win in terms of ops / simplicity (see findFloor, allows us to not modify coords for that)
|
|
||||||
// note: for intersection, one we find the floor of the min we can use that as the start index
|
// note: for intersection, one we find the floor of the min we can use that as the start index
|
||||||
// for the next check as source max >= source min
|
// for the next check as source max >= source min
|
||||||
// note: we can fast check intersection on the two other axis by seeing if the min index is >= size,
|
// note: we can fast check intersection on the two other axis by seeing if the min index is >= size,
|
||||||
@@ -427,7 +427,7 @@ public final class CollisionUtil {
|
|||||||
|
|
||||||
final int floor_min_x = Math.max(
|
final int floor_min_x = Math.max(
|
||||||
0,
|
0,
|
||||||
findFloor(coords_x, (aabb.minX - off_x) + COLLISION_EPSILON, 0, size_x)
|
findFloor(coords_x, off_x, aabb.minX + COLLISION_EPSILON, 0, size_x)
|
||||||
);
|
);
|
||||||
if (floor_min_x >= size_x) {
|
if (floor_min_x >= size_x) {
|
||||||
// cannot intersect
|
// cannot intersect
|
||||||
@@ -436,7 +436,7 @@ public final class CollisionUtil {
|
|||||||
|
|
||||||
final int ceil_max_x = Math.min(
|
final int ceil_max_x = Math.min(
|
||||||
size_x,
|
size_x,
|
||||||
findFloor(coords_x, (aabb.maxX - off_x) - COLLISION_EPSILON, floor_min_x, size_x) + 1
|
findFloor(coords_x, off_x, aabb.maxX - COLLISION_EPSILON, floor_min_x, size_x) + 1
|
||||||
);
|
);
|
||||||
if (floor_min_x >= ceil_max_x) {
|
if (floor_min_x >= ceil_max_x) {
|
||||||
// cannot intersect
|
// cannot intersect
|
||||||
@@ -445,7 +445,7 @@ public final class CollisionUtil {
|
|||||||
|
|
||||||
final int floor_min_y = Math.max(
|
final int floor_min_y = Math.max(
|
||||||
0,
|
0,
|
||||||
findFloor(coords_y, (aabb.minY - off_y) + COLLISION_EPSILON, 0, size_y)
|
findFloor(coords_y, off_y, aabb.minY + COLLISION_EPSILON, 0, size_y)
|
||||||
);
|
);
|
||||||
if (floor_min_y >= size_y) {
|
if (floor_min_y >= size_y) {
|
||||||
// cannot intersect
|
// cannot intersect
|
||||||
@@ -454,7 +454,7 @@ public final class CollisionUtil {
|
|||||||
|
|
||||||
final int ceil_max_y = Math.min(
|
final int ceil_max_y = Math.min(
|
||||||
size_y,
|
size_y,
|
||||||
findFloor(coords_y, (aabb.maxY - off_y) - COLLISION_EPSILON, floor_min_y, size_y) + 1
|
findFloor(coords_y, off_y, aabb.maxY - COLLISION_EPSILON, floor_min_y, size_y) + 1
|
||||||
);
|
);
|
||||||
if (floor_min_y >= ceil_max_y) {
|
if (floor_min_y >= ceil_max_y) {
|
||||||
// cannot intersect
|
// cannot intersect
|
||||||
@@ -463,7 +463,7 @@ public final class CollisionUtil {
|
|||||||
|
|
||||||
final int floor_min_z = Math.max(
|
final int floor_min_z = Math.max(
|
||||||
0,
|
0,
|
||||||
findFloor(coords_z, (aabb.minZ - off_z) + COLLISION_EPSILON, 0, size_z)
|
findFloor(coords_z, off_z, aabb.minZ + COLLISION_EPSILON, 0, size_z)
|
||||||
);
|
);
|
||||||
if (floor_min_z >= size_z) {
|
if (floor_min_z >= size_z) {
|
||||||
// cannot intersect
|
// cannot intersect
|
||||||
@@ -472,7 +472,7 @@ public final class CollisionUtil {
|
|||||||
|
|
||||||
final int ceil_max_z = Math.min(
|
final int ceil_max_z = Math.min(
|
||||||
size_z,
|
size_z,
|
||||||
findFloor(coords_z, (aabb.maxZ - off_z) - COLLISION_EPSILON, floor_min_z, size_z) + 1
|
findFloor(coords_z, off_z, aabb.maxZ - COLLISION_EPSILON, floor_min_z, size_z) + 1
|
||||||
);
|
);
|
||||||
if (floor_min_z >= ceil_max_z) {
|
if (floor_min_z >= ceil_max_z) {
|
||||||
// cannot intersect
|
// cannot intersect
|
||||||
@@ -528,8 +528,6 @@ public final class CollisionUtil {
|
|||||||
// is collidable. this is the fundamental principle of operation for the voxel collision operation
|
// is collidable. this is the fundamental principle of operation for the voxel collision operation
|
||||||
|
|
||||||
|
|
||||||
// note: we should be offsetting coords, but we can also just subtract from source as well - which is
|
|
||||||
// a win in terms of ops / simplicity (see findFloor, allows us to not modify coords for that)
|
|
||||||
// note: for intersection, one we find the floor of the min we can use that as the start index
|
// note: for intersection, one we find the floor of the min we can use that as the start index
|
||||||
// for the next check as source max >= source min
|
// for the next check as source max >= source min
|
||||||
// note: we can fast check intersection on the two other axis by seeing if the min index is >= size,
|
// note: we can fast check intersection on the two other axis by seeing if the min index is >= size,
|
||||||
@@ -538,7 +536,7 @@ public final class CollisionUtil {
|
|||||||
|
|
||||||
final int floor_min_y = Math.max(
|
final int floor_min_y = Math.max(
|
||||||
0,
|
0,
|
||||||
findFloor(coords_y, (source.minY - off_y) + COLLISION_EPSILON, 0, size_y)
|
findFloor(coords_y, off_y, source.minY + COLLISION_EPSILON, 0, size_y)
|
||||||
);
|
);
|
||||||
if (floor_min_y >= size_y) {
|
if (floor_min_y >= size_y) {
|
||||||
// cannot intersect
|
// cannot intersect
|
||||||
@@ -547,7 +545,7 @@ public final class CollisionUtil {
|
|||||||
|
|
||||||
final int ceil_max_y = Math.min(
|
final int ceil_max_y = Math.min(
|
||||||
size_y,
|
size_y,
|
||||||
findFloor(coords_y, (source.maxY - off_y) - COLLISION_EPSILON, floor_min_y, size_y) + 1
|
findFloor(coords_y, off_y, source.maxY - COLLISION_EPSILON, floor_min_y, size_y) + 1
|
||||||
);
|
);
|
||||||
if (floor_min_y >= ceil_max_y) {
|
if (floor_min_y >= ceil_max_y) {
|
||||||
// cannot intersect
|
// cannot intersect
|
||||||
@@ -556,7 +554,7 @@ public final class CollisionUtil {
|
|||||||
|
|
||||||
final int floor_min_z = Math.max(
|
final int floor_min_z = Math.max(
|
||||||
0,
|
0,
|
||||||
findFloor(coords_z, (source.minZ - off_z) + COLLISION_EPSILON, 0, size_z)
|
findFloor(coords_z, off_z, source.minZ + COLLISION_EPSILON, 0, size_z)
|
||||||
);
|
);
|
||||||
if (floor_min_z >= size_z) {
|
if (floor_min_z >= size_z) {
|
||||||
// cannot intersect
|
// cannot intersect
|
||||||
@@ -565,7 +563,7 @@ public final class CollisionUtil {
|
|||||||
|
|
||||||
final int ceil_max_z = Math.min(
|
final int ceil_max_z = Math.min(
|
||||||
size_z,
|
size_z,
|
||||||
findFloor(coords_z, (source.maxZ - off_z) - COLLISION_EPSILON, floor_min_z, size_z) + 1
|
findFloor(coords_z, off_z, source.maxZ - COLLISION_EPSILON, floor_min_z, size_z) + 1
|
||||||
);
|
);
|
||||||
if (floor_min_z >= ceil_max_z) {
|
if (floor_min_z >= ceil_max_z) {
|
||||||
// cannot intersect
|
// cannot intersect
|
||||||
@@ -577,9 +575,9 @@ public final class CollisionUtil {
|
|||||||
final long[] bitset = cached_shape_data.voxelSet();
|
final long[] bitset = cached_shape_data.voxelSet();
|
||||||
|
|
||||||
if (source_move > 0.0) {
|
if (source_move > 0.0) {
|
||||||
final double source_max = source.maxX - off_x;
|
final double source_max = source.maxX;
|
||||||
final int ceil_max_x = findFloor(
|
final int ceil_max_x = findFloor(
|
||||||
coords_x, source_max - COLLISION_EPSILON, 0, size_x
|
coords_x, off_x, source_max - COLLISION_EPSILON, 0, size_x
|
||||||
) + 1; // add one, we are not interested in (coords[i] + COLLISION_EPSILON) < max
|
) + 1; // add one, we are not interested in (coords[i] + COLLISION_EPSILON) < max
|
||||||
|
|
||||||
// note: only the order of the first loop matters
|
// note: only the order of the first loop matters
|
||||||
@@ -588,7 +586,7 @@ public final class CollisionUtil {
|
|||||||
|
|
||||||
final int mul_x = size_y*size_z;
|
final int mul_x = size_y*size_z;
|
||||||
for (int curr_x = ceil_max_x; curr_x < size_x; ++curr_x) {
|
for (int curr_x = ceil_max_x; curr_x < size_x; ++curr_x) {
|
||||||
double max_dist = coords_x[curr_x] - source_max;
|
double max_dist = (coords_x[curr_x] + off_x) - source_max;
|
||||||
if (max_dist >= source_move) {
|
if (max_dist >= source_move) {
|
||||||
// if we reach here, then we will never have a case where
|
// if we reach here, then we will never have a case where
|
||||||
// coords[curr + n] - source_max < source_move, as coords[curr + n] < coords[curr + n + 1]
|
// coords[curr + n] - source_max < source_move, as coords[curr + n] < coords[curr + n + 1]
|
||||||
@@ -615,9 +613,9 @@ public final class CollisionUtil {
|
|||||||
|
|
||||||
return source_move;
|
return source_move;
|
||||||
} else {
|
} else {
|
||||||
final double source_min = source.minX - off_x;
|
final double source_min = source.minX;
|
||||||
final int floor_min_x = findFloor(
|
final int floor_min_x = findFloor(
|
||||||
coords_x, source_min + COLLISION_EPSILON, 0, size_x
|
coords_x, off_x, source_min + COLLISION_EPSILON, 0, size_x
|
||||||
);
|
);
|
||||||
|
|
||||||
// note: only the order of the first loop matters
|
// note: only the order of the first loop matters
|
||||||
@@ -629,7 +627,7 @@ public final class CollisionUtil {
|
|||||||
// thus, we need to use the voxel index i-1 if we want to check that the face at index i is solid
|
// thus, we need to use the voxel index i-1 if we want to check that the face at index i is solid
|
||||||
final int mul_x = size_y*size_z;
|
final int mul_x = size_y*size_z;
|
||||||
for (int curr_x = floor_min_x - 1; curr_x >= 0; --curr_x) {
|
for (int curr_x = floor_min_x - 1; curr_x >= 0; --curr_x) {
|
||||||
double max_dist = coords_x[curr_x + 1] - source_min;
|
double max_dist = (coords_x[curr_x + 1] + off_x) - source_min;
|
||||||
if (max_dist <= source_move) {
|
if (max_dist <= source_move) {
|
||||||
// if we reach here, then we will never have a case where
|
// if we reach here, then we will never have a case where
|
||||||
// coords[curr + n] - source_max > source_move, as coords[curr + n] > coords[curr + n - 1]
|
// coords[curr + n] - source_max > source_move, as coords[curr + n] > coords[curr + n - 1]
|
||||||
@@ -686,8 +684,6 @@ public final class CollisionUtil {
|
|||||||
// is collidable. this is the fundamental principle of operation for the voxel collision operation
|
// is collidable. this is the fundamental principle of operation for the voxel collision operation
|
||||||
|
|
||||||
|
|
||||||
// note: we should be offsetting coords, but we can also just subtract from source as well - which is
|
|
||||||
// a win in terms of ops / simplicity (see findFloor, allows us to not modify coords for that)
|
|
||||||
// note: for intersection, one we find the floor of the min we can use that as the start index
|
// note: for intersection, one we find the floor of the min we can use that as the start index
|
||||||
// for the next check as source max >= source min
|
// for the next check as source max >= source min
|
||||||
// note: we can fast check intersection on the two other axis by seeing if the min index is >= size,
|
// note: we can fast check intersection on the two other axis by seeing if the min index is >= size,
|
||||||
@@ -696,7 +692,7 @@ public final class CollisionUtil {
|
|||||||
|
|
||||||
final int floor_min_x = Math.max(
|
final int floor_min_x = Math.max(
|
||||||
0,
|
0,
|
||||||
findFloor(coords_x, (source.minX - off_x) + COLLISION_EPSILON, 0, size_x)
|
findFloor(coords_x, off_x, source.minX + COLLISION_EPSILON, 0, size_x)
|
||||||
);
|
);
|
||||||
if (floor_min_x >= size_x) {
|
if (floor_min_x >= size_x) {
|
||||||
// cannot intersect
|
// cannot intersect
|
||||||
@@ -705,7 +701,7 @@ public final class CollisionUtil {
|
|||||||
|
|
||||||
final int ceil_max_x = Math.min(
|
final int ceil_max_x = Math.min(
|
||||||
size_x,
|
size_x,
|
||||||
findFloor(coords_x, (source.maxX - off_x) - COLLISION_EPSILON, floor_min_x, size_x) + 1
|
findFloor(coords_x, off_x, source.maxX - COLLISION_EPSILON, floor_min_x, size_x) + 1
|
||||||
);
|
);
|
||||||
if (floor_min_x >= ceil_max_x) {
|
if (floor_min_x >= ceil_max_x) {
|
||||||
// cannot intersect
|
// cannot intersect
|
||||||
@@ -714,7 +710,7 @@ public final class CollisionUtil {
|
|||||||
|
|
||||||
final int floor_min_z = Math.max(
|
final int floor_min_z = Math.max(
|
||||||
0,
|
0,
|
||||||
findFloor(coords_z, (source.minZ - off_z) + COLLISION_EPSILON, 0, size_z)
|
findFloor(coords_z, off_z, source.minZ + COLLISION_EPSILON, 0, size_z)
|
||||||
);
|
);
|
||||||
if (floor_min_z >= size_z) {
|
if (floor_min_z >= size_z) {
|
||||||
// cannot intersect
|
// cannot intersect
|
||||||
@@ -723,7 +719,7 @@ public final class CollisionUtil {
|
|||||||
|
|
||||||
final int ceil_max_z = Math.min(
|
final int ceil_max_z = Math.min(
|
||||||
size_z,
|
size_z,
|
||||||
findFloor(coords_z, (source.maxZ - off_z) - COLLISION_EPSILON, floor_min_z, size_z) + 1
|
findFloor(coords_z, off_z, source.maxZ - COLLISION_EPSILON, floor_min_z, size_z) + 1
|
||||||
);
|
);
|
||||||
if (floor_min_z >= ceil_max_z) {
|
if (floor_min_z >= ceil_max_z) {
|
||||||
// cannot intersect
|
// cannot intersect
|
||||||
@@ -735,9 +731,9 @@ public final class CollisionUtil {
|
|||||||
final long[] bitset = cached_shape_data.voxelSet();
|
final long[] bitset = cached_shape_data.voxelSet();
|
||||||
|
|
||||||
if (source_move > 0.0) {
|
if (source_move > 0.0) {
|
||||||
final double source_max = source.maxY - off_y;
|
final double source_max = source.maxY;
|
||||||
final int ceil_max_y = findFloor(
|
final int ceil_max_y = findFloor(
|
||||||
coords_y, source_max - COLLISION_EPSILON, 0, size_y
|
coords_y, off_y, source_max - COLLISION_EPSILON, 0, size_y
|
||||||
) + 1; // add one, we are not interested in (coords[i] + COLLISION_EPSILON) < max
|
) + 1; // add one, we are not interested in (coords[i] + COLLISION_EPSILON) < max
|
||||||
|
|
||||||
// note: only the order of the first loop matters
|
// note: only the order of the first loop matters
|
||||||
@@ -746,7 +742,7 @@ public final class CollisionUtil {
|
|||||||
|
|
||||||
final int mul_x = size_y*size_z;
|
final int mul_x = size_y*size_z;
|
||||||
for (int curr_y = ceil_max_y; curr_y < size_y; ++curr_y) {
|
for (int curr_y = ceil_max_y; curr_y < size_y; ++curr_y) {
|
||||||
double max_dist = coords_y[curr_y] - source_max;
|
double max_dist = (coords_y[curr_y] + off_y) - source_max;
|
||||||
if (max_dist >= source_move) {
|
if (max_dist >= source_move) {
|
||||||
// if we reach here, then we will never have a case where
|
// if we reach here, then we will never have a case where
|
||||||
// coords[curr + n] - source_max < source_move, as coords[curr + n] < coords[curr + n + 1]
|
// coords[curr + n] - source_max < source_move, as coords[curr + n] < coords[curr + n + 1]
|
||||||
@@ -773,9 +769,9 @@ public final class CollisionUtil {
|
|||||||
|
|
||||||
return source_move;
|
return source_move;
|
||||||
} else {
|
} else {
|
||||||
final double source_min = source.minY - off_y;
|
final double source_min = source.minY;
|
||||||
final int floor_min_y = findFloor(
|
final int floor_min_y = findFloor(
|
||||||
coords_y, source_min + COLLISION_EPSILON, 0, size_y
|
coords_y, off_y, source_min + COLLISION_EPSILON, 0, size_y
|
||||||
);
|
);
|
||||||
|
|
||||||
// note: only the order of the first loop matters
|
// note: only the order of the first loop matters
|
||||||
@@ -787,7 +783,7 @@ public final class CollisionUtil {
|
|||||||
// thus, we need to use the voxel index i-1 if we want to check that the face at index i is solid
|
// thus, we need to use the voxel index i-1 if we want to check that the face at index i is solid
|
||||||
final int mul_x = size_y*size_z;
|
final int mul_x = size_y*size_z;
|
||||||
for (int curr_y = floor_min_y - 1; curr_y >= 0; --curr_y) {
|
for (int curr_y = floor_min_y - 1; curr_y >= 0; --curr_y) {
|
||||||
double max_dist = coords_y[curr_y + 1] - source_min;
|
double max_dist = (coords_y[curr_y + 1] + off_y) - source_min;
|
||||||
if (max_dist <= source_move) {
|
if (max_dist <= source_move) {
|
||||||
// if we reach here, then we will never have a case where
|
// if we reach here, then we will never have a case where
|
||||||
// coords[curr + n] - source_max > source_move, as coords[curr + n] > coords[curr + n - 1]
|
// coords[curr + n] - source_max > source_move, as coords[curr + n] > coords[curr + n - 1]
|
||||||
@@ -844,8 +840,6 @@ public final class CollisionUtil {
|
|||||||
// is collidable. this is the fundamental principle of operation for the voxel collision operation
|
// is collidable. this is the fundamental principle of operation for the voxel collision operation
|
||||||
|
|
||||||
|
|
||||||
// note: we should be offsetting coords, but we can also just subtract from source as well - which is
|
|
||||||
// a win in terms of ops / simplicity (see findFloor, allows us to not modify coords for that)
|
|
||||||
// note: for intersection, one we find the floor of the min we can use that as the start index
|
// note: for intersection, one we find the floor of the min we can use that as the start index
|
||||||
// for the next check as source max >= source min
|
// for the next check as source max >= source min
|
||||||
// note: we can fast check intersection on the two other axis by seeing if the min index is >= size,
|
// note: we can fast check intersection on the two other axis by seeing if the min index is >= size,
|
||||||
@@ -854,7 +848,7 @@ public final class CollisionUtil {
|
|||||||
|
|
||||||
final int floor_min_x = Math.max(
|
final int floor_min_x = Math.max(
|
||||||
0,
|
0,
|
||||||
findFloor(coords_x, (source.minX - off_x) + COLLISION_EPSILON, 0, size_x)
|
findFloor(coords_x, off_x, source.minX + COLLISION_EPSILON, 0, size_x)
|
||||||
);
|
);
|
||||||
if (floor_min_x >= size_x) {
|
if (floor_min_x >= size_x) {
|
||||||
// cannot intersect
|
// cannot intersect
|
||||||
@@ -863,7 +857,7 @@ public final class CollisionUtil {
|
|||||||
|
|
||||||
final int ceil_max_x = Math.min(
|
final int ceil_max_x = Math.min(
|
||||||
size_x,
|
size_x,
|
||||||
findFloor(coords_x, (source.maxX - off_x) - COLLISION_EPSILON, floor_min_x, size_x) + 1
|
findFloor(coords_x, off_x, source.maxX - COLLISION_EPSILON, floor_min_x, size_x) + 1
|
||||||
);
|
);
|
||||||
if (floor_min_x >= ceil_max_x) {
|
if (floor_min_x >= ceil_max_x) {
|
||||||
// cannot intersect
|
// cannot intersect
|
||||||
@@ -872,7 +866,7 @@ public final class CollisionUtil {
|
|||||||
|
|
||||||
final int floor_min_y = Math.max(
|
final int floor_min_y = Math.max(
|
||||||
0,
|
0,
|
||||||
findFloor(coords_y, (source.minY - off_y) + COLLISION_EPSILON, 0, size_y)
|
findFloor(coords_y, off_y, source.minY + COLLISION_EPSILON, 0, size_y)
|
||||||
);
|
);
|
||||||
if (floor_min_y >= size_y) {
|
if (floor_min_y >= size_y) {
|
||||||
// cannot intersect
|
// cannot intersect
|
||||||
@@ -881,7 +875,7 @@ public final class CollisionUtil {
|
|||||||
|
|
||||||
final int ceil_max_y = Math.min(
|
final int ceil_max_y = Math.min(
|
||||||
size_y,
|
size_y,
|
||||||
findFloor(coords_y, (source.maxY - off_y) - COLLISION_EPSILON, floor_min_y, size_y) + 1
|
findFloor(coords_y, off_y, source.maxY - COLLISION_EPSILON, floor_min_y, size_y) + 1
|
||||||
);
|
);
|
||||||
if (floor_min_y >= ceil_max_y) {
|
if (floor_min_y >= ceil_max_y) {
|
||||||
// cannot intersect
|
// cannot intersect
|
||||||
@@ -893,9 +887,9 @@ public final class CollisionUtil {
|
|||||||
final long[] bitset = cached_shape_data.voxelSet();
|
final long[] bitset = cached_shape_data.voxelSet();
|
||||||
|
|
||||||
if (source_move > 0.0) {
|
if (source_move > 0.0) {
|
||||||
final double source_max = source.maxZ - off_z;
|
final double source_max = source.maxZ;
|
||||||
final int ceil_max_z = findFloor(
|
final int ceil_max_z = findFloor(
|
||||||
coords_z, source_max - COLLISION_EPSILON, 0, size_z
|
coords_z, off_z, source_max - COLLISION_EPSILON, 0, size_z
|
||||||
) + 1; // add one, we are not interested in (coords[i] + COLLISION_EPSILON) < max
|
) + 1; // add one, we are not interested in (coords[i] + COLLISION_EPSILON) < max
|
||||||
|
|
||||||
// note: only the order of the first loop matters
|
// note: only the order of the first loop matters
|
||||||
@@ -904,7 +898,7 @@ public final class CollisionUtil {
|
|||||||
|
|
||||||
final int mul_x = size_y*size_z;
|
final int mul_x = size_y*size_z;
|
||||||
for (int curr_z = ceil_max_z; curr_z < size_z; ++curr_z) {
|
for (int curr_z = ceil_max_z; curr_z < size_z; ++curr_z) {
|
||||||
double max_dist = coords_z[curr_z] - source_max;
|
double max_dist = (coords_z[curr_z] + off_z) - source_max;
|
||||||
if (max_dist >= source_move) {
|
if (max_dist >= source_move) {
|
||||||
// if we reach here, then we will never have a case where
|
// if we reach here, then we will never have a case where
|
||||||
// coords[curr + n] - source_max < source_move, as coords[curr + n] < coords[curr + n + 1]
|
// coords[curr + n] - source_max < source_move, as coords[curr + n] < coords[curr + n + 1]
|
||||||
@@ -931,9 +925,9 @@ public final class CollisionUtil {
|
|||||||
|
|
||||||
return source_move;
|
return source_move;
|
||||||
} else {
|
} else {
|
||||||
final double source_min = source.minZ - off_z;
|
final double source_min = source.minZ;
|
||||||
final int floor_min_z = findFloor(
|
final int floor_min_z = findFloor(
|
||||||
coords_z, source_min + COLLISION_EPSILON, 0, size_z
|
coords_z, off_z, source_min + COLLISION_EPSILON, 0, size_z
|
||||||
);
|
);
|
||||||
|
|
||||||
// note: only the order of the first loop matters
|
// note: only the order of the first loop matters
|
||||||
@@ -945,7 +939,7 @@ public final class CollisionUtil {
|
|||||||
// thus, we need to use the voxel index i-1 if we want to check that the face at index i is solid
|
// thus, we need to use the voxel index i-1 if we want to check that the face at index i is solid
|
||||||
final int mul_x = size_y*size_z;
|
final int mul_x = size_y*size_z;
|
||||||
for (int curr_z = floor_min_z - 1; curr_z >= 0; --curr_z) {
|
for (int curr_z = floor_min_z - 1; curr_z >= 0; --curr_z) {
|
||||||
double max_dist = coords_z[curr_z + 1] - source_min;
|
double max_dist = (coords_z[curr_z + 1] + off_z) - source_min;
|
||||||
if (max_dist <= source_move) {
|
if (max_dist <= source_move) {
|
||||||
// if we reach here, then we will never have a case where
|
// if we reach here, then we will never have a case where
|
||||||
// coords[curr + n] - source_max > source_move, as coords[curr + n] > coords[curr + n - 1]
|
// coords[curr + n] - source_max > source_move, as coords[curr + n] > coords[curr + n - 1]
|
||||||
@@ -980,7 +974,7 @@ public final class CollisionUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// does not use epsilon
|
// does not use epsilon
|
||||||
public static boolean strictlyContains(final VoxelShape voxel, double x, double y, double z) {
|
public static boolean strictlyContains(final VoxelShape voxel, final double x, final double y, final double z) {
|
||||||
final AABB single_aabb = ((CollisionVoxelShape)voxel).moonrise$getSingleAABBRepresentation();
|
final AABB single_aabb = ((CollisionVoxelShape)voxel).moonrise$getSingleAABBRepresentation();
|
||||||
if (single_aabb != null) {
|
if (single_aabb != null) {
|
||||||
return single_aabb.contains(x, y, z);
|
return single_aabb.contains(x, y, z);
|
||||||
@@ -991,10 +985,9 @@ public final class CollisionUtil {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// offset input
|
final double off_x = ((CollisionVoxelShape)voxel).moonrise$offsetX();
|
||||||
x -= ((CollisionVoxelShape)voxel).moonrise$offsetX();
|
final double off_y = ((CollisionVoxelShape)voxel).moonrise$offsetY();
|
||||||
y -= ((CollisionVoxelShape)voxel).moonrise$offsetY();
|
final double off_z = ((CollisionVoxelShape)voxel).moonrise$offsetZ();
|
||||||
z -= ((CollisionVoxelShape)voxel).moonrise$offsetZ();
|
|
||||||
|
|
||||||
final double[] coords_x = ((CollisionVoxelShape)voxel).moonrise$rootCoordinatesX();
|
final double[] coords_x = ((CollisionVoxelShape)voxel).moonrise$rootCoordinatesX();
|
||||||
final double[] coords_y = ((CollisionVoxelShape)voxel).moonrise$rootCoordinatesY();
|
final double[] coords_y = ((CollisionVoxelShape)voxel).moonrise$rootCoordinatesY();
|
||||||
@@ -1010,17 +1003,17 @@ public final class CollisionUtil {
|
|||||||
// note: should mirror AABB#contains, which is that for any point X that X >= min and X < max.
|
// note: should mirror AABB#contains, which is that for any point X that X >= min and X < max.
|
||||||
// specifically, it cannot collide on the max bounds of the shape
|
// specifically, it cannot collide on the max bounds of the shape
|
||||||
|
|
||||||
final int index_x = findFloor(coords_x, x, 0, size_x);
|
final int index_x = findFloor(coords_x, off_x, x, 0, size_x);
|
||||||
if (index_x < 0 || index_x >= size_x) {
|
if (index_x < 0 || index_x >= size_x) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
final int index_y = findFloor(coords_y, y, 0, size_y);
|
final int index_y = findFloor(coords_y, off_y, y, 0, size_y);
|
||||||
if (index_y < 0 || index_y >= size_y) {
|
if (index_y < 0 || index_y >= size_y) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
final int index_z = findFloor(coords_z, z, 0, size_z);
|
final int index_z = findFloor(coords_z, off_z, z, 0, size_z);
|
||||||
if (index_z < 0 || index_z >= size_z) {
|
if (index_z < 0 || index_z >= size_z) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -1693,74 +1686,56 @@ public final class CollisionUtil {
|
|||||||
|
|
||||||
public static double performAABBCollisionsX(final AABB currentBoundingBox, double value, final List<AABB> potentialCollisions) {
|
public static double performAABBCollisionsX(final AABB currentBoundingBox, double value, final List<AABB> potentialCollisions) {
|
||||||
for (int i = 0, len = potentialCollisions.size(); i < len; ++i) {
|
for (int i = 0, len = potentialCollisions.size(); i < len; ++i) {
|
||||||
if (Math.abs(value) < COLLISION_EPSILON) {
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
final AABB target = potentialCollisions.get(i);
|
final AABB target = potentialCollisions.get(i);
|
||||||
value = collideX(target, currentBoundingBox, value);
|
value = collideX(target, currentBoundingBox, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Math.abs(value) < COLLISION_EPSILON ? 0.0 : value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static double performAABBCollisionsY(final AABB currentBoundingBox, double value, final List<AABB> potentialCollisions) {
|
public static double performAABBCollisionsY(final AABB currentBoundingBox, double value, final List<AABB> potentialCollisions) {
|
||||||
for (int i = 0, len = potentialCollisions.size(); i < len; ++i) {
|
for (int i = 0, len = potentialCollisions.size(); i < len; ++i) {
|
||||||
if (Math.abs(value) < COLLISION_EPSILON) {
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
final AABB target = potentialCollisions.get(i);
|
final AABB target = potentialCollisions.get(i);
|
||||||
value = collideY(target, currentBoundingBox, value);
|
value = collideY(target, currentBoundingBox, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Math.abs(value) < COLLISION_EPSILON ? 0.0 : value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static double performAABBCollisionsZ(final AABB currentBoundingBox, double value, final List<AABB> potentialCollisions) {
|
public static double performAABBCollisionsZ(final AABB currentBoundingBox, double value, final List<AABB> potentialCollisions) {
|
||||||
for (int i = 0, len = potentialCollisions.size(); i < len; ++i) {
|
for (int i = 0, len = potentialCollisions.size(); i < len; ++i) {
|
||||||
if (Math.abs(value) < COLLISION_EPSILON) {
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
final AABB target = potentialCollisions.get(i);
|
final AABB target = potentialCollisions.get(i);
|
||||||
value = collideZ(target, currentBoundingBox, value);
|
value = collideZ(target, currentBoundingBox, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Math.abs(value) < COLLISION_EPSILON ? 0.0 : value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static double performVoxelCollisionsX(final AABB currentBoundingBox, double value, final List<VoxelShape> potentialCollisions) {
|
public static double performVoxelCollisionsX(final AABB currentBoundingBox, double value, final List<VoxelShape> potentialCollisions) {
|
||||||
for (int i = 0, len = potentialCollisions.size(); i < len; ++i) {
|
for (int i = 0, len = potentialCollisions.size(); i < len; ++i) {
|
||||||
if (Math.abs(value) < COLLISION_EPSILON) {
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
final VoxelShape target = potentialCollisions.get(i);
|
final VoxelShape target = potentialCollisions.get(i);
|
||||||
value = collideX(target, currentBoundingBox, value);
|
value = collideX(target, currentBoundingBox, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Math.abs(value) < COLLISION_EPSILON ? 0.0 : value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static double performVoxelCollisionsY(final AABB currentBoundingBox, double value, final List<VoxelShape> potentialCollisions) {
|
public static double performVoxelCollisionsY(final AABB currentBoundingBox, double value, final List<VoxelShape> potentialCollisions) {
|
||||||
for (int i = 0, len = potentialCollisions.size(); i < len; ++i) {
|
for (int i = 0, len = potentialCollisions.size(); i < len; ++i) {
|
||||||
if (Math.abs(value) < COLLISION_EPSILON) {
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
final VoxelShape target = potentialCollisions.get(i);
|
final VoxelShape target = potentialCollisions.get(i);
|
||||||
value = collideY(target, currentBoundingBox, value);
|
value = collideY(target, currentBoundingBox, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Math.abs(value) < COLLISION_EPSILON ? 0.0 : value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static double performVoxelCollisionsZ(final AABB currentBoundingBox, double value, final List<VoxelShape> potentialCollisions) {
|
public static double performVoxelCollisionsZ(final AABB currentBoundingBox, double value, final List<VoxelShape> potentialCollisions) {
|
||||||
for (int i = 0, len = potentialCollisions.size(); i < len; ++i) {
|
for (int i = 0, len = potentialCollisions.size(); i < len; ++i) {
|
||||||
if (Math.abs(value) < COLLISION_EPSILON) {
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
final VoxelShape target = potentialCollisions.get(i);
|
final VoxelShape target = potentialCollisions.get(i);
|
||||||
value = collideZ(target, currentBoundingBox, value);
|
value = collideZ(target, currentBoundingBox, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Math.abs(value) < COLLISION_EPSILON ? 0.0 : value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Vec3 performVoxelCollisions(final Vec3 moveVector, AABB axisalignedbb, final List<VoxelShape> potentialCollisions) {
|
public static Vec3 performVoxelCollisions(final Vec3 moveVector, AABB axisalignedbb, final List<VoxelShape> potentialCollisions) {
|
||||||
@@ -1943,6 +1918,7 @@ public final class CollisionUtil {
|
|||||||
|
|
||||||
final BlockPos.MutableBlockPos mutablePos = new BlockPos.MutableBlockPos();
|
final BlockPos.MutableBlockPos mutablePos = new BlockPos.MutableBlockPos();
|
||||||
final CollisionContext collisionShape = new LazyEntityCollisionContext(entity);
|
final CollisionContext collisionShape = new LazyEntityCollisionContext(entity);
|
||||||
|
final boolean useEntityCollisionShape = LazyEntityCollisionContext.useEntityCollisionShape(world, entity);
|
||||||
|
|
||||||
// special cases:
|
// special cases:
|
||||||
if (minBlockY > maxBlockY) {
|
if (minBlockY > maxBlockY) {
|
||||||
@@ -2028,7 +2004,10 @@ public final class CollisionUtil {
|
|||||||
VoxelShape blockCollision = ((CollisionBlockState)blockData).moonrise$getConstantContextCollisionShape();
|
VoxelShape blockCollision = ((CollisionBlockState)blockData).moonrise$getConstantContextCollisionShape();
|
||||||
|
|
||||||
if (edgeCount == 0 || ((edgeCount != 1 || blockData.hasLargeCollisionShape()) && (edgeCount != 2 || blockData.getBlock() == Blocks.MOVING_PISTON))) {
|
if (edgeCount == 0 || ((edgeCount != 1 || blockData.hasLargeCollisionShape()) && (edgeCount != 2 || blockData.getBlock() == Blocks.MOVING_PISTON))) {
|
||||||
if (blockCollision == null) {
|
if (useEntityCollisionShape) {
|
||||||
|
mutablePos.set(blockX, blockY, blockZ);
|
||||||
|
blockCollision = collisionShape.getCollisionShape(blockData, world, mutablePos);
|
||||||
|
} else if (blockCollision == null) {
|
||||||
mutablePos.set(blockX, blockY, blockZ);
|
mutablePos.set(blockX, blockY, blockZ);
|
||||||
blockCollision = blockData.getCollisionShape(world, mutablePos, collisionShape);
|
blockCollision = blockData.getCollisionShape(world, mutablePos, collisionShape);
|
||||||
}
|
}
|
||||||
@@ -2150,6 +2129,10 @@ public final class CollisionUtil {
|
|||||||
super(false, 0.0, null, null, entity);
|
super(false, 0.0, null, null, entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean useEntityCollisionShape(final Level world, final Entity entity) {
|
||||||
|
return entity instanceof AbstractMinecart && AbstractMinecart.useExperimentalMovement(world);
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isDelegated() {
|
public boolean isDelegated() {
|
||||||
final boolean delegated = this.delegated;
|
final boolean delegated = this.delegated;
|
||||||
this.delegated = false;
|
this.delegated = false;
|
||||||
@@ -2158,10 +2141,16 @@ public final class CollisionUtil {
|
|||||||
|
|
||||||
public CollisionContext getDelegate() {
|
public CollisionContext getDelegate() {
|
||||||
this.delegated = true;
|
this.delegated = true;
|
||||||
final Entity entity = this.getEntity();
|
final Entity entity = super.getEntity();
|
||||||
return this.delegate == null ? this.delegate = (entity == null ? CollisionContext.empty() : CollisionContext.of(entity)) : this.delegate;
|
return this.delegate == null ? this.delegate = (entity == null ? CollisionContext.empty() : CollisionContext.of(entity)) : this.delegate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Entity getEntity() {
|
||||||
|
this.getDelegate();
|
||||||
|
return super.getEntity();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isDescending() {
|
public boolean isDescending() {
|
||||||
return this.getDelegate().isDescending();
|
return this.getDelegate().isDescending();
|
||||||
@@ -2181,6 +2170,11 @@ public final class CollisionUtil {
|
|||||||
public boolean canStandOnFluid(final FluidState state, final FluidState fluidState) {
|
public boolean canStandOnFluid(final FluidState state, final FluidState fluidState) {
|
||||||
return this.getDelegate().canStandOnFluid(state, fluidState);
|
return this.getDelegate().canStandOnFluid(state, fluidState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public VoxelShape getCollisionShape(final BlockState blockState, final CollisionGetter collisionGetter, final BlockPos blockPos) {
|
||||||
|
return this.getDelegate().getCollisionShape(blockState, collisionGetter, blockPos);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private CollisionUtil() {
|
private CollisionUtil() {
|
||||||
|
|||||||
@@ -237,7 +237,7 @@ public final class MoonriseCommand {
|
|||||||
return Command.SINGLE_SUCCESS;
|
return Command.SINGLE_SUCCESS;
|
||||||
} else {
|
} else {
|
||||||
ctx.getSource().sendFailure(
|
ctx.getSource().sendFailure(
|
||||||
Component.literal("Reloaded Moonrise config.")
|
Component.literal("Failed to reload Moonrise config, see logs.")
|
||||||
.withStyle(ChatFormatting.RED)
|
.withStyle(ChatFormatting.RED)
|
||||||
);
|
);
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ accessible field net/minecraft/world/level/chunk/PalettedContainer data Lnet/min
|
|||||||
|
|
||||||
# PalettedContainer.Data
|
# PalettedContainer.Data
|
||||||
accessible class net/minecraft/world/level/chunk/PalettedContainer$Data
|
accessible class net/minecraft/world/level/chunk/PalettedContainer$Data
|
||||||
|
# MDG requires we AT the constructor if we AT the class
|
||||||
|
accessible method net/minecraft/world/level/chunk/PalettedContainer$Data <init> (Lnet/minecraft/world/level/chunk/PalettedContainer$Configuration;Lnet/minecraft/util/BitStorage;Lnet/minecraft/world/level/chunk/Palette;)V
|
||||||
|
|
||||||
|
|
||||||
# PaletteResize
|
# PaletteResize
|
||||||
@@ -150,6 +152,11 @@ accessible method net/minecraft/world/level/material/Fluid isEmpty ()Z
|
|||||||
accessible method net/minecraft/world/level/material/Fluid createLegacyBlock (Lnet/minecraft/world/level/material/FluidState;)Lnet/minecraft/world/level/block/state/BlockState;
|
accessible method net/minecraft/world/level/material/Fluid createLegacyBlock (Lnet/minecraft/world/level/material/FluidState;)Lnet/minecraft/world/level/block/state/BlockState;
|
||||||
accessible method net/minecraft/world/level/material/Fluid isRandomlyTicking ()Z
|
accessible method net/minecraft/world/level/material/Fluid isRandomlyTicking ()Z
|
||||||
|
|
||||||
|
# We need to manually copy these down for MDG
|
||||||
|
accessible method net/minecraft/world/level/material/EmptyFluid isEmpty ()Z
|
||||||
|
accessible method net/minecraft/world/level/material/EmptyFluid createLegacyBlock (Lnet/minecraft/world/level/material/FluidState;)Lnet/minecraft/world/level/block/state/BlockState;
|
||||||
|
accessible method net/minecraft/world/level/material/LavaFluid createLegacyBlock (Lnet/minecraft/world/level/material/FluidState;)Lnet/minecraft/world/level/block/state/BlockState;
|
||||||
|
accessible method net/minecraft/world/level/material/LavaFluid isRandomlyTicking ()Z
|
||||||
|
|
||||||
# VisibilitySet
|
# VisibilitySet
|
||||||
accessible field net/minecraft/client/renderer/chunk/VisibilitySet FACINGS I
|
accessible field net/minecraft/client/renderer/chunk/VisibilitySet FACINGS I
|
||||||
@@ -305,3 +312,5 @@ accessible class net/minecraft/world/level/LocalMobCapCalculator$MobCounts
|
|||||||
|
|
||||||
# SectionStorage$PackedChunk
|
# SectionStorage$PackedChunk
|
||||||
accessible class net/minecraft/world/level/chunk/storage/SectionStorage$PackedChunk
|
accessible class net/minecraft/world/level/chunk/storage/SectionStorage$PackedChunk
|
||||||
|
# MDG requires we AT the constructor if we AT the class
|
||||||
|
accessible method net/minecraft/world/level/chunk/storage/SectionStorage$PackedChunk <init> (Lit/unimi/dsi/fastutil/ints/Int2ObjectMap;Z)V
|
||||||
|
|||||||
@@ -1,143 +1,145 @@
|
|||||||
{
|
{
|
||||||
"required": true,
|
"required": true,
|
||||||
"minVersion": "0.8",
|
"minVersion": "0.8",
|
||||||
"package": "ca.spottedleaf.moonrise.mixin",
|
"package": "ca.spottedleaf.moonrise.mixin",
|
||||||
"compatibilityLevel": "JAVA_21",
|
"compatibilityLevel": "JAVA_21",
|
||||||
"mixins": [
|
"mixins": [
|
||||||
"bitstorage.SimpleBitStorageMixin",
|
"bitstorage.SimpleBitStorageMixin",
|
||||||
"bitstorage.ZeroBitStorageMixin",
|
"bitstorage.ZeroBitStorageMixin",
|
||||||
"block_counting.BitStorageMixin",
|
"block_counting.BitStorageMixin",
|
||||||
"block_counting.LevelChunkSectionMixin",
|
"block_counting.LevelChunkSectionMixin",
|
||||||
"block_counting.SimpleBitStorageMixin",
|
"block_counting.SimpleBitStorageMixin",
|
||||||
"block_counting.ZeroBitStorageMixin",
|
"block_counting.ZeroBitStorageMixin",
|
||||||
"block_entity_remove.LevelMixin",
|
"block_entity_remove.LevelMixin",
|
||||||
"blockstate_propertyaccess.BooleanPropertyMixin",
|
"blockstate_propertyaccess.BooleanPropertyMixin",
|
||||||
"blockstate_propertyaccess.EnumPropertyMixin",
|
"blockstate_propertyaccess.EnumPropertyMixin",
|
||||||
"blockstate_propertyaccess.IntegerPropertyMixin",
|
"blockstate_propertyaccess.IntegerPropertyMixin",
|
||||||
"blockstate_propertyaccess.PropertyMixin",
|
"blockstate_propertyaccess.PropertyMixin",
|
||||||
"blockstate_propertyaccess.StateHolderMixin",
|
"blockstate_propertyaccess.StateHolderMixin",
|
||||||
"chunk_system.ChunkBufferMixin",
|
"chunk_system.ChunkBufferMixin",
|
||||||
"chunk_system.ChunkGeneratorMixin",
|
"chunk_system.ChunkGeneratorMixin",
|
||||||
"chunk_system.ChunkHolderMixin",
|
"chunk_system.ChunkHolderMixin",
|
||||||
"chunk_system.ChunkMap$DistanceManagerMixin",
|
"chunk_system.ChunkMap$DistanceManagerMixin",
|
||||||
"chunk_system.ChunkMapMixin",
|
"chunk_system.ChunkMapMixin",
|
||||||
"chunk_system.ChunkPyramidMixin",
|
"chunk_system.ChunkPyramidMixin",
|
||||||
"chunk_system.ChunkStatusMixin",
|
"chunk_system.ChunkStatusMixin",
|
||||||
"chunk_system.ChunkStepMixin",
|
"chunk_system.ChunkStepMixin",
|
||||||
"chunk_system.ChunkStorageMixin",
|
"chunk_system.ChunkStorageMixin",
|
||||||
"chunk_system.DistanceManagerMixin",
|
"chunk_system.DistanceManagerMixin",
|
||||||
"chunk_system.EntityGetterMixin",
|
"chunk_system.EntityGetterMixin",
|
||||||
"chunk_system.EntityMixin",
|
"chunk_system.EntityMixin",
|
||||||
"chunk_system.EntityTickListMixin",
|
"chunk_system.EntityTickListMixin",
|
||||||
"chunk_system.GenerationChunkHolderMixin",
|
"chunk_system.GenerationChunkHolderMixin",
|
||||||
"chunk_system.LevelChunkMixin",
|
"chunk_system.LevelChunkMixin",
|
||||||
"chunk_system.LevelChunkTicksMixin",
|
"chunk_system.LevelChunkTicksMixin",
|
||||||
"chunk_system.LevelMixin",
|
"chunk_system.LevelMixin",
|
||||||
"chunk_system.LevelReaderMixin",
|
"chunk_system.LevelReaderMixin",
|
||||||
"chunk_system.MinecraftServerMixin",
|
"chunk_system.MinecraftServerMixin",
|
||||||
"chunk_system.NoiseBasedChunkGeneratorMixin",
|
"chunk_system.NoiseBasedChunkGeneratorMixin",
|
||||||
"chunk_system.PlayerListMixin",
|
"chunk_system.PlayerListMixin",
|
||||||
"chunk_system.PoiManagerMixin",
|
"chunk_system.PoiManagerMixin",
|
||||||
"chunk_system.PoiSectionMixin",
|
"chunk_system.PoiSectionMixin",
|
||||||
"chunk_system.RegionFileMixin",
|
"chunk_system.RegionFileMixin",
|
||||||
"chunk_system.RegionFileStorageMixin",
|
"chunk_system.RegionFileStorageMixin",
|
||||||
"chunk_system.SectionStorageMixin",
|
"chunk_system.SectionStorageMixin",
|
||||||
"chunk_system.SerializableChunkDataMixin",
|
"chunk_system.SerializableChunkDataMixin",
|
||||||
"chunk_system.ServerChunkCache$MainThreadExecutorMixin",
|
"chunk_system.ServerChunkCache$MainThreadExecutorMixin",
|
||||||
"chunk_system.ServerChunkCacheMixin",
|
"chunk_system.ServerChunkCacheMixin",
|
||||||
"chunk_system.ServerLevelMixin",
|
"chunk_system.ServerLevelMixin",
|
||||||
"chunk_system.ServerPlayerMixin",
|
"chunk_system.ServerPlayerMixin",
|
||||||
"chunk_system.SortedArraySetMixin",
|
"chunk_system.SortedArraySetMixin",
|
||||||
"chunk_system.StructureCheckMixin",
|
"chunk_system.StructureCheckMixin",
|
||||||
"chunk_system.StructureTemplate$PaletteMixin",
|
"chunk_system.StructureTemplate$PaletteMixin",
|
||||||
"chunk_system.TicketMixin",
|
"chunk_system.TicketMixin",
|
||||||
"chunk_tick_iteration.ChunkMapMixin",
|
"chunk_tick_iteration.ChunkMapMixin",
|
||||||
"chunk_tick_iteration.DistanceManagerMixin",
|
"chunk_tick_iteration.DistanceManagerMixin",
|
||||||
"chunk_tick_iteration.ServerChunkCacheMixin",
|
"chunk_tick_iteration.ServerChunkCacheMixin",
|
||||||
"chunk_tick_iteration.ServerLevelMixin",
|
"chunk_tick_iteration.ServerLevelMixin",
|
||||||
"collisions.ArmorStandMixin",
|
"collisions.ArmorStandMixin",
|
||||||
"collisions.ArrayVoxelShapeMixin",
|
"collisions.ArrayVoxelShapeMixin",
|
||||||
"collisions.BitSetDiscreteVoxelShapeMixin",
|
"collisions.BitSetDiscreteVoxelShapeMixin",
|
||||||
"collisions.BlockMixin",
|
"collisions.BlockMixin",
|
||||||
"collisions.BlockPosMixin",
|
"collisions.BlockPosMixin",
|
||||||
"collisions.BlockStateBaseMixin",
|
"collisions.BlockStateBaseMixin",
|
||||||
"collisions.CubeVoxelShapeMixin",
|
"collisions.CubeVoxelShapeMixin",
|
||||||
"collisions.DirectionMixin",
|
"collisions.DirectionMixin",
|
||||||
"collisions.DiscreteVoxelShapeMixin",
|
"collisions.DiscreteVoxelShapeMixin",
|
||||||
"collisions.EntityGetterMixin",
|
"collisions.EntityGetterMixin",
|
||||||
"collisions.EntityMixin",
|
"collisions.EntityMixin",
|
||||||
"collisions.LevelMixin",
|
"collisions.LevelMixin",
|
||||||
"collisions.ServerEntityMixin",
|
"collisions.ServerEntityMixin",
|
||||||
"collisions.ServerExplosionMixin",
|
"collisions.ServerExplosionMixin",
|
||||||
"collisions.ShapesMixin",
|
"collisions.ShapesMixin",
|
||||||
"collisions.SliceShapeMixin",
|
"collisions.SliceShapeMixin",
|
||||||
"collisions.VoxelShapeMixin",
|
"collisions.VoxelShapeMixin",
|
||||||
"command.CommandsMixin",
|
"command.CommandsMixin",
|
||||||
"config.MinecraftServerMixin",
|
"config.MinecraftServerMixin",
|
||||||
"end_island.DensityFunctions$EndIslandDensityFunctionMixin",
|
"end_island.DensityFunctions$EndIslandDensityFunctionMixin",
|
||||||
"entity_tracker.ChunkMapMixin",
|
"entity_tracker.ChunkMapMixin",
|
||||||
"entity_tracker.EntityMixin",
|
"entity_tracker.EntityMixin",
|
||||||
"entity_tracker.TrackedEntityMixin",
|
"entity_tracker.TrackedEntityMixin",
|
||||||
"fast_palette.CrudeIncrementalIntIdentityHashBiMapMixin",
|
"fast_palette.CrudeIncrementalIntIdentityHashBiMapMixin",
|
||||||
"fast_palette.HashMapPaletteMixin",
|
"fast_palette.HashMapPaletteMixin",
|
||||||
"fast_palette.LinearPaletteMixin",
|
"fast_palette.LinearPaletteMixin",
|
||||||
"fast_palette.PalettedContainer$DataMixin",
|
"fast_palette.PalettedContainer$DataMixin",
|
||||||
"fast_palette.PalettedContainerMixin",
|
"fast_palette.PalettedContainerMixin",
|
||||||
"fast_palette.PaletteMixin",
|
"fast_palette.PaletteMixin",
|
||||||
"fast_palette.SingleValuePaletteMixin",
|
"fast_palette.SingleValuePaletteMixin",
|
||||||
"fluid.FlowingFluidMixin",
|
"fluid.FlowingFluidMixin",
|
||||||
"fluid.FluidStateMixin",
|
"fluid.FluidStateMixin",
|
||||||
"fluid.MappedRegistryMixin",
|
"fluid.MappedRegistryMixin",
|
||||||
"getblock.ChunkAccessMixin",
|
"getblock.ChunkAccessMixin",
|
||||||
"getblock.LevelChunkMixin",
|
"getblock.LevelChunkMixin",
|
||||||
"getblock.LevelMixin",
|
"getblock.LevelMixin",
|
||||||
"keep_alive_client.ServerGamePacketListenerImplMixin",
|
"keep_alive_client.ServerGamePacketListenerImplMixin",
|
||||||
"mob_spawning.EntityTypeMixin",
|
"mob_spawning.EntityTypeMixin",
|
||||||
"mob_spawning.LocalMobCapCalculator$MobCountsMixin",
|
"mob_spawning.LocalMobCapCalculator$MobCountsMixin",
|
||||||
"mob_spawning.MobSpawnSettingsMixin",
|
"mob_spawning.MobSpawnSettingsMixin",
|
||||||
"mob_spawning.NaturalSpawnerMixin",
|
"mob_spawning.NaturalSpawnerMixin",
|
||||||
"poi_lookup.AcquirePoiMixin",
|
"poi_lookup.AcquirePoiMixin",
|
||||||
"poi_lookup.PoiManagerMixin",
|
"poi_lookup.PoiManagerMixin",
|
||||||
"poi_lookup.PortalForcerMixin",
|
"poi_lookup.PortalForcerMixin",
|
||||||
"random_ticking.BiomeManagerMixin",
|
"random.EntityMixin",
|
||||||
"random_ticking.BiomeMixin",
|
"random.LevelMixin",
|
||||||
"random_ticking.LevelMixin",
|
"random_ticking.BiomeManagerMixin",
|
||||||
"random_ticking.ServerLevelMixin",
|
"random_ticking.BiomeMixin",
|
||||||
"serverlist.ConnectionMixin",
|
"random_ticking.LevelMixin",
|
||||||
"starlight.blockstate.BlockStateBaseMixin",
|
"random_ticking.ServerLevelMixin",
|
||||||
"starlight.chunk.ChunkAccessMixin",
|
"serverlist.ConnectionMixin",
|
||||||
"starlight.chunk.EmptyLevelChunkMixin",
|
"starlight.blockstate.BlockStateBaseMixin",
|
||||||
"starlight.chunk.ImposterProtoChunkMixin",
|
"starlight.chunk.ChunkAccessMixin",
|
||||||
"starlight.chunk.LevelChunkMixin",
|
"starlight.chunk.EmptyLevelChunkMixin",
|
||||||
"starlight.chunk.ProtoChunkMixin",
|
"starlight.chunk.ImposterProtoChunkMixin",
|
||||||
"starlight.lightengine.LevelLightEngineMixin",
|
"starlight.chunk.LevelChunkMixin",
|
||||||
"starlight.lightengine.ThreadedLevelLightEngineMixin",
|
"starlight.chunk.ProtoChunkMixin",
|
||||||
"starlight.world.SerializableChunkData$SectionData",
|
"starlight.lightengine.LevelLightEngineMixin",
|
||||||
"starlight.world.SerializableChunkDataMixin",
|
"starlight.lightengine.ThreadedLevelLightEngineMixin",
|
||||||
"starlight.world.WorldGenRegionMixin",
|
"starlight.world.SerializableChunkData$SectionData",
|
||||||
"util_thread_counts.UtilMixin",
|
"starlight.world.SerializableChunkDataMixin",
|
||||||
"util_threading_detector.PalettedContainerMixin",
|
"starlight.world.WorldGenRegionMixin",
|
||||||
"util_threading_detector.ThreadingDetectorMixin",
|
"util_thread_counts.UtilMixin",
|
||||||
"util_time_source.UtilMixin"
|
"util_threading_detector.PalettedContainerMixin",
|
||||||
],
|
"util_threading_detector.ThreadingDetectorMixin",
|
||||||
"client": [
|
"util_time_source.UtilMixin"
|
||||||
"chunk_system.ClientLevelMixin",
|
],
|
||||||
"chunk_system.OptionsMixin",
|
"client": [
|
||||||
"collisions.LiquidBlockRendererMixin",
|
"chunk_system.ClientLevelMixin",
|
||||||
"collisions.ParticleMixin",
|
"chunk_system.OptionsMixin",
|
||||||
"config.MinecraftMixin",
|
"collisions.LiquidBlockRendererMixin",
|
||||||
"loading_screen.LevelLoadStatusManagerMixin",
|
"collisions.ParticleMixin",
|
||||||
"profiler.MinecraftMixin",
|
"config.MinecraftMixin",
|
||||||
"render.SectionRenderDispatcherMixin",
|
"loading_screen.LevelLoadStatusManagerMixin",
|
||||||
"serverlist.ClientConnectionMixin",
|
"profiler.MinecraftMixin",
|
||||||
"serverlist.ServerAddressResolverMixin",
|
"render.SectionRenderDispatcherMixin",
|
||||||
"serverlist.ServerSelectionListMixin",
|
"serverlist.ClientConnectionMixin",
|
||||||
"starlight.multiplayer.ClientPacketListenerMixin"
|
"serverlist.ServerAddressResolverMixin",
|
||||||
],
|
"serverlist.ServerSelectionListMixin",
|
||||||
"injectors": {
|
"starlight.multiplayer.ClientPacketListenerMixin"
|
||||||
"defaultRequire": 1
|
],
|
||||||
},
|
"injectors": {
|
||||||
"overwrites": {
|
"defaultRequire": 1
|
||||||
"conformVisibility": true
|
},
|
||||||
|
"overwrites": {
|
||||||
|
"conformVisibility": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user