Compare commits

..

2 Commits

Author SHA1 Message Date
Jason Penilla
68c3c6ffa2 leaf formatting 2025-01-17 19:38:58 -07:00
Jason Penilla
b5684eae6d Update for Lithium 0.14.6 compat 2025-01-17 19:38:58 -07:00
84 changed files with 745 additions and 1401 deletions

View File

@@ -18,10 +18,13 @@ def aw2at = Aw2AtTask.configureDefault(
sourceSets.main sourceSets.main
) )
sourceSets.create("lithium")
neoForge { neoForge {
neoFormVersion = neoform_version neoFormVersion = neoform_version
validateAccessTransformers = true validateAccessTransformers = true
accessTransformers.files.setFrom(aw2at.flatMap { t -> t.getOutputFile() }) accessTransformers.files.setFrom(aw2at.flatMap { t -> t.getOutputFile() })
addModdingDependenciesTo sourceSets.lithium
} }
runConfigCommon { runConfigCommon {
@@ -41,6 +44,13 @@ dependencies {
// todo: does cloth publish a platform-agnostic jar in mojang mappings? // todo: does cloth publish a platform-agnostic jar in mojang mappings?
compileOnly "me.shedaniel.cloth:cloth-config-neoforge:${rootProject.cloth_version}" compileOnly "me.shedaniel.cloth:cloth-config-neoforge:${rootProject.cloth_version}"
lithiumCompileOnly("maven.modrinth:lithium:${rootProject.neo_lithium_version}")
compileOnly(sourceSets.lithium.output)
}
tasks.jar {
from(sourceSets.lithium.output)
} }
allprojects { allprojects {

View File

@@ -6,12 +6,6 @@ plugins {
id 'maven-publish' id 'maven-publish'
} }
boolean gui = enable_gui == "true"
if (gui) {
sourceSets.create("gui")
loom.createRemapConfigurations(sourceSets.gui)
}
dependencies { dependencies {
minecraft "com.mojang:minecraft:${project.minecraft_version}" minecraft "com.mojang:minecraft:${project.minecraft_version}"
mappings loom.officialMojangMappings() mappings loom.officialMojangMappings()
@@ -19,6 +13,7 @@ dependencies {
testImplementation "net.fabricmc:fabric-loader-junit:${project.loader_version}" testImplementation "net.fabricmc:fabric-loader-junit:${project.loader_version}"
runtimeOnly(project(":").sourceSets.main.output) runtimeOnly(project(":").sourceSets.main.output)
runtimeOnly(project(":").sourceSets.lithium.output)
shadow(project(":")) shadow(project(":"))
compileOnly(project(":")) compileOnly(project(":"))
@@ -26,16 +21,9 @@ dependencies {
libs("ca.spottedleaf:yamlconfig:${rootProject.yamlconfig_version}") { setTransitive(false) } libs("ca.spottedleaf:yamlconfig:${rootProject.yamlconfig_version}") { setTransitive(false) }
libs("org.yaml:snakeyaml:${rootProject.snakeyaml_version}") libs("org.yaml:snakeyaml:${rootProject.snakeyaml_version}")
if (gui) { modImplementation "me.shedaniel.cloth:cloth-config-fabric:${rootProject.cloth_version}"
guiCompileOnly(project(":")) include "me.shedaniel.cloth:cloth-config-fabric:${rootProject.cloth_version}"
runtimeOnly(sourceSets.gui.output) modImplementation "com.terraformersmc:modmenu:${rootProject.modmenu_version}"
shadow(sourceSets.gui.output)
modGuiImplementation "me.shedaniel.cloth:cloth-config-fabric:${rootProject.cloth_version}"
modRuntimeOnly "me.shedaniel.cloth:cloth-config-fabric:${rootProject.cloth_version}"
include "me.shedaniel.cloth:cloth-config-fabric:${rootProject.cloth_version}"
modGuiImplementation "com.terraformersmc:modmenu:${rootProject.modmenu_version}"
modRuntimeOnly "com.terraformersmc:modmenu:${rootProject.modmenu_version}"
}
modImplementation platform(fabricApiLibs.bom) modImplementation platform(fabricApiLibs.bom)
modImplementation fabricApiLibs.command.api.v2 modImplementation fabricApiLibs.command.api.v2
@@ -44,14 +32,6 @@ dependencies {
include fabricApiLibs.base include fabricApiLibs.base
} }
if (gui) {
afterEvaluate {
configurations.guiCompileOnly {
extendsFrom configurations.getByName("minecraftNamedCompile")
}
}
}
tasks.processResources { tasks.processResources {
def properties = [ def properties = [
"version": project.version, "version": project.version,
@@ -106,6 +86,7 @@ loom {
main { main {
sourceSet("main") sourceSet("main")
sourceSet("main", project.rootProject) sourceSet("main", project.rootProject)
sourceSet("lithium", project.rootProject)
} }
} }
} }

View File

@@ -3,12 +3,9 @@ package ca.spottedleaf.moonrise.fabric;
import ca.spottedleaf.moonrise.common.util.BaseChunkSystemHooks; import ca.spottedleaf.moonrise.common.util.BaseChunkSystemHooks;
import ca.spottedleaf.moonrise.common.PlatformHooks; import ca.spottedleaf.moonrise.common.PlatformHooks;
import ca.spottedleaf.moonrise.common.util.ConfigHolder; import ca.spottedleaf.moonrise.common.util.ConfigHolder;
import ca.spottedleaf.moonrise.patches.chunk_system.ticket.ChunkSystemTicketType;
import com.mojang.datafixers.DSL; import com.mojang.datafixers.DSL;
import com.mojang.datafixers.DataFixer; import com.mojang.datafixers.DataFixer;
import com.mojang.logging.LogUtils;
import com.mojang.serialization.Dynamic; import com.mojang.serialization.Dynamic;
import it.unimi.dsi.fastutil.longs.LongArrays;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerChunkEvents; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerChunkEvents;
import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
@@ -18,8 +15,6 @@ import net.minecraft.server.level.ChunkHolder;
import net.minecraft.server.level.GenerationChunkHolder; import net.minecraft.server.level.GenerationChunkHolder;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.level.TicketType;
import net.minecraft.util.ProblemReporter;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.boss.EnderDragonPart; import net.minecraft.world.entity.boss.EnderDragonPart;
import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.BlockGetter;
@@ -33,9 +28,7 @@ import net.minecraft.world.level.chunk.ProtoChunk;
import net.minecraft.world.level.chunk.status.ChunkStatusTasks; import net.minecraft.world.level.chunk.status.ChunkStatusTasks;
import net.minecraft.world.level.chunk.storage.SerializableChunkData; import net.minecraft.world.level.chunk.storage.SerializableChunkData;
import net.minecraft.world.level.entity.EntityTypeTest; import net.minecraft.world.level.entity.EntityTypeTest;
import net.minecraft.world.level.storage.TagValueInput;
import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.AABB;
import org.slf4j.Logger;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.function.Predicate; import java.util.function.Predicate;
@@ -44,13 +37,16 @@ public final class FabricHooks extends BaseChunkSystemHooks implements PlatformH
private static final boolean HAS_FABRIC_LIFECYCLE_EVENTS = FabricLoader.getInstance().isModLoaded("fabric-lifecycle-events-v1"); private static final boolean HAS_FABRIC_LIFECYCLE_EVENTS = FabricLoader.getInstance().isModLoaded("fabric-lifecycle-events-v1");
private static final Logger LOGGER = LogUtils.getLogger();
@Override @Override
public String getBrand() { public String getBrand() {
return "Moonrise"; return "Moonrise";
} }
@Override
public boolean isModLoaded(final String modId) {
return FabricLoader.getInstance().isModLoaded(modId);
}
@Override @Override
public int getLightEmission(final BlockState blockState, final BlockGetter world, final BlockPos pos) { public int getLightEmission(final BlockState blockState, final BlockGetter world, final BlockPos pos) {
return blockState.getLightEmission(); return blockState.getLightEmission();
@@ -257,18 +253,11 @@ public final class FabricHooks extends BaseChunkSystemHooks implements PlatformH
@Override @Override
public void postLoadProtoChunk(final ServerLevel world, final ProtoChunk chunk) { public void postLoadProtoChunk(final ServerLevel world, final ProtoChunk chunk) {
try (final ProblemReporter.ScopedCollector scopedCollector = new ProblemReporter.ScopedCollector(chunk.problemPath(), LOGGER)) { ChunkStatusTasks.postLoadProtoChunk(world, chunk.getEntities());
ChunkStatusTasks.postLoadProtoChunk(world, TagValueInput.create(scopedCollector, world.registryAccess(), chunk.getEntities()));
}
} }
@Override @Override
public int modifyEntityTrackingRange(final Entity entity, final int currentRange) { public int modifyEntityTrackingRange(final Entity entity, final int currentRange) {
return currentRange; return currentRange;
} }
@Override
public long[] getCounterTypesUncached(final TicketType type) {
return type == TicketType.FORCED ? new long[] { ChunkSystemTicketType.COUNTER_TYPE_FORCED } : LongArrays.EMPTY_ARRAY;
}
} }

View File

@@ -0,0 +1,33 @@
package ca.spottedleaf.moonrise.fabric.mixin.chunk_system;
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkSystemDistanceManager;
import net.minecraft.server.level.ChunkLevel;
import net.minecraft.server.level.DistanceManager;
import net.minecraft.server.level.FullChunkStatus;
import net.minecraft.server.level.TicketType;
import net.minecraft.world.level.ChunkPos;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
@Mixin(DistanceManager.class)
abstract class FabricDistanceManagerMixin implements ChunkSystemDistanceManager {
/**
* @reason Route to new chunk system
* @author Spottedleaf
*/
@Overwrite
public <T> void addRegionTicket(final TicketType<T> type, final ChunkPos pos, final int radius, final T identifier) {
this.moonrise$getChunkHolderManager().addTicketAtLevel(type, pos, ChunkLevel.byStatus(FullChunkStatus.FULL) - radius, identifier);
}
/**
* @reason Route to new chunk system
* @author Spottedleaf
*/
@Overwrite
public <T> void removeRegionTicket(final TicketType<T> type, final ChunkPos pos, final int radius, final T identifier) {
this.moonrise$getChunkHolderManager().removeTicketAtLevel(type, pos, ChunkLevel.byStatus(FullChunkStatus.FULL) - radius, identifier);
}
}

View File

@@ -36,7 +36,7 @@
"accessWidener": "moonrise.accesswidener", "accessWidener": "moonrise.accesswidener",
"depends": { "depends": {
"fabricloader": ">=${loader_version}", "fabricloader": ">=${loader_version}",
"minecraft": ">1.21.5 <1.21.7", "minecraft": ">1.21.3 <1.21.5",
"fabric-command-api-v2": "*" "fabric-command-api-v2": "*"
}, },
"custom": { "custom": {

View File

@@ -2,6 +2,7 @@
"parent": "moonrise.mixins.json", "parent": "moonrise.mixins.json",
"package": "ca.spottedleaf.moonrise.fabric.mixin", "package": "ca.spottedleaf.moonrise.fabric.mixin",
"mixins": [ "mixins": [
"chunk_system.FabricDistanceManagerMixin",
"chunk_system.FabricMinecraftServerMixin", "chunk_system.FabricMinecraftServerMixin",
"chunk_system.FabricServerLevelMixin", "chunk_system.FabricServerLevelMixin",
"collisions.EntityMixin" "collisions.EntityMixin"

View File

@@ -4,25 +4,23 @@ org.gradle.parallel=true
org.gradle.caching=true org.gradle.caching=true
org.gradle.configuration-cache=true org.gradle.configuration-cache=true
# Fabric Properties # Fabric Properties
# check these on https://fabricmc.net/develop/ # check these on https://modmuss50.me/fabric.html
minecraft_version=1.21.6 minecraft_version=1.21.4
loader_version=0.16.14 loader_version=0.16.9
supported_minecraft_versions=1.21.6 supported_minecraft_versions=1.21.4
neoforge_version=21.6.5-beta neoforge_version=21.4.59-beta
neoform_version=1.21.6-20250617.151856 neoform_version=1.21.4-20241203.161809
fabric_api_version=0.127.0+1.21.6 fabric_api_version=0.114.3+1.21.4
snakeyaml_version=2.3 snakeyaml_version=2.3
concurrentutil_version=0.0.3 concurrentutil_version=0.0.3
yamlconfig_version=1.0.2 yamlconfig_version=1.0.2
cloth_version=19.0.146 cloth_version=17.0.144
modmenu_version=15.0.0-beta.2 modmenu_version=13.0.0-beta.1
# set to false when modmenu/cloth is not updated for the current minecraft version
enable_gui=true
junit_version=5.11.3 junit_version=5.11.3
# version ids from modrinth # version ids from modrinth
fabric_lithium_version=nhc57Td2 fabric_lithium_version=zVOQw7YU
neo_lithium_version=P5VT33Jo neo_lithium_version=CfXh2ZF6
# Mod Properties # Mod Properties
mod_version=0.4.0-beta.1 mod_version=0.2.0-SNAPSHOT
maven_group=ca.spottedleaf.moonrise maven_group=ca.spottedleaf.moonrise
archives_base_name=moonrise archives_base_name=moonrise

Binary file not shown.

View File

@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.1-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-all.zip
networkTimeout=10000 networkTimeout=10000
validateDistributionUrl=true validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME

6
gradlew vendored
View File

@@ -114,7 +114,7 @@ case "$( uname )" in #(
NONSTOP* ) nonstop=true ;; NONSTOP* ) nonstop=true ;;
esac esac
CLASSPATH="\\\"\\\"" CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM. # Determine the Java command to use to start the JVM.
@@ -205,7 +205,7 @@ fi
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command: # Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, # * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped. # and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line. # treated as '${Hostname}' itself on the command line.
@@ -213,7 +213,7 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
set -- \ set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \ "-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \ -classpath "$CLASSPATH" \
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ org.gradle.wrapper.GradleWrapperMain \
"$@" "$@"
# Stop when "xargs" is not available. # Stop when "xargs" is not available.

4
gradlew.bat vendored
View File

@@ -70,11 +70,11 @@ goto fail
:execute :execute
@rem Setup the command line @rem Setup the command line
set CLASSPATH= set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle @rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end :end
@rem End local scope for the variables with windows NT shell @rem End local scope for the variables with windows NT shell

View File

@@ -28,6 +28,7 @@ neoForge {
moonrise { moonrise {
sourceSet sourceSets.main sourceSet sourceSets.main
sourceSet rootProject.sourceSets.main sourceSet rootProject.sourceSets.main
sourceSet rootProject.sourceSets.lithium
} }
} }
runs { runs {
@@ -46,6 +47,7 @@ neoForge {
dependencies { dependencies {
runtimeOnly(project(":").sourceSets.main.output) runtimeOnly(project(":").sourceSets.main.output)
runtimeOnly(project(":").sourceSets.lithium.output)
shadow(project(":")) shadow(project(":"))
compileOnly(project(":")) compileOnly(project(":"))

View File

@@ -4,12 +4,9 @@ import ca.spottedleaf.moonrise.common.util.BaseChunkSystemHooks;
import ca.spottedleaf.moonrise.common.PlatformHooks; import ca.spottedleaf.moonrise.common.PlatformHooks;
import ca.spottedleaf.moonrise.common.util.ConfigHolder; import ca.spottedleaf.moonrise.common.util.ConfigHolder;
import ca.spottedleaf.moonrise.common.util.CoordinateUtils; import ca.spottedleaf.moonrise.common.util.CoordinateUtils;
import ca.spottedleaf.moonrise.patches.chunk_system.ticket.ChunkSystemTicketType;
import com.mojang.datafixers.DSL; import com.mojang.datafixers.DSL;
import com.mojang.datafixers.DataFixer; import com.mojang.datafixers.DataFixer;
import com.mojang.logging.LogUtils;
import com.mojang.serialization.Dynamic; import com.mojang.serialization.Dynamic;
import it.unimi.dsi.fastutil.longs.LongArrayList;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtOps; import net.minecraft.nbt.NbtOps;
@@ -17,8 +14,6 @@ import net.minecraft.server.level.ChunkHolder;
import net.minecraft.server.level.GenerationChunkHolder; import net.minecraft.server.level.GenerationChunkHolder;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.level.TicketType;
import net.minecraft.util.ProblemReporter;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.ChunkPos;
@@ -32,8 +27,9 @@ import net.minecraft.world.level.chunk.ProtoChunk;
import net.minecraft.world.level.chunk.status.ChunkStatusTasks; import net.minecraft.world.level.chunk.status.ChunkStatusTasks;
import net.minecraft.world.level.chunk.storage.SerializableChunkData; import net.minecraft.world.level.chunk.storage.SerializableChunkData;
import net.minecraft.world.level.entity.EntityTypeTest; import net.minecraft.world.level.entity.EntityTypeTest;
import net.minecraft.world.level.storage.TagValueInput;
import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.AABB;
import net.neoforged.fml.ModList;
import net.neoforged.fml.loading.LoadingModList;
import net.neoforged.neoforge.common.CommonHooks; import net.neoforged.neoforge.common.CommonHooks;
import net.neoforged.neoforge.common.NeoForge; import net.neoforged.neoforge.common.NeoForge;
import net.neoforged.neoforge.entity.PartEntity; import net.neoforged.neoforge.entity.PartEntity;
@@ -41,20 +37,26 @@ import net.neoforged.neoforge.event.EventHooks;
import net.neoforged.neoforge.event.entity.EntityJoinLevelEvent; import net.neoforged.neoforge.event.entity.EntityJoinLevelEvent;
import net.neoforged.neoforge.event.level.ChunkDataEvent; import net.neoforged.neoforge.event.level.ChunkDataEvent;
import net.neoforged.neoforge.event.level.ChunkEvent; import net.neoforged.neoforge.event.level.ChunkEvent;
import org.slf4j.Logger;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.function.Predicate; import java.util.function.Predicate;
public final class NeoForgeHooks extends BaseChunkSystemHooks implements PlatformHooks { public final class NeoForgeHooks extends BaseChunkSystemHooks implements PlatformHooks {
private static final Logger LOGGER = LogUtils.getLogger();
@Override @Override
public String getBrand() { public String getBrand() {
return "Moonrise"; return "Moonrise";
} }
@Override
public boolean isModLoaded(final String modId) {
final ModList modList = ModList.get();
if (modList == null) {
return LoadingModList.get().getModFileById(modId) != null;
}
return modList.isLoaded(modId);
}
@Override @Override
public int getLightEmission(final BlockState blockState, final BlockGetter world, final BlockPos pos) { public int getLightEmission(final BlockState blockState, final BlockGetter world, final BlockPos pos) {
return blockState.getLightEmission(world, pos); return blockState.getLightEmission(world, pos);
@@ -263,27 +265,11 @@ public final class NeoForgeHooks extends BaseChunkSystemHooks implements Platfor
@Override @Override
public void postLoadProtoChunk(final ServerLevel world, final ProtoChunk chunk) { public void postLoadProtoChunk(final ServerLevel world, final ProtoChunk chunk) {
try (final ProblemReporter.ScopedCollector scopedCollector = new ProblemReporter.ScopedCollector(chunk.problemPath(), LOGGER)) { ChunkStatusTasks.postLoadProtoChunk(world, chunk.getEntities());
ChunkStatusTasks.postLoadProtoChunk(world, TagValueInput.create(scopedCollector, world.registryAccess(), chunk.getEntities()));
}
} }
@Override @Override
public int modifyEntityTrackingRange(final Entity entity, final int currentRange) { public int modifyEntityTrackingRange(final Entity entity, final int currentRange) {
return currentRange; return currentRange;
} }
@Override
public long[] getCounterTypesUncached(final TicketType type) {
final LongArrayList ret = new LongArrayList();
if (type == TicketType.FORCED) {
ret.add(ChunkSystemTicketType.COUNTER_TYPE_FORCED);
}
if (type.forceNaturalSpawning()) {
ret.add(ChunkSystemTicketType.COUNTER_TYPER_NATURAL_SPAWNING_FORCED);
}
return ret.toLongArray();
}
} }

View File

@@ -0,0 +1,87 @@
package ca.spottedleaf.moonrise.neoforge.mixin.chunk_system;
import ca.spottedleaf.moonrise.common.util.CoordinateUtils;
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkSystemDistanceManager;
import ca.spottedleaf.moonrise.patches.chunk_tick_iteration.ChunkTickServerLevel;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import net.minecraft.server.level.ChunkLevel;
import net.minecraft.server.level.DistanceManager;
import net.minecraft.server.level.FullChunkStatus;
import net.minecraft.server.level.Ticket;
import net.minecraft.server.level.TicketType;
import net.minecraft.util.SortedArraySet;
import net.minecraft.world.level.ChunkPos;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
@Mixin(DistanceManager.class)
abstract class NeoForgeDistanceManagerMixin implements ChunkSystemDistanceManager {
@Shadow
@Final
private Long2ObjectOpenHashMap<SortedArraySet<Ticket<?>>> forcedTickets;
/**
* @reason Route to new chunk system
* @author Spottedleaf
*/
@Overwrite
public <T> void addRegionTicket(final TicketType<T> type, final ChunkPos pos, final int radius, final T identifier, final boolean forceTicks) {
final int level = ChunkLevel.byStatus(FullChunkStatus.FULL) - radius;
this.moonrise$getChunkHolderManager().addTicketAtLevel(type, pos, level, identifier);
if (forceTicks) {
final Ticket<T> forceTicket = new Ticket<>(type, level, identifier, forceTicks);
this.forcedTickets.compute(pos.toLong(), (final Long keyInMap, final SortedArraySet<Ticket<?>> valueInMap) -> {
final SortedArraySet<Ticket<?>> ret;
if (valueInMap != null) {
ret = valueInMap;
} else {
ret = SortedArraySet.create(4);
}
if (ret.add(forceTicket)) {
((ChunkTickServerLevel)NeoForgeDistanceManagerMixin.this.moonrise$getChunkMap().level).moonrise$addPlayerTickingRequest(
CoordinateUtils.getChunkX(keyInMap.longValue()), CoordinateUtils.getChunkZ(keyInMap.longValue())
);
}
return ret;
});
}
}
/**
* @reason Route to new chunk system
* @author Spottedleaf
*/
@Overwrite
public <T> void removeRegionTicket(final TicketType<T> type, final ChunkPos pos, final int radius, final T identifier, final boolean forceTicks) {
final int level = ChunkLevel.byStatus(FullChunkStatus.FULL) - radius;
this.moonrise$getChunkHolderManager().removeTicketAtLevel(type, pos, level, identifier);
if (forceTicks) {
final Ticket<T> forceTicket = new Ticket<>(type, level, identifier, forceTicks);
this.forcedTickets.computeIfPresent(pos.toLong(), (final Long keyInMap, final SortedArraySet<Ticket<?>> valueInMap) -> {
if (valueInMap.remove(forceTicket)) {
((ChunkTickServerLevel)NeoForgeDistanceManagerMixin.this.moonrise$getChunkMap().level).moonrise$removePlayerTickingRequest(
CoordinateUtils.getChunkX(keyInMap.longValue()), CoordinateUtils.getChunkZ(keyInMap.longValue())
);
}
return valueInMap.isEmpty() ? null : valueInMap;
});
}
}
/**
* @reason Only use containsKey, as we fix the leak with this impl
* @author Spottedleaf
*/
@Overwrite
public boolean shouldForceTicks(final long chunkPos) {
return this.forcedTickets.containsKey(chunkPos);
}
}

View File

@@ -1,69 +0,0 @@
package ca.spottedleaf.moonrise.neoforge.mixin.chunk_system;
import ca.spottedleaf.moonrise.common.util.CoordinateUtils;
import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel;
import ca.spottedleaf.moonrise.patches.chunk_system.ticket.ChunkSystemTicketStorage;
import ca.spottedleaf.moonrise.patches.chunk_system.ticket.ChunkSystemTicketType;
import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.longs.LongSet;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.TicketStorage;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
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.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(TicketStorage.class)
abstract class NeoForgeTicketStorageMixin implements ChunkSystemTicketStorage {
@Shadow
private LongSet chunksWithForceNaturalSpawning;
/**
* @reason Destroy old chunk system state
* @author Spottedleaf
*/
@Inject(
method = "<init>(Lit/unimi/dsi/fastutil/longs/Long2ObjectOpenHashMap;Lit/unimi/dsi/fastutil/longs/Long2ObjectOpenHashMap;)V",
at = @At(
value = "RETURN"
)
)
private void destroyFields(Long2ObjectOpenHashMap p_393873_, Long2ObjectOpenHashMap p_394615_, CallbackInfo ci) {
this.chunksWithForceNaturalSpawning = null;
}
/**
* @reason The forced natural spawning chunks would be empty, as tickets should always be empty.
* We need to do this to avoid throwing immediately.
* @author Spottedleaf
*/
@Redirect(
method = "<init>(Lit/unimi/dsi/fastutil/longs/Long2ObjectOpenHashMap;Lit/unimi/dsi/fastutil/longs/Long2ObjectOpenHashMap;)V",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/level/TicketStorage;updateForcedNaturalSpawning()V"
)
)
private void avoidUpdatingForcedNaturalChunks(final TicketStorage instance) {}
/**
* @reason Route to new chunk system
* @author Spottedleaf
*/
@Overwrite
public boolean shouldForceNaturalSpawning(final ChunkPos pos) {
final Long2IntOpenHashMap counters = ((ChunkSystemServerLevel)this.moonrise$getChunkMap().level).moonrise$getChunkTaskScheduler()
.chunkHolderManager.getTicketCounters(ChunkSystemTicketType.COUNTER_TYPER_NATURAL_SPAWNING_FORCED);
if (counters == null) {
return false;
}
return counters.containsKey(CoordinateUtils.getChunkKey(pos));
}
}

View File

@@ -28,7 +28,7 @@ side = "BOTH"
[[dependencies.moonrise]] [[dependencies.moonrise]]
modId = "minecraft" modId = "minecraft"
type = "required" type = "required"
versionRange = "(1.21.5,1.21.7)" versionRange = "(1.21.3,1.21.5)"
ordering = "NONE" ordering = "NONE"
side = "BOTH" side = "BOTH"

View File

@@ -2,9 +2,9 @@
"parent": "moonrise.mixins.json", "parent": "moonrise.mixins.json",
"package": "ca.spottedleaf.moonrise.neoforge.mixin", "package": "ca.spottedleaf.moonrise.neoforge.mixin",
"mixins": [ "mixins": [
"chunk_system.NeoForgeDistanceManagerMixin",
"chunk_system.NeoForgeMinecraftServerMixin", "chunk_system.NeoForgeMinecraftServerMixin",
"chunk_system.NeoForgeServerLevelMixin", "chunk_system.NeoForgeServerLevelMixin",
"chunk_system.NeoForgeTicketStorageMixin",
"collisions.EntityMixin" "collisions.EntityMixin"
], ],
"client": [ "client": [

View File

@@ -22,10 +22,10 @@ pluginManagement {
} }
plugins { plugins {
id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0" id("org.gradle.toolchains.foojay-resolver-convention") version "0.9.0"
id("quiet-fabric-loom") version "1.10.317" apply false id("quiet-fabric-loom") version "1.9.312" apply false
id("net.neoforged.moddev") version "2.0.80" apply false id("net.neoforged.moddev") version "2.0.61-beta" apply false
id 'com.gradleup.shadow' version '8.3.6' apply false id 'com.gradleup.shadow' version '8.3.5' apply false
} }
dependencyResolutionManagement { dependencyResolutionManagement {

View File

@@ -0,0 +1,18 @@
package ca.spottledleaf.moonrise.compat.lithium;
import net.caffeinemc.mods.lithium.common.world.chunk.ChunkStatusTracker;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.chunk.LevelChunk;
public final class LithiumHooks {
private LithiumHooks() {}
public static void onChunkInaccessible(final ServerLevel serverLevel, final ChunkPos pos) {
ChunkStatusTracker.onChunkInaccessible(serverLevel, pos);
}
public static void onChunkAccessible(final ServerLevel serverLevel, final LevelChunk chunk) {
ChunkStatusTracker.onChunkAccessible(serverLevel, chunk);
}
}

View File

@@ -31,6 +31,10 @@ public interface PlatformHooks extends ChunkSystemHooks {
public String getBrand(); public String getBrand();
public default boolean isModLoaded(final String modId) {
return false;
}
public int getLightEmission(final BlockState blockState, final BlockGetter world, final BlockPos pos); public int getLightEmission(final BlockState blockState, final BlockGetter world, final BlockPos pos);
public Predicate<BlockState> maybeHasLightEmission(); public Predicate<BlockState> maybeHasLightEmission();

View File

@@ -2,7 +2,6 @@ package ca.spottedleaf.moonrise.common.list;
import it.unimi.dsi.fastutil.objects.Reference2IntLinkedOpenHashMap; import it.unimi.dsi.fastutil.objects.Reference2IntLinkedOpenHashMap;
import it.unimi.dsi.fastutil.objects.Reference2IntMap; import it.unimi.dsi.fastutil.objects.Reference2IntMap;
import java.lang.reflect.Array;
import java.util.Arrays; import java.util.Arrays;
import java.util.NoSuchElementException; import java.util.NoSuchElementException;
@@ -22,34 +21,15 @@ public final class IteratorSafeOrderedReferenceSet<E> {
private int iteratorCount; private int iteratorCount;
public IteratorSafeOrderedReferenceSet() { public IteratorSafeOrderedReferenceSet() {
this(Object.class); this(16, 0.75f, 16, 0.2);
}
public IteratorSafeOrderedReferenceSet(final Class<? super E> arrComponent) {
this(16, 0.75f, 16, 0.2, arrComponent);
} }
public IteratorSafeOrderedReferenceSet(final int setCapacity, final float setLoadFactor, final int arrayCapacity, public IteratorSafeOrderedReferenceSet(final int setCapacity, final float setLoadFactor, final int arrayCapacity,
final double maxFragFactor) { final double maxFragFactor) {
this(setCapacity, setLoadFactor, arrayCapacity, maxFragFactor, Object.class);
}
public IteratorSafeOrderedReferenceSet(final int setCapacity, final float setLoadFactor, final int arrayCapacity,
final double maxFragFactor, final Class<? super E> arrComponent) {
this.indexMap = new Reference2IntLinkedOpenHashMap<>(setCapacity, setLoadFactor); this.indexMap = new Reference2IntLinkedOpenHashMap<>(setCapacity, setLoadFactor);
this.indexMap.defaultReturnValue(-1); this.indexMap.defaultReturnValue(-1);
this.maxFragFactor = maxFragFactor; this.maxFragFactor = maxFragFactor;
this.listElements = (E[])Array.newInstance(arrComponent, arrayCapacity); this.listElements = (E[])new Object[arrayCapacity];
}
// includes null (gravestone) elements
public E[] getListRaw() {
return this.listElements;
}
// includes null (gravestone) elements
public int getListSize() {
return this.listSize;
} }
/* /*
@@ -101,7 +81,7 @@ public final class IteratorSafeOrderedReferenceSet<E> {
public int createRawIterator() { public int createRawIterator() {
++this.iteratorCount; ++this.iteratorCount;
if (this.indexMap.isEmpty()) { if (this.indexMap.isEmpty()) {
return Integer.MAX_VALUE; return -1;
} else { } else {
return this.firstInvalidIndex == 0 ? this.indexMap.getInt(this.indexMap.firstKey()) : 0; return this.firstInvalidIndex == 0 ? this.indexMap.getInt(this.indexMap.firstKey()) : 0;
} }
@@ -116,7 +96,7 @@ public final class IteratorSafeOrderedReferenceSet<E> {
} }
} }
return Integer.MAX_VALUE; return -1;
} }
public void finishRawIterator() { public void finishRawIterator() {
@@ -225,6 +205,10 @@ public final class IteratorSafeOrderedReferenceSet<E> {
//this.check(); //this.check();
} }
public E rawGet(final int index) {
return this.listElements[index];
}
public int size() { public int size() {
// always returns the correct amount - listSize can be different // always returns the correct amount - listSize can be different
return this.indexMap.size(); return this.indexMap.size();

View File

@@ -1,6 +1,6 @@
package ca.spottedleaf.moonrise.common.misc; package ca.spottedleaf.moonrise.common.misc;
import ca.spottedleaf.moonrise.common.util.CoordinateUtils; import ca.spottedleaf.concurrentutil.util.IntPairUtil;
import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap;
import it.unimi.dsi.fastutil.longs.LongSet; import it.unimi.dsi.fastutil.longs.LongSet;
import it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap; import it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap;
@@ -23,16 +23,12 @@ public final class PositionCountingAreaMap<T> {
return this.positions.size(); return this.positions.size();
} }
public boolean hasObjectsNear(final long pos) {
return this.positions.containsKey(pos);
}
public boolean hasObjectsNear(final int toX, final int toZ) { public boolean hasObjectsNear(final int toX, final int toZ) {
return this.positions.containsKey(CoordinateUtils.getChunkKey(toX, toZ)); return this.positions.containsKey(IntPairUtil.key(toX, toZ));
} }
public int getObjectsNear(final int toX, final int toZ) { public int getObjectsNear(final int toX, final int toZ) {
return this.positions.get(CoordinateUtils.getChunkKey(toX, toZ)); return this.positions.get(IntPairUtil.key(toX, toZ));
} }
public boolean add(final T parameter, final int toX, final int toZ, final int distance) { public boolean add(final T parameter, final int toX, final int toZ, final int distance) {
@@ -89,12 +85,12 @@ public final class PositionCountingAreaMap<T> {
@Override @Override
protected void addCallback(final T parameter, final int toX, final int toZ) { protected void addCallback(final T parameter, final int toX, final int toZ) {
PositionCountingAreaMap.this.positions.addTo(CoordinateUtils.getChunkKey(toX, toZ), 1); PositionCountingAreaMap.this.positions.addTo(IntPairUtil.key(toX, toZ), 1);
} }
@Override @Override
protected void removeCallback(final T parameter, final int toX, final int toZ) { protected void removeCallback(final T parameter, final int toX, final int toZ) {
final long key = CoordinateUtils.getChunkKey(toX, toZ); final long key = IntPairUtil.key(toX, toZ);
if (PositionCountingAreaMap.this.positions.addTo(key, -1) == 1) { if (PositionCountingAreaMap.this.positions.addTo(key, -1) == 1) {
PositionCountingAreaMap.this.positions.remove(key); PositionCountingAreaMap.this.positions.remove(key);
} }

View File

@@ -1,5 +1,7 @@
package ca.spottedleaf.moonrise.common.misc; package ca.spottedleaf.moonrise.common.misc;
import ca.spottedleaf.concurrentutil.util.IntegerUtil;
public abstract class SingleUserAreaMap<T> { public abstract class SingleUserAreaMap<T> {
public static final int NOT_SET = Integer.MIN_VALUE; public static final int NOT_SET = Integer.MIN_VALUE;
@@ -97,8 +99,8 @@ public abstract class SingleUserAreaMap<T> {
final int dx = toX - fromX; final int dx = toX - fromX;
final int dz = toZ - fromZ; final int dz = toZ - fromZ;
final int totalX = Math.abs(fromX - toX); final int totalX = IntegerUtil.branchlessAbs(fromX - toX);
final int totalZ = Math.abs(fromZ - toZ); final int totalZ = IntegerUtil.branchlessAbs(fromZ - toZ);
if (Math.max(totalX, totalZ) > (2 * Math.max(newViewDistance, oldViewDistance))) { if (Math.max(totalX, totalZ) > (2 * Math.max(newViewDistance, oldViewDistance))) {
// teleported // teleported
@@ -118,7 +120,7 @@ public abstract class SingleUserAreaMap<T> {
for (int currZ = oldMinZ; currZ <= oldMaxZ; ++currZ) { for (int currZ = oldMinZ; currZ <= oldMaxZ; ++currZ) {
// only remove if we're outside the new view distance... // only remove if we're outside the new view distance...
if (Math.max(Math.abs(currX - toX), Math.abs(currZ - toZ)) > newViewDistance) { if (Math.max(IntegerUtil.branchlessAbs(currX - toX), IntegerUtil.branchlessAbs(currZ - toZ)) > newViewDistance) {
this.removeCallback(parameter, currX, currZ); this.removeCallback(parameter, currX, currZ);
} }
} }
@@ -134,7 +136,7 @@ public abstract class SingleUserAreaMap<T> {
for (int currZ = newMinZ; currZ <= newMaxZ; ++currZ) { for (int currZ = newMinZ; currZ <= newMaxZ; ++currZ) {
// only add if we're outside the old view distance... // only add if we're outside the old view distance...
if (Math.max(Math.abs(currX - fromX), Math.abs(currZ - fromZ)) > oldViewDistance) { if (Math.max(IntegerUtil.branchlessAbs(currX - fromX), IntegerUtil.branchlessAbs(currZ - fromZ)) > oldViewDistance) {
this.addCallback(parameter, currX, currZ); this.addCallback(parameter, currX, currZ);
} }
} }

View File

@@ -1,11 +1,13 @@
package ca.spottedleaf.moonrise.common.util; package ca.spottedleaf.moonrise.common.util;
import ca.spottedleaf.concurrentutil.util.Priority; import ca.spottedleaf.concurrentutil.util.Priority;
import ca.spottedleaf.moonrise.common.PlatformHooks;
import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel; import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel;
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkSystemLevelChunk; import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkSystemLevelChunk;
import ca.spottedleaf.moonrise.patches.chunk_system.player.RegionizedPlayerChunkLoader; import ca.spottedleaf.moonrise.patches.chunk_system.player.RegionizedPlayerChunkLoader;
import ca.spottedleaf.moonrise.patches.chunk_system.world.ChunkSystemServerChunkCache; import ca.spottedleaf.moonrise.patches.chunk_system.world.ChunkSystemServerChunkCache;
import ca.spottedleaf.moonrise.patches.chunk_tick_iteration.ChunkTickServerLevel; import ca.spottedleaf.moonrise.patches.chunk_tick_iteration.ChunkTickServerLevel;
import ca.spottledleaf.moonrise.compat.lithium.LithiumHooks;
import net.minecraft.server.level.ChunkHolder; import net.minecraft.server.level.ChunkHolder;
import net.minecraft.server.level.FullChunkStatus; import net.minecraft.server.level.FullChunkStatus;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
@@ -19,9 +21,11 @@ import java.util.function.Consumer;
public abstract class BaseChunkSystemHooks implements ChunkSystemHooks { public abstract class BaseChunkSystemHooks implements ChunkSystemHooks {
private final boolean hasLithium = ((PlatformHooks)this).isModLoaded("lithium");
@Override @Override
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) {
this.scheduleChunkTask(level, chunkX, chunkZ, run, Priority.NORMAL); scheduleChunkTask(level, chunkX, chunkZ, run, Priority.NORMAL);
} }
@Override @Override
@@ -71,7 +75,7 @@ public abstract class BaseChunkSystemHooks implements ChunkSystemHooks {
@Override @Override
public boolean hasAnyChunkHolders(final ServerLevel level) { public boolean hasAnyChunkHolders(final ServerLevel level) {
return this.getUpdatingChunkHolderCount(level) != 0; return getUpdatingChunkHolderCount(level) != 0;
} }
@Override @Override
@@ -98,12 +102,22 @@ public abstract class BaseChunkSystemHooks implements ChunkSystemHooks {
@Override @Override
public void onChunkBorder(final LevelChunk chunk, final ChunkHolder holder) { public void onChunkBorder(final LevelChunk chunk, final ChunkHolder holder) {
((ChunkSystemServerLevel)((ServerLevel)chunk.getLevel())).moonrise$getLoadedChunks().add(chunk); ((ChunkSystemServerLevel)((ServerLevel)chunk.getLevel())).moonrise$getLoadedChunks().add(
((ChunkSystemLevelChunk)chunk).moonrise$getChunkAndHolder()
);
if (this.hasLithium) {
LithiumHooks.onChunkAccessible((ServerLevel) chunk.getLevel(), chunk);
}
} }
@Override @Override
public void onChunkNotBorder(final LevelChunk chunk, final ChunkHolder holder) { public void onChunkNotBorder(final LevelChunk chunk, final ChunkHolder holder) {
((ChunkSystemServerLevel)((ServerLevel)chunk.getLevel())).moonrise$getLoadedChunks().remove(chunk); ((ChunkSystemServerLevel)((ServerLevel)chunk.getLevel())).moonrise$getLoadedChunks().remove(
((ChunkSystemLevelChunk)chunk).moonrise$getChunkAndHolder()
);
if (this.hasLithium) {
LithiumHooks.onChunkInaccessible((ServerLevel) chunk.getLevel(), chunk.getPos());
}
} }
@Override @Override
@@ -114,31 +128,39 @@ public abstract class BaseChunkSystemHooks implements ChunkSystemHooks {
@Override @Override
public void onChunkTicking(final LevelChunk chunk, final ChunkHolder holder) { public void onChunkTicking(final LevelChunk chunk, final ChunkHolder holder) {
((ChunkSystemServerLevel)((ServerLevel)chunk.getLevel())).moonrise$getTickingChunks().add(chunk); ((ChunkSystemServerLevel)((ServerLevel)chunk.getLevel())).moonrise$getTickingChunks().add(
((ChunkSystemLevelChunk)chunk).moonrise$getChunkAndHolder()
);
if (!((ChunkSystemLevelChunk)chunk).moonrise$isPostProcessingDone()) { if (!((ChunkSystemLevelChunk)chunk).moonrise$isPostProcessingDone()) {
chunk.postProcessGeneration((ServerLevel)chunk.getLevel()); chunk.postProcessGeneration((ServerLevel)chunk.getLevel());
} }
((ServerLevel)chunk.getLevel()).startTickingChunk(chunk); ((ServerLevel)chunk.getLevel()).startTickingChunk(chunk);
((ServerLevel)chunk.getLevel()).getChunkSource().chunkMap.tickingGenerated.incrementAndGet(); ((ServerLevel)chunk.getLevel()).getChunkSource().chunkMap.tickingGenerated.incrementAndGet();
}
@Override
public void onChunkNotTicking(final LevelChunk chunk, final ChunkHolder holder) {
((ChunkSystemServerLevel)((ServerLevel)chunk.getLevel())).moonrise$getTickingChunks().remove(chunk);
}
@Override
public void onChunkEntityTicking(final LevelChunk chunk, final ChunkHolder holder) {
((ChunkSystemServerLevel)((ServerLevel)chunk.getLevel())).moonrise$getEntityTickingChunks().add(chunk);
((ChunkTickServerLevel)(ServerLevel)chunk.getLevel()).moonrise$markChunkForPlayerTicking(chunk); // Moonrise - chunk tick iteration ((ChunkTickServerLevel)(ServerLevel)chunk.getLevel()).moonrise$markChunkForPlayerTicking(chunk); // Moonrise - chunk tick iteration
} }
@Override @Override
public void onChunkNotEntityTicking(final LevelChunk chunk, final ChunkHolder holder) { public void onChunkNotTicking(final LevelChunk chunk, final ChunkHolder holder) {
((ChunkSystemServerLevel)((ServerLevel)chunk.getLevel())).moonrise$getEntityTickingChunks().remove(chunk); ((ChunkSystemServerLevel)((ServerLevel)chunk.getLevel())).moonrise$getTickingChunks().remove(
((ChunkSystemLevelChunk)chunk).moonrise$getChunkAndHolder()
);
((ChunkTickServerLevel)(ServerLevel)chunk.getLevel()).moonrise$removeChunkForPlayerTicking(chunk); // Moonrise - chunk tick iteration ((ChunkTickServerLevel)(ServerLevel)chunk.getLevel()).moonrise$removeChunkForPlayerTicking(chunk); // Moonrise - chunk tick iteration
} }
@Override
public void onChunkEntityTicking(final LevelChunk chunk, final ChunkHolder holder) {
((ChunkSystemServerLevel)((ServerLevel)chunk.getLevel())).moonrise$getEntityTickingChunks().add(
((ChunkSystemLevelChunk)chunk).moonrise$getChunkAndHolder()
);
}
@Override
public void onChunkNotEntityTicking(final LevelChunk chunk, final ChunkHolder holder) {
((ChunkSystemServerLevel)((ServerLevel)chunk.getLevel())).moonrise$getEntityTickingChunks().remove(
((ChunkSystemLevelChunk)chunk).moonrise$getChunkAndHolder()
);
}
@Override @Override
public ChunkHolder getUnloadingChunkHolder(final ServerLevel level, final int chunkX, final int chunkZ) { public ChunkHolder getUnloadingChunkHolder(final ServerLevel level, final int chunkX, final int chunkZ) {
return null; return null;

View File

@@ -5,7 +5,6 @@ import net.minecraft.server.level.ChunkHolder;
import net.minecraft.server.level.FullChunkStatus; import net.minecraft.server.level.FullChunkStatus;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.level.TicketType;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.chunk.LevelChunk;
@@ -75,6 +74,4 @@ public interface ChunkSystemHooks {
public void removePlayerFromDistanceMaps(final ServerLevel world, final ServerPlayer player); public void removePlayerFromDistanceMaps(final ServerLevel world, final ServerPlayer player);
public void updateMaps(final ServerLevel world, final ServerPlayer player); public void updateMaps(final ServerLevel world, final ServerPlayer player);
public long[] getCounterTypesUncached(final TicketType type);
} }

View File

@@ -1,44 +0,0 @@
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() {}
}

View File

@@ -15,25 +15,21 @@ public class TickThread extends Thread {
private static final Logger LOGGER = LoggerFactory.getLogger(TickThread.class); private static final Logger LOGGER = LoggerFactory.getLogger(TickThread.class);
private static String getThreadContext() {
return "thread=" + Thread.currentThread().getName();
}
/** /**
* @deprecated * @deprecated
*/ */
@Deprecated @Deprecated
public static void ensureTickThread(final String reason) { public static void ensureTickThread(final String reason) {
if (!isTickThread()) { if (!isTickThread()) {
LOGGER.error("Thread failed main thread check: " + reason + ", context=" + getThreadContext(), new Throwable()); LOGGER.error("Thread " + Thread.currentThread().getName() + " failed main thread check: " + reason, new Throwable());
throw new IllegalStateException(reason); throw new IllegalStateException(reason);
} }
} }
public static void ensureTickThread(final Level world, final BlockPos pos, final String reason) { public static void ensureTickThread(final Level world, final BlockPos pos, final String reason) {
if (!isTickThreadFor(world, pos)) { if (!isTickThreadFor(world, pos)) {
final String ex = "Thread failed main thread check: " + final String ex = "Thread " + Thread.currentThread().getName() + " failed main thread check: " +
reason + ", context=" + getThreadContext() + ", world=" + WorldUtil.getWorldName(world) + ", block_pos=" + pos; reason + ", world=" + WorldUtil.getWorldName(world) + ", block_pos=" + pos;
LOGGER.error(ex, new Throwable()); LOGGER.error(ex, new Throwable());
throw new IllegalStateException(ex); throw new IllegalStateException(ex);
} }
@@ -41,8 +37,8 @@ public class TickThread extends Thread {
public static void ensureTickThread(final Level world, final BlockPos pos, final int blockRadius, final String reason) { public static void ensureTickThread(final Level world, final BlockPos pos, final int blockRadius, final String reason) {
if (!isTickThreadFor(world, pos, blockRadius)) { if (!isTickThreadFor(world, pos, blockRadius)) {
final String ex = "Thread failed main thread check: " + final String ex = "Thread " + Thread.currentThread().getName() + " failed main thread check: " +
reason + ", context=" + getThreadContext() + ", world=" + WorldUtil.getWorldName(world) + ", block_pos=" + pos + ", block_radius=" + blockRadius; reason + ", world=" + WorldUtil.getWorldName(world) + ", block_pos=" + pos + ", block_radius=" + blockRadius;
LOGGER.error(ex, new Throwable()); LOGGER.error(ex, new Throwable());
throw new IllegalStateException(ex); throw new IllegalStateException(ex);
} }
@@ -50,8 +46,8 @@ public class TickThread extends Thread {
public static void ensureTickThread(final Level world, final ChunkPos pos, final String reason) { public static void ensureTickThread(final Level world, final ChunkPos pos, final String reason) {
if (!isTickThreadFor(world, pos)) { if (!isTickThreadFor(world, pos)) {
final String ex = "Thread failed main thread check: " + final String ex = "Thread " + Thread.currentThread().getName() + " failed main thread check: " +
reason + ", context=" + getThreadContext() + ", world=" + WorldUtil.getWorldName(world) + ", chunk_pos=" + pos; reason + ", world=" + WorldUtil.getWorldName(world) + ", chunk_pos=" + pos;
LOGGER.error(ex, new Throwable()); LOGGER.error(ex, new Throwable());
throw new IllegalStateException(ex); throw new IllegalStateException(ex);
} }
@@ -59,8 +55,8 @@ public class TickThread extends Thread {
public static void ensureTickThread(final Level world, final int chunkX, final int chunkZ, final String reason) { public static void ensureTickThread(final Level world, final int chunkX, final int chunkZ, final String reason) {
if (!isTickThreadFor(world, chunkX, chunkZ)) { if (!isTickThreadFor(world, chunkX, chunkZ)) {
final String ex = "Thread failed main thread check: " + final String ex = "Thread " + Thread.currentThread().getName() + " failed main thread check: " +
reason + ", context=" + getThreadContext() + ", world=" + WorldUtil.getWorldName(world) + ", chunk_pos=" + new ChunkPos(chunkX, chunkZ); reason + ", world=" + WorldUtil.getWorldName(world) + ", chunk_pos=" + new ChunkPos(chunkX, chunkZ);
LOGGER.error(ex, new Throwable()); LOGGER.error(ex, new Throwable());
throw new IllegalStateException(ex); throw new IllegalStateException(ex);
} }
@@ -68,8 +64,8 @@ public class TickThread extends Thread {
public static void ensureTickThread(final Entity entity, final String reason) { public static void ensureTickThread(final Entity entity, final String reason) {
if (!isTickThreadFor(entity)) { if (!isTickThreadFor(entity)) {
final String ex = "Thread failed main thread check: " + final String ex = "Thread " + Thread.currentThread().getName() + " failed main thread check: " +
reason + ", context=" + getThreadContext() + ", entity=" + EntityUtil.dumpEntity(entity); reason + ", entity=" + entity;
LOGGER.error(ex, new Throwable()); LOGGER.error(ex, new Throwable());
throw new IllegalStateException(ex); throw new IllegalStateException(ex);
} }
@@ -77,8 +73,8 @@ public class TickThread extends Thread {
public static void ensureTickThread(final Level world, final AABB aabb, final String reason) { public static void ensureTickThread(final Level world, final AABB aabb, final String reason) {
if (!isTickThreadFor(world, aabb)) { if (!isTickThreadFor(world, aabb)) {
final String ex = "Thread failed main thread check: " + final String ex = "Thread " + Thread.currentThread().getName() + " failed main thread check: " +
reason + ", context=" + getThreadContext() + ", world=" + WorldUtil.getWorldName(world) + ", aabb=" + aabb; reason + ", world=" + WorldUtil.getWorldName(world) + ", aabb=" + aabb;
LOGGER.error(ex, new Throwable()); LOGGER.error(ex, new Throwable());
throw new IllegalStateException(ex); throw new IllegalStateException(ex);
} }
@@ -86,8 +82,8 @@ public class TickThread extends Thread {
public static void ensureTickThread(final Level world, final double blockX, final double blockZ, final String reason) { public static void ensureTickThread(final Level world, final double blockX, final double blockZ, final String reason) {
if (!isTickThreadFor(world, blockX, blockZ)) { if (!isTickThreadFor(world, blockX, blockZ)) {
final String ex = "Thread failed main thread check: " + final String ex = "Thread " + Thread.currentThread().getName() + " failed main thread check: " +
reason + ", context=" + getThreadContext() + ", world=" + WorldUtil.getWorldName(world) + ", block_pos=" + new Vec3(blockX, 0.0, blockZ); reason + ", world=" + WorldUtil.getWorldName(world) + ", block_pos=" + new Vec3(blockX, 0.0, blockZ);
LOGGER.error(ex, new Throwable()); LOGGER.error(ex, new Throwable());
throw new IllegalStateException(ex); throw new IllegalStateException(ex);
} }

View File

@@ -87,7 +87,7 @@ abstract class LevelMixin implements LevelAccessor, AutoCloseable {
if (doTick && this.shouldTickBlocksAt(tileEntity.getPos())) { if (doTick && this.shouldTickBlocksAt(tileEntity.getPos())) {
tileEntity.tick(); tileEntity.tick();
// call mid-tick tasks for chunk system // call mid tick tasks for chunk system
if ((++tickedEntities & 7) == 0) { if ((++tickedEntities & 7) == 0) {
((ChunkSystemLevel)(Level)(Object)this).moonrise$midTickTasks(); ((ChunkSystemLevel)(Level)(Object)this).moonrise$midTickTasks();
} }

View File

@@ -125,7 +125,7 @@ abstract class StateHolderMixin<O, S> implements PropertyAccessStateHolder {
* @author Spottedleaf * @author Spottedleaf
*/ */
@Overwrite @Overwrite
public <T extends Comparable<T>> T getNullableValue(final Property<T> property) { public <T extends Comparable<T>> T getNullableValue(Property<T> property) {
return property == null ? null : this.optimisedTable.get(this.tableIndex, property); return property == null ? null : this.optimisedTable.get(this.tableIndex, property);
} }
@@ -166,7 +166,7 @@ abstract class StateHolderMixin<O, S> implements PropertyAccessStateHolder {
*/ */
@Overwrite @Overwrite
public Map<Property<?>, Comparable<?>> getValues() { public Map<Property<?>, Comparable<?>> getValues() {
final ZeroCollidingReferenceStateTable<O, S> table = this.optimisedTable; ZeroCollidingReferenceStateTable<O, S> table = this.optimisedTable;
// We have to use this.values until the table is loaded // We have to use this.values until the table is loaded
return table.isLoaded() ? table.getMapView(this.tableIndex) : this.values; return table.isLoaded() ? table.getMapView(this.tableIndex) : this.values;
} }

View File

@@ -366,7 +366,7 @@ abstract class ChunkHolderMixin extends GenerationChunkHolder implements ChunkSy
/** /**
* @reason Use ticket system to control ticket levels * @reason Use ticket system to control ticket levels
* @author Spottedleaf * @author Spottedleaf
* @see net.minecraft.server.level.ServerChunkCache#addTicketWithRadius(TicketType, ChunkPos, int) * @see net.minecraft.server.level.ServerChunkCache#addRegionTicket(TicketType, ChunkPos, int, Object)
*/ */
@Overwrite @Overwrite
public void setTicketLevel(int i) { public void setTicketLevel(int i) {
@@ -397,14 +397,8 @@ abstract class ChunkHolderMixin extends GenerationChunkHolder implements ChunkSy
* @reason Chunk system hooks for ticket level updating now in {@link NewChunkHolder#processTicketLevelUpdate(List, List)} * @reason Chunk system hooks for ticket level updating now in {@link NewChunkHolder#processTicketLevelUpdate(List, List)}
* @author Spottedleaf * @author Spottedleaf
*/ */
// inject to avoid conflicting with fabric API's mixin here, we call their event in FabricHooks @Overwrite
@Inject( public void updateFutures(final ChunkMap chunkMap, final Executor executor) {
method = "updateFutures",
at = @At(
value = "HEAD"
)
)
public void clobberUpdateFutures(final ChunkMap chunkMap, final Executor executor, final CallbackInfo ci) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }

View File

@@ -2,7 +2,6 @@ package ca.spottedleaf.moonrise.mixin.chunk_system;
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkSystemDistanceManager; import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkSystemDistanceManager;
import net.minecraft.server.level.ChunkMap; import net.minecraft.server.level.ChunkMap;
import net.minecraft.world.level.TicketStorage;
import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Overwrite;
@@ -16,8 +15,8 @@ abstract class ChunkMap$DistanceManagerMixin extends net.minecraft.server.level.
@Final @Final
ChunkMap field_17443; ChunkMap field_17443;
protected ChunkMap$DistanceManagerMixin(final TicketStorage p_394060_, final Executor p_140774_, final Executor p_140775_) { protected ChunkMap$DistanceManagerMixin(Executor executor, Executor executor2) {
super(p_394060_, p_140774_, p_140775_); super(executor, executor2);
} }
/** /**

View File

@@ -32,7 +32,6 @@ import net.minecraft.util.Mth;
import net.minecraft.util.StaticCache2D; import net.minecraft.util.StaticCache2D;
import net.minecraft.util.thread.BlockableEventLoop; import net.minecraft.util.thread.BlockableEventLoop;
import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.TicketStorage;
import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkGenerator; import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.chunk.LevelChunk;
@@ -44,6 +43,7 @@ import net.minecraft.world.level.chunk.storage.IOWorker;
import net.minecraft.world.level.chunk.storage.RegionStorageInfo; import net.minecraft.world.level.chunk.storage.RegionStorageInfo;
import net.minecraft.world.level.entity.ChunkStatusUpdateListener; import net.minecraft.world.level.entity.ChunkStatusUpdateListener;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager; import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager;
import net.minecraft.world.level.storage.DimensionDataStorage;
import net.minecraft.world.level.storage.LevelStorageSource; import net.minecraft.world.level.storage.LevelStorageSource;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Final;
@@ -124,11 +124,11 @@ abstract class ChunkMapMixin extends ChunkStorage implements ChunkSystemChunkMap
) )
) )
private void constructor( private void constructor(
ServerLevel p_214836_, LevelStorageSource.LevelStorageAccess p_214837_, DataFixer p_214838_, ServerLevel arg, LevelStorageSource.LevelStorageAccess arg2, DataFixer dataFixer,
StructureTemplateManager p_214839_, Executor p_214840_, BlockableEventLoop p_214841_, StructureTemplateManager arg3, Executor executor, BlockableEventLoop<Runnable> arg4,
LightChunkGetter p_214842_, ChunkGenerator p_214843_, ChunkProgressListener p_214844_, LightChunkGetter arg5, ChunkGenerator arg6, ChunkProgressListener arg7,
ChunkStatusUpdateListener p_214845_, Supplier p_214846_, TicketStorage p_394462_, int p_214847_, ChunkStatusUpdateListener arg8, Supplier<DimensionDataStorage> supplier, int j, boolean bl,
boolean p_214848_, CallbackInfo ci) { final CallbackInfo ci) {
// intentionally destroy old chunk system hooks // intentionally destroy old chunk system hooks
this.updatingChunkMap = null; this.updatingChunkMap = null;
this.visibleChunkMap = null; this.visibleChunkMap = null;
@@ -143,8 +143,7 @@ abstract class ChunkMapMixin extends ChunkStorage implements ChunkSystemChunkMap
// Dummy impl for mods that try to loadAsync directly // Dummy impl for mods that try to loadAsync directly
this.worker = new IOWorker( this.worker = new IOWorker(
// copied from super call // copied from super call
new RegionStorageInfo(p_214837_.getLevelId(), p_214836_.dimension(), "chunk"), new RegionStorageInfo(arg2.getLevelId(), arg.dimension(), "chunk"), arg2.getDimensionPath(arg.dimension()).resolve("region"), bl
p_214837_.getDimensionPath(p_214836_.dimension()).resolve("region"), p_214848_
) { ) {
@Override @Override
public boolean isOldChunkAround(final ChunkPos chunkPos, final int i) { public boolean isOldChunkAround(final ChunkPos chunkPos, final int i) {
@@ -544,31 +543,13 @@ abstract class ChunkMapMixin extends ChunkStorage implements ChunkSystemChunkMap
* @author Spottedleaf * @author Spottedleaf
*/ */
@Redirect( @Redirect(
method = "collectSpawningChunks", method = "forEachSpawnCandidateChunk",
at = @At( at = @At(
value = "INVOKE", value = "INVOKE",
target = "Lit/unimi/dsi/fastutil/longs/Long2ObjectLinkedOpenHashMap;get(J)Ljava/lang/Object;" target = "Lit/unimi/dsi/fastutil/longs/Long2ObjectLinkedOpenHashMap;get(J)Ljava/lang/Object;"
) )
) )
private <V> V redirectChunkHolderGetForSpawning(final Long2ObjectLinkedOpenHashMap<V> instance, final long key) { private <V> V redirectChunkHolderGet(final Long2ObjectLinkedOpenHashMap<V> instance, final long key) {
return (V)this.getVisibleChunkIfPresent(key);
}
/**
* @reason Route to new chunk system
* @author Spottedleaf
*/
@Redirect(
method = {
"method_67499",
"lambda$forEachBlockTickingChunk$36"
},
at = @At(
value = "INVOKE",
target = "Lit/unimi/dsi/fastutil/longs/Long2ObjectLinkedOpenHashMap;get(J)Ljava/lang/Object;"
)
)
private <V> V redirectChunkHolderGetForBlockTicking(final Long2ObjectLinkedOpenHashMap<V> instance, final long key) {
return (V)this.getVisibleChunkIfPresent(key); return (V)this.getVisibleChunkIfPresent(key);
} }

View File

@@ -1,27 +1,22 @@
package ca.spottedleaf.moonrise.mixin.chunk_system; package ca.spottedleaf.moonrise.mixin.chunk_system;
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.MoonriseConstants;
import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel; import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel;
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkSystemDistanceManager; import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkSystemDistanceManager;
import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkHolderManager; import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkHolderManager;
import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.NewChunkHolder; import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.NewChunkHolder;
import ca.spottedleaf.moonrise.patches.chunk_system.ticket.ChunkSystemTicketStorage; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.longs.LongConsumer;
import it.unimi.dsi.fastutil.longs.LongSet; import it.unimi.dsi.fastutil.longs.LongSet;
import net.minecraft.server.level.ChunkHolder; import net.minecraft.server.level.ChunkHolder;
import net.minecraft.server.level.ChunkMap; import net.minecraft.server.level.ChunkMap;
import net.minecraft.server.level.DistanceManager; import net.minecraft.server.level.DistanceManager;
import net.minecraft.server.level.LoadingChunkTracker;
import net.minecraft.server.level.SimulationChunkTracker;
import net.minecraft.server.level.ThrottlingChunkTaskDispatcher; import net.minecraft.server.level.ThrottlingChunkTaskDispatcher;
import net.minecraft.server.level.Ticket; import net.minecraft.server.level.Ticket;
import net.minecraft.server.level.TicketType;
import net.minecraft.server.level.TickingTracker;
import net.minecraft.util.Mth; import net.minecraft.util.Mth;
import net.minecraft.util.SortedArraySet;
import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.TicketStorage;
import net.minecraft.world.level.chunk.LevelChunk;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
@@ -29,7 +24,6 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
@@ -37,14 +31,13 @@ import java.util.concurrent.Executor;
abstract class DistanceManagerMixin implements ChunkSystemDistanceManager { abstract class DistanceManagerMixin implements ChunkSystemDistanceManager {
@Shadow @Shadow
public LoadingChunkTracker loadingChunkTracker; Long2ObjectOpenHashMap<SortedArraySet<Ticket<?>>> tickets;
@Shadow @Shadow
public SimulationChunkTracker simulationChunkTracker; private DistanceManager.ChunkTicketTracker ticketTracker;
@Shadow @Shadow
@Final private TickingTracker tickingTicketsTracker;
private TicketStorage ticketStorage;
@Shadow @Shadow
private DistanceManager.PlayerTicketTracker playerTicketManager; private DistanceManager.PlayerTicketTracker playerTicketManager;
@@ -71,8 +64,7 @@ abstract class DistanceManagerMixin implements ChunkSystemDistanceManager {
} }
/** /**
* @reason Destroy old chunk system state to prevent it from being used, and set the chunk map * @reason Destroy old chunk system state to prevent it from being used
* for the ticket storage
* @author Spottedleaf * @author Spottedleaf
*/ */
@Inject( @Inject(
@@ -82,16 +74,15 @@ abstract class DistanceManagerMixin implements ChunkSystemDistanceManager {
) )
) )
private void destroyFields(final CallbackInfo ci) { private void destroyFields(final CallbackInfo ci) {
this.loadingChunkTracker = null; this.tickets = null;
this.simulationChunkTracker = null; this.ticketTracker = null;
this.tickingTicketsTracker = null;
this.playerTicketManager = null; this.playerTicketManager = null;
this.chunksToUpdateFutures = null; this.chunksToUpdateFutures = null;
this.ticketDispatcher = null; this.ticketDispatcher = null;
this.ticketsToRelease = null; this.ticketsToRelease = null;
this.mainThreadExecutor = null; this.mainThreadExecutor = null;
this.simulationDistance = -1; this.simulationDistance = -1;
((ChunkSystemTicketStorage)this.ticketStorage).moonrise$setChunkMap(this.moonrise$getChunkMap());
} }
@Override @Override
@@ -99,6 +90,15 @@ abstract class DistanceManagerMixin implements ChunkSystemDistanceManager {
return ((ChunkSystemServerLevel)this.moonrise$getChunkMap().level).moonrise$getChunkTaskScheduler().chunkHolderManager; return ((ChunkSystemServerLevel)this.moonrise$getChunkMap().level).moonrise$getChunkTaskScheduler().chunkHolderManager;
} }
/**
* @reason Route to new chunk system
* @author Spottedleaf
*/
@Overwrite
public void purgeStaleTickets() {
this.moonrise$getChunkHolderManager().tick();
}
/** /**
* @reason Route to new chunk system * @reason Route to new chunk system
* @author Spottedleaf * @author Spottedleaf
@@ -108,6 +108,46 @@ abstract class DistanceManagerMixin implements ChunkSystemDistanceManager {
return this.moonrise$getChunkHolderManager().processTicketUpdates(); return this.moonrise$getChunkHolderManager().processTicketUpdates();
} }
/**
* @reason Route to new chunk system
* @author Spottedleaf
*/
@Overwrite
public void addTicket(final long pos, final Ticket<?> ticket) {
this.moonrise$getChunkHolderManager().addTicketAtLevel((TicketType)ticket.getType(), pos, ticket.getTicketLevel(), ticket.key);
}
/**
* @reason Route to new chunk system
* @author Spottedleaf
*/
@Overwrite
public void removeTicket(final long pos, final Ticket<?> ticket) {
this.moonrise$getChunkHolderManager().removeTicketAtLevel((TicketType)ticket.getType(), pos, ticket.getTicketLevel(), ticket.key);
}
/**
* @reason Remove old chunk system hooks
* @author Spottedleaf
*/
@Overwrite
public SortedArraySet<Ticket<?>> getTickets(final long pos) {
throw new UnsupportedOperationException();
}
/**
* @reason Route to new chunk system
* @author Spottedleaf
*/
@Overwrite
public void updateChunkForced(final ChunkPos pos, final boolean forced) {
if (forced) {
this.moonrise$getChunkHolderManager().addTicketAtLevel(TicketType.FORCED, pos, ChunkMap.FORCED_TICKET_LEVEL, pos);
} else {
this.moonrise$getChunkHolderManager().removeTicketAtLevel(TicketType.FORCED, pos, ChunkMap.FORCED_TICKET_LEVEL, pos);
}
}
/** /**
* @reason Remove old chunk system hooks * @reason Remove old chunk system hooks
* @author Spottedleaf * @author Spottedleaf
@@ -130,10 +170,11 @@ abstract class DistanceManagerMixin implements ChunkSystemDistanceManager {
method = "addPlayer", method = "addPlayer",
at = @At( at = @At(
value = "INVOKE", value = "INVOKE",
target = "Lnet/minecraft/world/level/TicketStorage;addTicket(Lnet/minecraft/server/level/Ticket;Lnet/minecraft/world/level/ChunkPos;)V" target = "Lnet/minecraft/server/level/TickingTracker;addTicket(Lnet/minecraft/server/level/TicketType;Lnet/minecraft/world/level/ChunkPos;ILjava/lang/Object;)V"
) )
) )
private void skipTickingTicketTrackerAdd(final TicketStorage instance, final Ticket ticket, final ChunkPos pos) {} private <T> void skipTickingTicketTrackerAdd(final TickingTracker instance, final TicketType<T> ticketType,
final ChunkPos chunkPos, final int i, final T object) {}
/** /**
* @reason Remove old chunk system hooks * @reason Remove old chunk system hooks
@@ -172,10 +213,11 @@ abstract class DistanceManagerMixin implements ChunkSystemDistanceManager {
method = "removePlayer", method = "removePlayer",
at = @At( at = @At(
value = "INVOKE", value = "INVOKE",
target = "Lnet/minecraft/world/level/TicketStorage;removeTicket(Lnet/minecraft/server/level/Ticket;Lnet/minecraft/world/level/ChunkPos;)V" target = "Lnet/minecraft/server/level/TickingTracker;removeTicket(Lnet/minecraft/server/level/TicketType;Lnet/minecraft/world/level/ChunkPos;ILjava/lang/Object;)V"
) )
) )
private void skipTickingTicketTrackerRemove(final TicketStorage instance, final Ticket ticket, final ChunkPos pos) {} private <T> void skipTickingTicketTrackerRemove(final TickingTracker instance, final TicketType<T> ticketType,
final ChunkPos chunkPos, final int i, final T object) {}
/** /**
* @reason Remove old chunk system hooks * @reason Remove old chunk system hooks
@@ -226,9 +268,8 @@ abstract class DistanceManagerMixin implements ChunkSystemDistanceManager {
* @author Spottedleaf * @author Spottedleaf
*/ */
@Overwrite @Overwrite
public int getChunkLevel(final long pos, final boolean simulation) { public String getTicketDebugString(final long pos) {
final NewChunkHolder chunkHolder = this.moonrise$getChunkHolderManager().getChunkHolder(pos); return this.moonrise$getChunkHolderManager().getTicketDebugString(pos);
return chunkHolder == null ? ChunkHolderManager.MAX_TICKET_LEVEL + 1 : chunkHolder.getTicketLevel();
} }
/** /**
@@ -257,25 +298,50 @@ abstract class DistanceManagerMixin implements ChunkSystemDistanceManager {
* @author Spottedleaf * @author Spottedleaf
*/ */
@Overwrite @Overwrite
public void forEachEntityTickingChunk(final LongConsumer consumer) { public String getDebugStatus() {
final ReferenceList<LevelChunk> chunks = ((ChunkSystemServerLevel)this.moonrise$getChunkMap().level).moonrise$getEntityTickingChunks(); return "No DistanceManager stats available";
final LevelChunk[] raw = chunks.getRawDataUnchecked();
final int size = chunks.size();
Objects.checkFromToIndex(0, size, raw.length);
for (int i = 0; i < size; ++i) {
final LevelChunk chunk = raw[i];
consumer.accept(CoordinateUtils.getChunkKey(chunk.getPos()));
}
} }
/** /**
* @reason Route to new chunk system * @reason Remove old chunk system hooks
* @author Spottedleaf * @author Spottedleaf
*/ */
@Overwrite @Overwrite
public String getDebugStatus() { public void dumpTickets(final String file) {
return "N/A"; throw new UnsupportedOperationException();
}
/**
* @reason Remove old chunk system hooks
* @author Spottedleaf
*/
@Overwrite
public TickingTracker tickingTracker() {
throw new UnsupportedOperationException();
}
/**
* @reason Remove old chunk system hooks
* @author Spottedleaf
*/
@Overwrite
public LongSet getTickingChunks() {
throw new UnsupportedOperationException();
}
/**
* @reason This hack is not required anymore, see {@link MinecraftServerMixin}
* @author Spottedleaf
*/
@Overwrite
public void removeTicketsOnClosing() {}
/**
* @reason This hack is not required anymore, see {@link MinecraftServerMixin}
* @author Spottedleaf
*/
@Overwrite
public boolean hasTickets() {
throw new UnsupportedOperationException();
} }
} }

View File

@@ -1,30 +0,0 @@
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;
}
}

View File

@@ -4,7 +4,6 @@ import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkData;
import ca.spottedleaf.moonrise.patches.chunk_system.entity.ChunkSystemEntity; import ca.spottedleaf.moonrise.patches.chunk_system.entity.ChunkSystemEntity;
import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemLevel; import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemLevel;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.mojang.logging.LogUtils;
import net.minecraft.server.level.FullChunkStatus; import net.minecraft.server.level.FullChunkStatus;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
@@ -33,6 +32,10 @@ abstract class EntityMixin implements ChunkSystemEntity {
@Shadow @Shadow
protected abstract Stream<Entity> getIndirectPassengersStream(); protected abstract Stream<Entity> getIndirectPassengersStream();
@Shadow
@Final
private static Logger LOGGER;
@Shadow @Shadow
private Level level; private Level level;
@@ -40,8 +43,6 @@ abstract class EntityMixin implements ChunkSystemEntity {
@Nullable @Nullable
private Entity.RemovalReason removalReason; private Entity.RemovalReason removalReason;
@Unique
private static final Logger LOGGER = LogUtils.getLogger();
@Unique @Unique
private final boolean isHardColliding = this.moonrise$isHardCollidingUncached(); private final boolean isHardColliding = this.moonrise$isHardCollidingUncached();

View File

@@ -25,7 +25,7 @@ abstract class EntityTickListMixin {
private Int2ObjectMap<Entity> passive; private Int2ObjectMap<Entity> passive;
@Unique @Unique
private final IteratorSafeOrderedReferenceSet<Entity> entities = new IteratorSafeOrderedReferenceSet<>(Entity.class); private final IteratorSafeOrderedReferenceSet<Entity> entities = new IteratorSafeOrderedReferenceSet<>();
/** /**
* @reason Initialise new fields and destroy old state * @reason Initialise new fields and destroy old state

View File

@@ -1,7 +1,6 @@
package ca.spottedleaf.moonrise.mixin.chunk_system; package ca.spottedleaf.moonrise.mixin.chunk_system;
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkSystemLevelChunk; import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkSystemLevelChunk;
import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.NewChunkHolder;
import ca.spottedleaf.moonrise.patches.chunk_system.ticks.ChunkSystemLevelChunkTicks; import ca.spottedleaf.moonrise.patches.chunk_system.ticks.ChunkSystemLevelChunkTicks;
import net.minecraft.core.Registry; import net.minecraft.core.Registry;
import net.minecraft.server.level.ServerChunkCache; import net.minecraft.server.level.ServerChunkCache;
@@ -49,7 +48,7 @@ abstract class LevelChunkMixin extends ChunkAccess implements ChunkSystemLevelCh
private boolean postProcessingDone; private boolean postProcessingDone;
@Unique @Unique
private NewChunkHolder chunkAndHolder; private ServerChunkCache.ChunkAndHolder chunkAndHolder;
@Override @Override
public final boolean moonrise$isPostProcessingDone() { public final boolean moonrise$isPostProcessingDone() {
@@ -57,12 +56,12 @@ abstract class LevelChunkMixin extends ChunkAccess implements ChunkSystemLevelCh
} }
@Override @Override
public final NewChunkHolder moonrise$getChunkHolder() { public final ServerChunkCache.ChunkAndHolder moonrise$getChunkAndHolder() {
return this.chunkAndHolder; return this.chunkAndHolder;
} }
@Override @Override
public final void moonrise$setChunkHolder(final NewChunkHolder holder) { public final void moonrise$setChunkAndHolder(final ServerChunkCache.ChunkAndHolder holder) {
this.chunkAndHolder = holder; this.chunkAndHolder = holder;
} }

View File

@@ -105,12 +105,12 @@ abstract class LevelChunkTicksMixin<T> implements ChunkSystemLevelChunkTicks, Se
* @author Spottedleaf * @author Spottedleaf
*/ */
@Inject( @Inject(
method = "pack", method = "save(JLjava/util/function/Function;)Lnet/minecraft/nbt/ListTag;",
at = @At( at = @At(
value = "HEAD" value = "HEAD"
) )
) )
private void saveHook(final long time, final CallbackInfoReturnable<ListTag> cir) { private void saveHook(final long time, final Function<T, String> idFunction, final CallbackInfoReturnable<ListTag> cir) {
this.lastSaved = time; this.lastSaved = time;
} }

View File

@@ -190,11 +190,6 @@ abstract class MinecraftServerMixin extends ReentrantBlockableEventLoop<TickTask
) )
) )
private boolean doNotWaitChunkSystemShutdown(final Stream<ServerLevel> instance, final Predicate<? super ServerLevel> predicate) { private boolean doNotWaitChunkSystemShutdown(final Stream<ServerLevel> instance, final Predicate<? super ServerLevel> predicate) {
// note: make sure we call deactivateTicketsOnClosing
for (final ServerLevel world : this.getAllLevels()) {
world.getChunkSource().deactivateTicketsOnClosing();
}
return false; return false;
} }
@@ -243,9 +238,9 @@ abstract class MinecraftServerMixin extends ReentrantBlockableEventLoop<TickTask
) )
) )
private void closeIOThreads(final CallbackInfo ci) { private void closeIOThreads(final CallbackInfo ci) {
LOGGER.info("Waiting for all RegionFile I/O tasks to complete..."); LOGGER.info("Waiting for I/O tasks to complete...");
MoonriseRegionFileIO.flush((MinecraftServer)(Object)this); MoonriseRegionFileIO.flush((MinecraftServer)(Object)this);
LOGGER.info("All RegionFile I/O tasks to complete"); LOGGER.info("All I/O tasks to complete");
if ((Object)this instanceof DedicatedServer) { if ((Object)this instanceof DedicatedServer) {
MoonriseCommon.haltExecutors(); MoonriseCommon.haltExecutors();
} }

View File

@@ -3,17 +3,18 @@ package ca.spottedleaf.moonrise.mixin.chunk_system;
import ca.spottedleaf.concurrentutil.map.ConcurrentLong2ReferenceChainedHashTable; import ca.spottedleaf.concurrentutil.map.ConcurrentLong2ReferenceChainedHashTable;
import ca.spottedleaf.concurrentutil.util.Priority; import ca.spottedleaf.concurrentutil.util.Priority;
import ca.spottedleaf.moonrise.common.PlatformHooks; 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.CoordinateUtils;
import ca.spottedleaf.moonrise.common.util.TickThread; import ca.spottedleaf.moonrise.common.util.TickThread;
import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel; import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel;
import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkHolderManager; import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkHolderManager;
import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkTaskScheduler; import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkTaskScheduler;
import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.NewChunkHolder; import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.NewChunkHolder;
import ca.spottedleaf.moonrise.patches.chunk_system.server.ChunkSystemMinecraftServer;
import ca.spottedleaf.moonrise.patches.chunk_system.world.ChunkSystemServerChunkCache; import ca.spottedleaf.moonrise.patches.chunk_system.world.ChunkSystemServerChunkCache;
import net.minecraft.server.level.ChunkHolder; import net.minecraft.server.level.ChunkHolder;
import net.minecraft.server.level.ChunkLevel; import net.minecraft.server.level.ChunkLevel;
import net.minecraft.server.level.ChunkResult; import net.minecraft.server.level.ChunkResult;
import net.minecraft.server.level.DistanceManager;
import net.minecraft.server.level.FullChunkStatus; import net.minecraft.server.level.FullChunkStatus;
import net.minecraft.server.level.ServerChunkCache; import net.minecraft.server.level.ServerChunkCache;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
@@ -34,6 +35,8 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.io.IOException; import java.io.IOException;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer; import java.util.function.Consumer;
@@ -56,6 +59,9 @@ abstract class ServerChunkCacheMixin extends ChunkSource implements ChunkSystemS
@Unique @Unique
private final ConcurrentLong2ReferenceChainedHashTable<LevelChunk> fullChunks = new ConcurrentLong2ReferenceChainedHashTable<>(); private final ConcurrentLong2ReferenceChainedHashTable<LevelChunk> fullChunks = new ConcurrentLong2ReferenceChainedHashTable<>();
@Unique
private long chunksTicked;
@Override @Override
public final void moonrise$setFullChunk(final int chunkX, final int chunkZ, final LevelChunk chunk) { public final void moonrise$setFullChunk(final int chunkX, final int chunkZ, final LevelChunk chunk) {
final long key = CoordinateUtils.getChunkKey(chunkX, chunkZ); final long key = CoordinateUtils.getChunkKey(chunkX, chunkZ);
@@ -333,34 +339,38 @@ abstract class ServerChunkCacheMixin extends ChunkSource implements ChunkSystemS
} }
/** /**
* @reason In the chunk system, spawn chunks will return only entity ticking chunks - we can elide the * @reason Perform mid-tick chunk task processing during chunk tick
* entity ticking range check.
* @author Spottedleaf * @author Spottedleaf
*/ */
@Redirect( @Inject(
method = "tickSpawningChunk", method = "tickChunks(Lnet/minecraft/util/profiling/ProfilerFiller;JLjava/util/List;)V",
at = @At( at = @At(
value = "INVOKE", value = "INVOKE",
target = "Lnet/minecraft/server/level/DistanceManager;inEntityTickingRange(J)Z" shift = At.Shift.AFTER,
) target = "Lnet/minecraft/server/level/ServerLevel;tickChunk(Lnet/minecraft/world/level/chunk/LevelChunk;I)V"
)
) )
private boolean shortTickThunder(final DistanceManager instance, final long pos) { private void midTickChunks(final CallbackInfo ci) {
return true; if ((++this.chunksTicked & 7L) != 0L) {
return;
}
((ChunkSystemMinecraftServer)this.level.getServer()).moonrise$executeMidTickTasks();
} }
/** /**
* @reason In the chunk system, spawn chunks will return only entity ticking chunks - we can elide the * @reason In the chunk system, ticking chunks always have loaded entities. Of course, they are also always
* entity ticking check. * marked to be as ticking as well.
* @author Spottedleaf * @author Spottedleaf
*/ */
@Redirect( @Redirect(
method = "tickSpawningChunk", method = "tickChunks(Lnet/minecraft/util/profiling/ProfilerFiller;JLjava/util/List;)V",
at = @At( at = @At(
value = "INVOKE", value = "INVOKE",
target = "Lnet/minecraft/server/level/ServerLevel;canSpawnEntitiesInChunk(Lnet/minecraft/world/level/ChunkPos;)Z" target = "Lnet/minecraft/server/level/ServerLevel;shouldTickBlocksAt(J)Z"
) )
) )
private boolean onlyCheckWBForSpawning(final ServerLevel instance, final ChunkPos pos) { private boolean shortShouldTickBlocks(final ServerLevel instance, final long pos) {
return instance.getWorldBorder().isWithinBounds(pos); return true;
} }
} }

View File

@@ -10,6 +10,7 @@ import ca.spottedleaf.moonrise.patches.chunk_system.io.datacontroller.EntityData
import ca.spottedleaf.moonrise.patches.chunk_system.io.datacontroller.PoiDataController; import ca.spottedleaf.moonrise.patches.chunk_system.io.datacontroller.PoiDataController;
import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemLevelReader; import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemLevelReader;
import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel; import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel;
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkSystemChunkHolder;
import ca.spottedleaf.moonrise.patches.chunk_system.level.entity.server.ServerEntityLookup; import ca.spottedleaf.moonrise.patches.chunk_system.level.entity.server.ServerEntityLookup;
import ca.spottedleaf.moonrise.patches.chunk_system.player.RegionizedPlayerChunkLoader; import ca.spottedleaf.moonrise.patches.chunk_system.player.RegionizedPlayerChunkLoader;
import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkHolderManager; import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkHolderManager;
@@ -26,11 +27,13 @@ import net.minecraft.core.Holder;
import net.minecraft.core.RegistryAccess; import net.minecraft.core.RegistryAccess;
import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceKey;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ChunkHolder;
import net.minecraft.server.level.ChunkMap; import net.minecraft.server.level.ChunkMap;
import net.minecraft.server.level.DistanceManager; import net.minecraft.server.level.DistanceManager;
import net.minecraft.server.level.ServerChunkCache; import net.minecraft.server.level.ServerChunkCache;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.progress.ChunkProgressListener; import net.minecraft.server.level.progress.ChunkProgressListener;
import net.minecraft.util.profiling.ProfilerFiller;
import net.minecraft.world.RandomSequences; import net.minecraft.world.RandomSequences;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.ChunkPos;
@@ -61,10 +64,12 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.io.Writer; import java.io.Writer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.stream.Stream; import java.util.stream.Stream;
@Mixin(ServerLevel.class) @Mixin(ServerLevel.class)
@@ -116,16 +121,16 @@ abstract class ServerLevelMixin extends Level implements ChunkSystemServerLevel,
private final NearbyPlayers nearbyPlayers = new NearbyPlayers((ServerLevel)(Object)this); private final NearbyPlayers nearbyPlayers = new NearbyPlayers((ServerLevel)(Object)this);
@Unique @Unique
private static final LevelChunk[] EMPTY_LEVEL_CHUNKS = new LevelChunk[0]; private static final ServerChunkCache.ChunkAndHolder[] EMPTY_CHUNK_AND_HOLDERS = new ServerChunkCache.ChunkAndHolder[0];
@Unique @Unique
private final ReferenceList<LevelChunk> loadedChunks = new ReferenceList<>(EMPTY_LEVEL_CHUNKS); private final ReferenceList<ServerChunkCache.ChunkAndHolder> loadedChunks = new ReferenceList<>(EMPTY_CHUNK_AND_HOLDERS);
@Unique @Unique
private final ReferenceList<LevelChunk> tickingChunks = new ReferenceList<>(EMPTY_LEVEL_CHUNKS); private final ReferenceList<ServerChunkCache.ChunkAndHolder> tickingChunks = new ReferenceList<>(EMPTY_CHUNK_AND_HOLDERS);
@Unique @Unique
private final ReferenceList<LevelChunk> entityTickingChunks = new ReferenceList<>(EMPTY_LEVEL_CHUNKS); private final ReferenceList<ServerChunkCache.ChunkAndHolder> entityTickingChunks = new ReferenceList<>(EMPTY_CHUNK_AND_HOLDERS);
/** /**
* @reason Initialise fields / destroy entity manager state * @reason Initialise fields / destroy entity manager state
@@ -329,17 +334,17 @@ abstract class ServerLevelMixin extends Level implements ChunkSystemServerLevel,
} }
@Override @Override
public final ReferenceList<LevelChunk> moonrise$getLoadedChunks() { public final ReferenceList<ServerChunkCache.ChunkAndHolder> moonrise$getLoadedChunks() {
return this.loadedChunks; return this.loadedChunks;
} }
@Override @Override
public final ReferenceList<LevelChunk> moonrise$getTickingChunks() { public final ReferenceList<ServerChunkCache.ChunkAndHolder> moonrise$getTickingChunks() {
return this.tickingChunks; return this.tickingChunks;
} }
@Override @Override
public final ReferenceList<LevelChunk> moonrise$getEntityTickingChunks() { public final ReferenceList<ServerChunkCache.ChunkAndHolder> moonrise$getEntityTickingChunks() {
return this.entityTickingChunks; return this.entityTickingChunks;
} }
@@ -607,22 +612,6 @@ abstract class ServerLevelMixin extends Level implements ChunkSystemServerLevel,
this.moonrise$getEntityLookup().addWorldGenChunkEntities(stream.toList(), null); // TODO this.moonrise$getEntityLookup().addWorldGenChunkEntities(stream.toList(), null); // TODO
} }
/**
* @reason Not needed in new chunk system, also avoid accessing old entity manager
* @author Spottedleaf
*/
@Redirect(
method = {
"method_72080",
"lambda$waitForChunkAndEntities$21"
},
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/level/entity/PersistentEntitySectionManager;processPendingLoads()V"
)
)
private void redirectWaitForChunks(final PersistentEntitySectionManager<Entity> instance) {}
/** /**
* @reason Level close now handles this * @reason Level close now handles this
* @author Spottedleaf * @author Spottedleaf
@@ -677,7 +666,7 @@ abstract class ServerLevelMixin extends Level implements ChunkSystemServerLevel,
* @author Spottedleaf * @author Spottedleaf
*/ */
@Overwrite @Overwrite
public boolean isPositionEntityTicking(final BlockPos pos) { public boolean isPositionEntityTicking(BlockPos pos) {
final NewChunkHolder chunkHolder = this.moonrise$getChunkTaskScheduler().chunkHolderManager.getChunkHolder(CoordinateUtils.getChunkKey(pos)); final NewChunkHolder chunkHolder = this.moonrise$getChunkTaskScheduler().chunkHolderManager.getChunkHolder(CoordinateUtils.getChunkKey(pos));
return chunkHolder != null && chunkHolder.isEntityTickingReady(); return chunkHolder != null && chunkHolder.isEntityTickingReady();
} }
@@ -687,7 +676,7 @@ abstract class ServerLevelMixin extends Level implements ChunkSystemServerLevel,
* @author Spottedleaf * @author Spottedleaf
*/ */
@Overwrite @Overwrite
public boolean areEntitiesActuallyLoadedAndTicking(final ChunkPos pos) { public boolean isNaturalSpawningAllowed(final BlockPos pos) {
final NewChunkHolder chunkHolder = this.moonrise$getChunkTaskScheduler().chunkHolderManager.getChunkHolder(CoordinateUtils.getChunkKey(pos)); final NewChunkHolder chunkHolder = this.moonrise$getChunkTaskScheduler().chunkHolderManager.getChunkHolder(CoordinateUtils.getChunkKey(pos));
return chunkHolder != null && chunkHolder.isEntityTickingReady(); return chunkHolder != null && chunkHolder.isEntityTickingReady();
} }
@@ -696,14 +685,8 @@ abstract class ServerLevelMixin extends Level implements ChunkSystemServerLevel,
* @reason Redirect to chunk system * @reason Redirect to chunk system
* @author Spottedleaf * @author Spottedleaf
*/ */
@Redirect( @Overwrite
method = "canSpawnEntitiesInChunk", public boolean isNaturalSpawningAllowed(final ChunkPos pos) {
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/level/entity/PersistentEntitySectionManager;canPositionTick(Lnet/minecraft/world/level/ChunkPos;)Z"
)
)
private <T extends EntityAccess> boolean redirectCanEntitiesSpawnTickCheck(final PersistentEntitySectionManager<T> instance, final ChunkPos pos) {
final NewChunkHolder chunkHolder = this.moonrise$getChunkTaskScheduler().chunkHolderManager.getChunkHolder(CoordinateUtils.getChunkKey(pos)); final NewChunkHolder chunkHolder = this.moonrise$getChunkTaskScheduler().chunkHolderManager.getChunkHolder(CoordinateUtils.getChunkKey(pos));
return chunkHolder != null && chunkHolder.isEntityTickingReady(); return chunkHolder != null && chunkHolder.isEntityTickingReady();
} }

View File

@@ -15,8 +15,8 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(ServerPlayer.class) @Mixin(ServerPlayer.class)
abstract class ServerPlayerMixin extends Player implements ChunkSystemServerPlayer { abstract class ServerPlayerMixin extends Player implements ChunkSystemServerPlayer {
public ServerPlayerMixin(final Level p_250508_, final GameProfile p_252153_) { public ServerPlayerMixin(Level level, BlockPos blockPos, float f, GameProfile gameProfile) {
super(p_250508_, p_252153_); super(level, blockPos, f, gameProfile);
} }
@Unique @Unique

View File

@@ -49,7 +49,8 @@ abstract class SortedArraySetMixin<T> extends AbstractSet<T> implements ChunkSys
if (i >= len) { if (i >= len) {
return false; return false;
} }
if (!filter.test(backingArray[i++])) { if (!filter.test(backingArray[i])) {
++i;
continue; continue;
} }
break; break;
@@ -57,7 +58,7 @@ abstract class SortedArraySetMixin<T> extends AbstractSet<T> implements ChunkSys
// we only want to write back to backingArray if we really need to // we only want to write back to backingArray if we really need to
int lastIndex = i - 1; // this is where new elements are shifted to int lastIndex = i; // this is where new elements are shifted to
for (; i < len; ++i) { for (; i < len; ++i) {
final T curr = backingArray[i]; final T curr = backingArray[i];

View File

@@ -1,7 +1,6 @@
package ca.spottedleaf.moonrise.mixin.chunk_system; package ca.spottedleaf.moonrise.mixin.chunk_system;
import ca.spottedleaf.moonrise.patches.chunk_system.ticket.ChunkSystemTicket; import ca.spottedleaf.moonrise.patches.chunk_system.ticket.ChunkSystemTicket;
import ca.spottedleaf.moonrise.patches.chunk_system.ticket.ChunkSystemTicketType;
import net.minecraft.server.level.Ticket; import net.minecraft.server.level.Ticket;
import net.minecraft.server.level.TicketType; import net.minecraft.server.level.TicketType;
import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Final;
@@ -9,75 +8,61 @@ import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.Unique;
import java.util.Comparator;
@Mixin(Ticket.class) @Mixin(Ticket.class)
abstract class TicketMixin<T> implements ChunkSystemTicket<T>, Comparable<Ticket> { abstract class TicketMixin<T> implements ChunkSystemTicket<T>, Comparable<Ticket<?>> {
@Shadow @Shadow
@Final @Final
private TicketType type; private TicketType<T> type;
@Shadow @Shadow
@Final @Final
private int ticketLevel; private int ticketLevel;
@Shadow @Shadow
private long ticksLeft; @Final
public T key;
@Unique @Unique
private T identifier; private long removeDelay;
@Override @Override
public final long moonrise$getRemoveDelay() { public final long moonrise$getRemoveDelay() {
return this.ticksLeft; return this.removeDelay;
} }
@Override @Override
public final void moonrise$setRemoveDelay(final long removeDelay) { public final void moonrise$setRemoveDelay(final long removeDelay) {
this.ticksLeft = removeDelay; this.removeDelay = removeDelay;
}
@Override
public final T moonrise$getIdentifier() {
return this.identifier;
}
@Override
public final void moonrise$setIdentifier(final T identifier) {
if ((identifier == null) != (((ChunkSystemTicketType<T>)(Object)this.type).moonrise$getIdentifierComparator() == null)) {
throw new IllegalStateException("Nullability of identifier should match nullability of comparator");
}
this.identifier = identifier;
} }
/** /**
* @reason Change debug to include remove identifier * @reason Change debug to include remove delay
* @author Spottedleaf * @author Spottedleaf
*/ */
@Overwrite @Overwrite
@Override @Override
public String toString() { public String toString() {
return "Ticket[" + this.type + " " + this.ticketLevel + " (" + this.identifier + ")] to die in " + this.ticksLeft; return "Ticket[" + this.type + " " + this.ticketLevel + " (" + this.key + ")] to die in " + this.removeDelay;
} }
@Override /**
public final int compareTo(final Ticket ticket) { * @reason Remove old chunk system hook
final int levelCompare = Integer.compare(this.ticketLevel, ((TicketMixin<?>)(Object)ticket).ticketLevel); * @author Spottedleaf
if (levelCompare != 0) { */
return levelCompare; @Overwrite
} public void setCreatedTick(final long tickCreated) {
throw new UnsupportedOperationException();
}
final int typeCompare = Long.compare( /**
((ChunkSystemTicketType<T>)(Object)this.type).moonrise$getId(), * @reason Remove old chunk system hook
((ChunkSystemTicketType<?>)(Object)((TicketMixin<?>)(Object)ticket).type).moonrise$getId() * @author Spottedleaf
); */
if (typeCompare != 0) { @Overwrite
return typeCompare; public boolean timedOut(final long currentTick) {
} throw new UnsupportedOperationException();
final Comparator<T> comparator = ((ChunkSystemTicketType<T>)(Object)this.type).moonrise$getIdentifierComparator();
return comparator == null ? 0 : comparator.compare(this.identifier, ((TicketMixin<T>)(Object)ticket).identifier);
} }
} }

View File

@@ -1,261 +0,0 @@
package ca.spottedleaf.moonrise.mixin.chunk_system;
import ca.spottedleaf.moonrise.common.util.CoordinateUtils;
import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel;
import ca.spottedleaf.moonrise.patches.chunk_system.ticket.ChunkSystemTicket;
import ca.spottedleaf.moonrise.patches.chunk_system.ticket.ChunkSystemTicketStorage;
import ca.spottedleaf.moonrise.patches.chunk_system.ticket.ChunkSystemTicketType;
import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
import it.unimi.dsi.fastutil.longs.LongSet;
import net.minecraft.server.level.ChunkMap;
import net.minecraft.server.level.Ticket;
import net.minecraft.server.level.TicketType;
import net.minecraft.util.SortedArraySet;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.TicketStorage;
import net.minecraft.world.level.saveddata.SavedData;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.Iterator;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.BiPredicate;
import java.util.function.Predicate;
@Mixin(TicketStorage.class)
abstract class TicketStorageMixin extends SavedData implements ChunkSystemTicketStorage {
@Shadow
@Final
private Long2ObjectOpenHashMap<List<Ticket>> deactivatedTickets;
@Shadow
private Long2ObjectOpenHashMap<List<Ticket>> tickets;
@Shadow
private LongSet chunksWithForcedTickets;
@Unique
private ChunkMap chunkMap;
@Override
public final ChunkMap moonrise$getChunkMap() {
return this.chunkMap;
}
@Override
public final void moonrise$setChunkMap(final ChunkMap chunkMap) {
this.chunkMap = chunkMap;
}
/**
* @reason Destroy old chunk system state
* @author Spottedleaf
*/
@Inject(
method = "<init>(Lit/unimi/dsi/fastutil/longs/Long2ObjectOpenHashMap;Lit/unimi/dsi/fastutil/longs/Long2ObjectOpenHashMap;)V",
at = @At(
value = "RETURN"
)
)
private void destroyFields(Long2ObjectOpenHashMap p_393873_, Long2ObjectOpenHashMap p_394615_, CallbackInfo ci) {
if (!this.tickets.isEmpty()) {
throw new IllegalStateException("Expect tickets to be empty here!");
}
this.tickets = null;
this.chunksWithForcedTickets = null;
}
/**
* @reason The forced chunks would be empty, as tickets should always be empty.
* We need to do this to avoid throwing immediately.
* @author Spottedleaf
*/
@Redirect(
method = "<init>(Lit/unimi/dsi/fastutil/longs/Long2ObjectOpenHashMap;Lit/unimi/dsi/fastutil/longs/Long2ObjectOpenHashMap;)V",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/level/TicketStorage;updateForcedChunks()V"
)
)
private void avoidUpdatingForcedChunks(final TicketStorage instance) {}
/**
* @reason Redirect regular ticket retrieval to new chunk system
* @author Spottedleaf
*/
@Redirect(
method = "forEachTicket(Ljava/util/function/BiConsumer;)V",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/level/TicketStorage;forEachTicket(Ljava/util/function/BiConsumer;Lit/unimi/dsi/fastutil/longs/Long2ObjectOpenHashMap;)V",
ordinal = 0
)
)
private void redirectRegularTickets(final BiConsumer<ChunkPos, Ticket> consumer, final Long2ObjectOpenHashMap<List<Ticket>> ticketsParam) {
if (ticketsParam != null) {
throw new IllegalStateException("Bad injection point");
}
final Long2ObjectOpenHashMap<SortedArraySet<Ticket>> tickets = ((ChunkSystemServerLevel)this.chunkMap.level)
.moonrise$getChunkTaskScheduler().chunkHolderManager.getTicketsCopy();
for (final Iterator<Long2ObjectMap.Entry<SortedArraySet<Ticket>>> iterator = tickets.long2ObjectEntrySet().fastIterator(); iterator.hasNext();) {
final Long2ObjectMap.Entry<SortedArraySet<Ticket>> entry = iterator.next();
final long pos = entry.getLongKey();
final SortedArraySet<Ticket> chunkTickets = entry.getValue();
final ChunkPos chunkPos = new ChunkPos(pos);
for (final Ticket ticket : chunkTickets) {
consumer.accept(chunkPos, ticket);
}
}
}
/**
* @reason Avoid setting old chunk system state
* @author Spottedleaf
*/
@Overwrite
public void setLoadingChunkUpdatedListener(final TicketStorage.ChunkUpdated callback) {}
/**
* @reason Avoid setting old chunk system state
* @author Spottedleaf
*/
@Overwrite
public void setSimulationChunkUpdatedListener(final TicketStorage.ChunkUpdated callback) {}
/**
* @reason Redirect to new chunk system
* @author Spottedleaf
*/
@Overwrite
public boolean hasTickets() {
return ((ChunkSystemServerLevel)this.chunkMap.level).moonrise$getChunkTaskScheduler().chunkHolderManager.hasTickets();
}
/**
* @reason Redirect to new chunk system
* @author Spottedleaf
*/
@Overwrite
public List<Ticket> getTickets(final long pos) {
return ((ChunkSystemServerLevel)this.chunkMap.level).moonrise$getChunkTaskScheduler().chunkHolderManager
.getTicketsAt(CoordinateUtils.getChunkX(pos), CoordinateUtils.getChunkZ(pos));
}
/**
* @reason Redirect to new chunk system
* @author Spottedleaf
*/
@Overwrite
public boolean addTicket(final long pos, final Ticket ticket) {
final boolean ret = ((ChunkSystemServerLevel)this.chunkMap.level).moonrise$getChunkTaskScheduler().chunkHolderManager
.addTicketAtLevel(ticket.getType(), pos, ticket.getTicketLevel(), ((ChunkSystemTicket<?>)ticket).moonrise$getIdentifier());
this.setDirty();
return ret;
}
/**
* @reason Redirect to new chunk system
* @author Spottedleaf
*/
@Overwrite
public boolean removeTicket(final long pos, final Ticket ticket) {
final boolean ret = ((ChunkSystemServerLevel)this.chunkMap.level).moonrise$getChunkTaskScheduler().chunkHolderManager
.removeTicketAtLevel(ticket.getType(), pos, ticket.getTicketLevel(), ((ChunkSystemTicket<?>)ticket).moonrise$getIdentifier());
if (ret) {
this.setDirty();
}
return ret;
}
/**
* @reason Redirect to new chunk system
* @author Spottedleaf
*/
@Overwrite
public void purgeStaleTickets(final ChunkMap chunkMap) {
((ChunkSystemServerLevel)chunkMap.level).moonrise$getChunkTaskScheduler().chunkHolderManager.tick();
this.setDirty();
}
/**
* @reason All tickets (inactive or not) are packed and saved, so there's no real reason we need to remove them.
* Vanilla removes them as it requires every chunk to go through the unload logic; however we already manually
* do this on shutdown.
* @author Spottedleaf
*/
@Redirect(
method = "deactivateTicketsOnClosing",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/level/TicketStorage;removeTicketIf(Ljava/util/function/BiPredicate;Lit/unimi/dsi/fastutil/longs/Long2ObjectOpenHashMap;)V"
)
)
private void avoidRemovingTicketsOnShutdown(final TicketStorage instance,
final BiPredicate<Long, Ticket> predicate,
final Long2ObjectOpenHashMap<List<Ticket>> tickets) {}
/**
* @reason Destroy old chunk system hooks
* @author Spottedleaf
*/
@Overwrite
public void removeTicketIf(final BiPredicate<Long, Ticket> predicate, final Long2ObjectOpenHashMap<List<Ticket>> into) {
throw new UnsupportedOperationException();
}
/**
* @reason Destroy old chunk system hooks
* @author Spottedleaf
*/
@Overwrite
public void replaceTicketLevelOfType(final int newLevel, final TicketType forType) {
throw new UnsupportedOperationException();
}
/**
* @reason Route to new chunk system
* @author Spottedleaf
*/
@Overwrite
public LongSet getForceLoadedChunks() {
final Long2IntOpenHashMap forced = ((ChunkSystemServerLevel)this.chunkMap.level).moonrise$getChunkTaskScheduler()
.chunkHolderManager.getTicketCounters(ChunkSystemTicketType.COUNTER_TYPE_FORCED);
if (forced == null) {
return LongSet.of();
}
return forced.keySet();
}
/**
* @reason Destroy old chunk system hooks
* @author Spottedleaf
*/
@Overwrite
public LongSet getAllChunksWithTicketThat(final Predicate<Ticket> predicate) {
throw new UnsupportedOperationException();
}
}

View File

@@ -1,69 +0,0 @@
package ca.spottedleaf.moonrise.mixin.chunk_system;
import ca.spottedleaf.moonrise.common.PlatformHooks;
import ca.spottedleaf.moonrise.patches.chunk_system.ticket.ChunkSystemTicketType;
import net.minecraft.server.level.TicketType;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.Comparator;
import java.util.concurrent.atomic.AtomicLong;
@Mixin(TicketType.class)
abstract class TicketTypeMixin<T> implements ChunkSystemTicketType<T> {
@Unique
private static AtomicLong ID_GENERATOR;
/**
* @reason Need to initialise at the start of clinit, as ticket types are constructed after.
* Using just the field initialiser would append the static initialiser.
* @author Spottedleaf
*/
@Inject(
method = "<clinit>",
at = @At(
value = "HEAD"
)
)
private static void initIdGenerator(final CallbackInfo ci) {
ID_GENERATOR = new AtomicLong();
}
@Unique
private final long id = ID_GENERATOR.getAndIncrement();
@Unique
private Comparator<T> identifierComparator;
@Unique
private volatile long[] counterTypes;
@Override
public final long moonrise$getId() {
return this.id;
}
@Override
public final Comparator<T> moonrise$getIdentifierComparator() {
return this.identifierComparator;
}
@Override
public final void moonrise$setIdentifierComparator(final Comparator<T> comparator) {
this.identifierComparator = comparator;
}
@Override
public final long[] moonrise$getCounterTypes() {
// need to lazy init this because we cannot check if we are FORCED during construction
final long[] types = this.counterTypes;
if (types != null) {
return types;
}
return this.counterTypes = PlatformHooks.get().getCounterTypesUncached((TicketType)(Object)this);
}
}

View File

@@ -1,25 +0,0 @@
package ca.spottedleaf.moonrise.mixin.chunk_system;
import ca.spottedleaf.moonrise.common.util.CoordinateUtils;
import ca.spottedleaf.moonrise.patches.chunk_system.player.ChunkSystemServerPlayer;
import ca.spottedleaf.moonrise.patches.chunk_system.player.RegionizedPlayerChunkLoader;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.waypoints.Waypoint;
import net.minecraft.world.waypoints.WaypointTransmitter;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
@Mixin(WaypointTransmitter.class)
interface WaypointTransmitterMixin extends Waypoint {
/**
* @reason Redirect to the new player chunk loader, as the Vanilla chunk tracker is set to empty on Moonrise
* @author Spottedleaf
*/
@Overwrite
public static boolean isChunkVisible(final ChunkPos pos, final ServerPlayer player) {
final RegionizedPlayerChunkLoader.PlayerChunkLoaderData playerChunkLoader = ((ChunkSystemServerPlayer)player).moonrise$getChunkLoader();
return playerChunkLoader != null && playerChunkLoader.getSentChunksRaw().contains(CoordinateUtils.getChunkKey(pos));
}
}

View File

@@ -2,27 +2,18 @@ package ca.spottedleaf.moonrise.mixin.chunk_tick_iteration;
import ca.spottedleaf.moonrise.common.list.ReferenceList; import ca.spottedleaf.moonrise.common.list.ReferenceList;
import ca.spottedleaf.moonrise.common.misc.NearbyPlayers; import ca.spottedleaf.moonrise.common.misc.NearbyPlayers;
import ca.spottedleaf.moonrise.common.util.CoordinateUtils;
import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel; import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel;
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkData;
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkSystemLevelChunk;
import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkHolderManager;
import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.NewChunkHolder;
import ca.spottedleaf.moonrise.patches.chunk_system.ticket.ChunkSystemTicketType;
import ca.spottedleaf.moonrise.patches.chunk_tick_iteration.ChunkTickDistanceManager; import ca.spottedleaf.moonrise.patches.chunk_tick_iteration.ChunkTickDistanceManager;
import ca.spottedleaf.moonrise.patches.chunk_tick_iteration.ChunkTickServerLevel;
import com.llamalad7.mixinextras.sugar.Local; import com.llamalad7.mixinextras.sugar.Local;
import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap;
import it.unimi.dsi.fastutil.longs.LongIterator;
import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
import net.minecraft.core.SectionPos; import net.minecraft.core.SectionPos;
import net.minecraft.server.level.ChunkMap; import net.minecraft.server.level.ChunkMap;
import net.minecraft.server.level.ServerChunkCache;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.chunk.LevelChunk; import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.*; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@@ -94,15 +85,11 @@ abstract class ChunkMapMixin {
} }
/** /**
* @reason Avoid checking for DEFAULT state, as we make internal perform this implicitly. * @reason Avoid checking first if there are nearby players, as we make internal perform this implicitly.
* @author Spottedleaf * @author Spottedleaf
*/ */
@Overwrite @Overwrite
public boolean anyPlayerCloseEnoughForSpawning(final ChunkPos pos) { public boolean anyPlayerCloseEnoughForSpawning(final ChunkPos pos) {
if (((ChunkTickDistanceManager)this.distanceManager).moonrise$hasAnyNearbyNarrow(pos.x, pos.z)) {
return true;
}
return this.anyPlayerCloseEnoughForSpawningInternal(pos); return this.anyPlayerCloseEnoughForSpawningInternal(pos);
} }
@@ -165,111 +152,4 @@ abstract class ChunkMapMixin {
return ret == null ? new ArrayList<>() : ret; return ret == null ? new ArrayList<>() : ret;
} }
@Unique
private boolean isChunkNearPlayer(final ChunkMap chunkMap, final ChunkPos chunkPos, final LevelChunk levelChunk) {
final ChunkData chunkData = ((ChunkSystemLevelChunk)levelChunk).moonrise$getChunkHolder().holderData;
final NearbyPlayers.TrackedChunk nearbyPlayers = chunkData.nearbyPlayers;
if (nearbyPlayers == null) {
return false;
}
if (((ChunkTickDistanceManager)this.distanceManager).moonrise$hasAnyNearbyNarrow(chunkPos.x, chunkPos.z)) {
return true;
}
final ReferenceList<ServerPlayer> players = nearbyPlayers.getPlayers(NearbyPlayers.NearbyMapType.SPAWN_RANGE);
if (players == null) {
return false;
}
final ServerPlayer[] raw = players.getRawDataUnchecked();
final int len = players.size();
Objects.checkFromIndexSize(0, len, raw.length);
for (int i = 0; i < len; ++i) {
if (chunkMap.playerIsCloseEnoughForSpawning(raw[i], chunkPos)) {
return true;
}
}
return false;
}
/**
* @reason Use the player ticking chunks list, which already contains chunks that are:
* 1. entity ticking
* 2. within spawn range (8 chunks on any axis)
* @author Spottedleaf
*/
@Inject(
method = "collectSpawningChunks",
// use cancellable inject to be compatible with the chunk system's hook here
cancellable = true,
at = @At(
value = "HEAD"
)
)
public void collectSpawningChunks(final List<LevelChunk> list, final CallbackInfo ci) {
final ReferenceList<LevelChunk> tickingChunks = ((ChunkTickServerLevel)this.level).moonrise$getPlayerTickingChunks();
final Long2IntOpenHashMap forceSpawningChunks = ((ChunkSystemServerLevel)this.level).moonrise$getChunkTaskScheduler()
.chunkHolderManager.getTicketCounters(ChunkSystemTicketType.COUNTER_TYPER_NATURAL_SPAWNING_FORCED);
final LevelChunk[] raw = tickingChunks.getRawDataUnchecked();
final int size = tickingChunks.size();
Objects.checkFromToIndex(0, size, raw.length);
if (forceSpawningChunks != null && !forceSpawningChunks.isEmpty()) {
// note: expect forceSpawningChunks.size <<< tickingChunks.size
final LongOpenHashSet seen = new LongOpenHashSet(forceSpawningChunks.size());
final ChunkHolderManager chunkHolderManager = ((ChunkSystemServerLevel)this.level).moonrise$getChunkTaskScheduler().chunkHolderManager;
// note: this fixes a bug in neoforge where these chunks don't tick away from a player...
// note: this is NOT the only problem with their implementation, either...
for (final LongIterator iterator = forceSpawningChunks.keySet().longIterator(); iterator.hasNext();) {
final long pos = iterator.nextLong();
final NewChunkHolder holder = chunkHolderManager.getChunkHolder(pos);
if (holder == null || !holder.isEntityTickingReady()) {
continue;
}
seen.add(pos);
list.add((LevelChunk)holder.getCurrentChunk());
}
for (int i = 0; i < size; ++i) {
final LevelChunk levelChunk = raw[i];
if (seen.contains(CoordinateUtils.getChunkKey(levelChunk.getPos()))) {
// do not add duplicate chunks
continue;
}
if (!this.isChunkNearPlayer((ChunkMap)(Object)this, levelChunk.getPos(), levelChunk)) {
continue;
}
list.add(levelChunk);
}
} else {
for (int i = 0; i < size; ++i) {
final LevelChunk levelChunk = raw[i];
if (!this.isChunkNearPlayer((ChunkMap)(Object)this, levelChunk.getPos(), levelChunk)) {
continue;
}
list.add(levelChunk);
}
}
ci.cancel();
}
} }

View File

@@ -8,7 +8,6 @@ import it.unimi.dsi.fastutil.longs.LongIterator;
import net.minecraft.core.SectionPos; import net.minecraft.core.SectionPos;
import net.minecraft.server.level.DistanceManager; import net.minecraft.server.level.DistanceManager;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import net.minecraft.util.TriState;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
@@ -22,24 +21,20 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
abstract class DistanceManagerMixin implements ChunkTickDistanceManager { abstract class DistanceManagerMixin implements ChunkTickDistanceManager {
@Shadow @Shadow
public DistanceManager.FixedPlayerDistanceChunkTracker naturalSpawnChunkCounter; private DistanceManager.FixedPlayerDistanceChunkTracker naturalSpawnChunkCounter;
@Unique @Unique
private final PositionCountingAreaMap<ServerPlayer> spawnChunkTracker = new PositionCountingAreaMap<>(); private final PositionCountingAreaMap<ServerPlayer> spawnChunkTracker = new PositionCountingAreaMap<>();
@Unique
private final PositionCountingAreaMap<ServerPlayer> narrowSpawnChunkTracker = new PositionCountingAreaMap<>();
@Override @Override
public final void moonrise$addPlayer(final ServerPlayer player, final SectionPos pos) { public final void moonrise$addPlayer(final ServerPlayer player, final SectionPos pos) {
this.spawnChunkTracker.add(player, pos.x(), pos.z(), ChunkTickConstants.PLAYER_SPAWN_TRACK_RANGE); this.spawnChunkTracker.add(player, pos.x(), pos.z(), ChunkTickConstants.PLAYER_SPAWN_TRACK_RANGE);
this.narrowSpawnChunkTracker.add(player, pos.x(), pos.z(), ChunkTickConstants.NARROW_SPAWN_TRACK_RANGE);
} }
@Override @Override
public final void moonrise$removePlayer(final ServerPlayer player, final SectionPos pos) { public final void moonrise$removePlayer(final ServerPlayer player, final SectionPos pos) {
this.spawnChunkTracker.remove(player); this.spawnChunkTracker.remove(player);
this.narrowSpawnChunkTracker.remove(player);
} }
@Override @Override
@@ -48,18 +43,11 @@ abstract class DistanceManagerMixin implements ChunkTickDistanceManager {
final boolean oldIgnore, final boolean newIgnore) { final boolean oldIgnore, final boolean newIgnore) {
if (newIgnore) { if (newIgnore) {
this.spawnChunkTracker.remove(player); this.spawnChunkTracker.remove(player);
this.narrowSpawnChunkTracker.remove(player);
} else { } else {
this.spawnChunkTracker.addOrUpdate(player, newPos.x(), newPos.z(), ChunkTickConstants.PLAYER_SPAWN_TRACK_RANGE); this.spawnChunkTracker.addOrUpdate(player, newPos.x(), newPos.z(), ChunkTickConstants.PLAYER_SPAWN_TRACK_RANGE);
this.narrowSpawnChunkTracker.addOrUpdate(player, newPos.x(), newPos.z(), ChunkTickConstants.NARROW_SPAWN_TRACK_RANGE);
} }
} }
@Override
public final boolean moonrise$hasAnyNearbyNarrow(final int chunkX, final int chunkZ) {
return this.narrowSpawnChunkTracker.hasObjectsNear(chunkX, chunkZ);
}
/** /**
* @reason Destroy natural spawning tracker field to prevent it from being used * @reason Destroy natural spawning tracker field to prevent it from being used
* @author Spottedleaf * @author Spottedleaf
@@ -116,11 +104,8 @@ abstract class DistanceManagerMixin implements ChunkTickDistanceManager {
* @author Spottedleaf * @author Spottedleaf
*/ */
@Overwrite @Overwrite
public TriState hasPlayersNearby(final long pos) { public boolean hasPlayersNearby(final long pos) {
if (this.narrowSpawnChunkTracker.hasObjectsNear(pos)) { return this.spawnChunkTracker.hasObjectsNear(CoordinateUtils.getChunkX(pos), CoordinateUtils.getChunkZ(pos));
return TriState.TRUE;
}
return this.spawnChunkTracker.hasObjectsNear(pos) ? TriState.DEFAULT : TriState.FALSE;
} }
/** /**

View File

@@ -1,26 +1,30 @@
package ca.spottedleaf.moonrise.mixin.chunk_tick_iteration; package ca.spottedleaf.moonrise.mixin.chunk_tick_iteration;
import ca.spottedleaf.moonrise.common.list.ReferenceList; import ca.spottedleaf.moonrise.common.list.ReferenceList;
import ca.spottedleaf.moonrise.common.misc.NearbyPlayers;
import ca.spottedleaf.moonrise.common.util.SimpleThreadUnsafeRandom; import ca.spottedleaf.moonrise.common.util.SimpleThreadUnsafeRandom;
import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel; import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkData;
import ca.spottedleaf.moonrise.patches.chunk_system.server.ChunkSystemMinecraftServer; import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkSystemChunkHolder;
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkSystemLevelChunk;
import ca.spottedleaf.moonrise.patches.chunk_tick_iteration.ChunkTickServerLevel;
import net.minecraft.Util; import net.minecraft.Util;
import net.minecraft.server.level.ChunkMap; import net.minecraft.server.level.ChunkMap;
import net.minecraft.server.level.ServerChunkCache; import net.minecraft.server.level.ServerChunkCache;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.util.RandomSource; import net.minecraft.util.RandomSource;
import net.minecraft.world.level.GameRules; import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.chunk.ChunkSource; import net.minecraft.world.level.chunk.ChunkSource;
import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.chunk.LevelChunk;
import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.Redirect;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.function.Consumer;
@Mixin(ServerChunkCache.class) @Mixin(ServerChunkCache.class)
abstract class ServerChunkCacheMixin extends ChunkSource { abstract class ServerChunkCacheMixin extends ChunkSource {
@@ -37,13 +41,69 @@ abstract class ServerChunkCacheMixin extends ChunkSource {
@Unique @Unique
private final SimpleThreadUnsafeRandom shuffleRandom = new SimpleThreadUnsafeRandom(0L); private final SimpleThreadUnsafeRandom shuffleRandom = new SimpleThreadUnsafeRandom(0L);
@Unique
private boolean isChunkNearPlayer(final ChunkMap chunkMap, final ChunkPos chunkPos, final LevelChunk levelChunk) {
final ChunkData chunkData = ((ChunkSystemChunkHolder)((ChunkSystemLevelChunk)levelChunk).moonrise$getChunkAndHolder().holder())
.moonrise$getRealChunkHolder().holderData;
final NearbyPlayers.TrackedChunk nearbyPlayers = chunkData.nearbyPlayers;
if (nearbyPlayers == null) {
return false;
}
final ReferenceList<ServerPlayer> players = nearbyPlayers.getPlayers(NearbyPlayers.NearbyMapType.SPAWN_RANGE);
if (players == null) {
return false;
}
final ServerPlayer[] raw = players.getRawDataUnchecked();
final int len = players.size();
Objects.checkFromIndexSize(0, len, raw.length);
for (int i = 0; i < len; ++i) {
if (chunkMap.playerIsCloseEnoughForSpawning(raw[i], chunkPos)) {
return true;
}
}
return false;
}
/**
* @reason Use the player ticking chunks list, which already contains chunks that are:
* 1. block ticking
* 2. within spawn range (8 chunks on any axis)
* @author Spottedleaf
*/
@Overwrite
private void collectTickingChunks(final List<LevelChunk> list) {
final ReferenceList<ServerChunkCache.ChunkAndHolder> tickingChunks =
((ChunkTickServerLevel)this.level).moonrise$getPlayerTickingChunks();
final ServerChunkCache.ChunkAndHolder[] raw = tickingChunks.getRawDataUnchecked();
final int size = tickingChunks.size();
final ChunkMap chunkMap = this.chunkMap;
for (int i = 0; i < size; ++i) {
final ServerChunkCache.ChunkAndHolder chunkAndHolder = raw[i];
final LevelChunk levelChunk = chunkAndHolder.chunk();
if (!this.isChunkNearPlayer(chunkMap, levelChunk.getPos(), levelChunk)) {
continue;
}
list.add(levelChunk);
}
}
/** /**
* @reason Use random implementation which does not use CAS and has a faster nextInt(int) * @reason Use random implementation which does not use CAS and has a faster nextInt(int)
* function * function
* @author Spottedleaf * @author Spottedleaf
*/ */
@Redirect( @Redirect(
method = "tickChunks(Lnet/minecraft/util/profiling/ProfilerFiller;J)V", method = "tickChunks()V",
at = @At( at = @At(
value = "INVOKE", value = "INVOKE",
target = "Lnet/minecraft/Util;shuffle(Ljava/util/List;Lnet/minecraft/util/RandomSource;)V" target = "Lnet/minecraft/Util;shuffle(Ljava/util/List;Lnet/minecraft/util/RandomSource;)V"
@@ -53,41 +113,4 @@ abstract class ServerChunkCacheMixin extends ChunkSource {
this.shuffleRandom.setSeed(randomSource.nextLong()); this.shuffleRandom.setSeed(randomSource.nextLong());
Util.shuffle(list, this.shuffleRandom); Util.shuffle(list, this.shuffleRandom);
} }
/**
* @reason Do not iterate over entire chunk holder map; additionally perform mid-tick chunk task execution
* @author Spottedleaf
*/
@Redirect(
method = "tickChunks(Lnet/minecraft/util/profiling/ProfilerFiller;J)V",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/server/level/ChunkMap;forEachBlockTickingChunk(Ljava/util/function/Consumer;)V"
)
)
private void iterateTickingChunksFaster(final ChunkMap instance, final Consumer<LevelChunk> consumer) {
final ServerLevel world = this.level;
final int randomTickSpeed = world.getGameRules().getInt(GameRules.RULE_RANDOMTICKING);
// TODO check on update: impl of forEachBlockTickingChunk will only iterate ENTITY ticking chunks!
// TODO check on update: consumer just runs tickChunk
final ReferenceList<LevelChunk> entityTickingChunks = ((ChunkSystemServerLevel)world).moonrise$getEntityTickingChunks();
// note: we can use the backing array here because:
// 1. we do not care about new additions
// 2. _removes_ are impossible at this stage in the tick
final LevelChunk[] raw = entityTickingChunks.getRawDataUnchecked();
final int size = entityTickingChunks.size();
Objects.checkFromToIndex(0, size, raw.length);
for (int i = 0; i < size; ++i) {
world.tickChunk(raw[i], randomTickSpeed);
// call mid-tick tasks for chunk system
if ((i & 7) == 0) {
((ChunkSystemMinecraftServer)this.level.getServer()).moonrise$executeMidTickTasks();
continue;
}
}
}
} }

View File

@@ -19,16 +19,16 @@ import org.spongepowered.asm.mixin.Unique;
abstract class ServerLevelMixin implements ChunkTickServerLevel { abstract class ServerLevelMixin implements ChunkTickServerLevel {
@Unique @Unique
private static final LevelChunk[] EMPTY_LEVEL_CHUNKS = new LevelChunk[0]; private static final ServerChunkCache.ChunkAndHolder[] EMPTY_PLAYER_CHUNK_HOLDERS = new ServerChunkCache.ChunkAndHolder[0];
@Unique @Unique
private final ReferenceList<LevelChunk> playerTickingChunks = new ReferenceList<>(EMPTY_LEVEL_CHUNKS); private final ReferenceList<ServerChunkCache.ChunkAndHolder> playerTickingChunks = new ReferenceList<>(EMPTY_PLAYER_CHUNK_HOLDERS);
@Unique @Unique
private final Long2IntOpenHashMap playerTickingRequests = new Long2IntOpenHashMap(); private final Long2IntOpenHashMap playerTickingRequests = new Long2IntOpenHashMap();
@Override @Override
public final ReferenceList<LevelChunk> moonrise$getPlayerTickingChunks() { public final ReferenceList<ServerChunkCache.ChunkAndHolder> moonrise$getPlayerTickingChunks() {
return this.playerTickingChunks; return this.playerTickingChunks;
} }
@@ -39,12 +39,12 @@ abstract class ServerLevelMixin implements ChunkTickServerLevel {
return; return;
} }
this.playerTickingChunks.add(chunk); this.playerTickingChunks.add(((ChunkSystemLevelChunk)chunk).moonrise$getChunkAndHolder());
} }
@Override @Override
public final void moonrise$removeChunkForPlayerTicking(final LevelChunk chunk) { public final void moonrise$removeChunkForPlayerTicking(final LevelChunk chunk) {
this.playerTickingChunks.remove(chunk); this.playerTickingChunks.remove(((ChunkSystemLevelChunk)chunk).moonrise$getChunkAndHolder());
} }
@Override @Override
@@ -65,7 +65,9 @@ abstract class ServerLevelMixin implements ChunkTickServerLevel {
return; return;
} }
this.playerTickingChunks.add((LevelChunk)chunkHolder.getCurrentChunk()); this.playerTickingChunks.add(
((ChunkSystemLevelChunk)(LevelChunk)chunkHolder.getCurrentChunk()).moonrise$getChunkAndHolder()
);
} }
@Override @Override
@@ -91,6 +93,8 @@ abstract class ServerLevelMixin implements ChunkTickServerLevel {
return; return;
} }
this.playerTickingChunks.remove((LevelChunk)chunkHolder.getCurrentChunk()); this.playerTickingChunks.remove(
((ChunkSystemLevelChunk)(LevelChunk)chunkHolder.getCurrentChunk()).moonrise$getChunkAndHolder()
);
} }
} }

View File

@@ -59,7 +59,7 @@ interface EntityGetterMixin {
continue; continue;
} }
if ((entity == null && otherEntity.canBeCollidedWith(entity)) || (entity != null && entity.canCollideWith(otherEntity))) { if ((entity == null && otherEntity.canBeCollidedWith()) || (entity != null && entity.canCollideWith(otherEntity))) {
ret.add(Shapes.create(otherEntity.getBoundingBox())); ret.add(Shapes.create(otherEntity.getBoundingBox()));
} }
} }
@@ -74,7 +74,7 @@ interface EntityGetterMixin {
@Overwrite @Overwrite
default boolean isUnobstructed(final Entity entity, final VoxelShape voxel) { default boolean isUnobstructed(final Entity entity, final VoxelShape voxel) {
if (voxel.isEmpty()) { if (voxel.isEmpty()) {
return true; return false;
} }
final AABB singleAABB = ((CollisionVoxelShape)voxel).moonrise$getSingleAABBRepresentation(); final AABB singleAABB = ((CollisionVoxelShape)voxel).moonrise$getSingleAABBRepresentation();

View File

@@ -55,7 +55,7 @@ abstract class LevelMixin implements LevelAccessor, AutoCloseable {
public boolean isUnobstructed(final Entity entity) { public boolean isUnobstructed(final Entity entity) {
final AABB boundingBox = entity.getBoundingBox(); final AABB boundingBox = entity.getBoundingBox();
if (CollisionUtil.isEmpty(boundingBox)) { if (CollisionUtil.isEmpty(boundingBox)) {
return true; return false;
} }
final List<Entity> entities = this.getEntities( final List<Entity> entities = this.getEntities(

View File

@@ -345,8 +345,11 @@ abstract class ShapesMixin {
* @author Spottedleaf * @author Spottedleaf
*/ */
@Overwrite @Overwrite
public static boolean blockOccludes(final VoxelShape first, final VoxelShape second, final Direction direction) { public static boolean blockOccudes(final VoxelShape first, final VoxelShape second, final Direction direction) {
if (first == BLOCK & second == BLOCK) { final boolean firstBlock = first == BLOCK;
final boolean secondBlock = second == BLOCK;
if (firstBlock & secondBlock) {
return true; return true;
} }

View File

@@ -17,7 +17,7 @@ interface ServerAddressResolverMixin {
@Redirect( @Redirect(
method = { method = {
"method_36903", "method_36903",
"lambda$static$0" "*(Lnet/minecraft/client/multiplayer/resolver/ServerAddress;)Ljava/util/Optional;"
}, },
at = @At( at = @At(
value = "INVOKE", value = "INVOKE",

View File

@@ -49,10 +49,10 @@ import java.util.function.Supplier;
abstract class ThreadedLevelLightEngineMixin extends LevelLightEngine implements StarLightLightingProvider { abstract class ThreadedLevelLightEngineMixin extends LevelLightEngine implements StarLightLightingProvider {
@Shadow @Shadow
public ConsecutiveExecutor consecutiveExecutor; private ConsecutiveExecutor consecutiveExecutor;
@Shadow @Shadow
public ChunkTaskDispatcher taskDispatcher; private ChunkTaskDispatcher taskDispatcher;
public ThreadedLevelLightEngineMixin(final LightChunkGetter chunkProvider, final boolean hasBlockLight, final boolean hasSkyLight) { public ThreadedLevelLightEngineMixin(final LightChunkGetter chunkProvider, final boolean hasBlockLight, final boolean hasSkyLight) {
super(chunkProvider, hasBlockLight, hasSkyLight); super(chunkProvider, hasBlockLight, hasSkyLight);
@@ -86,10 +86,10 @@ abstract class ThreadedLevelLightEngineMixin extends LevelLightEngine implements
final Long ticketId = Long.valueOf(this.chunkWorkCounter.getAndIncrement()); final Long ticketId = Long.valueOf(this.chunkWorkCounter.getAndIncrement());
final ChunkPos pos = new ChunkPos(chunkX, chunkZ); final ChunkPos pos = new ChunkPos(chunkX, chunkZ);
((ChunkSystemServerLevel)world).moonrise$getChunkTaskScheduler().chunkHolderManager.addTicketAtLevel(StarLightInterface.CHUNK_WORK_TICKET, pos, StarLightInterface.LIGHT_TICKET_LEVEL, ticketId); world.getChunkSource().addRegionTicket(StarLightInterface.CHUNK_WORK_TICKET, pos, StarLightInterface.REGION_LIGHT_TICKET_LEVEL, ticketId);
scheduledTask.queueOrRunTask(() -> { scheduledTask.queueOrRunTask(() -> {
((ChunkSystemServerLevel)world).moonrise$getChunkTaskScheduler().chunkHolderManager.removeTicketAtLevel(StarLightInterface.CHUNK_WORK_TICKET, pos, StarLightInterface.LIGHT_TICKET_LEVEL, ticketId); world.getChunkSource().removeRegionTicket(StarLightInterface.CHUNK_WORK_TICKET, pos, StarLightInterface.REGION_LIGHT_TICKET_LEVEL, ticketId);
}); });
} }
@@ -105,7 +105,7 @@ abstract class ThreadedLevelLightEngineMixin extends LevelLightEngine implements
final ChunkPos pos = iterator.next(); final ChunkPos pos = iterator.next();
final Long id = ChunkTaskScheduler.getNextChunkRelightId(); final Long id = ChunkTaskScheduler.getNextChunkRelightId();
((ChunkSystemServerLevel)world).moonrise$getChunkTaskScheduler().chunkHolderManager.addTicketAtLevel(ChunkTaskScheduler.CHUNK_RELIGHT, pos, StarLightInterface.LIGHT_TICKET_LEVEL, id); world.getChunkSource().addRegionTicket(ChunkTaskScheduler.CHUNK_RELIGHT, pos, StarLightInterface.REGION_LIGHT_TICKET_LEVEL, id);
ticketIds.put(pos, id); ticketIds.put(pos, id);
final ChunkAccess chunk = (ChunkAccess)world.getChunkSource().getChunkForLighting(pos.x, pos.z); final ChunkAccess chunk = (ChunkAccess)world.getChunkSource().getChunkForLighting(pos.x, pos.z);
@@ -113,7 +113,7 @@ abstract class ThreadedLevelLightEngineMixin extends LevelLightEngine implements
// cannot relight this chunk // cannot relight this chunk
iterator.remove(); iterator.remove();
ticketIds.remove(pos); ticketIds.remove(pos);
((ChunkSystemServerLevel)world).moonrise$getChunkTaskScheduler().chunkHolderManager.removeTicketAtLevel(ChunkTaskScheduler.CHUNK_RELIGHT, pos, StarLightInterface.LIGHT_TICKET_LEVEL, id); world.getChunkSource().removeRegionTicket(ChunkTaskScheduler.CHUNK_RELIGHT, pos, StarLightInterface.REGION_LIGHT_TICKET_LEVEL, id);
continue; continue;
} }
} }
@@ -160,9 +160,9 @@ abstract class ThreadedLevelLightEngineMixin extends LevelLightEngine implements
} }
for (final Map.Entry<ChunkPos, Long> entry : ticketIds.entrySet()) { for (final Map.Entry<ChunkPos, Long> entry : ticketIds.entrySet()) {
((ChunkSystemServerLevel)world).moonrise$getChunkTaskScheduler().chunkHolderManager.removeTicketAtLevel( world.getChunkSource().removeRegionTicket(
ChunkTaskScheduler.CHUNK_RELIGHT, entry.getKey(), ChunkTaskScheduler.CHUNK_RELIGHT, entry.getKey(),
StarLightInterface.LIGHT_TICKET_LEVEL, entry.getValue() StarLightInterface.REGION_LIGHT_TICKET_LEVEL, entry.getValue()
); );
} }
} }

View File

@@ -60,13 +60,13 @@ abstract class SerializableChunkDataMixin {
method = "parse", method = "parse",
at = @At( at = @At(
value = "INVOKE", value = "INVOKE",
target = "Lnet/minecraft/nbt/CompoundTag;getBooleanOr(Ljava/lang/String;Z)Z", target = "Lnet/minecraft/nbt/CompoundTag;getBoolean(Ljava/lang/String;)Z",
ordinal = 0 ordinal = 0
) )
) )
private static boolean setLightCorrect(final CompoundTag instance, final String string, final boolean dfl, private static boolean setLightCorrect(final CompoundTag instance, final String string,
@Local(ordinal = 0, argsOnly = false) final ChunkStatus status) { @Local(ordinal = 0, argsOnly = false) final ChunkStatus status) {
final boolean starlightCorrect = instance.get("isLightOn") != null && instance.getIntOr(SaveUtil.STARLIGHT_VERSION_TAG, -1) == SaveUtil.STARLIGHT_LIGHT_VERSION; final boolean starlightCorrect = instance.get("isLightOn") != null && instance.getInt(SaveUtil.STARLIGHT_VERSION_TAG) == SaveUtil.STARLIGHT_LIGHT_VERSION;
return status.isOrAfter(ChunkStatus.LIGHT) && starlightCorrect; return status.isOrAfter(ChunkStatus.LIGHT) && starlightCorrect;
} }
@@ -84,17 +84,17 @@ abstract class SerializableChunkDataMixin {
) )
private static SerializableChunkData.SectionData readStarlightState(final int y, final LevelChunkSection chunkSection, private static SerializableChunkData.SectionData readStarlightState(final int y, final LevelChunkSection chunkSection,
final DataLayer blockLight, final DataLayer skyLight, final DataLayer blockLight, final DataLayer skyLight,
@Local(ordinal = 2, argsOnly = false) final CompoundTag sectionData) { @Local(ordinal = 3, argsOnly = false) final CompoundTag sectionData) {
final SerializableChunkData.SectionData ret = new SerializableChunkData.SectionData( final SerializableChunkData.SectionData ret = new SerializableChunkData.SectionData(
y, chunkSection, blockLight, skyLight y, chunkSection, blockLight, skyLight
); );
if (sectionData.contains(SaveUtil.BLOCKLIGHT_STATE_TAG)) { if (sectionData.contains(SaveUtil.BLOCKLIGHT_STATE_TAG, Tag.TAG_ANY_NUMERIC)) {
((StarlightSectionData)(Object)ret).starlight$setBlockLightState(sectionData.getIntOr(SaveUtil.BLOCKLIGHT_STATE_TAG, 0)); ((StarlightSectionData)(Object)ret).starlight$setBlockLightState(sectionData.getInt(SaveUtil.BLOCKLIGHT_STATE_TAG));
} }
if (sectionData.contains(SaveUtil.SKYLIGHT_STATE_TAG)) { if (sectionData.contains(SaveUtil.SKYLIGHT_STATE_TAG, Tag.TAG_ANY_NUMERIC)) {
((StarlightSectionData)(Object)ret).starlight$setSkyLightState(sectionData.getIntOr(SaveUtil.SKYLIGHT_STATE_TAG, 0)); ((StarlightSectionData)(Object)ret).starlight$setSkyLightState(sectionData.getInt(SaveUtil.SKYLIGHT_STATE_TAG));
} }
return ret; return ret;

View File

@@ -15,11 +15,12 @@ public final class ChunkSystemConverters {
private static final int DEFAULT_ENTITY_CHUNK_DATA_VERSION = -1; private static final int DEFAULT_ENTITY_CHUNK_DATA_VERSION = -1;
private static int getCurrentVersion() { private static int getCurrentVersion() {
return SharedConstants.getCurrentVersion().dataVersion().version(); return SharedConstants.getCurrentVersion().getDataVersion().getVersion();
} }
private static int getDataVersion(final CompoundTag data, final int dfl) { private static int getDataVersion(final CompoundTag data, final int dfl) {
return data.getIntOr(SharedConstants.DATA_VERSION_TAG, dfl); return !data.contains(SharedConstants.DATA_VERSION_TAG, Tag.TAG_ANY_NUMERIC)
? dfl : data.getInt(SharedConstants.DATA_VERSION_TAG);
} }
public static CompoundTag convertPoiCompoundTag(final CompoundTag data, final ServerLevel world) { public static CompoundTag convertPoiCompoundTag(final CompoundTag data, final ServerLevel world) {

View File

@@ -3,7 +3,6 @@ package ca.spottedleaf.moonrise.patches.chunk_system.entity;
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkData; import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkData;
import net.minecraft.server.level.FullChunkStatus; import net.minecraft.server.level.FullChunkStatus;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.animal.HappyGhast;
import net.minecraft.world.entity.monster.Shulker; import net.minecraft.world.entity.monster.Shulker;
import net.minecraft.world.entity.vehicle.AbstractMinecart; import net.minecraft.world.entity.vehicle.AbstractMinecart;
import net.minecraft.world.entity.vehicle.Boat; import net.minecraft.world.entity.vehicle.Boat;
@@ -14,7 +13,7 @@ public interface ChunkSystemEntity {
// for mods to override // for mods to override
public default boolean moonrise$isHardCollidingUncached() { public default boolean moonrise$isHardCollidingUncached() {
return this instanceof Boat || this instanceof AbstractMinecart || this instanceof Shulker || this instanceof HappyGhast || ((Entity)this).canBeCollidedWith(null); return this instanceof Boat || this instanceof AbstractMinecart || this instanceof Shulker || ((Entity)this).canBeCollidedWith();
} }
public FullChunkStatus moonrise$getChunkStatus(); public FullChunkStatus moonrise$getChunkStatus();

View File

@@ -1143,7 +1143,7 @@ public final class MoonriseRegionFileIO {
LOGGER.error("Failed to decompress chunk data for task: " + this.toString(), thr); LOGGER.error("Failed to decompress chunk data for task: " + this.toString(), thr);
} }
if (throwable == null && compoundTag == null) { if (compoundTag == null) {
// need to re-try from the start // need to re-try from the start
this.scheduleReadIO(); this.scheduleReadIO();
return; return;

View File

@@ -48,7 +48,7 @@ public final class EntityDataController extends MoonriseRegionFileIO.RegionDataC
} }
private static void checkPosition(final ChunkPos pos, final CompoundTag nbt) { private static void checkPosition(final ChunkPos pos, final CompoundTag nbt) {
final ChunkPos nbtPos = nbt == null ? null : nbt.read("Position", ChunkPos.CODEC).orElse(null); final ChunkPos nbtPos = nbt == null ? null : EntityStorage.readChunkPos(nbt);
if (nbtPos != null && !pos.equals(nbtPos)) { if (nbtPos != null && !pos.equals(nbtPos)) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Entity chunk coordinate and serialized data do not have matching coordinates, trying to serialize coordinate " + pos.toString() "Entity chunk coordinate and serialized data do not have matching coordinates, trying to serialize coordinate " + pos.toString()

View File

@@ -1,7 +1,6 @@
package ca.spottedleaf.moonrise.patches.chunk_system.level; package ca.spottedleaf.moonrise.patches.chunk_system.level;
import ca.spottedleaf.concurrentutil.util.Priority; import ca.spottedleaf.concurrentutil.util.Priority;
import ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet;
import ca.spottedleaf.moonrise.common.list.ReferenceList; import ca.spottedleaf.moonrise.common.list.ReferenceList;
import ca.spottedleaf.moonrise.common.misc.NearbyPlayers; import ca.spottedleaf.moonrise.common.misc.NearbyPlayers;
import ca.spottedleaf.moonrise.patches.chunk_system.io.MoonriseRegionFileIO; import ca.spottedleaf.moonrise.patches.chunk_system.io.MoonriseRegionFileIO;
@@ -11,7 +10,6 @@ import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ChunkHolder; import net.minecraft.server.level.ChunkHolder;
import net.minecraft.server.level.ServerChunkCache; import net.minecraft.server.level.ServerChunkCache;
import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.chunk.status.ChunkStatus; import net.minecraft.world.level.chunk.status.ChunkStatus;
import java.util.List; import java.util.List;
import java.util.function.Consumer; import java.util.function.Consumer;
@@ -58,9 +56,9 @@ public interface ChunkSystemServerLevel extends ChunkSystemLevel {
public NearbyPlayers moonrise$getNearbyPlayers(); public NearbyPlayers moonrise$getNearbyPlayers();
public ReferenceList<LevelChunk> moonrise$getLoadedChunks(); public ReferenceList<ServerChunkCache.ChunkAndHolder> moonrise$getLoadedChunks();
public ReferenceList<LevelChunk> moonrise$getTickingChunks(); public ReferenceList<ServerChunkCache.ChunkAndHolder> moonrise$getTickingChunks();
public ReferenceList<LevelChunk> moonrise$getEntityTickingChunks(); public ReferenceList<ServerChunkCache.ChunkAndHolder> moonrise$getEntityTickingChunks();
} }

View File

@@ -1,13 +1,13 @@
package ca.spottedleaf.moonrise.patches.chunk_system.level.chunk; package ca.spottedleaf.moonrise.patches.chunk_system.level.chunk;
import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.NewChunkHolder; import net.minecraft.server.level.ServerChunkCache;
public interface ChunkSystemLevelChunk { public interface ChunkSystemLevelChunk {
public boolean moonrise$isPostProcessingDone(); public boolean moonrise$isPostProcessingDone();
public NewChunkHolder moonrise$getChunkHolder(); public ServerChunkCache.ChunkAndHolder moonrise$getChunkAndHolder();
public void moonrise$setChunkHolder(final NewChunkHolder holder); public void moonrise$setChunkAndHolder(final ServerChunkCache.ChunkAndHolder holder);
} }

View File

@@ -5,7 +5,6 @@ import ca.spottedleaf.moonrise.common.list.EntityList;
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkData; import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkData;
import ca.spottedleaf.moonrise.patches.chunk_system.entity.ChunkSystemEntity; import ca.spottedleaf.moonrise.patches.chunk_system.entity.ChunkSystemEntity;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.mojang.logging.LogUtils;
import it.unimi.dsi.fastutil.objects.Reference2ObjectMap; import it.unimi.dsi.fastutil.objects.Reference2ObjectMap;
import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
@@ -15,7 +14,6 @@ import net.minecraft.nbt.Tag;
import net.minecraft.server.level.FullChunkStatus; import net.minecraft.server.level.FullChunkStatus;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.Mth; import net.minecraft.util.Mth;
import net.minecraft.util.ProblemReporter;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntitySpawnReason; import net.minecraft.world.entity.EntitySpawnReason;
import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.EntityType;
@@ -23,14 +21,9 @@ import net.minecraft.world.entity.boss.EnderDragonPart;
import net.minecraft.world.entity.boss.enderdragon.EnderDragon; import net.minecraft.world.entity.boss.enderdragon.EnderDragon;
import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.storage.EntityStorage; import net.minecraft.world.level.chunk.storage.EntityStorage;
import net.minecraft.world.level.entity.Visibility; import net.minecraft.world.level.entity.Visibility;
import net.minecraft.world.level.storage.TagValueInput;
import net.minecraft.world.level.storage.TagValueOutput;
import net.minecraft.world.level.storage.ValueInput;
import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.AABB;
import org.slf4j.Logger;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Iterator; import java.util.Iterator;
@@ -39,8 +32,6 @@ import java.util.function.Predicate;
public final class ChunkEntitySlices { public final class ChunkEntitySlices {
private static final Logger LOGGER = LogUtils.getLogger();
public final int minSection; public final int minSection;
public final int maxSection; public final int maxSection;
public final int chunkX; public final int chunkX;
@@ -83,12 +74,9 @@ public final class ChunkEntitySlices {
this.chunkData = chunkData; this.chunkData = chunkData;
} }
public static List<Entity> readEntities(final ServerLevel world, final ChunkPos pos, final CompoundTag compoundTag) { public static List<Entity> readEntities(final ServerLevel world, final CompoundTag compoundTag) {
try (final ProblemReporter.ScopedCollector scopedCollector = new ProblemReporter.ScopedCollector(ChunkAccess.problemPath(pos), LOGGER)) { // TODO check this and below on update for format changes
ValueInput valueinput = TagValueInput.create(scopedCollector, world.registryAccess(), compoundTag); return EntityType.loadEntitiesRecursive(compoundTag.getList("Entities", 10), world, EntitySpawnReason.LOAD).collect(ImmutableList.toImmutableList());
// TODO check this and below on update for format changes
return EntityType.loadEntitiesRecursive(valueinput.childrenListOrEmpty("Entities"), world, EntitySpawnReason.LOAD).collect(ImmutableList.toImmutableList());
}
} }
// Paper start - rewrite chunk system // Paper start - rewrite chunk system
@@ -96,12 +84,12 @@ public final class ChunkEntitySlices {
if (from == null) { if (from == null) {
return; return;
} }
final ListTag entitiesFrom = from.getListOrEmpty("Entities"); final ListTag entitiesFrom = from.getList("Entities", Tag.TAG_COMPOUND);
if (entitiesFrom == null || entitiesFrom.isEmpty()) { if (entitiesFrom == null || entitiesFrom.isEmpty()) {
return; return;
} }
final ListTag entitiesInto = into.getListOrEmpty("Entities"); final ListTag entitiesInto = into.getList("Entities", Tag.TAG_COMPOUND);
into.put("Entities", entitiesInto); // this is in case into doesn't have any entities into.put("Entities", entitiesInto); // this is in case into doesn't have any entities
entitiesInto.addAll(0, entitiesFrom); entitiesInto.addAll(0, entitiesFrom);
} }
@@ -116,25 +104,15 @@ public final class ChunkEntitySlices {
} }
final ListTag entitiesTag = new ListTag(); final ListTag entitiesTag = new ListTag();
try (final ProblemReporter.ScopedCollector scopedCollector = new ProblemReporter.ScopedCollector(ChunkAccess.problemPath(chunkPos), LOGGER)) { for (final Entity entity : PlatformHooks.get().modifySavedEntities(world, chunkPos.x, chunkPos.z, entities)) {
for (final Entity entity : PlatformHooks.get().modifySavedEntities(world, chunkPos.x, chunkPos.z, entities)) { CompoundTag compoundTag = new CompoundTag();
final TagValueOutput savedEntity = TagValueOutput.createWithContext( if (entity.save(compoundTag)) {
scopedCollector.forChild(entity.problemPath()), entity.registryAccess() entitiesTag.add(compoundTag);
);
try {
if (entity.save(savedEntity)) {
entitiesTag.add(savedEntity.buildResult());
}
} catch (final Exception ex) {
LOGGER.error("Entity type " + entity.getType() + " failed to serialize", ex);
}
} }
} }
final CompoundTag ret = NbtUtils.addCurrentDataVersion(new CompoundTag()); final CompoundTag ret = NbtUtils.addCurrentDataVersion(new CompoundTag());
ret.put("Entities", entitiesTag); ret.put("Entities", entitiesTag);
ret.store("Position", ChunkPos.CODEC, chunkPos); EntityStorage.writeChunkPos(ret, chunkPos);
return !force && entitiesTag.isEmpty() ? null : ret; return !force && entitiesTag.isEmpty() ? null : ret;
} }

View File

@@ -179,10 +179,6 @@ public abstract class EntityLookup implements LevelEntityGetter<Entity> {
} }
} }
public Iterable<Entity> getAllMapped() {
return this.entityByUUID.values();
}
public int getEntityCount() { public int getEntityCount() {
synchronized (this.accessibleEntities) { synchronized (this.accessibleEntities) {
return this.accessibleEntities.size(); return this.accessibleEntities.size();

View File

@@ -119,7 +119,7 @@ public final class PoiChunk {
final CompoundTag sections = new CompoundTag(); final CompoundTag sections = new CompoundTag();
ret.put("Sections", sections); ret.put("Sections", sections);
ret.putInt("DataVersion", SharedConstants.getCurrentVersion().dataVersion().version()); ret.putInt("DataVersion", SharedConstants.getCurrentVersion().getDataVersion().getVersion());
final ServerLevel world = this.world; final ServerLevel world = this.world;
final int chunkX = this.chunkX; final int chunkX = this.chunkX;
@@ -159,7 +159,7 @@ public final class PoiChunk {
final RegistryOps<Tag> registryOps = RegistryOps.create(NbtOps.INSTANCE, world.registryAccess()); final RegistryOps<Tag> registryOps = RegistryOps.create(NbtOps.INSTANCE, world.registryAccess());
final CompoundTag sections = data.getCompoundOrEmpty("Sections"); final CompoundTag sections = data.getCompound("Sections");
if (sections.isEmpty()) { if (sections.isEmpty()) {
// nothing to parse // nothing to parse
@@ -176,7 +176,7 @@ public final class PoiChunk {
continue; continue;
} }
final CompoundTag section = sections.getCompoundOrEmpty(key); final CompoundTag section = sections.getCompound(key);
final DataResult<PoiSection.Packed> deserializeResult = PoiSection.Packed.CODEC.parse(registryOps, section); final DataResult<PoiSection.Packed> deserializeResult = PoiSection.Packed.CODEC.parse(registryOps, section);
final int finalSectionY = sectionY; final int finalSectionY = sectionY;
final PoiSection.Packed packed = deserializeResult.resultOrPartial((final String description) -> { final PoiSection.Packed packed = deserializeResult.resultOrPartial((final String description) -> {

View File

@@ -14,7 +14,6 @@ import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkSystemChunk
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkSystemLevelChunk; import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkSystemLevelChunk;
import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkHolderManager; import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkHolderManager;
import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkTaskScheduler; import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkTaskScheduler;
import ca.spottedleaf.moonrise.patches.chunk_system.ticket.ChunkSystemTicketType;
import ca.spottedleaf.moonrise.patches.chunk_system.util.ParallelSearchRadiusIteration; import ca.spottedleaf.moonrise.patches.chunk_system.util.ParallelSearchRadiusIteration;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import it.unimi.dsi.fastutil.longs.Long2ByteOpenHashMap; import it.unimi.dsi.fastutil.longs.Long2ByteOpenHashMap;
@@ -46,8 +45,11 @@ import java.util.function.Function;
public final class RegionizedPlayerChunkLoader { public final class RegionizedPlayerChunkLoader {
public static final TicketType PLAYER_TICKET = ChunkSystemTicketType.create("chunk_system:player_ticket", Long::compareTo); public static final TicketType<Long> PLAYER_TICKET = TicketType.create("chunk_system:player_ticket", Long::compareTo);
public static final TicketType PLAYER_TICKET_DELAYED = ChunkSystemTicketType.create("chunk_system:player_ticket_delayed", Long::compareTo, 5L * 20L); public static final TicketType<Long> PLAYER_TICKET_DELAYED = TicketType.create("chunk_system:player_ticket_delayed", Long::compareTo, 5 * 20);
public static final int MIN_VIEW_DISTANCE = 2;
public static final int MAX_VIEW_DISTANCE = 32;
public static final int GENERATED_TICKET_LEVEL = ChunkHolderManager.FULL_LOADED_TICKET_LEVEL; public static final int GENERATED_TICKET_LEVEL = ChunkHolderManager.FULL_LOADED_TICKET_LEVEL;
public static final int LOADED_TICKET_LEVEL = ChunkTaskScheduler.getTicketLevel(ChunkStatus.EMPTY); public static final int LOADED_TICKET_LEVEL = ChunkTaskScheduler.getTicketLevel(ChunkStatus.EMPTY);
@@ -147,7 +149,7 @@ public final class RegionizedPlayerChunkLoader {
} }
public static int getAPITickViewDistance(final ServerPlayer player) { public static int getAPITickViewDistance(final ServerPlayer player) {
final ServerLevel level = player.level(); final ServerLevel level = player.serverLevel();
final PlayerChunkLoaderData data = ((ChunkSystemServerPlayer)player).moonrise$getChunkLoader(); final PlayerChunkLoaderData data = ((ChunkSystemServerPlayer)player).moonrise$getChunkLoader();
if (data == null) { if (data == null) {
return ((ChunkSystemServerLevel)level).moonrise$getPlayerChunkLoader().getAPITickDistance(); return ((ChunkSystemServerLevel)level).moonrise$getPlayerChunkLoader().getAPITickDistance();
@@ -156,7 +158,7 @@ public final class RegionizedPlayerChunkLoader {
} }
public static int getAPIViewDistance(final ServerPlayer player) { public static int getAPIViewDistance(final ServerPlayer player) {
final ServerLevel level = player.level(); final ServerLevel level = player.serverLevel();
final PlayerChunkLoaderData data = ((ChunkSystemServerPlayer)player).moonrise$getChunkLoader(); final PlayerChunkLoaderData data = ((ChunkSystemServerPlayer)player).moonrise$getChunkLoader();
if (data == null) { if (data == null) {
return ((ChunkSystemServerLevel)level).moonrise$getPlayerChunkLoader().getAPIViewDistance(); return ((ChunkSystemServerLevel)level).moonrise$getPlayerChunkLoader().getAPIViewDistance();
@@ -166,7 +168,7 @@ public final class RegionizedPlayerChunkLoader {
} }
public static int getAPISendViewDistance(final ServerPlayer player) { public static int getAPISendViewDistance(final ServerPlayer player) {
final ServerLevel level = player.level(); final ServerLevel level = player.serverLevel();
final PlayerChunkLoaderData data = ((ChunkSystemServerPlayer)player).moonrise$getChunkLoader(); final PlayerChunkLoaderData data = ((ChunkSystemServerPlayer)player).moonrise$getChunkLoader();
if (data == null) { if (data == null) {
return ((ChunkSystemServerLevel)level).moonrise$getPlayerChunkLoader().getAPISendViewDistance(); return ((ChunkSystemServerLevel)level).moonrise$getPlayerChunkLoader().getAPISendViewDistance();
@@ -683,7 +685,8 @@ public final class RegionizedPlayerChunkLoader {
} }
this.pushDelayedTicketOp( this.pushDelayedTicketOp(
ChunkHolderManager.TicketOperation.addOp( ChunkHolderManager.TicketOperation.addOp(
chunk, PLAYER_TICKET, LOADED_TICKET_LEVEL, this.idBoxed chunk,
PLAYER_TICKET, LOADED_TICKET_LEVEL, this.idBoxed
) )
); );
chunks.add(chunk); chunks.add(chunk);

View File

@@ -16,11 +16,9 @@ import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.task.ChunkLoadTas
import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.task.ChunkProgressionTask; import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.task.ChunkProgressionTask;
import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.task.GenericDataLoadTask; import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.task.GenericDataLoadTask;
import ca.spottedleaf.moonrise.patches.chunk_system.ticket.ChunkSystemTicket; import ca.spottedleaf.moonrise.patches.chunk_system.ticket.ChunkSystemTicket;
import ca.spottedleaf.moonrise.patches.chunk_system.ticket.ChunkSystemTicketType;
import ca.spottedleaf.moonrise.patches.chunk_system.util.ChunkSystemSortedArraySet; import ca.spottedleaf.moonrise.patches.chunk_system.util.ChunkSystemSortedArraySet;
import com.google.gson.JsonArray; import com.google.gson.JsonArray;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.longs.Long2ByteLinkedOpenHashMap; import it.unimi.dsi.fastutil.longs.Long2ByteLinkedOpenHashMap;
import it.unimi.dsi.fastutil.longs.Long2ByteMap; import it.unimi.dsi.fastutil.longs.Long2ByteMap;
import it.unimi.dsi.fastutil.longs.Long2IntMap; import it.unimi.dsi.fastutil.longs.Long2IntMap;
@@ -67,12 +65,13 @@ public final class ChunkHolderManager {
public static final int ENTITY_TICKING_TICKET_LEVEL = ChunkLevel.ENTITY_TICKING_LEVEL; public static final int ENTITY_TICKING_TICKET_LEVEL = ChunkLevel.ENTITY_TICKING_LEVEL;
public static final int MAX_TICKET_LEVEL = ChunkLevel.MAX_LEVEL; // inclusive public static final int MAX_TICKET_LEVEL = ChunkLevel.MAX_LEVEL; // inclusive
public static final TicketType UNLOAD_COOLDOWN = ChunkSystemTicketType.create("chunk_system:unload_cooldown", null, 5L * 20L); public static final TicketType<Unit> UNLOAD_COOLDOWN = TicketType.create("unload_cooldown", (u1, u2) -> 0, 5 * 20);
private static final long NO_TIMEOUT_MARKER = Long.MIN_VALUE; private static final long NO_TIMEOUT_MARKER = Long.MIN_VALUE;
private static final long PROBE_MARKER = Long.MIN_VALUE + 1;
public final ReentrantAreaLock ticketLockArea; public final ReentrantAreaLock ticketLockArea;
private final ConcurrentLong2ReferenceChainedHashTable<SortedArraySet<Ticket>> tickets = new ConcurrentLong2ReferenceChainedHashTable<>(); private final ConcurrentLong2ReferenceChainedHashTable<SortedArraySet<Ticket<?>>> tickets = new ConcurrentLong2ReferenceChainedHashTable<>();
private final ConcurrentLong2ReferenceChainedHashTable<Long2IntOpenHashMap> sectionToChunkToExpireCount = new ConcurrentLong2ReferenceChainedHashTable<>(); private final ConcurrentLong2ReferenceChainedHashTable<Long2IntOpenHashMap> sectionToChunkToExpireCount = new ConcurrentLong2ReferenceChainedHashTable<>();
final ChunkUnloadQueue unloadQueue; final ChunkUnloadQueue unloadQueue;
@@ -103,8 +102,6 @@ public final class ChunkHolderManager {
return Long.compare(coord1, coord2); return Long.compare(coord1, coord2);
}); });
private final ConcurrentLong2ReferenceChainedHashTable<Long2IntOpenHashMap> ticketCounters = new ConcurrentLong2ReferenceChainedHashTable<>();
public ChunkHolderManager(final ServerLevel world, final ChunkTaskScheduler taskScheduler) { public ChunkHolderManager(final ServerLevel world, final ChunkTaskScheduler taskScheduler) {
this.world = world; this.world = world;
this.taskScheduler = taskScheduler; this.taskScheduler = taskScheduler;
@@ -166,6 +163,7 @@ public final class ChunkHolderManager {
return this.chunkHolders.size(); return this.chunkHolders.size();
} }
// TODO replace the need for this, specifically: optimise ServerChunkCache#tickChunks
public Iterable<ChunkHolder> getOldChunkHoldersIterable() { public Iterable<ChunkHolder> getOldChunkHoldersIterable() {
return new Iterable<ChunkHolder>() { return new Iterable<ChunkHolder>() {
@Override @Override
@@ -413,7 +411,7 @@ public final class ChunkHolderManager {
public String getTicketDebugString(final long coordinate) { public String getTicketDebugString(final long coordinate) {
final ReentrantAreaLock.Node ticketLock = this.ticketLockArea.lock(CoordinateUtils.getChunkX(coordinate), CoordinateUtils.getChunkZ(coordinate)); final ReentrantAreaLock.Node ticketLock = this.ticketLockArea.lock(CoordinateUtils.getChunkX(coordinate), CoordinateUtils.getChunkZ(coordinate));
try { try {
final SortedArraySet<Ticket> tickets = this.tickets.get(coordinate); final SortedArraySet<Ticket<?>> tickets = this.tickets.get(coordinate);
return tickets != null ? tickets.first().toString() : "no_ticket"; return tickets != null ? tickets.first().toString() : "no_ticket";
} finally { } finally {
@@ -423,40 +421,8 @@ public final class ChunkHolderManager {
} }
} }
public boolean hasTickets() { public Long2ObjectOpenHashMap<SortedArraySet<Ticket<?>>> getTicketsCopy() {
return !this.tickets.isEmpty(); final Long2ObjectOpenHashMap<SortedArraySet<Ticket<?>>> ret = new Long2ObjectOpenHashMap<>();
}
public List<Ticket> getTicketsAt(final int chunkX, final int chunkZ) {
final long key = CoordinateUtils.getChunkKey(chunkX, chunkZ);
if (!this.tickets.containsKey(key)) {
// avoid contending lock
return new ArrayList<>();
}
final ReentrantAreaLock.Node lock = this.ticketLockArea.lock(chunkX, chunkZ);
try {
final SortedArraySet<Ticket> tickets = this.tickets.get(key);
if (tickets == null) {
return new ArrayList<>();
}
final List<Ticket> ret = new ArrayList<>(tickets.size());
for (final Ticket ticket : tickets) {
ret.add(ticket);
}
return ret;
} finally {
this.ticketLockArea.unlock(lock);
}
}
public Long2ObjectOpenHashMap<SortedArraySet<Ticket>> getTicketsCopy() {
final Long2ObjectOpenHashMap<SortedArraySet<Ticket>> ret = new Long2ObjectOpenHashMap<>();
final Long2ObjectOpenHashMap<LongArrayList> sections = new Long2ObjectOpenHashMap<>(); final Long2ObjectOpenHashMap<LongArrayList> sections = new Long2ObjectOpenHashMap<>();
final int sectionShift = this.taskScheduler.getChunkSystemLockShift(); final int sectionShift = this.taskScheduler.getChunkSystemLockShift();
for (final PrimitiveIterator.OfLong iterator = this.tickets.keyIterator(); iterator.hasNext();) { for (final PrimitiveIterator.OfLong iterator = this.tickets.keyIterator(); iterator.hasNext();) {
@@ -485,12 +451,12 @@ public final class ChunkHolderManager {
try { try {
for (final LongIterator iterator2 = coordinates.iterator(); iterator2.hasNext();) { for (final LongIterator iterator2 = coordinates.iterator(); iterator2.hasNext();) {
final long coord = iterator2.nextLong(); final long coord = iterator2.nextLong();
final SortedArraySet<Ticket> tickets = this.tickets.get(coord); final SortedArraySet<Ticket<?>> tickets = this.tickets.get(coord);
if (tickets == null) { if (tickets == null) {
// removed before we acquired lock // removed before we acquired lock
continue; continue;
} }
ret.put(coord, ((ChunkSystemSortedArraySet<Ticket>)tickets).moonrise$copy()); ret.put(coord, ((ChunkSystemSortedArraySet<Ticket<?>>)tickets).moonrise$copy());
} }
} finally { } finally {
this.ticketLockArea.unlock(ticketLock); this.ticketLockArea.unlock(ticketLock);
@@ -508,16 +474,16 @@ public final class ChunkHolderManager {
} }
} }
private static int getTicketLevelAt(final SortedArraySet<Ticket> tickets) { private static int getTicketLevelAt(SortedArraySet<Ticket<?>> tickets) {
return !tickets.isEmpty() ? tickets.first().getTicketLevel() : MAX_TICKET_LEVEL + 1; return !tickets.isEmpty() ? tickets.first().getTicketLevel() : MAX_TICKET_LEVEL + 1;
} }
public <T> boolean addTicketAtLevel(final TicketType type, final ChunkPos chunkPos, final int level, public <T> boolean addTicketAtLevel(final TicketType<T> type, final ChunkPos chunkPos, final int level,
final T identifier) { final T identifier) {
return this.addTicketAtLevel(type, CoordinateUtils.getChunkKey(chunkPos), level, identifier); return this.addTicketAtLevel(type, CoordinateUtils.getChunkKey(chunkPos), level, identifier);
} }
public <T> boolean addTicketAtLevel(final TicketType type, final int chunkX, final int chunkZ, final int level, public <T> boolean addTicketAtLevel(final TicketType<T> type, final int chunkX, final int chunkZ, final int level,
final T identifier) { final T identifier) {
return this.addTicketAtLevel(type, CoordinateUtils.getChunkKey(chunkX, chunkZ), level, identifier); return this.addTicketAtLevel(type, CoordinateUtils.getChunkKey(chunkX, chunkZ), level, identifier);
} }
@@ -558,29 +524,29 @@ public final class ChunkHolderManager {
// supposed to return true if the ticket was added and did not replace another // supposed to return true if the ticket was added and did not replace another
// but, we always return false if the ticket cannot be added // but, we always return false if the ticket cannot be added
public <T> boolean addTicketAtLevel(final TicketType type, final long chunk, final int level, final T identifier) { public <T> boolean addTicketAtLevel(final TicketType<T> type, final long chunk, final int level, final T identifier) {
return this.addTicketAtLevel(type, chunk, level, identifier, true); return this.addTicketAtLevel(type, chunk, level, identifier, true);
} }
<T> boolean addTicketAtLevel(final TicketType type, final long chunk, final int level, final T identifier, final boolean lock) { <T> boolean addTicketAtLevel(final TicketType<T> type, final long chunk, final int level, final T identifier, final boolean lock) {
final long removeDelay = type.timeout() <= 0 ? NO_TIMEOUT_MARKER : type.timeout(); final long removeDelay = type.timeout <= 0 ? NO_TIMEOUT_MARKER : type.timeout;
if (level > MAX_TICKET_LEVEL) { if (level > MAX_TICKET_LEVEL) {
return false; return false;
} }
final int chunkX = CoordinateUtils.getChunkX(chunk); final int chunkX = CoordinateUtils.getChunkX(chunk);
final int chunkZ = CoordinateUtils.getChunkZ(chunk); final int chunkZ = CoordinateUtils.getChunkZ(chunk);
final Ticket ticket = new Ticket(type, level, removeDelay); final Ticket<T> ticket = new Ticket<>(type, level, identifier);
((ChunkSystemTicket<T>)(Object)ticket).moonrise$setIdentifier(identifier); ((ChunkSystemTicket<T>)(Object)ticket).moonrise$setRemoveDelay(removeDelay);
final ReentrantAreaLock.Node ticketLock = lock ? this.ticketLockArea.lock(chunkX, chunkZ) : null; final ReentrantAreaLock.Node ticketLock = lock ? this.ticketLockArea.lock(chunkX, chunkZ) : null;
try { try {
final SortedArraySet<Ticket> ticketsAtChunk = this.tickets.computeIfAbsent(chunk, (final long keyInMap) -> { final SortedArraySet<Ticket<?>> ticketsAtChunk = this.tickets.computeIfAbsent(chunk, (final long keyInMap) -> {
return (SortedArraySet)SortedArraySet.create(4); return SortedArraySet.create(4);
}); });
final int levelBefore = getTicketLevelAt(ticketsAtChunk); final int levelBefore = getTicketLevelAt(ticketsAtChunk);
final Ticket current = (Ticket)((ChunkSystemSortedArraySet<Ticket>)ticketsAtChunk).moonrise$replace(ticket); final Ticket<T> current = (Ticket<T>)((ChunkSystemSortedArraySet<Ticket<?>>)ticketsAtChunk).moonrise$replace(ticket);
final int levelAfter = getTicketLevelAt(ticketsAtChunk); final int levelAfter = getTicketLevelAt(ticketsAtChunk);
if (current != ticket) { if (current != ticket) {
@@ -597,7 +563,6 @@ public final class ChunkHolderManager {
if (removeDelay != NO_TIMEOUT_MARKER) { if (removeDelay != NO_TIMEOUT_MARKER) {
this.addExpireCount(chunkX, chunkZ); this.addExpireCount(chunkX, chunkZ);
} }
this.addTicketCounter(type, chunk);
} }
if (levelBefore != levelAfter) { if (levelBefore != levelAfter) {
@@ -612,85 +577,36 @@ public final class ChunkHolderManager {
} }
} }
private void addTicketCounter(final TicketType type, final long pos) { public <T> boolean removeTicketAtLevel(final TicketType<T> type, final ChunkPos chunkPos, final int level, final T identifier) {
final long[] counterTypes = ((ChunkSystemTicketType<?>)(Object)type).moonrise$getCounterTypes();
if (counterTypes.length == 0) {
return;
}
synchronized (this.ticketCounters) {
for (final long counterType : counterTypes) {
final Long2IntOpenHashMap oldCounters = this.ticketCounters.get(counterType);
final Long2IntOpenHashMap newCounters = oldCounters == null ? new Long2IntOpenHashMap() : oldCounters.clone();
newCounters.addTo(pos, 1);
this.ticketCounters.put(counterType, newCounters);
}
}
}
private void removeTicketCounter(final TicketType type, final long pos) {
final long[] counterTypes = ((ChunkSystemTicketType<?>)(Object)type).moonrise$getCounterTypes();
if (counterTypes.length == 0) {
return;
}
synchronized (this.ticketCounters) {
for (final long counterType : counterTypes) {
final Long2IntOpenHashMap oldCounters = this.ticketCounters.get(counterType);
final Long2IntOpenHashMap newCounters = oldCounters == null ? new Long2IntOpenHashMap() : oldCounters.clone();
final int currCount = newCounters.get(pos);
if (currCount <= 0) {
throw new IllegalStateException("Count must be > 0 at this stage");
}
if (currCount == 1) {
newCounters.remove(pos);
} else {
newCounters.put(pos, currCount - 1);
}
this.ticketCounters.put(counterType, newCounters);
}
}
}
public Long2IntOpenHashMap getTicketCounters(final long counterType) {
return this.ticketCounters.get(counterType);
}
public <T> boolean removeTicketAtLevel(final TicketType type, final ChunkPos chunkPos, final int level, final T identifier) {
return this.removeTicketAtLevel(type, CoordinateUtils.getChunkKey(chunkPos), level, identifier); return this.removeTicketAtLevel(type, CoordinateUtils.getChunkKey(chunkPos), level, identifier);
} }
public <T> boolean removeTicketAtLevel(final TicketType type, final int chunkX, final int chunkZ, final int level, final T identifier) { public <T> boolean removeTicketAtLevel(final TicketType<T> type, final int chunkX, final int chunkZ, final int level, final T identifier) {
return this.removeTicketAtLevel(type, CoordinateUtils.getChunkKey(chunkX, chunkZ), level, identifier); return this.removeTicketAtLevel(type, CoordinateUtils.getChunkKey(chunkX, chunkZ), level, identifier);
} }
public <T> boolean removeTicketAtLevel(final TicketType type, final long chunk, final int level, final T identifier) { public <T> boolean removeTicketAtLevel(final TicketType<T> type, final long chunk, final int level, final T identifier) {
return this.removeTicketAtLevel(type, chunk, level, identifier, true); return this.removeTicketAtLevel(type, chunk, level, identifier, true);
} }
<T> boolean removeTicketAtLevel(final TicketType type, final long chunk, final int level, final T identifier, final boolean lock) { <T> boolean removeTicketAtLevel(final TicketType<T> type, final long chunk, final int level, final T identifier, final boolean lock) {
if (level > MAX_TICKET_LEVEL) { if (level > MAX_TICKET_LEVEL) {
return false; return false;
} }
final int chunkX = CoordinateUtils.getChunkX(chunk); final int chunkX = CoordinateUtils.getChunkX(chunk);
final int chunkZ = CoordinateUtils.getChunkZ(chunk); final int chunkZ = CoordinateUtils.getChunkZ(chunk);
final Ticket probe = new Ticket(type, level, 0L); final Ticket<T> probe = new Ticket<>(type, level, identifier);
((ChunkSystemTicket<T>)(Object)probe).moonrise$setIdentifier(identifier);
final ReentrantAreaLock.Node ticketLock = lock ? this.ticketLockArea.lock(chunkX, chunkZ) : null; final ReentrantAreaLock.Node ticketLock = lock ? this.ticketLockArea.lock(chunkX, chunkZ) : null;
try { try {
final SortedArraySet<Ticket> ticketsAtChunk = this.tickets.get(chunk); final SortedArraySet<Ticket<?>> ticketsAtChunk = this.tickets.get(chunk);
if (ticketsAtChunk == null) { if (ticketsAtChunk == null) {
return false; return false;
} }
final int oldLevel = getTicketLevelAt(ticketsAtChunk); final int oldLevel = getTicketLevelAt(ticketsAtChunk);
final Ticket ticket = (Ticket)((ChunkSystemSortedArraySet<Ticket>)ticketsAtChunk).moonrise$removeAndGet(probe); final Ticket<T> ticket = (Ticket<T>)((ChunkSystemSortedArraySet<Ticket<?>>)ticketsAtChunk).moonrise$removeAndGet(probe);
if (ticket == null) { if (ticket == null) {
return false; return false;
@@ -699,7 +615,8 @@ public final class ChunkHolderManager {
final int newLevel = getTicketLevelAt(ticketsAtChunk); final int newLevel = getTicketLevelAt(ticketsAtChunk);
// we should not change the ticket levels while the target region may be ticking // we should not change the ticket levels while the target region may be ticking
if (oldLevel != newLevel) { if (oldLevel != newLevel) {
final Ticket unknownTicket = new Ticket(TicketType.UNKNOWN, level); final Ticket<ChunkPos> unknownTicket = new Ticket<>(TicketType.UNKNOWN, level, new ChunkPos(chunk));
((ChunkSystemTicket<ChunkPos>)(Object)unknownTicket).moonrise$setRemoveDelay(Math.max(1, TicketType.UNKNOWN.timeout));
if (ticketsAtChunk.add(unknownTicket)) { if (ticketsAtChunk.add(unknownTicket)) {
this.addExpireCount(chunkX, chunkZ); this.addExpireCount(chunkX, chunkZ);
} else { } else {
@@ -712,8 +629,6 @@ public final class ChunkHolderManager {
this.removeExpireCount(chunkX, chunkZ); this.removeExpireCount(chunkX, chunkZ);
} }
this.removeTicketCounter(type, chunk);
return true; return true;
} finally { } finally {
if (ticketLock != null) { if (ticketLock != null) {
@@ -723,8 +638,8 @@ public final class ChunkHolderManager {
} }
// atomic with respect to all add/remove/addandremove ticket calls for the given chunk // atomic with respect to all add/remove/addandremove ticket calls for the given chunk
public <T, V> void addAndRemoveTickets(final long chunk, final TicketType addType, final int addLevel, final T addIdentifier, public <T, V> void addAndRemoveTickets(final long chunk, final TicketType<T> addType, final int addLevel, final T addIdentifier,
final TicketType removeType, final int removeLevel, final V removeIdentifier) { final TicketType<V> removeType, final int removeLevel, final V removeIdentifier) {
final ReentrantAreaLock.Node ticketLock = this.ticketLockArea.lock(CoordinateUtils.getChunkX(chunk), CoordinateUtils.getChunkZ(chunk)); final ReentrantAreaLock.Node ticketLock = this.ticketLockArea.lock(CoordinateUtils.getChunkX(chunk), CoordinateUtils.getChunkZ(chunk));
try { try {
this.addTicketAtLevel(addType, chunk, addLevel, addIdentifier, false); this.addTicketAtLevel(addType, chunk, addLevel, addIdentifier, false);
@@ -735,8 +650,8 @@ public final class ChunkHolderManager {
} }
// atomic with respect to all add/remove/addandremove ticket calls for the given chunk // atomic with respect to all add/remove/addandremove ticket calls for the given chunk
public <T, V> boolean addIfRemovedTicket(final long chunk, final TicketType addType, final int addLevel, final T addIdentifier, public <T, V> boolean addIfRemovedTicket(final long chunk, final TicketType<T> addType, final int addLevel, final T addIdentifier,
final TicketType removeType, final int removeLevel, final V removeIdentifier) { final TicketType<V> removeType, final int removeLevel, final V removeIdentifier) {
final ReentrantAreaLock.Node ticketLock = this.ticketLockArea.lock(CoordinateUtils.getChunkX(chunk), CoordinateUtils.getChunkZ(chunk)); final ReentrantAreaLock.Node ticketLock = this.ticketLockArea.lock(CoordinateUtils.getChunkX(chunk), CoordinateUtils.getChunkZ(chunk));
try { try {
if (this.removeTicketAtLevel(removeType, chunk, removeLevel, removeIdentifier, false)) { if (this.removeTicketAtLevel(removeType, chunk, removeLevel, removeIdentifier, false)) {
@@ -749,7 +664,7 @@ public final class ChunkHolderManager {
} }
} }
public <T> void removeAllTicketsFor(final TicketType ticketType, final int ticketLevel, final T ticketIdentifier) { public <T> void removeAllTicketsFor(final TicketType<T> ticketType, final int ticketLevel, final T ticketIdentifier) {
if (ticketLevel > MAX_TICKET_LEVEL) { if (ticketLevel > MAX_TICKET_LEVEL) {
return; return;
} }
@@ -795,7 +710,7 @@ public final class ChunkHolderManager {
final int sectionShift = ((ChunkSystemServerLevel)this.world).moonrise$getRegionChunkShift(); final int sectionShift = ((ChunkSystemServerLevel)this.world).moonrise$getRegionChunkShift();
final Predicate<Ticket> expireNow = (final Ticket ticket) -> { final Predicate<Ticket<?>> expireNow = (final Ticket<?> ticket) -> {
long removeDelay = ((ChunkSystemTicket<?>)(Object)ticket).moonrise$getRemoveDelay(); long removeDelay = ((ChunkSystemTicket<?>)(Object)ticket).moonrise$getRemoveDelay();
if (removeDelay == NO_TIMEOUT_MARKER) { if (removeDelay == NO_TIMEOUT_MARKER) {
return false; return false;
@@ -831,7 +746,7 @@ public final class ChunkHolderManager {
final long chunkKey = entry.getLongKey(); final long chunkKey = entry.getLongKey();
final int expireCount = entry.getIntValue(); final int expireCount = entry.getIntValue();
final SortedArraySet<Ticket> tickets = this.tickets.get(chunkKey); final SortedArraySet<Ticket<?>> tickets = this.tickets.get(chunkKey);
final int levelBefore = getTicketLevelAt(tickets); final int levelBefore = getTicketLevelAt(tickets);
final int sizeBefore = tickets.size(); final int sizeBefore = tickets.size();
@@ -1249,7 +1164,7 @@ public final class ChunkHolderManager {
this.removeChunkHolder(holder); this.removeChunkHolder(holder);
} else { } else {
// add cooldown so the next unload check is not immediately next tick // add cooldown so the next unload check is not immediately next tick
this.addTicketAtLevel(UNLOAD_COOLDOWN, CoordinateUtils.getChunkKey(holder.chunkX, holder.chunkZ), MAX_TICKET_LEVEL, null, false); this.addTicketAtLevel(UNLOAD_COOLDOWN, CoordinateUtils.getChunkKey(holder.chunkX, holder.chunkZ), MAX_TICKET_LEVEL, Unit.INSTANCE, false);
} }
} }
} finally { } finally {
@@ -1273,42 +1188,42 @@ public final class ChunkHolderManager {
public static record TicketOperation<T, V> ( public static record TicketOperation<T, V> (
TicketOperationType op, long chunkCoord, TicketOperationType op, long chunkCoord,
TicketType ticketType, int ticketLevel, T identifier, TicketType<T> ticketType, int ticketLevel, T identifier,
TicketType ticketType2, int ticketLevel2, V identifier2 TicketType<V> ticketType2, int ticketLevel2, V identifier2
) { ) {
private TicketOperation(TicketOperationType op, long chunkCoord, private TicketOperation(TicketOperationType op, long chunkCoord,
TicketType ticketType, int ticketLevel, T identifier) { TicketType<T> ticketType, int ticketLevel, T identifier) {
this(op, chunkCoord, ticketType, ticketLevel, identifier, null, 0, null); this(op, chunkCoord, ticketType, ticketLevel, identifier, null, 0, null);
} }
public static <T> TicketOperation<T, T> addOp(final ChunkPos chunk, final TicketType type, final int ticketLevel, final T identifier) { public static <T> TicketOperation<T, T> addOp(final ChunkPos chunk, final TicketType<T> type, final int ticketLevel, final T identifier) {
return addOp(CoordinateUtils.getChunkKey(chunk), type, ticketLevel, identifier); return addOp(CoordinateUtils.getChunkKey(chunk), type, ticketLevel, identifier);
} }
public static <T> TicketOperation<T, T> addOp(final int chunkX, final int chunkZ, final TicketType type, final int ticketLevel, final T identifier) { public static <T> TicketOperation<T, T> addOp(final int chunkX, final int chunkZ, final TicketType<T> type, final int ticketLevel, final T identifier) {
return addOp(CoordinateUtils.getChunkKey(chunkX, chunkZ), type, ticketLevel, identifier); return addOp(CoordinateUtils.getChunkKey(chunkX, chunkZ), type, ticketLevel, identifier);
} }
public static <T> TicketOperation<T, T> addOp(final long chunk, final TicketType type, final int ticketLevel, final T identifier) { public static <T> TicketOperation<T, T> addOp(final long chunk, final TicketType<T> type, final int ticketLevel, final T identifier) {
return new TicketOperation<>(TicketOperationType.ADD, chunk, type, ticketLevel, identifier); return new TicketOperation<>(TicketOperationType.ADD, chunk, type, ticketLevel, identifier);
} }
public static <T> TicketOperation<T, T> removeOp(final ChunkPos chunk, final TicketType type, final int ticketLevel, final T identifier) { public static <T> TicketOperation<T, T> removeOp(final ChunkPos chunk, final TicketType<T> type, final int ticketLevel, final T identifier) {
return removeOp(CoordinateUtils.getChunkKey(chunk), type, ticketLevel, identifier); return removeOp(CoordinateUtils.getChunkKey(chunk), type, ticketLevel, identifier);
} }
public static <T> TicketOperation<T, T> removeOp(final int chunkX, final int chunkZ, final TicketType type, final int ticketLevel, final T identifier) { public static <T> TicketOperation<T, T> removeOp(final int chunkX, final int chunkZ, final TicketType<T> type, final int ticketLevel, final T identifier) {
return removeOp(CoordinateUtils.getChunkKey(chunkX, chunkZ), type, ticketLevel, identifier); return removeOp(CoordinateUtils.getChunkKey(chunkX, chunkZ), type, ticketLevel, identifier);
} }
public static <T> TicketOperation<T, T> removeOp(final long chunk, final TicketType type, final int ticketLevel, final T identifier) { public static <T> TicketOperation<T, T> removeOp(final long chunk, final TicketType<T> type, final int ticketLevel, final T identifier) {
return new TicketOperation<>(TicketOperationType.REMOVE, chunk, type, ticketLevel, identifier); return new TicketOperation<>(TicketOperationType.REMOVE, chunk, type, ticketLevel, identifier);
} }
public static <T, V> TicketOperation<T, V> addIfRemovedOp(final long chunk, public static <T, V> TicketOperation<T, V> addIfRemovedOp(final long chunk,
final TicketType addType, final int addLevel, final T addIdentifier, final TicketType<T> addType, final int addLevel, final T addIdentifier,
final TicketType removeType, final int removeLevel, final V removeIdentifier) { final TicketType<V> removeType, final int removeLevel, final V removeIdentifier) {
return new TicketOperation<>( return new TicketOperation<>(
TicketOperationType.ADD_IF_REMOVED, chunk, addType, addLevel, addIdentifier, TicketOperationType.ADD_IF_REMOVED, chunk, addType, addLevel, addIdentifier,
removeType, removeLevel, removeIdentifier removeType, removeLevel, removeIdentifier
@@ -1316,8 +1231,8 @@ public final class ChunkHolderManager {
} }
public static <T, V> TicketOperation<T, V> addAndRemove(final long chunk, public static <T, V> TicketOperation<T, V> addAndRemove(final long chunk,
final TicketType addType, final int addLevel, final T addIdentifier, final TicketType<T> addType, final int addLevel, final T addIdentifier,
final TicketType removeType, final int removeLevel, final V removeIdentifier) { final TicketType<V> removeType, final int removeLevel, final V removeIdentifier) {
return new TicketOperation<>( return new TicketOperation<>(
TicketOperationType.ADD_AND_REMOVE, chunk, addType, addLevel, addIdentifier, TicketOperationType.ADD_AND_REMOVE, chunk, addType, addLevel, addIdentifier,
removeType, removeLevel, removeIdentifier removeType, removeLevel, removeIdentifier
@@ -1476,11 +1391,11 @@ public final class ChunkHolderManager {
final JsonArray allTicketsJson = new JsonArray(); final JsonArray allTicketsJson = new JsonArray();
ret.add("tickets", allTicketsJson); ret.add("tickets", allTicketsJson);
for (final Iterator<ConcurrentLong2ReferenceChainedHashTable.TableEntry<SortedArraySet<Ticket>>> iterator = this.tickets.entryIterator(); for (final Iterator<ConcurrentLong2ReferenceChainedHashTable.TableEntry<SortedArraySet<Ticket<?>>>> iterator = this.tickets.entryIterator();
iterator.hasNext();) { iterator.hasNext();) {
final ConcurrentLong2ReferenceChainedHashTable.TableEntry<SortedArraySet<Ticket>> coordinateTickets = iterator.next(); final ConcurrentLong2ReferenceChainedHashTable.TableEntry<SortedArraySet<Ticket<?>>> coordinateTickets = iterator.next();
final long coordinate = coordinateTickets.getKey(); final long coordinate = coordinateTickets.getKey();
final SortedArraySet<Ticket> tickets = coordinateTickets.getValue(); final SortedArraySet<Ticket<?>> tickets = coordinateTickets.getValue();
final JsonObject coordinateJson = new JsonObject(); final JsonObject coordinateJson = new JsonObject();
allTicketsJson.add(coordinateJson); allTicketsJson.add(coordinateJson);
@@ -1495,17 +1410,17 @@ public final class ChunkHolderManager {
// directly over the set using the iterator // directly over the set using the iterator
// however, it also means we need to null-check the values, and there is a possibility that we _miss_ an // however, it also means we need to null-check the values, and there is a possibility that we _miss_ an
// entry OR iterate over an entry multiple times // entry OR iterate over an entry multiple times
for (final Object ticketUncasted : ((ChunkSystemSortedArraySet<Ticket>)tickets).moonrise$copyBackingArray()) { for (final Object ticketUncasted : ((ChunkSystemSortedArraySet<Ticket<?>>)tickets).moonrise$copyBackingArray()) {
if (ticketUncasted == null) { if (ticketUncasted == null) {
continue; continue;
} }
final Ticket ticket = (Ticket)ticketUncasted; final Ticket<?> ticket = (Ticket<?>)ticketUncasted;
final JsonObject ticketSerialized = new JsonObject(); final JsonObject ticketSerialized = new JsonObject();
ticketsSerialized.add(ticketSerialized); ticketsSerialized.add(ticketSerialized);
ticketSerialized.addProperty("type", ticket.getType().toString()); ticketSerialized.addProperty("type", ticket.getType().toString());
ticketSerialized.addProperty("level", Integer.valueOf(ticket.getTicketLevel())); ticketSerialized.addProperty("level", Integer.valueOf(ticket.getTicketLevel()));
ticketSerialized.addProperty("identifier", Objects.toString(((ChunkSystemTicket<?>)(Object)ticket).moonrise$getIdentifier())); ticketSerialized.addProperty("identifier", Objects.toString(ticket.key));
ticketSerialized.addProperty("remove_tick", Long.valueOf(((ChunkSystemTicket<?>)(Object)ticket).moonrise$getRemoveDelay())); ticketSerialized.addProperty("remove_tick", Long.valueOf(((ChunkSystemTicket<?>)(Object)ticket).moonrise$getRemoveDelay()));
} }
} }

View File

@@ -22,7 +22,6 @@ import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.task.ChunkProgres
import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.task.ChunkUpgradeGenericStatusTask; import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.task.ChunkUpgradeGenericStatusTask;
import ca.spottedleaf.moonrise.patches.chunk_system.server.ChunkSystemMinecraftServer; import ca.spottedleaf.moonrise.patches.chunk_system.server.ChunkSystemMinecraftServer;
import ca.spottedleaf.moonrise.patches.chunk_system.status.ChunkSystemChunkStep; import ca.spottedleaf.moonrise.patches.chunk_system.status.ChunkSystemChunkStep;
import ca.spottedleaf.moonrise.patches.chunk_system.ticket.ChunkSystemTicketType;
import ca.spottedleaf.moonrise.patches.chunk_system.util.ParallelSearchRadiusIteration; import ca.spottedleaf.moonrise.patches.chunk_system.util.ParallelSearchRadiusIteration;
import com.google.gson.JsonArray; import com.google.gson.JsonArray;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
@@ -74,35 +73,35 @@ public final class ChunkTaskScheduler {
LOGGER.info("Chunk system is using population gen parallelism: " + useParallelGen); LOGGER.info("Chunk system is using population gen parallelism: " + useParallelGen);
} }
public static final TicketType CHUNK_LOAD = ChunkSystemTicketType.create("chunk_system:chunk_load", Long::compareTo); public static final TicketType<Long> CHUNK_LOAD = TicketType.create("chunk_system:chunk_load", Long::compareTo);
private static final AtomicLong CHUNK_LOAD_IDS = new AtomicLong(); private static final AtomicLong CHUNK_LOAD_IDS = new AtomicLong();
public static Long getNextChunkLoadId() { public static Long getNextChunkLoadId() {
return Long.valueOf(CHUNK_LOAD_IDS.getAndIncrement()); return Long.valueOf(CHUNK_LOAD_IDS.getAndIncrement());
} }
public static final TicketType NON_FULL_CHUNK_LOAD = ChunkSystemTicketType.create("chunk_system:non_full_load", Long::compareTo); public static final TicketType<Long> NON_FULL_CHUNK_LOAD = TicketType.create("chunk_system:non_full_load", Long::compareTo);
private static final AtomicLong NON_FULL_CHUNK_LOAD_IDS = new AtomicLong(); private static final AtomicLong NON_FULL_CHUNK_LOAD_IDS = new AtomicLong();
public static Long getNextNonFullLoadId() { public static Long getNextNonFullLoadId() {
return Long.valueOf(NON_FULL_CHUNK_LOAD_IDS.getAndIncrement()); return Long.valueOf(NON_FULL_CHUNK_LOAD_IDS.getAndIncrement());
} }
public static final TicketType ENTITY_LOAD = ChunkSystemTicketType.create("chunk_system:entity_load", Long::compareTo); public static final TicketType<Long> ENTITY_LOAD = TicketType.create("chunk_system:entity_load", Long::compareTo);
private static final AtomicLong ENTITY_LOAD_IDS = new AtomicLong(); private static final AtomicLong ENTITY_LOAD_IDS = new AtomicLong();
public static Long getNextEntityLoadId() { public static Long getNextEntityLoadId() {
return Long.valueOf(ENTITY_LOAD_IDS.getAndIncrement()); return Long.valueOf(ENTITY_LOAD_IDS.getAndIncrement());
} }
public static final TicketType POI_LOAD = ChunkSystemTicketType.create("chunk_system:poi_load", Long::compareTo); public static final TicketType<Long> POI_LOAD = TicketType.create("chunk_system:poi_load", Long::compareTo);
private static final AtomicLong POI_LOAD_IDS = new AtomicLong(); private static final AtomicLong POI_LOAD_IDS = new AtomicLong();
public static Long getNextPoiLoadId() { public static Long getNextPoiLoadId() {
return Long.valueOf(POI_LOAD_IDS.getAndIncrement()); return Long.valueOf(POI_LOAD_IDS.getAndIncrement());
} }
public static final TicketType CHUNK_RELIGHT = ChunkSystemTicketType.create("starlight:chunk_relight", Long::compareTo); public static final TicketType<Long> CHUNK_RELIGHT = TicketType.create("starlight:chunk_relight", Long::compareTo);
private static final AtomicLong CHUNK_RELIGHT_IDS = new AtomicLong(); private static final AtomicLong CHUNK_RELIGHT_IDS = new AtomicLong();
public static Long getNextChunkRelightId() { public static Long getNextChunkRelightId() {

View File

@@ -117,11 +117,9 @@ public final class NewChunkHolder {
if (!transientChunk) { if (!transientChunk) {
if (entityChunk != null) { if (entityChunk != null) {
final ChunkPos pos = new ChunkPos(this.chunkX, this.chunkZ); final List<Entity> entities = ChunkEntitySlices.readEntities(this.world, entityChunk);
final List<Entity> entities = ChunkEntitySlices.readEntities(this.world, pos, entityChunk); ((ChunkSystemServerLevel)this.world).moonrise$getEntityLookup().addEntityChunkEntities(entities, new ChunkPos(this.chunkX, this.chunkZ));
((ChunkSystemServerLevel)this.world).moonrise$getEntityLookup().addEntityChunkEntities(entities, pos);
} }
} }

View File

@@ -70,7 +70,7 @@ public final class ChunkFullTask extends ChunkProgressionTask implements Runnabl
this.chunkHolder.replaceProtoChunk(new ImposterProtoChunk(chunk, false)); this.chunkHolder.replaceProtoChunk(new ImposterProtoChunk(chunk, false));
} }
((ChunkSystemLevelChunk)chunk).moonrise$setChunkHolder(this.chunkHolder); ((ChunkSystemLevelChunk)chunk).moonrise$setChunkAndHolder(new ServerChunkCache.ChunkAndHolder(chunk, this.chunkHolder.vanillaChunkHolder));
final NewChunkHolder chunkHolder = this.chunkHolder; final NewChunkHolder chunkHolder = this.chunkHolder;

View File

@@ -6,8 +6,4 @@ public interface ChunkSystemTicket<T> {
public void moonrise$setRemoveDelay(final long removeDelay); public void moonrise$setRemoveDelay(final long removeDelay);
public T moonrise$getIdentifier();
public void moonrise$setIdentifier(final T identifier);
} }

View File

@@ -1,11 +0,0 @@
package ca.spottedleaf.moonrise.patches.chunk_system.ticket;
import net.minecraft.server.level.ChunkMap;
public interface ChunkSystemTicketStorage {
public ChunkMap moonrise$getChunkMap();
public void moonrise$setChunkMap(final ChunkMap chunkMap);
}

View File

@@ -1,33 +0,0 @@
package ca.spottedleaf.moonrise.patches.chunk_system.ticket;
import net.minecraft.server.level.TicketType;
import java.util.Comparator;
public interface ChunkSystemTicketType<T> {
public static final long COUNTER_TYPE_FORCED = 0L;
// used only by neoforge
public static final long COUNTER_TYPER_NATURAL_SPAWNING_FORCED = 1L;
public static <T> TicketType create(final String name, final Comparator<T> identifierComparator) {
return create(name, identifierComparator, 0L);
}
public static <T> TicketType create(final String name, final Comparator<T> identifierComparator, final long timeout) {
// note: cannot persist unless registered
final TicketType ret = new TicketType(timeout, false, TicketType.TicketUse.LOADING_AND_SIMULATION);
((ChunkSystemTicketType<T>)(Object)ret).moonrise$setIdentifierComparator(identifierComparator);
return ret;
}
public long moonrise$getId();
public Comparator<T> moonrise$getIdentifierComparator();
public void moonrise$setIdentifierComparator(final Comparator<T> comparator);
public long[] moonrise$getCounterTypes();
}

View File

@@ -3,13 +3,5 @@ package ca.spottedleaf.moonrise.patches.chunk_tick_iteration;
public final class ChunkTickConstants { public final class ChunkTickConstants {
public static final int PLAYER_SPAWN_TRACK_RANGE = 8; public static final int PLAYER_SPAWN_TRACK_RANGE = 8;
// the smallest distance on x/z is at 45 degrees, we need to subtract 0.5 since this is calculated from chunk center and not chunk perimeter
// note: vanilla does not subtract 0.5 but the result is (luckily!) the same
public static final int NARROW_SPAWN_TRACK_RANGE = (int)Math.floor(((double)PLAYER_SPAWN_TRACK_RANGE / Math.sqrt(2.0)) - 0.5);
static {
if (NARROW_SPAWN_TRACK_RANGE < 0) {
throw new IllegalStateException();
}
}
} }

View File

@@ -13,6 +13,4 @@ public interface ChunkTickDistanceManager {
final SectionPos oldPos, final SectionPos newPos, final SectionPos oldPos, final SectionPos newPos,
final boolean oldIgnore, final boolean newIgnore); final boolean oldIgnore, final boolean newIgnore);
public boolean moonrise$hasAnyNearbyNarrow(final int chunkX, final int chunkZ);
} }

View File

@@ -6,7 +6,7 @@ import net.minecraft.world.level.chunk.LevelChunk;
public interface ChunkTickServerLevel { public interface ChunkTickServerLevel {
public ReferenceList<LevelChunk> moonrise$getPlayerTickingChunks(); public ReferenceList<ServerChunkCache.ChunkAndHolder> moonrise$getPlayerTickingChunks();
public void moonrise$markChunkForPlayerTicking(final LevelChunk chunk); public void moonrise$markChunkForPlayerTicking(final LevelChunk chunk);

View File

@@ -2004,10 +2004,11 @@ public final class CollisionUtil {
VoxelShape blockCollision = ((CollisionBlockState)blockData).moonrise$getConstantContextCollisionShape(); VoxelShape blockCollision = ((CollisionBlockState)blockData).moonrise$getConstantContextCollisionShape();
if (edgeCount == 0 || ((edgeCount != 1 || blockData.hasLargeCollisionShape()) && (edgeCount != 2 || blockData.getBlock() == Blocks.MOVING_PISTON))) { if (edgeCount == 0 || ((edgeCount != 1 || blockData.hasLargeCollisionShape()) && (edgeCount != 2 || blockData.getBlock() == Blocks.MOVING_PISTON))) {
mutablePos.set(blockX, blockY, blockZ);
if (useEntityCollisionShape) { if (useEntityCollisionShape) {
mutablePos.set(blockX, blockY, blockZ);
blockCollision = collisionShape.getCollisionShape(blockData, world, mutablePos); blockCollision = collisionShape.getCollisionShape(blockData, world, mutablePos);
} else if (blockCollision == null) { } else if (blockCollision == null) {
mutablePos.set(blockX, blockY, blockZ);
blockCollision = blockData.getCollisionShape(world, mutablePos, collisionShape); blockCollision = blockData.getCollisionShape(world, mutablePos, collisionShape);
} }
@@ -2019,6 +2020,7 @@ public final class CollisionUtil {
} }
if (predicate != null) { if (predicate != null) {
mutablePos.set(blockX, blockY, blockZ);
if (!predicate.test(blockData, mutablePos)) { if (!predicate.test(blockData, mutablePos)) {
continue; continue;
} }
@@ -2044,6 +2046,7 @@ public final class CollisionUtil {
} }
if (predicate != null) { if (predicate != null) {
mutablePos.set(blockX, blockY, blockZ);
if (!predicate.test(blockData, mutablePos)) { if (!predicate.test(blockData, mutablePos)) {
continue; continue;
} }
@@ -2091,7 +2094,7 @@ public final class CollisionUtil {
continue; continue;
} }
if ((entity == null && otherEntity.canBeCollidedWith(entity)) || (entity != null && entity.canCollideWith(otherEntity))) { if ((entity == null && otherEntity.canBeCollidedWith()) || (entity != null && entity.canCollideWith(otherEntity))) {
if (checkOnly) { if (checkOnly) {
return true; return true;
} else { } else {
@@ -2123,7 +2126,7 @@ public final class CollisionUtil {
private boolean delegated; private boolean delegated;
public LazyEntityCollisionContext(final Entity entity) { public LazyEntityCollisionContext(final Entity entity) {
super(false, false, 0.0, null, null, entity); super(false, 0.0, null, null, entity);
} }
public static boolean useEntityCollisionShape(final Level world, final Entity entity) { public static boolean useEntityCollisionShape(final Level world, final Entity entity) {
@@ -2153,11 +2156,6 @@ public final class CollisionUtil {
return this.getDelegate().isDescending(); return this.getDelegate().isDescending();
} }
@Override
public boolean isPlacement() {
return this.getDelegate().isPlacement();
}
@Override @Override
public boolean isAbove(final VoxelShape shape, final BlockPos pos, final boolean defaultValue) { public boolean isAbove(final VoxelShape shape, final BlockPos pos, final boolean defaultValue) {
return this.getDelegate().isAbove(shape, pos, defaultValue); return this.getDelegate().isAbove(shape, pos, defaultValue);

View File

@@ -182,7 +182,7 @@ public abstract class StarLightEngine {
for (int dx = -radius; dx <= radius; ++dx) { for (int dx = -radius; dx <= radius; ++dx) {
final int cx = centerChunkX + dx; final int cx = centerChunkX + dx;
final int cz = centerChunkZ + dz; final int cz = centerChunkZ + dz;
final boolean isTwoRadius = Math.max(Math.abs(dx), Math.abs(dz)) == 2; final boolean isTwoRadius = Math.max(IntegerUtil.branchlessAbs(dx), IntegerUtil.branchlessAbs(dz)) == 2;
final ChunkAccess chunk = (ChunkAccess)chunkProvider.getChunkForLighting(cx, cz); final ChunkAccess chunk = (ChunkAccess)chunkProvider.getChunkForLighting(cx, cz);
if (chunk == null) { if (chunk == null) {

View File

@@ -9,7 +9,6 @@ import ca.spottedleaf.moonrise.common.util.WorldUtil;
import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemLevel; import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemLevel;
import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel; import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel;
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkSystemChunkStatus; import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkSystemChunkStatus;
import ca.spottedleaf.moonrise.patches.chunk_system.ticket.ChunkSystemTicketType;
import ca.spottedleaf.moonrise.patches.starlight.chunk.StarlightChunk; import ca.spottedleaf.moonrise.patches.starlight.chunk.StarlightChunk;
import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap;
import it.unimi.dsi.fastutil.shorts.ShortCollection; import it.unimi.dsi.fastutil.shorts.ShortCollection;
@@ -40,8 +39,10 @@ import java.util.function.IntConsumer;
public final class StarLightInterface { public final class StarLightInterface {
public static final TicketType CHUNK_WORK_TICKET = ChunkSystemTicketType.create("starlight:chunk_work_ticket", Long::compareTo); public static final TicketType<Long> CHUNK_WORK_TICKET = TicketType.create("starlight:chunk_work_ticket", Long::compareTo);
public static final int LIGHT_TICKET_LEVEL = ChunkLevel.byStatus(ChunkStatus.LIGHT); public static final int LIGHT_TICKET_LEVEL = ChunkLevel.byStatus(ChunkStatus.LIGHT);
// ticket level = ChunkLevel.byStatus(FullChunkStatus.FULL) - input
public static final int REGION_LIGHT_TICKET_LEVEL = ChunkLevel.byStatus(FullChunkStatus.FULL) - LIGHT_TICKET_LEVEL;
/** /**
* Can be {@code null}, indicating the light is all empty. * Can be {@code null}, indicating the light is all empty.

View File

@@ -56,18 +56,15 @@ public final class SaveUtil {
tag.putBoolean("isLightOn", false); tag.putBoolean("isLightOn", false);
} }
// diff end - store our tag for whether light data is init'd // diff end - store our tag for whether light data is init'd
ChunkStatus status = tag.read("Status", ChunkStatus.CODEC).orElse(ChunkStatus.EMPTY); ChunkStatus status = ChunkStatus.byName(tag.getString("Status"));
CompoundTag[] sections = new CompoundTag[maxSection - minSection + 1]; CompoundTag[] sections = new CompoundTag[maxSection - minSection + 1];
ListTag sectionsStored = tag.getListOrEmpty("sections"); ListTag sectionsStored = tag.getList("sections", 10);
for (int i = 0; i < sectionsStored.size(); ++i) { for (int i = 0; i < sectionsStored.size(); ++i) {
CompoundTag sectionStored = sectionsStored.getCompound(i).orElse(null); CompoundTag sectionStored = sectionsStored.getCompound(i);
if (sectionStored == null) { int k = sectionStored.getByte("Y");
continue;
}
int k = sectionStored.getByteOr("Y", (byte)0);
// strip light data // strip light data
sectionStored.remove("BlockLight"); sectionStored.remove("BlockLight");
@@ -150,38 +147,33 @@ public final class SaveUtil {
// start copy from the original method // start copy from the original method
boolean lit = tag.get("isLightOn") != null && tag.getIntOr(STARLIGHT_VERSION_TAG, -1) == STARLIGHT_LIGHT_VERSION; boolean lit = tag.get("isLightOn") != null && tag.getInt(STARLIGHT_VERSION_TAG) == STARLIGHT_LIGHT_VERSION;
boolean canReadSky = world.dimensionType().hasSkyLight(); boolean canReadSky = world.dimensionType().hasSkyLight();
ChunkStatus status = tag.read("Status", ChunkStatus.CODEC).orElse(ChunkStatus.EMPTY); ChunkStatus status = ChunkStatus.byName(tag.getString("Status"));
if (lit && status.isOrAfter(ChunkStatus.LIGHT)) { // diff - we add the status check here if (lit && status.isOrAfter(ChunkStatus.LIGHT)) { // diff - we add the status check here
ListTag sections = tag.getListOrEmpty("sections"); ListTag sections = tag.getList("sections", 10);
for (int i = 0; i < sections.size(); ++i) { for (int i = 0; i < sections.size(); ++i) {
CompoundTag sectionData = sections.getCompound(i).orElse(null); CompoundTag sectionData = sections.getCompound(i);
if (sectionData == null) { int y = sectionData.getByte("Y");
continue;
}
int y = sectionData.getByteOr("Y", (byte)0);
final byte[] blockLight = sectionData.getByteArray("BlockLight").orElse(null); if (sectionData.contains("BlockLight", 7)) {
if (blockLight != null) {
// this is where our diff is // this is where our diff is
blockNibbles[y - minSection] = new SWMRNibbleArray(blockLight.clone(), sectionData.getIntOr(BLOCKLIGHT_STATE_TAG, 0)); // clone for data safety blockNibbles[y - minSection] = new SWMRNibbleArray(sectionData.getByteArray("BlockLight").clone(), sectionData.getInt(BLOCKLIGHT_STATE_TAG)); // clone for data safety
} else { } else {
blockNibbles[y - minSection] = new SWMRNibbleArray(null, sectionData.getIntOr(BLOCKLIGHT_STATE_TAG, 0)); blockNibbles[y - minSection] = new SWMRNibbleArray(null, sectionData.getInt(BLOCKLIGHT_STATE_TAG));
} }
if (canReadSky) { if (canReadSky) {
final byte[] skyLight = sectionData.getByteArray("SkyLight").orElse(null); if (sectionData.contains("SkyLight", 7)) {
if (skyLight != null) {
// we store under the same key so mod programs editing nbt // we store under the same key so mod programs editing nbt
// can still read the data, hopefully. // can still read the data, hopefully.
// however, for compatibility we store chunks as unlit so vanilla // however, for compatibility we store chunks as unlit so vanilla
// is forced to re-light them if it encounters our data. It's too much of a burden // is forced to re-light them if it encounters our data. It's too much of a burden
// to try and maintain compatibility with a broken and inferior skylight management system. // to try and maintain compatibility with a broken and inferior skylight management system.
skyNibbles[y - minSection] = new SWMRNibbleArray(skyLight.clone(), sectionData.getIntOr(SKYLIGHT_STATE_TAG, 0)); // clone for data safety skyNibbles[y - minSection] = new SWMRNibbleArray(sectionData.getByteArray("SkyLight").clone(), sectionData.getInt(SKYLIGHT_STATE_TAG)); // clone for data safety
} else { } else {
skyNibbles[y - minSection] = new SWMRNibbleArray(null, sectionData.getIntOr(SKYLIGHT_STATE_TAG, 0)); skyNibbles[y - minSection] = new SWMRNibbleArray(null, sectionData.getInt(SKYLIGHT_STATE_TAG));
} }
} }
} }

View File

@@ -177,7 +177,7 @@ accessible method net/minecraft/server/network/PlayerChunkSender sendChunk (Lnet
# ChunkStatusTasks # ChunkStatusTasks
accessible method net/minecraft/world/level/chunk/status/ChunkStatusTasks postLoadProtoChunk (Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/level/storage/ValueInput$ValueInputList;)V accessible method net/minecraft/world/level/chunk/status/ChunkStatusTasks postLoadProtoChunk (Lnet/minecraft/server/level/ServerLevel;Ljava/util/List;)V
accessible method net/minecraft/world/level/chunk/status/ChunkStatusTasks light (Lnet/minecraft/world/level/chunk/status/WorldGenContext;Lnet/minecraft/world/level/chunk/status/ChunkStep;Lnet/minecraft/util/StaticCache2D;Lnet/minecraft/world/level/chunk/ChunkAccess;)Ljava/util/concurrent/CompletableFuture; accessible method net/minecraft/world/level/chunk/status/ChunkStatusTasks light (Lnet/minecraft/world/level/chunk/status/WorldGenContext;Lnet/minecraft/world/level/chunk/status/ChunkStep;Lnet/minecraft/util/StaticCache2D;Lnet/minecraft/world/level/chunk/ChunkAccess;)Ljava/util/concurrent/CompletableFuture;
@@ -194,8 +194,9 @@ accessible class net/minecraft/server/level/ChunkMap$DistanceManager
# DistanceManager # DistanceManager
mutable field net/minecraft/server/level/DistanceManager playersPerChunk Lit/unimi/dsi/fastutil/longs/Long2ObjectMap; mutable field net/minecraft/server/level/DistanceManager playersPerChunk Lit/unimi/dsi/fastutil/longs/Long2ObjectMap;
mutable field net/minecraft/server/level/DistanceManager loadingChunkTracker Lnet/minecraft/server/level/LoadingChunkTracker; mutable field net/minecraft/server/level/DistanceManager tickets Lit/unimi/dsi/fastutil/longs/Long2ObjectOpenHashMap;
mutable field net/minecraft/server/level/DistanceManager simulationChunkTracker Lnet/minecraft/server/level/SimulationChunkTracker; mutable field net/minecraft/server/level/DistanceManager ticketTracker Lnet/minecraft/server/level/DistanceManager$ChunkTicketTracker;
mutable field net/minecraft/server/level/DistanceManager tickingTicketsTracker Lnet/minecraft/server/level/TickingTracker;
mutable field net/minecraft/server/level/DistanceManager playerTicketManager Lnet/minecraft/server/level/DistanceManager$PlayerTicketTracker; mutable field net/minecraft/server/level/DistanceManager playerTicketManager Lnet/minecraft/server/level/DistanceManager$PlayerTicketTracker;
mutable field net/minecraft/server/level/DistanceManager chunksToUpdateFutures Ljava/util/Set; mutable field net/minecraft/server/level/DistanceManager chunksToUpdateFutures Ljava/util/Set;
mutable field net/minecraft/server/level/DistanceManager ticketDispatcher Lnet/minecraft/server/level/ThrottlingChunkTaskDispatcher; mutable field net/minecraft/server/level/DistanceManager ticketDispatcher Lnet/minecraft/server/level/ThrottlingChunkTaskDispatcher;
@@ -204,6 +205,10 @@ mutable field net/minecraft/server/level/DistanceManager mainThreadExecutor Ljav
mutable field net/minecraft/server/level/DistanceManager naturalSpawnChunkCounter Lnet/minecraft/server/level/DistanceManager$FixedPlayerDistanceChunkTracker; mutable field net/minecraft/server/level/DistanceManager naturalSpawnChunkCounter Lnet/minecraft/server/level/DistanceManager$FixedPlayerDistanceChunkTracker;
# DistanceManager$ChunkTicketTracker
accessible class net/minecraft/server/level/DistanceManager$ChunkTicketTracker
# DistanceManager$PlayerTicketTracker # DistanceManager$PlayerTicketTracker
accessible class net/minecraft/server/level/DistanceManager$PlayerTicketTracker accessible class net/minecraft/server/level/DistanceManager$PlayerTicketTracker
@@ -212,6 +217,11 @@ accessible class net/minecraft/server/level/DistanceManager$PlayerTicketTracker
accessible class net/minecraft/server/level/DistanceManager$FixedPlayerDistanceChunkTracker accessible class net/minecraft/server/level/DistanceManager$FixedPlayerDistanceChunkTracker
# Ticket
accessible field net/minecraft/server/level/Ticket key Ljava/lang/Object;
accessible field net/minecraft/server/level/TicketType timeout J
# ServerChunkCache # ServerChunkCache
accessible method net/minecraft/server/level/ServerChunkCache runDistanceManagerUpdates ()Z accessible method net/minecraft/server/level/ServerChunkCache runDistanceManagerUpdates ()Z
accessible field net/minecraft/server/level/ServerChunkCache level Lnet/minecraft/server/level/ServerLevel; accessible field net/minecraft/server/level/ServerChunkCache level Lnet/minecraft/server/level/ServerLevel;
@@ -231,6 +241,14 @@ accessible class net/minecraft/server/level/ServerLevel$EntityCallbacks
accessible method net/minecraft/server/level/ServerLevel$EntityCallbacks <init> (Lnet/minecraft/server/level/ServerLevel;)V accessible method net/minecraft/server/level/ServerLevel$EntityCallbacks <init> (Lnet/minecraft/server/level/ServerLevel;)V
# EntityStorage
accessible method net/minecraft/world/level/chunk/storage/EntityStorage readChunkPos (Lnet/minecraft/nbt/CompoundTag;)Lnet/minecraft/world/level/ChunkPos;
accessible method net/minecraft/world/level/chunk/storage/EntityStorage writeChunkPos (Lnet/minecraft/nbt/CompoundTag;Lnet/minecraft/world/level/ChunkPos;)V
# Ticket
accessible method net/minecraft/server/level/Ticket <init> (Lnet/minecraft/server/level/TicketType;ILjava/lang/Object;)V
# ChunkStorage # ChunkStorage
accessible field net/minecraft/world/level/chunk/storage/ChunkStorage worker Lnet/minecraft/world/level/chunk/storage/IOWorker; accessible field net/minecraft/world/level/chunk/storage/ChunkStorage worker Lnet/minecraft/world/level/chunk/storage/IOWorker;
mutable field net/minecraft/world/level/chunk/storage/ChunkStorage worker Lnet/minecraft/world/level/chunk/storage/IOWorker; mutable field net/minecraft/world/level/chunk/storage/ChunkStorage worker Lnet/minecraft/world/level/chunk/storage/IOWorker;
@@ -267,6 +285,11 @@ accessible class net/minecraft/server/level/ChunkMap$TrackedEntity
accessible field net/minecraft/server/level/ChunkMap$TrackedEntity serverEntity Lnet/minecraft/server/level/ServerEntity; accessible field net/minecraft/server/level/ChunkMap$TrackedEntity serverEntity Lnet/minecraft/server/level/ServerEntity;
# ServerChunkCache$ChunkAndHolder
accessible class net/minecraft/server/level/ServerChunkCache$ChunkAndHolder
accessible method net/minecraft/server/level/ServerChunkCache$ChunkAndHolder <init> (Lnet/minecraft/world/level/chunk/LevelChunk;Lnet/minecraft/server/level/ChunkHolder;)V
# LevelLoadStatusManager$Status # LevelLoadStatusManager$Status
accessible class net/minecraft/client/multiplayer/LevelLoadStatusManager$Status accessible class net/minecraft/client/multiplayer/LevelLoadStatusManager$Status
@@ -291,15 +314,3 @@ accessible class net/minecraft/world/level/LocalMobCapCalculator$MobCounts
accessible class net/minecraft/world/level/chunk/storage/SectionStorage$PackedChunk accessible class net/minecraft/world/level/chunk/storage/SectionStorage$PackedChunk
# MDG requires we AT the constructor if we AT the class # 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 accessible method net/minecraft/world/level/chunk/storage/SectionStorage$PackedChunk <init> (Lit/unimi/dsi/fastutil/ints/Int2ObjectMap;Z)V
# Ticket
accessible method net/minecraft/server/level/Ticket <init> (Lnet/minecraft/server/level/TicketType;IJ)V
# LoadingChunkTracker
accessible class net/minecraft/server/level/LoadingChunkTracker
# TicketStorage
mutable field net/minecraft/world/level/TicketStorage tickets Lit/unimi/dsi/fastutil/longs/Long2ObjectOpenHashMap;

View File

@@ -26,7 +26,6 @@
"chunk_system.ChunkStepMixin", "chunk_system.ChunkStepMixin",
"chunk_system.ChunkStorageMixin", "chunk_system.ChunkStorageMixin",
"chunk_system.DistanceManagerMixin", "chunk_system.DistanceManagerMixin",
"chunk_system.DynamicGameEventListenerMixin",
"chunk_system.EntityGetterMixin", "chunk_system.EntityGetterMixin",
"chunk_system.EntityMixin", "chunk_system.EntityMixin",
"chunk_system.EntityTickListMixin", "chunk_system.EntityTickListMixin",
@@ -52,9 +51,6 @@
"chunk_system.StructureCheckMixin", "chunk_system.StructureCheckMixin",
"chunk_system.StructureTemplate$PaletteMixin", "chunk_system.StructureTemplate$PaletteMixin",
"chunk_system.TicketMixin", "chunk_system.TicketMixin",
"chunk_system.TicketStorageMixin",
"chunk_system.TicketTypeMixin",
"chunk_system.WaypointTransmitterMixin",
"chunk_tick_iteration.ChunkMapMixin", "chunk_tick_iteration.ChunkMapMixin",
"chunk_tick_iteration.DistanceManagerMixin", "chunk_tick_iteration.DistanceManagerMixin",
"chunk_tick_iteration.ServerChunkCacheMixin", "chunk_tick_iteration.ServerChunkCacheMixin",
@@ -145,5 +141,5 @@
}, },
"overwrites": { "overwrites": {
"conformVisibility": true "conformVisibility": true
} }
} }