Compare commits
39 Commits
v0.2.0-bet
...
v0.2.0-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ac0c7deb43 | ||
|
|
16c8398d8a | ||
|
|
661ef813bb | ||
|
|
cf1d26a73c | ||
|
|
0cbff02a1c | ||
|
|
ce4ee767fe | ||
|
|
d31b15122f | ||
|
|
ca931e842b | ||
|
|
c2cf985899 | ||
|
|
d270cf06d9 | ||
|
|
09735958c0 | ||
|
|
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 |
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') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-project-local-gradle-caches-
|
||||
- name: "setup dependencies"
|
||||
run: ./install_deps.sh
|
||||
- name: "execute gradle build"
|
||||
run: ./gradlew build
|
||||
- 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)
|
||||
!gradle-wrapper.jar
|
||||
|
||||
ConcurrentUtil/
|
||||
YamlConfig/
|
||||
|
||||
6
.gitmodules
vendored
6
.gitmodules
vendored
@@ -1,6 +0,0 @@
|
||||
[submodule "ConcurrentUtil"]
|
||||
path = ConcurrentUtil
|
||||
url = https://github.com/Spottedleaf/ConcurrentUtil.git
|
||||
[submodule "YamlConfig"]
|
||||
path = YamlConfig
|
||||
url = https://github.com/Spottedleaf/YamlConfig.git
|
||||
|
||||
Submodule ConcurrentUtil deleted from 08d3ca3241
Submodule YamlConfig deleted from 67552e7707
129
build.gradle
129
build.gradle
@@ -1,41 +1,53 @@
|
||||
import me.modmuss50.mpp.ReleaseType
|
||||
|
||||
plugins {
|
||||
id("xyz.jpenilla.quiet-architectury-loom")
|
||||
id("me.modmuss50.mod-publish-plugin") version "0.7.2" apply false
|
||||
id("java-library")
|
||||
id("net.neoforged.moddev")
|
||||
id("me.modmuss50.mod-publish-plugin") version "0.8.4" apply false
|
||||
}
|
||||
|
||||
/*
|
||||
* Gets the version name from the latest Git tag
|
||||
*/
|
||||
// https://stackoverflow.com/questions/28498688/gradle-script-to-autoversion-and-include-the-commit-hash-in-android
|
||||
def getGitCommit = { ->
|
||||
def stdout = new ByteArrayOutputStream()
|
||||
exec {
|
||||
commandLine 'git', 'rev-parse', '--short', 'HEAD'
|
||||
standardOutput = stdout
|
||||
}
|
||||
return stdout.toString().trim()
|
||||
extensions.create("runConfigCommon", RunConfigCommon.class)
|
||||
|
||||
def getGitCommit = providers.exec {
|
||||
commandLine 'git', 'rev-parse', '--short', 'HEAD'
|
||||
}.standardOutput.getAsText().map { it.trim() }
|
||||
|
||||
def aw2at = Aw2AtTask.configureDefault(
|
||||
getProject(),
|
||||
layout.projectDirectory.file("src/main/resources/moonrise.accesswidener").getAsFile(),
|
||||
sourceSets.main
|
||||
)
|
||||
|
||||
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 {
|
||||
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:yamlconfig:${rootProject.yamlconfig_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}")
|
||||
|
||||
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 {
|
||||
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 {
|
||||
withSourcesJar()
|
||||
@@ -45,26 +57,30 @@ allprojects {
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testImplementation "org.junit.jupiter:junit-jupiter:${rootProject.junit_version}"
|
||||
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
|
||||
}
|
||||
|
||||
tasks.test {
|
||||
useJUnitPlatform()
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenLocal {
|
||||
maven {
|
||||
url = "https://repo.papermc.io/repository/maven-public/"
|
||||
mavenContent {
|
||||
includeModule("ca.spottedleaf", "concurrentutil")
|
||||
includeModule("ca.spottedleaf", "yamlconfig")
|
||||
includeGroup("ca.spottedleaf")
|
||||
}
|
||||
}
|
||||
maven {
|
||||
url "https://api.modrinth.com/maven"
|
||||
url = "https://api.modrinth.com/maven"
|
||||
mavenContent {
|
||||
includeGroup("maven.modrinth")
|
||||
}
|
||||
}
|
||||
maven { url "https://maven.shedaniel.me/" }
|
||||
maven { url "https://maven.terraformersmc.com/releases/" }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
minecraft "com.mojang:minecraft:${project.minecraft_version}"
|
||||
mappings loom.officialMojangMappings()
|
||||
maven { url = "https://maven.shedaniel.me/" }
|
||||
maven { url = "https://maven.terraformersmc.com/releases/" }
|
||||
}
|
||||
|
||||
// make build reproducible
|
||||
@@ -82,32 +98,22 @@ allprojects {
|
||||
rename { "${it}_${rootProject.base.archivesName.get()}"}
|
||||
}
|
||||
}
|
||||
|
||||
loom {
|
||||
accessWidenerPath = awFile
|
||||
mixin {
|
||||
useLegacyMixinAp = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 'java-library'
|
||||
plugins.apply 'com.gradleup.shadow'
|
||||
|
||||
configurations.create("libs")
|
||||
configurations.shadow {
|
||||
extendsFrom(configurations.libs)
|
||||
}
|
||||
configurations.implementation {
|
||||
extendsFrom(configurations.libs)
|
||||
}
|
||||
|
||||
publishMods {
|
||||
file = remapJar.archiveFile
|
||||
if (project.version.contains("-beta.")) {
|
||||
type = ReleaseType.BETA
|
||||
} else {
|
||||
@@ -131,20 +137,7 @@ subprojects {
|
||||
}
|
||||
|
||||
// Setup a run with lithium for compatibility testing
|
||||
sourceSets.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 {
|
||||
String coordinates = "maven.modrinth:lithium:"
|
||||
if (getProject().name == "Moonrise-NeoForge") {
|
||||
@@ -152,10 +145,6 @@ subprojects {
|
||||
} else {
|
||||
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")
|
||||
}
|
||||
152
buildSrc/src/main/java/Aw2AtTask.java
Normal file
152
buildSrc/src/main/java/Aw2AtTask.java
Normal file
@@ -0,0 +1,152 @@
|
||||
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.AccessTransformFormat;
|
||||
import dev.architectury.at.io.AccessTransformFormats;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
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());
|
||||
writeLF(AccessTransformFormats.FML, this.getOutputFile().get().getAsFile().toPath(), accessTransformSet);
|
||||
} catch (final IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static void writeLF(final AccessTransformFormat format, final Path path, final AccessTransformSet at) throws IOException {
|
||||
final StringWriter stringWriter = new StringWriter();
|
||||
final BufferedWriter writer = new BufferedWriter(stringWriter);
|
||||
format.write(writer, at);
|
||||
writer.close();
|
||||
final List<String> lines = Arrays.stream(stringWriter.toString()
|
||||
// unify line endings
|
||||
.replace("\r\n", "\n")
|
||||
.split("\n"))
|
||||
// skip blank lines
|
||||
.filter(it -> !it.isBlank())
|
||||
// sort
|
||||
.sorted()
|
||||
.toList();
|
||||
Files.writeString(path, String.join("\n", lines));
|
||||
}
|
||||
|
||||
// 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 {
|
||||
AccessTransformSet atSet = AccessTransformSet.create();
|
||||
|
||||
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();
|
||||
}
|
||||
@@ -1,45 +1,50 @@
|
||||
plugins {
|
||||
id("xyz.jpenilla.quiet-architectury-loom")
|
||||
id 'maven-publish'
|
||||
id 'com.gradleup.shadow'
|
||||
}
|
||||
import java.util.stream.Collectors
|
||||
import net.fabricmc.loom.util.gradle.SourceSetHelper
|
||||
|
||||
configurations.create("libs")
|
||||
configurations.shadow {
|
||||
extendsFrom(configurations.libs)
|
||||
}
|
||||
configurations.implementation {
|
||||
extendsFrom(configurations.libs)
|
||||
plugins {
|
||||
id("quiet-fabric-loom")
|
||||
id 'maven-publish'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
add('shadow', project([path: ":", configuration: "namedElements"]))
|
||||
runtimeOnly(project(":").sourceSets.main.output)
|
||||
minecraft "com.mojang:minecraft:${project.minecraft_version}"
|
||||
mappings loom.officialMojangMappings()
|
||||
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
|
||||
testImplementation "net.fabricmc:fabric-loader-junit:${project.loader_version}"
|
||||
|
||||
libs("ca.spottedleaf:concurrentutil:${rootProject.concurrentutil_version}")
|
||||
libs("ca.spottedleaf:yamlconfig:${rootProject.yamlconfig_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}")
|
||||
|
||||
modImplementation "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 platform(fabricApiLibs.bom)
|
||||
modImplementation fabricApiLibs.command.api.v2
|
||||
modImplementation fabricApiLibs.lifecycle.events.v1
|
||||
include fabricApiLibs.command.api.v2
|
||||
include fabricApiLibs.base
|
||||
}
|
||||
|
||||
processResources {
|
||||
inputs.property "version", project.version
|
||||
|
||||
tasks.processResources {
|
||||
def properties = [
|
||||
"version": project.version,
|
||||
"minecraft_version": minecraft_version,
|
||||
"loader_version": loader_version,
|
||||
"mod_version": mod_version
|
||||
]
|
||||
inputs.properties(properties)
|
||||
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"
|
||||
destinationDirectory = layout.buildDirectory.dir("libs")
|
||||
configurations = [project.configurations.shadow]
|
||||
@@ -49,6 +54,7 @@ shadowJar {
|
||||
}
|
||||
|
||||
publishMods {
|
||||
file = remapJar.archiveFile
|
||||
modLoaders = ["fabric"]
|
||||
|
||||
modrinth {
|
||||
@@ -66,3 +72,52 @@ publishMods {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
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,5 +1,6 @@
|
||||
package ca.spottedleaf.moonrise.fabric;
|
||||
|
||||
import ca.spottedleaf.moonrise.common.util.BaseChunkSystemHooks;
|
||||
import ca.spottedleaf.moonrise.common.PlatformHooks;
|
||||
import ca.spottedleaf.moonrise.common.util.ConfigHolder;
|
||||
import com.mojang.datafixers.DSL;
|
||||
@@ -15,6 +16,7 @@ import net.minecraft.server.level.GenerationChunkHolder;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.boss.EnderDragonPart;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import net.minecraft.world.level.Level;
|
||||
@@ -27,10 +29,11 @@ import net.minecraft.world.level.chunk.status.ChunkStatusTasks;
|
||||
import net.minecraft.world.level.chunk.storage.SerializableChunkData;
|
||||
import net.minecraft.world.level.entity.EntityTypeTest;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
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");
|
||||
|
||||
@@ -111,13 +114,43 @@ public final class FabricHooks implements PlatformHooks {
|
||||
@Override
|
||||
public void addToGetEntities(final Level world, final Entity entity, final AABB boundingBox, final Predicate<? super Entity> predicate,
|
||||
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
|
||||
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) {
|
||||
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
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
"accessWidener": "moonrise.accesswidener",
|
||||
"depends": {
|
||||
"fabricloader": ">=${loader_version}",
|
||||
"minecraft": ">1.21.1 <1.21.4",
|
||||
"minecraft": ">1.21.3 <1.21.5",
|
||||
"fabric-command-api-v2": "*"
|
||||
},
|
||||
"custom": {
|
||||
|
||||
@@ -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,22 +1,26 @@
|
||||
# Done to increase the memory available to gradle.
|
||||
org.gradle.jvmargs=-Xmx2G
|
||||
org.gradle.daemon=false
|
||||
org.gradle.parallel=true
|
||||
org.gradle.caching=true
|
||||
org.gradle.configuration-cache=true
|
||||
# Fabric Properties
|
||||
# check these on https://modmuss50.me/fabric.html
|
||||
minecraft_version=1.21.3
|
||||
loader_version=0.16.7
|
||||
supported_minecraft_versions=1.21.3
|
||||
neoforge_version=21.3.31-beta
|
||||
fabric_api_version=0.107.0+1.21.3
|
||||
minecraft_version=1.21.4
|
||||
loader_version=0.16.9
|
||||
supported_minecraft_versions=1.21.4
|
||||
neoforge_version=21.4.33-beta
|
||||
neoform_version=1.21.4-20241203.161809
|
||||
fabric_api_version=0.110.5+1.21.4
|
||||
snakeyaml_version=2.3
|
||||
concurrentutil_version=0.0.2-SNAPSHOT
|
||||
yamlconfig_version=1.0.2-SNAPSHOT
|
||||
cloth_version=16.0.141
|
||||
modmenu_version=12.0.0-beta.1
|
||||
concurrentutil_version=0.0.3
|
||||
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
|
||||
fabric_lithium_version=QhCwdt4l
|
||||
neo_lithium_version=wDD955sb
|
||||
fabric_lithium_version=t1FlWYl9
|
||||
neo_lithium_version=iDqQi66g
|
||||
# Mod Properties
|
||||
mod_version=0.2.0-beta.5
|
||||
mod_version=0.2.0-beta.9
|
||||
maven_group=ca.spottedleaf.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
|
||||
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
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
3
gradlew
vendored
3
gradlew
vendored
@@ -86,8 +86,7 @@ done
|
||||
# shellcheck disable=SC2034
|
||||
APP_BASE_NAME=${0##*/}
|
||||
# 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
|
||||
' "$PWD" ) || exit
|
||||
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -eou pipefail
|
||||
|
||||
git submodule update --init --recursive
|
||||
|
||||
cd ConcurrentUtil
|
||||
mvn install
|
||||
|
||||
cd ..
|
||||
|
||||
cd YamlConfig
|
||||
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 {
|
||||
id("xyz.jpenilla.quiet-architectury-loom")
|
||||
id("net.neoforged.moddev")
|
||||
id 'maven-publish'
|
||||
id 'com.gradleup.shadow'
|
||||
}
|
||||
|
||||
repositories {
|
||||
@@ -13,32 +14,66 @@ repositories {
|
||||
}
|
||||
}
|
||||
|
||||
configurations.implementation {
|
||||
extendsFrom(configurations.shadow)
|
||||
}
|
||||
def aw2at = Aw2AtTask.configureDefault(
|
||||
getProject(),
|
||||
rootProject.layout.projectDirectory.file("src/main/resources/moonrise.accesswidener").getAsFile(),
|
||||
sourceSets.main
|
||||
)
|
||||
|
||||
dependencies {
|
||||
add('shadow', project([path: ":", configuration: "namedElements"]))
|
||||
neoForge "net.neoforged:neoforge:${rootProject.neoforge_version}"
|
||||
|
||||
shadow("ca.spottedleaf:concurrentutil:${rootProject.concurrentutil_version}")
|
||||
shadow("ca.spottedleaf:yamlconfig:${rootProject.yamlconfig_version}")
|
||||
shadow("org.yaml:snakeyaml:${rootProject.snakeyaml_version}")
|
||||
forgeExtra("org.yaml:snakeyaml:${rootProject.snakeyaml_version}")
|
||||
|
||||
modImplementation "me.shedaniel.cloth:cloth-config-neoforge:${rootProject.cloth_version}"
|
||||
include "me.shedaniel.cloth:cloth-config-neoforge:${rootProject.cloth_version}"
|
||||
}
|
||||
|
||||
processResources {
|
||||
inputs.property "version", project.version
|
||||
|
||||
filesMatching("META-INF/neoforge.mods.toml") {
|
||||
expand "version": project.version, "minecraft_version": minecraft_version, "loader_version": loader_version, "mod_version": mod_version
|
||||
neoForge {
|
||||
version = rootProject.neoforge_version
|
||||
validateAccessTransformers = true
|
||||
accessTransformers.files.setFrom(aw2at.flatMap { t -> t.getOutputFile() })
|
||||
mods {
|
||||
moonrise {
|
||||
sourceSet sourceSets.main
|
||||
sourceSet rootProject.sourceSets.main
|
||||
}
|
||||
}
|
||||
runs {
|
||||
client {
|
||||
client()
|
||||
}
|
||||
server {
|
||||
server()
|
||||
}
|
||||
}
|
||||
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"
|
||||
destinationDirectory = layout.buildDirectory.dir("libs")
|
||||
configurations = [project.configurations.shadow]
|
||||
@@ -47,9 +82,20 @@ shadowJar {
|
||||
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 {
|
||||
file = productionJar.archiveFile
|
||||
modLoaders = ["neoforge"]
|
||||
|
||||
modrinth {
|
||||
@@ -67,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,5 +1,6 @@
|
||||
package ca.spottedleaf.moonrise.neoforge;
|
||||
|
||||
import ca.spottedleaf.moonrise.common.util.BaseChunkSystemHooks;
|
||||
import ca.spottedleaf.moonrise.common.PlatformHooks;
|
||||
import ca.spottedleaf.moonrise.common.util.ConfigHolder;
|
||||
import ca.spottedleaf.moonrise.common.util.CoordinateUtils;
|
||||
@@ -34,10 +35,11 @@ import net.neoforged.neoforge.event.EventHooks;
|
||||
import net.neoforged.neoforge.event.entity.EntityJoinLevelEvent;
|
||||
import net.neoforged.neoforge.event.level.ChunkDataEvent;
|
||||
import net.neoforged.neoforge.event.level.ChunkEvent;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public final class NeoForgeHooks implements PlatformHooks {
|
||||
public final class NeoForgeHooks extends BaseChunkSystemHooks implements PlatformHooks {
|
||||
|
||||
@Override
|
||||
public String getBrand() {
|
||||
@@ -114,7 +116,12 @@ public final class NeoForgeHooks implements PlatformHooks {
|
||||
@Override
|
||||
public void addToGetEntities(final Level world, final Entity entity, final AABB boundingBox, final Predicate<? super Entity> predicate,
|
||||
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))) {
|
||||
into.add(part);
|
||||
}
|
||||
@@ -129,9 +136,18 @@ public final class NeoForgeHooks implements PlatformHooks {
|
||||
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);
|
||||
if (casted != null && casted.getBoundingBox().intersects(boundingBox) && (predicate == null || predicate.test(casted))) {
|
||||
if (casted != null && (predicate == null || predicate.test(casted))) {
|
||||
into.add(casted);
|
||||
if (into.size() >= maxCount) {
|
||||
break;
|
||||
|
||||
@@ -28,7 +28,7 @@ side = "BOTH"
|
||||
[[dependencies.moonrise]]
|
||||
modId = "minecraft"
|
||||
type = "required"
|
||||
versionRange = "(1.21.1,1.21.4)"
|
||||
versionRange = "(1.21.3,1.21.5)"
|
||||
ordering = "NONE"
|
||||
side = "BOTH"
|
||||
|
||||
|
||||
@@ -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 {
|
||||
name = 'jmp'
|
||||
url = 'https://repo.jpenilla.xyz/snapshots'
|
||||
mavenContent { snapshotsOnly() }
|
||||
}
|
||||
maven {
|
||||
name = 'architectury'
|
||||
@@ -23,9 +22,10 @@ pluginManagement {
|
||||
}
|
||||
|
||||
plugins {
|
||||
id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0"
|
||||
id("xyz.jpenilla.quiet-architectury-loom") version "1.7.300" apply false
|
||||
id 'com.gradleup.shadow' version '8.3.0' apply false
|
||||
id("org.gradle.toolchains.foojay-resolver-convention") version "0.9.0"
|
||||
id("quiet-fabric-loom") version "1.9.312" apply false
|
||||
id("net.neoforged.moddev") version "2.0.61-beta" apply false
|
||||
id 'com.gradleup.shadow' version '8.3.5' apply false
|
||||
}
|
||||
|
||||
dependencyResolutionManagement {
|
||||
@@ -48,3 +48,6 @@ include("fabric")
|
||||
findProject(":fabric").name = "Moonrise-Fabric"
|
||||
include("neoforge")
|
||||
findProject(":neoforge").name = "Moonrise-NeoForge"
|
||||
|
||||
// includeBuild("../YamlConfig") // Uncomment to use local YamlConfig
|
||||
// includeBuild("../ConcurrentUtil") // Uncomment to use local ConcurrentUtil
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package ca.spottedleaf.moonrise.common;
|
||||
|
||||
import ca.spottedleaf.moonrise.common.util.ChunkSystemHooks;
|
||||
import com.mojang.datafixers.DSL;
|
||||
import com.mojang.datafixers.DataFixer;
|
||||
import net.minecraft.core.BlockPos;
|
||||
@@ -8,7 +9,6 @@ import net.minecraft.server.level.ChunkHolder;
|
||||
import net.minecraft.server.level.GenerationChunkHolder;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.util.datafix.DataFixTypes;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
@@ -24,7 +24,7 @@ import java.util.List;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public interface PlatformHooks {
|
||||
public interface PlatformHooks extends ChunkSystemHooks {
|
||||
public static PlatformHooks get() {
|
||||
return Holder.INSTANCE;
|
||||
}
|
||||
@@ -64,8 +64,6 @@ public interface PlatformHooks {
|
||||
|
||||
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 configAutoConfigSendDistance();
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package ca.spottedleaf.moonrise.common.misc;
|
||||
|
||||
import ca.spottedleaf.moonrise.common.PlatformHooks;
|
||||
import ca.spottedleaf.moonrise.common.list.ReferenceList;
|
||||
import ca.spottedleaf.moonrise.common.util.CoordinateUtils;
|
||||
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.chunk.ChunkData;
|
||||
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_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.TICK_VIEW_DISTANCE.ordinal()].update(chunk.x, chunk.z, ChunkSystem.getTickViewDistance(player));
|
||||
players[NearbyMapType.VIEW_DISTANCE.ordinal()].update(chunk.x, chunk.z, ChunkSystem.getViewDistance(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, PlatformHooks.get().getViewDistance(player));
|
||||
players[NearbyMapType.SPAWN_RANGE.ordinal()].update(chunk.x, chunk.z, ChunkTickConstants.PLAYER_SPAWN_TRACK_RANGE); // Moonrise - chunk tick iteration
|
||||
}
|
||||
|
||||
|
||||
@@ -1,121 +1,125 @@
|
||||
package ca.spottedleaf.moonrise.common.util;
|
||||
|
||||
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.chunk.ChunkSystemLevelChunk;
|
||||
import ca.spottedleaf.moonrise.patches.chunk_system.player.RegionizedPlayerChunkLoader;
|
||||
import ca.spottedleaf.moonrise.patches.chunk_system.world.ChunkSystemServerChunkCache;
|
||||
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.FullChunkStatus;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
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.LevelChunk;
|
||||
import net.minecraft.world.level.chunk.status.ChunkStatus;
|
||||
import org.slf4j.Logger;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public final class ChunkSystem {
|
||||
public abstract class BaseChunkSystemHooks implements ChunkSystemHooks {
|
||||
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
|
||||
public static void scheduleChunkTask(final ServerLevel level, final int chunkX, final int chunkZ, final Runnable run) {
|
||||
@Override
|
||||
public void scheduleChunkTask(final ServerLevel level, final int chunkX, final int chunkZ, final Runnable run) {
|
||||
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);
|
||||
}
|
||||
|
||||
public static 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) {
|
||||
@Override
|
||||
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) {
|
||||
((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,
|
||||
final boolean addTicket, final Priority priority, final Consumer<ChunkAccess> onComplete) {
|
||||
@Override
|
||||
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);
|
||||
}
|
||||
|
||||
public static void scheduleTickingState(final ServerLevel level, final int chunkX, final int chunkZ,
|
||||
final FullChunkStatus toStatus, final boolean addTicket,
|
||||
final Priority priority, final Consumer<LevelChunk> onComplete) {
|
||||
@Override
|
||||
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) {
|
||||
((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();
|
||||
}
|
||||
|
||||
public static List<ChunkHolder> getUpdatingChunkHolders(final ServerLevel level) {
|
||||
@Override
|
||||
public List<ChunkHolder> getUpdatingChunkHolders(final ServerLevel level) {
|
||||
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();
|
||||
}
|
||||
|
||||
public static int getUpdatingChunkHolderCount(final ServerLevel level) {
|
||||
@Override
|
||||
public int getUpdatingChunkHolderCount(final ServerLevel level) {
|
||||
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;
|
||||
}
|
||||
|
||||
public static boolean screenEntity(final ServerLevel level, final Entity entity, final boolean fromDisk, final boolean event) {
|
||||
if (!PlatformHooks.get().screenEntity(level, entity, fromDisk, event)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void onChunkHolderCreate(final ServerLevel level, final ChunkHolder holder) {
|
||||
@Override
|
||||
public 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
|
||||
final ChunkProgressListener progressListener = level.getChunkSource().chunkMap.progressListener;
|
||||
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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
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())
|
||||
.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(
|
||||
((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(
|
||||
((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())
|
||||
.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(
|
||||
((ChunkSystemLevelChunk)chunk).moonrise$getChunkAndHolder()
|
||||
((ChunkSystemLevelChunk)chunk).moonrise$getChunkAndHolder()
|
||||
);
|
||||
if (!((ChunkSystemLevelChunk)chunk).moonrise$isPostProcessingDone()) {
|
||||
chunk.postProcessGeneration((ServerLevel)chunk.getLevel());
|
||||
@@ -125,52 +129,60 @@ public final class ChunkSystem {
|
||||
((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(
|
||||
((ChunkSystemLevelChunk)chunk).moonrise$getChunkAndHolder()
|
||||
((ChunkSystemLevelChunk)chunk).moonrise$getChunkAndHolder()
|
||||
);
|
||||
((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(
|
||||
((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(
|
||||
((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;
|
||||
}
|
||||
|
||||
public static int getSendViewDistance(final ServerPlayer player) {
|
||||
@Override
|
||||
public int getSendViewDistance(final ServerPlayer player) {
|
||||
return RegionizedPlayerChunkLoader.getAPISendViewDistance(player);
|
||||
}
|
||||
|
||||
public static int getViewDistance(final ServerPlayer player) {
|
||||
@Override
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package ca.spottedleaf.moonrise.common.util;
|
||||
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public final class EntityUtil {
|
||||
|
||||
private static final ThreadLocal<DecimalFormat> THREE_DECIMAL_PLACES = ThreadLocal.withInitial(() -> {
|
||||
return new DecimalFormat("#,##0.000");
|
||||
});
|
||||
|
||||
private static String formatVec(final Vec3 vec) {
|
||||
final DecimalFormat format = THREE_DECIMAL_PLACES.get();
|
||||
|
||||
return "(" + format.format(vec.x) + "," + format.format(vec.y) + "," + format.format(vec.z) + ")";
|
||||
}
|
||||
|
||||
private static String dumpEntityWithoutReferences(final Entity entity) {
|
||||
if (entity == null) {
|
||||
return "{null}";
|
||||
}
|
||||
|
||||
return "{type=" + entity.getClass().getSimpleName() + ",id=" + entity.getId() + ",uuid=" + entity.getUUID() + ",pos=" + formatVec(entity.position())
|
||||
+ ",mot=" + formatVec(entity.getDeltaMovement()) + ",aabb=" + entity.getBoundingBox() + ",removed=" + entity.getRemovalReason() + ",has_vehicle=" + (entity.getVehicle() != null)
|
||||
+ ",passenger_count=" + entity.getPassengers().size();
|
||||
}
|
||||
|
||||
public static String dumpEntity(final Entity entity) {
|
||||
final List<Entity> passengers = entity.getPassengers();
|
||||
final List<String> passengerStrings = new ArrayList<>(passengers.size());
|
||||
|
||||
for (final Entity passenger : passengers) {
|
||||
passengerStrings.add("(" + dumpEntityWithoutReferences(passenger) + ")");
|
||||
}
|
||||
|
||||
return "{root=[" + dumpEntityWithoutReferences(entity) + "], vehicle=[" + dumpEntityWithoutReferences(entity.getVehicle())
|
||||
+ "], passengers=[" + String.join(",", passengerStrings) + "]";
|
||||
}
|
||||
|
||||
private EntityUtil() {}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package ca.spottedleaf.moonrise.common.util;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.Strictness;
|
||||
import com.google.gson.internal.Streams;
|
||||
import com.google.gson.stream.JsonWriter;
|
||||
import java.io.File;
|
||||
@@ -16,7 +17,7 @@ public final class JsonUtil {
|
||||
final StringWriter stringWriter = new StringWriter();
|
||||
final JsonWriter jsonWriter = new JsonWriter(stringWriter);
|
||||
jsonWriter.setIndent(" ");
|
||||
jsonWriter.setLenient(false);
|
||||
jsonWriter.setStrictness(Strictness.LENIENT);
|
||||
Streams.write(element, jsonWriter);
|
||||
|
||||
final String jsonString = stringWriter.toString();
|
||||
|
||||
@@ -15,56 +15,81 @@ public class TickThread extends Thread {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(TickThread.class);
|
||||
|
||||
private static String getThreadContext() {
|
||||
return "thread=" + Thread.currentThread().getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
@Deprecated
|
||||
public static void ensureTickThread(final String reason) {
|
||||
if (!isTickThread()) {
|
||||
LOGGER.error("Thread " + Thread.currentThread().getName() + " failed main thread check: " + reason, new Throwable());
|
||||
LOGGER.error("Thread failed main thread check: " + reason + ", context=" + getThreadContext(), new Throwable());
|
||||
throw new IllegalStateException(reason);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ensureTickThread(final Level world, final BlockPos pos, final String reason) {
|
||||
if (!isTickThreadFor(world, pos)) {
|
||||
LOGGER.error("Thread " + Thread.currentThread().getName() + " failed main thread check: " + reason, new Throwable());
|
||||
throw new IllegalStateException(reason);
|
||||
final String ex = "Thread failed main thread check: " +
|
||||
reason + ", context=" + getThreadContext() + ", world=" + WorldUtil.getWorldName(world) + ", block_pos=" + pos;
|
||||
LOGGER.error(ex, new Throwable());
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ensureTickThread(final Level world, final BlockPos pos, final int blockRadius, final String reason) {
|
||||
if (!isTickThreadFor(world, pos, blockRadius)) {
|
||||
final String ex = "Thread failed main thread check: " +
|
||||
reason + ", context=" + getThreadContext() + ", world=" + WorldUtil.getWorldName(world) + ", block_pos=" + pos + ", block_radius=" + blockRadius;
|
||||
LOGGER.error(ex, new Throwable());
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ensureTickThread(final Level world, final ChunkPos pos, final String reason) {
|
||||
if (!isTickThreadFor(world, pos)) {
|
||||
LOGGER.error("Thread " + Thread.currentThread().getName() + " failed main thread check: " + reason, new Throwable());
|
||||
throw new IllegalStateException(reason);
|
||||
final String ex = "Thread failed main thread check: " +
|
||||
reason + ", context=" + getThreadContext() + ", world=" + WorldUtil.getWorldName(world) + ", chunk_pos=" + pos;
|
||||
LOGGER.error(ex, new Throwable());
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ensureTickThread(final Level world, final int chunkX, final int chunkZ, final String reason) {
|
||||
if (!isTickThreadFor(world, chunkX, chunkZ)) {
|
||||
LOGGER.error("Thread " + Thread.currentThread().getName() + " failed main thread check: " + reason, new Throwable());
|
||||
throw new IllegalStateException(reason);
|
||||
final String ex = "Thread failed main thread check: " +
|
||||
reason + ", context=" + getThreadContext() + ", world=" + WorldUtil.getWorldName(world) + ", chunk_pos=" + new ChunkPos(chunkX, chunkZ);
|
||||
LOGGER.error(ex, new Throwable());
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ensureTickThread(final Entity entity, final String reason) {
|
||||
if (!isTickThreadFor(entity)) {
|
||||
LOGGER.error("Thread " + Thread.currentThread().getName() + " failed main thread check: " + reason, new Throwable());
|
||||
throw new IllegalStateException(reason);
|
||||
final String ex = "Thread failed main thread check: " +
|
||||
reason + ", context=" + getThreadContext() + ", entity=" + EntityUtil.dumpEntity(entity);
|
||||
LOGGER.error(ex, new Throwable());
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ensureTickThread(final Level world, final AABB aabb, final String reason) {
|
||||
if (!isTickThreadFor(world, aabb)) {
|
||||
LOGGER.error("Thread " + Thread.currentThread().getName() + " failed main thread check: " + reason, new Throwable());
|
||||
throw new IllegalStateException(reason);
|
||||
final String ex = "Thread failed main thread check: " +
|
||||
reason + ", context=" + getThreadContext() + ", world=" + WorldUtil.getWorldName(world) + ", aabb=" + aabb;
|
||||
LOGGER.error(ex, new Throwable());
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ensureTickThread(final Level world, final double blockX, final double blockZ, final String reason) {
|
||||
if (!isTickThreadFor(world, blockX, blockZ)) {
|
||||
LOGGER.error("Thread " + Thread.currentThread().getName() + " failed main thread check: " + reason, new Throwable());
|
||||
throw new IllegalStateException(reason);
|
||||
final String ex = "Thread failed main thread check: " +
|
||||
reason + ", context=" + getThreadContext() + ", world=" + WorldUtil.getWorldName(world) + ", block_pos=" + new Vec3(blockX, 0.0, blockZ);
|
||||
LOGGER.error(ex, new Throwable());
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,6 +130,10 @@ public class TickThread extends Thread {
|
||||
return isTickThread();
|
||||
}
|
||||
|
||||
public static boolean isTickThreadFor(final Level world, final BlockPos pos, final int blockRadius) {
|
||||
return isTickThread();
|
||||
}
|
||||
|
||||
public static boolean isTickThreadFor(final Level world, final ChunkPos pos) {
|
||||
return isTickThread();
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
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.ChunkSystem;
|
||||
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.ChunkSystemServerLevel;
|
||||
@@ -499,7 +499,7 @@ abstract class ChunkMapMixin extends ChunkStorage implements ChunkSystemChunkMap
|
||||
*/
|
||||
@Overwrite
|
||||
public int getPlayerViewDistance(final ServerPlayer player) {
|
||||
return ChunkSystem.getSendViewDistance(player);
|
||||
return PlatformHooks.get().getSendViewDistance(player);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -597,7 +597,7 @@ abstract class ChunkMapMixin extends ChunkStorage implements ChunkSystemChunkMap
|
||||
)
|
||||
)
|
||||
private void avoidUpdateChunkTrackingInUpdate(final ChunkMap instance, final ServerPlayer serverPlayer) {
|
||||
ChunkSystem.addPlayerToDistanceMaps(this.level, serverPlayer);
|
||||
PlatformHooks.get().addPlayerToDistanceMaps(this.level, serverPlayer);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -627,7 +627,7 @@ abstract class ChunkMapMixin extends ChunkStorage implements ChunkSystemChunkMap
|
||||
)
|
||||
private void avoidApplyChunkTrackingViewInUpdate(final ChunkMap instance, final ServerPlayer serverPlayer,
|
||||
final ChunkTrackingView chunkTrackingView) {
|
||||
ChunkSystem.removePlayerFromDistanceMaps(this.level, serverPlayer);
|
||||
PlatformHooks.get().removePlayerFromDistanceMaps(this.level, serverPlayer);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -641,7 +641,7 @@ abstract class ChunkMapMixin extends ChunkStorage implements ChunkSystemChunkMap
|
||||
)
|
||||
)
|
||||
private void updateMapsHook(final ServerPlayer player, final CallbackInfo ci) {
|
||||
ChunkSystem.updateMaps(this.level, player);
|
||||
PlatformHooks.get().updateMaps(this.level, player);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package ca.spottedleaf.moonrise.mixin.chunk_system;
|
||||
|
||||
import net.minecraft.core.SectionPos;
|
||||
import net.minecraft.world.level.gameevent.DynamicGameEventListener;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(DynamicGameEventListener.class)
|
||||
abstract class DynamicGameEventListenerMixin {
|
||||
@Shadow @Nullable private SectionPos lastSection;
|
||||
|
||||
@Inject(method = "remove", at = @At("RETURN"))
|
||||
private void onRemove(final CallbackInfo ci) {
|
||||
// We need to unset the last section when removed, otherwise if the same instance is re-added at the same position it
|
||||
// will assume there was no change and fail to re-register.
|
||||
// In vanilla, chunks rarely unload and re-load quickly enough to trigger this issue. However, our chunk system has a
|
||||
// quirk where fast chunk reload cycles will often occur on player login (see PR #22).
|
||||
// So we fix this vanilla oversight as our changes cause it to manifest in bugs much more often (see issue #87).
|
||||
this.lastSection = null;
|
||||
}
|
||||
}
|
||||
@@ -86,6 +86,13 @@ abstract class ServerChunkCacheMixin extends ChunkSource implements ChunkSystemS
|
||||
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)) {
|
||||
ChunkTaskScheduler.pushChunkWait(this.level, chunkX, chunkZ);
|
||||
this.mainThreadProcessor.managedBlock(completable::isDone);
|
||||
|
||||
@@ -74,7 +74,7 @@ interface EntityGetterMixin {
|
||||
@Overwrite
|
||||
default boolean isUnobstructed(final Entity entity, final VoxelShape voxel) {
|
||||
if (voxel.isEmpty()) {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
final AABB singleAABB = ((CollisionVoxelShape)voxel).moonrise$getSingleAABBRepresentation();
|
||||
|
||||
@@ -55,7 +55,7 @@ abstract class LevelMixin implements LevelAccessor, AutoCloseable {
|
||||
public boolean isUnobstructed(final Entity entity) {
|
||||
final AABB boundingBox = entity.getBoundingBox();
|
||||
if (CollisionUtil.isEmpty(boundingBox)) {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
final List<Entity> entities = this.getEntities(
|
||||
|
||||
@@ -378,19 +378,19 @@ abstract class VoxelShapeMixin implements CollisionVoxelShape {
|
||||
case X: {
|
||||
final double[] values = this.rootCoordinatesX;
|
||||
return CollisionUtil.findFloor(
|
||||
values, value - this.offsetX, 0, values.length - 1
|
||||
values, this.offsetX, value, 0, values.length - 1
|
||||
);
|
||||
}
|
||||
case Y: {
|
||||
final double[] values = this.rootCoordinatesY;
|
||||
return CollisionUtil.findFloor(
|
||||
values, value - this.offsetY, 0, values.length - 1
|
||||
values, this.offsetY, value, 0, values.length - 1
|
||||
);
|
||||
}
|
||||
case Z: {
|
||||
final double[] values = this.rootCoordinatesZ;
|
||||
return CollisionUtil.findFloor(
|
||||
values, value - this.offsetZ, 0, values.length - 1
|
||||
values, this.offsetZ, value, 0, values.length - 1
|
||||
);
|
||||
}
|
||||
default: {
|
||||
@@ -411,7 +411,7 @@ abstract class VoxelShapeMixin implements CollisionVoxelShape {
|
||||
|
||||
// see findIndex
|
||||
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
|
||||
);
|
||||
|
||||
|
||||
@@ -24,8 +24,8 @@ abstract class AcquirePoiMixin {
|
||||
*/
|
||||
@Redirect(
|
||||
method = {
|
||||
"method_46885",
|
||||
"*(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"
|
||||
"lambda$create$8",
|
||||
"method_46885"
|
||||
},
|
||||
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;",
|
||||
@@ -33,9 +33,9 @@ abstract class AcquirePoiMixin {
|
||||
ordinal = 0
|
||||
)
|
||||
)
|
||||
private static Stream<Pair<Holder<PoiType>, BlockPos>> aaa(PoiManager poiManager, Predicate<Holder<PoiType>> predicate,
|
||||
Predicate<BlockPos> predicate2, BlockPos blockPos, int i,
|
||||
PoiManager.Occupancy occup) {
|
||||
private static Stream<Pair<Holder<PoiType>, BlockPos>> useLimitedSearch(PoiManager poiManager, Predicate<Holder<PoiType>> predicate,
|
||||
Predicate<BlockPos> predicate2, BlockPos blockPos, int i,
|
||||
PoiManager.Occupancy occup) {
|
||||
final List<Pair<Holder<PoiType>, BlockPos>> ret = new ArrayList<>();
|
||||
|
||||
PoiAccess.findNearestPoiPositions(
|
||||
|
||||
@@ -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) {
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
public boolean getEntities(final Entity except, final AABB box, final List<Entity> into, final Predicate<? super Entity> predicate,
|
||||
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) {
|
||||
final int 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,
|
||||
final Predicate<? super T> predicate, final int maxCount) {
|
||||
final Predicate<? super T> predicate, final int maxCount) {
|
||||
final EntityCollectionBySection byType = this.entitiesByType.get(type);
|
||||
|
||||
if (byType != null) {
|
||||
@@ -356,21 +347,21 @@ public final class ChunkEntitySlices {
|
||||
final Predicate<? super T> predicate) {
|
||||
EntityCollectionBySection collection = this.entitiesByClass.get(clazz);
|
||||
if (collection != null) {
|
||||
collection.getEntitiesWithEnderDragonParts(except, clazz, box, (List)into, (Predicate)predicate);
|
||||
collection.getEntities(except, box, (List)into, (Predicate)predicate);
|
||||
} else {
|
||||
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,
|
||||
final Predicate<? super T> predicate, final int maxCount) {
|
||||
final Predicate<? super T> predicate, final int maxCount) {
|
||||
EntityCollectionBySection collection = this.entitiesByClass.get(clazz);
|
||||
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 {
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
public void get(final AABB box, final Consumer<Entity> action) {
|
||||
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) {
|
||||
action.accept(entities.get(i));
|
||||
}
|
||||
@@ -218,7 +218,7 @@ public abstract class EntityLookup implements LevelEntityGetter<Entity> {
|
||||
@Override
|
||||
public <U extends Entity> void get(final EntityTypeTest<Entity, U> filter, final AABB box, final AbortableIterationConsumer<U> action) {
|
||||
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) {
|
||||
final U casted = filter.tryCast(entities.get(i));
|
||||
if (casted != null && action.accept(casted).shouldAbort()) {
|
||||
@@ -560,45 +560,6 @@ public abstract class EntityLookup implements LevelEntityGetter<Entity> {
|
||||
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) {
|
||||
final int minChunkX = (Mth.floor(box.minX) - 2) >> 4;
|
||||
final int minChunkZ = (Mth.floor(box.minZ) - 2) >> 4;
|
||||
@@ -759,48 +720,6 @@ public abstract class EntityLookup implements LevelEntityGetter<Entity> {
|
||||
|
||||
//////// 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,
|
||||
final int maxCount) {
|
||||
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.util.CoordinateUtils;
|
||||
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.entity.ChunkEntitySlices;
|
||||
import ca.spottedleaf.moonrise.patches.chunk_system.level.entity.EntityLookup;
|
||||
@@ -111,6 +110,6 @@ public final class ServerEntityLookup extends EntityLookup {
|
||||
|
||||
@Override
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ import ca.spottedleaf.moonrise.common.PlatformHooks;
|
||||
import ca.spottedleaf.moonrise.common.util.CoordinateUtils;
|
||||
import ca.spottedleaf.moonrise.common.util.TickThread;
|
||||
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.level.ChunkSystemServerLevel;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
this.taskScheduler.setShutdown(true);
|
||||
}
|
||||
|
||||
void ensureInAutosave(final NewChunkHolder holder) {
|
||||
@@ -816,7 +817,7 @@ public final class ChunkHolderManager {
|
||||
private NewChunkHolder createChunkHolder(final long position) {
|
||||
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;
|
||||
}
|
||||
@@ -1024,7 +1025,7 @@ public final class ChunkHolderManager {
|
||||
private void removeChunkHolder(final NewChunkHolder holder) {
|
||||
holder.onUnload();
|
||||
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));
|
||||
}
|
||||
|
||||
|
||||
@@ -271,6 +271,16 @@ public final class ChunkTaskScheduler {
|
||||
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) {
|
||||
this.world = world;
|
||||
// must be >= region shift (in paper, doesn't exist) and must be >= ticket propagator section shift
|
||||
@@ -525,6 +535,13 @@ public final class ChunkTaskScheduler {
|
||||
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 int ticketLevel = getTicketLevel(status);
|
||||
this.chunkHolderManager.addTicketAtLevel(NON_FULL_CHUNK_LOAD, chunkX, chunkZ, ticketLevel, ticketId);
|
||||
|
||||
@@ -11,7 +11,6 @@ import ca.spottedleaf.moonrise.common.misc.LazyRunnable;
|
||||
import ca.spottedleaf.moonrise.common.util.CoordinateUtils;
|
||||
import ca.spottedleaf.moonrise.common.util.TickThread;
|
||||
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.io.MoonriseRegionFileIO;
|
||||
import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemLevel;
|
||||
@@ -1270,10 +1269,10 @@ public final class NewChunkHolder {
|
||||
// state upgrade
|
||||
if (!current.isOrAfter(FullChunkStatus.FULL) && pending.isOrAfter(FullChunkStatus.FULL)) {
|
||||
this.updateCurrentState(FullChunkStatus.FULL);
|
||||
ChunkSystem.onChunkPreBorder(chunk, this.vanillaChunkHolder);
|
||||
PlatformHooks.get().onChunkPreBorder(chunk, this.vanillaChunkHolder);
|
||||
this.scheduler.chunkHolderManager.ensureInAutosave(this);
|
||||
this.changeEntityChunkStatus(FullChunkStatus.FULL);
|
||||
ChunkSystem.onChunkBorder(chunk, this.vanillaChunkHolder);
|
||||
PlatformHooks.get().onChunkBorder(chunk, this.vanillaChunkHolder);
|
||||
this.onFullChunkLoadChange(true, changedFullStatus);
|
||||
this.completeFullStatusConsumers(FullChunkStatus.FULL, chunk);
|
||||
}
|
||||
@@ -1281,34 +1280,34 @@ public final class NewChunkHolder {
|
||||
if (!current.isOrAfter(FullChunkStatus.BLOCK_TICKING) && pending.isOrAfter(FullChunkStatus.BLOCK_TICKING)) {
|
||||
this.updateCurrentState(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);
|
||||
}
|
||||
|
||||
if (!current.isOrAfter(FullChunkStatus.ENTITY_TICKING) && pending.isOrAfter(FullChunkStatus.ENTITY_TICKING)) {
|
||||
this.updateCurrentState(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);
|
||||
}
|
||||
} else {
|
||||
if (current.isOrAfter(FullChunkStatus.ENTITY_TICKING) && !pending.isOrAfter(FullChunkStatus.ENTITY_TICKING)) {
|
||||
this.changeEntityChunkStatus(FullChunkStatus.BLOCK_TICKING);
|
||||
ChunkSystem.onChunkNotEntityTicking(chunk, this.vanillaChunkHolder);
|
||||
PlatformHooks.get().onChunkNotEntityTicking(chunk, this.vanillaChunkHolder);
|
||||
this.updateCurrentState(FullChunkStatus.BLOCK_TICKING);
|
||||
}
|
||||
|
||||
if (current.isOrAfter(FullChunkStatus.BLOCK_TICKING) && !pending.isOrAfter(FullChunkStatus.BLOCK_TICKING)) {
|
||||
this.changeEntityChunkStatus(FullChunkStatus.FULL);
|
||||
ChunkSystem.onChunkNotTicking(chunk, this.vanillaChunkHolder);
|
||||
PlatformHooks.get().onChunkNotTicking(chunk, this.vanillaChunkHolder);
|
||||
this.updateCurrentState(FullChunkStatus.FULL);
|
||||
}
|
||||
|
||||
if (current.isOrAfter(FullChunkStatus.FULL) && !pending.isOrAfter(FullChunkStatus.FULL)) {
|
||||
this.onFullChunkLoadChange(false, changedFullStatus);
|
||||
this.changeEntityChunkStatus(FullChunkStatus.INACCESSIBLE);
|
||||
ChunkSystem.onChunkNotBorder(chunk, this.vanillaChunkHolder);
|
||||
ChunkSystem.onChunkPostNotBorder(chunk, this.vanillaChunkHolder);
|
||||
PlatformHooks.get().onChunkNotBorder(chunk, this.vanillaChunkHolder);
|
||||
PlatformHooks.get().onChunkPostNotBorder(chunk, this.vanillaChunkHolder);
|
||||
this.updateCurrentState(FullChunkStatus.INACCESSIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,11 +166,11 @@ public final class CollisionUtil {
|
||||
|
||||
// startIndex and endIndex inclusive
|
||||
// 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);
|
||||
do {
|
||||
final int middle = (startIndex + endIndex) >>> 1;
|
||||
final double middleVal = values[middle];
|
||||
final double middleVal = (values[middle] + offset);
|
||||
|
||||
if (value < middleVal) {
|
||||
endIndex = middle - 1;
|
||||
@@ -419,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])
|
||||
// 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
|
||||
// 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,
|
||||
@@ -429,7 +427,7 @@ public final class CollisionUtil {
|
||||
|
||||
final int floor_min_x = Math.max(
|
||||
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) {
|
||||
// cannot intersect
|
||||
@@ -438,7 +436,7 @@ public final class CollisionUtil {
|
||||
|
||||
final int ceil_max_x = Math.min(
|
||||
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) {
|
||||
// cannot intersect
|
||||
@@ -447,7 +445,7 @@ public final class CollisionUtil {
|
||||
|
||||
final int floor_min_y = Math.max(
|
||||
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) {
|
||||
// cannot intersect
|
||||
@@ -456,7 +454,7 @@ public final class CollisionUtil {
|
||||
|
||||
final int ceil_max_y = Math.min(
|
||||
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) {
|
||||
// cannot intersect
|
||||
@@ -465,7 +463,7 @@ public final class CollisionUtil {
|
||||
|
||||
final int floor_min_z = Math.max(
|
||||
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) {
|
||||
// cannot intersect
|
||||
@@ -474,7 +472,7 @@ public final class CollisionUtil {
|
||||
|
||||
final int ceil_max_z = Math.min(
|
||||
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) {
|
||||
// cannot intersect
|
||||
@@ -530,8 +528,6 @@ public final class CollisionUtil {
|
||||
// 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
|
||||
// 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,
|
||||
@@ -540,7 +536,7 @@ public final class CollisionUtil {
|
||||
|
||||
final int floor_min_y = Math.max(
|
||||
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) {
|
||||
// cannot intersect
|
||||
@@ -549,7 +545,7 @@ public final class CollisionUtil {
|
||||
|
||||
final int ceil_max_y = Math.min(
|
||||
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) {
|
||||
// cannot intersect
|
||||
@@ -558,7 +554,7 @@ public final class CollisionUtil {
|
||||
|
||||
final int floor_min_z = Math.max(
|
||||
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) {
|
||||
// cannot intersect
|
||||
@@ -567,7 +563,7 @@ public final class CollisionUtil {
|
||||
|
||||
final int ceil_max_z = Math.min(
|
||||
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) {
|
||||
// cannot intersect
|
||||
@@ -579,9 +575,9 @@ public final class CollisionUtil {
|
||||
final long[] bitset = cached_shape_data.voxelSet();
|
||||
|
||||
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(
|
||||
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
|
||||
|
||||
// note: only the order of the first loop matters
|
||||
@@ -590,7 +586,7 @@ public final class CollisionUtil {
|
||||
|
||||
final int mul_x = size_y*size_z;
|
||||
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 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]
|
||||
@@ -617,9 +613,9 @@ public final class CollisionUtil {
|
||||
|
||||
return source_move;
|
||||
} else {
|
||||
final double source_min = source.minX - off_x;
|
||||
final double source_min = source.minX;
|
||||
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
|
||||
@@ -631,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
|
||||
final int mul_x = size_y*size_z;
|
||||
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 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]
|
||||
@@ -688,8 +684,6 @@ public final class CollisionUtil {
|
||||
// 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
|
||||
// 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,
|
||||
@@ -698,7 +692,7 @@ public final class CollisionUtil {
|
||||
|
||||
final int floor_min_x = Math.max(
|
||||
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) {
|
||||
// cannot intersect
|
||||
@@ -707,7 +701,7 @@ public final class CollisionUtil {
|
||||
|
||||
final int ceil_max_x = Math.min(
|
||||
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) {
|
||||
// cannot intersect
|
||||
@@ -716,7 +710,7 @@ public final class CollisionUtil {
|
||||
|
||||
final int floor_min_z = Math.max(
|
||||
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) {
|
||||
// cannot intersect
|
||||
@@ -725,7 +719,7 @@ public final class CollisionUtil {
|
||||
|
||||
final int ceil_max_z = Math.min(
|
||||
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) {
|
||||
// cannot intersect
|
||||
@@ -737,9 +731,9 @@ public final class CollisionUtil {
|
||||
final long[] bitset = cached_shape_data.voxelSet();
|
||||
|
||||
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(
|
||||
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
|
||||
|
||||
// note: only the order of the first loop matters
|
||||
@@ -748,7 +742,7 @@ public final class CollisionUtil {
|
||||
|
||||
final int mul_x = size_y*size_z;
|
||||
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 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]
|
||||
@@ -775,9 +769,9 @@ public final class CollisionUtil {
|
||||
|
||||
return source_move;
|
||||
} else {
|
||||
final double source_min = source.minY - off_y;
|
||||
final double source_min = source.minY;
|
||||
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
|
||||
@@ -789,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
|
||||
final int mul_x = size_y*size_z;
|
||||
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 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]
|
||||
@@ -846,8 +840,6 @@ public final class CollisionUtil {
|
||||
// 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
|
||||
// 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,
|
||||
@@ -856,7 +848,7 @@ public final class CollisionUtil {
|
||||
|
||||
final int floor_min_x = Math.max(
|
||||
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) {
|
||||
// cannot intersect
|
||||
@@ -865,7 +857,7 @@ public final class CollisionUtil {
|
||||
|
||||
final int ceil_max_x = Math.min(
|
||||
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) {
|
||||
// cannot intersect
|
||||
@@ -874,7 +866,7 @@ public final class CollisionUtil {
|
||||
|
||||
final int floor_min_y = Math.max(
|
||||
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) {
|
||||
// cannot intersect
|
||||
@@ -883,7 +875,7 @@ public final class CollisionUtil {
|
||||
|
||||
final int ceil_max_y = Math.min(
|
||||
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) {
|
||||
// cannot intersect
|
||||
@@ -895,9 +887,9 @@ public final class CollisionUtil {
|
||||
final long[] bitset = cached_shape_data.voxelSet();
|
||||
|
||||
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(
|
||||
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
|
||||
|
||||
// note: only the order of the first loop matters
|
||||
@@ -906,7 +898,7 @@ public final class CollisionUtil {
|
||||
|
||||
final int mul_x = size_y*size_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 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]
|
||||
@@ -933,9 +925,9 @@ public final class CollisionUtil {
|
||||
|
||||
return source_move;
|
||||
} else {
|
||||
final double source_min = source.minZ - off_z;
|
||||
final double source_min = source.minZ;
|
||||
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
|
||||
@@ -947,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
|
||||
final int mul_x = size_y*size_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 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]
|
||||
@@ -982,7 +974,7 @@ public final class CollisionUtil {
|
||||
}
|
||||
|
||||
// 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();
|
||||
if (single_aabb != null) {
|
||||
return single_aabb.contains(x, y, z);
|
||||
@@ -993,10 +985,9 @@ public final class CollisionUtil {
|
||||
return false;
|
||||
}
|
||||
|
||||
// offset input
|
||||
x -= ((CollisionVoxelShape)voxel).moonrise$offsetX();
|
||||
y -= ((CollisionVoxelShape)voxel).moonrise$offsetY();
|
||||
z -= ((CollisionVoxelShape)voxel).moonrise$offsetZ();
|
||||
final double off_x = ((CollisionVoxelShape)voxel).moonrise$offsetX();
|
||||
final double off_y = ((CollisionVoxelShape)voxel).moonrise$offsetY();
|
||||
final double off_z = ((CollisionVoxelShape)voxel).moonrise$offsetZ();
|
||||
|
||||
final double[] coords_x = ((CollisionVoxelShape)voxel).moonrise$rootCoordinatesX();
|
||||
final double[] coords_y = ((CollisionVoxelShape)voxel).moonrise$rootCoordinatesY();
|
||||
@@ -1012,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.
|
||||
// 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) {
|
||||
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) {
|
||||
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) {
|
||||
return false;
|
||||
}
|
||||
@@ -1695,74 +1686,56 @@ public final class CollisionUtil {
|
||||
|
||||
public static double performAABBCollisionsX(final AABB currentBoundingBox, double value, final List<AABB> potentialCollisions) {
|
||||
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);
|
||||
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) {
|
||||
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);
|
||||
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) {
|
||||
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);
|
||||
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) {
|
||||
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);
|
||||
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) {
|
||||
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);
|
||||
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) {
|
||||
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);
|
||||
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) {
|
||||
|
||||
@@ -22,6 +22,8 @@ accessible field net/minecraft/world/level/chunk/PalettedContainer data Lnet/min
|
||||
|
||||
# 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
|
||||
@@ -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 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
|
||||
accessible field net/minecraft/client/renderer/chunk/VisibilitySet FACINGS I
|
||||
@@ -305,3 +312,5 @@ accessible class net/minecraft/world/level/LocalMobCapCalculator$MobCounts
|
||||
|
||||
# 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
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
"chunk_system.ChunkStepMixin",
|
||||
"chunk_system.ChunkStorageMixin",
|
||||
"chunk_system.DistanceManagerMixin",
|
||||
"chunk_system.DynamicGameEventListenerMixin",
|
||||
"chunk_system.EntityGetterMixin",
|
||||
"chunk_system.EntityMixin",
|
||||
"chunk_system.EntityTickListMixin",
|
||||
|
||||
Reference in New Issue
Block a user