Compare commits
18 Commits
v0.3.0-bet
...
mc/1.21.6
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a33ac1dc01 | ||
|
|
da21aeca85 | ||
|
|
694dab69c0 | ||
|
|
0764327cba | ||
|
|
724b8ef20a | ||
|
|
0ea5e4dcf5 | ||
|
|
1f8e863c4b | ||
|
|
9d58071cf5 | ||
|
|
303d763167 | ||
|
|
9e3a55f7bc | ||
|
|
aef2b81d6e | ||
|
|
0451444abf | ||
|
|
9a4078966d | ||
|
|
b2a7a92c74 | ||
|
|
30b011246c | ||
|
|
91455be558 | ||
|
|
41ccbb2611 | ||
|
|
b312be2921 |
@@ -6,6 +6,12 @@ plugins {
|
||||
id 'maven-publish'
|
||||
}
|
||||
|
||||
boolean gui = enable_gui == "true"
|
||||
if (gui) {
|
||||
sourceSets.create("gui")
|
||||
loom.createRemapConfigurations(sourceSets.gui)
|
||||
}
|
||||
|
||||
dependencies {
|
||||
minecraft "com.mojang:minecraft:${project.minecraft_version}"
|
||||
mappings loom.officialMojangMappings()
|
||||
@@ -20,9 +26,16 @@ dependencies {
|
||||
libs("ca.spottedleaf:yamlconfig:${rootProject.yamlconfig_version}") { setTransitive(false) }
|
||||
libs("org.yaml:snakeyaml:${rootProject.snakeyaml_version}")
|
||||
|
||||
modImplementation "me.shedaniel.cloth:cloth-config-fabric:${rootProject.cloth_version}"
|
||||
if (gui) {
|
||||
guiCompileOnly(project(":"))
|
||||
runtimeOnly(sourceSets.gui.output)
|
||||
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}"
|
||||
modImplementation "com.terraformersmc:modmenu:${rootProject.modmenu_version}"
|
||||
modGuiImplementation "com.terraformersmc:modmenu:${rootProject.modmenu_version}"
|
||||
modRuntimeOnly "com.terraformersmc:modmenu:${rootProject.modmenu_version}"
|
||||
}
|
||||
|
||||
modImplementation platform(fabricApiLibs.bom)
|
||||
modImplementation fabricApiLibs.command.api.v2
|
||||
@@ -31,6 +44,14 @@ dependencies {
|
||||
include fabricApiLibs.base
|
||||
}
|
||||
|
||||
if (gui) {
|
||||
afterEvaluate {
|
||||
configurations.guiCompileOnly {
|
||||
extendsFrom configurations.getByName("minecraftNamedCompile")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks.processResources {
|
||||
def properties = [
|
||||
"version": project.version,
|
||||
|
||||
@@ -6,6 +6,7 @@ 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.DataFixer;
|
||||
import com.mojang.logging.LogUtils;
|
||||
import com.mojang.serialization.Dynamic;
|
||||
import it.unimi.dsi.fastutil.longs.LongArrays;
|
||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerChunkEvents;
|
||||
@@ -18,6 +19,7 @@ import net.minecraft.server.level.GenerationChunkHolder;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
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.boss.EnderDragonPart;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
@@ -31,7 +33,9 @@ import net.minecraft.world.level.chunk.ProtoChunk;
|
||||
import net.minecraft.world.level.chunk.status.ChunkStatusTasks;
|
||||
import net.minecraft.world.level.chunk.storage.SerializableChunkData;
|
||||
import net.minecraft.world.level.entity.EntityTypeTest;
|
||||
import net.minecraft.world.level.storage.TagValueInput;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import org.slf4j.Logger;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
@@ -40,6 +44,8 @@ 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 Logger LOGGER = LogUtils.getLogger();
|
||||
|
||||
@Override
|
||||
public String getBrand() {
|
||||
return "Moonrise";
|
||||
@@ -251,7 +257,9 @@ public final class FabricHooks extends BaseChunkSystemHooks implements PlatformH
|
||||
|
||||
@Override
|
||||
public void postLoadProtoChunk(final ServerLevel world, final ProtoChunk chunk) {
|
||||
ChunkStatusTasks.postLoadProtoChunk(world, chunk.getEntities());
|
||||
try (final ProblemReporter.ScopedCollector scopedCollector = new ProblemReporter.ScopedCollector(chunk.problemPath(), LOGGER)) {
|
||||
ChunkStatusTasks.postLoadProtoChunk(world, TagValueInput.create(scopedCollector, world.registryAccess(), chunk.getEntities()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -263,4 +271,9 @@ public final class FabricHooks extends BaseChunkSystemHooks implements PlatformH
|
||||
public long[] getCounterTypesUncached(final TicketType type) {
|
||||
return type == TicketType.FORCED ? new long[] { ChunkSystemTicketType.COUNTER_TYPE_FORCED } : LongArrays.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addTicketForEnderPearls(final ServerLevel world) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
"accessWidener": "moonrise.accesswidener",
|
||||
"depends": {
|
||||
"fabricloader": ">=${loader_version}",
|
||||
"minecraft": ">1.21.4 <1.21.6",
|
||||
"minecraft": ">1.21.5 <1.21.7",
|
||||
"fabric-command-api-v2": "*"
|
||||
},
|
||||
"custom": {
|
||||
|
||||
@@ -4,23 +4,25 @@ org.gradle.parallel=true
|
||||
org.gradle.caching=true
|
||||
org.gradle.configuration-cache=true
|
||||
# Fabric Properties
|
||||
# check these on https://modmuss50.me/fabric.html
|
||||
minecraft_version=1.21.5
|
||||
# check these on https://fabricmc.net/develop/
|
||||
minecraft_version=1.21.6
|
||||
loader_version=0.16.14
|
||||
supported_minecraft_versions=1.21.5
|
||||
neoforge_version=21.5.65-beta
|
||||
neoform_version=1.21.5-20250325.162830
|
||||
fabric_api_version=0.123.0+1.21.5
|
||||
supported_minecraft_versions=1.21.6
|
||||
neoforge_version=21.6.11-beta
|
||||
neoform_version=1.21.6-20250617.151856
|
||||
fabric_api_version=0.127.1+1.21.6
|
||||
snakeyaml_version=2.3
|
||||
concurrentutil_version=0.0.3
|
||||
yamlconfig_version=1.0.2
|
||||
cloth_version=18.0.145
|
||||
modmenu_version=14.0.0-rc.2
|
||||
cloth_version=19.0.147
|
||||
modmenu_version=15.0.0-beta.2
|
||||
# set to false when modmenu/cloth is not updated for the current minecraft version
|
||||
enable_gui=true
|
||||
junit_version=5.11.3
|
||||
# version ids from modrinth
|
||||
fabric_lithium_version=nhc57Td2
|
||||
neo_lithium_version=P5VT33Jo
|
||||
# Mod Properties
|
||||
mod_version=0.3.0-SNAPSHOT
|
||||
mod_version=0.4.0-SNAPSHOT
|
||||
maven_group=ca.spottedleaf.moonrise
|
||||
archives_base_name=moonrise
|
||||
|
||||
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,6 +1,6 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.1-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
6
gradlew
vendored
6
gradlew
vendored
@@ -114,7 +114,7 @@ case "$( uname )" in #(
|
||||
NONSTOP* ) nonstop=true ;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
CLASSPATH="\\\"\\\""
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
@@ -205,7 +205,7 @@ fi
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Collect all arguments for the java command:
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||
# 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
|
||||
# treated as '${Hostname}' itself on the command line.
|
||||
@@ -213,7 +213,7 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
set -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
-classpath "$CLASSPATH" \
|
||||
org.gradle.wrapper.GradleWrapperMain \
|
||||
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
|
||||
"$@"
|
||||
|
||||
# Stop when "xargs" is not available.
|
||||
|
||||
4
gradlew.bat
vendored
4
gradlew.bat
vendored
@@ -70,11 +70,11 @@ goto fail
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
set CLASSPATH=
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
"%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" %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
|
||||
@@ -7,6 +7,7 @@ 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.DataFixer;
|
||||
import com.mojang.logging.LogUtils;
|
||||
import com.mojang.serialization.Dynamic;
|
||||
import it.unimi.dsi.fastutil.longs.LongArrayList;
|
||||
import net.minecraft.core.BlockPos;
|
||||
@@ -17,6 +18,7 @@ import net.minecraft.server.level.GenerationChunkHolder;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
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.level.BlockGetter;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
@@ -30,6 +32,7 @@ import net.minecraft.world.level.chunk.ProtoChunk;
|
||||
import net.minecraft.world.level.chunk.status.ChunkStatusTasks;
|
||||
import net.minecraft.world.level.chunk.storage.SerializableChunkData;
|
||||
import net.minecraft.world.level.entity.EntityTypeTest;
|
||||
import net.minecraft.world.level.storage.TagValueInput;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import net.neoforged.neoforge.common.CommonHooks;
|
||||
import net.neoforged.neoforge.common.NeoForge;
|
||||
@@ -38,12 +41,15 @@ import net.neoforged.neoforge.event.EventHooks;
|
||||
import net.neoforged.neoforge.event.entity.EntityJoinLevelEvent;
|
||||
import net.neoforged.neoforge.event.level.ChunkDataEvent;
|
||||
import net.neoforged.neoforge.event.level.ChunkEvent;
|
||||
import org.slf4j.Logger;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public final class NeoForgeHooks extends BaseChunkSystemHooks implements PlatformHooks {
|
||||
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
|
||||
@Override
|
||||
public String getBrand() {
|
||||
return "Moonrise";
|
||||
@@ -257,7 +263,9 @@ public final class NeoForgeHooks extends BaseChunkSystemHooks implements Platfor
|
||||
|
||||
@Override
|
||||
public void postLoadProtoChunk(final ServerLevel world, final ProtoChunk chunk) {
|
||||
ChunkStatusTasks.postLoadProtoChunk(world, chunk.getEntities());
|
||||
try (final ProblemReporter.ScopedCollector scopedCollector = new ProblemReporter.ScopedCollector(chunk.problemPath(), LOGGER)) {
|
||||
ChunkStatusTasks.postLoadProtoChunk(world, TagValueInput.create(scopedCollector, world.registryAccess(), chunk.getEntities()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -278,4 +286,9 @@ public final class NeoForgeHooks extends BaseChunkSystemHooks implements Platfor
|
||||
|
||||
return ret.toLongArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addTicketForEnderPearls(final ServerLevel world) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ side = "BOTH"
|
||||
[[dependencies.moonrise]]
|
||||
modId = "minecraft"
|
||||
type = "required"
|
||||
versionRange = "(1.21.4,1.21.6)"
|
||||
versionRange = "(1.21.5,1.21.7)"
|
||||
ordering = "NONE"
|
||||
side = "BOTH"
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ pluginManagement {
|
||||
}
|
||||
|
||||
plugins {
|
||||
id("org.gradle.toolchains.foojay-resolver-convention") version "0.9.0"
|
||||
id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0"
|
||||
id("quiet-fabric-loom") version "1.10.317" apply false
|
||||
id("net.neoforged.moddev") version "2.0.80" apply false
|
||||
id 'com.gradleup.shadow' version '8.3.6' apply false
|
||||
|
||||
@@ -102,6 +102,8 @@ public interface PlatformHooks extends ChunkSystemHooks {
|
||||
|
||||
public int modifyEntityTrackingRange(final Entity entity, final int currentRange);
|
||||
|
||||
public boolean addTicketForEnderPearls(final ServerLevel world);
|
||||
|
||||
public static final class Holder {
|
||||
private Holder() {
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package ca.spottedleaf.moonrise.common.config.moonrise;
|
||||
|
||||
import ca.spottedleaf.moonrise.common.config.ui.ClothConfig;
|
||||
import ca.spottedleaf.moonrise.common.util.MoonriseCommon;
|
||||
import ca.spottedleaf.moonrise.patches.chunk_system.player.RegionizedPlayerChunkLoader;
|
||||
import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkTaskScheduler;
|
||||
import ca.spottedleaf.yamlconfig.InitialiseHook;
|
||||
import ca.spottedleaf.yamlconfig.annotation.Adaptable;
|
||||
@@ -38,7 +39,7 @@ public final class MoonriseConfig {
|
||||
|
||||
|
||||
@Adaptable
|
||||
public static final class Basic {
|
||||
public static final class Basic implements InitialiseHook {
|
||||
@Serializable(
|
||||
comment = """
|
||||
The maximum rate of chunks to send to any given player, per second. If this value is <= 0,
|
||||
@@ -72,6 +73,20 @@ public final class MoonriseConfig {
|
||||
section = CHUNK_SYSTEM_SECTION
|
||||
)
|
||||
public double playerMaxGenRate = -1.0;
|
||||
|
||||
@Serializable(
|
||||
comment = """
|
||||
The delay before chunks are unloaded around players once they leave their view distance.
|
||||
The Vanilla value is 0 ticks. Setting this value higher (i.e 5s) will allow pets to teleport
|
||||
to their owners when they teleport.
|
||||
"""
|
||||
)
|
||||
public Duration playerChunkUnloadDelay = Duration.parse("0t");
|
||||
|
||||
@Override
|
||||
public void initialise() {
|
||||
RegionizedPlayerChunkLoader.setUnloadDelay(this.playerChunkUnloadDelay.getTimeTicks());
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable(
|
||||
|
||||
@@ -16,7 +16,8 @@ public final class CoordinateUtils {
|
||||
}
|
||||
|
||||
public static long getChunkKey(final Entity entity) {
|
||||
return ((Mth.lfloor(entity.getZ()) >> 4) << 32) | ((Mth.lfloor(entity.getX()) >> 4) & 0xFFFFFFFFL);
|
||||
final ChunkPos pos = entity.chunkPosition();
|
||||
return ((long)pos.z << 32) | (pos.x & 0xFFFFFFFFL);
|
||||
}
|
||||
|
||||
public static long getChunkKey(final ChunkPos pos) {
|
||||
|
||||
@@ -607,6 +607,22 @@ abstract class ServerLevelMixin extends Level implements ChunkSystemServerLevel,
|
||||
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
|
||||
* @author Spottedleaf
|
||||
|
||||
@@ -15,8 +15,8 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(ServerPlayer.class)
|
||||
abstract class ServerPlayerMixin extends Player implements ChunkSystemServerPlayer {
|
||||
public ServerPlayerMixin(Level level, BlockPos blockPos, float f, GameProfile gameProfile) {
|
||||
super(level, blockPos, f, gameProfile);
|
||||
public ServerPlayerMixin(final Level p_250508_, final GameProfile p_252153_) {
|
||||
super(p_250508_, p_252153_);
|
||||
}
|
||||
|
||||
@Unique
|
||||
|
||||
@@ -29,6 +29,7 @@ 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)
|
||||
@@ -193,8 +194,8 @@ abstract class TicketStorageMixin extends SavedData implements ChunkSystemTicket
|
||||
* @author Spottedleaf
|
||||
*/
|
||||
@Overwrite
|
||||
public void purgeStaleTickets() {
|
||||
((ChunkSystemServerLevel)this.chunkMap.level).moonrise$getChunkTaskScheduler().chunkHolderManager.tick();
|
||||
public void purgeStaleTickets(final ChunkMap chunkMap) {
|
||||
((ChunkSystemServerLevel)chunkMap.level).moonrise$getChunkTaskScheduler().chunkHolderManager.tick();
|
||||
this.setDirty();
|
||||
}
|
||||
|
||||
@@ -208,11 +209,11 @@ abstract class TicketStorageMixin extends SavedData implements ChunkSystemTicket
|
||||
method = "deactivateTicketsOnClosing",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/world/level/TicketStorage;removeTicketIf(Ljava/util/function/Predicate;Lit/unimi/dsi/fastutil/longs/Long2ObjectOpenHashMap;)V"
|
||||
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 Predicate<Ticket> predicate,
|
||||
final BiPredicate<Long, Ticket> predicate,
|
||||
final Long2ObjectOpenHashMap<List<Ticket>> tickets) {}
|
||||
|
||||
/**
|
||||
@@ -220,7 +221,7 @@ abstract class TicketStorageMixin extends SavedData implements ChunkSystemTicket
|
||||
* @author Spottedleaf
|
||||
*/
|
||||
@Overwrite
|
||||
public void removeTicketIf(final Predicate<Ticket> predicate, final Long2ObjectOpenHashMap<List<Ticket>> into) {
|
||||
public void removeTicketIf(final BiPredicate<Long, Ticket> predicate, final Long2ObjectOpenHashMap<List<Ticket>> into) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,10 @@ 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.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Mutable;
|
||||
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;
|
||||
@@ -14,6 +17,11 @@ import java.util.concurrent.atomic.AtomicLong;
|
||||
@Mixin(TicketType.class)
|
||||
abstract class TicketTypeMixin<T> implements ChunkSystemTicketType<T> {
|
||||
|
||||
@Final
|
||||
@Shadow
|
||||
@Mutable
|
||||
private long timeout;
|
||||
|
||||
@Unique
|
||||
private static AtomicLong ID_GENERATOR;
|
||||
|
||||
@@ -66,4 +74,9 @@ abstract class TicketTypeMixin<T> implements ChunkSystemTicketType<T> {
|
||||
|
||||
return this.counterTypes = PlatformHooks.get().getCounterTypesUncached((TicketType)(Object)this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void moonrise$setTimeout(final long to) {
|
||||
this.timeout = to;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
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));
|
||||
}
|
||||
}
|
||||
@@ -59,7 +59,7 @@ interface EntityGetterMixin {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((entity == null && otherEntity.canBeCollidedWith()) || (entity != null && entity.canCollideWith(otherEntity))) {
|
||||
if ((entity == null && otherEntity.canBeCollidedWith(entity)) || (entity != null && entity.canCollideWith(otherEntity))) {
|
||||
ret.add(Shapes.create(otherEntity.getBoundingBox()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
package ca.spottedleaf.moonrise.mixin.serverlist;
|
||||
|
||||
import com.llamalad7.mixinextras.sugar.Local;
|
||||
import net.minecraft.client.multiplayer.resolver.ServerAddress;
|
||||
import net.minecraft.client.multiplayer.resolver.ServerAddressResolver;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
@Mixin(ServerAddressResolver.class)
|
||||
@@ -20,19 +23,18 @@ interface ServerAddressResolverMixin {
|
||||
"lambda$static$0"
|
||||
},
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Ljava/net/InetAddress;getByName(Ljava/lang/String;)Ljava/net/InetAddress;"
|
||||
value = "NEW",
|
||||
target = "(Ljava/net/InetAddress;I)Ljava/net/InetSocketAddress;"
|
||||
)
|
||||
)
|
||||
private static InetAddress eliminateRDNS(final String name) throws UnknownHostException {
|
||||
final InetAddress ret = InetAddress.getByName(name);
|
||||
|
||||
final byte[] address = ret.getAddress();
|
||||
private static InetSocketAddress eliminateRDNS(InetAddress addr, final int port,
|
||||
@Local(ordinal = 0, argsOnly = true) final ServerAddress serverAddress) throws UnknownHostException {
|
||||
final byte[] address = addr.getAddress();
|
||||
if (address != null) {
|
||||
// pass name to prevent rDNS
|
||||
return InetAddress.getByAddress(name, address);
|
||||
addr = InetAddress.getByAddress(serverAddress.getHost(), address);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return new InetSocketAddress(addr, port);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ public final class ChunkSystemConverters {
|
||||
private static final int DEFAULT_ENTITY_CHUNK_DATA_VERSION = -1;
|
||||
|
||||
private static int getCurrentVersion() {
|
||||
return SharedConstants.getCurrentVersion().getDataVersion().getVersion();
|
||||
return SharedConstants.getCurrentVersion().dataVersion().version();
|
||||
}
|
||||
|
||||
private static int getDataVersion(final CompoundTag data, final int dfl) {
|
||||
|
||||
@@ -3,6 +3,7 @@ package ca.spottedleaf.moonrise.patches.chunk_system.entity;
|
||||
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkData;
|
||||
import net.minecraft.server.level.FullChunkStatus;
|
||||
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.vehicle.AbstractMinecart;
|
||||
import net.minecraft.world.entity.vehicle.Boat;
|
||||
@@ -13,7 +14,7 @@ public interface ChunkSystemEntity {
|
||||
|
||||
// for mods to override
|
||||
public default boolean moonrise$isHardCollidingUncached() {
|
||||
return this instanceof Boat || this instanceof AbstractMinecart || this instanceof Shulker || ((Entity)this).canBeCollidedWith();
|
||||
return this instanceof Boat || this instanceof AbstractMinecart || this instanceof Shulker || this instanceof HappyGhast || ((Entity)this).canBeCollidedWith(null);
|
||||
}
|
||||
|
||||
public FullChunkStatus moonrise$getChunkStatus();
|
||||
|
||||
@@ -1143,7 +1143,7 @@ public final class MoonriseRegionFileIO {
|
||||
LOGGER.error("Failed to decompress chunk data for task: " + this.toString(), thr);
|
||||
}
|
||||
|
||||
if (compoundTag == null) {
|
||||
if (throwable == null && compoundTag == null) {
|
||||
// need to re-try from the start
|
||||
this.scheduleReadIO();
|
||||
return;
|
||||
|
||||
@@ -5,6 +5,7 @@ import ca.spottedleaf.moonrise.common.list.EntityList;
|
||||
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkData;
|
||||
import ca.spottedleaf.moonrise.patches.chunk_system.entity.ChunkSystemEntity;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.mojang.logging.LogUtils;
|
||||
import it.unimi.dsi.fastutil.objects.Reference2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
@@ -14,6 +15,7 @@ import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.server.level.FullChunkStatus;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.util.ProblemReporter;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.EntitySpawnReason;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
@@ -21,9 +23,14 @@ import net.minecraft.world.entity.boss.EnderDragonPart;
|
||||
import net.minecraft.world.entity.boss.enderdragon.EnderDragon;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
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.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 org.slf4j.Logger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
@@ -32,6 +39,8 @@ import java.util.function.Predicate;
|
||||
|
||||
public final class ChunkEntitySlices {
|
||||
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
|
||||
public final int minSection;
|
||||
public final int maxSection;
|
||||
public final int chunkX;
|
||||
@@ -74,9 +83,12 @@ public final class ChunkEntitySlices {
|
||||
this.chunkData = chunkData;
|
||||
}
|
||||
|
||||
public static List<Entity> readEntities(final ServerLevel world, final CompoundTag compoundTag) {
|
||||
public static List<Entity> readEntities(final ServerLevel world, final ChunkPos pos, final CompoundTag compoundTag) {
|
||||
try (final ProblemReporter.ScopedCollector scopedCollector = new ProblemReporter.ScopedCollector(ChunkAccess.problemPath(pos), LOGGER)) {
|
||||
ValueInput valueinput = TagValueInput.create(scopedCollector, world.registryAccess(), compoundTag);
|
||||
// TODO check this and below on update for format changes
|
||||
return EntityType.loadEntitiesRecursive(compoundTag.getListOrEmpty("Entities"), world, EntitySpawnReason.LOAD).collect(ImmutableList.toImmutableList());
|
||||
return EntityType.loadEntitiesRecursive(valueinput.childrenListOrEmpty("Entities"), world, EntitySpawnReason.LOAD).collect(ImmutableList.toImmutableList());
|
||||
}
|
||||
}
|
||||
|
||||
// Paper start - rewrite chunk system
|
||||
@@ -104,12 +116,22 @@ public final class ChunkEntitySlices {
|
||||
}
|
||||
|
||||
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)) {
|
||||
CompoundTag compoundTag = new CompoundTag();
|
||||
if (entity.save(compoundTag)) {
|
||||
entitiesTag.add(compoundTag);
|
||||
final TagValueOutput savedEntity = TagValueOutput.createWithContext(
|
||||
scopedCollector.forChild(entity.problemPath()), entity.registryAccess()
|
||||
);
|
||||
|
||||
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());
|
||||
ret.put("Entities", entitiesTag);
|
||||
ret.store("Position", ChunkPos.CODEC, chunkPos);
|
||||
|
||||
@@ -45,8 +45,7 @@ public final class ClientEntityLookup extends EntityLookup {
|
||||
final boolean ticking = this.tickingChunks.contains(CoordinateUtils.getChunkKey(chunkX, chunkZ));
|
||||
|
||||
final ChunkEntitySlices ret = new ChunkEntitySlices(
|
||||
this.world, chunkX, chunkZ,
|
||||
ticking ? FullChunkStatus.ENTITY_TICKING : FullChunkStatus.FULL, null,
|
||||
this.world, chunkX, chunkZ, ticking ? FullChunkStatus.ENTITY_TICKING : FullChunkStatus.FULL, null,
|
||||
WorldUtil.getMinSection(this.world), WorldUtil.getMaxSection(this.world)
|
||||
);
|
||||
|
||||
|
||||
@@ -7,9 +7,14 @@ import ca.spottedleaf.moonrise.common.util.TickThread;
|
||||
import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel;
|
||||
import ca.spottedleaf.moonrise.patches.chunk_system.level.entity.ChunkEntitySlices;
|
||||
import ca.spottedleaf.moonrise.patches.chunk_system.level.entity.EntityLookup;
|
||||
import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkHolderManager;
|
||||
import ca.spottedleaf.moonrise.patches.chunk_system.ticket.ChunkSystemTicketType;
|
||||
import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.server.level.TicketType;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.projectile.ThrownEnderpearl;
|
||||
import net.minecraft.world.level.entity.LevelCallback;
|
||||
|
||||
public final class ServerEntityLookup extends EntityLookup {
|
||||
@@ -19,9 +24,18 @@ public final class ServerEntityLookup extends EntityLookup {
|
||||
private final ServerLevel serverWorld;
|
||||
public final ReferenceList<Entity> trackerEntities = new ReferenceList<>(EMPTY_ENTITY_ARRAY); // Moonrise - entity tracker
|
||||
|
||||
// Vanilla does not increment ticket timeouts if the chunk is progressing in generation. They made this change in 1.21.6 so that the ender pearl
|
||||
// ticket does not expire if the chunk fails to generate before the timeout expires. Rather than blindly adjusting the entire system behavior
|
||||
// to fix this small issue, we instead add non-expirable tickets here to keep ender pearls ticking. This is how the original feature should have
|
||||
// been implemented, but I don't think Vanilla has proper entity add/remove hooks like we do. Fixes MC-297591
|
||||
private static final TicketType ENDER_PEARL_TICKER = ChunkSystemTicketType.create("chunk_system:ender_pearl_ticker", null);
|
||||
private final Long2IntOpenHashMap enderPearlChunkCount = new Long2IntOpenHashMap();
|
||||
private final boolean keepEnderPearlsTicking;
|
||||
|
||||
public ServerEntityLookup(final ServerLevel world, final LevelCallback<Entity> worldCallback) {
|
||||
super(world, worldCallback);
|
||||
this.serverWorld = world;
|
||||
this.keepEnderPearlsTicking = PlatformHooks.get().addTicketForEnderPearls(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -63,6 +77,10 @@ public final class ServerEntityLookup extends EntityLookup {
|
||||
if (entity instanceof ServerPlayer player) {
|
||||
((ChunkSystemServerLevel)this.serverWorld).moonrise$getNearbyPlayers().tickPlayer(player);
|
||||
}
|
||||
if (entity instanceof ThrownEnderpearl enderpearl && (oldSectionX != newSectionX || oldSectionZ != newSectionZ)) {
|
||||
this.removeEnderPearl(CoordinateUtils.getChunkKey(oldSectionX, oldSectionZ));
|
||||
this.addEnderPearl(CoordinateUtils.getChunkKey(newSectionX, newSectionZ));
|
||||
}
|
||||
PlatformHooks.get().entityMove(
|
||||
entity,
|
||||
CoordinateUtils.getChunkSectionKey(oldSectionX, oldSectionY, oldSectionZ),
|
||||
@@ -75,6 +93,9 @@ public final class ServerEntityLookup extends EntityLookup {
|
||||
if (entity instanceof ServerPlayer player) {
|
||||
((ChunkSystemServerLevel)this.serverWorld).moonrise$getNearbyPlayers().addPlayer(player);
|
||||
}
|
||||
if (entity instanceof ThrownEnderpearl enderpearl) {
|
||||
this.addEnderPearl(CoordinateUtils.getChunkKey(enderpearl.chunkPosition()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -82,6 +103,9 @@ public final class ServerEntityLookup extends EntityLookup {
|
||||
if (entity instanceof ServerPlayer player) {
|
||||
((ChunkSystemServerLevel)this.serverWorld).moonrise$getNearbyPlayers().removePlayer(player);
|
||||
}
|
||||
if (entity instanceof ThrownEnderpearl enderpearl) {
|
||||
this.removeEnderPearl(CoordinateUtils.getChunkKey(enderpearl.chunkPosition()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -112,4 +136,31 @@ public final class ServerEntityLookup extends EntityLookup {
|
||||
protected boolean screenEntity(final Entity entity, final boolean fromDisk, final boolean event) {
|
||||
return PlatformHooks.get().screenEntity(this.serverWorld, entity, fromDisk, event);
|
||||
}
|
||||
|
||||
private void addEnderPearl(final long coordinate) {
|
||||
if (!this.keepEnderPearlsTicking) {
|
||||
return;
|
||||
}
|
||||
|
||||
final int oldCount = this.enderPearlChunkCount.addTo(coordinate, 1);
|
||||
if (oldCount != 0) {
|
||||
return;
|
||||
}
|
||||
((ChunkSystemServerLevel)this.serverWorld).moonrise$getChunkTaskScheduler().chunkHolderManager
|
||||
.addTicketAtLevel(ENDER_PEARL_TICKER, coordinate, ChunkHolderManager.ENTITY_TICKING_TICKET_LEVEL, null);
|
||||
}
|
||||
|
||||
private void removeEnderPearl(final long coordinate) {
|
||||
if (!this.keepEnderPearlsTicking) {
|
||||
return;
|
||||
}
|
||||
|
||||
final int oldCount = this.enderPearlChunkCount.addTo(coordinate, -1);
|
||||
if (oldCount != 1) {
|
||||
return;
|
||||
}
|
||||
this.enderPearlChunkCount.remove(coordinate);
|
||||
((ChunkSystemServerLevel)this.serverWorld).moonrise$getChunkTaskScheduler().chunkHolderManager
|
||||
.removeTicketAtLevel(ENDER_PEARL_TICKER, coordinate, ChunkHolderManager.ENTITY_TICKING_TICKET_LEVEL, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,7 +119,7 @@ public final class PoiChunk {
|
||||
final CompoundTag sections = new CompoundTag();
|
||||
ret.put("Sections", sections);
|
||||
|
||||
ret.putInt("DataVersion", SharedConstants.getCurrentVersion().getDataVersion().getVersion());
|
||||
ret.putInt("DataVersion", SharedConstants.getCurrentVersion().dataVersion().version());
|
||||
|
||||
final ServerLevel world = this.world;
|
||||
final int chunkX = this.chunkX;
|
||||
|
||||
@@ -47,12 +47,16 @@ import java.util.function.Function;
|
||||
public final class RegionizedPlayerChunkLoader {
|
||||
|
||||
public static final TicketType PLAYER_TICKET = ChunkSystemTicketType.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 PLAYER_TICKET_DELAYED = ChunkSystemTicketType.create("chunk_system:player_ticket_delayed", Long::compareTo, 1L);
|
||||
|
||||
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 TICK_TICKET_LEVEL = ChunkHolderManager.ENTITY_TICKING_TICKET_LEVEL;
|
||||
|
||||
public static void setUnloadDelay(final long ticks) {
|
||||
((ChunkSystemTicketType)(Object)PLAYER_TICKET_DELAYED).moonrise$setTimeout(Math.max(1, ticks));
|
||||
}
|
||||
|
||||
public static final class ViewDistanceHolder {
|
||||
|
||||
private volatile ViewDistances viewDistances;
|
||||
@@ -147,7 +151,7 @@ public final class RegionizedPlayerChunkLoader {
|
||||
}
|
||||
|
||||
public static int getAPITickViewDistance(final ServerPlayer player) {
|
||||
final ServerLevel level = player.serverLevel();
|
||||
final ServerLevel level = player.level();
|
||||
final PlayerChunkLoaderData data = ((ChunkSystemServerPlayer)player).moonrise$getChunkLoader();
|
||||
if (data == null) {
|
||||
return ((ChunkSystemServerLevel)level).moonrise$getPlayerChunkLoader().getAPITickDistance();
|
||||
@@ -156,7 +160,7 @@ public final class RegionizedPlayerChunkLoader {
|
||||
}
|
||||
|
||||
public static int getAPIViewDistance(final ServerPlayer player) {
|
||||
final ServerLevel level = player.serverLevel();
|
||||
final ServerLevel level = player.level();
|
||||
final PlayerChunkLoaderData data = ((ChunkSystemServerPlayer)player).moonrise$getChunkLoader();
|
||||
if (data == null) {
|
||||
return ((ChunkSystemServerLevel)level).moonrise$getPlayerChunkLoader().getAPIViewDistance();
|
||||
@@ -166,7 +170,7 @@ public final class RegionizedPlayerChunkLoader {
|
||||
}
|
||||
|
||||
public static int getAPISendViewDistance(final ServerPlayer player) {
|
||||
final ServerLevel level = player.serverLevel();
|
||||
final ServerLevel level = player.level();
|
||||
final PlayerChunkLoaderData data = ((ChunkSystemServerPlayer)player).moonrise$getChunkLoader();
|
||||
if (data == null) {
|
||||
return ((ChunkSystemServerLevel)level).moonrise$getPlayerChunkLoader().getAPISendViewDistance();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package ca.spottedleaf.moonrise.patches.chunk_system.scheduling;
|
||||
|
||||
import ca.spottedleaf.concurrentutil.collection.MultiThreadedQueue;
|
||||
import ca.spottedleaf.concurrentutil.lock.ReentrantAreaLock;
|
||||
import ca.spottedleaf.concurrentutil.map.ConcurrentLong2ReferenceChainedHashTable;
|
||||
import ca.spottedleaf.concurrentutil.util.Priority;
|
||||
@@ -82,6 +83,7 @@ public final class ChunkHolderManager {
|
||||
private long currentTick;
|
||||
|
||||
private final ArrayDeque<NewChunkHolder> pendingFullLoadUpdate = new ArrayDeque<>();
|
||||
private final MultiThreadedQueue<NewChunkHolder> offThreadPendingFullLoadUpdate = new MultiThreadedQueue<>();
|
||||
private final ObjectRBTreeSet<NewChunkHolder> autoSaveQueue = new ObjectRBTreeSet<>((final NewChunkHolder c1, final NewChunkHolder c2) -> {
|
||||
if (c1 == c2) {
|
||||
return 0;
|
||||
@@ -112,20 +114,20 @@ public final class ChunkHolderManager {
|
||||
this.unloadQueue = new ChunkUnloadQueue(((ChunkSystemServerLevel)world).moonrise$getRegionChunkShift());
|
||||
}
|
||||
|
||||
public boolean processTicketUpdates(final int posX, final int posZ) {
|
||||
public boolean processTicketUpdates(final int chunkX, final int chunkZ) {
|
||||
final int ticketShift = ThreadedTicketLevelPropagator.SECTION_SHIFT;
|
||||
final int ticketMask = (1 << ticketShift) - 1;
|
||||
final List<ChunkProgressionTask> scheduledTasks = new ArrayList<>();
|
||||
final List<NewChunkHolder> changedFullStatus = new ArrayList<>();
|
||||
final boolean ret;
|
||||
final ReentrantAreaLock.Node ticketLock = this.ticketLockArea.lock(
|
||||
((posX >> ticketShift) - 1) << ticketShift,
|
||||
((posZ >> ticketShift) - 1) << ticketShift,
|
||||
(((posX >> ticketShift) + 1) << ticketShift) | ticketMask,
|
||||
(((posZ >> ticketShift) + 1) << ticketShift) | ticketMask
|
||||
((chunkX >> ticketShift) - 1) << ticketShift,
|
||||
((chunkZ >> ticketShift) - 1) << ticketShift,
|
||||
(((chunkX >> ticketShift) + 1) << ticketShift) | ticketMask,
|
||||
(((chunkZ >> ticketShift) + 1) << ticketShift) | ticketMask
|
||||
);
|
||||
try {
|
||||
ret = this.processTicketUpdatesNoLock(posX >> ticketShift, posZ >> ticketShift, scheduledTasks, changedFullStatus);
|
||||
ret = this.processTicketUpdatesNoLock(chunkX >> ticketShift, chunkZ >> ticketShift, scheduledTasks, changedFullStatus);
|
||||
} finally {
|
||||
this.ticketLockArea.unlock(ticketLock);
|
||||
}
|
||||
@@ -805,6 +807,9 @@ public final class ChunkHolderManager {
|
||||
return removeDelay <= 0L;
|
||||
};
|
||||
|
||||
final List<ChunkProgressionTask> scheduledTasks = new ArrayList<>();
|
||||
final List<NewChunkHolder> changedFullStatus = new ArrayList<>();
|
||||
|
||||
for (final PrimitiveIterator.OfLong iterator = this.sectionToChunkToExpireCount.keyIterator(); iterator.hasNext();) {
|
||||
final long sectionKey = iterator.nextLong();
|
||||
|
||||
@@ -813,9 +818,16 @@ public final class ChunkHolderManager {
|
||||
continue;
|
||||
}
|
||||
|
||||
final int lowerChunkX = CoordinateUtils.getChunkX(sectionKey) << sectionShift;
|
||||
final int lowerChunkZ = CoordinateUtils.getChunkZ(sectionKey) << sectionShift;
|
||||
|
||||
final int ticketShift = ThreadedTicketLevelPropagator.SECTION_SHIFT;
|
||||
final int ticketMask = (1 << ticketShift) - 1;
|
||||
final ReentrantAreaLock.Node ticketLock = this.ticketLockArea.lock(
|
||||
CoordinateUtils.getChunkX(sectionKey) << sectionShift,
|
||||
CoordinateUtils.getChunkZ(sectionKey) << sectionShift
|
||||
((lowerChunkX >> ticketShift) - 1) << ticketShift,
|
||||
((lowerChunkZ >> ticketShift) - 1) << ticketShift,
|
||||
(((lowerChunkX >> ticketShift) + 1) << ticketShift) | ticketMask,
|
||||
(((lowerChunkZ >> ticketShift) + 1) << ticketShift) | ticketMask
|
||||
);
|
||||
|
||||
try {
|
||||
@@ -862,9 +874,23 @@ public final class ChunkHolderManager {
|
||||
if (chunkToExpireCount.isEmpty()) {
|
||||
this.sectionToChunkToExpireCount.remove(sectionKey);
|
||||
}
|
||||
|
||||
// In order to prevent a race condition where an off-thread invokes processTicketUpdates(), we need to process ticket updates here
|
||||
// so that we catch any additions to the changed full status list. If an off-thread were to process tickets here, it would not be guaranteed
|
||||
// that it would be added to the full changed status set by the end of the call - possibly allowing ticket level decreases to be processed
|
||||
// outside of this call, which is not an intended or expected of this chunk system.
|
||||
this.processTicketUpdatesNoLock(lowerChunkX >> ThreadedTicketLevelPropagator.SECTION_SHIFT, lowerChunkZ >> ThreadedTicketLevelPropagator.SECTION_SHIFT, scheduledTasks, changedFullStatus);
|
||||
} finally {
|
||||
this.ticketLockArea.unlock(ticketLock);
|
||||
}
|
||||
|
||||
this.addChangedStatuses(changedFullStatus);
|
||||
changedFullStatus.clear(); // clear for next loop iteration
|
||||
|
||||
for (int i = 0, len = scheduledTasks.size(); i < len; ++i) {
|
||||
scheduledTasks.get(i).schedule();
|
||||
}
|
||||
scheduledTasks.clear(); // clear for next loop iteration
|
||||
}
|
||||
|
||||
this.processTicketUpdates();
|
||||
@@ -1091,14 +1117,9 @@ public final class ChunkHolderManager {
|
||||
return;
|
||||
}
|
||||
if (!TickThread.isTickThread()) {
|
||||
this.taskScheduler.scheduleChunkTask(() -> {
|
||||
final ArrayDeque<NewChunkHolder> pendingFullLoadUpdate = ChunkHolderManager.this.pendingFullLoadUpdate;
|
||||
for (int i = 0, len = changedFullStatus.size(); i < len; ++i) {
|
||||
pendingFullLoadUpdate.add(changedFullStatus.get(i));
|
||||
}
|
||||
|
||||
ChunkHolderManager.this.processPendingFullUpdate();
|
||||
}, Priority.HIGHEST);
|
||||
// These will be handled on the next ServerChunkCache$MainThreadExecutor#pollTask, as it runs the distance manager update
|
||||
// which will invoke processTicketUpdates
|
||||
this.offThreadPendingFullLoadUpdate.addAll(changedFullStatus);
|
||||
} else {
|
||||
final ArrayDeque<NewChunkHolder> pendingFullLoadUpdate = this.pendingFullLoadUpdate;
|
||||
for (int i = 0, len = changedFullStatus.size(); i < len; ++i) {
|
||||
@@ -1379,36 +1400,20 @@ public final class ChunkHolderManager {
|
||||
}
|
||||
|
||||
public boolean processTicketUpdates() {
|
||||
return this.processTicketUpdates(true, null);
|
||||
}
|
||||
|
||||
private static final ThreadLocal<List<ChunkProgressionTask>> CURRENT_TICKET_UPDATE_SCHEDULING = new ThreadLocal<>();
|
||||
|
||||
static List<ChunkProgressionTask> getCurrentTicketUpdateScheduling() {
|
||||
return CURRENT_TICKET_UPDATE_SCHEDULING.get();
|
||||
}
|
||||
|
||||
private boolean processTicketUpdates(final boolean processFullUpdates, List<ChunkProgressionTask> scheduledTasks) {
|
||||
if (BLOCK_TICKET_UPDATES.get() == Boolean.TRUE) {
|
||||
throw new IllegalStateException("Cannot update ticket level while unloading chunks or updating entity manager");
|
||||
}
|
||||
if (!PlatformHooks.get().allowAsyncTicketUpdates() && !TickThread.isTickThread()) {
|
||||
final boolean isTickThread = TickThread.isTickThread();
|
||||
|
||||
if (!PlatformHooks.get().allowAsyncTicketUpdates() && isTickThread) {
|
||||
TickThread.ensureTickThread("Cannot asynchronously process ticket updates");
|
||||
}
|
||||
|
||||
List<NewChunkHolder> changedFullStatus = null;
|
||||
|
||||
final boolean isTickThread = TickThread.isTickThread();
|
||||
|
||||
boolean ret = false;
|
||||
final boolean canProcessFullUpdates = processFullUpdates & isTickThread;
|
||||
final boolean canProcessScheduling = scheduledTasks == null;
|
||||
|
||||
if (this.ticketLevelPropagator.hasPendingUpdates()) {
|
||||
if (scheduledTasks == null) {
|
||||
scheduledTasks = new ArrayList<>();
|
||||
}
|
||||
changedFullStatus = new ArrayList<>();
|
||||
final List<ChunkProgressionTask> scheduledTasks = new ArrayList<>();
|
||||
final List<NewChunkHolder> changedFullStatus = new ArrayList<>();
|
||||
|
||||
this.blockTicketUpdates();
|
||||
try {
|
||||
@@ -1419,27 +1424,42 @@ public final class ChunkHolderManager {
|
||||
} finally {
|
||||
this.unblockTicketUpdates(Boolean.FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
if (changedFullStatus != null) {
|
||||
this.addChangedStatuses(changedFullStatus);
|
||||
}
|
||||
|
||||
if (canProcessScheduling && scheduledTasks != null) {
|
||||
for (int i = 0, len = scheduledTasks.size(); i < len; ++i) {
|
||||
scheduledTasks.get(i).schedule();
|
||||
}
|
||||
}
|
||||
|
||||
if (canProcessFullUpdates) {
|
||||
if (isTickThread) {
|
||||
ret |= this.processPendingFullUpdate();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static final ThreadLocal<List<ChunkProgressionTask>> CURRENT_TICKET_UPDATE_SCHEDULING = new ThreadLocal<>();
|
||||
|
||||
static List<ChunkProgressionTask> getCurrentTicketUpdateScheduling() {
|
||||
return CURRENT_TICKET_UPDATE_SCHEDULING.get();
|
||||
}
|
||||
|
||||
// only call on tick thread
|
||||
private void processOffThreadFullUpdates() {
|
||||
final ArrayDeque<NewChunkHolder> pendingFullLoadUpdate = this.pendingFullLoadUpdate;
|
||||
final MultiThreadedQueue<NewChunkHolder> offThreadPendingFullLoadUpdate = this.offThreadPendingFullLoadUpdate;
|
||||
|
||||
NewChunkHolder toUpdate;
|
||||
while ((toUpdate = offThreadPendingFullLoadUpdate.poll()) != null) {
|
||||
pendingFullLoadUpdate.add(toUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
// only call on tick thread
|
||||
private boolean processPendingFullUpdate() {
|
||||
this.processOffThreadFullUpdates();
|
||||
|
||||
final ArrayDeque<NewChunkHolder> pendingFullLoadUpdate = this.pendingFullLoadUpdate;
|
||||
|
||||
boolean ret = false;
|
||||
|
||||
@@ -117,9 +117,11 @@ public final class NewChunkHolder {
|
||||
|
||||
if (!transientChunk) {
|
||||
if (entityChunk != null) {
|
||||
final List<Entity> entities = ChunkEntitySlices.readEntities(this.world, entityChunk);
|
||||
final ChunkPos pos = new ChunkPos(this.chunkX, this.chunkZ);
|
||||
|
||||
((ChunkSystemServerLevel)this.world).moonrise$getEntityLookup().addEntityChunkEntities(entities, new ChunkPos(this.chunkX, this.chunkZ));
|
||||
final List<Entity> entities = ChunkEntitySlices.readEntities(this.world, pos, entityChunk);
|
||||
|
||||
((ChunkSystemServerLevel)this.world).moonrise$getEntityLookup().addEntityChunkEntities(entities, pos);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,4 +30,5 @@ public interface ChunkSystemTicketType<T> {
|
||||
|
||||
public long[] moonrise$getCounterTypes();
|
||||
|
||||
public void moonrise$setTimeout(final long to);
|
||||
}
|
||||
|
||||
@@ -2091,7 +2091,7 @@ public final class CollisionUtil {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((entity == null && otherEntity.canBeCollidedWith()) || (entity != null && entity.canCollideWith(otherEntity))) {
|
||||
if ((entity == null && otherEntity.canBeCollidedWith(entity)) || (entity != null && entity.canCollideWith(otherEntity))) {
|
||||
if (checkOnly) {
|
||||
return true;
|
||||
} else {
|
||||
|
||||
@@ -177,7 +177,7 @@ accessible method net/minecraft/server/network/PlayerChunkSender sendChunk (Lnet
|
||||
|
||||
|
||||
# ChunkStatusTasks
|
||||
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 postLoadProtoChunk (Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/level/storage/ValueInput$ValueInputList;)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;
|
||||
|
||||
|
||||
|
||||
@@ -54,6 +54,7 @@
|
||||
"chunk_system.TicketMixin",
|
||||
"chunk_system.TicketStorageMixin",
|
||||
"chunk_system.TicketTypeMixin",
|
||||
"chunk_system.WaypointTransmitterMixin",
|
||||
"chunk_tick_iteration.ChunkMapMixin",
|
||||
"chunk_tick_iteration.DistanceManagerMixin",
|
||||
"chunk_tick_iteration.ServerChunkCacheMixin",
|
||||
|
||||
Reference in New Issue
Block a user